mirror of
https://github.com/R0m1k3/CollectFlow.git
synced 2026-10-11 17:26:32 +02:00
merge: piloter Période + garde-fou d'intégrité + sélection par dimension Mois
Fusion de deux lignes de travail parallèles sur main, complémentaires et non concurrentes :cd2e77eselectionnerFenetreViaDimensionMois() — sélectionne les 12 mois par qElemNumber sur la dimension maître Mois. C'est ce qui marche : les champs Date exposés sont dissociés des faits (100 % du total avant comme après), la dimension maître porte les vraies valeurs.4ef0e9fgarde-fou d'intégrité — refuse d'écrire le cache si la fenêtre n'est pas entièrement couverte. C'est pourquoi le cache est resté inchangé au lieu d'être corrompu.726fb84choisirPeriode() — le maillon manquant. Le dump des expressions donne la cause de fond : « Quantité N » = Sum({<Type_Cal={'N'}>} quantite) « Quantité COMP » = Sum({<Type_Cal={'$(vPeriod_comp)'}…>} quantite) Un pont de périodes duplique les lignes de faits ; Type_Cal marque la période analysée (N) ou de comparaison (COMP), et le champ Période (4 valeurs) décide de quelle période il s'agit. Sélectionner correctement les mois ne suffit donc pas : sous la période par défaut, « Quantité N » rend 0 sur tout mois hors période courante, même parfaitement sélectionné. Orchestration fusionnée : 1. choisirPeriode() essaie chaque valeur de Période et MESURE, sur un cube [Mois] × Quantité N, combien de mois de la fenêtre elle rend disponibles. Aucun libellé n'est deviné. 2. Si une période couvre les 12 mois → master measures (exactes sur toute la fenêtre). Sinon → agrégation directe des faits, en secours. 3. Dans les deux cas, la couverture des 12 mois est revérifiée avant persistance ; sinon l'extraction est refusée et le cache laissé intact. La tendance conserve la règle stricte de4ef0e9f(les 12 clés explicitement présentes, ou pas de tendance), qui écarte aussi le « +4100 % » calculé sur deux points pour un article vendu depuis mai. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DfqUihgixw4K1AmJhizWiu
This commit is contained in:
8 files changed
+389
-145
No files matched your search
+42
-29
@@ -152,6 +152,14 @@ Un seul cube `[Article Code, Mois]` couvre les 12 mois : ni passe N-1 ni
|
||||
rattrapage — c'est exactement ce qu'ils compensaient. Les totaux deviennent la
|
||||
**somme des 12 mois de la fenêtre**.
|
||||
|
||||
Sur l'app de production, les champs `Date`, `Date calendrier` et `Date_Key`
|
||||
existent mais leur sélection ne réduit pas `Sum(quantite)` : ils restent à
|
||||
100 % du total historique. L'extracteur essaie d'abord ces champs puis utilise
|
||||
la dimension maître `Mois` comme chemin fiable. Il crée un list object, retrouve
|
||||
les 12 valeurs `YYYY-MM`, les sélectionne par `qElemNumber`, puis exécute le
|
||||
cube mensuel. Cette méthode ne dépend ni du champ sous-jacent ni de son format
|
||||
dual et conserve le chemin rapide (une sélection articles + un cube paginé).
|
||||
|
||||
Garde-fous : « Quantité N » est incluse dans le cube pour **calibrage**, et le
|
||||
log compare les deux sur les mois de l'année en cours, seul périmètre où la
|
||||
master measure est juste :
|
||||
@@ -161,8 +169,20 @@ master measure est juste :
|
||||
```
|
||||
|
||||
Un calibrage faible signale une expression à ajuster (filtre `flag_type_mvt`,
|
||||
`ca_ttc` plutôt que `ca_ht`…). Quantité totale nulle ou erreur Engine → repli
|
||||
automatique sur l'ancien chemin. `QLIK_USE_EXPR=0` le force.
|
||||
`ca_ttc` plutôt que `ca_ht`…). Il n'existe plus de repli automatique vers les
|
||||
master measures annuelles : quantité totale nulle, champ Date invalide, erreur
|
||||
Engine ou somme incohérente font échouer la synchronisation et laissent le cache
|
||||
précédent intact.
|
||||
|
||||
Après sélection de la fenêtre, l'extracteur vérifie deux invariants avant tout
|
||||
upsert :
|
||||
|
||||
1. la somme de toutes les lignes `[Article Code, Mois]` est égale au total Qlik
|
||||
sans dimension calculé avec les mêmes sélections ;
|
||||
2. pour chaque article, la quantité réseau totale est exactement la somme de ses
|
||||
12 mois. Les mois sans ligne de faits sont alors seulement matérialisés à `0`.
|
||||
|
||||
Une extraction interrompue ou partielle n'est jamais publiée.
|
||||
|
||||
### Valider les expressions sur le vrai serveur
|
||||
|
||||
@@ -203,8 +223,10 @@ au total sans filtre — 0 % signifie que la sélection ne matche rien, 100 % qu
|
||||
n'a aucun effet. Candidats essayés dans l'ordre : `QLIK_DATE_FIELD` (si défini),
|
||||
`Date`, `Date calendrier`, `Date_Key` (celui-ci sélectionné au format `AAAAMMJJ`).
|
||||
|
||||
Si aucun ne filtre, l'extraction le dit et repart sur l'ancien chemin plutôt que
|
||||
de produire une fenêtre fausse.
|
||||
Si aucun ne filtre, l'extraction échoue explicitement plutôt que de produire une
|
||||
fenêtre fausse. Chaque sélection d'un candidat rejeté est effacée avant l'essai
|
||||
suivant ; autrement un premier candidat à zéro contaminait tous les contrôles
|
||||
suivants. Avant cet échec, la dimension maître `Mois` est testée elle aussi.
|
||||
|
||||
## La passe de rattrapage a été supprimée
|
||||
|
||||
@@ -217,7 +239,7 @@ qu'elle recopiait dans chaque mois manquant : d'où les plateaux identiques d'ao
|
||||
Un mois qu'on ne sait pas extraire doit rester **absent**, jamais rempli d'une
|
||||
valeur plausible.
|
||||
|
||||
## Mois vides de la fenêtre glissante (chemin de repli)
|
||||
## Mois vides de la fenêtre glissante
|
||||
|
||||
Les mesures « N » de l'app sont bornées à une année civile. Quand la fenêtre
|
||||
12 mois glissants chevauche deux années (le cas 11 mois sur 12), le chemin
|
||||
@@ -227,22 +249,15 @@ que sur une seule année : les mois de l'année précédente ressortent vides.
|
||||
cours — d'où, en juillet 2026, un trou observé d'août à décembre 2025 sur
|
||||
**tous** les articles.
|
||||
|
||||
Trois garde-fous, dans `qlik-playwright.ts` :
|
||||
Le chemin daté repose uniquement sur les expressions de faits et un cube unique
|
||||
`[Article Code, Mois]`. Après validation de la fenêtre et du total, chaque
|
||||
article reçoit exactement les 12 clés attendues. Une clé absente du cube signifie
|
||||
alors réellement « aucun fait sur ce mois » et vaut `0`; avant cette validation,
|
||||
aucun zéro n'est inventé.
|
||||
|
||||
1. La passe principale n'écrit plus de `0` pour un mois hors année N, et
|
||||
« Quantité COMP » n'écrit rien quand elle est vide. Un mois **absent** peut
|
||||
être rattrapé ; un mois **à 0** se lit comme « pas de vente » et masque le trou.
|
||||
2. `rattraperMoisVides()` : après les passes N et N-1, tout mois vide pour
|
||||
**tous** les articles est ré-extrait en ne sélectionnant **que ses dates** —
|
||||
la mesure se résout alors sur la bonne année, quelle que soit l'écriture de
|
||||
son set analysis.
|
||||
3. Les expressions des master measures sont dumpées au log
|
||||
(`[qlik-pw][dump] expression « Quantité N » = …`) : c'est la seule façon de
|
||||
savoir comment la mesure est bornée.
|
||||
|
||||
Contournement immédiat sans redéploiement : `QLIK_MONTH_DIM=0` repasse sur
|
||||
l'itération mois par mois (une sélection de dates par mois, donc pas de trou),
|
||||
au prix d'une extraction plus lente.
|
||||
`QLIK_MONTH_DIM=0` ou `QLIK_USE_EXPR=0` désactive désormais un prérequis et fait
|
||||
échouer la synchronisation datée : ces options ne peuvent plus réactiver un
|
||||
chemin connu comme incorrect.
|
||||
|
||||
⚠️ Les données déjà en cache gardent leurs zéros : il faut relancer la sync Qlik
|
||||
pour les corriger.
|
||||
@@ -263,21 +278,19 @@ sélection de codes, puis seule la fenêtre de dates change d'un mois à l'autre
|
||||
La sonde de diagnostic de fin de sync a été retirée : elle refaisait une sélection
|
||||
complète des codes et des 365 jours pour rien.
|
||||
|
||||
### Résultat partiel plutôt que rien
|
||||
### Aucun résultat partiel dans le cache
|
||||
|
||||
Le script in-page pousse un point de contrôle (`cfCheckpoint`) après chaque passe.
|
||||
Si la session meurt en cours de route, l'extraction repart de ce point au lieu de
|
||||
tout perdre : les codes déjà traités ont des données **complètes** (la dimension
|
||||
Mois livre tous leurs mois d'un coup), seul le reliquat manque. Le log signale
|
||||
alors `⚠ résultat PARTIEL` — relancer la sync complète le reste.
|
||||
Le script in-page conserve des points de contrôle à des fins de diagnostic, mais
|
||||
une synchronisation datée interrompue est refusée intégralement. Le cache garde
|
||||
sa dernière version complète jusqu'à la réussite d'une nouvelle extraction.
|
||||
|
||||
## Tendance réseau = 12 mois glissants stricts
|
||||
|
||||
`computeNetworkTrend()` reconstruit sa fenêtre à partir de la date du jour :
|
||||
12 mois complets, **mois en cours exclu** (partiel, il tirait la pente vers le bas).
|
||||
Les mois de la fenêtre absents du cache valent 0 (produit non vendu) ; ceux
|
||||
antérieurs au premier mois réellement extrait sont écartés au lieu d'être
|
||||
inventés à 0 (extraction plus courte que 12 mois).
|
||||
La tendance n'est affichée que si les 12 clés sont explicitement présentes dans
|
||||
le cache. Les anciennes séries partielles de deux ou trois mois sont donc
|
||||
refusées au lieu d'être présentées comme une tendance.
|
||||
|
||||
Retirés : ranking (champs/query/colonnes), analyse IA (routes `/api/ai/*`, `bulk-ai-analyzer`,
|
||||
dossier `ai-copilot`), score (`score-engine.ts`, colonne score).
|
||||
|
||||
Reference in new issue
Block a user