mirror of
https://github.com/R0m1k3/CollectFlow.git
synced 2026-10-11 17:26:32 +02:00
feat(ai): update batch analysis to use global supplier weight (CA/Margin)
This commit is contained in:
1 parent
c89e046dee
commit
0bb73ebcca
2 files changed
+33
-13
No files matched your search
@@ -5,6 +5,8 @@ import { getSavedDatabaseConfig } from "@/features/settings/actions";
|
||||
// Schema for the incoming request
|
||||
const BatchAnalyzeSchema = z.object({
|
||||
rayon: z.string(),
|
||||
supplierTotalCa: z.number().optional(),
|
||||
supplierTotalMarge: z.number().optional(),
|
||||
products: z.array(z.object({
|
||||
codein: z.string(),
|
||||
nom: z.string().nullable().optional(),
|
||||
@@ -37,28 +39,38 @@ export async function POST(req: NextRequest) {
|
||||
return NextResponse.json({ error: "Format de données invalide." }, { status: 400 });
|
||||
}
|
||||
|
||||
const { rayon, products } = parsed.data;
|
||||
const { rayon, products, supplierTotalCa, supplierTotalMarge } = parsed.data;
|
||||
|
||||
// Context-Aware System Prompt: Relative weighting within the batch
|
||||
const systemPrompt = `Tu es un expert en stratégie d'achat retail. Ton rôle est de catégoriser les produits d'un fournisseur (A=Permanent, C=Saisonnier, Z=Sortie) en analysant leur POIDS RELATIF dans le lot fourni.
|
||||
const supplierMetricsContext = supplierTotalCa && supplierTotalMarge
|
||||
? `CONTEXTE FOURNISSEUR TOTAL :
|
||||
- CA Total Fournisseur : ${supplierTotalCa.toLocaleString('fr-FR')} €
|
||||
- Marge Totale Fournisseur : ${supplierTotalMarge.toLocaleString('fr-FR')} €
|
||||
|
||||
L'IMPORTANCE RELATIVE AU SEIN DU LOT PRIME SUR LE SCORE DE PERFORMANCE.
|
||||
Toute analyse de poids doit se faire par rapport à ce TOTAL FOURNISSEUR global, et non uniquement par rapport au lot envoyé.`
|
||||
: "CONTEXTE : Analyse par rapport au lot fourni.";
|
||||
|
||||
// Context-Aware System Prompt: Relative weighting relative to supplier totals
|
||||
const systemPrompt = `Tu es un expert en stratégie d'achat retail. Ton rôle est de catégoriser les produits d'un fournisseur (A=Permanent, C=Saisonnier, Z=Sortie) en analysant leur POIDS RÉEL dans le business global du fournisseur.
|
||||
|
||||
${supplierMetricsContext}
|
||||
|
||||
L'IMPORTANCE STRATÉGIQUE (POIDS CA/MARGE FOURNISSEUR) PRIME SUR LE SCORE DE PERFORMANCE.
|
||||
|
||||
MÉTHODOLOGIE D'ANALYSE :
|
||||
1. ANALYSE DU LOT : Identifie les produits qui portent le business du fournisseur (Top contributeurs en CA et Marge au sein de ce groupe).
|
||||
2. RÈGLE D'OR (PROTECTION DES PILIERS) : Un produit avec une contribution significative (ex: dans les 20% supérieurs du lot en CA ou Marge) est stratégique (Gamme A). Son Score faible indique un besoin d'optimisation, PAS une sortie (Z).
|
||||
1. ANALYSE DU POIDS : Calcule la contribution de chaque produit par rapport au chiffre d'affaires et à la marge globale du fournisseur.
|
||||
2. RÈGLE D'OR (PROTECTION DES PILIERS) : Un produit qui représente une part significative du business fournisseur (ex: > 1% du CA total ou contributeur majeur à la marge) est stratégique (Gamme A). Son Score faible indique un besoin d'optimisation, PAS une sortie (Z).
|
||||
3. HIÉRARCHIE DÉCISIONNELLE :
|
||||
a. Poids relatif dans le lot (CA/Marge %) -> Priorité 1
|
||||
a. Poids relatif dans le business fournisseur (CA/Marge %) -> Priorité 1
|
||||
b. Régularité des ventes (sales12m) -> Priorité 2
|
||||
c. Performance relative (Score 0-100) -> Priorité 3 (Simple indicateur de santé).
|
||||
c. Performance relative (Score 0-100) -> Priorité 3 (Indicateur de santé opérationnelle).
|
||||
|
||||
DÉFINITION DES GAMMES :
|
||||
- A (Permanent) : Produit "pilier" par son poids relatif OU sa rotation régulière.
|
||||
- A (Permanent) : Produit "pilier" par son poids global OU sa rotation régulière.
|
||||
- C (Saisonnier) : Pics de ventes saisonniers clairs.
|
||||
- Z (Sortie) : Cumul de : poids insignifiant dans le lot + marge faible + score médiocre + ventes sporadiques.
|
||||
- Z (Sortie) : Cumul de : poids insignifiant chez le fournisseur + marge faible + score médiocre + ventes sporadiques.
|
||||
|
||||
IMPORTANT : RÉPONDS UNIQUEMENT EN JSON VALIDE.
|
||||
La justification doit obligatoirement situer le produit par rapport au reste du lot (ex: "Top 10% du CA du lot"). Ne donne aucun seuil en euros.
|
||||
La justification doit impérativement situer le produit par rapport au business global du fournisseur (ex: "Représente X% du CA total fournisseur, pilier stratégique"). Ne donne aucun seuil en euros.
|
||||
|
||||
Format:
|
||||
{
|
||||
|
||||
@@ -14,7 +14,10 @@ export function BulkAiAnalyzer() {
|
||||
|
||||
const handleAnalyze = async () => {
|
||||
const { rows } = useGridStore.getState();
|
||||
console.log("[BulkAiAnalyzer] Starting analysis on", rows.length, "rows");
|
||||
const supplierTotalCa = rows.reduce((acc, row) => acc + (row.totalCa || 0), 0);
|
||||
const supplierTotalMarge = rows.reduce((acc, row) => acc + (row.totalMarge || 0), 0);
|
||||
|
||||
console.log("[BulkAiAnalyzer] Starting analysis on", rows.length, "rows", { supplierTotalCa, supplierTotalMarge });
|
||||
|
||||
setIsAnalyzing(true);
|
||||
let completed = 0;
|
||||
@@ -67,7 +70,12 @@ export function BulkAiAnalyzer() {
|
||||
res = await fetch("/api/ai/batch-analyze", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ rayon: chunk.rayon, products: payloadProducts })
|
||||
body: JSON.stringify({
|
||||
rayon: chunk.rayon,
|
||||
products: payloadProducts,
|
||||
supplierTotalCa,
|
||||
supplierTotalMarge
|
||||
})
|
||||
});
|
||||
|
||||
if (res.status === 429 && attempt < MAX_CHUNK_RETRIES) {
|
||||
|
||||
Reference in new issue
Block a user