#!/usr/bin/env python3 # ----------------------------------------------------------------------------- # Groupe KA — Annuaire des déménageurs du Québec (module partagé Lou-Ka/Immo-Ka) # demenageurs.py : sert data/demenageurs.json — 565+ entreprises de déménagement # couvrant les 17 régions administratives (balayage Google Places via Serper). # Régénération du dataset : scripts/build_demenageurs.py puis remplacer le JSON # (identique sur Lou-Ka et Immo-Ka — garder les deux copies synchronisées). # ----------------------------------------------------------------------------- from __future__ import annotations import json import threading from pathlib import Path from fastapi import APIRouter ROOT = Path(__file__).resolve().parent.parent DATA = ROOT / "data" / "demenageurs.json" router = APIRouter() _cache: dict = {"mtime": None, "doc": None} _lock = threading.Lock() def load() -> dict: """Charge (avec cache par mtime) l'annuaire canonique des déménageurs.""" try: mtime = DATA.stat().st_mtime except FileNotFoundError: return {"generated": None, "count": 0, "movers": [], "regions": []} with _lock: if _cache["doc"] is None or mtime != _cache["mtime"]: doc = json.loads(DATA.read_text(encoding="utf-8")) regs: dict[str, int] = {} for m in doc.get("movers", []): regs[m["region"]] = regs.get(m["region"], 0) + 1 doc["regions"] = [{"region": r, "n": n} for r, n in sorted(regs.items(), key=lambda x: (-x[1], x[0]))] _cache["doc"], _cache["mtime"] = doc, mtime return _cache["doc"] @router.get("/api/demenageurs") def api_demenageurs(region: str | None = None, q: str | None = None): """Annuaire complet des déménageurs du Québec (filtres : région, texte).""" doc = load() movers = doc.get("movers", []) if region: movers = [m for m in movers if m["region"] == region] if q: needle = q.strip().lower() movers = [m for m in movers if needle in (m["name"] + " " + m["city"]).lower()] return {"generated": doc.get("generated"), "total": doc.get("count", 0), "count": len(movers), "regions": doc.get("regions", []), "movers": movers}