mz_chatbot / scripts /backfill_country_codes.py
Shurem's picture
multiple issues resolves
d3bc588
Raw History Blame Contribute Delete
3.11 kB
"""
backfill_country_codes.py — fix leads saved with a non-standard country
value instead of a real ISO 3166-1 alpha-2 code.
Confirmed live 2026-09-17: plain AI Discovery (app/services/qualify.py
_qualify_one, before this fix) trusted the model's raw `country` output --
"UK" or "United Kingdom" text both got saved as-is (or mangled to "UN" by a
bare .upper()[:2] on the full name). The Country filter (Cold Call Desk,
Pipeline, Contacts) compares against real codes ("GB" for United Kingdom),
so a lead like that silently matched NO filter selection and looked like it
had vanished. qualify.py now runs every candidate's country through
countries.name_to_iso2() before saving; this script fixes leads that were
already written wrong before that fix shipped.
Only touches leads where name_to_iso2(lead.country) resolves to something
DIFFERENT from what's already stored -- an already-correct code like "GB"
isn't a name/alias in that dict and is left untouched.
Dry-run by default -- prints exactly what it would change and changes
nothing in the database. Re-run with --apply to actually change it.
uv run python scripts/backfill_country_codes.py # dry run
uv run python scripts/backfill_country_codes.py --apply # apply it
Always run without --apply first and read the output before adding --apply.
"""
from __future__ import annotations
import argparse
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from sqlalchemy import select # noqa: E402
from app.database import SessionLocal # noqa: E402
from app.models import Lead # noqa: E402
from app.services.countries import name_to_iso2 # noqa: E402
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("--apply", action="store_true", help="actually fix country (default: dry run only)")
args = parser.parse_args()
db = SessionLocal()
try:
rows = list(db.scalars(select(Lead).where(Lead.country != "")).all())
print(f"Scanning {len(rows)} lead(s) with a country set...")
changes: list[tuple[Lead, str, str]] = []
for lead in rows:
fixed = name_to_iso2(lead.country)
if fixed and fixed != lead.country:
changes.append((lead, lead.country, fixed))
if not changes:
print("Nothing to backfill -- every stored country is already a real ISO2 code.")
return 0
print(f"\n{len(changes)} lead(s) have a non-standard country value:")
for lead, old, new in changes:
print(f" #{lead.id:<6} {lead.company_name[:40]:<40} {old!r:<10} -> {new}")
if not args.apply:
print("\nDry run only -- re-run with --apply to write these changes.")
return 0
for lead, _old, new in changes:
lead.country = new
db.commit()
print(f"\nApplied: {len(changes)} lead(s) updated.")
return 0
finally:
db.close()
if __name__ == "__main__":
sys.exit(main())