git-subtree-dir: fiscal git-subtree-mainline:d95165fc8fgit-subtree-split:102ba84500
225 lines
18 KiB
Python
225 lines
18 KiB
Python
"""Fiscal Decision Engine V1: independent per-field, per-product decisions.
|
|
|
|
Pure functions (no I/O). Every domain gets its own decision; a dataset being
|
|
available is never treated as a rule being resolved. Nothing here writes to
|
|
any database — it only marks `write_eligible`, and only for fields whose ERP
|
|
mapping is confirmed AND whose rule is deterministic AND that need no
|
|
operation context.
|
|
|
|
Status vocabulary (per domain):
|
|
RULE_RESOLVED, RULE_CANDIDATE, RULE_UNRESOLVED, OPERATION_CONTEXT_REQUIRED
|
|
plus flags data_available / match_found. `action_class` is the Phase-14 bucket:
|
|
AUTO_APPLY_SAFE, REVIEW_REQUIRED, OPERATION_CONTEXT_REQUIRED, NO_RULE, NO_DATA
|
|
(+ ALREADY_CORRECT when the ERP value already equals the deterministic one).
|
|
"""
|
|
from .dry_run_planner import build_field_proposals
|
|
|
|
DECISION_ENGINE_VERSION = "fiscal-decision-v1"
|
|
|
|
NATURE = {
|
|
"NCM": "PRODUCT_INTRINSIC", "IPI": "PRODUCT_INTRINSIC", "EX_TIPI": "PRODUCT_INTRINSIC",
|
|
"CEST": "PRODUCT_INTRINSIC", "MVA": "PRODUCT_INTRINSIC",
|
|
"ORIGEM": "PRODUCT_INTRINSIC",
|
|
"CFOP": "OPERATION_DEPENDENT", "CSOSN": "OPERATION_DEPENDENT", "CST_ICMS": "OPERATION_DEPENDENT",
|
|
"PIS_CST": "OPERATION_DEPENDENT", "COFINS_CST": "OPERATION_DEPENDENT",
|
|
"PIS_COFINS_RATE": "COMPANY_CONTEXT_DEPENDENT", "FCP": "OPERATION_DEPENDENT",
|
|
"RTC_CCLASSTRIB": "OPERATION_DEPENDENT", "RTC_CBS_RATE": "OPERATION_DEPENDENT",
|
|
"RTC_CCREDPRES": "OPERATION_DEPENDENT",
|
|
}
|
|
|
|
# ERP_FIELD, SEMANTICS, DB_TYPE, CONFIDENCE, EVIDENCE — audited against the live
|
|
# C000025 schema (RDB$ metadata: no field comments exist) and value distributions
|
|
# over all 521 rows (scripts/audit_erp_fields.py). No supplier DDL/doc file was
|
|
# found in the repo, so semantic confirmation rests on value-domain evidence.
|
|
ERP_FIELD_MAP = [
|
|
{"ERP_FIELD": "CLASSIFICACAO_FISCAL", "SEMANTICS": "NCM canônico (8 dígitos)", "DB_TYPE": "VARCHAR(20)", "CONFIDENCE": "HIGH", "EVIDENCE": "54 distinct 8-digit values, 495 valid in NCM dataset; prior-mission confirmed (NCM column is 100% NULL)", "MAPPING": "CONFIRMED"},
|
|
{"ERP_FIELD": "IPI", "SEMANTICS": "alíquota numérica de IPI (%)", "DB_TYPE": "DOUBLE PRECISION", "CONFIDENCE": "HIGH", "EVIDENCE": "numeric type; 105 rows = 19.5 written earlier from TIPI and verified; prior-mission confirmed", "MAPPING": "CONFIRMED"},
|
|
{"ERP_FIELD": "EX_TIPI", "SEMANTICS": "código EX da TIPI", "DB_TYPE": "VARCHAR(3)", "CONFIDENCE": "HIGH", "EVIDENCE": "prior-mission confirmed; 100% NULL now", "MAPPING": "CONFIRMED"},
|
|
{"ERP_FIELD": "CEST", "SEMANTICS": "CEST do produto (7 dígitos sem pontuação)", "DB_TYPE": "VARCHAR(7)", "CONFIDENCE": "HIGH", "EVIDENCE": "values like 0601100/1708400 = CEST 06.011.00/17.084.00 without dots; prior-mission confirmed", "MAPPING": "CONFIRMED"},
|
|
{"ERP_FIELD": "CFOP", "SEMANTICS": "CFOP padrão de SAÍDA do produto (default, não a operação real)", "DB_TYPE": "VARCHAR(4)", "CONFIDENCE": "HIGH", "EVIDENCE": "values 5102 (493), 5405 (3), 5656 (2): all valid 5xxx output CFOPs in CFOP dataset; 5405=ST, 5656=fuel", "MAPPING": "CONFIRMED"},
|
|
{"ERP_FIELD": "CFOP_ENTRADA", "SEMANTICS": "CFOP padrão de entrada", "DB_TYPE": "SMALLINT", "CONFIDENCE": "LOW", "EVIDENCE": "100% NULL in all 521 rows; name only", "MAPPING": "MAPPING_UNCONFIRMED"},
|
|
{"ERP_FIELD": "CST", "SEMANTICS": "CST ICMS de saída em 3 dígitos = ORIGEM(1)+CST(2)", "DB_TYPE": "VARCHAR(10)", "CONFIDENCE": "MEDIUM", "EVIDENCE": "values 040/000/060/020/051: last 2 digits all in CST_ICMS dataset, first digit in ORIGEM dataset (0)", "MAPPING": "CONFIRMED"},
|
|
{"ERP_FIELD": "CST_ENTRADA", "SEMANTICS": "CST ICMS de entrada", "DB_TYPE": "SMALLINT", "CONFIDENCE": "LOW", "EVIDENCE": "100% NULL; name only", "MAPPING": "MAPPING_UNCONFIRMED"},
|
|
{"ERP_FIELD": "ALIQUOTA", "SEMANTICS": "alíquota de ICMS % (saída)", "DB_TYPE": "NUMERIC(8,2)", "CONFIDENCE": "MEDIUM", "EVIDENCE": "values 20.5 (492), 17 (24), 0 (4), 21.5 (1): plausible BA ICMS rates; no doc confirms", "MAPPING": "CONFIRMED"},
|
|
{"ERP_FIELD": "CSOSN", "SEMANTICS": "CSOSN de saída (Simples Nacional)", "DB_TYPE": "VARCHAR(60)", "CONFIDENCE": "HIGH", "EVIDENCE": "values 102/500/101/103 all in CSOSN dataset; company CRT=1", "MAPPING": "CONFIRMED"},
|
|
{"ERP_FIELD": "COD_ENTRADA_PIS", "SEMANTICS": "CST PIS de entrada", "DB_TYPE": "VARCHAR(3)", "CONFIDENCE": "MEDIUM", "EVIDENCE": "2 non-null rows ('2','73'); mixed formatting ('2' vs 2-digit codes) — too sparse", "MAPPING": "MAPPING_UNCONFIRMED"},
|
|
{"ERP_FIELD": "COD_SAIDA_PIS", "SEMANTICS": "CST PIS de saída", "DB_TYPE": "VARCHAR(3)", "CONFIDENCE": "MEDIUM", "EVIDENCE": "3 non-null rows ('01','04','2'); inconsistent formatting", "MAPPING": "MAPPING_UNCONFIRMED"},
|
|
{"ERP_FIELD": "ALIQ_PIS", "SEMANTICS": "alíquota PIS (texto, vírgula decimal)", "DB_TYPE": "VARCHAR(8)", "CONFIDENCE": "LOW", "EVIDENCE": "3 non-null rows ('0,65','2', blank); text type", "MAPPING": "MAPPING_UNCONFIRMED"},
|
|
{"ERP_FIELD": "COD_ENTRADA_COFINS", "SEMANTICS": "CST COFINS de entrada", "DB_TYPE": "VARCHAR(3)", "CONFIDENCE": "MEDIUM", "EVIDENCE": "2 non-null rows; too sparse", "MAPPING": "MAPPING_UNCONFIRMED"},
|
|
{"ERP_FIELD": "COD_SAIDA_COFINS", "SEMANTICS": "CST COFINS de saída", "DB_TYPE": "VARCHAR(3)", "CONFIDENCE": "MEDIUM", "EVIDENCE": "3 non-null rows; inconsistent formatting", "MAPPING": "MAPPING_UNCONFIRMED"},
|
|
{"ERP_FIELD": "ALIQ_COFINS", "SEMANTICS": "alíquota COFINS (texto)", "DB_TYPE": "VARCHAR(8)", "CONFIDENCE": "LOW", "EVIDENCE": "3 non-null rows ('2','3', blank)", "MAPPING": "MAPPING_UNCONFIRMED"},
|
|
{"ERP_FIELD": "CST_IPI", "SEMANTICS": "CST do IPI", "DB_TYPE": "SMALLINT", "CONFIDENCE": "LOW", "EVIDENCE": "1 non-null row ('040'); IPI CST is 2 digits — value contradicts", "MAPPING": "MAPPING_UNCONFIRMED"},
|
|
{"ERP_FIELD": "ORIGEM", "SEMANTICS": "origem da mercadoria (0-8)", "DB_TYPE": "VARCHAR(1)", "CONFIDENCE": "LOW", "EVIDENCE": "100% NULL; origin digit is instead embedded in CST (first digit)", "MAPPING": "MAPPING_UNCONFIRMED"},
|
|
{"ERP_FIELD": "IAT", "SEMANTICS": "indicador arredondamento/truncamento (A/T)", "DB_TYPE": "VARCHAR(1)", "CONFIDENCE": "MEDIUM", "EVIDENCE": "constant 'A' in 521 rows; not a fiscal-decision field", "MAPPING": "CONFIRMED"},
|
|
{"ERP_FIELD": "INCIDENCIA_PISCOFINS", "SEMANTICS": "tipo de incidência PIS/COFINS", "DB_TYPE": "VARCHAR(30)", "CONFIDENCE": "HIGH", "EVIDENCE": "values NENHUMA (519), MONOFÁSICA (1), SUBST.TRIBUTÁRIA (1)", "MAPPING": "CONFIRMED"},
|
|
{"ERP_FIELD": "IPPT", "SEMANTICS": "indicador produção própria/terceiros (P/T)", "DB_TYPE": "VARCHAR(1)", "CONFIDENCE": "MEDIUM", "EVIDENCE": "constant 'T' in 521 rows; not a fiscal-decision field", "MAPPING": "CONFIRMED"},
|
|
]
|
|
|
|
_ACTION = {
|
|
"RULE_RESOLVED": "AUTO_APPLY_SAFE", # only if write_eligible; refined below
|
|
"RULE_CANDIDATE": "REVIEW_REQUIRED",
|
|
"OPERATION_CONTEXT_REQUIRED": "OPERATION_CONTEXT_REQUIRED",
|
|
}
|
|
|
|
|
|
def _rec(domain, current, proposed, status, reason, confidence, provenance, write_eligible=False,
|
|
data_available=True, match_found=False, action=None, **extra):
|
|
if action is None:
|
|
if status == "RULE_RESOLVED":
|
|
action = "AUTO_APPLY_SAFE" if write_eligible else "ALREADY_CORRECT" if reason.endswith("SAME_VALUE") else "NO_RULE"
|
|
elif status == "RULE_UNRESOLVED":
|
|
action = "NO_DATA" if not data_available else "NO_RULE"
|
|
else:
|
|
action = _ACTION[status]
|
|
return {
|
|
"domain": domain, "nature": NATURE[domain], "current_value": current, "proposed_value": proposed,
|
|
"status": status, "reason_code": reason, "confidence": confidence, "provenance": provenance,
|
|
"write_eligible": write_eligible, "action_class": action,
|
|
"data_available": data_available, "match_found": match_found, **extra,
|
|
}
|
|
|
|
|
|
def _norm_words(text):
|
|
import unicodedata
|
|
text = unicodedata.normalize("NFKD", str(text or "")).encode("ascii", "ignore").decode().lower()
|
|
return {w for w in "".join(c if c.isalnum() else " " for c in text).split() if len(w) >= 4}
|
|
|
|
|
|
def _ex_described(product_description, ex_description):
|
|
"""An EX code applies to a product only if the product's own description
|
|
carries the EX's official description terms. A lone EX row for the NCM is
|
|
NOT evidence that this product is that EX (e.g. EX 'Chope' vs any beer)."""
|
|
ex_words = _norm_words(ex_description)
|
|
return bool(ex_words) and ex_words <= _norm_words(product_description)
|
|
|
|
|
|
def _blank(value):
|
|
return value is None or str(value).strip() == ""
|
|
|
|
|
|
def decide_product(product, decision, company, refs):
|
|
"""company: {"uf": "BA", "crt": "1"}; refs: reference-data snapshot dict:
|
|
cfop_valid(set of codes), cst_icms/csosn/cst_pis/cst_cofins/origem (sets),
|
|
fcp_uf(dict uf->{'aliq_1':...}), cbs_rate_2026 (float|None), cclasstrib_count (int)."""
|
|
versions = decision.get("dataset_versions", {})
|
|
prov = lambda kind: {"dataset": kind, "version": versions.get(kind.lower()), "engine": DECISION_ENGINE_VERSION} # noqa: E731
|
|
out = {}
|
|
|
|
# ---- NCM (never written) -------------------------------------------------
|
|
raw_ncm = product.get("CLASSIFICACAO_FISCAL")
|
|
status = decision.get("status")
|
|
if _blank(raw_ncm):
|
|
out["NCM"] = _rec("NCM", raw_ncm, None, "RULE_UNRESOLVED", "NCM_MISSING", "NONE", prov("NCM"), data_available=False)
|
|
elif status == "EXACT_NCM":
|
|
out["NCM"] = _rec("NCM", raw_ncm, raw_ncm, "RULE_RESOLVED", "NCM_VALID_SAME_VALUE", "HIGH", prov("NCM"), match_found=True)
|
|
elif status == "LEGACY_NCM":
|
|
out["NCM"] = _rec("NCM", raw_ncm, None, "RULE_CANDIDATE", "LEGACY_NCM_REVIEW_REQUIRED", "LOW", prov("NCM"), match_found=True, action="REVIEW_REQUIRED")
|
|
else:
|
|
out["NCM"] = _rec("NCM", raw_ncm, None, "RULE_CANDIDATE", "NCM_INVALID_REVIEW_REQUIRED", "LOW", prov("NCM"), action="REVIEW_REQUIRED")
|
|
|
|
legacy = status == "LEGACY_NCM"
|
|
proposals = {p["field"]: p for p in build_field_proposals(
|
|
product["CODIGO"], decision,
|
|
{"ipi": product.get("IPI"), "cest": product.get("CEST"), "ex_tipi": product.get("EX_TIPI")})}
|
|
|
|
# ---- IPI -------------------------------------------------------------------
|
|
p = proposals.get("IPI")
|
|
ipi_status = decision.get("ipi_status")
|
|
if p and p["status"] in ("SAME_VALUE", "CHANGE_REQUIRED"):
|
|
same = p["status"] == "SAME_VALUE"
|
|
out["IPI"] = _rec("IPI", p["current_value"], p["proposed_value"], "RULE_RESOLVED",
|
|
"TIPI_NUMERIC_SAME_VALUE" if same else "TIPI_NUMERIC_DIVERGES_FROM_ERP", "HIGH", prov("TIPI_IPI"),
|
|
write_eligible=p["write_eligible"], match_found=True)
|
|
elif p:
|
|
blank = p["status"] == "SOURCE_BLANK" or p["reason_code"].endswith("SOURCE_BLANK")
|
|
out["IPI"] = _rec("IPI", p["current_value"], None, "RULE_UNRESOLVED", p["reason_code"], "NONE", prov("TIPI_IPI"),
|
|
data_available=not blank, match_found=True, action="NO_DATA" if blank else "NO_RULE")
|
|
elif ipi_status == "IPI_CANDIDATES":
|
|
out["IPI"] = _rec("IPI", product.get("IPI"), None, "RULE_CANDIDATE", "MULTIPLE_TIPI_CANDIDATES", "LOW", prov("TIPI_IPI"), match_found=True)
|
|
else:
|
|
out["IPI"] = _rec("IPI", product.get("IPI"), None, "RULE_UNRESOLVED", "LEGACY_NCM" if legacy else "NO_TIPI_MAPPING_FOUND", "NONE", prov("TIPI_IPI"))
|
|
|
|
# ---- EX_TIPI ---------------------------------------------------------------
|
|
p = proposals.get("EX_TIPI")
|
|
if p:
|
|
ex_desc = next((c.get("description") for c in (decision.get("classification") or {}).get("ipi_candidates", []) if c.get("ex")), None)
|
|
if p["status"] in ("SAME_VALUE", "CHANGE_REQUIRED") and not _ex_described(product.get("PRODUTO"), ex_desc):
|
|
out["EX_TIPI"] = _rec("EX_TIPI", p["current_value"], None, "RULE_CANDIDATE", "SINGLE_EX_FOR_NCM_BUT_PRODUCT_DESCRIPTION_DOES_NOT_EVIDENCE_IT", "LOW", prov("TIPI_IPI"), match_found=True)
|
|
elif p["status"] in ("SAME_VALUE", "CHANGE_REQUIRED"):
|
|
out["EX_TIPI"] = _rec("EX_TIPI", p["current_value"], p["proposed_value"], "RULE_RESOLVED", "EX_" + p["status"], "HIGH", prov("TIPI_IPI"), write_eligible=p["write_eligible"], match_found=True)
|
|
else:
|
|
out["EX_TIPI"] = _rec("EX_TIPI", p["current_value"], None, "RULE_CANDIDATE", p["reason_code"], "LOW", prov("TIPI_IPI"), match_found=True)
|
|
else:
|
|
out["EX_TIPI"] = _rec("EX_TIPI", product.get("EX_TIPI"), None, "RULE_UNRESOLVED", "NO_EX_TIPI_FOR_NCM", "NONE", prov("TIPI_IPI"), data_available=not legacy)
|
|
|
|
# ---- CEST ------------------------------------------------------------------
|
|
p = proposals.get("CEST")
|
|
if p and p["status"] in ("SAME_VALUE", "CHANGE_REQUIRED"):
|
|
out["CEST"] = _rec("CEST", p["current_value"], p["proposed_value"], "RULE_RESOLVED", "CEST_" + p["status"], "HIGH", prov("CEST"), write_eligible=p["write_eligible"], match_found=True)
|
|
elif p and p["status"] == "CANDIDATE":
|
|
n = len((decision.get("classification") or {}).get("cest_candidates") or [])
|
|
out["CEST"] = _rec("CEST", p["current_value"], None, "RULE_CANDIDATE", p["reason_code"], "LOW", prov("CEST"), match_found=True, candidate_count=n)
|
|
else:
|
|
out["CEST"] = _rec("CEST", product.get("CEST"), None, "RULE_UNRESOLVED", p["reason_code"] if p else ("LEGACY_NCM" if legacy else "NO_CEST_DECISION"), "NONE", prov("CEST"), data_available=False if not p else True)
|
|
|
|
# ---- BA ST / MVA (no ERP destination field: never eligible) ---------------
|
|
mva_status = decision.get("ba_st_mva_status")
|
|
if mva_status == "MVA_RESOLVED":
|
|
entry = (decision.get("classification") or {}).get("ba_st_mva") or {}
|
|
out["MVA"] = _rec("MVA", None, entry.get("mva_original") or entry.get("mva_adjusted"), "RULE_RESOLVED", "MVA_RESOLVED_NO_ERP_TARGET_FIELD", "HIGH", prov("BA_ST_MVA"), match_found=True, action="NO_RULE", mva_status="MVA_RESOLVED")
|
|
elif mva_status == "MVA_CANDIDATES":
|
|
out["MVA"] = _rec("MVA", None, None, "RULE_CANDIDATE", "MULTIPLE_MVA_ITEMS_NEED_CEST_CONFIRMATION", "LOW", prov("BA_ST_MVA"), match_found=True, mva_status="MVA_CANDIDATE")
|
|
elif mva_status == "NO_MVA_MAPPING_FOUND":
|
|
out["MVA"] = _rec("MVA", None, None, "RULE_UNRESOLVED", "MVA_NOT_APPLICABLE_NO_BA_ANNEX1_ENTRY_FOR_NCM", "MEDIUM", prov("BA_ST_MVA"), action="NO_RULE", mva_status="MVA_NOT_APPLICABLE")
|
|
else:
|
|
out["MVA"] = _rec("MVA", None, None, "RULE_UNRESOLVED", "LEGACY_OR_INVALID_NCM", "NONE", prov("BA_ST_MVA"), data_available=False, mva_status="MVA_UNRESOLVED")
|
|
mva_subject = mva_status in ("MVA_RESOLVED", "MVA_CANDIDATES")
|
|
|
|
# ---- CFOP (operation dependent) --------------------------------------------
|
|
cfop = product.get("CFOP")
|
|
cfop_valid = not _blank(cfop) and str(cfop).strip() in refs["cfop_valid"]
|
|
out["CFOP"] = _rec("CFOP", cfop, None, "OPERATION_CONTEXT_REQUIRED", "CFOP_DEPENDS_ON_OPERATION_DIRECTION_UF_ST_PURPOSE", "HIGH", prov("CFOP"),
|
|
data_available=True, match_found=cfop_valid, domain_valid=cfop_valid, current_is_blank=_blank(cfop))
|
|
|
|
# ---- CSOSN / CST ICMS / ORIGEM ---------------------------------------------
|
|
csosn = product.get("CSOSN")
|
|
csosn_valid = not _blank(csosn) and str(csosn).strip() in refs["csosn"]
|
|
flags = {}
|
|
if mva_subject and csosn_valid and str(csosn).strip() == "102":
|
|
flags["consistency_flag"] = "CSOSN_102_BUT_NCM_IN_BA_ST_ANNEX1"
|
|
out["CSOSN"] = _rec("CSOSN", csosn, None, "OPERATION_CONTEXT_REQUIRED", "CSOSN_DEPENDS_ON_SALE_SCENARIO_ST_RETENTION_CONSUMER", "HIGH", prov("NFE_MOC_TABLES"),
|
|
match_found=csosn_valid, domain_valid=csosn_valid, **flags)
|
|
|
|
cst = product.get("CST")
|
|
cst_s = "" if _blank(cst) else str(cst).strip()
|
|
cst_valid = len(cst_s) == 3 and cst_s[1:] in refs["cst_icms"] and cst_s[0] in refs["origem"]
|
|
out["CST_ICMS"] = _rec("CST_ICMS", cst, None, "OPERATION_CONTEXT_REQUIRED", "CRT1_USES_CSOSN_CST_DEPENDS_ON_OPERATION", "MEDIUM", prov("NFE_MOC_TABLES"),
|
|
match_found=cst_valid, domain_valid=cst_valid)
|
|
|
|
origin_candidate = cst_s[0] if cst_valid else None
|
|
out["ORIGEM"] = _rec("ORIGEM", product.get("ORIGEM"), origin_candidate, "RULE_CANDIDATE" if origin_candidate else "RULE_UNRESOLVED",
|
|
"ORIGIN_ONLY_FROM_ERP_CST_FIRST_DIGIT_NO_OBJECTIVE_PRODUCT_ORIGIN" if origin_candidate else "NO_ORIGIN_INFORMATION",
|
|
"LOW", prov("NFE_MOC_TABLES"), data_available=bool(origin_candidate),
|
|
action="REVIEW_REQUIRED" if origin_candidate else "NO_DATA", mapping="MAPPING_UNCONFIRMED")
|
|
|
|
# ---- PIS / COFINS ----------------------------------------------------------
|
|
for domain, field, dom in (("PIS_CST", "COD_SAIDA_PIS", "cst_pis"), ("COFINS_CST", "COD_SAIDA_COFINS", "cst_cofins")):
|
|
cur = product.get(field)
|
|
valid = not _blank(cur) and str(cur).strip() in refs[dom]
|
|
out[domain] = _rec(domain, cur, None, "OPERATION_CONTEXT_REQUIRED", "CST_PIS_COFINS_DEPENDS_ON_OPERATION_AND_INCIDENCE_NO_DETERMINISTIC_RULE_IN_CORE_DATASETS", "MEDIUM", prov("NFE_MOC_TABLES"),
|
|
match_found=valid, domain_valid=valid, mapping="MAPPING_UNCONFIRMED")
|
|
out["PIS_COFINS_RATE"] = _rec("PIS_COFINS_RATE", product.get("ALIQ_PIS"), None, "RULE_UNRESOLVED", "NO_RATE_SOURCE_4_3_10_17_DEFERRED_NEVER_ASSUME_ZERO", "NONE", prov("NFE_MOC_TABLES"), data_available=False, action="NO_RULE")
|
|
|
|
# ---- FCP -------------------------------------------------------------------
|
|
fcp = refs["fcp_uf"].get(company["uf"])
|
|
out["FCP"] = _rec("FCP", None, None, "OPERATION_CONTEXT_REQUIRED", "FCP_APPLICABILITY_DEPENDS_ON_DESTINATION_UF_OPERATION_AND_ITEM_LIST", "HIGH", prov("FCP"),
|
|
data_available=fcp is not None, match_found=False, fcp_rate_available=fcp is not None, company_uf=company["uf"])
|
|
|
|
# ---- RTC -------------------------------------------------------------------
|
|
out["RTC_CCLASSTRIB"] = _rec("RTC_CCLASSTRIB", None, None, "OPERATION_CONTEXT_REQUIRED", "NO_NCM_TO_CCLASSTRIB_MAP_IN_ACTIVE_DATASETS_AND_DEPENDS_ON_OPERATION", "NONE", prov("RTC_CCLASSTRIB"),
|
|
data_available=refs["cclasstrib_count"] > 0, candidate_count=0)
|
|
out["RTC_CBS_RATE"] = _rec("RTC_CBS_RATE", None, None, "OPERATION_CONTEXT_REQUIRED", "CBS_2026_RATE_APPLIES_ONLY_AFTER_CCLASSTRIB_RESOLVED_NOT_UNIVERSAL", "NONE", prov("RTC_CBS_RATES"),
|
|
data_available=refs["cbs_rate_2026"] is not None, reference_rate_2026=refs["cbs_rate_2026"])
|
|
out["RTC_CCREDPRES"] = _rec("RTC_CCREDPRES", None, None, "RULE_UNRESOLVED", "OFFICIAL_CONDITION_NOT_SATISFIED_OR_NOT_KNOWABLE_FROM_PRODUCT", "NONE", prov("RTC_CCREDPRES"), action="NO_RULE")
|
|
return out
|