mirror of
https://github.com/R0m1k3/CollectFlow.git
synced 2026-10-11 17:26:32 +02:00
feat: introduce AI analysis engine with detailed system prompt and rich contextual product data messaging for recommendations.
This commit is contained in:
1 parent
5773ed9a26
commit
8e07e8c115
2 files changed
+28
-14
No files matched your search
@@ -38,8 +38,10 @@ IMPORTANT : La gamme C est RÉSERVÉE aux produits saisonniers et gérée MANUEL
|
||||
— Quadrant STAR ⭐ : Fort signal positif → A sauf inactivité ≥ 3 mois.
|
||||
— Quadrant TRAFIC 🚶 : Signal positif SEULEMENT si poids QTÉ fournisseur > 1%.
|
||||
Si poids < 1% et score < 40 → Z.
|
||||
— Quadrant MARGE 💎 : Signal positif SEULEMENT si poids CA fournisseur > 0.5%.
|
||||
Si poids < 0.5% et score < 35 → Z.
|
||||
— Quadrant MARGE 💎 : Ce produit contribue par la rentabilité, pas le volume. C'est son rôle attendu.
|
||||
Si percentileMarge >= 70 → A (capital rentabilité du lot, protéger absolument).
|
||||
Si percentileMarge < 70 ET poids CA fournisseur < 0.5% ET score < 35 → Z (marginal ET sous-performant).
|
||||
Sinon → A si actif (inactivité < 3 mois), Z si inactif ≥ 3 mois.
|
||||
— Quadrant WATCH ⚠️ : Signal négatif.
|
||||
Si poids CA rayon > 5% ou poids QTÉ rayon > 5% → A (surveiller).
|
||||
Sinon → Z si inactivité ≥ 2 mois, A si actif.
|
||||
|
||||
@@ -223,33 +223,45 @@ export class ContextProfiler {
|
||||
? Math.round((getWeightedQty(target) / totalQtyFournisseur) * 1000) / 10
|
||||
: 0;
|
||||
|
||||
const isLowContribution = weightCaFournisseur < 0.5 && weightQtyFournisseur < 0.5;
|
||||
// Bug fix : un produit dans le top 30% de marge du lot apporte une valeur
|
||||
// réelle en rentabilité. L'exclure du signal isLowContribution évite de le
|
||||
// pénaliser uniquement parce que son volume/CA est faible (profil 💎 pur).
|
||||
const isLowContribution = weightCaFournisseur < 0.5 && weightQtyFournisseur < 0.5 && pMarge <= 70;
|
||||
|
||||
// 6. Signaux Trafic / Marge + Quadrant (sur valeurs PAR MAGASIN)
|
||||
// Médianes calculées ici pour être disponibles dans les sections 6 ET 7.
|
||||
const medianQtyPerStore = computeMedian(allQtyPerStore);
|
||||
const medianMarge = computeMedian(allMargeValues);
|
||||
|
||||
// 6. Signaux Trafic / Marge (sur valeurs PAR MAGASIN)
|
||||
const rayonSizeForSignals = rayonProds.length;
|
||||
const signalsActive = rayonSizeForSignals >= MIN_RAYON_SIZE;
|
||||
|
||||
let isHighVolumeWithLowMargin = false;
|
||||
let isMargePure = false;
|
||||
|
||||
if (signalsActive) {
|
||||
// Bug fix : isMargePure est désormais calculé sur tous les rayons, même petits.
|
||||
// Raison : la marge absolue est une donnée fiable quelle que soit la taille du lot.
|
||||
// Le signal isHighVolumeWithLowMargin (trafic) garde le seuil MIN_RAYON_SIZE car
|
||||
// il nécessite une distribution volumique suffisante pour être statistiquement valide.
|
||||
{
|
||||
const marge40 = valueAtPercentile(allMargeValues, 40);
|
||||
const marge70 = valueAtPercentile(allMargeValues, 70);
|
||||
const qty60PerStore = valueAtPercentile(allQtyPerStore, 60);
|
||||
const medianQtyPerStore = computeMedian(allQtyPerStore);
|
||||
|
||||
isHighVolumeWithLowMargin =
|
||||
targetQtyPerStore >= qty60PerStore &&
|
||||
(target.tauxMarge ?? 0) < marge40;
|
||||
// Signal trafic : nécessite un rayon suffisamment large
|
||||
if (signalsActive) {
|
||||
isHighVolumeWithLowMargin =
|
||||
targetQtyPerStore >= qty60PerStore &&
|
||||
(target.tauxMarge ?? 0) < marge40;
|
||||
}
|
||||
|
||||
// Signal marge pure : au-dessus de la médiane marge + volume faible.
|
||||
// Utilise la médiane (P50) plutôt que P70 pour être robuste sur petits lots.
|
||||
isMargePure =
|
||||
(target.tauxMarge ?? 0) >= marge70 &&
|
||||
(target.tauxMarge ?? 0) > medianMarge &&
|
||||
targetQtyPerStore < medianQtyPerStore;
|
||||
}
|
||||
|
||||
// 7. Quadrant (basé sur les médianes PAR MAGASIN)
|
||||
const medianQtyPerStore = computeMedian(allQtyPerStore);
|
||||
const medianMarge = computeMedian(allMargeValues);
|
||||
// 7. Quadrant (basé sur les médianes PAR MAGASIN — déjà calculées en section 6)
|
||||
const { quadrant, quadrantLabel, quadrantEmoji } = ContextProfiler.resolveQuadrant(
|
||||
targetQtyPerStore,
|
||||
target.tauxMarge ?? 0,
|
||||
|
||||
Reference in new issue
Block a user