"""TECHNICAL_PLACEHOLDER semantics for the product enrichment. The SGV refuses to save a product without an NCM, so operators type a technical filler to get past the form. That filler is NOT a human fiscal decision: it means "not classified yet". Explicit allowlist PER FIELD (never generalised: "0", "99999999", "SEM NCM" ... are NOT placeholders until the real SGV behaviour is confirmed). The Agent carries the same table (agent/src/gti_fiscal_agent/enrichment.py PLACEHOLDERS); a test asserts both are identical. """ import re PRODUCT_ENRICHMENT_PLACEHOLDERS = {"CLASSIFICACAO_FISCAL": frozenset({"00000000"})} def _norm(field: str, value) -> str: text = "" if value is None else str(value).strip() return re.sub(r"\D", "", text) if field == "CLASSIFICACAO_FISCAL" else text # 0000.00.00 and 00000000 are the same NCM filler def is_placeholder(field: str, value) -> bool: return _norm(field, value) in PRODUCT_ENRICHMENT_PLACEHOLDERS.get(field, frozenset()) def is_blank(value) -> bool: return not ("" if value is None else str(value)).strip() def is_writable_empty(field: str, value) -> bool: """True when the field is empty OR holds the approved technical placeholder. A real value (even a wrong one) is never writable here.""" return is_blank(value) or is_placeholder(field, value)