/* En-tête de programme
   ====================
Programme:			Factures.cpp

Acteur:				Alexandre Therrien et Martin Robinsson

Date de création:	25/02/12

But du programme:	Vous devez créer un programme qui permettra le traitement des factures pour
					le magasin chez Ti-Père.  Ce magasin enregistre les informations des factures
					des clients à l’aide d’un lecteur numérique et les données sont stockées dans
					un fichier texte.  Votre programme doit à partir de ces fichiers textes en input
					créer les factures complètes, avec les taxes et les escomptes, prêtes pour
					l’impression dans un autre fichier texte en output.

modification : 27-02-2012 martin robinson
               ajout de ma librairie pour alégé le code
			   formatage de sortie et création de fonction prévu à cet éffet
			   ajout d'une boucle pour que l'utilisateur puisse rédiger plusieurs rapport
			        j'ai déplacé quelque initialisation
			   correction du calcul rabais 
			   correction du calcul des statistique , 
			        initialisation à 0 au lieu de 1
					(int)*100/nbFacture au lieu de (int)/nbFacture*100

/* Directive au pré-processeur
   =========================== */
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>

#include "martinrobinson.hpp"		//27-02-2012 mr

using namespace std;

/* prototype de fonction
   =========================== */

//affiche/ecrit l'entete de la facture
void enteteFacture(ostream & output, 
	               int nbFacture, 
				   string dateFact, 
				   int noClient, 
				   string prenom, 
				   string nom);
//affiche/ecrit les articles de la facture
void articleFacture(ostream & output, 
	                int noArticle, 
					string description, 
					int qty, 
					float prix, 
					float sousTotalArticle , 
					char sel,
					int rabais, 
					float totalArticle);
//affiche/ecrit le pied de la facture
void piedFacture(ostream & output, 
	             float sousTotal, 
				 float tps, 
				 float tvq, 
				 float totalFacture, 
				 int totalQtyArticle, 
				 float totalRabais);
//affiche/ecrit le sommaire des factures
void sommaireFactures(ostream & output, 
	                  string dateFact, 
					  int nbFacture, 
					  int grandTotalQtyArticle, 
					  float grandTotalSansRabais,
					  float grandTotalRabais,
					  float grandTotalTaxes,
					  float grandTotalFacture,
					  int nbClientMembre,
					  int nbClientVip,
					  int nbClientNonMembre);

/* Programme principal
   =================== */
int main()
{
	string dateVente,				// Date de la vente
		   fichierVente,			// Nom du fichier en entée
		   fichierFacture,			// Nom du fichier en sortie
		   nom,						// Nom du client
		   prenom,					// Prénom du client
		   type,					// Type de client
		   description,				// Description de l'article
		   dateFact;				// Date de la facture

	int noClient,					// Numéro du client
		noArticle,					// Numéro de l'article
		nbFacture,				// Compteur de facture
		qty,						// Quantité sur la facture
		nbArticle,					// Nombre d'article différents
		totalQtyArticle,		// Total de quantité d'article
		grandTotalQtyArticle,	// Grand total du nombre d'article
		nbClientMembre,			// Nombre de client membre
		nbClientVip,			// Nombre de client VIP
		nbClientNonMembre;		// Nombre de client non membre

	float prix,						// Prix unitaire de l'article
		  rabais,					// Rabais pour l'article
		  sousTotalArticle,			// Sous-total de l'article
		  totalArticle,				// Prix total de l'article
		  sousTotal,     			// Sous total de la facture
		  tps,						// Montant de TPS
		  tvq,						// Montant de TVQ
		  totalFacture,				// Montant de la facture
		  totalRabais,			    // Montant total des rabais
		  grandTotalSansRabais,     // Grand total des montants des factures sans rabais
		  grandTotalRabais,	        // Grand total des montants des rabais
		  grandTotalTaxes,		    // Grand total des montants des taxes
		  grandTotalFacture;	    // Grand total des montants des factures

	char sel;						// Si l'article est selectionné

	ofstream sortie;	// Déclaration variable ofstream et ouverture du fichier ds même instruction
	ifstream entree;

	do{		//27-02-2012 mr
		//initialisation intraboucle 27-02-2012 mr
		nbFacture = 0,				// Compteur de facture
		grandTotalQtyArticle = 0;	// Grand total du nombre d'article
		nbClientMembre = 0;			// Nombre de client membre
		nbClientVip = 0;			// Nombre de client VIP
		nbClientNonMembre = 0;		// Nombre de client non membre
		grandTotalSansRabais = 0;   // Grand total des montants des factures sans rabais
		grandTotalRabais = 0;		// Grand total des montants des rabais
		grandTotalTaxes = 0;		// Grand total des montants des taxes
		grandTotalFacture = 0;	    // Grand total des montants des factures

		//saisi de la date de facturation et ouverture du fichier lecture
		do
		{
			cout << "Veuillez entrer la date des transaction ( JJ-MM-AAAA ) : " << endl
				 << "\tDate : ";
			cin >> dateVente;
			fichierVente = "vente" + dateVente + ".txt";
		}while(!ouvrirFichierLecture(entree,fichierVente));			//tan qu'il ny a pas de fichier de ce nom //27-02-2012 mr

		//ouverture du fichier ecriture
		fichierFacture = "facture " + dateVente + ".txt";
		sortie.open(fichierFacture);

		//lecture de la premiere ligne et saisie de la date a meme le fichier telque demande
		for(int i=0; i<6; i++)
			entree >> dateFact;
		cout << "La date dans le fichier est : " <<  dateFact << endl;
		
		//lecture de l'infomation sur le client et le nombre d'article
		entree >> noClient >> prenom >> nom >> type >> nbArticle; //27-02-2012 mr
		if (entree.fail())
		{
			cout << endl << "Aucun n'achat n'a \x82t\x82 effectu\x82 pour cette date" << endl;
		}
		else
		{
			while(entree) //tanque le fichier n'est pas termine
			{
				//initialisation intraloop
				sousTotal = 0;
				totalRabais = 0;			// Montant total des rabais
				totalQtyArticle = 0;		// Total de quantité d'article

				//affichage debut de facture
				enteteFacture(cout, 
							  nbFacture, 
							  dateFact, 
							  noClient, 
							  prenom, 
							  nom);  //affichage entete de facture //29-02-2012 mr
				enteteFacture(sortie, 
							  nbFacture, 
							  dateFact, 
							  noClient, 
							  prenom, 
							  nom);  //ecriture entete de facture //29-02-2012 mr

				for (int i = 0; i < nbArticle; i++)  //pour chaque article de la liste
				{
					entree >> noArticle >> description >> qty >> prix >> sel;  //lecture d'information sur l'article

					//calcul du taux de rabais selon l'article selectionné et le statu du client
					if (type == "membre")
						if (sel == 's')
							rabais = 20;
						else
							rabais = 10;
					else if (type == "vip")
						if (sel == 's')
							rabais = 25;
						else
							rabais = 20;
					else
						if (sel == 's')
							rabais = 5;
						else
							rabais = 0;

					//calcul du sous total par article et du total apres rabais
					sousTotalArticle = qty * prix;
					totalArticle = sousTotalArticle - (sousTotalArticle * rabais / 100); //correction 27-02-2012mr


					//accumulateur de la facture , le soustotal , quantité et rabais
					sousTotal = sousTotal + totalArticle;
					totalQtyArticle = totalQtyArticle + qty;
					totalRabais = totalRabais + (sousTotalArticle * rabais /100); //correction 27-02-2012mr

					//afficher/ecrire le corp de la facture
					articleFacture(cout, 
								   noArticle, 
								   description, 
								   qty, 
								   prix, 
								   sousTotalArticle ,
								   sel, 
								   rabais, 
								   totalArticle);		//27-02-2012 mr
					articleFacture(sortie, 
								   noArticle, 
								   description, 
								   qty, 
								   prix, 
								   sousTotalArticle ,
								   sel, 
								   rabais, 
								   totalArticle);		//27-02-2012 mr
				}

				//calcul des taxes
				tps = sousTotal * 0.06;
				tvq = (sousTotal + tps) * 0.075;
				totalFacture = sousTotal + tps + tvq;

				//afficher/ecrire le pied de la facture
				piedFacture(cout, 
							sousTotal, 
							tps, 
							tvq, 
							totalFacture, 
							totalQtyArticle, 
							totalRabais);  //27-02-2012 mr
				piedFacture(sortie, 
							sousTotal, 
							tps, 
							tvq, 
							totalFacture, 
							totalQtyArticle, 
							totalRabais);  //27-02-2012 mr

				//accumulateur du rapport de facturation
				nbFacture = nbFacture + 1;												//numéraux de facture
				grandTotalQtyArticle = grandTotalQtyArticle + totalQtyArticle;			//nombre d'article
				grandTotalSansRabais = grandTotalSansRabais + sousTotal + totalRabais;	//total sans rabais
				grandTotalRabais = grandTotalRabais + totalRabais;						//total des rabais
				grandTotalTaxes = grandTotalTaxes + tps + tvq;							//total des taxes
				grandTotalFacture = grandTotalFacture + totalFacture;					//total avec rabais et taxes
				if (type == "membre")													//statistique du statu membre
					nbClientMembre = nbClientMembre + 1;
				else if(type == "vip")
					nbClientVip = nbClientVip + 1;
				else
					nbClientNonMembre = nbClientNonMembre + 1;

				//prochain article
				entree >> noClient >> prenom >> nom >> type >> nbArticle; //27-02-2012 mr
			}
			sommaireFactures(cout, 
							 dateFact,
							 nbFacture, 
							 grandTotalQtyArticle, 
							 grandTotalSansRabais, 
							 grandTotalRabais,
							 grandTotalTaxes,
							 grandTotalFacture,
							 nbClientMembre,
							 nbClientVip,
							 nbClientNonMembre);		//27-02-2012 mr
			sommaireFactures(sortie, 
							 dateFact,
							 nbFacture, 
							 grandTotalQtyArticle, 
							 grandTotalSansRabais, 
							 grandTotalRabais,
							 grandTotalTaxes,
							 grandTotalFacture,
							 nbClientMembre,
							 nbClientVip,
							 nbClientNonMembre);		//27-02-2012 mr

			entree.close();		//27-02-2012 mr
			sortie.close();		//27-02-2012 mr
		}
	}while(questionOuiNon("voulez-vous rediger un autre rapport ?"));		//27-02-2012 mr
	attendre();		//27-02-2012 mr
	return 0;
}

/* Fonction
   =========================== */

//affiche/ecrit l'entete de la facture
void enteteFacture(ostream & output, 
	               int nbFacture, 
				   string dateFact, 
				   int noClient, 
				   string prenom, 
				   string nom)
{
	output << setprecision(2) << fixed << left << setw (70) << "Magasin chez Ti-Pere" << right << setw(8) << "No : "<< nbFacture << endl
			<< left << setw (69) << "2550 blv. Portland" << right << setw(9) << dateFact << endl
			<< "Sherbrooke, Qc\n"
			<< "(819) 555-7662\n"
			<< "-------------------------------------------------------------------------------\n"
			<< "Client : " << left << setw(15) << noClient << prenom << ' ' << nom << "\n\n"
			<< "    No.Art. Description  Qty    Prix  Sous-Total  Selection   Rabais  Total\n"
			<< "    =======================================================================\n";
}

//affiche/ecrit les articles de la facture
void articleFacture(ostream & output, 
	                int noArticle, 
					string description, 
					int qty, 
					float prix, 
					float sousTotalArticle , 
					char sel,
					int rabais, 
					float totalArticle)
{
	output << setprecision(2) << fixed << "    " << left << setw(8) << noArticle
		   << setw(14) << description
		   << qty
		   << right << setw(9) << prix << '$'
		   << setw(9) << sousTotalArticle << '$'
		   << setw(9) << (sel=='s'?"oui":"non")
		   << setw(9) << rabais << '%' 
		   << setw(8) << totalArticle << '$'
		   << endl;
}

//affiche/ecrit le pied de la facture
void piedFacture(ostream & output, 
	             float sousTotal, 
				 float tps, 
				 float tvq, 
				 float totalFacture, 
				 int totalQtyArticle, 
				 float totalRabais)
{
	output << setprecision(2) << fixed << endl << right << setw (59) << "sous-total : " << setw(15) << sousTotal << "$\n"
		   << setw (59) << "tps : " << setw(15) << tps << "$\n"
		   << setw (59) << "tvq : " << setw(15) << tvq << "$\n"
		   << setw (59) << "total : " << setw(15) << totalFacture << "$\n\n"
		   << setprecision(2) << fixed << " Nb. d'article sur la facture : " << right <<  setw(4) << totalQtyArticle ;

	if (totalRabais != 0)
		output << "Aujourd'hui, vous avez épargné : " << right <<  setw(8) << totalRabais << "$\n";
	else
		output << endl;

	output << "    =======================================================================\n"
		   << right << setw(57) << "Merci d'avoir magasine chez Ti-Pere\n"
		   << "    =======================================================================\n\f\n\n";
}

//affiche/ecrit le sommaire des factures
void sommaireFactures(ostream & output, 
	                  string dateFact, 
					  int nbFacture, 
					  int grandTotalQtyArticle, 
					  float grandTotalSansRabais,
					  float grandTotalRabais,
					  float grandTotalTaxes,
					  float grandTotalFacture,
					  int nbClientMembre,
					  int nbClientVip,
					  int nbClientNonMembre)
{
		output << setprecision(2) << fixed << right << setw(46) << "Sommaire des factures du " << dateFact << "\n"
			   << setw(56) << "===================================" << "\n\n"
				<< setw(42) << "Nombre de factures :" << setw(14) << nbFacture << endl
				<< setw(42) << "Moyenne d'article par client :" << setw(14) << grandTotalQtyArticle / nbFacture <<"\n\n"
				<< setw(42) << "Montant total des factures avant rabais :" << setw(12) << grandTotalSansRabais << " $\n"
				<< setw(42) << "Montant total des rabais :" << setw(12) << grandTotalRabais << " $\n"
				<< setw(42) << "Montant total des taxes :" << setw(12) << grandTotalTaxes << " $\n"
				<< setw(42) << "Montant total avec rabais et taxes :" << setw(12) << grandTotalFacture << " $\n\n"
				<< setw(42) << "Clients membre :" << setw(12) << nbClientMembre*100 / nbFacture << " %\n"
				<< setw(42) << "Clients VIP :" << setw(12) << nbClientVip*100 / nbFacture << " %\n"
				<< setw(42) << "Clients Non-membre :" << setw(12) << nbClientNonMembre*100 / nbFacture << " %\n";
}