SPB Git forge

spb/api-ka

Public

API-KA — plateforme centrale : collecte quotidienne des 8 services KA, historisation append-only et API publique sur www.api-ka.com

48commits 1branches 0releases
5.9 MBsize
maindefault branch
20 days agolast push
Python 60.9% HTML 21% TypeScript 7.3% JavaScript 5.2% CSS 4.8% Shell 0.8%
11.2 KB · 186 lines markdown
Rendered Raw Blame History
1# ka-stats — module Stats commun Groupe KA (spec v2)23Contrat partagé par les plateformes pour leurs pages **/stats** (tableau de4bord analytique) et les **exports PDF** estampillés Groupe-KA. Le visuel suit5le design system ka-ui (tokens.css) avec l'accent de la marque.67**v2 (2026-08-19)** : sparklines dans les KPI, jauges, multi-courbes,8barres empilées, distributions (histogrammes), heatmap horaire 7×24, deltas9sur les répartitions, statistiques de séries (min/max/moy/méd/σ), et **510rapports PDF** au lieu de 2. Tous les nouveaux champs sont **optionnels** :11un dashboard v1 reste valide et se rend tel quel.1213## 1. Page /stats — structure obligatoire (dans cet ordre)14151. **Bandeau KPI** : 6–10 grandes cartes (`KpiCard`) — valeur, libellé,16   variation vs période précédente (▲/▼ + %, vert `--green` / rouge17   `--danger`), **sparkline** de tendance quand une série existe.182. **Sélecteur de période global** (`PeriodSelector`) : `aujourd'hui · 7 j ·19   30 j · 3 m · 6 m · 12 m · année en cours · tout` + plage personnalisée20   (2 champs date). Toute la page se recalcule (state → refetch dashboard).213. **Jauges** (`GaugeCard`) quand pertinent : taux, couvertures, complétude.224. **Graphiques d'évolution** : courbes/aires (`LineChart`, survol =23   infobulle, légende cliquable, comparaison N vs N-1 en pointillé), barres24   verticales (`VBarChart` — volumes quotidiens), **multi-courbes ≤ 4 séries**25   (`MultiLineChart` — motifs de trait distincts, jamais la couleur seule),26   **barres empilées** (`StackedBarChart` — composition dans le temps).27   Sous les courbes clés : `StatSummary` (min/max/moyenne/médiane/écart-type).285. **Répartitions** : barres horizontales (`BarChart`, deltas optionnels),29   anneaux (`Donut`), **distributions/histogrammes** (`Histogram`).306. **Répartition géographique** (par ville/région) — barres horizontales31   triées (pas besoin de vraie carte).327. **Calendriers** : `CalendarHeatmap` (26 semaines) et, quand l'activité33   horaire est journalisée, `HourHeatmap` (7 jours × 24 h).348. **Tableaux détaillés** (`DataTable`) : tri par colonne, recherche interne,35   pagination (25/pg), débordement horizontal propre sur mobile (.tbl-wrap).36   Viser 3 à 5 tableaux par plateforme.379. **Records & faits marquants** : générés depuis les données (jour record,38   plus forte croissance, meilleure entrée…) — cartes compactes, 6–12.3910. **Fraîcheur** : « Mis à jour le {date heure} » + bouton Rafraîchir.4011. **Bouton PDF** bien visible en haut (`PdfButton`) : bouton principal41    « Rapport PDF complet » + menu « Autres rapports ▾ » listant les42    **5 rapports** (voir §3). Indicateur de progression si > 2 s.4344Responsive : KPI empilés < 768 px, graphiques pleine largeur redimensionnés45(SVG viewBox), tableaux en défilement horizontal contenu, tactile ≥ 44 px.46AUCUNE donnée inventée : une stat indisponible = bloc « Pas encore mesuré »47(carte grise propre), jamais un faux chiffre.4849Accessibilité (règles fermes) : un seul axe Y par graphique (jamais de50double échelle) ; ≥ 2 séries ⇒ légende obligatoire ; l'identité d'une série51multi-courbes passe par le **motif de trait** en plus de la couleur ; le52texte reste en encre (jamais coloré à la couleur de série) ; chaque53graphique a son infobulle de survol et un équivalent tableau existe.5455## 2. API — contrat commun5657`GET /api/stats/dashboard?period=7j|30j|3m|6m|12m|annee|tout|auj&from=YYYY-MM-DD&to=YYYY-MM-DD`5859```jsonc60{61  "updated": "2026-08-19T01:00:00-04:00",62  "period": { "from": "2026-07-20", "to": "2026-08-19", "label": "30 jours" },63  "kpis": [ { "id": "total", "label": "Annonces actives", "value": 33744,64              "unit": "", "delta_pct": 4.2, "direction": "up",65              "spark": [{ "t": "2026-08-01", "v": 31200 }] } ],   // spark optionnel66  "gauges": [ { "id": "geo", "label": "Fiches géolocalisées", "value": 92,67                "max": 100, "unit": "%" } ],                       // optionnel68  "series": [ { "id": "vol", "title": "Annonces actives par jour", "unit": "annonces",69                "kind": "line",                    // line | bar | area70                "points": [{ "t": "2026-07-20", "v": 31200 }],71                "compare": [{ "t": "2025-07-20", "v": 24100 }] } ],72  "multiseries": [ { "id": "seg", "title": "Prix médian par taille", "unit": "$",73                     "series": [ { "label": "3½", "points": [/* … */] },74                                 { "label": "4½", "points": [/* … */] } ] } ], // ≤ 475  "stacked": [ { "id": "src", "title": "Ajouts par source", "unit": "ajouts",76                 "keys": ["Kijiji", "Centris", "Autres"],77                 "points": [{ "t": "2026-08-01", "values": [120, 80, 30] }] } ],78  "breakdowns": [ { "id": "types", "title": "Par type", "kind": "donut",  // donut | bars79                    "items": [{ "label": "4½", "value": 9120, "delta_pct": 2.1 }] } ],80  "distributions": [ { "id": "prix", "title": "Distribution des loyers", "unit": "annonces",81                       "bins": [{ "label": "800-1000$", "value": 3120 }] } ],82  "geo": { "title": "Par région", "items": [{ "label": "Montréal", "value": 15680 }] },83  "heatmap": { "title": "Activité", "cells": [{ "date": "2026-08-01", "value": 210 }] },84  "hourly": { "title": "Activité par heure",85              "cells": [{ "dow": 0, "hour": 9, "value": 40 }] },   // dow 0=lun … 6=dim86  "tables": [ { "id": "top", "title": "Top villes", "columns": ["Ville", "Annonces", "Δ 30 j"],87                "rows": [["Montréal", 15680, "+3,1 %"]] } ],88  "records": [ { "label": "Jour record d'ajouts", "value": "412 annonces", "date": "2026-08-09" } ]89}90```9192Champs absents = section masquée. Cache serveur recommandé (≥ 5 min par93période). Les valeurs proviennent des données réelles (DB de la plateforme,94journaux de sync des connecteurs, /api/v1/runs d'API-KA…). Arrondir les95`delta_pct` à 1 décimale côté serveur.9697## 3. Rapports PDF — 5 modes9899`GET /api/stats/report?period=…&from=&to=&mode=complet|synthese|tendances|repartitions|donnees`100→ `application/pdf`, en-tête `Content-Disposition: attachment; filename=101groupe-ka_<plateforme>_stats_<periode>[_<mode>]_<YYYY-MM-DD>.pdf`102(pas de suffixe pour `complet` — rétrocompatible v1 ; `kapdf.filename()`103accepte maintenant `mode` en 3e argument).104105| Mode | Contenu |106|---|---|107| `complet` | tout : sommaire, KPI, jauges, séries + stats de séries, multi-séries, empilées, répartitions, distributions, géo, heatmap horaire, tableaux (200 lignes), records |108| `synthese` | couverture + KPI + jauges + records (2–3 pages) |109| `tendances` | KPI + toutes les séries temporelles + min/max/moy/méd/σ + records |110| `repartitions` | breakdowns, distributions, géo, activité horaire |111| `donnees` | tous les tableaux en version longue (400 lignes) |112113Un `mode` inconnu retombe sur `complet`. Le gabarit (implémentations :114`kapdf.py` fpdf2 pour les apps Python ; les apps Next portent le même115gabarit en pdfkit) :116117- **Couverture** : cadre encre, kicker « GROUPE KA · RAPPORT STATISTIQUE »,118  wordmark de la plateforme (boîte encre + accent), **type de rapport**,119  période couverte, date/heure de génération, bande encre au pied avec120  « par Groupe KA — groupe-ka.com ».121- **Sommaire** avec numéros de pages (modes complet et donnees).122- **KPI** : grille de cartes (bordure encre, valeur en gros, delta coloré123  arrondi à 1 décimale). **Jauges** : demi-arcs accent.124- **Graphiques VECTORIELS** (dessinés en primitives, jamais de capture) :125  courbes/aires, barres verticales, multi-courbes (motifs distincts),126  empilées (nuances d'accent), anneaux, heatmap horaire — accent de la127  plateforme, axes/graduations encre.128- **Tableaux** paginés proprement (lignes zébrées `--surface-2`, jamais129  coupés en deux à cheval sur une ligne).130- **Records** puis **page de fin** : coordonnées Groupe KA (3 courriels +131  rôles d'ecosystem.json, groupe-ka.com), avertissement d'agrégateur,132  mentions légales courtes.133- **Chaque page** : en-tête discret (« Groupe KA · {Plateforme} », filet134  encre) + pied (« © Groupe-KA — {année} — groupe-ka.com · {période} · p. X/Y »).135- A4 portrait, marges 18 mm, typo : Helvetica (fallback sûr) ou fonts TTF du136  DS si présentes.137138## 4. Spécifique par plateforme (sections métier attendues)139140- **groupe-ka** : tableau de bord maître — consolidation des plateformes141  (volume total, croissance), classement, bloc résumé par plateforme + lien142  vers sa page /stats ; « Rapport écosystème complet » = PDF consolidé.143- **lou-ka** : annonces actives/nouvelles/retirées, loyers moyens/médians par144  ville & taille (multiseries), distribution des loyers, évolution,145  répartition par type, top villes, sources (stacked).146- **immo-ka** : annonces actives/nouvelles/vendues-retirées, prix147  moyen/médian par ville/région/type (multiseries), distribution des prix,148  délai de présence, top villes, tension du marché.149- **vrai-prix** : couverture du rôle (unités, valeur totale), estimations150  servies si journalisées, répartitions par municipalité/type, distribution151  des valeurs, indices marché.152- **auto-ka** : volume par marque/modèle/année/carburant/boîte, prix moyens153  et km moyens par segment (multiseries), distributions prix/km/année,154  top marques/modèles.155- **fabri-ka** : produits par catégorie/région/boutique, fourchettes de prix156  (distribution), nouveautés par période, top catégories.157- **food-ka** : produits suivis, relevés de prix, soldes détectés158  (baisses/hausses, amplitude — stacked), top produits en solde, prix moyens159  par catégorie, distribution des rabais.160- **resto-ka** : restos par cuisine/ville/gamme, menus & plats, distribution161  des prix de plats, nouveautés/fermetures détectées, top établissements.162- **sorti-ka** : événements à venir/passés par catégorie/ville, gratuits vs163  payants (stacked), heatmap calendrier + horaire, top lieux.164- **crea-ka** : créateurs par plateforme/niche/tier, comptes reliés165  (stacked par plateforme), distribution des audiences, top créateurs,166  croissance du répertoire.167- **trouve-ka** : pages indexées, domaines, rythme de crawl (indexées/h —168  hourly), erreurs, file frontier, tendances des requêtes journalisées.169- **api-ka** : appels par endpoint/jour/heure (hourly), latences moyennes +170  p95 (multiseries), taux d'erreur, top endpoints/clés, uptime.171- **job-ka** : offres actives/nouvelles/expirées par catégorie/ville/172  entreprise, distribution des salaires affichés, top employeurs.173- **Transverse (tous)** : volume total agrégé + croissance, connecteurs174  actifs et éléments ajoutés/mis à jour par période (journaux de sync —175  stacked par source quand possible), complétude/fraîcheur moyenne des176  fiches quand mesurable (jauges). Trafic web : seulement si des journaux177  d'accès existent — sinon état vide propre.178179## 5. Ajouter une métrique / un graphique / une plateforme1801811 métrique = 1 entrée `kpis[]`, `series[]`, `multiseries[]`, `stacked[]`,182`distributions[]` ou `gauges[]` côté API (requête SQL agrégée + cache) — le183front la rend automatiquement. 1 plateforme = implémenter les 2 endpoints du184contrat + une page /stats montée sur les composants du kit + `kapdf.py` (ou185gabarit pdfkit) branché sur le même JSON de dashboard.186