mirror of
https://github.com/R0m1k3/CollectFlow.git
synced 2026-10-11 17:26:32 +02:00
feat: implement product grid data fetching with schema self-healing and add a database verification script.
This commit is contained in:
1 parent
08d361e980
commit
1b09994087
5 files changed
+133
-1
No files matched your search
+1
-1
@@ -4,7 +4,7 @@ const nextConfig = {
|
|||||||
serverExternalPackages: ["pg"],
|
serverExternalPackages: ["pg"],
|
||||||
experimental: {
|
experimental: {
|
||||||
serverActions: {
|
serverActions: {
|
||||||
bodySizeLimit: "10mb",
|
bodySizeLimit: "50mb",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
typescript: {
|
typescript: {
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
const { Pool } = require('pg');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
console.log("--- DB DIAGNOSIS Start (Node) ---");
|
||||||
|
|
||||||
|
let connectionString = process.env.DATABASE_URL;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const CONFIG_PATH = path.join(process.cwd(), "data", ".db-config.json");
|
||||||
|
if (fs.existsSync(CONFIG_PATH)) {
|
||||||
|
const config = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
|
||||||
|
if (config.url) {
|
||||||
|
connectionString = config.url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {}
|
||||||
|
|
||||||
|
if (!connectionString) {
|
||||||
|
console.error("No connection string found.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pool = new Pool({ connectionString });
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await pool.query(`
|
||||||
|
SELECT
|
||||||
|
code_fournisseur,
|
||||||
|
nom_fournisseur,
|
||||||
|
COUNT(*) as total_rows,
|
||||||
|
COUNT(DISTINCT codein) as distinct_products
|
||||||
|
FROM ventes_produits
|
||||||
|
GROUP BY code_fournisseur, nom_fournisseur
|
||||||
|
ORDER BY total_rows DESC
|
||||||
|
`);
|
||||||
|
|
||||||
|
console.table(res.rows);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Diagnosis failed:", error);
|
||||||
|
} finally {
|
||||||
|
await pool.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
import { db } from "@/db";
|
||||||
|
import { ventesProduits } from "@/db/schema";
|
||||||
|
import { sql } from "drizzle-orm";
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
console.log("--- DB DIAGNOSIS Start ---");
|
||||||
|
try {
|
||||||
|
const results = await db.execute(sql`
|
||||||
|
SELECT
|
||||||
|
code_fournisseur,
|
||||||
|
nom_fournisseur,
|
||||||
|
COUNT(*) as total_rows,
|
||||||
|
COUNT(DISTINCT codein) as distinct_products
|
||||||
|
FROM ventes_produits
|
||||||
|
GROUP BY code_fournisseur, nom_fournisseur
|
||||||
|
ORDER BY total_rows DESC
|
||||||
|
`);
|
||||||
|
|
||||||
|
console.table(results.rows);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Diagnosis failed:", error);
|
||||||
|
}
|
||||||
|
console.log("--- DB DIAGNOSIS End ---");
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
@@ -5,6 +5,8 @@ import { ventesProduits } from "@/db/schema";
|
|||||||
import { eq, and, ne, like, sql } from "drizzle-orm";
|
import { eq, and, ne, like, sql } from "drizzle-orm";
|
||||||
import type { ProductRow, GammeCode, GridFilters } from "@/types/grid";
|
import type { ProductRow, GammeCode, GridFilters } from "@/types/grid";
|
||||||
import { computeProductScores } from "@/lib/score-engine";
|
import { computeProductScores } from "@/lib/score-engine";
|
||||||
|
import fs from "fs";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
let isSchemaInitialized = false;
|
let isSchemaInitialized = false;
|
||||||
|
|
||||||
@@ -70,6 +72,21 @@ export async function getProductRows(input: GetProductRowsInput): Promise<Produc
|
|||||||
|
|
||||||
// Group by codein and aggregate monthly sales + track store participation
|
// Group by codein and aggregate monthly sales + track store participation
|
||||||
const productMap = new Map<string, ProductRow>();
|
const productMap = new Map<string, ProductRow>();
|
||||||
|
|
||||||
|
// DEBUG: Log counts
|
||||||
|
console.log(`\n--- [getProductRows] DIAGNOSTIC for Supplier ${codeFournisseur} ---`);
|
||||||
|
const rawCount = await db.execute(sql`
|
||||||
|
SELECT COUNT(DISTINCT codein) as count FROM ventes_produits
|
||||||
|
WHERE code_fournisseur = ${codeFournisseur}
|
||||||
|
`);
|
||||||
|
console.log(`- TOTAL DISTINCT codein for this supplier in DB (unfiltered): ${rawCount.rows[0].count}`);
|
||||||
|
|
||||||
|
console.log(`- DB Rows retrieved for current filters: ${rows.length}`);
|
||||||
|
|
||||||
|
// Count distinct products in the DB results
|
||||||
|
const distinctInDb = new Set(rows.map(r => r.codein)).size;
|
||||||
|
console.log(`- Distinct Products in DB results: ${distinctInDb}`);
|
||||||
|
|
||||||
const storeParticipationMap = new Map<string, Map<string, Set<string>>>(); // codein -> magasin -> Set of periods
|
const storeParticipationMap = new Map<string, Map<string, Set<string>>>(); // codein -> magasin -> Set of periods
|
||||||
|
|
||||||
for (const row of rows) {
|
for (const row of rows) {
|
||||||
@@ -164,6 +181,9 @@ 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()));
|
return computeProductScores(Array.from(productMap.values()));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`[getProductRows] Error for supplier ${codeFournisseur}:`, error);
|
console.error(`[getProductRows] Error for supplier ${codeFournisseur}:`, error);
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
const { Pool } = require('pg');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const CONFIG_PATH = path.join(process.cwd(), "data", ".db-config.json");
|
||||||
|
let url = "";
|
||||||
|
if (fs.existsSync(CONFIG_PATH)) {
|
||||||
|
url = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8")).url;
|
||||||
|
}
|
||||||
|
if (!url) url = process.env.DATABASE_URL;
|
||||||
|
|
||||||
|
const pool = new Pool({ connectionString: url });
|
||||||
|
|
||||||
|
async function check() {
|
||||||
|
try {
|
||||||
|
console.log("Checking DB URL:", url.replace(/:([^@]+)@/, ":****@"));
|
||||||
|
|
||||||
|
const resTotal = await pool.query('SELECT COUNT(*) FROM ventes_produits');
|
||||||
|
console.log("Total rows in table:", resTotal.rows[0].count);
|
||||||
|
|
||||||
|
const resSuppliers = await pool.query('SELECT code_fournisseur, COUNT(*) as count FROM ventes_produits GROUP BY code_fournisseur ORDER BY count DESC LIMIT 10');
|
||||||
|
console.log("Top suppliers by row count:", resSuppliers.rows);
|
||||||
|
|
||||||
|
// Check for specific supplier in user screenshot (if any, but I'll check all)
|
||||||
|
for (const s of resSuppliers.rows) {
|
||||||
|
const resDistinct = await pool.query('SELECT COUNT(DISTINCT codein) FROM ventes_produits WHERE code_fournisseur = $1', [s.code_fournisseur]);
|
||||||
|
console.log(`Supplier ${s.code_fournisseur}: Distinct Products = ${resDistinct.rows[0].count}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.error("DB Error:", e);
|
||||||
|
} finally {
|
||||||
|
await pool.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
check();
|
||||||
Reference in new issue
Block a user