From 9493a39d12c81ed5ffab691919e2e447e69a6d86 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 21 Feb 2026 18:30:48 +0100 Subject: [PATCH] feat(grid): preserve initial gamme reference and add modification icon --- diagnose_db.ts | 30 ------------------- src/db/schema.ts | 1 + src/features/grid/api/get-product-rows.ts | 25 +++++++++++++++- src/features/grid/components/heatmap-grid.tsx | 21 +++++++++---- src/types/grid.ts | 2 ++ 5 files changed, 42 insertions(+), 37 deletions(-) delete mode 100644 diagnose_db.ts diff --git a/diagnose_db.ts b/diagnose_db.ts deleted file mode 100644 index 94f2891..0000000 --- a/diagnose_db.ts +++ /dev/null @@ -1,30 +0,0 @@ - -import { db } from "./src/db"; -import { ventesProduits } from "./src/db/schema"; -import { sql } from "drizzle-orm"; - -async function diagnose() { - console.log("Checking DB connection..."); - try { - await db.execute(sql`SELECT 1`); - console.log("DB Connection OK."); - - console.log("Checking table 'ventes_produits'..."); - const tableCheck = await db.execute(sql`SELECT EXISTS ( - SELECT FROM information_schema.tables - WHERE table_name = 'ventes_produits' - )`); - console.log("Table exists:", tableCheck.rows[0].exists); - - if (tableCheck.rows[0].exists) { - const count = await db.select({ count: sql`count(*)` }).from(ventesProduits); - console.log("Total rows in 'ventes_produits':", count[0].count); - } - } catch (err) { - console.error("Diagnosis failed:", err); - } finally { - process.exit(0); - } -} - -diagnose(); diff --git a/src/db/schema.ts b/src/db/schema.ts index f011245..fc21ee3 100644 --- a/src/db/schema.ts +++ b/src/db/schema.ts @@ -14,6 +14,7 @@ export const ventesProduits = pgTable("ventes_produits", { // Gamme & Nomenclature codeGamme: varchar("code_gamme", { length: 20 }), + codeGammeInit: varchar("code_gamme_init", { length: 20 }), code3: varchar("code3", { length: 20 }), libelle3: varchar("libelle3", { length: 500 }), diff --git a/src/features/grid/api/get-product-rows.ts b/src/features/grid/api/get-product-rows.ts index 2e0a533..7501765 100644 --- a/src/features/grid/api/get-product-rows.ts +++ b/src/features/grid/api/get-product-rows.ts @@ -2,10 +2,12 @@ import { db } from "@/db"; import { ventesProduits } from "@/db/schema"; -import { eq, and, ne, like } from "drizzle-orm"; +import { eq, and, ne, like, sql } from "drizzle-orm"; import type { ProductRow, GammeCode, GridFilters } from "@/types/grid"; import { computeProductScores } from "@/lib/score-engine"; +let isSchemaInitialized = false; + interface GetProductRowsInput { codeFournisseur: string; magasin?: string; @@ -15,6 +17,26 @@ interface GetProductRowsInput { export async function getProductRows(input: GetProductRowsInput): Promise { const { codeFournisseur, magasin = "TOTAL", filters } = input; + // Self-healing: Ensure codeGammeInit column exists and is populated + if (!isSchemaInitialized) { + try { + await db.execute(sql` + ALTER TABLE ventes_produits + ADD COLUMN IF NOT EXISTS code_gamme_init VARCHAR(20) + `); + await db.execute(sql` + UPDATE ventes_produits + SET code_gamme_init = code_gamme + WHERE code_gamme_init IS NULL + `); + isSchemaInitialized = true; + console.log("[Schema] codeGammeInit initialized successfully."); + } catch (err) { + console.error("[Schema] Failed to initialize codeGammeInit:", err); + // We continue anyway, the mapping fallback will handle it for the UI + } + } + // ... (allowedPeriods calculation remains the same) const now = new Date(); const allowedPeriods = new Set(); @@ -106,6 +128,7 @@ export async function getProductRows(input: GetProductRowsInput): Promise (
- {row.original.codeGamme || "-"} + {row.original.codeGammeInit || "-"}
), }, @@ -295,12 +295,21 @@ export function HeatmapGrid({ onSelectionChange }: HeatmapGridProps) { size: 110, cell: ({ row }) => { const effectiveGamme = (draftChanges[row.original.codein] ?? row.original.codeGamme) as GammeCode | null; + const isModified = row.original.codeGamme !== row.original.codeGammeInit && row.original.codeGammeInit !== null; + return ( - setDraftGamme(row.original.codein, g)} - /> +
+ setDraftGamme(row.original.codein, g)} + /> + {isModified && !draftChanges[row.original.codein] && ( +
+ +
+ )} +
); }, }, diff --git a/src/types/grid.ts b/src/types/grid.ts index fc7f4d6..b66eb0a 100644 --- a/src/types/grid.ts +++ b/src/types/grid.ts @@ -13,6 +13,7 @@ export interface VenteProduit { gtin: string | null; reference: string | null; codeGamme: GammeCode | null; + codeGammeInit: GammeCode | null; code3: string | null; libelle3: string | null; magasin: string; @@ -43,6 +44,7 @@ export interface ProductRow { code3: string; libelle3: string; codeGamme: GammeCode | null; + codeGammeInit: GammeCode | null; /** Draft gamme value before saving */ codeGammeDraft: GammeCode | null; /** 12-month sales quantities, indexed by YYYYMM key */