Matches PRO100 rows to existing catalogue items.
The file identifies a row by a numeric code, which is our SKU reduced to digits
(Pro100.Id.digits_only/1). That reduction is lossy — it drops the decor letter
and the finish, so 73.U767.18 and 73.U767.PM.18 both become 7376718.
Matching on it alone leaves every such row permanently ambiguous: on a real
export, 28 codes were shared by 62 rows, none of which could ever be updated.
Resolution therefore tries {digits, name} first and falls back to digits alone
only when that is unique. The name decides when the code cannot; the code still
decides when the name has drifted.
Both indexes skip items whose SKU carries no digits. That is what stops a
code-less file row from matching a SKU-less item by name alone — the file's
Tööpind spacer row (price 0.00) is named like a real item and would zero
its price.
Summary
Functions
Collapses a name to its match key: case-folded, whitespace-collapsed, trimmed.
Resolves one row against the index.
Types
@type t() :: %{ digits: %{required(String.t()) => [PhoenixKitCatalogue.Schemas.Item.t()]}, digits_name: %{ required({String.t(), String.t()}) => [PhoenixKitCatalogue.Schemas.Item.t()] } }
Functions
@spec index([PhoenixKitCatalogue.Schemas.Item.t()]) :: t()
Collapses a name to its match key: case-folded, whitespace-collapsed, trimmed.
Applied to item.name when the index is built and to the row name when a row
is resolved. It must stay a single function: two copies that drift by one
character make the name stage silently stop matching, and the symptom looks
like a data problem rather than a code one.
iex> PhoenixKitCatalogue.Import.Matcher.normalize_name(" MP U741 ST9 ")
"mp u741 st9"
iex> PhoenixKitCatalogue.Import.Matcher.normalize_name(nil)
""
@spec resolve(t(), String.t(), String.t() | nil) :: {:matched, PhoenixKitCatalogue.Schemas.Item.t()} | {:ambiguous, [PhoenixKitCatalogue.Schemas.Item.t()]} | :unmatched
Resolves one row against the index.
Stages, in order: a blank id never matches; {id, name} wins when unique; the
id alone wins when unique; an id held by several items is refused rather than
guessed.