1 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 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
| PROCEDURE calculBesoinsNets(aid est un entier = 0)
SI aid = 0 ALORS
// premier appel de la procédure avec argument aid = 0
// purge des tables qui vont contenir les propositions (OF, OA, OP positionnées dans le temps, et nomenclature d'OF)
// dans une structure de tableau d'objets références avec propriétés de rang dans la nomenclature
// je mets l'ensemble A des articles qui ont un besoin "brut" (commande, prévision, stock sécu, sont composants de nomenclature d'OF insuffisamment approvisionnés)
// et je mets les composants de nomenclatures des articles de A dans ce même tableau de références
// en même temps que j'alimente le tableau, je m'arrange pour associer à chaque article son rang de nomenclature le plus élevé (le plus profond dans l'arbre)
// et je trie le tableau par ordre croissant du rang de nomenclature des articles
// ça me permet de lancer le véritable calcul CBN en ne parcourant le tableau qu'une seule fois, de façon ascendante
POUR chaque element A du tableau T
calculBesoinsNets(A)
FIN
SINON
// pour un article donné
// on part de son stock virtuel initial (avant même d'avancer dans le temps)
// on calcule toutes les entrées/sorties pour la période avant aujourd'hui strictement (aujourd'hui exclu)
// stock = stock actuel + qté au contrôle + réceptions OA (existants ET proposés) en retard mais dues (échéance de livraison < aujourd'hui)
// + réceptions OF (existants et proposés) en retard mais dues (échéance de l'ordre < aujourd'hui)
// - stock secu - retard de livraison de commandes client (délai de livraison < aujourd'hui)
// - besoin en composants sur des opérations en retard d'OFs parents (existants ET proposés)
// ????? est-ce qu'on s'occupe de la prévision pour le stock virtuel initial ??????
// => option choisie : les prévisions passées non complètement honorées n'ont pas d'impact sur le CBN
// calcul du stock virtuel initial
stock_virtuel est un numérique = stockVirtuelInitial(aid)
balance_jour est un numérique
// on récupère dans l'article, les infos de stock sécu, politique d'appro, etc...
HFiltre(art, art_id, hValMin, hValMax, "art_id = " + aid)
HLitPremier(art)
stock_secu est un numérique = art.art_stock_secu
gamme_correcte est un numérique = art.art_gamme_nmcl_correcte
politique est un entier = art.art_appro
periode est un entier = art.art_periode_appro
taille_de_lot est un entier = art.art_lot_appro
delai_appro est un entier = art.art_delai_appro
HDésactiveFiltre(art)
q est un numérique
p est un numérique = 0
echeance est une Date
flag est un entier = 0
dTemp est une Date = DateDuJour()
dTemp..Jour -= 1 // hier
// en fonction de la politique de réappro
// - si égal au besoin : à chaque fois qu'on passe en négatif on génère une proposition
// et on va comme ça jusqu'au bout de l'horizon
// - si par lots : on attend de dépasser la taille de lot pour générer la proposition
// et on relance le cbn sur le même article
// si on atteint l'horizon avant de dépasser la taille de lot
// on fait quand même une dernière proposition égale à la taille de lot mais on ne relance pas le CBN
// si par période : on attend de passer en négatif pour entamer la période
// (cela marque la date d'échéance de l'ordre qui sera proposé)
// et on déroule la période (ou bien on atteint l'horizon)
// si la période est atteinte, on génère une proposition et on relance le CBN sur le même article
// si on atteint l'horizon avant la période, on génère une proposition mais on ne relance pas le CBN
//
// ON AVANCE JOUR PAR JOUR (jusqu'à atteindre l'horizon saisi dans l'interface)
// ON commence à la date de "hier"
q = stock_secu - stock_virtuel
TANTQUE dTemp <= SAI_horizon
SI q > 0 ALORS
// on marque le date de début du besoin (pour les politiques d'appro par lot et par période)
SI flag = 0 ALORS
echeance = dTemp
flag = 1
p++ // on entame la période que dont on souhaite couvrir le besoin (si politique par période)
FIN
SI flag = 1 ALORS
p++
FIN
SELON politique
CAS 1: // égal au besoin
// on génère une proposition de qté = q pour échéance = dtemp
// ça permet juste de remettre le stock au niveau du stock sécu
// potentiellement, il est possible que dès le lendemain le stock soit déja consommé et nécessite un réappro
// auquel cas, la politique d'appro est mal choisie, il faut passer en appro par période (et déterminer la période)
// ou par lot (avec lot dimensionné suffisamment grand pour couvrir le besoin d'une période à déterminer)
PROPOSE(aid, dTemp, q, Val(gamme_correcte), delai_appro)
CAS 2: // par lot
SI (q >= taille_de_lot) ALORS
// on génère n propositions avec q = taille_de_lot pour échéance = date où le besoin a commencé a être identifié mais inférieur au lot
nb = ArrondiSupérieur(PartieEntière(q / taille_de_lot))
POUR i = 1 _A_ nb
PROPOSE(aid, echeance, taille_de_lot, Val(gamme_correcte), delai_appro)
FIN
// et on relance le CBN sur le même article pour détecter un éventuel autre besoin (ultérieur) et générer un nouveau lot
SI dTemp < SAI_horizon ALORS
calculBesoinsNets(aid)
FIN
RETOUR // pas besoin d'aller plus loin
SINON
SI dTemp = SAI_horizon ET q > 0 ALORS
// on a atteint l'horizon et on a quand même un besoin (inférieur à la taille de lot)
// on génère quand même une proposition de qté = taille_de_lot pour échéance = début du besoin
PROPOSE(aid, echeance, taille_de_lot, Val(gamme_correcte), delai_appro)
FIN
// sinon on ne fait rien
// la taille de lot n'est pas atteinte et on n'est pas au bout de l'horizon
// on va un jour plus loin
FIN
CAS 3: // par période
SI p = periode ALORS
// on a atteint la période pour laquelle on souhaite couvrir le besoin
// on génère une proposition égale au besoin de la période
PROPOSE(aid, echeance, q, Val(gamme_correcte), delai_appro)
// et on relance le CBN sur le même article pour détecter un éventuel autre besoin dans la période qui suit
SI dTemp < SAI_horizon ALORS
calculBesoinsNets(aid)
FIN
RETOUR // pas besoin d'aller plus loin
SINON
SI dTemp = SAI_horizon ET q > 0 ALORS
// on a atteint l'horizon mais pas la période
// on a quand même un besoin
// on génère quand même une proposition de qté = q pour échéance = début du besoin
// cette proposition couvrira une période inférieure à la période d'appro
// du fait qu'on a atteint l'horizon de calcul du CBN
PROPOSE(aid, echeance, q, Val(gamme_correcte), delai_appro)
FIN
// sinon on ne fait rien
// la période n'est pas atteinte et on n'est pas au bout de l'horizon
// on va un jour plus loin
FIN
AUTRE CAS
FIN
FIN
dTemp..Jour ++
SI dTemp < SAI_horizon ALORS
// puis on calcule l'évolution du stock_virtuel de l'article (pour le jour qui suit)
// en tenant compte des différentes entrées sorties qui peuvent survenir
// livraison de commande, reception d'achat, réception de proposition d'achat
// reception d'of ou de pof
// besoin sur un OF parent (demande à approvisionner en composant aid) ou sur POF
balance_jour = BalanceJour(aid, dtemp)
q -= balance_jour
FIN
FIN // (horizon atteint)
FIN |
Partager