Lou·Ka — tous les logements à louer du Québec, un seul endroit.
HTML 98.9%
Python 0.6%
1#!/usr/bin/env python32# -----------------------------------------------------------------------------3# Groupe KA — Annuaire des déménageurs du Québec (module partagé Lou-Ka/Immo-Ka)4# demenageurs.py : sert data/demenageurs.json — 565+ entreprises de déménagement5# couvrant les 17 régions administratives (balayage Google Places via Serper).6# Régénération du dataset : scripts/build_demenageurs.py puis remplacer le JSON7# (identique sur Lou-Ka et Immo-Ka — garder les deux copies synchronisées).8# -----------------------------------------------------------------------------9from __future__ import annotations1011import json12import threading13from pathlib import Path1415from fastapi import APIRouter1617ROOT = Path(__file__).resolve().parent.parent18DATA = ROOT / "data" / "demenageurs.json"1920router = APIRouter()21_cache: dict = {"mtime": None, "doc": None}22_lock = threading.Lock()232425def load() -> dict:26 """Charge (avec cache par mtime) l'annuaire canonique des déménageurs."""27 try:28 mtime = DATA.stat().st_mtime29 except FileNotFoundError:30 return {"generated": None, "count": 0, "movers": [], "regions": []}31 with _lock:32 if _cache["doc"] is None or mtime != _cache["mtime"]:33 doc = json.loads(DATA.read_text(encoding="utf-8"))34 regs: dict[str, int] = {}35 for m in doc.get("movers", []):36 regs[m["region"]] = regs.get(m["region"], 0) + 137 doc["regions"] = [{"region": r, "n": n}38 for r, n in sorted(regs.items(),39 key=lambda x: (-x[1], x[0]))]40 _cache["doc"], _cache["mtime"] = doc, mtime41 return _cache["doc"]424344@router.get("/api/demenageurs")45def api_demenageurs(region: str | None = None, q: str | None = None):46 """Annuaire complet des déménageurs du Québec (filtres : région, texte)."""47 doc = load()48 movers = doc.get("movers", [])49 if region:50 movers = [m for m in movers if m["region"] == region]51 if q:52 needle = q.strip().lower()53 movers = [m for m in movers54 if needle in (m["name"] + " " + m["city"]).lower()]55 return {"generated": doc.get("generated"),56 "total": doc.get("count", 0),57 "count": len(movers),58 "regions": doc.get("regions", []),59 "movers": movers}60