I. L'idée de départ▲
Trois tables :
- une pour référencer les articles : tArticles ;
- une pour comptabiliser les entrées en stock : tEntrees ;
- une pour comptabiliser les sorties : tSorties.
Si, lors de la mise en place, un stock existe déjà, il est comptabilisé comme une entrée.
La colonne « CMUP » (Coût Moyen Unitaire Pondéré) est ajoutée pour les besoins de l'exemple qui va suivre.
On pourrait reprocher la colonne « CMUP » dans la table tSorties : elle est redondante puisque cette notion est déjà incluse dans tEntrees.
Le souci de faciliter les calculs de prix de revient (en aval) justifie ce choix.
II. Avantage d'une telle approche : la simplicité▲
Le stock à un moment donné s'obtient :
Somme des entrées - somme des sorties
à cette date |
Voici le contenu du module mFonctions :
Option
Compare Database
Option
Explicit
Public
Function
EntreesADate
(
Article As
Long
, DateAng As
Date
) As
Single
EntreesADate =
Nz
(
DSum
(
"EntreeQuant"
, "tEntrees"
, _
"format(EntreeDate,""yyyymmdd"")<="
&
Format
(
DateAng, "yyyymmdd"
) &
" and tArticlesFK="
&
Article), 0
)
End
Function
Public
Function
SortiesADate
(
Article As
Long
, DateAng As
Date
) As
Single
SortiesADate =
Nz
(
DSum
(
"sortieQuant"
, "tSorties"
, _
"format(SortieDate,""yyyymmdd"")<="
&
Format
(
DateAng, "yyyymmdd"
) &
" and tArticlesFK="
&
Article), 0
)
End
Function
Public
Function
StockADate
(
Article As
Long
, DateAng As
Date
) As
Single
StockADate =
EntreesADate
(
Article, DateAng) -
SortiesADate
(
Article, DateAng)
End
Function
La fonction Nz() renverra zéro si aucun enregistrement pour cet article.
.
Pour tester ces fonctions, rendez-vous dans la base de données qui nous sert d'exemple, nous avons :
et ouvrez la fenêtre d'exécution (<CRTL + G>) et saisissez :
? EntreesADate
(
961
,#10
/
04
/
2013
#)
et enfoncez <ENTER>, vous obtiendrez ceci :
soit 12 + 25.
De même :
III. Contexte▲
Pour la suite, nous partons de l'hypothèse que l'entreprise veut valoriser les sorties au CMUP pour le calcul du prix de revient de sa fabrication.
La valorisation des sorties de marchandise au CMUP impose que :
- les entrées de marchandise sont comptabilisées à leur coût réel ;
- les sorties se font au coût unitaire moyen pondéré de la quantité totale du stock disponible.
Voici un exemple pour illustrer la méthode :
Dans un tel contexte, il est impératif que les comptabilisations se fassent dans un ordre chronologique rigoureux : quand un CMUP a été calculé après une entrée, il n'est plus possible de comptabiliser des sorties antérieures à cette date.
IV. Alimenter la table des entrées▲
- L'utilisateur choisit un article dans la liste déroulante.
- S'affiche alors l'historique des entrées dans l'ordre chronologique décroissant (en fait le sous-formulaire sfEntreesDetail)
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
rivate Sub
CboArticle_AfterUpdate
(
)
'Afficher l'historique
Me.CTNRsfEntreesDetail.Form.Requery
'Rendre visibles les contrôles pour l'encodage d'une nouvelle entrée
Me.txtDate.Visible
=
True
Me.txtQuant.Visible
=
True
Me.txtPU.Visible
=
True
Me.txtDate
=
Null
Me.txtQuant
=
Null
Me.txtPU
=
Null
'Afficher le stock actuel de cet article
Me.txtStock
=
StockADate
(
Me.CboArticle
, Format
(
Date
, "mm/dd/yyyy"
))
'Se positionner sur la date à encoder
DoCmd.GoToControl
"txtDate"
End
Sub
Remarquez la syntaxe à la ligne 12
Me.txtStock = StockADate(Me.CboArticle, Format(Date, "mm/dd/yyyy"))
Dans une version Access francophone la fonction Date
(
) renvoie la date d'ajourd'hui sous la forme jj/mm/aaaa.
Or quand on traite une date en VBA, il faut que celle-ci soit sous la forme anglo-saxone (mm/dd/yyyy), d'où ce reformatage nécessaire.
- Introduction de la date de la nouvelle entrée. Pour respecter la méthode CMUP, cette date doit être :
- postérieure à celle de la dernière entrée ;
- postérieure à celle de la dernière sortie ;
- et au plus, égale à aujourd'hui.
Private
Sub
txtDate_AfterUpdate
(
)
'la date doit être postérieure à la dernière entrée et à la date de dernière sortie
If
Me.txtDate
<=
DMax
(
"EntreeDate"
, "tEntrees"
, "tArticlesFK="
&
Me.CboArticle
) Then
MsgBox
"La date doit être postérieure à la dernière entrée de cet article"
txtDate =
Null
Exit
Sub
Else
If
Me.txtDate
<=
DMax
(
"SortieDate"
, "tSorties"
, "tArticlesFK="
&
Me.CboArticle
) Then
MsgBox
"La date doit être postérieure à la dernière sortie de cet article"
txtDate =
Null
Exit
Sub
Else
DoCmd.GoToControl
"txtQuant"
End
If
End
If
End
Sub
et
- L'utilisateur complète la quantité et le prix unitaire et clique sur
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
Private
Sub
btEnregistrer_Click
(
)
Dim
AvantDernDate As
Date
Dim
AvantDernCMUP As
Double
Dim
StockFinal As
Double
Dim
dCMUP As
Double
Dim
sSql As
String
'Est-ce complet ?
If
IsNull
(
Me.txtDate
) Or
Nz
(
Me.txtQuant
, 0
) =
0
Or
Nz
(
Me.txtPU
, 0
) =
0
Then
MsgBox
"Un des champs obligatoires n'est pas rempli"
, vbCritical
Exit
Sub
End
If
'Déterminer les éléments pour le calcul du CMUP
'AvantDernDate : date de l'entrée précédente
AvantDernDate =
Nz
(
DLookup
(
"EntreeDate"
, "rAvantDernEntree"
), Me.txtDate
)
If
AvantDernDate =
Me.txtDate
Then
dCMUP =
Me.txtPU
GoTo
MajtEntrees
End
If
'AvantDernCMUP : CMUP après l'entrée précédente
AvantDernCMUP =
DLookup
(
"CMUP"
, "rAvantDernEntree"
)
'Stock final : stock après cette dernière entrée
StockFinal =
StockADate
(
Me.CboArticle
, Format
(
Date
, "mm/dd/yyyy"
)) +
Me.txtQuant
' Calcul CMUP
dCMUP =
StockADate
(
Me.CboArticle
, Format
(
Date
, "mm/dd/yyyy"
)) *
AvantDernCMUP +
Me.txtQuant
*
Me.txtPU
dCMUP =
dCMUP /
StockFinal
MajtEntrees
:
sSql =
"INSERT INTO tEntrees ( EntreeDate, EntreeQuant, EntreePU, tArticlesFK, CMUP ) "
_
&
"SELECT #"
&
Format
(
Me.txtDate
, "mm/dd/yy"
) &
"# AS Expr1,"
_
&
Replace
(
Me.txtQuant
, ","
, "."
) &
" AS Expr2, "
_
&
Replace
(
Me.txtPU
, ","
, "."
) &
" AS Expr3, "
_
&
Me.CboArticle
&
" As Expr4, "
_
&
Replace
(
dCMUP, ","
, "."
) &
" as Expr5;"
DoCmd.SetWarnings
False
DoCmd.RunSQL
sSql
DoCmd.SetWarnings
True
'Remettre à zéro
Me.txtDate
=
Null
: Me.txtQuant
=
Null
: Me.txtPU
=
Null
Me.CTNRsfEntreesDetail.Requery
Me.txtStock
=
StockADate
(
Me.CboArticle
, Format
(
Date
, "mm/dd/yyyy"
))
End
Sub
V. Alimenter la table des sorties▲
- L'utilisateur choisit un article dans la liste déroulante.
- S'affiche alors l'historique des sorties dans l'ordre chronologique décroissant (en fait le sous-formulaire sfSortiesDetail)
- Introduction de la date de la nouvelle sortie. Pour respecter la méthode CMUP, cette date doit être :
- postérieure à celle de la dernière entrée ;
- postérieure à celle de la dernière sortie ;
- et au plus, égale à aujourd'hui.
Private
Sub
txtDate_AfterUpdate
(
)
'la date doit être postérieure ou au moins égale à la dernière entrée
If
Me.txtDate
<
Me.txtDernEntree
Then
MsgBox
"La date doit être égale ou postérieure à la dernière entrée de cet article"
txtDate =
Null
Else
DoCmd.GoToControl
"txtQuant"
End
If
End
Sub
et
- L'utilisateur complète la quantité et clique sur
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
Private
Sub
btEnregistrer_Click
(
)
Dim
sSql As
String
'Est-ce complet ?
If
IsNull
(
Me.txtDate
) Or
Nz
(
Me.txtQuant
, 0
) =
0
Or
Nz
(
Me.txtImputation
, 0
) =
0
Then
MsgBox
"Un des champs obligatoires n'est pas rempli"
, vbCritical
Exit
Sub
End
If
'Maj tSorties
sSql =
"INSERT INTO tSorties ( SortieDate, SortieQuant, SortieImputation, CMUP, tArticlesFK ) "
_
&
"SELECT #"
&
Format
(
Me.txtDate
, "mm/dd/yy"
) &
"# AS Expr1, "
_
&
Replace
(
Me.txtQuant
, ","
, "."
) &
" AS Expr2, "
_
&
""""
&
Me.txtImputation
&
""" AS Expr3, "
_
&
Replace
(
Me.txtCMUP
, ","
, "."
) &
" AS Expr4, "
_
&
Me.CboArticle
&
" As Expr5;"
DoCmd.SetWarnings
False
DoCmd.RunSQL
sSql
DoCmd.SetWarnings
True
'Réinitialiser pour une nouvelle sortie éventuelle
Me.CTNRsfSortiesDetail.Requery
Me.txtDate
=
Null
: Me.txtQuant
=
Null
: Me.txtImputation
=
Null
Me.txtStock
=
StockADate
(
Me.CboArticle
, Format
(
Date
, "mm/dd/yyyy"
))
End
Sub
Lignes | Commentaire |
4=>5 | On vérifie la présence d'une date, d'une quantité et d'une imputation non nulles. Sinon, message d'alerte et blocage. |
9=>18 | On construit une requête « Ajout » pour insérer la nouvelle sortie dans tSorties. Remarquez aux lignes 11 et 13 le reformatage (un point comme symbole décimal au lieu de la virgule). |
22 | Même remarque que plus haut, pour le format Me.txtStock = StockADate ( Me.CboArticle , Format ( Date , "mm/dd/yyyy" )) |
VI. Et la suite ?▲
Voilà pour l'aspect valorisation de l'inventaire au CMUP, reste à développer les différentes fonctionnalités que l'on juge utiles dans le cadre d'une application :
contrôle des inventaires ;
calcul des prix de revient de la fabrication ;
statistiques d'achat et de vente...
VII. Télécharger▲
La base de données qui m'a servi à tester est ici.