From 0226585d4ea6010422934255602dc2e53c27cc64 Mon Sep 17 00:00:00 2001 From: Michael SCHAL Date: Wed, 25 Feb 2026 10:28:18 +0100 Subject: [PATCH] feat: Implement bulk AI product analysis, including prompt generation, insight processing, and a dedicated UI component. --- .../ai-copilot/business/analysis-engine.ts | 4 +++- .../grid/components/bulk-ai-analyzer.tsx | 20 ++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/features/ai-copilot/business/analysis-engine.ts b/src/features/ai-copilot/business/analysis-engine.ts index 21229ea..0a870e2 100644 --- a/src/features/ai-copilot/business/analysis-engine.ts +++ b/src/features/ai-copilot/business/analysis-engine.ts @@ -19,7 +19,9 @@ Le score (0 à 100) est une mesure de performance RELATIVE au sein du rayon. 4. CONCISE : 2 phrases maximum. Pas de blabla technique sur les percentiles, parle de "performance relative". --- FORMAT ATTENDU --- -"[Recommandation] : [Justification factuelle incluant le Score et les axes clés]"`; +"[Recommandation] : [Justification factuelle incluant le Score et les axes clés]" +Exemple : "[A] : Score de 85/100 porté par une marge excellente de 45% et une forte croissance volume." +Exemple : "[Z] : Score faible (12/100) en raison d'une baisse drastique du CA et d'une inactivité de 3 mois."`; } static generateUserMessage(p: ProductAnalysisInput): string { diff --git a/src/features/grid/components/bulk-ai-analyzer.tsx b/src/features/grid/components/bulk-ai-analyzer.tsx index 7f90c5e..6a28ec2 100644 --- a/src/features/grid/components/bulk-ai-analyzer.tsx +++ b/src/features/grid/components/bulk-ai-analyzer.tsx @@ -3,6 +3,7 @@ import React, { useState, useRef } from "react"; import { useGridStore } from "@/features/grid/store/use-grid-store"; import { useAiCopilotStore } from "@/features/ai-copilot/store/use-ai-copilot-store"; +import { ScoringEngine } from "@/features/ai-copilot/business/scoring-engine"; import { Sparkles, Loader2, CheckCircle2, XCircle } from "lucide-react"; import { ProductRow, GammeCode } from "@/types/grid"; import { ProductAnalysisInput } from "@/features/ai-copilot/models/ai-analysis.types"; @@ -55,7 +56,7 @@ export function BulkAiAnalyzer() { } }); - const productPayloads: ProductAnalysisInput[] = rows.map((r) => { + const initialPayloads: ProductAnalysisInput[] = rows.map((r) => { const sc = r.workingStores?.length || 1; const weight = sc === 1 ? 2 : 1; const rb = rayonBenchmarks.get(r.libelleNiveau2 || "Général"); @@ -105,6 +106,23 @@ export function BulkAiAnalyzer() { }; }); + // 2. Calculer le scoring algorithmique pour chaque produit + const productPayloads = initialPayloads.map(p => { + const scoringRes = ScoringEngine.analyzeRayon(p, initialPayloads); + return { + ...p, + scoring: { + compositeScore: scoringRes.compositeScore, + decision: scoringRes.decision.recommendation, + labelProfil: scoringRes.decision.labelProfil, + isTop30Supplier: scoringRes.decision.isTop30Supplier, + isRecent: scoringRes.decision.isRecent, + isLastProduct: scoringRes.decision.isLastProduct, + threshold: scoringRes.decision.threshold, + } + }; + }); + setIsAnalyzing(true); let completed = 0; let errorsCount = 0;