| """Map messy PO product names to the nearest canonical sticker in the catalog.""" |
|
|
| from __future__ import annotations |
|
|
| from difflib import SequenceMatcher, get_close_matches |
|
|
| from data import SAMPLE_CATALOG |
| from parser_fallback import PRODUCT_ALIASES |
|
|
| _CATALOG_LOWER = {p.lower(): p for p in SAMPLE_CATALOG} |
|
|
|
|
| def resolve_product(raw: str, catalog: list[str] | None = None) -> str: |
| """Return the closest catalog name for a parsed product string.""" |
| if not raw or not str(raw).strip(): |
| return raw |
|
|
| catalog = catalog or SAMPLE_CATALOG |
| catalog_lower = {p.lower(): p for p in catalog} |
| cleaned = str(raw).strip() |
| key = cleaned.lower() |
|
|
| if key in catalog_lower: |
| return catalog_lower[key] |
|
|
| for alias, canonical in sorted(PRODUCT_ALIASES.items(), key=lambda x: -len(x[0])): |
| if alias in key or key in alias: |
| if canonical.lower() in catalog_lower: |
| return catalog_lower[canonical.lower()] |
| return canonical |
|
|
| for cat_lower, canonical in catalog_lower.items(): |
| if cat_lower in key or key in cat_lower: |
| return canonical |
|
|
| matches = get_close_matches(key, catalog_lower.keys(), n=1, cutoff=0.55) |
| if matches: |
| return catalog_lower[matches[0]] |
|
|
| best_name, best_score = cleaned, 0.0 |
| for cat_lower, canonical in catalog_lower.items(): |
| score = SequenceMatcher(None, key, cat_lower).ratio() |
| if score > best_score: |
| best_score, best_name = score, canonical |
| if best_score >= 0.5: |
| return best_name |
|
|
| return cleaned |
|
|
|
|
| def resolve_items(items: list[dict], catalog: list[str] | None = None) -> list[dict]: |
| """Normalize product field on each parsed item.""" |
| out = [] |
| for it in items: |
| row = dict(it) |
| raw = row.get("product", "") |
| resolved = resolve_product(raw, catalog) |
| if resolved != raw and not row.get("notes"): |
| row["notes"] = f"matched from: {raw}" |
| elif resolved != raw: |
| row["notes"] = f"{row['notes']} (matched from: {raw})" |
| row["product"] = resolved |
| out.append(row) |
| return out |
|
|