#!/usr/bin/env python3 """Map an SEO findings.json → estimate-engine scope.json (service=seo, effort). Stage 5 of ourdigital-presales-seo: keeps the SEO-specific mapping here; the engine (96-ourdigital-estimate-engine) owns the costing. Then call: python /scripts/estimate.py --rate-card /references/rate_card.yaml \ --catalog-dir /catalog --scope scope.json --out-dir Usage: python findings_to_scope.py --findings data/findings.json --out data/scope.json [--tier auto] [--seq N] """ import argparse import json def main(): ap = argparse.ArgumentParser(description="SEO findings.json -> engine scope.json") ap.add_argument("--findings", required=True) ap.add_argument("--out", required=True) ap.add_argument("--tier", default="auto", help="auto|smb|basic|treatment") ap.add_argument("--billing", type=float, default=None) ap.add_argument("--seq", type=int, default=1) args = ap.parse_args() with open(args.findings, encoding="utf-8") as fh: f = json.load(fh) e = f.get("entity", {}) p = f.get("prospect", {}) severity = sorted({x.get("severity") for x in f.get("findings", []) if x.get("severity")}) scope = { "service": "seo", "method": "effort", "tier": args.tier, "billing_rate": args.billing, "signals": { "properties_total": e.get("properties_total", 0), "subbrands_total": e.get("subbrands_total", 0), "vertical": p.get("vertical", ""), "severity": severity, }, "prospect": { "name": p.get("name", ""), "domain": p.get("domain", ""), "audit_date": p.get("audit_date", ""), "account_code": p.get("account_code", ""), }, "seq": args.seq, } with open(args.out, "w", encoding="utf-8") as fh: json.dump(scope, fh, ensure_ascii=False, indent=2) print(f"scope -> {args.out} | service=seo tier={args.tier} " f"properties={scope['signals']['properties_total']} subbrands={scope['signals']['subbrands_total']} " f"vertical={scope['signals']['vertical']!r}") if __name__ == "__main__": main()