docs: PIPELINE-DONNEES.md — pipeline batch de bout en bout (continuité)
Documente le pipeline qui produit data/vraiprix.db (il tourne sur le laptop, pas sur le nœud) : sources amont (rôles MAMH 2021-2026 FGDB/GPKG Données Québec licence ouverte ; transactions api.qub.ca scrapées en quadtree avec token Bearer manuel), étapes (extract_roles → merge_transactions kNN 2 passes 99,88 % → hedonic LightGBM 4 modèles → build_vrai_prix_db → build_stats), livraison scp 1,5 Go vers M3U96a, volumétrie vérifiée live (3 747 008 unités, 745 119 transactions, market_index 268), complétude (GPS 100 %, frontage 83 %, année 79 %), risques (token manuel, non-reproductible sur nœud, rôle 2027) et procédure de rafraîchissement pas à pas. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 changed file +175 −0
added
docs/PIPELINE-DONNEES.md
+175 −0
@@ -0,0 +1,175 @@ | ||
| 1 | +# Vrai-Prix — Pipeline de données (documentation de continuité) | |
| 2 | + | |
| 3 | +> Rédigé le 2026-08-18. **Important : contrairement aux autres apps Ka, Vrai-Prix | |
| 4 | +> n'a AUCUN connecteur runtime.** Toute la donnée est produite par un pipeline | |
| 5 | +> **batch qui tourne sur le laptop** (`~/Desktop/qc_house_eval/` et | |
| 6 | +> `~/Desktop/house/`), puis livrée au nœud M3U96a sous forme d'un unique | |
| 7 | +> fichier SQLite (`data/vraiprix.db`, ~1,5 Go). Ce document existe pour que | |
| 8 | +> n'importe quelle session future puisse comprendre, auditer et rejouer le | |
| 9 | +> pipeline même sans accès à l'historique de conversation. | |
| 10 | + | |
| 11 | +## Vue d'ensemble | |
| 12 | + | |
| 13 | +``` | |
| 14 | +[MAMH — rôles d'évaluation 2021-2026] [api.qub.ca — transactions] | |
| 15 | + Données Québec (FGDB/GPKG, licence scraping quadtree, token | |
| 16 | + ouverte, téléchargement MANUEL) Bearer recapturé via Safari | |
| 17 | + │ │ | |
| 18 | + │ extract_roles.py │ ~/Desktop/house/scrape_province.py | |
| 19 | + ▼ ▼ | |
| 20 | + unités normalisées ◄──── merge_transactions.py ──── transactions brutes | |
| 21 | + (fusion spatiale kNN, 2 passes, 99,88 %) | |
| 22 | + │ | |
| 23 | + ▼ | |
| 24 | + hedonic.py — LightGBM, 4 modèles hédoniques (estimation de valeur) | |
| 25 | + │ | |
| 26 | + ▼ | |
| 27 | + build_vrai_prix_db.py — assemble data/vraiprix.db (units, transactions, | |
| 28 | + │ market_index, FTS5 units_fts, leads) | |
| 29 | + ▼ | |
| 30 | + build_stats.py — agrégats / index de marché | |
| 31 | + │ | |
| 32 | + ▼ | |
| 33 | + scp vraiprix.db (~1,5 Go) → M3U96a:~/apps/vrai-prix/data/ → app Next.js | |
| 34 | +``` | |
| 35 | + | |
| 36 | +## 1. Sources amont | |
| 37 | + | |
| 38 | +### 1.1 Rôles d'évaluation foncière (MAMH) | |
| 39 | + | |
| 40 | +- **Quoi** : rôles d'évaluation municipale du Québec, millésime **2021-2026** | |
| 41 | + (MAMH — ministère des Affaires municipales et de l'Habitation). | |
| 42 | +- **Où** : [Données Québec](https://www.donneesquebec.ca/) — jeu « Rôles | |
| 43 | + d'évaluation foncière ». **Licence ouverte** (réutilisation permise avec | |
| 44 | + attribution — Données Québec / MAMH). | |
| 45 | +- **Format** : **FGDB** (Esri File Geodatabase) et/ou **GPKG** (GeoPackage), | |
| 46 | + **téléchargés manuellement** (pas d'API d'ingestion automatique — les | |
| 47 | + fichiers sont volumineux et versionnés par millésime). | |
| 48 | +- **Contenu utile** : chaque unité d'évaluation (adresse, matricule, usage, | |
| 49 | + géométrie/GPS, valeurs au rôle terrain/bâtiment, caractéristiques physiques | |
| 50 | + — frontage, superficie, année de construction, nb logements…). | |
| 51 | +- **Stockage laptop** : sous `~/Desktop/qc_house_eval/` (données brutes + | |
| 52 | + scripts dans `scripts/`). | |
| 53 | + | |
| 54 | +### 1.2 Transactions immobilières (api.qub.ca) | |
| 55 | + | |
| 56 | +- **Quoi** : transactions de vente résidentielles (prix réel, date d'acte), | |
| 57 | + utilisées pour entraîner les modèles hédoniques et calculer l'indice de | |
| 58 | + marché. | |
| 59 | +- **Comment** : **scraping par quadtree** de l'API `api.qub.ca` avec | |
| 60 | + `~/Desktop/house/scrape_province.py` (sur le **laptop**) : découpage | |
| 61 | + récursif du territoire en tuiles jusqu'à passer sous le plafond de | |
| 62 | + résultats par requête, couverture provinciale complète. | |
| 63 | +- **Auth** : jeton **Bearer** requis, **recapturé manuellement via Safari** | |
| 64 | + (ouvrir le site qub.ca, inspecteur web → copier l'en-tête Authorization | |
| 65 | + d'une requête à `api.qub.ca`, le coller dans le script). Le jeton expire : | |
| 66 | + c'est l'étape manuelle fragile du pipeline (voir « Risques »). | |
| 67 | + | |
| 68 | +## 2. Étapes du pipeline (laptop — `~/Desktop/qc_house_eval/scripts/`) | |
| 69 | + | |
| 70 | +Ordre d'exécution (chaque étape lit la sortie de la précédente) : | |
| 71 | + | |
| 72 | +| # | Script | Rôle | | |
| 73 | +|---|---|---| | |
| 74 | +| 0 | `~/Desktop/house/scrape_province.py` | scraping quadtree des transactions api.qub.ca (token Bearer manuel) — préalable, peut tourner indépendamment | | |
| 75 | +| 1 | `extract_roles.py` | extraction/normalisation des unités d'évaluation depuis les FGDB/GPKG MAMH (usages résidentiels, champs canoniques, GPS) | | |
| 76 | +| 2 | `merge_transactions.py` | **fusion spatiale kNN en 2 passes** des transactions sur les unités du rôle — taux d'appariement **99,88 %** | | |
| 77 | +| 3 | `hedonic.py` | entraînement **LightGBM — 4 modèles hédoniques** (par grande famille de propriété) → valeur estimée « vrai prix » par unité | | |
| 78 | +| 4 | `build_vrai_prix_db.py` | assemblage du SQLite final `vraiprix.db` : tables `units`, `transactions`, `market_index`, index plein-texte FTS5 (`units_fts*`), table applicative `leads` | | |
| 79 | +| 5 | `build_stats.py` | agrégats statistiques / indice de marché (alimente `market_index` et la page /stats) | | |
| 80 | + | |
| 81 | +## 3. Livraison au nœud | |
| 82 | + | |
| 83 | +Le nœud **ne fait que servir** la base — l'app Next.js (M3U96a, ce repo) lit | |
| 84 | +`data/vraiprix.db` en lecture seule. | |
| 85 | + | |
| 86 | +```bash | |
| 87 | +# depuis le laptop, après un build complet : | |
| 88 | +scp ~/Desktop/qc_house_eval/…/vraiprix.db M3U96a:apps/vrai-prix/data/vraiprix.db | |
| 89 | +ssh M3U96a 'pm2 restart vrai-prix' # recharger l'app après remplacement de la BD | |
| 90 | +``` | |
| 91 | + | |
| 92 | +- Taille du livrable : **~1,5 Go** (dernier fichier livré : 2026-08-08). | |
| 93 | +- La BD est en WAL (`-shm`/`-wal` présents sur le nœud) ; remplacer le `.db` | |
| 94 | + quand l'app est arrêtée ou juste avant un `pm2 restart` pour éviter tout | |
| 95 | + mélange de journaux. | |
| 96 | + | |
| 97 | +## 4. Volumétrie (build livré, vérifiée live sur le nœud 2026-08-18) | |
| 98 | + | |
| 99 | +| Table | Lignes | Note | | |
| 100 | +|---|---|---| | |
| 101 | +| `units` | **3 747 008** | unités d'évaluation résidentielles, province entière | | |
| 102 | +| `transactions` | **745 119** | ventes appariées (kNN 2 passes, 99,88 %) | | |
| 103 | +| `market_index` | **268** | lignes d'indice de marché (build_stats.py) | | |
| 104 | +| `units_fts` (+`_data`/`_idx`/`_config`/`_docsize`) | — | index FTS5 de recherche d'adresses | | |
| 105 | +| `leads` | — | table applicative (demandes des visiteurs), remplie par l'app, PAS par le pipeline | | |
| 106 | + | |
| 107 | +- **Dernier build : 2026-08-08** (mtime du fichier sur le nœud : 8 août 18:22). | |
| 108 | + | |
| 109 | +## 5. Complétude des champs (build 2026-08-08) | |
| 110 | + | |
| 111 | +| Champ | Complétude | | |
| 112 | +|---|---| | |
| 113 | +| GPS (lat/lng des unités) | **100 %** | | |
| 114 | +| Frontage | **83 %** | | |
| 115 | +| Année de construction | **79 %** | | |
| 116 | + | |
| 117 | +Les champs manquants sont des trous du rôle MAMH lui-même (certaines | |
| 118 | +municipalités ne publient pas toutes les caractéristiques) — les modèles | |
| 119 | +hédoniques les traitent comme valeurs manquantes natives LightGBM. | |
| 120 | + | |
| 121 | +## 6. Risques & limites (à connaître avant tout rafraîchissement) | |
| 122 | + | |
| 123 | +1. **Token qub.ca manuel** : le Bearer d'api.qub.ca doit être recapturé à la | |
| 124 | + main via Safari à chaque campagne de scraping ; s'il expire en cours de | |
| 125 | + quadtree, relancer `scrape_province.py` (il est repriseable par tuiles). | |
| 126 | + Aucun renouvellement automatique — point de fragilité n° 1. | |
| 127 | +2. **Pipeline NON reproductible sur le nœud** : les données brutes (FGDB/GPKG | |
| 128 | + MAMH, dumps qub.ca), les scripts et les environnements Python (GDAL/ | |
| 129 | + pyogrio pour lire les FGDB, LightGBM) ne vivent que sur le **laptop** | |
| 130 | + (`~/Desktop/qc_house_eval/`, `~/Desktop/house/`). Si le laptop est perdu, | |
| 131 | + le pipeline doit être reconstruit ; seul le livrable `vraiprix.db` est sur | |
| 132 | + le nœud (et le repo git ne contient PAS la BD ni les données brutes). | |
| 133 | + → Recommandation : archiver `qc_house_eval/scripts/` + `house/` (au moins | |
| 134 | + les scripts) sur le NAS ou dans un repo gitsrv dédié. | |
| 135 | +3. **Rôle 2027 à venir** : le millésime MAMH suivant (rôles 2024-2029 / | |
| 136 | + publication « 2027 ») exigera de rejouer tout le pipeline : re-télécharger | |
| 137 | + les FGDB/GPKG, revalider les schémas (les noms de couches/champs bougent | |
| 138 | + entre millésimes), ré-entraîner les 4 modèles. | |
| 139 | +4. **Décalage de fraîcheur** : la BD servie date du dernier build (2026-08-08) ; | |
| 140 | + l'app n'a aucun mécanisme de mise à jour incrémentale — c'est voulu | |
| 141 | + (batch + livraison atomique d'un seul fichier). | |
| 142 | + | |
| 143 | +## 7. Procédure de rafraîchissement pas à pas | |
| 144 | + | |
| 145 | +Sur le **laptop** : | |
| 146 | + | |
| 147 | +1. **Transactions** — recapturer le token : Safari → qub.ca (section | |
| 148 | + immobilier) → inspecteur web → requête vers `api.qub.ca` → copier le | |
| 149 | + header `Authorization: Bearer …` → le mettre dans | |
| 150 | + `~/Desktop/house/scrape_province.py` → lancer le scraping quadtree | |
| 151 | + (long ; repriseable). Vérifier le volume obtenu vs ~745 k. | |
| 152 | +2. **Rôles** — si nouveau millésime MAMH : télécharger manuellement les | |
| 153 | + FGDB/GPKG depuis Données Québec dans `~/Desktop/qc_house_eval/`. | |
| 154 | +3. `cd ~/Desktop/qc_house_eval/scripts/` puis, dans l'ordre : | |
| 155 | + `python3 extract_roles.py` → `python3 merge_transactions.py` (contrôler le | |
| 156 | + taux d'appariement, attendu ≥ 99,8 %) → `python3 hedonic.py` (4 modèles ; | |
| 157 | + contrôler les métriques de validation avant de continuer) → | |
| 158 | + `python3 build_vrai_prix_db.py` → `python3 build_stats.py`. | |
| 159 | +4. **Contrôles qualité** sur le `vraiprix.db` produit : | |
| 160 | + `SELECT COUNT(*) FROM units;` (~3,7 M), `SELECT COUNT(*) FROM transactions;` | |
| 161 | + (~745 k+), `SELECT COUNT(*) FROM market_index;`, complétude GPS = 100 %, | |
| 162 | + spot-check de quelques adresses connues dans `units_fts`. | |
| 163 | +5. **Livraison** : `scp` du fichier vers `M3U96a:apps/vrai-prix/data/vraiprix.db` | |
| 164 | + puis `ssh M3U96a 'pm2 restart vrai-prix'`. | |
| 165 | +6. **Vérification en prod** : ouvrir le site (vrai-prix), chercher une adresse, | |
| 166 | + vérifier /stats, puis noter la date de build ici (section 4) et committer | |
| 167 | + la mise à jour de ce document **sur le nœud** (remote-first : | |
| 168 | + `git add docs/PIPELINE-DONNEES.md && git commit && git push origin main`). | |
| 169 | + | |
| 170 | +## 8. Attribution | |
| 171 | + | |
| 172 | +Les données du rôle d'évaluation proviennent du **MAMH via Données Québec** | |
| 173 | +(licence ouverte — attribution requise). Les transactions servent au calcul | |
| 174 | +de modèles et d'indices agrégés ; les pages publiques n'exposent pas la | |
| 175 | +source brute qub.ca. | |
| 176 | ||