Calcul décrit au 8 septembre 2026. Les exemples sont fictifs. Les formules, coefficients et limites présentés ont été relevés dans le code d’AuditStock à cette date.
Une commande fournisseur engage de la place, du temps de gestion et de la trésorerie. Avant d’acheter, la question est simple : ce produit répond-il à une demande suffisamment solide pour éviter de rester longtemps dans l’entrepôt ?
Pour éclairer cette décision, AuditStock attribue au produit un indice de risque compris entre 0 et 100, affiché avec un signe %. Le calcul examine les commandes clients, la diversité des acheteurs, les stocks, les commandes fournisseurs ouvertes, les prix, les anomalies et la durée de rotation.
La colonne « % Risque », encadrée en rouge, permet de repérer le niveau de risque de chaque produit. Le détail du calcul aide ensuite à comprendre les raisons de ce score.
Dans cet article, je déroule chaque étape du calcul, puis je montre comment lire le résultat avant un réapprovisionnement. L’objectif est de comprendre autant le chiffre que les raisons qui le font monter ou descendre.
1. Ce que signifie réellement le pourcentage
Plus le score est faible, plus les signaux retenus par le modèle sont favorables. Plus il est élevé, plus le produit mérite une analyse avant de le réapprovisionner.
Le composant d’affichage utilise les seuils suivants :
| Score affiché | Couleur | Lecture du niveau de risque |
|---|---|---|
| 0 à 25 inclus | Vert | Faible |
| Plus de 25 à 50 inclus | Bleu | Modéré |
| Plus de 50 à 75 inclus | Orange | Moyen, avec une vigilance renforcée |
| Plus de 75 à 100 | Rouge | Élevé |
Ces couleurs facilitent le repérage. Elles ne constituent pas des règles automatiques d’achat ou d’interdiction de commande.
Un score de 70 % ne signifie pas que 70 % des unités resteront invendues, ni qu’il existe une probabilité statistiquement démontrée de 70 % de dépasser une durée de stockage donnée. Le résultat est un score composite, construit avec des règles de pondération. Le calcul ne définit pas un événement comme « encore en stock dans 90 jours » et ne mesure pas sa probabilité sur des résultats observés.
Le périmètre est également plus large que le seul surstock : une rupture ou des délais d’approvisionnement défavorables peuvent augmenter le score. Pour comprendre un risque de stockage prolongé, il faut donc lire particulièrement la demande, la couverture, le surstock et la rotation, puis replacer les autres composantes dans leur contexte.
2. Un indice du produit, tous entrepôts et fournisseurs confondus
Le calcul reçoit un identifiant de produit. Il ne reçoit ni un fournisseur sélectionné, ni une quantité envisagée, ni une date de livraison future.
Il agrège les stocks des entrepôts associés au produit et exploite les historiques fournisseurs de ce même produit. Le score est donc une lecture globale de la référence à la date du calcul.
Cela a trois conséquences pratiques :
- Le score affiché pour un produit chez un fournisseur ne devient pas un score spécifique à ce fournisseur.
- Un entrepôt très chargé peut compenser, dans les sommes utilisées, un autre entrepôt en tension.
- Une quantité seulement envisagée n’entre pas dans le calcul. Les lignes de commande fournisseur déjà enregistrées et non soldées peuvent, elles, alimenter le stock provisionné.
flowchart LR
V["Commandes clients du produit"] --> C["Calcul global du produit"]
E["Stocks de tous ses entrepôts"] --> C
O["Commandes fournisseurs ouvertes"] --> C
R["Réceptions et délais du produit"] --> C
Q["Prix, anomalies et rotation"] --> C
C --> S["Indice de 0 à 100"]
C --> X["Explication détaillée"]
S --> A["Analyse de la prochaine commande"]
X --> A
H["Quantité envisagée et date de réception"] -. "À examiner en complément" .-> A3. Quelles données sont utilisées ?
Les fenêtres temporelles sont calculées à partir de la date du traitement.
| Donnée | Période ou périmètre retenu | Utilité |
|---|---|---|
| Lignes de commandes clients | Deux dernières années, selon la date de création de la commande | Quantités, prix de vente et commandes multiproduits |
| Ventes récentes | 30 jours et 180 jours | Accélération ou ralentissement récent |
| Clients distincts | Six derniers mois | Largeur de la clientèle |
| Présence d’un historique d’achat | Ligne fournisseur créée dans les 24 derniers mois | Contrôle préalable |
| Prix d’achat positifs | Deux dernières années, selon la création de la ligne fournisseur | Variabilité des prix |
| Stocks physiques, minima et points de commande | État courant de tous les entrepôts du produit | Disponibilité et surstock |
| Commandes fournisseurs non soldées | Sans limite d’ancienneté dans cette requête | Quantités provisionnées |
| Lignes clients non équilibrées | Sans limite d’ancienneté dans cette requête | Quantités réservées |
| Anomalies de stock | Six derniers mois | Qualité opérationnelle |
| Commandes fournisseurs distinctes | Lignes créées dans les six derniers mois | Dénominateur du ratio d’anomalies |
| Délais des réceptions fournisseurs | Deux dernières années | Délai moyen et irrégularité |
| Rotation du produit | Valeur enregistrée sur la fiche | Durée de séjour observée ; couverture utilisée en repli |
| Âge du produit | Depuis sa date de création | Maturité de l’historique |
Dans ce calcul, le mot « ventes » désigne les quantités des lignes de commandes clients sélectionnées. La requête ne filtre pas les commandes selon leur état de livraison ou de facturation. Il ne faut donc pas assimiler systématiquement cette base à des sorties physiques déjà réalisées.
La moyenne journalière est recalculée à partir de ces lignes. Elle ne reprend pas directement le champ de demande moyenne affiché ailleurs sur la fiche produit. Deux indicateurs voisins peuvent ainsi utiliser des bases différentes.
4. Les contrôles qui précèdent le calcul
Le traitement vérifie d’abord que l’état d’import autorise le calcul. Il recherche ensuite le produit et ne poursuit que pour un produit de type matériel, Material.
Un produit absent génère une erreur « Produit introuvable ». Un état d’import incompatible ou un autre type de produit entraîne une sortie sans nouveau calcul.
Deux situations imposent directement un risque de 100 :
- Aucun entrepôt associé au produit. AuditStock enregistre l’explication « Le produit n’est présent dans aucun entrepôt ».
- Aucune ligne de commande fournisseur créée dans les 24 derniers mois. La chaîne s’arrête sur l’absence d’historique d’achat.
Une commande fournisseur n’a pas besoin d’être réceptionnée pour satisfaire ce second contrôle : l’implémentation vérifie l’existence d’une ligne, sans imposer un état particulier à la commande.
Ces 100 points expriment une règle de prudence du modèle. Ils ne prouvent pas qu’un nouveau produit ne se vendra jamais. Un lancement sans historique doit être examiné avec ses prévisions et ses engagements clients.
flowchart TD
A["Demande de recalcul"] --> B{"Import autorisé et produit matériel ?"}
B -- Non --> Z["Pas de nouveau score"]
B -- Oui --> C{"Au moins un entrepôt associé ?"}
C -- Non --> R["Score 100 et explication"]
C -- Oui --> D{"Une ligne fournisseur sur 24 mois ?"}
D -- Non --> R
D -- Oui --> E["Demande"]
E --> F["Tendance hebdomadaire"]
F --> G["Disponibilité et surstock"]
G --> H["Attractivité"]
H --> I["Qualité du stock"]
I --> J["Risque structurel"]
J --> K["Bonus finaux"]
K --> L["Enregistrement du score et du détail"]Le schéma représente le parcours normal après recherche du produit. À chaque ajout de contribution, si le cumul atteint 100, le traitement s’interrompt : les étapes suivantes, y compris les bonus finaux, ne sont plus exécutées.
5. Première composante : existe-t-il une demande ?
5.1. La consommation moyenne sur deux ans
Le calcul commence par additionner les quantités commandées par les clients pendant les deux dernières années, puis divise ce total par le nombre de jours calendaires de cette fenêtre.
d = total des quantités clients sur deux ans / nombre de jours de la fenêtre
La période correspond à deux années calendaires, soit généralement 730 ou 731 jours. Elle n’est pas raccourcie à l’âge du produit. Un produit créé depuis trois mois est donc encore rapporté à la fenêtre complète, ce qui rend sa moyenne plus faible qu’une moyenne calculée uniquement depuis son lancement.
5.2. La tendance récente : 30 jours contre 180 jours
AuditStock compare les deux moyennes suivantes :
d30 = quantités des 30 derniers jours / 30
d180 = quantités des 180 derniers jours / 180
Si d180 <= 0 : T = 1
Sinon : T = borne(d30 / d180 ; 0,6 ; 1,4)
Dans les formules de cet article, borne(x ; minimum ; maximum) ramène une valeur dans l’intervalle indiqué.
Une accélération augmente le facteur de demande jusqu’à 1,4. Un ralentissement le réduit jusqu’à 0,6. Cette borne évite qu’un mois exceptionnel amplifie ou écrase totalement l’historique long. Les 30 derniers jours font partie des 180 derniers jours : les fenêtres se recouvrent.
5.3. Transformer l’intensité en signal de demande
lambda = max(d × T ; 0,0001)
Pbase = 1 - exp(-lambda)
La forme 1 - exp(-lambda) est celle utilisée pour la probabilité d’au moins un événement dans un modèle de Poisson. Ici, l’intensité est construite à partir des quantités commandées par jour. Elle sert de signal de demande ; elle n’établit pas une probabilité validée d’écoulement d’un lot entier.
À tendance neutre, avant correction par la clientèle :
| Quantité moyenne par jour | Signal de base approximatif |
|---|---|
| 0,1 | 9,5 % |
| 0,5 | 39,3 % |
| 1 | 63,2 % |
| 2 | 86,5 % |
| 5 | 99,3 % |
Cette transformation sature rapidement pour les produits vendus en grandes quantités. L’unité dans laquelle la quantité est exprimée compte donc dans la lecture du résultat.
5.4. La diversité des clients
Le seuil de clientèle H est configurable avec CustomerThreshold. Sa valeur par défaut est 5 ; la valeur d’une installation donnée peut être différente.
C = nombre de codes clients distincts sur six mois
Si H <= 0 : ratioClients = 1
Sinon : ratioClients = borne(C / H ; 0 ; 2)
MultiplicateurClients = 0,5 + 0,7 × ratioClients
Pdemande = borne(Pbase × MultiplicateurClients ; 0,01 ; 1)
Rdemande = arrondi à une décimale de [100 × (1 - Pdemande)]
Avec le seuil par défaut :
| Clients distincts sur six mois | Ratio | Multiplicateur |
|---|---|---|
| 0 | 0 | 0,5 |
| 1 | 0,2 | 0,64 |
| 5 | 1 | 1,2 |
| 10 ou plus | 2 | 1,9 |
L’idée métier est qu’un produit acheté par plusieurs clients dépend moins d’un acheteur unique. Le calcul compte les codes distincts ; il ne mesure pas la part de volume réalisée par le premier client. Dix clients dont un représente presque toutes les quantités restent dix clients pour cette composante.
6. Deuxième lecture de la demande : la tendance hebdomadaire
En complément du ratio 30/180 jours, une étape examine la pente des quantités hebdomadaires sur l’historique de deux ans.
Les semaines sont définies par tranches de sept jours à partir du début de la fenêtre. Pour chaque semaine représentée, le calcul additionne les quantités, puis applique une régression linéaire :
x = numéro de semaine depuis le début de la fenêtre
y = quantité commandée pendant cette semaine
n = nombre de semaines représentées
pente = [n × somme(x × y) - somme(x) × somme(y)]
/ [n × somme(x²) - somme(x)²]
penteNormalisée = borne(pente / (7 × d) ; -1 ; 1)
ajustement = 10 × penteNormalisée
Le traitement exige une moyenne journalière positive et au moins quatre semaines représentées. Les semaines sans ligne de commande ne sont pas ajoutées avec une quantité nulle. Une période totalement silencieuse n’apparaît donc pas automatiquement comme une série de zéros dans cette régression.
- Si la pente est négative, la valeur absolue de l’ajustement est arrondie à l’entier supérieur et ajoutée au risque : au maximum 10 points.
- Si la pente est positive, l’ajustement est arrondi à l’entier inférieur et soustrait : au maximum 10 points.
- Si la pente est nulle, il n’y a pas d’ajustement.
Ce bonus ou malus intervient juste après la contribution de demande. Une hausse ne peut pas rendre le cumul négatif : si le cumul vaut 2 et le bonus théorique 6, seulement 2 points sont effectivement retirés. Les 4 points restants ne sont pas reportés sur les étapes suivantes.
7. Troisième composante : combien de stock faut-il écouler ?
7.1. Le stock net retenu par le modèle
La relation utilisée est :
N = stock physique total + provisionné - réservé
Le provisionné provient des lignes fournisseurs dont la date de solde est absente, en additionnant Quantity - ReceivedQuantity. Le réservé provient des lignes clients non équilibrées, en additionnant Quantity.
Deux précisions sont nécessaires pour comprendre la donnée :
- La réservation retient la quantité de la ligne ouverte, sans soustraire ici une quantité déjà livrée.
- Le provisionné est intégré sans calendrier de réception. Une quantité à recevoir plus tard contribue au stock net du modèle dès lors que sa ligne répond au filtre.
Ce stock net est donc une position calculée d’approvisionnement, qui peut inclure du stock non encore présent physiquement. La cohérence des unités entre physique, provisionné et réservé reste un point technique à vérifier sur les agrégations en base de données ; les exemples complets ci-dessous utilisent un provisionné et un réservé nuls.
7.2. Le nombre de jours de couverture
Couverture = N / max(d ; 0,01)
Par exemple, si les entrées du calcul sont 100 unités physiques, 30 provisionnées, 20 réservées et une demande de 5 unités par jour :
N = 100 + 30 - 20 = 110
Couverture = 110 / 5 = 22 jours
La couverture utilise la moyenne sur deux ans sans appliquer le facteur de tendance récent. Elle peut être négative si les réservations dépassent le physique et le provisionné.
Le plancher de 0,01 évite une division par zéro. Il ne constitue pas une prévision minimale de vente. Un produit sans demande observée peut ainsi afficher une couverture numérique très élevée, qui ne doit pas être interprétée comme une date certaine d’écoulement.
7.3. L’état de disponibilité
Les conditions sont testées dans cet ordre :
| Condition | Valeur d’état E |
|---|---|
Stock net N <= 0 |
0,05 |
| Sinon, minimum total positif et physique inférieur à ce minimum | 0,35 |
| Sinon, point de commande total positif et physique inférieur à ce point | 0,60 |
| Sinon | 1 |
La rupture est évaluée sur le net ; les comparaisons au minimum et au point de commande utilisent le physique. Cette distinction explique qu’une livraison attendue puisse améliorer le résultat sans effacer toute la pénalité liée au stock physique insuffisant.
La composante couverture vaut :
Pcouverture = borne(Couverture / 30 ; 0 ; 1)
Elle atteint son plafond à 30 jours. Le surplus de couverture est ensuite examiné par une pénalité spécifique.
8. Le surstock : le signal le plus directement lié à l’immobilisation
AuditStock combine trois dépassements : la couverture en jours, le stock net par rapport au minimum et le stock net par rapport au point de commande.
Notons M la somme des stocks minima et P la somme des points de commande :
rJours = borne((Couverture - 45) / 135 ; 0 ; 1)
Si M > 0 :
rMini = borne((N - M) / max(M ; 0,01) ; 0 ; 3) / 3
Sinon : rMini = 0
Si P > 0 :
rCommande = borne((N - P) / max(P ; 0,01) ; 0 ; 3) / 3
Sinon : rCommande = 0
PénalitéSurstock = borne(
0,60 × rJours + 0,25 × rMini + 0,15 × rCommande ;
0 ; 0,70)
Rsurstock = arrondi à une décimale de (100 × PénalitéSurstock)
Ce que veulent dire les seuils
La composante liée aux jours commence à augmenter au-delà de 45 jours et atteint son maximum à 180 jours, puisque 45 + 135 = 180.
Cela ne signifie pas qu’aucune pénalité n’existe avant 45 jours. Les dépassements du minimum ou du point de commande peuvent déjà en produire une.
Pour les deux autres ratios, le maximum est atteint quand le net vaut quatre fois le seuil : (4 × seuil - seuil) / seuil = 3. Le calcul ne compare pas le stock à un stock maximum configuré.
La pénalité totale est plafonnée à 0,70, soit un risque de surstock maximal de 70 pour cette sous-composante.
Comment la pénalité agit sur la disponibilité
Pdisponibilité = borne(
(0,70 × E + 0,30 × Pcouverture) × (1 - PénalitéSurstock) ;
0,01 ; 0,99)
Rstock = arrondi à une décimale de [100 × (1 - Pdisponibilité)]
Le surstock agit donc par deux chemins : il dégrade la disponibilité calculée et ajoute un risque structurel dédié. Le nom « disponibilité » recouvre ici davantage que la présence physique : il intègre aussi l’excès de stock.
flowchart TD
A["Physique + provisionné - réservé"] --> B["Stock net"]
B --> C["Couverture en jours"]
D["Demande moyenne sur deux ans"] --> C
C --> E["Excès au-delà de 45 jours"]
B --> F["Dépassement du minimum"]
B --> G["Dépassement du point de commande"]
E --> H["Pénalité de surstock plafonnée à 70 %"]
F --> H
G --> H
H --> I["Dégradation de la disponibilité"]
H --> J["Risque structurel de surstock"]
I --> K["Contribution au score"]
J --> K9. L’attractivité : stabilité des prix et ventes associées
9.1. La variabilité des prix
AuditStock extrait les prix de vente et d’achat strictement positifs, puis calcule pour chaque série un coefficient de variation :
CV = borne(écart-type / moyenne ; 0 ; 2)
L’écart-type utilise une variance divisée par le nombre de valeurs, sans correction d’échantillon. Avec moins de deux valeurs, le coefficient vaut zéro. Il vaut également zéro si la moyenne est non positive.
Les prix sont observés par ligne ; ils ne sont pas pondérés par les quantités. Une stabilité apparente issue d’un historique très court n’est donc pas une preuve de stabilité commerciale durable.
PénalitéPrix = borne((CVvente + CVachat) / 2 ; 0 ; 0,70)
StabilitéPrix = 1 - PénalitéPrix
Rprix = borne(50 × (CVvente + CVachat) ; 0 ; 100)
Cette composante mesure la variabilité, pas la compétitivité face aux concurrents. Un prix stable peut être trop élevé ; le modèle ne le détecte pas par une comparaison au marché.
9.2. La présence dans les commandes multiproduits
X = nombre de commandes distinctes contenant le produit
et plus d’une référence distincte
/ nombre de commandes distinctes contenant le produit
Sans commande, le ratio vaut zéro. Le nombre de références est celui enregistré sur la commande.
Pattractivité = borne(StabilitéPrix × (0,70 + 0,30 × X) ; 0,01 ; 0,99)
RventesAssociées = borne(100 × (1 - X) ; 0 ; 100)
Le modèle valorise ainsi les références souvent présentes dans des paniers multiproduits. Il ne démontre pas qu’un autre produit provoque leur vente.
10. La qualité du stock : le poids des anomalies
Cette étape compare les anomalies du produit à un nombre de commandes utilisé comme approximation de l’activité :
Activité = max(
commandes clients distinctes sur deux ans
+ commandes fournisseurs distinctes sur six mois ;
1)
RatioAnomalies = borne(anomalies sur six mois / Activité ; 0 ; 1)
Pqualité = borne(1 - 0,80 × RatioAnomalies ; 0,01 ; 0,99)
Ranomalies = borne(100 × RatioAnomalies ; 0 ; 100)
L’explication générée appelle le dénominateur « mouvements ». Il s’agit ici de commandes distinctes, avec des fenêtres différentes côté clients et fournisseurs, et non d’un décompte homogène de tous les mouvements physiques sur six mois.
Sans anomalie, Pqualité vaut 0,99 en raison du plafond opérationnel. Le modèle conserve ainsi une petite contribution résiduelle.
11. Les risques structurels : ce qui fragilise le produit dans la durée
11.1. Délai et irrégularité de l’approvisionnement
Le délai retenu est le plus grand entre :
- le maximum des délais moyens enregistrés sur les associations produit-entrepôt ;
- la moyenne des durées de réception du produit sur deux ans.
L = max(délai entrepôt maximal ; délai moyen des réceptions)
S = écart-type des durées de réception
Rfournisseur = borne(70 × L / 45 + 30 × S / 30 ; 0 ; 100)
À titre d’exemple, 30 jours de délai retenu avec un écart-type nul produisent environ 46,7 de risque fournisseur. Un délai de 45 jours et un écart-type de 30 jours produisent 100.
Les observations concernent le produit, sans filtre sur le fournisseur d’une prochaine commande. En l’absence de réceptions, la moyenne et l’écart-type observés valent zéro ; une éventuelle valeur entrepôt reste prise en compte.
11.2. La couverture de clientèle
Le ratio clients déjà calculé est réutilisé :
Rclients = borne(100 - 50 × ratioClients ; 0 ; 100)
Avec le seuil par défaut, cinq clients donnent un risque de clientèle de 50 et dix clients ou plus le ramènent à zéro. La clientèle joue donc à la fois dans la demande et dans la structure du risque.
11.3. La durée de rotation
Si StockTurnoverDurationInDays est strictement positif, le modèle utilise cette valeur. Sinon, il retient la couverture calculée, ramenée au minimum à zéro.
Dans le calcul de KPI examiné, la valeur produit est alimentée par la moyenne de DayCountInStock des éléments sortis pendant la période mensuelle traitée, jusqu’à la date du calcul. Il s’agit d’une durée observée sur les sorties retenues. Le calcul de risque relit la valeur enregistrée ; il ne reconstruit pas lui-même cet historique.
Pour une durée J :
Si J <= 45 : Rrotation = 30 × J / 45
Sinon : Rrotation = min(100 ; 30 + 0,80 × (J - 45))
| Durée retenue | Risque de rotation |
|---|---|
| 15 jours | 10 |
| 30 jours | 20 |
| 45 jours | 30 |
| 90 jours | 66 |
| 120 jours | 90 |
| 132,5 jours et au-delà | 100 |
Une durée enregistrée positive garde la priorité sur la couverture courante. Une hausse du stock ne modifie donc pas automatiquement cette durée observée, même si elle fait augmenter la pénalité de surstock.
11.4. L’âge du produit
| Âge depuis la création de la fiche | Risque de cycle de vie |
|---|---|
| Moins de 30 jours | 70 |
| De 30 à moins de 90 jours | 40 |
| 90 jours ou plus | 10 |
Il s’agit de l’âge de la fiche dans les données, pas nécessairement de l’âge commercial réel de la référence. Ce facteur traduit surtout une prudence envers un historique récent.
12. Comment ces composantes deviennent-elles un score unique ?
12.1. Les deux synthèses calculées
Le modèle calcule d’abord un indicateur immédiat :
PventeJour = 0,55 × Pdemande
+ 0,25 × Pdisponibilité
+ 0,10 × Pattractivité
+ 0,10 × Pqualité
Rimmédiat = arrondi à une décimale de [100 × (1 - PventeJour)]
L’appellation interne évoque la vente « aujourd’hui ». Puisque cette moyenne pondérée comprend du provisionné sans calendrier de réception, elle doit rester comprise comme un indicateur composite.
La synthèse structurelle utilise dix pondérations :
| Risque | Poids dans la synthèse structurelle |
|---|---|
| Demande | 24 % |
| Stock | 14 % |
| Fournisseur | 12 % |
| Prix | 8 % |
| Clientèle | 11 % |
| Ventes associées | 7 % |
| Anomalies | 5 % |
| Cycle de vie | 3 % |
| Rotation | 10 % |
| Surstock | 6 % |
| Total | 100 % |
Rstructurel est la somme pondérée de ces dix risques, arrondie à une décimale.
12.2. La pondération globale de référence
La répartition sous-jacente est 55 % de risque immédiat et 45 % de risque structurel. Avant arrondis, tendance et bonus, cela correspond aux poids suivants :
| Signal élémentaire | Poids global théorique |
|---|---|
| Risque de demande | 41,05 % |
| Risque de stock | 20,05 % |
| Risque fournisseur | 5,40 % |
| Risque prix | 3,60 % |
| Risque clientèle | 4,95 % |
| Risque de ventes associées | 3,15 % |
| Risque d’anomalies | 2,25 % |
| Risque de cycle de vie | 1,35 % |
| Risque de rotation | 4,50 % |
| Risque de surstock | 2,70 % |
Complément de l’attractivité : 100 × (1 - Pattractivité) |
5,50 % |
Complément de la qualité : 100 × (1 - Pqualité) |
5,50 % |
| Total | 100 % |
Ces poids ne sont pas indépendants : le surstock modifie aussi le risque de stock ; les prix et les ventes associées modifient aussi l’attractivité.
12.3. Le résultat enregistré est une accumulation par étape
Pour reproduire exactement le score, il ne suffit pas de calculer 0,55 × Rimmédiat + 0,45 × Rstructurel, puis d’arrondir une fois.
L’implémentation ajoute des contributions entières au fil des étapes. Chaque contribution ci-dessous est arrondie à une décimale, puis à l’entier supérieur avant son ajout :
| Étape | Contribution avant ces arrondis |
|---|---|
| Demande | 0,3025 × Rdemande |
| Disponibilité | 0,1375 × Rstock + 0,027 × Rsurstock |
| Attractivité | 0,036 × Rprix + 0,0315 × RventesAssociées + 0,055 × 100 × (1 - Pattractivité) |
| Qualité du stock | 0,055 × 100 × (1 - Pqualité) + 0,0225 × Ranomalies |
| Risque structurel | 0,108 × Rdemande + 0,063 × Rstock + 0,054 × Rfournisseur + 0,0495 × Rclients + 0,0135 × Rcycle + 0,045 × Rrotation |
La dernière ligne ajoute seulement la part structurelle qui n’a pas déjà été comptée dans les étapes précédentes. Le risque structurel complet est calculé séparément pour la synthèse explicative.
Le cumul commence à zéro. La tendance intervient après la demande. Chaque ajout est limité à un cumul de 100 et peut arrêter la chaîne. Les arrondis à une décimale utilisent le comportement .NET par défaut, avec les égalités départagées vers le chiffre pair ; l’arrondi suivant est un plafond mathématique.
Une contribution de 1,2 devient donc 2 points ; 0,04 devient d’abord 0,0, puis zéro point. Ces détails expliquent pourquoi une reconstitution simplifiée peut différer du badge affiché.
13. Les bonus appliqués à la fin
13.1. Le bonus commercial : jusqu’à 25 points
Si la chaîne atteint la finalisation :
ForceDemande = borne(d / 50 ; 0 ; 1)
ForceClients = borne(C / max(2 × H ; 1) ; 0 ; 1)
BonusCommercial = arrondi entier de [
25 × (0,60 × ForceDemande + 0,40 × ForceClients)]
L’arrondi est au plus proche, avec les demi-unités éloignées de zéro. Le volume peut apporter jusqu’à 15 points et la clientèle jusqu’à 10 points.
Avec une moyenne de 1 unité par jour, cinq clients et un seuil de cinq :
ForceDemande = 1 / 50 = 0,02
ForceClients = 5 / 10 = 0,5
BonusCommercial = arrondi(25 × (0,60 × 0,02 + 0,40 × 0,5))
= arrondi(5,3) = 5 points
13.2. Le bonus de sous-stock : jusqu’à 6 points
Le modèle mesure aussi les déficits du physique par rapport aux seuils :
DéficitMini = borne((M - physique) / max(M ; 0,01) ; 0 ; 1)
DéficitCommande = borne((P - physique) / max(P ; 0,01) ; 0 ; 1)
Chaque déficit vaut zéro si son seuil n’est pas positif ou si le physique n’est pas inférieur à ce seuil.
BonusSousStockDécimal = arrondi à une décimale de [
15 × borne(0,65 × DéficitMini + 0,35 × DéficitCommande ; 0 ; 0,40)]
Ce montant est ensuite arrondi à l’entier le plus proche, avec les demi-unités éloignées de zéro. Le maximum est 15 × 0,40 = 6 points.
Ce bonus coexiste avec les pénalités de disponibilité. Il ne les annule pas nécessairement. Il n’est pas conditionné ici par un test supplémentaire de demande positive.
13.3. La dernière opération
ScoreFinal = max(0 ; cumul des étapes - BonusCommercial - BonusSousStock)
Les bonus ne sont appliqués que si aucune étape précédente n’a arrêté le traitement à 100. Le score final est enregistré sous forme entière, avec son explication Markdown.
14. Exemple complet : un même produit avec 30 ou 180 jours de stock
Considérons un produit fictif avec des entrées de calcul cohérentes dans la même unité :
| Paramètre | Valeur |
|---|---|
| Moyenne des quantités clients sur deux ans | 1 unité par jour |
| Ratio de tendance 30/180 jours | 1 |
| Tendance hebdomadaire | Nulle |
| Clients distincts sur six mois | 5 |
| Seuil clients | 5 |
| Âge du produit | Au moins 90 jours |
| Historique fournisseur sur 24 mois | Présent |
| Stock physique et stock net | 30 unités |
| Provisionné et réservé | 0 |
| Stock minimum total | 10 unités |
| Point de commande total | 20 unités |
| Variabilité des prix | Nulle |
| Part des commandes multiproduits | 50 % |
| Anomalies | 0 |
| Délai fournisseur retenu | 30 jours |
| Écart-type du délai | 0 jour |
| Rotation déjà enregistrée | 30 jours |
14.1. Les composantes de départ
Le signal de demande vaut :
Pbase = 1 - exp(-1) ≈ 0,632121
Pdemande = Pbase × 1,2 ≈ 0,758545
Rdemande = 24,1
La couverture est de 30 jours. La pénalité de surstock liée aux jours est nulle, mais les deux seuils sont dépassés :
rMini = ((30 - 10) / 10) / 3 = 2/3
rCommande = ((30 - 20) / 20) / 3 = 1/6
PénalitéSurstock = 0,25 × 2/3 + 0,15 × 1/6
≈ 0,191667
Pdisponibilité ≈ 1 × (1 - 0,191667) = 0,808333
Rstock = 19,2
Rsurstock = 19,2
Les autres valeurs sont :
Pattractivité = 1 × (0,70 + 0,30 × 0,5) = 0,85
Rprix = 0 ; RventesAssociées = 50
Pqualité = 0,99 ; Ranomalies = 0
Rfournisseur = 70 × 30 / 45 ≈ 46,666667
Rclients = 50 ; Rcycle = 10 ; Rrotation = 20
14.2. Le cumul exact par participant
| Étape | Contribution avant arrondi à une décimale | Contribution entière | Cumul |
|---|---|---|---|
| Demande | 7,29025 | +8 | 8 |
| Tendance | 0 | 0 | 8 |
| Disponibilité | 3,1584 | +4 | 12 |
| Attractivité | 2,4 | +3 | 15 |
| Qualité du stock | 0,055 | +1 | 16 |
| Risque structurel | 9,8424 | +10 | 26 |
| Bonus commercial | 5,3 avant arrondi entier | −5 | 21 |
| Bonus sous-stock | 0 | 0 | 21 |
Le score final est de 21 %, dans la tranche verte. La demande est établie, mais le résultat conserve notamment l’effet de la couverture par rapport aux seuils et du délai d’approvisionnement.
Les synthèses intermédiaires valent environ 19,7 de risque immédiat et 26,5 de risque structurel. Leur fusion suivie d’un arrondi unique ne redonne pas exactement 21, puisque l’implémentation arrondit les contributions séparément.
14.3. Si le stock net atteint 180 unités
Conservons les mêmes historiques, la même demande et la même rotation enregistrée, mais portons le physique et le net à 180 unités. Il s’agit d’une comparaison entre deux états du calcul, pas d’une simulation de commande intégrée à l’écran.
La couverture atteint 180 jours. Les trois ratios de surstock sont au maximum ; la pénalité est plafonnée à 0,70. La disponibilité passe à 0,30 et les risques de stock et de surstock à 70.
| Étape | Contribution entière avec 30 unités | Contribution entière avec 180 unités |
|---|---|---|
| Demande | 8 | 8 |
| Tendance | 0 | 0 |
| Disponibilité | 4 | 12 |
| Attractivité | 3 | 3 |
| Qualité du stock | 1 | 1 |
| Risque structurel | 10 | 13 |
| Bonus commercial | −5 | −5 |
| Bonus sous-stock | 0 | 0 |
| Score final | 21 | 32 |
Le risque augmente de 11 points. Pourtant, le score reste dans la tranche bleue. Cet exemple montre pourquoi une couleur favorable ne suffit pas à justifier un achat : 180 jours de couverture doivent être examinés directement, même si les autres signaux du produit restent bons.
La rotation enregistrée demeure ici à 30 jours. Si elle était absente, la couverture servirait de repli et ajouterait un autre effet au score.
15. Comment utiliser l’indice avant de commander ?
La bonne lecture associe le score, son explication et la quantité envisagée.
Commencer par le motif du risque
Un score élevé accompagné d’une faible demande, d’une couverture longue et d’une rotation lente appelle une revue du volume à acheter. Un score élevé principalement causé par une rupture doit être examiné avec les besoins clients : commander peut améliorer la disponibilité.
De même, un score à 100 pour absence d’historique ne se lit pas comme un score à 100 après accumulation de signaux défavorables. L’explication permet de distinguer ces situations.
Examiner la couverture après l’achat envisagé
Pour compléter manuellement la lecture, on peut construire une estimation simple :
Couverture indicative après ajout = (stock net + quantité envisagée)
/ demande journalière retenue
Cette formule complémentaire n’est pas une fonction de simulation de la requête de risque actuelle. Elle suppose une demande positive et constante, sans consommation intermédiaire, et une quantité qui n’est pas déjà comptée dans le provisionné.
Par exemple, avec 30 unités nettes, une demande de 1 unité par jour et un achat envisagé de 120 unités, on obtient 150 jours de couverture indicative. Si ces 120 unités sont déjà provisionnées dans le net utilisé, les ajouter de nouveau compterait deux fois la même commande.
Une analyse plus fine doit positionner les livraisons et les besoins dans le temps, vérifier le conditionnement fournisseur et examiner les stocks par entrepôt. Elle permet aussi de tenir compte d’une campagne exceptionnelle ou d’une saisonnalité que le score ne modélise pas explicitement.
Comparer les signaux dans le temps
Une demande en baisse, des jours de couverture en hausse et une rotation qui se dégrade forment un ensemble plus parlant qu’un chiffre isolé. À l’inverse, une bonne demande ne justifie pas mécaniquement plusieurs mois de stock supplémentaire.
flowchart TD
A["Avant de valider une commande"] --> B["Lire le score et son explication"]
B --> C{"Score imposé faute de données ?"}
C -- Oui --> D["Vérifier historique, entrepôts et lancement produit"]
C -- Non --> E{"Demande faible ou couverture longue ?"}
E -- Oui --> F["Examiner réduction du lot ou livraisons fractionnées"]
E -- Non --> G["Examiner besoins clients et risque de rupture"]
D --> H["Évaluer la quantité et les dates envisagées"]
F --> H
G --> H
H --> I["Décider avec la couverture, la rotation et les engagements"]Ces pistes relèvent de la décision d’approvisionnement. Le moteur de risque décrit ici ne les exécute pas automatiquement.
16. Où retrouver les raisons du score dans AuditStock ?
Dans la liste des produits, la colonne de risque utilise un badge coloré affichant directement la valeur enregistrée. Son infobulle présente l’explication en Markdown lorsqu’elle est disponible.
Le rapport produit comporte également une zone « Risque produit » et une section « Explication du risque ». Le détail prend la forme d’un tableau avec le participant, son explication et le risque cumulé, suivi du taux final.
Les nombres des sous-composantes et les points ajoutés ne sont pas interchangeables. Par exemple, un « risque stock 70 % » ne signifie pas que la disponibilité ajoute 70 points au score final : la contribution applique ses coefficients avant les arrondis.
Un recalcul peut être demandé depuis l’action « Recalcul des scores de risque » de la liste. Le code prévoit aussi un déclenchement sur notification de changement d’un produit dans un entrepôt. Lire un badge affiche la valeur enregistrée ; cela ne constitue pas en soi un nouveau calcul.
La couverture présentée ailleurs dans le rapport utilise StockLifetimeInDays. Le calcul de risque reconstruit sa propre couverture à partir du net et des commandes clients sur deux ans. Il ne faut donc pas supposer que ces deux valeurs sont systématiquement identiques.
17. Les limites à garder en tête pour une décision d’achat
L’indice rend plusieurs signaux comparables, mais son utilisation demande de conserver leur sens métier :
- Pas de prévision de durée exacte. Le score n’annonce pas combien de jours le prochain lot restera en stock.
- Pas de simulation spécifique de commande. Le calcul ne reçoit pas la quantité, le fournisseur et la date de réception envisagés.
- Périmètre global. Il peut masquer des écarts entre entrepôts ou entre fournisseurs.
- Historique de commandes. Une commande saisie n’est pas nécessairement une livraison réalisée ; la qualité des états et des imports compte.
- Historique incomplet ou récent. La moyenne reste calculée sur deux ans et certains manques de données peuvent produire des valeurs favorables par défaut, comme une variabilité nulle.
- Saisonnalité et concentration. Il existe des tendances, mais pas de modèle saisonnier explicite ni de mesure de dépendance au volume du premier client.
- Coût d’immobilisation. La variabilité des prix intervient, mais le score ne chiffre pas la trésorerie immobilisée, le coût de stockage ou la marge attendue du lot envisagé.
- Arrondis et arrêts. Le cumul entier, l’ordre des bonus et l’arrêt à 100 font partie du résultat réel.
Pour savoir si une commande risque de laisser un produit longtemps en stock, je commence donc par lire le détail du score, puis je confronte la quantité envisagée à la demande et à la couverture. L’indice aide à repérer et à expliquer les situations à examiner ; la quantité à acheter se décide avec ces informations et les engagements réels.