<?php
/*
fonctions de calcul des besoins : 
la structure des tables a changé. voici la structure pour cette version :
-- Structure de la table `mrpbesoins`
CREATE TABLE IF NOT EXISTS `mrpbesoins` (
  `artCode` varchar(15) NOT NULL,
  `besDate` date NOT NULL,
  `besQte` int(9) NOT NULL,
  `besType` varchar(2) NOT NULL,
  `besRef` varchar(15) NOT NULL COMMENT 'origine du besoin (cc, op, ...)+num',
  `besLevel` int(1) NOT NULL COMMENT 'niveau du besoin 1=pf, n=mp',
  KEY `mrpbesoins_ibfk_1` (`artCode`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='besoins calcules';

-- Contraintes pour la table `mrpbesoins`
ALTER TABLE `mrpbesoins`
  ADD CONSTRAINT `mrpbesoins_ibfk_1` FOREIGN KEY (`artCode`) REFERENCES `article` (`artCode`);

-- Structure de la table `mrpressources`
CREATE TABLE IF NOT EXISTS `mrpressources` (
  `artCode` varchar(15) NOT NULL,
  `resDate` date NOT NULL,
  `resQte` int(9) NOT NULL,
  `resType` varchar(2) NOT NULL,
  `resRef` varchar(15) NOT NULL COMMENT 'origine de la ressource (cf, bp, of, oa, ...)+num',
  `resLevel` int(1) NOT NULL COMMENT 'niveau de besoin 1=pf, n=matière',
  KEY `mrpressources_ibfk_1` (`artCode`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='ressources calculees';

ALTER TABLE `mrpressources`
  ADD CONSTRAINT `mrpressources_ibfk_1` FOREIGN KEY (`artCode`) REFERENCES `article` (`artCode`);

  les changements portent sur l'interprétation de resType/besType :
	ici = bf, bp, cc, cf, etc...
	new = 1=ferme, 4=prev et ajout d'un champ resOrig/besOrig qui reprend l'ancien rôle
*/
/*
	états des commandes : 
	0= nouvelle=devis, 1=commande ferme, 2=livrée, 4=facturée, 8=payée, 16=terminée, 32=annulée
		pflc **	pflC **	pfLc **	pfLC **		
		0000  0	0001  1	0010  2	0011  3	
		0100  4	0101  5	0110  6	0111  7	Fac
		1000  8	1001  9	1010 10	1011 11		Pay = payée non facturée = impossible
		1100 12	1101 13	1110 14	1111 15	Fac	Pay
	0=new/devis, 1=invoice, 2=part.shipped, 3=shipped, 4=billed, 7=done, 9=cancel
	A FAIRE : faire la gestion du stock : 
	-	afficher si le stock est suffisant ou non dans les lignes et, 
		dans ce cas, envoyer un petit script qui interdit l'expédition globale 
		(la facturation devra rester possible si on peut facturer avent d'expédier ...)
	- 	inscrire les mouvements de stock correspondants et, 
		si la base de données est adaptée, modifier le stock dynamique courant de chaque article expédier.
		
	A VENIR : 
		- 	gérer les expéditions en plusieurs colis
		-	gérer les expéditions partielles
*/

// ==============================================================================================================
// fonction de calcul des besoins avec la méthode MRP.
// ==============================================================================================================
/* Principe,
	On calcule tous les besoins fermes issus des commandes en cours (non livrées).
	A partir de là, on propose des besoins prévisionnels
	ces besoins prévisionnels sont convertis en ordres prévisionnels.
	
	Les ordres prévisionnels seront alors regroupés et serviront au calcul suivant....
*/
function _initBesoins(){
// met en place les besoins fermes dans les besoins
}
function _initRessources(){
// met en place les ordres lancés dans les ressources
}
function MRP_calculMRP() {
global $connexion;
	$errNum=0;
	
// ==Passe 1 : Calcul des besoins de produits finis  ====================================
/* revoir l'algo : 
	passe initiale
	e0 vider les données inutiles = mrbbesoins et mrpressources
	e1 transformer les besoins brut fermes en besoins mrp à écrire dans mrpbesoins
	e2 calculer les ressources théoriques
	e3 transformer ces ressources théoriques en besoins via les nomenclatures
	
	passe n°1
	
*/
// ETAPE 0 : RAZ du calcul : vider la table des besoins ----------------------------------
	$clearSQL="TRUNCATE TABLE mrpbesoins ;";
	DB_executerRequete($clearSQL, $connexion);
	$clearSQL="TRUNCATE TABLE mrpressources ;";
	DB_executerRequete($clearSQL, $connexion);
// ETAPE 1 : calcul des besoins fermes ----------------------------------
	// A BIG MARVELOUS QUERY !!!
	// BB besoins brut ----------------------------------------------------------------------------------------------------------
	// bcc : Besoins de commandes client en cours (toutes commandes non livrées = )
	$BBccSQL="Select lignecdeclientart.artCode AS artCode, cdeDate AS date, qte AS qte, 'bc' AS type
	FROM article, lignecdeclientart, cdeclient 
	WHERE article.artCode=lignecdeclientart.artCode
	AND lignecdeclientart.cdeNum=cdeclient.cdeNum
	AND ligneEtat in (0,1,4,5,8,9,12,13) 
	AND artTypeCode in ('F', 'N')
	"; // besoins client	
	// bof : besoins pour ordres de fabrication
/* Ici, on utilise la date de début de l'opération de l'OF pour caler le besoin. 
   Dans la partie laissée active (+loin) on utilise la date de début de l'OF, comme si toutes les matières devrait toutes être présentes en début d'OF
	$BBofSQL="SELECT ofComp_artCode AS besArtCode, ofGamme.opDateDeb AS besDate, (ofQteTheo) AS besQte, 'of' AS besType
	FROM ofNomenclature, ofGamme
	WHERE ofNomenclature.ofNum=ofGamme.ofNum
	AND ofNomenclature.opNum=ofGamme.opNum "; // besoins issus des OF
*/
	$BBofSQL="Select ofComp_artCode AS artCode, ofDateDeb AS date, (ofQteTheo) AS qte, 'bf' AS type
	FROM article, ofnomenclature, ordfab
	WHERE article.artCode=ofnomenclature.ofComp_artCode
	AND ofnomenclature.ofNum=ordFab.ofNum 
	AND artTypeCode in ('F', 'N')
	"; // besoins issus des OF

	// OL Ordres Lancés = ressources réelles attendues ---------------------------------------------------------------------------
	// rcf : ressource commandes fournisseur (non encore livrées !!! A FAIRE)
	$OLcfSQL="SELECT lignecdefourart.artCode AS artCode,  cdeDate AS date, qte AS qte, 'rc' AS type 
	FROM article, lignecdefourart, cdefour
	WHERE article.artCode=lignecdefourart.artCode
	AND lignecdefourart.cdeNum=cdeFour.cdeNum 
	AND artTypeCode in ('F', 'N')
	"; // commandes fournisseur
	// ressource ordre de fabrication en cours
	$OLofSQL="SELECT ordfab.artCode AS artCode, ofDateFin AS date, ofQte AS qte, 'rf' AS type
	FROM article, ordfab 
	WHERE article.artCode=ordfab.artCode
	AND artTypeCode in ('F', 'N')
	"; // ordres de fabrication

	// BB mrp calculés : y en a pas encore ... (ressources théoriques calculées) -----------------------------------------------------------
	$BBmrpSQL="Select mrpbesoins.artCode AS artCode, besDate AS date, besQte AS qte, 'bb' AS type
	FROM article.mrpBesoins 
	WHERE article.artCode=mrpbesoins.artCode
	AND artTypeCode in ('F', 'N')
	"; // besoins calculés	

	$theBigQuery=$BBccSQL." UNION ".$BBofSQL." UNION ".$OLcfSQL." UNION ".$OLofSQL." ORDER BY artCode, date ;";
	$theBigQuery_id=DB_ouvrirRequete($theBigQuery, $connexion);
	echo "DBG : ".mysql_error();
	$theBigQueryNbRow=mysql_num_rows($theBigQuery_id);

	/* 	Bon! on a une table qui a deux ruptures : l'article et la date.
		Le problème c'est qu'on peut avoir plusieurs lignes de BB ou OL pour un même article et une même date ...
		Il faut donc les additionner jusqu'à ce qu'on passe à la date (ou l'article suivant).
		A ce moment là seulement, on peut écrire la ligne dans le code html.
		
		L'algo ressemble donc à ceci : 
		TQ non EOT Faire :
			Si on change de date ou d'article, on écrit la ligne en cours
			Si on a une nouvelle date, on prépare une ligne de date qui deviens la date en cours.
			Si on a un nouvel article, on écrit une ligne spéciale d'entête d'article qui devient l'article en cours.
			On accumule les BB et le OL
		Fin TQ
		Si on a une ligne en cours, on l'écrit
	*/
	$currentArtCode="";
	$currentDate="";
	$compNbr=0;
	//$opOpen=false;
	$insert=false;	// on n'a encore rien ajouté dans les ressources
	$stockMini=5;
	$SPQty=$BBQty=$OLQty=$BPQty=0;
	// $theBigQuery_id2=DB_ouvrirRequete($theBigQuery, $connexion); // déjà fait
	// $tbqNbRow=mysql_num_rows($theBigQuery_id2);					// déjà fait
	// les besoins sont condensés par date et écrits comme des propositions de ressources.
	while ($t_tbq=DB_lireLigne($theBigQuery_id)){
		// D'abord terminer la ligne en cours si on change de code article ou de date
		if ($t_tbq['artCode']!=$currentArtCode || $t_tbq['date']!=$currentDate){ // nouvelle date ou nouvel article, finir la ligne en cours
			if ($BBQty+$OLQty+$BPQty>0){ // Si il y a une quantité à écrire, la ligne en cours
				// calcul des ordres prévisionnels (ce sont eux qui sont à planifier, pas le besoin net ...)
				// ST ------	reprise du stock de la ligne précédente (si même article ...)
					$STQty=$SPQty;	// attention, ce SPQty est celui de la ligne précédente !!!
				// BN ------ on ne tient pas compte des notions de lot ou de multiple ; 
					// le stock réellement dispo est le stock au-delà du stock mini (sécu ou point de commande) donc -(STQty-stockMini)
					$BNQty=$BBQty+$BPQty-$OLQty-$STQty+$stockMini;
					if ($BNQty<0) $BNQty=0;
					if ($BNQty<0) $BNQty=0;
				// OP ------	calcul des ordres prévisionnels
					$OPQty=$BNQty;	// pour l'instant pas de calcul, on reprend le BN
				// SP ------ 	calcul du stock prévisionnel avec les besoins calculés pour la prochaine rotation ...
					$SPQty=$STQty-$BBQty-$BPQty+$OLQty+$OPQty;
				
				// écriture des ordres prévisionnels à lancer dans le fichier mrpRessources
				$besSQL= "INSERT INTO mrpressources (resType, artCode, resDate, resQte, resLevel) VALUES ('4', '$currentArtCode', '$currentDate', $OPQty, '1');";
				DB_executerRequete($besSQL, $connexion);
				// echo "DBG : ".mysql_error();
				
				// RAZ des compteurs
				$STQty=$BBQty=$BPQty=$OLQty=$BNQty=$OPQty=0; // $SPQty ne doit pas être RAZ, on en a besoin au prochain tour ...
				
			}
		}
		if ($t_tbq['artCode']!=$currentArtCode){  // NEW item, écrire la première ligne du nouvel article [ok au 04/01/2015]
			$currentArtCode=$t_tbq['artCode'];
			$t_article=_getArticle($t_tbq['artCode']); // c'est le premier SPQty
			$SPQty=$t_article['stockInit']; // c'est le premier SPQty
			$stockMini=$t_article['artStockMini']; // c'est le premier stockMini
			$currentDate=""; // pour être en situation de nouvelle date au test de la date
		}
		if ($t_tbq['date']!=$currentDate){ // nouvelle date, préparer l'accumulation des quantités
			$currentDate=$t_tbq['date'];
		}
		
		// comptabiliser le mouvement courant : besoin ou ressource
		switch ($t_tbq['type']) {	// selon que le type de ligne est un besoin, une ressource ou le résultat d'un calcul (4=previ)
			case 'bc' :
			case 'bf' :
				$BBQty=$BBQty+$t_tbq['qte']; break; 	// incrémenter les besoins
			case 'rc' :
			case 'rf' :
			case 'rp' :
				$OLQty=$OLQty+$t_tbq['qte']; break;	// incrémenter les ressources (fermes ou issues du calcul mrp)
			case 'bp' :
				$BPQty=$BPQty+$t_tbq['qte']; break;	// incrémenter les besoins calculés (c'est une ressource prévisionnelle)
		}
	} // Fin de la lecture de la maousse requête
			if ($BBQty+$OLQty+$BPQty>0){ // il y a une quantité à écrire, finir la ligne courante
				// calcul des données
				// ST ------	reprise du stock de la ligne précédente (si même article ...)
					$STQty=$SPQty;	// attention, ce SPQty est celui de la ligne précédente !!!
				// BN ------ on ne tient pas compte des notions de lot ou de multiple ; 
					// le stock réellement dispo est le stock au-delà du stock mini (sécu ou point de commande) donc -(STQty-stockMini)
					$BNQty=$BBQty+$BPQty-$OLQty-$STQty+$stockMini;
					if ($BNQty<0) $BNQty=0;
					if ($BNQty<0) $BNQty=0;
				// OP ------	calcul des ordres prévisionnels
					$OPQty=$BNQty;	// pour l'instant pas de calcul, on reprend le BN
				// SP ------ 	calcul du stock prévisionnel avec les besoins calculés plus besoin
				//	$SPQty=$STQty-$BBQty-$BPQty+$OLQty+$OPQty;
				
				// écriture de la quantité à lancer dans le fichier mrpBesoins /!\ il peut y avoir plusieurs lignes !!!
				if ($OPQty >0){
					$resRef=$t_tbq['type'].".".$t_tbq['artCode'];
					$besSQL= "INSERT INTO mrpressources (resType, artCode, resDate, resQte, resRef, resLevel) VALUES ('rp', '$currentArtCode', '$currentDate', $OPQty, 1);";
					DB_executerRequete($besSQL, $connexion);
					// echo mysql_error();
					$insert=true;	// on a ajouté quelque chose
				}
			}
// ETAPE 2 : propagation des besoins calculés au long des nomenclatures ----------------------------------
//	calcul des OP (ordres prévisionnels) => mrpressources
// on reprend les OP, on les transforme en besoins mrp via les nomenclatures. donc une ressource peut devenir plusieurs besoins
	$OPSQL="SELECT * FROM mrpressources ;";
	$OPSQL_id=DB_executerRequete($OPSQL, $connexion);
	while ($t_OP=DB_lireLigne($OPSQL_id)){
		//$t_art=_getArt($t_OP['artCode']); // récup de l'article pour savoir s'il est un composé d'une nomenclature
		$besLevel=$t_OP['resLevel'];
		$besRef="bp.".$t_OP['artCode'];
		$nomSQL="SELECT * FROM artnomenclature WHERE  artCode = '".$t_OP['artCode']."' ;";
		$nomSQL_id=DB_executerRequete($nomSQL, $connexion);
		//if (DB_getNbEnreg($nomSQL_id)>0){
			while ($t_nom=DB_lireLigne($nomSQL_id)){
				$BPmrpQty=$t_OP['resQte']*$t_nom['compQte'];
				$BPSate=$t_OP['resDate'];
				$besNomSQL= "INSERT INTO mrpbesoins (besType, artCode, besDate, besQte, besRef, besLevel) VALUES ('bp', '".$t_nom['comp_artCode']."', '".$BPSate."', $BPmrpQty, $besRef, $besLevel);";
				DB_executerRequete($besNomSQL, $connexion);
				echo "DBG : ".mysql_error();
			}
		//}
	}
/*
*/
// ==Passe 1 : Calcul des besoins de produits finis  ====================================

	return $errNum;
}
// --------------------------------------------------------------------------------------------------------------------
// ===================================================================================================
?>
