Python 49.6%
TypeScript 25.5%
CSS 24.1%
1# -----------------------------------------------------------------------------2# Home-Ka — US real-estate aggregator (Groupe KA)3# Author: Simon-Pierre Boucher — contact@spboucher.ai4# brokerages.py : brokerage registry — seed loading + scoring refresh.5# The seed (data/brokerages_seed.json) is the initial base of 500+ US6# brokerages worth pursuing for direct feeds; the discovery pipeline7# (discovery.py) then inspects, classifies and scores them.8# -----------------------------------------------------------------------------9from __future__ import annotations1011import json12import time13from pathlib import Path1415from . import db16from .discovery import priority1718SEED_PATH = Path(__file__).resolve().parent.parent / "data" / "brokerages_seed.json"192021def load_seed(path: Path | str | None = None) -> dict:22 """Upsert the seed file into the brokerages table (idempotent, keyed on23 website). Never overwrites discovery results or partnership statuses."""24 p = Path(path) if path else SEED_PATH25 data = json.loads(p.read_text(encoding="utf-8"))26 rows = data["brokerages"] if isinstance(data, dict) else data27 con = db.connect()28 now = time.time()29 added = updated = 030 for b in rows:31 website = (b.get("website") or "").strip().rstrip("/")32 if not website or not b.get("name"):33 continue34 states = b.get("states") or []35 prio = priority(b.get("estimated_listings"), b.get("estimated_agents"),36 30, len(states)) # 30 = unknown feed prob. before inspection37 existing = con.execute("SELECT id FROM brokerages WHERE website=?",38 (website,)).fetchone()39 if existing is None:40 con.execute(41 """INSERT INTO brokerages (name, website, states, cities,42 estimated_agents, estimated_listings, mls_affiliations,43 possible_feed_type, priority_score, partnership_status,44 created, updated)45 VALUES (?,?,?,?,?,?,?,?,?,'prospect',?,?)""",46 (b["name"], website,47 json.dumps(states, ensure_ascii=False),48 json.dumps(b.get("cities") or [], ensure_ascii=False),49 b.get("estimated_agents"), b.get("estimated_listings"),50 json.dumps(b.get("mls_affiliations") or [], ensure_ascii=False),51 b.get("possible_feed_type") or "crawl", prio, now, now))52 added += 153 else:54 con.execute(55 """UPDATE brokerages SET name=?,56 states=CASE WHEN states='[]' THEN ? ELSE states END,57 cities=CASE WHEN cities='[]' THEN ? ELSE cities END,58 estimated_agents=COALESCE(estimated_agents, ?),59 estimated_listings=COALESCE(estimated_listings, ?),60 updated=? WHERE id=?""",61 (b["name"], json.dumps(states, ensure_ascii=False),62 json.dumps(b.get("cities") or [], ensure_ascii=False),63 b.get("estimated_agents"), b.get("estimated_listings"),64 now, existing["id"]))65 updated += 166 con.commit()67 n = con.execute("SELECT COUNT(*) c FROM brokerages").fetchone()["c"]68 con.close()69 return {"added": added, "updated": updated, "total": n}707172def rescore(con=None) -> int:73 """Recompute priority scores from current inspection data."""74 own = con is None75 con = con or db.connect()76 n = 077 for r in con.execute("SELECT id, estimated_listings, estimated_agents,"78 " feed_probability_score, states FROM brokerages"):79 states = json.loads(r["states"] or "[]")80 prio = priority(r["estimated_listings"], r["estimated_agents"],81 r["feed_probability_score"] or 30, len(states))82 con.execute("UPDATE brokerages SET priority_score=? WHERE id=?",83 (prio, r["id"]))84 n += 185 con.commit()86 if own:87 con.close()88 return n89