fix: snapshot deletion, restore grid logic and add diagnostic API

This commit is contained in:
Michael committed 2026-03-10 16:07:24 +01:00
1 parent 5eb3f6732e
commit 8237cf2d9f
3 files changed
+83 -30

No files matched your search

+51 -14
View File
@@ -17,16 +17,64 @@ interface GetProductRowsInput {
}
export async function getProductRows(input: GetProductRowsInput): Promise<ProductRow[]> {
// MODEL DIAGNOSTIC (Clean version)
const { codeFournisseur, magasin = "TOTAL", filters } = input;
console.log(`\n>>> [getProductRows] RECEIVED CALL for supplier: ${codeFournisseur}, magasin: ${magasin}`);
try {
// 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);
}
}
const now = new Date();
const allowedPeriods = new Set<string>();
for (let i = 12; i >= 0; i--) {
const d = new Date(now.getFullYear(), now.getMonth() - i, 1);
allowedPeriods.add(`${d.getFullYear()}${String(d.getMonth() + 1).padStart(2, "0")}`);
}
const conditions = [
eq(ventesProduits.codeFournisseur, codeFournisseur),
ne(ventesProduits.periode, "TOTAL"),
magasin !== "TOTAL" ? eq(ventesProduits.magasin, magasin) : ne(ventesProduits.magasin, "TOTAL"),
];
if (filters?.code3) {
conditions.push(eq(ventesProduits.code3, filters.code3));
} else if (filters?.code2) {
conditions.push(like(ventesProduits.code3, `${filters.code2}%`));
} else if (filters?.code1) {
conditions.push(like(ventesProduits.code3, `${filters.code1}%`));
}
const rows = await db
.select()
.from(ventesProduits)
.where(and(...conditions));
console.log(`[getProductRows] Fetching for ${codeFournisseur} (${magasin}). Found ${rows.length} rows.`);
const productMap = new Map<string, ProductRow>();
const storeParticipationMap = new Map<string, Map<string, Set<string>>>(); // codein -> magasin -> Set of periods
for (const row of rows) {
const { codein, magasin, periode } = row;
const isInPeriod = allowedPeriods.has(periode);
// Suivi de la participation par magasin (seulement si dans la période et pas TOTAL)
if (isInPeriod && magasin !== "TOTAL") {
if (!storeParticipationMap.has(codein)) storeParticipationMap.set(codein, new Map());
const productStores = storeParticipationMap.get(codein)!;
@@ -36,20 +84,13 @@ export async function getProductRows(input: GetProductRowsInput): Promise<Produc
let existing = productMap.get(codein);
// Si le produit n'existe pas encore, on l'initialise avec les métadonnées de cette ligne
if (!existing) {
const c3 = row.code3 || "";
const c1 = c3.slice(0, 2);
const c2 = c3.slice(0, 4);
const NOMENCLATURE_LABELS: Record<string, string> = {
"20": "LIQUIDES",
"30": "ÉPICERIE",
"40": "DPH",
"50": "BAZAR",
"60": "TEXTILE",
"70": "FRAIS",
// Rayons
"20": "LIQUIDES", "30": "ÉPICERIE", "40": "DPH", "50": "BAZAR", "60": "TEXTILE", "70": "FRAIS",
"2001": "EAUX", "2002": "JUS DE FRUITS", "2003": "SODAS / BOUILLONS", "2004": "BIERES", "2005": "VINS", "2006": "CIDRES", "2007": "APERITIFS", "2008": "ALCOOLS",
"3001": "ÉPICERIE SALÉE", "3002": "ÉPICERIE SUCRÉE", "3003": "PETIT DÉJEUNER", "3004": "CONSERVES", "3005": "PLAT CUISINES",
"4001": "HYGIÈNE", "4002": "ENTRETIEN", "4003": "PARFUMERIE",
@@ -85,7 +126,6 @@ export async function getProductRows(input: GetProductRowsInput): Promise<Produc
productMap.set(codein, existing);
}
// On n'agrège les chiffres QUE si la période fait partie des 12 derniers mois
if (isInPeriod) {
const qty = Math.abs(parseFloat(row.quantite?.toString() ?? "0"));
const ca = Math.abs(parseFloat(row.montantMvt?.toString() ?? "0"));
@@ -99,7 +139,6 @@ export async function getProductRows(input: GetProductRowsInput): Promise<Produc
}
}
// Finaliser la liste des magasins "actifs" (travaillant le produit : >= 3 mois de vente)
for (const [codein, product] of productMap.entries()) {
const productStores = storeParticipationMap.get(codein);
if (productStores) {
@@ -114,9 +153,7 @@ export async function getProductRows(input: GetProductRowsInput): Promise<Produc
}
}
// DEBUG: Log final product count
console.log(`- Final ProductMap Size: ${productMap.size}`);
return computeProductScores(Array.from(productMap.values()));
} catch (error) {
console.error(`[getProductRows] Error for supplier ${codeFournisseur}:`, error);