feat: Introduce product assortment grid client and direct PostgreSQL data access for FF Nancy.

This commit is contained in:
Michael committed 2026-03-20 14:25:30 +01:00
1 parent 2e1988a6f5
commit e391550a30
2 files changed
+20 -9

No files matched your search

+9 -5
View File
@@ -23,9 +23,10 @@ interface GridClientProps {
magasin: string; magasin: string;
} }
export function GridClient({ initialRows, nomFournisseur, fournisseurs, magasins, magasin }: GridClientProps) { export function GridClient({ initialRows, codeFournisseur, nomFournisseur, fournisseurs, magasins, magasin }: GridClientProps) {
const setRows = useGridStore((s) => s.setRows); const setRows = useGridStore((s) => s.setRows);
const setActiveGridQuery = useGridStore((s) => s.setActiveGridQuery); const setActiveGridQuery = useGridStore((s) => s.setActiveGridQuery);
const setFilter = useGridStore((s) => s.setFilter);
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const [selectedCodeins, setSelectedCodeins] = useState<string[]>([]); const [selectedCodeins, setSelectedCodeins] = useState<string[]>([]);
@@ -52,12 +53,15 @@ export function GridClient({ initialRows, nomFournisseur, fournisseurs, magasins
useEffect(() => { useEffect(() => {
if (!isMounted) return; if (!isMounted) return;
// Optimisation : On évite le JSON.parse(JSON.stringify()) qui est très lourd sur 1000 lignes // Réinitialiser les filtres gamme et code3 lors du changement de fournisseur.
// On passe directement les initialRows au moteur de score, ou on fait une copie superficielle si nécessaire. // Ces filtres sont persistés en localStorage (Zustand persist) et s'appliquent
// Le moteur de score doit idéalement retourner de nouveaux objets. // au nouveau fournisseur, cachant toutes les lignes si le filtre ne correspond pas.
setFilter("codeGamme", null);
setFilter("code3", null);
const scoredRows = computeProductScores([...initialRows]); const scoredRows = computeProductScores([...initialRows]);
setRows(scoredRows); setRows(scoredRows);
}, [initialRows, setRows, isMounted]); }, [codeFournisseur, initialRows, setRows, setFilter, isMounted]);
const handleSave = () => { const handleSave = () => {
startTransition(async () => { startTransition(async () => {
+11 -4
View File
@@ -267,12 +267,19 @@ export async function pgGetNomenclatureByFournisseur(codefou: string): Promise<M
// Découverte de la colonne parent : mise en cache module-level (1 seule fois par process) // Découverte de la colonne parent : mise en cache module-level (1 seule fois par process)
if (_nomenclatureParentCol === undefined) { if (_nomenclatureParentCol === undefined) {
const metaResult = await db.execute(sql` const metaResult = await db.execute(sql`
SELECT column_name FROM information_schema.columns SELECT column_name, data_type FROM information_schema.columns
WHERE table_name = 'nomenclature' ORDER BY ordinal_position WHERE table_name = 'nomenclature' ORDER BY ordinal_position
`); `);
const nomCols = (metaResult.rows as { column_name: string }[]).map(r => r.column_name); const nomCols = (metaResult.rows as { column_name: string; data_type: string }[]);
console.log("[pg-ff] Nomenclature colonnes:", nomCols.join(", ")); console.log("[pg-ff] Nomenclature colonnes:", nomCols.map(r => `${r.column_name}(${r.data_type})`).join(", "));
_nomenclatureParentCol = nomCols.find(c => /parent/i.test(c) || (c !== "no_id" && /no_id$/i.test(c))) ?? null; // Cherche une colonne "parent" qui soit un entier (FK vers no_id du parent)
// "chemin_pere" = chemin vers le père en français
// On vérifie le data_type : integer/bigint/smallint uniquement (pas text/varchar qui serait un chemin matérialisé)
const parentRow = nomCols.find(r =>
(/parent|pere|father/i.test(r.column_name) || (r.column_name !== "no_id" && /no_id$/i.test(r.column_name)))
&& /int|serial/i.test(r.data_type)
);
_nomenclatureParentCol = parentRow?.column_name ?? null;
console.log("[pg-ff] Nomenclature parentCol:", _nomenclatureParentCol); console.log("[pg-ff] Nomenclature parentCol:", _nomenclatureParentCol);
} }
const parentCol = _nomenclatureParentCol; const parentCol = _nomenclatureParentCol;