Grille : colonnes de prix, et menu « Vues » pour les blocs de colonnes

Deux colonnes s'ajoutent à la suite de la tendance réseau :

  · PV moyen (Réseau) — calculé par l'application, CA réseau ÷ quantité
    vendue, exactement la définition déjà retenue par la fiche produit.
    Sans quantité sur la période, la colonne affiche « - » : le rapport
    n'existe pas, et un prix à 0 € se lirait comme un article donné.
  · PV central (Article) — le prix de vente de la fiche article, lu en base
    (article_infosup.prix_vente_mini), sans retraitement.

Les deux restent deux colonnes. En dériver un écart chiffré supposerait une
assiette commune — HT/TTC, remises — que les deux sources ne garantissent
pas ; le rapprochement se fait à l'œil, en connaissance de cause.

Le bouton de repli du bloc mensuel devient un menu « Vues » à deux entrées,
ventes mensuelles et prix, chacune repliable. Il agit par BLOCS, là où le
menu « Colonnes » voisin agit colonne par colonne : douze cellules
mensuelles ou deux prix ne se masquent pas une par une. Les deux états sont
persistés.

Au passage, le tri des colonnes réseau était faux. La sentinelle ±Infinity
choisie d'après le sens de tri courant ne pouvait pas fonctionner : TanStack
mémorise le résultat de l'accesseur dans `row._valuesCache` et ne le
réévalue jamais, si bien que la valeur calculée au premier tri restait figée
et remontait les lignes sans donnée en tête dès qu'on inversait le sens.
`sortUndefined: "last"`, traité avant l'inversion, les garde en bas dans les
deux sens. Les cinq colonnes réseau existantes en bénéficient, et `sorting`
quitte les dépendances des colonnes : plus de reconstruction complète à
chaque clic d'en-tête.

Vérifié sur build de production : les deux colonnes se placent bien après la
tendance, « - » sur quantité réseau nulle comme sur PV central absent, et le
tri place les absents en bas au premier clic (décroissant) comme au deuxième
(croissant). Menu « Vues » : 31 colonnes avec les deux blocs, 29 sans les
prix, 17 sans rien, 19 avec les prix seuls — chaque fois sur toutes les
lignes montées, sans rechargement, et l'état survit au rechargement.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYGgoQCG1VCe42HzbzhAXR
This commit is contained in:
Claude committed 2026-08-13 20:16:36 +00:00
1 parent 0a2bc8318b
commit 52b663579f
2 files changed
+171 -37

No files matched your search

+10 -3
View File
@@ -30,6 +30,9 @@ interface GridState {
*/
showMonthlySales: boolean;
setShowMonthlySales: (visible: boolean) => void;
/** Bloc des deux colonnes de prix (PV moyen réseau, PV central) affiché ou non. */
showPrices: boolean;
setShowPrices: (visible: boolean) => void;
/** Currently displayed store: "TOTAL" | "292" | "579" */
activeMagasin: string;
@@ -85,7 +88,7 @@ function computeSummary(rows: ProductRow[], drafts: Record<string, GammeCode>, m
/** Sous-ensemble réellement écrit dans le navigateur (cf. `partialize`). */
type GridPersisted = Pick<
GridState,
"filters" | "displayDensity" | "draftChanges" | "activeGridQuery" | "columnVisibility" | "columnSizing" | "showMonthlySales"
"filters" | "displayDensity" | "draftChanges" | "activeGridQuery" | "columnVisibility" | "columnSizing" | "showMonthlySales" | "showPrices"
>;
export const useGridStore = create<GridState>()(
@@ -117,8 +120,10 @@ export const useGridStore = create<GridState>()(
columnVisibility: {},
columnSizing: {},
showMonthlySales: true,
showPrices: true,
setShowMonthlySales: (visible) => set({ showMonthlySales: visible }),
setShowPrices: (visible) => set({ showPrices: visible }),
setActiveMagasin: (code) => {
set({ activeMagasin: code });
@@ -252,10 +257,11 @@ export const useGridStore = create<GridState>()(
const c = etat.filters.code3;
etat.filters.code3 = typeof c === "string" && c !== "" ? [c] : Array.isArray(c) ? c : null;
}
// Drapeau ajouté après coup : un état persisté antérieur n'en a
// Drapeaux ajoutés après coup : un état persisté antérieur n'en a
// pas, et une valeur `undefined` écraserait la valeur par défaut
// à la fusion (le bloc mensuel disparaîtrait sans raison).
// à la fusion (le bloc disparaîtrait sans raison).
if (typeof etat.showMonthlySales !== "boolean") etat.showMonthlySales = true;
if (typeof etat.showPrices !== "boolean") etat.showPrices = true;
return etat;
},
// Only persist filters, display density, drafts, active grid query, and column visibility/sizing
@@ -267,6 +273,7 @@ export const useGridStore = create<GridState>()(
columnVisibility: state.columnVisibility,
columnSizing: state.columnSizing,
showMonthlySales: state.showMonthlySales,
showPrices: state.showPrices,
}),
}
)