I. Introduction▲
La valorisation des stocks consiste à évaluer les entrées et les sorties des différentes matières premières et marchandises, pour connaître à tout moment la valeur effective des stocks de produits.
Le coût moyen des sorties de stock s'obtient principalement suivant trois grands types de méthodes :
Coût unitaire moyen pondéré périodique (CUMP)Méthode CUMP : le coût unitaire de sortie d'articles du stock est égal à la somme de (la valeur initiale + celles d'entrées en stock) divisée par la somme de (quantité initiale et celles d'entrées en stock). Si ce sont des stocks de produits finis, le coût unitaire d'entrée sera le coût de production (voir pour sa détermination la comptabilité analytique).
Premier entré, premier sorti (FIFO, PEPS en français)Méthodes FIFO et LIFO : le coût unitaire de sortie d'un type d'article du stock est égal à la valeur de l'article qui est entré en premier chronologiquement dans le stock. Un article entre à 10 € puis 20 €, il sortira en premier à 10 €.
Dernier entré, premier sorti (LIFO, DEPS en français)Méthodes FIFO et LIFO : le coût unitaire de sortie d'un type d'article du stock est égal à la valeur de l'article qui est entré en dernier chronologiquement dans le stock. Un article entre à 10 € puis 20 €, il sortira en premier à 20 €.
On souhaite donc créer une fonction en Python qui puisse calculer les coûts moyens des sorties sur le stock suivant ces 3 méthodes.
Si vous souhaitez avoir plus de détails sur le sujet, je vous invite à consulter la page Wikipédia Méthodes d'évaluation comptable des stocksMéthodes d'évaluation comptable des stocks ainsi que le tutoriel de Claude Leloup Évaluation des stocks avec ACCESSÉvaluation des stocks avec ACCESS.
II. Méthodes d'évaluation des stocks▲
Nous présentons maintenant les trois méthodes permettant d'évaluer le coût moyen des sorties sur le stock.
II-A. Méthode CUMP▲
Pour les entreprises qui vendent des marchandises non périssables et qui ne prennent pas de valeur avec le temps, c’est souvent la méthode du coût unitaire moyen pondéré (CUMP) qui est choisie.
Coût unitaire moyen pondéré périodique (CUMP) : le coût unitaire de sortie d'articles du stock est égal à la somme de (la valeur initiale + celles d'entrées en stock) divisé par la somme de (quantité initiale et celles d'entrées en stock). Si ce sont des stocks de produits finis, le coût unitaire d'entrée sera le coût de production (voir pour sa détermination la comptabilité analytique).
On entre dans le stock 10 articles avec une référence donnée au prix unitaire de 14 €, puis 20 unités supplémentaires avec la même référence cette fois à 15.50 €. Le coût moyen pondéré de la dernière entrée vaut alors :
coût_moyen = (10*14.00 € + 20*15.50 €)/30 = 15.00 €
Puis, on sort 25 unités, et le CUMP de la sortie reste à 15.00 €.
Enfin, on ajoute au stock 10 unités, et en tenant compte du stock précédent le CUMP devient :
coût_moyen = (5*15.00 € + 10*16.50 €)/15 = 16.00 €
II-B. Méthodes FIFO et LIFO▲
Décrivons maintenant les méthodes FIFO et LIFO permettant d'évaluer le coût moyen des sorties de stock.
Méthode FIFO
Les sociétés qui vendent des denrées périssables ont tendance à choisir cette méthode. Les sorties sont valorisées au coût d’achat des premières marchandises acquises.
Premier entré, premier sorti (FIFO, PEPS en français) : le coût unitaire de sortie d'un type d'article du stock est égal à la valeur de l'article qui est entré en premier chronologiquement dans le stock. Un article entre à 10 € puis à 20 €, il sortira en premier à 10 €.
On entre dans le stock 10 articles avec une référence donnée au prix unitaire de 14 €, puis 20 unités supplémentaires du même type cette fois à 16 €. Si maintenant on sort 25 unités de cet article, son coût moyen vaudra :
coût_moyen = (10*14.00 € + 15*16.00 €)/25 = (140.00 € + 240.00 €)/25 = 380.00 € / 25 = 15.20 €
Méthode LIFO
Cette méthode est plus rarement utilisée. Les sorties sont valorisées au coût d’acquisition des dernières marchandises achetées.
Dernier entré, premier sorti (LIFO, DEPS en français) : le coût unitaire de sortie d'un type d'article du stock est égal à la valeur de l'article qui est entré en dernier chronologiquement dans le stock. Un article entre à 10 € puis à 20 €, il sortira en premier à 20 €.
On entre dans le stock 10 articles avec une référence donnée au prix unitaire de 14 €, puis 20 unités supplémentaires du même type cette fois à 16 €. Si maintenant on sort 25 unités de cet article, son coût moyen vaudra :
coût_moyen = (20*16.00 € + 5*14.00 €)/25 = (320.00 € + 70.00 €)/25 = 390.00 € / 25 = 15.60 €
III. Création de la fonction d'évaluation des stocks▲
Pour valoriser les sorties du stock suivant les trois méthodes, nous allons donc créer une fonction en Python.
III-A. Fonction d'évaluation du CUMP▲
Elle prend en argument la liste triée des mouvements sur le stock et renvoie la liste des entrées/sorties valorisées.
Déroulé de la fonction :
- 1. Génération de la liste des références des produits contenus dans le stock ;
- -- 1.1. Pour chaque référence, filtre de la liste des mouvements par référence produit,
- -- 1.2. Pour chaque référence, parcours de la liste des mouvements du produit,
- ---- 1.2.1. Pour chaque entrée, évaluation de son prix moyen pondéré,
- ---- 1.2.2. Pour chaque sortie, récupération du CUMP de l'entrée précédente,
- ---- 1.2.3. Pour chaque entrée/sortie, ajout du mouvement valorisé à la liste résultat ;
- 2. Renvoi de la liste des mouvements valorisés.
récupérer_références_produits
tant que
existe
référence_produit
quantité_totale =
0
; somme_prix_entrées =
0
; quantité_stock_init=
0
; cump_init =
0
filtrer_mouvements_par_référence_produit
tant que
existe
mouvement_produit:
si
mouvement est
entrée_produit alors
:
quantité_totale =
quantité_totale +
quantité_entrée
somme_prix_entrées =
somme_prix_entrées +
prix_entrée*
quantité_entrée
cump =
(quantité_stock_init*
cump_init +
somme_prix_entrees)/
(quantité_stock_init+
quantite_totale)
cump_entrée =
cump
quantité_stock =
quantité_stock +
quantité_entrée
sinon
:
cump_sortie =
cump
quantité_stock =
quantité_stock -
quantité_sortie
quantité_stock_init =
quantité_stock; cump_init =
cump
fin
si
ajouter_mouvement_valorisé_à_liste
mouvement_suivant
fin
tant que
fin
tant que
retourner
liste_mouvements_valorisés
def
valoriser_stocks_cump
(
liste_mouvements):
# initialisation de la liste des sorties valorisées générée par la fonction
liste_mouvements_valorises =
[]
# filtre les sorties dans une liste
liste_references_produits =
sorted
(
set(
[mouv['référence'
] for
mouv in
liste_mouvements]))
# parcours de la liste des références des produits
for
reference_produit in
liste_references_produits:
# filtre les entrées/sorties en fonction de la référence du produit
liste_mouvs_produit =
[mouv_produit for
mouv_produit in
liste_mouvements if
(
mouv_produit['référence'
]==
reference_produit)]
# initialisation des quantités en stock et de la somme des prix en entrées
qte_stock =
0
; somme_prix_entrees =
0
; quantite_totale =
0
; cump =
0
; qte_stock_init=
0
; cump_init =
0
# parcours de la liste des mouvements du stock
for
mouv_produit in
liste_mouvs_produit:
if
mouv_produit['type_mouv'
]==
'entrée'
: # s'il s'agit d'une entrée dans le stock
# calcul de la somme des prix unitaires en entrées jusqu'à ce mouvement
somme_prix_entrees =
somme_prix_entrees +
mouv_produit['quantité'
]*
mouv_produit['prix_unitaire'
]
# calcul de la quantité totale des entrées jusqu'à ce mouvement
quantite_totale =
quantite_totale +
mouv_produit['quantité'
]
# calcul du coût moyen pondéré (CUMP) avec correction des erreurs dans les résultats des opérations en virgule flottante
cump =
round((
qte_stock_init*
cump_init +
somme_prix_entrees)/(
qte_stock_init+
quantite_totale),7
)
mouv_produit['CUMP'
] =
cump # mise à jour du champ CUMP
qte_stock =
qte_stock +
mouv_produit['quantité'
]
else
: # sinon
somme_prix_entrees =
0
# on initialise la somme des prix unitaires des entrées
quantite_totale =
0
# on initialise la quantité totale des entrées
stock_initial =
True
mouv_produit['CUMP'
] =
cump # mise à jour du champ CUMP
qte_stock =
qte_stock -
mouv_produit['quantité'
]
qte_stock_init =
qte_stock; cump_init=
cump # copie des valeurs du stock initial et du CUMP initial
liste_mouvements_valorises =
liste_mouvements_valorises +
[mouv_produit] # ajout du mouvement avec son coût moyen
return
liste_mouvements_valorises # retourne la liste des mouvements valorisés
III-B. Fonction d'évaluation du coût moyen des sorties par la méthode FIFO et LIFO▲
Elle prend en arguments la liste des mouvements sur le stock et la méthode de valorisation choisie (CUMP, FIFO ou FIFO) et renvoie la liste des mouvements valorisés.
- liste_mouvements : liste des mouvements (entrées/sorties) sur le stock ;
- methode_valorisation : méthode de valorisation choisie CUMP, FIFO ou LIFO.
Déroulé de la fonction :
- 1. Génération de la liste des références des produits contenus dans le stock ;
- -- 1.1. Pour chaque référence, filtre de la liste des entrées par référence produit,
- -- 1.2. Pour chaque référence, filtre de la liste des sorties par référence produit,
- -- 1.3. Pour chaque référence, parcours de la liste des sorties,
- ---- 1.3.1. Pour chaque sortie, calcul de son coût moyen suivant la méthode FIFO ou LIFO,
- ---- 1.3.2. Pour chaque sortie, ajout de la sortie valorisée à la liste résultat ;
- 2. Renvoi de la liste des sorties valorisées.
récupérer_références_produits
tant que
existe
référence_produit
filtrer_entrées_par_référence_produit
filtrer_sorties_par_référence_produit
tant que
existe
sortie_produit:
valoriser_sortie
ajouter_sortie_à_liste
sortie_suivante
fin
tant que
fin
tant que
retourner
liste_sorties_valorisées
def
valoriser_stocks
(
liste_mouvements, methode_valorisation):
# tri des mouvements dans l'ordre de leur numéro
liste_mouvements =
sorted
(
liste_mouvements,key=
lambda
d: d['numéro_mouv'
])
if
methode_valorisation==
'CUMP'
: # si la méthode choisie est CUMP
return
valoriser_stocks_cump
(
liste_mouvements)
else
: # sinon
# initialisation de la liste des sorties valorisées générée par la fonction
liste_sorties_valorisees =
[]
# récupère la liste des références des produits
liste_references_produits =
sorted
(
set(
[mouv['référence'
] for
mouv in
liste_mouvements]))
# parcours de la liste des références des produits
for
reference_produit in
liste_references_produits:
# filtre les entrées/sorties en fonction de la référence du produit
liste_sorties_produit =
[mouv_produit for
mouv_produit in
liste_mouvements
if
(
mouv_produit['type_mouv'
]==
'sortie'
) and
(
mouv_produit['référence'
]==
reference_produit)]
liste_entrees_produit =
[mouv_produit for
mouv_produit in
liste_mouvements
if
(
mouv_produit['type_mouv'
]==
'entrée'
) and
(
mouv_produit['référence'
]==
reference_produit)]
# parcours des sorties du produit dans l'ordre chronologique
for
sortie_produit in
liste_sorties_produit:
# valorise la sortie et ajoute le résultat à la liste
(
liste_entrees_produit, liste_sorties_valorisees) =
valoriser_sortie
(
sortie_produit, liste_entrees_produit,
liste_sorties_valorisees, methode_valorisation)
return
liste_sorties_valorisees # retourne la liste des sorties valorisées
Fonction de valorisation d'une sortie par la méthode FIFO ou LIFO
Elle a comme arguments :
- sortie_produit : sortie à valoriser ;
- liste_entrees_produit : liste des entrées avec leur quantité mise à jour ;
- liste_sorties_valorisees : liste des sorties valorisées à laquelle ajouter la nouvelle sortie ;
- methode_valorisation : méthode de valorisation des stocks choisie (FIFO, LIFO).
Déroulé de la fonction :
- 1. Pour chaque sortie, parcours des entrées qui la précèdent suivant les numéros d'ordre (FIFO) ou dans l'ordre inverse (LIFO) ;
- -- 1.1. Pour chaque entrée, évaluation de la quantité sortie,
- -- 1.2. Pour chaque entrée, mémorisation de son prix unitaire et de la quantité sortie ;
- 2. Pour chaque sortie, calcul de son coût moyen suivant la méthode FIFO ou LIFO ;
- 3. Pour chaque sortie, ajout de la sortie valorisée à la liste résultat ;
- 4. Renvoi de la liste des entrées et de la liste des sorties valorisées.
filtrer_entrées_antérieures_sortie
si
méthode_valorisation =
"FIFO"
:
inverser_entrées_antérieures_sortie
tant que
existe
entrée_antérieure_sortie:
si
(quantité_restant_à_sortir <=
quantité_dispo_en_entrée) alors
:
quantité_dispo_en_entrée =
quantité_dispo_en_entrée -
quantité_restant_à_sortir
somme_prix_entrées =
somme_prix_entrées +
prix_entrée*
quantité_restant_à_sortir
si
quantité_dispo_en_entrée =
0
:
supprimer_entrée_dans_liste
prix_unitaire =
somme_prix_entrees/
quantité_totale_sortie
ajouter_sortie_valorisée
sortie_boucle
fin
si
quantité_restant_à_sortir =
quantité_restant_à_sortir -
quantité_dispo_en_entrée
somme_prix_entrées =
somme_prix_entrées +
prix_entrée*
quantité_entrée
supprimer_entrée_dans_liste
entrée_suivante
fin
tant que
Comme on le constate, on a juste besoin d'inverser la liste des entrées précédant chacune des sorties pour passer de la méthode FIFO à la méthode LIFO. Inutile donc de créer deux fonctions séparées quasiment identiques pour implémenter les deux méthodes de valorisation des stocks. Le code pourrait sûrement encore être optimisé mais ce faisant on risquerait aussi de le rendre moins lisible.
IV. Implémentation de la fonction de valorisation des sorties▲
Pour effectuer les tests, il faut tout d'abord copier les fonctions précédentes dans un module Python. On propose d'ailleurs à la fin du tutoriel un module completModule Python permettant d'évaluer les sorties du stock avec la fonction valoriser_stocks.
IV-A. Test avec des données exemples▲
Comme vu précédemment, la fonction valoriser_stocks prend en arguments une liste représentant en fait des mouvements de stock enregistrés dans une base de données et la méthode de valorisation (CUMP, FIFO, LIFO).
Cette liste de dictionnaires passée en argument a comme structure :
[
{
"numéro_mouv"
:1
,
"date_mouv"
:"2022/01/01"
,
"référence"
:"1824"
,
"quantité"
:2
,
"prix_unitaire"
:100.98
,
"type_mouv"
:"entrée"
},
{
"numéro_mouv"
:2
,
"date_mouv"
:"2022/01/05"
,
"référence"
:"1824"
,
"quantité"
:10
,
"prix_unitaire"
:102.76
,
"type_mouv"
:"entrée"
},
...
]
Les numéros des mouvements sur le stock permettent de les classer, y compris s'il y a plusieurs entrées/sorties le même jour.
Exemple de test avec une liste de mouvements dont on souhaite évaluer les coûts moyens en sorties par la méthode FIFO :
# liste des mouvements sur le stock
liste_mouvements=
[{'numéro_mouv'
:1
, 'date_mouv'
:'2022/01/01'
, 'référence'
: '1824'
, 'quantité'
: 2
, 'prix_unitaire'
: 100.98
,'type_mouv'
:'entrée'
},
{'numéro_mouv'
:2
, 'date_mouv'
:'2022/01/05'
, 'référence'
: '1824'
, 'quantité'
: 10
, 'prix_unitaire'
: 102.76
,'type_mouv'
:'entrée'
},
{'numéro_mouv'
:3
, 'date_mouv'
:'2022/01/10'
, 'référence'
: '1824'
, 'quantité'
: 10
, 'prix_unitaire'
: 90.54
,'type_mouv'
:'entrée'
},
{'numéro_mouv'
:4
, 'date_mouv'
:'2022/01/12'
, 'référence'
: '1824'
, 'quantité'
: 5
, 'prix_unitaire'
: 0
,'type_mouv'
:'sortie'
},
{'numéro_mouv'
:5
, 'date_mouv'
:'2022/01/15'
, 'référence'
: '1824'
, 'quantité'
: 10
, 'prix_unitaire'
: 0
,'type_mouv'
:'sortie'
},
{'numéro_mouv'
:6
, 'date_mouv'
:'2022/01/20'
, 'référence'
: '1824'
, 'quantité'
: 20
, 'prix_unitaire'
: 101.32
,'type_mouv'
:'entrée'
},
{'numéro_mouv'
:7
, 'date_mouv'
:'2022/01/22'
, 'référence'
: '1824'
, 'quantité'
: 8
, 'prix_unitaire'
: 0
,'type_mouv'
:'sortie'
}]
# appel de la fonction de valorisation des stocks qui renvoie le résultat dans une liste
liste_sorties_valorisees =
valoriser_stocks
(
liste_mouvements,'FIFO'
)
# affiche les sorties avec leur coût moyen calculé en fonction de la méthode choisie
print
(
liste_sorties_valorisees)
Le résultat obtenu est sous la forme d'une liste de sorties, avec pour chacune d’entre elles le prix unitaire calculé et le détail des sorties (quantité sortie pour chaque prix unitaire) :
[
{
"numéro_mouv"
:4
,
"date_mouv"
:"2022/01/12"
,
"référence"
:"1824"
,
"quantité"
:5
,
"prix_unitaire"
:102.048
,
"type_mouv"
:"sortie"
,
"détail_sorties"
:[
{
"numéro_entrée"
:1
,
"date_entrée"
:"2022/01/01"
,
"quantité_sortie"
:2
,
"prix_unitaire"
:100.98
},
{
"numéro_entrée"
:2
,
"date_entrée"
:"2022/01/05"
,
"quantité_sortie"
:3
,
"prix_unitaire"
:102.76
}
]
},
{
"numéro_mouv"
:5
,
"date_mouv"
:"2022/01/15"
,
"référence"
:"1824"
,
"quantité"
:10
,
"prix_unitaire"
:99.094
,
"type_mouv"
:"sortie"
,
"détail_sorties"
:[
{
"numéro_entrée"
:2
,
"date_entrée"
:"2022/01/05"
,
"quantité_sortie"
:7
,
"prix_unitaire"
:102.76
},
{
"numéro_entrée"
:3
,
"date_entrée"
:"2022/01/10"
,
"quantité_sortie"
:3
,
"prix_unitaire"
:90.54
}
]
},
{
"numéro_mouv"
:7
,
"date_mouv"
:"2022/01/22"
,
"référence"
:"1824"
,
"quantité"
:8
,
"prix_unitaire"
:91.8875
,
"type_mouv"
:"sortie"
,
"détail_sorties"
:[
{
"numéro_entrée"
:3
,
"date_entrée"
:"2022/01/10"
,
"quantité_sortie"
:7
,
"prix_unitaire"
:90.54
},
{
"numéro_entrée"
:6
,
"date_entrée"
:"2022/01/20"
,
"quantité_sortie"
:1
,
"prix_unitaire"
:101.32
}
]
}
]
Ces données peuvent être ensuite facilement exportées dans une feuille Excel ou directement dans une base de données.
Les données sont issues du fichier Access de Claude Leloup disponible en téléchargement sur son tutoriel Évaluation des stocks avec ACCESSÉvaluation des stocks avec ACCESS
IV-B. Test avec récupération des données contenues dans une table SQLite▲
On dispose d'une base de données SQLite contenant une table MOUVEMENTS_STOCK permettant d'enregistrer les entrées/sorties sur le stock :
Nom de la colonne |
Type de données |
Description |
---|---|---|
NUMERO_MOUV |
INT |
Numéro du mouvement sur le stock |
DATE_MOUV |
TEXT |
Date du mouvement sur le stock |
REFERENCE |
TEXT |
Référence du produit |
QUANTITE |
NUMERIC |
Quantité de produit entrée ou sortie du stock |
PRIX_UNITAIRE |
REAL |
Prix unitaire du produit |
TYPE_MOUV |
TEXT |
Type de mouvement sur le stock : "entrée", "sortie". |
Pour importer les données contenues dans la base, on doit d'abord ajouter en haut de notre module une référence à la librairie sqlite3 :
import
sqlite3
from
sqlite3 import
Error
Puis, on écrit une fonction pour se connecter à la base SQLite :
def
create_connection
(
db_file):
""" crée une connexion à la base de données SQLite
specifié par le chemin du fichier passé en argument
:param db_file: chemin du fichier db
:return: un objet connexion ou renvoie none
"""
conn =
None
try
:
conn =
sqlite3.connect
(
db_file) # on crée l'objet connexion
return
conn
except
Error as
e: # gestion de l'erreur
print
(
e) # affichage du message d'erreur
return
conn
Enfin, on peut tester la fonction de valorisation avec une liste de mouvements issus d'une table SQLite :
Vous devrez bien sûr faire correspondre les colonnes de votre base de données avec les clefs des dictionnaires pour pouvoir ensuite récupérer la liste des mouvements sur le stock, puis valoriser les sorties à l'aide de la fonction valoriser_stocks.
V. Conclusion▲
Après avoir présenté les trois méthodes d'évaluation des stocks (CUMP, FIFO et LIFO) à l'aide de tableaux, nous avons pu ensuite écrire l'algorithme, puis la fonction permettant de valoriser une liste de mouvements de stock par ces trois méthodes. Enfin, nous avons montré comment tester cette fonction sur une liste d'entrées/sorties avec la méthode FIFO.
VI. Module Python▲
Il contient le code complet permettant de valoriser une liste de mouvements de stocks en fonction des trois méthodes :
VII. Remerciements▲
Je tiens à remercier Claude Leloup pour son tutoriel et sa base de données, ainsi qu’escartefigue pour sa relecture.