From 32c1e0678285d67b26a4122f6025d6a56263b3fb Mon Sep 17 00:00:00 2001 From: R0m1k3 Date: Thu, 23 Apr 2026 10:32:29 +0200 Subject: [PATCH] feat: implement PostgreSQL-based bulk fetching for article and sales data to replace HTTP API calls --- .claude/settings.local.json | 7 +++++- scripts/check-dashboard-api.js | 7 ++++++ src/lib/pg-ff-client.ts | 42 ++++++++++++++++++---------------- 3 files changed, 35 insertions(+), 21 deletions(-) create mode 100644 scripts/check-dashboard-api.js diff --git a/.claude/settings.local.json b/.claude/settings.local.json index b8f1cb8..6737ae1 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -5,7 +5,12 @@ "Bash(rtk tsc:*)", "Bash(rtk grep:*)", "Bash(node_modules/.bin/tsc --noEmit)", - "Bash(./node_modules/.bin/tsc --noEmit)" + "Bash(./node_modules/.bin/tsc --noEmit)", + "Bash(grep -v \"^$\")", + "Bash(rtk git *)", + "Bash(rtk npx *)", + "Bash(git add *)", + "Bash(git commit *)" ] } } diff --git a/scripts/check-dashboard-api.js b/scripts/check-dashboard-api.js new file mode 100644 index 0000000..a3614ac --- /dev/null +++ b/scripts/check-dashboard-api.js @@ -0,0 +1,7 @@ +const fs = require('fs'); +async function test() { + const res = await fetch("https://api.ffnancy.fr/api/performance/dashboard?date=2024-04-20"); + const data = await res.json(); + console.log(JSON.stringify(data.top10_ca?.[0] || {}, null, 2)); +} +test(); diff --git a/src/lib/pg-ff-client.ts b/src/lib/pg-ff-client.ts index bff6749..62a7f21 100644 --- a/src/lib/pg-ff-client.ts +++ b/src/lib/pg-ff-client.ts @@ -605,25 +605,27 @@ export async function pgGetDashboardData(): Promise { // s'affiche même si la DB n'est pas configurée). let stockMap = new Map(); let fouMap = new Map(); - try { - const [sm, fouResult] = await Promise.all([ - pgGetStockForCodeins(allCodeins), - pgNoParallel(sql` - SELECT - a.codein, - COALESCE(fi.nom, af.code, 'Sans fournisseur')::text AS fournisseur - FROM articles a - LEFT JOIN artfou1 af ON af.art_no_id = a.no_id AND af.preference = 1 - LEFT JOIN fouident fi ON fi.code = af.code - WHERE a.codein = ANY(string_to_array(${allCodeins.join(",")}, ',')) - `), - ]); - stockMap = sm; - for (const row of fouResult.rows as unknown as { codein: string; fournisseur: string }[]) { - if (row.codein) fouMap.set(row.codein, row.fournisseur); + if (allCodeins.length > 0) { + try { + const [sm, fouResult] = await Promise.all([ + pgGetStockForCodeins(allCodeins), + pgNoParallel(sql` + SELECT + a.codein::text AS codein, + COALESCE(fi.nom, af.code, 'Sans fournisseur')::text AS fournisseur + FROM articles a + LEFT JOIN artfou1 af ON af.art_no_id = a.no_id AND af.preference = 1 + LEFT JOIN fouident fi ON fi.code = af.code + WHERE a.codein::text = ANY(string_to_array(${allCodeins.join(",")}, ',')) + `), + ]); + stockMap = sm; + for (const row of fouResult.rows as unknown as { codein: string; fournisseur: string }[]) { + if (row.codein) fouMap.set(row.codein, row.fournisseur); + } + } catch (enrichErr) { + console.warn("[Dashboard] DB enrichment unavailable, continuing with API data only:", enrichErr); } - } catch (enrichErr) { - console.warn("[Dashboard] DB enrichment unavailable, continuing with API data only:", enrichErr); } const siteSet = [...new Set(allItems.map(i => i.site).filter(Boolean))].sort(); @@ -848,10 +850,10 @@ export async function pgGetStockForCodeins(codeins: string[]): Promise