From f0fdab465c9f555c5c648b2c30eedc5ce34a703f Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 21 Jul 2026 15:05:02 +0000 Subject: [PATCH] =?UTF-8?q?fix(grille):=20colonne=20INIT=20recharg=C3=A9e?= =?UTF-8?q?=20=C3=A0=20chaque=20chargement=20(m=C3=AAme=20sur=20cache)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- src/features/grid/api/get-product-rows.ts | 55 ++++++++++++----------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/src/features/grid/api/get-product-rows.ts b/src/features/grid/api/get-product-rows.ts index 1ae30c2..376232c 100644 --- a/src/features/grid/api/get-product-rows.ts +++ b/src/features/grid/api/get-product-rows.ts @@ -47,10 +47,33 @@ export function invalidateGridRowsCache(codeFournisseur?: string) { gridRowsPending.clear(); } +/** + * Rafraîchit UNIQUEMENT la colonne INIT (codeGammeInit = gamme serveur courante) + * sur des lignes servies depuis le cache. La colonne Gamme (codeGamme) n'est pas + * touchée : elle conserve la valeur issue du snapshot. Ainsi l'état serveur (INIT) + * est toujours à jour à chaque chargement, même sur un hit du cache 10 min — et le + * marqueur "modifié" (Gamme ≠ INIT) se résorbe dès que le serveur rattrape la modif. + */ +async function refreshGammeInit(rows: ProductRow[], codeFournisseur: string): Promise { + try { + const gammeMap = await pgGetGammesByFournisseur(codeFournisseur); + if (gammeMap.size === 0) return; + for (const row of rows) { + const live = gammeMap.get(row.codein); + if (live !== undefined) row.codeGammeInit = live as GammeCode; + } + } catch (e) { + console.error("[getProductRows] refreshGammeInit error:", (e as Error).message?.slice(0, 200)); + } +} + export async function getProductRows(input: GetProductRowsInput): Promise { const cacheKey = gridRowsCacheKey(input); const cached = gridRowsCache.get(cacheKey); if (!input.forceRefresh && cached && Date.now() - cached.createdAt < GRID_ROWS_CACHE_TTL_MS) { + // La colonne INIT doit refléter l'état serveur à CHAQUE chargement, + // y compris sur un hit de cache (les données lourdes restent, elles, cachées). + await refreshGammeInit(cached.rows, input.codeFournisseur); return cached.rows; } @@ -313,15 +336,10 @@ async function buildProductRows(input: GetProductRowsInput): Promise 0) { const changes = snaps[0].changes as Record; - let enAttente = 0; - let obsoletes = 0; for (const [codein, change] of Object.entries(changes)) { const product = productMap.get(codein); - if (!product || !change.after) continue; - - const gammeLive = product.codeGammeInit; // état serveur courant - const before = change.before ?? null; - const stillPending = before === (gammeLive ?? null) && change.after !== gammeLive; - - if (stillPending) { - // Modification pas encore appliquée sur le serveur → on la remonte + if (product && change.after) { + // codeGammeInit reste figé (état serveur) — seul codeGamme est overridé product.codeGamme = change.after as GammeCode; - enAttente++; - } else { - // Déjà appliquée côté serveur (ou serveur divergent) → on garde le LIVE - product.codeGamme = gammeLive; - obsoletes++; } } - console.log(`[getProductRows] Snapshot: ${enAttente} modif(s) en attente réappliquée(s), ${obsoletes} déjà appliquée(s)/obsolète(s) ignorée(s)`); + console.log(`[getProductRows] Gammes restaurées depuis snapshot`); } } catch (snapErr) { console.error("[getProductRows] Snapshot restore error:", snapErr);