Money parsing for supplier CSV feeds.
One implementation, shared by every import format, because the defect it
exists to prevent showed up independently in two of them:
Decimal.parse/1 returns {decimal, remainder} and a call site that
matches {decimal, _} discards the remainder, so "12,50" imports as
12 and "1,234.56" imports as 1. Nothing errors — the product simply
goes on sale at a fraction of its price.
parse/1 tolerates the formats suppliers actually send (currency
symbols, non-breaking spaces, either separator convention) and returns
nil rather than a truncated or invented number for anything it cannot
read. Callers are expected to fail the row on nil, not substitute zero.
Summary
Functions
Parses a money value from a supplier CSV cell.
Functions
Parses a money value from a supplier CSV cell.
Returns a Decimal, or nil when the value cannot be read
unambiguously.
Separator handling: whichever of . or , appears LAST is the decimal
separator and the other groups thousands. A single repeated separator is
resolved by validating group widths, not by guessing from the tail
length.
Examples
iex> PhoenixKitEcommerce.Import.Money.parse("12,50")
Decimal.new("12.50")
iex> PhoenixKitEcommerce.Import.Money.parse("1.234,56")
Decimal.new("1234.56")
iex> PhoenixKitEcommerce.Import.Money.parse("22.80 USD")
Decimal.new("22.80")
iex> PhoenixKitEcommerce.Import.Money.parse("1,2,3")
nil