"""Read-only extraction of populated supplier-item fiscal observations.""" from __future__ import annotations import hashlib import json import os import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT)) from central.app.evidence_aggregation import Observation, aggregate_observations # noqa: E402 def _hash(value: object) -> str: return hashlib.sha256(str(value).encode("utf-8")).hexdigest()[:16] def summarize_rows(rows: list[tuple[object, ...]]) -> dict: observations = [] for product, supplier, observed_at, ncm, cfop, cst in rows: identity = _hash(product) supplier_id = _hash(supplier) document = _hash(f"{supplier}:{product}:{observed_at}") for attribute, value in (("ncm", ncm), ("cfop", cfop), ("cst", cst)): if value not in (None, ""): observations.append(Observation(identity, attribute, str(value).strip(), supplier_id, document, str(observed_at), "SUPPLIER_OBSERVATION")) aggregate = aggregate_observations(observations) return { "observation_count": len(observations), "aggregate_count": len(aggregate), "sources": ["SUPPLIER_OBSERVATION"] if observations else [], "strong_evidence_count": sum(1 for row in aggregate.values() if row["strong_evidence"]), "conflict_count": sum(row["conflict_count"] for row in aggregate.values()), } def _env() -> None: path = ROOT / ".env" if path.exists(): for line in path.read_text(encoding="utf-8").splitlines(): if "=" in line and not line.lstrip().startswith("#"): key, _, value = line.partition("=") os.environ.setdefault(key.strip(), value.strip()) def analyze_database(path: Path) -> dict: import fdb conn = fdb.connect(database=str(path), user=os.environ["FB_USER"], password=os.environ["FB_PASSWORD"], fb_library_name=os.environ.get("FIREBIRD_CLIENT_LIBRARY"), isolation_level=fdb.ISOLATION_LEVEL_READ_COMMITED_RO) try: cur = conn.cursor() cur.execute("SELECT TRIM(RDB$FIELD_NAME) FROM RDB$RELATION_FIELDS WHERE RDB$RELATION_NAME = 'C000088'") fields = {row[0] for row in cur.fetchall()} required = {"CODPRODUTO", "CODFORNECEDOR", "DATA", "CLASSIFICACAO_FISCAL", "CFOP", "CST"} if not required <= fields: return {"database": path.name, "status": "NO_COMPLETE_INBOUND_ITEM_SHAPE", "fields_available": sorted(fields)} cur.execute("SELECT CODPRODUTO, CODFORNECEDOR, DATA, CLASSIFICACAO_FISCAL, CFOP, CST FROM C000088") rows = cur.fetchall() summary = summarize_rows(rows) return {"database": path.name, "status": "ANALYZED", "items_analyzed": len(rows), **summary, "origin_field_available": False, "origin_resolution": "ORIGIN_NEEDS_EVIDENCE"} finally: conn.close() def main() -> None: _env() paths = [ROOT / "TESTESOFICIAIS.FDB"] + sorted((ROOT / "Banco").glob("*.FDB")) result = {"artifact": "INBOUND_SUPPLIER_OBSERVATIONS_V1", "mode": "READ_ONLY", "firebird_writes": 0, "databases": []} for path in paths: try: result["databases"].append(analyze_database(path)) except Exception as exc: result["databases"].append({"database": path.name, "status": "UNAVAILABLE", "error_type": type(exc).__name__}) (ROOT / "docs/INBOUND_SUPPLIER_OBSERVATIONS_V1.json").write_text(json.dumps(result, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") print(json.dumps({"artifact": result["artifact"], "databases": len(result["databases"]), "firebird_writes": 0})) if __name__ == "__main__": main()