mirror of
https://github.com/R0m1k3/CollectFlow.git
synced 2026-10-12 01:36:43 +02:00
fix: snapshot deletion, restore grid logic and add diagnostic API
This commit is contained in:
1 parent
5eb3f6732e
commit
8237cf2d9f
3 files changed
+83
-30
No files matched your search
@@ -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);
|
||||
|
||||
@@ -7,18 +7,31 @@ import { auth } from "@/lib/auth";
|
||||
|
||||
export async function deleteSnapshot(id: number) {
|
||||
const session = await auth();
|
||||
const userId = session?.user ? Number((session.user as any).id) : null;
|
||||
const rawUserId = (session?.user as any)?.id;
|
||||
const userId = rawUserId ? parseInt(String(rawUserId), 10) : null;
|
||||
|
||||
if (!userId) {
|
||||
console.log(`[deleteSnapshot] Request for ID: ${id}, Session UserId: ${userId} (raw: ${rawUserId})`);
|
||||
|
||||
if (!userId || isNaN(userId)) {
|
||||
console.error("[deleteSnapshot] Unauthorized: userId is missing or invalid");
|
||||
return { success: false, error: "Non autorisé" };
|
||||
}
|
||||
|
||||
try {
|
||||
await db.delete(sessionSnapshots)
|
||||
.where(and(eq(sessionSnapshots.id, id), eq(sessionSnapshots.userId, userId)));
|
||||
const result = await db.delete(sessionSnapshots)
|
||||
.where(and(eq(sessionSnapshots.id, id), eq(sessionSnapshots.userId, userId)))
|
||||
.returning({ deletedId: sessionSnapshots.id });
|
||||
|
||||
if (result.length === 0) {
|
||||
console.warn(`[deleteSnapshot] No rows deleted for ID ${id} and User ${userId}. Maybe the snapshot doesn't belong to the user?`);
|
||||
// We return success: false to trigger the error modal in UI if nothing was actually deleted
|
||||
return { success: false, error: "Élément non trouvé ou non autorisé" };
|
||||
}
|
||||
|
||||
console.log(`[deleteSnapshot] Successfully deleted ID: ${id}`);
|
||||
return { success: true };
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return { success: false, error: "Delete failed" };
|
||||
} catch (err: any) {
|
||||
console.error("[deleteSnapshot] DB Error:", err);
|
||||
return { success: false, error: err.message || "Delete failed" };
|
||||
}
|
||||
}
|
||||
@@ -8,18 +8,21 @@ import { and, desc, eq } from "drizzle-orm";
|
||||
export async function getSnapshots(type?: "snapshot" | "export") {
|
||||
try {
|
||||
const session = await auth();
|
||||
const userId = session?.user ? Number((session.user as any).id) : null;
|
||||
const rawUserId = (session?.user as any)?.id;
|
||||
const userId = rawUserId ? parseInt(String(rawUserId), 10) : null;
|
||||
|
||||
let query = db.select().from(sessionSnapshots);
|
||||
const conditions = [];
|
||||
if (userId) conditions.push(eq(sessionSnapshots.userId, userId));
|
||||
if (type) conditions.push(eq(sessionSnapshots.type, type));
|
||||
|
||||
if (conditions.length > 0) {
|
||||
return query.where(and(...conditions)).orderBy(desc(sessionSnapshots.createdAt));
|
||||
if (!userId || isNaN(userId)) {
|
||||
console.warn("[getSnapshots] Unauthenticated access attempt");
|
||||
return [];
|
||||
}
|
||||
|
||||
return query.orderBy(desc(sessionSnapshots.createdAt));
|
||||
const conditions = [eq(sessionSnapshots.userId, userId)];
|
||||
if (type) conditions.push(eq(sessionSnapshots.type, type));
|
||||
|
||||
return await db.select()
|
||||
.from(sessionSnapshots)
|
||||
.where(and(...conditions))
|
||||
.orderBy(desc(sessionSnapshots.createdAt));
|
||||
} catch (err: any) {
|
||||
const msg = (err?.message || String(err)).split("\n")[0];
|
||||
console.error(`[getSnapshots] ERROR (type=${type}):`, msg, err);
|
||||
|
||||
Reference in new issue
Block a user