Commit Graph
502 Commits
Author SHA1 Message Date
Claude 164bda1fe9 Merge: message OOM Qlik explicite 2026-07-24 08:12:00 +00:00
Claude 1633d5e407 fix(qlik-sync): message explicite quand le serveur Qlik est en OOM
Quand l'app Qlik ne peut pas se charger faute de RAM serveur (code 6
'Not enough memory to load file' / code 3002 'File corrupted' / 'Out of
memory'), le job affiche un message clair ('Serveur Qlik saturé…') au
lieu de l'erreur technique. Ce n'est pas un bug CollectFlow : le sync
échoue à l'ouverture de l'app, avant toute requête.
2026-07-24 08:11:58 +00:00
Claude b5144ed0cf Merge: tooltip tendance + lots Qlik plus petits 2026-07-24 07:41:42 +00:00
Claude 2af7c42b2b fix(grille): tooltip tendance (régression 12 mois) + lots Qlik plus petits (OOM)
- Corrige le tooltip erroné 'X% (4 derniers mois vs 4 précédents)' →
  'Tendance X% sur 12 mois (régression)'. Le calcul est déjà une
  régression linéaire sur 12 mois ; seul le texte était resté l'ancien.
- Réduit la taille des lots du cube [Article Code, Mois] (800→300, replis
  150/75) pour alléger la mémoire moteur Qlik et limiter les 'Out of
  memory / File corrupted' (3002) observés sur le sync.
2026-07-24 07:41:41 +00:00
Claude 147a05c090 Merge into main: modal courbe 12 mois glissants 2026-07-24 06:29:38 +00:00
Claude ac1c404ce5 feat(grille): modal courbe sur 12 mois glissants (réintègre Quantité COMP)
Le modal doit couvrir 12 mois glissants (pas seulement depuis janvier).
Comme 'Quantité N' ne couvre que l'année en cours, on réintègre la mesure
'Quantité COMP' (N-1) pour les mois de l'année précédente : mois année N
→ Quantité N, mois année N-1 → Quantité COMP. La courbe du modal affiche
donc les 12 derniers mois.
2026-07-24 06:29:37 +00:00
Claude 24ed93f833 Merge into main: modal courbe unique + retrait COMP 2026-07-23 20:40:26 +00:00
Claude 5b5e69eed1 feat(grille): modal en courbe unique + retrait Quantité COMP (2025)
- Modal : les 12 barres remplacées par UNE seule courbe SVG des ventes
  réseau mensuelles (points + quantités affichées + axe des mois).
- Sync : retrait de la mesure 'Quantité COMP' (année N-1) — trop lent à
  récupérer. Retour au cube [Article Code, Mois] à 5 mesures (Quantité N).
  Le détail mensuel couvre donc les mois de l'année en cours ; la tendance
  (régression) se calcule sur ces mois.
2026-07-23 20:40:24 +00:00
Claude dec99ce3c1 Merge into main: modal Tendance + régression 12 mois + Quantité COMP 2026-07-23 19:53:22 +00:00
Claude 6d349e33b4 feat(grille): modal sur colonne Tendance + tendance par régression 12 mois + Quantité COMP
UI:
- La colonne Tendance (renommée 'Réseau · 12 m') ouvre le modal au clic
  (au lieu de la colonne Nb magasins, remise en simple affichage).
- Tendance calculée par RÉGRESSION LINÉAIRE (moindres carrés) sur les 12
  derniers mois : robuste au bruit, % = pente×durée/moyenne. Libellé
  Forte hausse/Hausse/Stable/Baisse/Forte baisse (seuils ±8% / ±25%).

Sync:
- Ajout de la mesure 'Quantité COMP' (année N-1) au cube [Article Code,
  Mois] → 12 mois glissants : mois de l'année N via Quantité N, mois de
  l'année N-1 via Quantité COMP. Cube 8 colonnes, PAGEM 1200 (<10000
  cellules). Total réseau reste en année N (non gonflé).
  Configurable : QLIK_MEAS_QTE_COMP_ID.
2026-07-23 19:53:20 +00:00
Claude 76e908e8b2 Merge into main: découpage mensuel réseau via dimension Mois 2026-07-23 13:15:44 +00:00
Claude 8a3f18f23b feat(qlik): découpage mensuel réel via dimension Mois (tendance + total corrigé)
La sonde a prouvé que les mesures 'Quantité N' se découpent correctement
par la dimension 'Mois' (id pfGAwTs, format 'YYYYMM'). L'itération par
sélection de Date, elle, renvoyait la valeur annuelle identique chaque
mois (tendance plate + total sommé 12×).

Nouvelle extraction réseau (activée par défaut, QLIK_MONTH_DIM=0 pour
revenir à l'ancienne) : un cube [Article Code, Mois] × 5 mesures par lot
de codes (avec repli code 15 800>400>200), sélection de la fenêtre de
dates une seule fois. Chaque ligne (code, mois, ...) alimente qteByMonth
en 'YYYY-MM' et le total par somme RÉELLE des mois.

Résultat attendu : la colonne Tendance affiche enfin de vraies variations,
le modal montre les ventes réseau mois par mois, et le total réseau n'est
plus gonflé 12×. Nécessite un nouveau Sync pour re-remplir le cache.

Note : 'Quantité N' = année N, donc les mois disponibles sont ceux de
l'année en cours (pas un glissant 12 mois strict) — suffisant pour la
tendance ; on pourra ajouter 'Quantité COMP' pour compléter N-1 si besoin.
2026-07-23 13:15:41 +00:00
Claude e8507490f7 Merge: sonde Mois en fin de sync 2026-07-23 12:10:51 +00:00
Claude adb8455353 diag(qlik): déplace la sonde Mois à la fin du sync (visible dans la queue du log) 2026-07-23 12:10:49 +00:00
Claude f0a553eb92 Merge: sonde Mois scopée 2026-07-23 12:05:23 +00:00
Claude 4cb2c7d1c5 diag(qlik): sonde Mois scopée (50 codes + fenêtre) pour éviter code 15 2026-07-23 12:05:21 +00:00
Claude 0511a3a7ea Merge into main: sonde cube [Article Code, Mois] 2026-07-23 11:52:54 +00:00
Claude 332b21c1ae diag(qlik): sonde cube [Article Code, Mois] x Quantite N
Le dump révèle une dimension 'Mois' (id pfGAwTs) et 'Période' (tKTPVU).
La sonde crée un mini-cube [Article Code, Mois] × Quantité N et logue le
format des valeurs Mois + si la quantité varie par mois — pour concevoir
le vrai découpage mensuel (dimension Mois) qui règlera tendance + total 12x.
2026-07-23 11:52:52 +00:00
Claude 21758573c2 Merge into main: chemin rapide Qlik par défaut + dump mesures/dimensions 2026-07-23 11:38:38 +00:00
Claude 473ed1e467 perf+diag(qlik): chemin rapide activé par défaut + dump mesures/dimensions
- Chemin rapide select-all activé par DÉFAUT (fiable, aucun code 15 en
  prod) — désactivable seulement via QLIK_SELECT_ALL_CODES=0. Plus besoin
  de la variable d'env (elle sautait à chaque mise à jour de la stack).
- Dump diagnostic des mesures + dimensions Qlik disponibles (titre+id)
  pour identifier une mesure Quantité non-annuelle / une dimension Mois,
  car les mesures 'CA N'/'Quantité N' renvoient la valeur annuelle figée
  (mois identiques → tendance impossible + total réseau sommé 12×).
2026-07-23 11:38:36 +00:00
Claude b9a5bd5e22 Merge into main: diag qteByMonth distribution (variant vs identique) 2026-07-23 11:35:29 +00:00
Claude 74b183abb3 diag(qlik): distribution codes variants vs identiques (mois) + exemples 2026-07-23 11:35:27 +00:00
Claude 5aeb1ca496 Merge branch 'claude/exciting-goldberg-wILkj' into main
diag(qlik): log échantillon qteByMonth pour diagnostiquer la tendance
réseau (indique si les valeurs mensuelles varient ou sont identiques).
2026-07-23 11:16:12 +00:00
Claude 5b74133ecd diag(qlik): log échantillon qteByMonth (vérifie si les mois varient) 2026-07-23 11:14:58 +00:00
Claude 5b874f3581 Merge branch 'claude/exciting-goldberg-wILkj' into main
feat(grille): tendance réseau (sparkline 12 mois) + modal ventes réseau
par mois. Nécessite un nouveau Sync Qlik pour peupler le détail mensuel.
2026-07-23 09:41:03 +00:00
Claude 71563500a0 feat(grille): tendance réseau (sparkline) + modal ventes réseau par mois
Le sync Qlik calculait déjà les ventes réseau mois par mois mais les
sommait en un total. On conserve désormais le détail mensuel.

- Sync : accumulation additive qteByMonth { code: { 'YYYY-MM': qté } }
  in-page (chemins rapide + par lots), rattachée au métrique réseau.
  Reset propre en cas de repli code 15. Total inchangé.
- Stockage : colonne jsonb qte_by_month sur qlik_network_metrics
  (schema + db-init ALTER), upsert + lecture.
- ProductRow.qteReseauByMonth propagé jusqu'à la grille.
- UI grille :
  · colonne '% Présence réseau' remplacée par 'Tendance réseau' :
    sparkline 12 mois teintée + flèche + variation % (moyenne 4 derniers
    mois vs 4 précédents), triable ;
  · cellule 'Nb magasins' rendue cliquable → modal des ventes réseau
    mois par mois (barres, 12 derniers mois).

Nécessite un nouveau Sync Qlik pour peupler le détail mensuel (les
données déjà en cache n'ont que le total → modal 'pas encore de détail').
2026-07-22 14:17:57 +00:00
Claude ff264dcdff Merge branch 'claude/exciting-goldberg-wILkj' into main
perf(qlik): chemin rapide select-all pour la sync Qlik derrière le flag
QLIK_SELECT_ALL_CODES (repli auto sur le chemin par lots en cas de code 15).
2026-07-22 11:34:32 +00:00
Claude 6c5e28b05e perf(qlik): chemin rapide select-all (sélection Article Code unique) derrière flag
La sync Qlik itérait mois × lots de 150 articles, en re-sélectionnant les
mêmes Article Code à chaque lot. La SelectValues répétée (~22 s × ~120)
représentait ~72% du temps total (~60 min pour 12 mois).

Ajoute un chemin rapide (flag env QLIK_SELECT_ALL_CODES=1) qui sélectionne
TOUS les Article Code une seule fois, puis n'itère que la sélection Date
par mois avec un seul cube paginé (Article Code en dimension). Passe de
~120 SelectValues Article Code à 1, et de ~120 cubes à 12 → gain estimé
~60 min → ~5-8 min.

Repli automatique et sûr : en cas d'erreur moteur code 15, les résultats
partiels et les sélections sont réinitialisés et l'ancien chemin par lots
reprend le relais. Flag désactivé par défaut : comportement inchangé tant
qu'on n'active pas la variable. À valider sur le Qlik réel.
2026-07-22 09:47:31 +00:00
Claude 6adcb0d4c8 Merge branch 'claude/exciting-goldberg-wILkj' into main
Grille : bouton "Rafraîchir" pour forcer le rechargement serveur (bypass
du cache 10 min, met à jour la colonne INIT et toutes les données).
2026-07-22 06:14:59 +00:00
Claude 2e25bbc5b3 feat(grille): bouton "Rafraîchir" pour forcer le rechargement serveur
Ajoute un bouton dans l'en-tête de la Grille qui force le rechargement
des données depuis le serveur en ignorant le cache mémoire de 10 min
(via le paramètre URL _refresh → refresh=1 → forceRefresh). Utile pour
remonter immédiatement l'état serveur courant, notamment la colonne INIT.
Spinner pendant le chargement, désactivé si un chargement est en cours.
2026-07-21 21:11:28 +00:00
Claude d0f92e46a3 Merge branch 'claude/exciting-goldberg-wILkj' into main
Corrections Hit Parade / Gestion de stock (ventes nettes par magasin,
tri stock négatif) et Grille (colonne INIT des gammes rechargée à chaque
chargement, y compris sur cache; colonne Gamme conserve le snapshot).
2026-07-21 15:15:34 +00:00
Claude f0fdab465c fix(grille): colonne INIT rechargée à chaque chargement (même sur cache)
La colonne Gamme conserve la valeur du snapshot (comportement voulu). Mais
la colonne INIT ne se mettait pas à jour : getProductRows sert les lignes
depuis un cache mémoire de 10 min, et le client n'envoie 'refresh=1' que
sur le bouton de rafraîchissement manuel. Sur une navigation normale dans
les 10 min, codeGammeInit restait donc figé.

Correctif : sur un hit de cache, on re-requête la gamme serveur courante
(pgGetGammesByFournisseur, 1 requête légère) et on met à jour uniquement
codeGammeInit sur les lignes cachées. codeGamme (snapshot) n'est pas
touché ; les données lourdes (ventes/stock/réseau) restent cachées.

Résultat : la colonne INIT reflète toujours l'état serveur à chaque
chargement, et le marqueur 'modifié' (Gamme ≠ INIT) se résorbe dès que
le serveur rattrape la modification. La révision précédente (reconcilier
codeGamme) est annulée : la colonne Gamme reste le snapshot tel quel.
2026-07-21 15:05:02 +00:00
Claude e9ac5bc0a5 fix(grille): la grille reflète l'état serveur courant des gammes (INIT rechargé)
La grille rechargeait bien le gamme INIT depuis l'état live du serveur à
chaque chargement (Phase 6), mais la Phase 9 réappliquait ensuite
AVEUGLÉMENT le 'after' du dernier snapshot sur codeGamme — même quand la
modification avait déjà été appliquée sur le serveur (ou que la gamme
serveur avait évolué depuis). Résultat : la grille affichait l'ancienne
cible du snapshot au lieu de l'état serveur réel, et une modif 'en
attente' fantôme.

Désormais on ne réapplique une modif du snapshot QUE si elle est encore
réellement en attente côté serveur (change.before === gamme live). Sinon
on garde l'état serveur courant. La grille montre donc toujours où en
sont les gammes sur le serveur, et une modif disparaît du 'en attente'
dès qu'elle est appliquée côté serveur — le suivi reste juste.

Note : les brouillons locaux (localStorage) restent gérés côté client
comme du travail non sauvegardé.
2026-07-21 15:00:40 +00:00
Claude eba4cb0774 fix(hit-parade,stock): retire le filtre montant (théorie invalidée) + tri stock négatif
Analyse de cohérence de stock sur le cas 487673 site 579 : 24 réceptions,
31 ventes brutes, 7 retours clients → 24 ventes nettes, stock final 3.
Le « 38 » affiché = 31 + 7 : signature de l'ancienne formule SUM(ABS)
qui additionnait les retours. La formule nette SUM(-qtemvt) déjà en place
donne 24 — le filtre mntmvtttc <> 0 (hypothèse de lignes fantômes 0 €)
était inutile : aucune ligne de ce type dans les données réelles. Retiré
pour rester strictement aligné sur le calcul de la Grille.

Gestion de stock : ORDER BY cs.qte (colonne affichée) au lieu de
cs.stockdispo (colonne différente) dans pgGetStockNegatif.
2026-07-07 06:46:45 +00:00
LogiFlow cda149ccaa Merge pull request #6 from R0m1k3/claude/exciting-goldberg-wILkj
Claude/exciting goldberg w i lkj
2026-07-06 23:19:39 +02:00
Claude ea19c5771e fix(hit-parade): exclut les lignes de quantité sans montant (corrections)
Cas réel : codein 487673 site 579 affichait 38 vendus au lieu de 24,
avec un CA pourtant exact (215,76 €) — mvtart contient des lignes
genremvt=3 portant une quantité mais aucun montant TTC (corrections /
régularisations), que les endpoints officiels de l'API excluent.

Ajout du filtre mntmvtttc IS NOT NULL AND <> 0 dans l'agrégation :
une vente réelle a toujours un montant TTC non nul. Validé sur
PostgreSQL local en reproduisant le cas : sans filtre 38/215,76 €
(= symptôme), avec filtre 24/215,76 € (= réalité). Le CA et les
requêtes Analytics ne changent pas (ces lignes valent 0 €).
2026-07-06 21:15:44 +00:00
Claude 159508132c fix(hit-parade): agrégation isolée sur mvtart×articles — corrige les chiffres faux des 2 magasins
La version précédente agrégeait les ventes avec les jointures fournisseur
(LATERAL par ligne de mouvement + fouident) dans la même passe : si
fouident contient des codes dupliqués, chaque mouvement était compté
plusieurs fois → chiffres faux sur les deux magasins, et le LATERAL
s'exécutait par mouvement (très lent).

Restructuration, validée sur 12 000 mouvements réels de l'API chargés
dans un PostgreSQL 16 local :
- CTE ventes : mvtart JOIN articles uniquement (1:1), SUM(-qtemvt) /
  SUM(-mntmvtttc) / SUM(margemvt) par (codein, site) — le calcul
  canonique de la Grille (pgGetMensuelByFournisseur), signes vérifiés
  sur les mouvements réels (ventes négatives, genremvt=3).
- CTE attrs : libellé/fournisseur/nomenclature joints APRÈS agrégation,
  dédupliqués par DISTINCT ON — aucune jointure ne peut plus fausser
  les sommes (totaux invariants aux doublons artfou1/fouident injectés).
- Même principe pour pgGetCaByFournisseur, pgGetStockNegatif,
  pgGetSansVente6Mois : sous-requête artfou1 DISTINCT ON au lieu du
  LATERAL par ligne.
2026-07-06 20:49:12 +00:00
Claude b7de347a99 fix(grid,hit-parade): convention de signe nette + lint React Compiler
- Grille (fallback API mensuel) : Math.abs remplacé par la négation sur
  qte_vendue/ca_ht (négatifs côté API) — les retours clients restent
  déduits au lieu d'être inversés en positif, même convention que le SQL.
- Hit Parade (client) : ColHeader extrait hors du composant (erreur
  'Cannot create components during render'), useMemo déplacés avant
  exportToExcel pour préserver la mémoïsation React Compiler, variable
  idx inutilisée supprimée. ESLint 0 erreur, build OK.
2026-07-06 20:28:03 +00:00
Claude d733755659 fix(hit-parade): ventes nettes par magasin — corrige les chiffres faussés (579)
La requête Hit Parade divergeait du calcul canonique de la Grille :
- SUM(ABS(qtemvt)) additionnait les retours clients comme des ventes au
  lieu de les déduire → quantités et CA gonflés sur le magasin ayant des
  retours/avoirs sur la période (visible sur 579).
- ABS(SUM(mntmvtttc)) inversait le signe d'un CA net négatif.
- GROUP BY no_id + jointure artfou1 preference=1 non dédupliquée pouvait
  produire plusieurs lignes par (codein, site), écrasées par le pivot.

Corrections :
- Hit Parade : ventes nettes SUM(-qtemvt) / SUM(-mntmvtttc), agrégation
  par (codein, site), fournisseur préféré via LATERAL ... LIMIT 1,
  stock agrégé par codein ; pivot en accumulation (+=) par sécurité.
- Analytics (même classe de bug) : pgGetCaByFournisseur et
  pgGetCaByNomenclature passent en CA net ; jointure fournisseur
  dédupliquée (LATERAL LIMIT 1) pour éviter le double comptage.
- Gestion de stock : pgGetStockNegatif et pgGetSansVente6Mois dédupliquent
  le fournisseur préféré (LATERAL LIMIT 1) pour éviter les lignes en double.

Audit complet du mapping par magasin (292/579) côté client : aucun champ
inversé (hit-parade, analytics, dashboard, grid, heatmap). Build OK.
2026-07-06 15:55:43 +00:00
R0m1k3 32f9a27563 Fix Qlik network column sorting 2026-06-22 12:12:48 +00:00
R0m1k3 abac5c5ee5 perf(qlik): optimize network sync extraction 2026-06-22 09:58:49 +00:00
R0m1k3 1cb6c2496d fix(qlik): retry engine aborts after selections 2026-06-22 06:13:05 +00:00
R0m1k3 f005c08ad6 fix(qlik): recreate hypercube per batch 2026-06-22 05:44:37 +00:00
R0m1k3 850852912f fix(qlik): track async sync job status 2026-06-21 19:08:04 +00:00
R0m1k3 e7bcba169c fix(qlik): extract by month and code batches 2026-06-21 18:24:53 +00:00
R0m1k3 c4eeab11d2 fix(qlik): select all articles per month 2026-06-21 16:43:36 +00:00
R0m1k3 649a1df267 fix(qlik): aggregate multi-month extraction correctly 2026-06-21 14:32:51 +00:00
R0m1k3 6036ea5600 fix(qlik): avoid abort on batched network extraction 2026-06-21 12:08:13 +00:00
R0m1k3 6d27c7935d fix: align qlik grid extraction date range 2026-06-21 11:26:49 +00:00
MichaelandClaude Opus 4.8 de8a435c14 fix(qlik): batch SelectValues to avoid Engine abort + drop couv stock metric
Large supplier (4816 codes) triggered Qlik Engine "Request aborted"
(code 15): a single SelectValues over all codes forced the hypercube to
calculate too many rows at once. Now select in 1200-code batches and
accumulate, keeping each calc small. 1417 codes worked before, 4816 did
not - chunking scales to any supplier.

Also remove the "Couverture de stock" network column end-to-end (grid,
types, Qlik clients, cache, schema, db-init), shifting the marge measure
index from 6 to 5 and the hypercube width from 7 to 6.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 10:55:03 +02:00