import json from pathlib import Path import pytest from central.app.product_defaults import cfop_default, cst_status, csosn_default, validate_against_history CFOPS = {"5102", "5405", "5656", "1102"} CSOSNS = {"101", "102", "103", "500", "400"} def P(**kw): return {"CFOP": "5102", "CSOSN": "102", "CST": "040", **kw} def test_cfop_consistent_non_st_is_resolved_but_never_a_write(): r = cfop_default(P(), "EXACT_NCM", "NO_MVA_MAPPING_FOUND", CFOPS) assert r["status"] == "CFOP_DEFAULT_RESOLVED" and r["action_class"] == "ALREADY_CORRECT" and not r["write_eligible"] def test_cfop_st_conflict_is_candidate_review_not_write(): r = cfop_default(P(), "EXACT_NCM", "MVA_RESOLVED", CFOPS) assert r["status"] == "CFOP_DEFAULT_CANDIDATE" and r["proposed_value"] == "5405" and r["action_class"] == "REVIEW_REQUIRED" and not r["write_eligible"] def test_cfop_insufficient_context_never_resolved(): assert cfop_default(P(), "EXACT_NCM", "MVA_CANDIDATES", CFOPS)["status"] == "CFOP_OPERATION_CONTEXT_REQUIRED" assert cfop_default(P(CFOP=None), "EXACT_NCM", "NO_MVA_MAPPING_FOUND", CFOPS)["status"] == "CFOP_OPERATION_CONTEXT_REQUIRED" assert cfop_default(P(CFOP="6102"), "EXACT_NCM", "NO_MVA_MAPPING_FOUND", CFOPS | {"6102"})["status"] == "CFOP_OPERATION_CONTEXT_REQUIRED" assert cfop_default(P(), "LEGACY_NCM", "NO_MVA_MAPPING_FOUND", CFOPS)["status"] == "CFOP_UNRESOLVED" assert cfop_default(P(CFOP="9999"), "EXACT_NCM", "NO_MVA_MAPPING_FOUND", CFOPS)["status"] == "CFOP_UNRESOLVED" def test_csosn_is_never_resolved_and_never_universal_102(): for mva in ("MVA_RESOLVED", "MVA_CANDIDATES", "NO_MVA_MAPPING_FOUND"): r = csosn_default(P(), "EXACT_NCM", mva, CSOSNS, "102") assert r["status"] != "CSOSN_DEFAULT_RESOLVED" and not r["write_eligible"] r = csosn_default(P(CSOSN="101"), "EXACT_NCM", "NO_MVA_MAPPING_FOUND", CSOSNS, "102") assert r["proposed_value"] is None def test_csosn_st_subject_flags_conflict_and_requires_retention_context(): r = csosn_default(P(), "EXACT_NCM", "MVA_RESOLVED", CSOSNS, "102") assert r["status"] == "CSOSN_OPERATION_CONTEXT_REQUIRED" and r["consistency_flag"] == "ST_SUBJECT_BUT_CSOSN_NOT_500" def test_history_validates_but_does_not_create_rules(): assert validate_against_history("5102", ["5102", "5102"]) == "MATCH" assert validate_against_history("5102", ["5102", "5405"]) == "MISMATCH" assert validate_against_history("5102", []) == "UNVALIDATED" assert validate_against_history(None, ["5102"]) == "UNVALIDATED" # history alone never proposes a value def test_cst_is_reference_only_under_crt1(): r = cst_status(P(), {"40", "00"}, set("012345678")) assert r["status"] == "CST_REFERENCE_ONLY" and r["origin_digit"] == "0" and not r["write_eligible"] assert cst_status(P(CST="99"), {"40"}, set("0"))["status"] == "CST_INVALID_REVIEW" def test_engine_is_deterministic_idempotent(): a = cfop_default(P(), "EXACT_NCM", "MVA_RESOLVED", CFOPS) assert a == cfop_default(P(), "EXACT_NCM", "MVA_RESOLVED", CFOPS) REC = Path(__file__).resolve().parents[2] / "docs" / "NCM_HISTORICAL_RECONCILIATION_V1.json" @pytest.mark.skipif(not REC.exists(), reason="reconciliation artifact not generated") def test_reconciliation_accounts_for_every_mismatch_and_finds_no_technical_bug(): d = json.loads(REC.read_text(encoding="utf-8")) assert sum(d["classification"].values()) == d["mismatches_total"] assert d["classification"].get("NORMALIZATION_BUG", 0) == 0 assert d["trusted_corpus"]["TRUSTED_HISTORICAL_ITEMS"] > 0