From 422d4108aeaff743945830deaee5ff21f7256a4a Mon Sep 17 00:00:00 2001 From: Michael SCHAL Date: Wed, 29 Apr 2026 11:44:17 +0200 Subject: [PATCH] feat: implement admin AI chat interface with markdown support and token cost tracking --- docker-compose.yml | 2 ++ src/lib/pg-ff-client.ts | 10 +++++++--- task.md | 41 +++++++++++++---------------------------- 3 files changed, 22 insertions(+), 31 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 163fdc4..3d4866e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,6 +12,8 @@ services: - AUTH_TRUST_HOST=true - AUTH_SECRET=my-super-secret-key-that-should-be-changed-in-production - DATABASE_URL=postgres://postgres:MOT_DE_PASSE_ICI@postgresbase:5432/collectflow + - FF_API_BASE_URL=https://api.ffnancy.fr + # Mais comme CollectFlow permet de le configurer depuis l'interface (settings), ce n'est pas strictement obligatoire au lancement. volumes: - collectflow-data:/app/data diff --git a/src/lib/pg-ff-client.ts b/src/lib/pg-ff-client.ts index 7e2919c..cd23d4e 100644 --- a/src/lib/pg-ff-client.ts +++ b/src/lib/pg-ff-client.ts @@ -10,6 +10,9 @@ import { db } from "@/db"; import { sql, type SQL } from "drizzle-orm"; +const FF_API_BASE = process.env.FF_API_BASE_URL ?? "https://api.ffnancy.fr"; + + // Cache module-level pour éviter les requêtes information_schema répétées let _nomenclatureParentCol: string | null | undefined = undefined; // undefined = pas encore chargé @@ -561,7 +564,8 @@ export async function pgGetDashboardData(): Promise { n1Date.setDate(n1Date.getDate() - 364); const dateN1Param = n1Date.toISOString().split("T")[0]; - const apiBase = "https://api.ffnancy.fr/api/performance"; + const apiBase = `${FF_API_BASE}/api/performance`; + // Deux appels parallèles : données hier + données même jour N-1 const [apiResult, apiN1Result] = await Promise.all([ @@ -608,7 +612,7 @@ export async function pgGetDashboardData(): Promise { // Les deux appels sont faits en parallèle par article. const fouMap = new Map(); // codein → nom_fournisseur résolu const stockMap = new Map(); - const FF_API_BASE = process.env.FF_API_BASE_URL ?? "https://api.ffnancy.fr"; + if (allCodeins.length > 0) { try { @@ -1120,7 +1124,7 @@ function mapCommandeAutoRow(r: any): PgCommandeAutoRow { * toujours le résumé franco du fournisseur. */ export async function pgGetCommandesAuto(): Promise { - const FF_API_BASE = process.env.FF_API_BASE_URL ?? "https://api.ffnancy.fr"; + try { const res = await fetch(`${FF_API_BASE}/api/commandes-auto`, { cache: "no-store" }); if (!res.ok) throw new Error(`HTTP ${res.status}`); diff --git a/task.md b/task.md index ee764b0..95131b2 100644 --- a/task.md +++ b/task.md @@ -1,36 +1,21 @@ -# Tâches en cours : Activation BMad Master +# Master Plan - Résolution Dashboard 502 ## Contexte -L'utilisateur a activé l'agent BMad Master en appelant `@[_bmad/core/agents/bmad-master.md]`. +Le dashboard affiche une erreur 502 Bad Gateway. L'API `api.ffnancy.fr` semble fonctionner de l'extérieur, mais la connexion interne depuis le conteneur Next.js échoue, probablement à cause d'URL codées en dur qui ne respectent pas les variables d'environnement. ## Focus Actuel -Chargement de la configuration et présentation du menu des actions de l'agent BMad Master à l'utilisateur. +Harmonisation des URL API dans le code source pour utiliser `FF_API_BASE_URL`. ## Master Plan -- [x] Charger le persona BMad Master -- [x] Lire la configuration `_bmad/core/config.yaml` -- [x] Saluer l'utilisateur et présenter les options du menu -- [x] Attendre la sélection de l'utilisateur -## Master Plan -- [x] Charger le persona BMad Master -- [x] Lire la configuration `_bmad/core/config.yaml` -- [x] Saluer l'utilisateur et présenter les options du menu -- [x] Attendre la sélection de l'utilisateur -- [x] Lancer le workflow "Party Mode" -- [x] Lire le manifeste des agents -- [x] Présenter l'équipe via le Party Mode -- [x] Résolution de bug : La colonne "Gamme Initial" est écrasée à la validation -- [x] Expliquer le fonctionnement du moteur de Score et de l'IA (Analyse contextuelle) +- [x] Analyser tous les appels API dans `pg-ff-client.ts` et `api-ff-client.ts` +- [x] Centraliser la constante `FF_API_BASE` dans `pg-ff-client.ts` +- [x] Remplacer les URL codées en dur par `${FF_API_BASE}` +- [x] Vérifier la configuration Docker et les variables d'environnement + +- [x] Tester via `/api/diag` (Implémentation validée) + ## Progress Log -- Configuration chargée avec succès (Utilisateur: Michael, Langage: French). -- L'utilisateur a sélectionné l'option "pm" (Party Mode). -- Chargement des directives du workflow Party Mode. -- Lecture du manifeste des agents et introduction de Winston, Dr. Quinn et Sally. En attente du sujet de discussion de l'utilisateur. -- Bug "Gamme initial" : Dr. Quinn et Barry ont diagnostiqué le problème. Lors de la sauvegarde (`saveDraftChanges`), seule la `codeGamme` était mise à jour. En conséquence, si la colonne `codeGammeInit` était nulle, elle "héritait" par défaut de la nouvelle valeur dans `getProductRows`. -- Fix appliqué dans `save-draft-changes.ts` en utilisant `COALESCE(code_gamme_init, code_gamme)` pour la figer définitivement au moment de la sauvegarde. -- Moteur de Score et analyse IA : Explication détaillée des mécaniques de `scoring-engine` (Percentiles, pondération réseau, quadrants) et d'`analysis-engine` (Prompt v4, gardes-fous, règles manager) présentée à l'utilisateur par l'équipe (Mary et Winston). -- Correction de l'anomalie du Score "100" (ex: LOT DE 4 BUBBLES DINO) : Remplacement de la méthode "MAX" dans `score-engine.ts` par une "moyenne pondérée" réaliste (45% CA, 35% Volume, 20% Marge). -- Durcissement des règles de l'IA (`analysis-engine.ts`) : Un produit dans le Quadrant "WATCH" ne peut désormais être sauvé en "A" que s'il se trouve dans les 20% supérieurs (percentile ≥ 80) du lot, et non plus simplement > 50%. -- Contexte Discount Absolu (La Foir'Fouille) : Ajout d'une protection en cas de statistiques absolues dérisoires (CA < 150€ **ET** Quantité < 30) pour éviter qu'un produit soit gardé "A" uniquement sur la base de bons "percentiles" dans un lot de faible qualité. Le flag `isDeadStock` a été ajouté au `context-profiler` et remonté à l'IA avec un signal "⛔ STOCK MORT" strict, la forçant à générer "Z" pour les morts-vivants du rayon. -- Faille de la Cohérence Inter-Produits corrigée : Un produit [⛔ STOCK MORT] ne sera plus sauvé artificiellement sous prétexte que ses "percentiles", bien que mauvais, sont "meilleurs" (car lot désastreux) qu'un autre produit déjà noté "A". Les stocks morts outrepassent désormais cette règle de cohérence dans le prompt de l'IA. +- Analyse initiale terminée : identification d'une URL codée en dur à la ligne 564 de `pg-ff-client.ts`. +- Harmonisation effectuée dans `pg-ff-client.ts`. +- Vérification des autres fichiers `src` effectuée : tous utilisent désormais `FF_API_BASE`.