fix: gate cClassTrib applicability by CRT and date

This commit is contained in:
gti
2026-09-25 17:47:04 -03:00
parent 95605c2ff5
commit 4a12640031
25 changed files with 498 additions and 72 deletions
+35 -8
View File
@@ -168,12 +168,38 @@ def _dedupe(items):
# ------------------------------------------------------------------------------------------------- RTC
CCLASSTRIB_EFFECTIVE_FROM = {
"3": date(2026, 8, 3),
"1": date(2027, 1, 1),
"2": date(2027, 1, 1),
"4": date(2027, 1, 1),
}
def rtc_enabled(caps: dict) -> bool:
"""RTC is in scope ONLY when the ERP is switched to the reform (PARAMETROS.USAR_REFORMA_TRIBUTARIA truthy) AND its schema can hold it."""
return bool(caps.get("HAS_PRODUCT_CCLASSTRIB") and caps.get("HAS_RTC_RELATIONSHIP") and caps.get("RTC_ENABLED_BY_PARAM"))
def cclasstrib_applicability(crt, rtc_enabled: bool, today: date | None = None) -> dict:
"""Company-level cClassTrib requiredness from live CRT and its effective date.
The ERP RTC switch scopes the feature; it does not make cClassTrib mandatory
for every company/product. Unknown regimes fail closed to NOT_APPLICABLE.
"""
today = today or date.today()
regime = _text(crt)
if not rtc_enabled:
return {"state": "NOT_APPLICABLE", "basis": "RTC_DISABLED_IN_ERP", "effective_from": None, "source": "PARAMETROS.USAR_REFORMA_TRIBUTARIA"}
effective_from = CCLASSTRIB_EFFECTIVE_FROM.get(regime)
if effective_from is None:
return {"state": "NOT_APPLICABLE", "basis": "COMPANY_CRT_UNRESOLVED", "effective_from": None, "source": "C000004.CRT"}
if today < effective_from:
basis = "SIMPLES_CCLASSTRIB_NOT_EFFECTIVE" if regime in SIMPLES_FAMILY else "CCLASSTRIB_NOT_YET_EFFECTIVE"
return {"state": "NOT_APPLICABLE", "basis": basis, "effective_from": effective_from.isoformat(), "source": "C000004.CRT + RTC effective-date rules"}
return {"state": "REQUIRED", "basis": "CCLASSTRIB_EFFECTIVE_FOR_CRT", "effective_from": effective_from.isoformat(), "source": "C000004.CRT + RTC effective-date rules"}
def catalog_integrity(catalog: dict) -> dict:
"""catalog: {"classes": {cClassTrib: cst_or_None}, "cst": {code, ...}, "duplicates": int}."""
classes, cst = catalog.get("classes", {}), set(catalog.get("cst", ()))
@@ -202,11 +228,13 @@ def validate_cclasstrib(value, catalog: dict | None, today: date | None = None)
return "VALID" if cst is not None and str(cst) in set(catalog.get("cst", ())) else "CST_MISSING"
def evaluate_rtc(product: dict, rtc: dict | None, today: date | None = None) -> dict:
"""rtc: {"enabled": bool, "catalog": {...}|None, "catalog_valid": bool}. Disabled => NOT_APPLICABLE and NO blocker, whatever CCLASSTRIB holds."""
if not rtc or not rtc.get("enabled"):
return {"applicability": {"state": "NOT_APPLICABLE", "basis": "RTC_DISABLED_IN_ERP"}, "blockers": []}
app = {"state": "REQUIRED", "basis": "RTC_ENABLED_IN_ERP"}
def evaluate_rtc(product: dict, rtc: dict | None, today: date | None = None, crt=None) -> dict:
"""Validate cClassTrib only when RTC is on and the company's regime/date gate applies."""
app = rtc.get("cclasstrib_applicability") if isinstance(rtc, dict) else None
if not isinstance(app, dict):
app = cclasstrib_applicability(crt, bool(rtc and rtc.get("enabled")), today)
if app["state"] != "REQUIRED":
return {"applicability": app, "blockers": []}
if not rtc.get("catalog_valid"):
return {"applicability": app, "blockers": [("RTC_CATALOG_INVALID", "LOCAL_CATALOG_FAILED_INTEGRITY")]}
state = validate_cclasstrib(product.get("CCLASSTRIB"), rtc.get("catalog"), today)
@@ -222,7 +250,7 @@ def evaluate_product(product: dict, company: dict | None, rtc: dict | None, toda
Returns {"blockers": [{"type","category","reason"}], "applicability": {"PIS_COFINS": state, "RTC": state}, "mandatory_fields": [...], "needs_review": bool}."""
crt = (company or {}).get("crt")
pis = evaluate_pis_cofins(product, crt)
rtc_result = evaluate_rtc(product, rtc, today)
rtc_result = evaluate_rtc(product, rtc, today, crt)
blockers = [{"type": kind, "category": blocker_category(kind), "reason": reason} for kind, reason in pis["blockers"] + rtc_result["blockers"]]
warnings = [{"type": kind, "reason": reason} for kind, reason in pis["warnings"]]
mandatory = []
@@ -236,8 +264,7 @@ def evaluate_product(product: dict, company: dict | None, rtc: dict | None, toda
def legal_effective_context(crt) -> dict:
"""INFORMATIONAL ONLY (never a blocker, never part of completeness). The operational rule stays ERP_RTC_ENABLED; this records what the official acts say about the
obligation to issue DF-e with IBS/CBS for the company regime, so a timing difference can be explained without inventing a rule.
"""Summarize the broad IBS/CBS document timeline; cClassTrib requiredness has its own CRT/date gate above.
Source: Ato Conjunto RFB/CGIBS n 4/2026 (DOU 31/07/2026) art. 1: NF-e (55) and NFC-e (65) from 2026-08-03; par. 1: Simples optantes from 2027-01-01."""
simples = _text(crt) in SIMPLES_FAMILY
return {"crt": _text(crt) or None, "informational_only": True,