Remises sur quantités des fournisseurs

Remises sur quantités










Accueil » Ressources » Ici

Les remises sur quantités ou sur volumes désignent les cas où le prix unitaire marginal des marchandises dépend de la quantité commandée. Généralement, les prix unitaires baissent lorsque les quantités augmentent afin d’inciter les clients à acheter plus. Lorsque les fournisseurs proposent des remises sur quantités, il est intéressant d’un point de vue économique d'ajuster les quantités commandées pour en profiter. Envision offre la possibilité de gérer entièrement les remises sur quantités de vos fournisseurs. Dans cette section, nous vous présentons comment modéliser les remises sur quantités en vue d’optimiser vos achats.


Représentation tabulaire des remises sur quantités

La façon la plus fréquente de représenter les remises sur quantités associées à une liste de produits est d’utiliser un tableau à 3 colonnes :

  • Id l’identifiant du produit ;
  • MinQuantity la quantité minimale à atteindre pour bénéficier du prix unitaire ;
  • Price le prix d’achat unitaire du produit.

Pour que le tableau reste lisible pour un produit donné, les lignes sont généralement triées par ordre croissant de quantité. Ce tri permet de mesurer l’ampleur des remises.

Cette représentation convient bien aux « prix unitaires marginaux négatifs » pour lesquels l’achat d’une unité supplémentaire peut permettre d’obtenir un prix inférieur.

Prenons le produit A vendu à 1 € par unité. Le produit A est associé à une remise sur quantité accordée à partir de 50 unités achetées, le prix passe alors à 0,9 € par unité. 46 unités coûtent 46 € alors que 50 unités coûtent seulement 45 €. Il n’est donc pas intéressant d'un point de vue économique d’acheter entre 46 et 49 unités puisque 50 unités coûtent moins cher. Le prix unitaire marginal de la 50e unité est -4 €.

Ces prix marginaux négatifs sont les conséquences du modèle de données sous-jacent des remises sur quantités. Des modèles de remises sur quantités plus élaborés — capables d’éliminer ces prix marginaux négatifs — existent, mais sont en dehors du périmètre couvert dans cette présentation.

Dans la suite, nous partons du principe que les données des remises sur quantités sont disponibles dans un tableau tel que présenté ci-dessus.

Fonction Pricebrk()

L'objectif de la fonction pricebrk() dans Envision est de transformer les données tabulaires des remises sur quantités en une distribution qui représente le coût d’achat marginal des unités. La syntaxe est la suivante :
expect Prices[Id, *] // ‘Prices’ correspond au tableau des remises sur quantités
B = pricebrk(Demand, Price, Prices.MinQuantity, Prices.Price, Stock, StockPrice)
La fonction renvoie la distribution du prix d’achat unitaire marginal, c’est-à-dire le prix à payer pour l’achat de la ke unité. Elle est un peu complexe. Nous détaillons et justifions cette complexité dans la suite.

Les arguments sont :
  • Demand, choix du support — au sens mathématique — de la distribution renvoyée. Les valeurs de cette distribution ne sont pas utilisées, mais la distribution renvoyée est ajustée pour être au moins aussi précise que Demand.
  • Price, chiffre interprété comme le prix unitaire par défaut du produit. Cette valeur est utilisée s’il n’y a pas de remise sur quantité pour une quantité minimale de 1, soit parce que la remise commence avec une quantité supérieure à 1, soit parce qu’aucune remise sur quantité n’est proposée pour le produit.
  • Prices.MinQuantity, quantité à partir de laquelle la ligne de remise s’applique. Doit être un entier supérieur ou égal à 1. Aucun doublon n’est autorisé.
  • Prices.Price, prix unitaire de cette ligne de remise sur quantité. S’applique à toutes les unités achetées et pas uniquement à celles au-delà de Prices.MinQuantity. Il doit s’agir d’une fonction décroissante de Prices.MinQuantity.
  • Stock, stock disponible pour le produit. Les valeurs non nulles indiquent que moins d’unités doivent être achetées pour atteindre un niveau de stock donné, ce qui signifie que les remises sur quantités sont plus difficiles à obtenir. Doit être un entier non négatif. Cet argument est facultatif. Lorsqu’il n’est pas fourni, StockPrice doit être ignoré également. Sa valeur par défaut est alors zéro.
  • StockPrice, prix unitaire des unités en stock. Cet argument est facultatif. Sa valeur par défaut est alors zéro, lorsqu’il n’est pas fourni.

L’argument Price est simplement un sucre syntaxique conçu pour gérer les situations dans lesquelles le tableau des remises sur quantités ne couvre que les produits qui bénéficient d'une remise sur quantités. À travers cet argument, le tableau Prices n’a pas besoin d’être étendu pour contenir au moins une ligne par produit.

Résolution de distributions

Le premier argument de pricebrk() doit être une distribution car les distributions dans Envision ne sont pas arbitrairement précises. En effet, il y a des limites pratiques à la résolution d’une distribution dans Envision. Pourtant les remises sur quantités d’un fournisseur donné peuvent aller d’une unité achetée à 10 millions d’unités achetées (théoriquement). La fonction pricebreak() utilise la distribution Demand pour ajuster la résolution de la distribution renvoyée à la plage visée.

En effet, Envision veille à éviter le piège qui consiste à suggérer une commande de 999 unités alors que la remise sur quantité cible démarre à partir de 1000 unités. Une telle situation peut se produire si la distribution générée par Envision ne fait pas de différence entre 999 unités et 1000 unités. En faisant passer la distribution par la fonction pricebrk(), Envision évite ce scénario grâce à l’adaptation de la résolution de la résolution renvoyée.

Espace de commande vc espace de stockage

L’organisation du tableau de remises sur quantités est adaptée aux « commandes », un prix d’achat unitaire est associé à chaque quantité achetée. Cependant, pour optimiser le stock, l’organisation doit être adaptée au « stockage » : la décision d’ajouter une unité au stock doit prendre en compte le stock déjà disponible, c’est-à-dire « l’espace de stockage ». Grâce à la fonction pricebrk(), la représentation des remises sur quantités basée sur l’espace de commande devient une représentation basée sur l’espace de stockage.

Cette conversion explique pourquoi pricebrk() requiert deux arguments associés au stock : le niveau de stock et le prix d’unité de stock. Ces deux arguments sont utilisés pour décaler la distribution des prix marginaux vers la droite par unités de « stock ». L’opérateur de décalage des distributions habituel >> pourrait être utilisé, mais des approximations mineures peuvent alors entrer en conflit avec les seuils des remises sur quantités. Ce décalage est intégré à la fonction pricebrk() afin d’éliminer ces approximations.

Coût marginal des unités

La distribution renvoyée par pricebrk() représente le coût d’achat unitaire marginal. Le segment [1;Stock] est associé aux stocks en cours et à StockPrice. Puis, si B est la distribution renvoyée par pricebrk(), alors l’intégrale int(B, Stock + 1, Stock + N) est le coût total de l’achat de « N » unités en plus des unités déjà en stock.

Comme nous l’avons souligné, les tableaux de remises sur quantités contiennent souvent des coûts unitaires marginaux négatifs — c’est-à-dire que l’achat d’une unité supplémentaire a un coût négatif. Ces situations sont représentées dans les distributions renvoyées par pricebrk() par des valeurs négatives locales. Ces dernières sont cohérentes et découlent directement du modèle de données des remises sur quantités.

Combinaison des remises sur quantités et des récompenses associées au stock

La fonction de récompense associée au stock calcule la distribution du rendement économique de chaque unité supplémentaire en stock. Dans un précédent article, nous avons vu que cette fonction peut être associée à des variables économiques qui représentent la marge brute, la pénalité de rupture de stock et le coût de stockage. Dans le précédent article, ces variables économiques étaient de simples chiffres. Cependant, lorsqu’il faut gérer des remises sur quantités, ces variables varient aussi en fonction de la quantité commandée. Ces variations sont faciles à modéliser à travers les distributions.
B = pricebrk(Demand, BuyPrice, Prices.MinQuantity, Prices.Price, Stock, StockPrice)

M = SellPrice - B // 'M' est une distribution
S = -0.5 * (SellPrice - B) // 'S' est une distribution
C = -0.3 * B * mean(Leadtime) / 365 // 'C' est une distribution
AM = 0.3
AC = 1 - 0.2 * mean(Leadtime) / 365

RM = stockrwd.m(Demand, AM) * M // multiplication
RS = stockrwd.s(Demand) * S // idem
RC = stockrwd.c(Demand, AC) * C // idem
R = RM + RS + RC 
La différence principale entre ce bloc de code et celui d’origine, lorsque nous avons commencé à évoquer la fonction de récompense associée au stock, est BuyPrice. La colonne BuyPrice devient la distribution de remises sur quantités B à la ligne 1 à travers la fonction pricebrk(). Le reste du script se résume à une application directe de l’algèbre des distributions, qui se charge de la partie compliquée pour nous.

Aux lignes 3 à 5, les variables économiques sont transformées en distributions. En effet, lorsqu’une constante est ajoutée à une distribution, le résultat de l’addition est une distribution. Il en va de même pour la soustraction. La récompense marginale « par unité » se trouve au-delà de M et, puisque les remises sur quantités donnent généralement accès à un prix unitaire inférieur lorsque les quantités augmentent, la distribution M est censée être croissante.

Aux lignes 9 à 11, les composants des fonctions de récompense associée au stock sont reliés aux « distributions » économiques (plutôt qu’à des chiffres), mais la syntaxe reste la même. C’est en fait des multiplications qui ont lieu entre les distributions. Enfin, à la ligne 12, la récompense associée au stock finale est construite comme précédemment.