"""Import historical ERP evidence (miner output) into the central KB. Dry-run by default; --apply commits. Local data only, no provider call. python -m central.scripts.import_kb_history --staging /path/to/history [--apply] [--report out.json] Runs against the database in DATABASE_URL (the Hub's PostgreSQL). Idempotent. Never touches any client database. """ import argparse import json import sys import time from pathlib import Path from central.app.db import SessionLocal from central.app.enrichment import history def main(argv=None): ap = argparse.ArgumentParser() ap.add_argument("--staging", required=True) ap.add_argument("--apply", action="store_true") ap.add_argument("--report", default=None) ap.add_argument("--only-current-vigente-gtins", action="store_true", help="skip GTINs without any NCM evidence") args = ap.parse_args(argv) files = sorted(f for f in Path(args.staging).glob("*.json") if not f.name.startswith("_")) stagings = [json.loads(f.read_text(encoding="utf-8")) for f in files] t0 = time.time() obs = history.build_observations(stagings) if args.only_current_vigente_gtins: obs["gtins"] = {k: v for k, v in obs["gtins"].items() if v["ncm"]} with SessionLocal() as session: current = history.official_sets(session) report = history.apply(session, obs, lambda v: v in current, dry_run=not args.apply) report.update({"mode": "APPLY" if args.apply else "DRY_RUN", "clients": [s["client"] for s in stagings], "build_stats": obs["stats"], "seconds": round(time.time() - t0, 1)}) text = json.dumps(report, indent=1, default=str) if args.report: Path(args.report).write_text(text, encoding="utf-8") print(text) if __name__ == "__main__": sys.exit(main())