"""READ-ONLY end-to-end of the UNIFIED fiscal coverage over a real Firebird database (default: TESTESOFICIAIS.FDB). python scripts/unified_coverage_e2e.py [--db TESTESOFICIAIS] [--out docs/runs/unified_coverage_e2e.json] Reads the products with the Agent's own reader (SELECT only), classifies them through the Hub, then computes the operational states BEFORE (decision only) and AFTER (decision + PIS/COFINS + RTC when enabled). The ERP's RTC switch is reported as found; a what-if run with RTC forced ON / OFF uses the pure evaluator only (nothing is written, PARAMETROS is never touched). """ import argparse import json import os import sys from collections import Counter from pathlib import Path ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT)); sys.path.insert(0, str(ROOT / "scripts")); sys.path.insert(0, str(ROOT / "agent" / "src")) from dotenv import load_dotenv # noqa: E402 load_dotenv(ROOT / ".env") import local_completion as lc # noqa: E402 from central.app.operational_state import classify_product_state, summarize_operational_states # noqa: E402 from gti_fiscal_agent import firebird_reader, unified_fiscal # noqa: E402 from gti_fiscal_agent.client import HubClient # noqa: E402 from gti_fiscal_agent.runner import to_hub_product # noqa: E402 PIS_COLS = ("COD_ENTRADA_PIS", "COD_SAIDA_PIS", "ALIQ_PIS", "COD_ENTRADA_COFINS", "COD_SAIDA_COFINS", "ALIQ_COFINS") def old_unknown(product): """The previous model's UNKNOWN_APPLICABILITY: no product-level evidence of PIS/COFINS at all.""" text = lambda v: "" if v is None else str(v).strip() # noqa: E731 evidence = any(text(product.get(c)) for c in PIS_COLS) or text(product.get("PISCOFINS")).upper() == "S" or text(product.get("INCIDENCIA_PISCOFINS")).upper() not in ("", "NENHUMA") return not evidence def main(): ap = argparse.ArgumentParser(); ap.add_argument("--db", default="TESTESOFICIAIS"); ap.add_argument("--out", default="docs/runs/unified_coverage_e2e.json"); ap.add_argument("--crt", default=None); ap.add_argument("--fiscal-only", action="store_true", help="skip the Hub classification (decisions = EXACT_NCM); measures only the PIS/COFINS + RTC contribution") a = ap.parse_args() path = lc.allowlist()[a.db]; env = lc.env_for(path) products = firebird_reader.read_products(env) connection = firebird_reader._connect(env) # READ COMMITTED READ ONLY (Agent reader) try: cursor = connection.cursor() schema, _catalog, extras = unified_fiscal.load_rtc_context(cursor) fiscal_products = unified_fiscal.read_products(cursor, schema) cursor.execute("SELECT DISTINCT TRIM(CRT) FROM C000004"); crts = [r[0] for r in cursor.fetchall()] finally: connection.close() crt = a.crt or (crts[0] if len(crts) == 1 else None) client = HubClient(os.environ.get("HUB_URL", lc.HUB), os.environ["AGENT_DEV_TOKEN"]) decisions = [{"status": "EXACT_NCM"} for _ in products] if a.fiscal_only else client.classify_batch([to_hub_product(p) for p in products]) before_states = [classify_product_state(p, d) for p, d in zip(products, decisions)] before = summarize_operational_states(before_states) company = {"crt": crt} runs = {} for label, override in (("ERP_AS_FOUND", None), ("RTC_OFF_SIMULATION", False), ("RTC_ON_SIMULATION", True)): conn = firebird_reader._connect(env) try: out = unified_fiscal.assess_from_connection(conn, company, rtc_override=override) finally: conn.close() findings = out["findings"] states = [classify_product_state(p, d, fiscal=findings.get(str(p["CODIGO"]))) for p, d in zip(products, decisions)] summary = summarize_operational_states(states) by_type, by_category = Counter(), Counter() for f in findings.values(): for kind in {(b["type"], b["category"]) for b in f["blockers"]}: by_type[kind[0]] += 1; by_category[kind[1]] += 1 changed = [{"product": s["product_code"], "BEFORE_STATUS": b["state"], "AFTER_STATUS": s["state"], "REASON": sorted({x["type"] for x in s["fiscal_blockers"]}) or ("NEEDS_REVIEW" if s["state"] == "NEEDS_REVIEW" else "")} for b, s in zip(before_states, states) if b["state"] != s["state"]] total = summary["TOTAL_PRODUCTS"] runs[label] = {"rtc_enabled": out["context"]["rtc_enabled"], "TOTAL_PRODUCTS": total, "COMPLETE_PRODUCTS": summary["COMPLETE_PRODUCTS"], "SAFE_BLOCKED_PRODUCTS": summary["SAFE_BLOCKED"], "FAILED_PRODUCTS": summary["FAILED_TECHNICAL"], "UNCLASSIFIED_PRODUCTS": summary["UNCLASSIFIED"], "COVERAGE_PERCENT": round(100 * summary["COMPLETE_PRODUCTS"] / total, 2) if total else 0.0, "INVARIANT_PASS": total == summary["COMPLETE_PRODUCTS"] + summary["SAFE_BLOCKED"] + summary["FAILED_TECHNICAL"] + summary["UNCLASSIFIED"], "PIS_BLOCKERS": by_category["PIS"], "COFINS_BLOCKERS": by_category["COFINS"], "RTC_BLOCKERS": by_category["RTC"], "OTHER_BLOCKERS": by_category["OTHER"], "blockers_by_type": dict(sorted(by_type.items())), "applicability": dict(Counter(f["applicability"]["PIS_COFINS"] for f in findings.values())), "rtc_applicability": dict(Counter(f["applicability"]["RTC"] for f in findings.values())), "changed_products": len(changed), "examples": changed[:30]} if label == "ERP_AS_FOUND": runs[label]["context"] = {k: v for k, v in out["context"].items() if k != "capabilities"} total = before["TOTAL_PRODUCTS"] report = {"mode": "FISCAL_ONLY (no Hub decision)" if a.fiscal_only else "FULL (Hub decision + fiscal)", "database": a.db, "crt": crt, "products": len(products), "fiscal_products_read": len(fiscal_products), "BEFORE": {"COMPLETE_PRODUCTS": before["COMPLETE_PRODUCTS"], "SAFE_BLOCKED_PRODUCTS": before["SAFE_BLOCKED"], "COVERAGE_PERCENT": round(100 * before["COMPLETE_PRODUCTS"] / total, 2), "UNKNOWN_APPLICABILITY_previous_model": sum(1 for p in fiscal_products if old_unknown(p))}, "runs": runs, "SAFETY": {"FIREBIRD_WRITES": 0, "WRITE_ATTEMPTS": 0, "WRITE_SUCCESSES": 0, "connection_mode": "READ COMMITTED READ ONLY (Agent reader); no write-capable connection opened"}} Path(ROOT / a.out).write_text(json.dumps(report, ensure_ascii=False, indent=1, default=str), encoding="utf-8") print(json.dumps({k: report[k] for k in ("database", "crt", "products", "BEFORE")}, ensure_ascii=False)) for label, r in runs.items(): print(label, {k: r[k] for k in ("rtc_enabled", "TOTAL_PRODUCTS", "COMPLETE_PRODUCTS", "SAFE_BLOCKED_PRODUCTS", "FAILED_PRODUCTS", "UNCLASSIFIED_PRODUCTS", "COVERAGE_PERCENT", "INVARIANT_PASS", "PIS_BLOCKERS", "COFINS_BLOCKERS", "RTC_BLOCKERS", "OTHER_BLOCKERS")}) print(" applicability", r["applicability"], "blockers", r["blockers_by_type"]) if __name__ == "__main__": main()