def generer(self, trans_vals, paramtexte, dossier_destination, par_plate): """ génération du fichier de bilan des usages à partir des transactions :param trans_vals: valeurs des transactions générées :param paramtexte: paramètres textuels :param dossier_destination: Une instance de la classe dossier.DossierDestination :param par_plate: tri des transactions par plateforme, par item """ ii = 0 for id_plate in par_plate.keys(): par_item = par_plate[id_plate]['items'] for item in par_item.keys(): tbtr = par_item[item] base = trans_vals[tbtr[0]] if base['item-type'] == paramtexte.donnees['item-service']: donnee = [] for cle in range(2, len(self.cles)-1): donnee.append(base[self.cles[cle]]) usage = 0 for indice in tbtr: val, info = Outils.est_un_nombre(trans_vals[indice]['transac-usage'], "l'usage", arrondi=4) if info != "": Outils.affiche_message(info) usage += val donnee += [round(usage, 4)] self.ajouter_valeur(donnee, ii) ii += 1 self.csv(dossier_destination, paramtexte)
def verification_date(self, annee, mois): """ vérifie que le mois et l'année présents sur la ligne sont bien ceux espérés :param annee: année selon paramètres d'édition :param mois: mois selon paramètres d'édition :return: 0 si ok, 1 sinon """ if self.verifie_date == 1: print(self.libelle + ": date déjà vérifiée") return 0 msg = "" position = 1 for donnee in self.donnees: try: if (int(donnee["mois"]) != mois) or (int(donnee["annee"]) != annee): msg += "date incorrect ligne " + str(position) + "\n" except ValueError: msg += "année ou mois n'est pas valable" + str(position) + "\n" position += 1 del self.donnees[0] self.verifie_date = 1 if msg != "": msg = self.libelle + "\n" + msg print("msg : " + msg) Outils.affiche_message(msg) return 1 return 0
def ouvrir_csv_sans_comptes_client(dossier_source, fichier, code_client, comptes, position_id=0): """ ouverture d'un csv comme string sans les données des comptes d'un client donné :param dossier_source: Une instance de la classe dossier.DossierSource :param fichier: nom du fichier csv :param code_client: code du client à ignorer :param comptes: comptes importés :param position_id: position colonne du compte id dans le csv :return: donnees du csv modifiées en tant que string """ donnees_csv = [] try: fichier_reader = dossier_source.reader(fichier) for ligne in fichier_reader: if ligne == -1: continue id_compte = ligne[position_id] if id_compte not in comptes.donnees or comptes.donnees[ id_compte]['code_client'] != code_client: donnees_csv.append(ligne) except IOError as e: Outils.fatal(e, "impossible d'ouvrir le fichier : " + fichier) return donnees_csv
def livraisons_pour_projet_par_categorie(self, num_projet, id_compte, code_client, prestations): """ retourne les livraisons pour un projet donné, pour une catégorie de prestations donnée :param num_projet: lenuméro de projet :param id_compte: l'id du compte :param code_client: le code du client :param prestations: prestations importées et vérifiées :return: les livraisons pour le projet donné, pour une catégorie de prestations donnée """ if prestations.verifie_coherence == 0: info = self.libelle + ". vous devez vérifier la cohérence des prestations avant de pouvvoir sélectionner " \ "les livraisons par catégorie" print(info) Outils.affiche_message(info) return {} donnees_dico = {} for donnee in self.donnees: if (donnee['id_compte'] == id_compte) and (donnee['code_client'] == code_client) \ and (donnee['num_projet'] == num_projet): categorie = prestations.donnees[donnee['id_prestation']]['categorie'] if categorie not in donnees_dico: donnees_dico[categorie] = [] liste = donnees_dico[categorie] liste.append(donnee) return donnees_dico
def creer_latex_pdf(nom_fichier, contenu): """ création d'un pdf à partir d'un contenu latex :param nom_fichier: nom du pdf final :param contenu: contenu latex """ with open(nom_fichier + ".tex", 'w') as f: f.write(contenu) proc = subprocess.Popen(['pdflatex', nom_fichier + ".tex"]) proc.communicate() # 2 fois pour que les longtable soient réguliers (courant de relancer latex) proc = subprocess.Popen(['pdflatex', nom_fichier + ".tex"]) proc.communicate() try: os.unlink(nom_fichier + '.tex') os.unlink(nom_fichier + '.log') os.unlink(nom_fichier + '.aux') except OSError as err: Outils.affiche_message("OSError: {0}".format(err)) except IOError as err: Outils.affiche_message("IOError: {0}".format(err))
def creer_latex_pdf(nom_fichier, contenu, nom_dossier=""): """ création d'un pdf à partir d'un contenu latex :param nom_fichier: nom du pdf final :param contenu: contenu latex :param nom_dossier: nom du dossier dans lequel enregistrer le pdf """ with open(nom_fichier + ".tex", 'w') as f: f.write(contenu) proc = subprocess.Popen(['pdflatex', nom_fichier + ".tex"]) proc.communicate() # 2 fois pour que les longtable soient réguliers (courant de relancer latex) proc = subprocess.Popen(['pdflatex', nom_fichier + ".tex"]) proc.communicate() os.unlink(nom_fichier + '.tex') os.unlink(nom_fichier + '.log') os.unlink(nom_fichier + '.aux') if nom_dossier != '': try: shutil.copy(nom_fichier + ".pdf", nom_dossier) os.unlink(nom_fichier + '.pdf') except IOError: Outils.affiche_message( "Le pdf " + nom_fichier + " est resté ouvert et ne sera pas mis à jour")
def mise_a_jour(edition, clients, dossier_source, dossier_destination, maj, f_html_sections): """ modification des résumés mensuels au niveau du client dont la facture est modifiée :param edition: paramètres d'édition :param clients: clients importés :param dossier_source: Une instance de la classe dossier.DossierSource :param dossier_destination: Une instance de la classe dossier.DossierDestination :param maj: données modifiées pour le client pour les différents fichiers :param f_html_sections: section html modifiée pour le client """ if len(maj) != len(Resumes.fichiers): info = "Résumés : erreur taille tableau" Outils.affiche_message(info) return for i in range(len(Resumes.fichiers)): fichier_complet = Resumes.fichiers[i] + "_" + str(edition.annee) + "_" + \ Outils.mois_string(edition.mois) + ".csv" donnees_csv = Resumes.ouvrir_csv_sans_client( dossier_source, fichier_complet, edition.client_unique, Resumes.positions[i]) with dossier_destination.writer(fichier_complet) as fichier_writer: for ligne in donnees_csv: fichier_writer.writerow(ligne) for ligne in maj[i]: fichier_writer.writerow(ligne) ticket_complet = "ticket_" + str(edition.annee) + "_" + Outils.mois_string(edition.mois) + ".html" section = list(f_html_sections.values())[0] nom_client = clients.donnees[edition.client_unique]['abrev_labo'] + " (" + edition.client_unique + ")" Resumes.maj_ticket(dossier_source, dossier_destination, ticket_complet, section, edition.client_unique, nom_client)
def verification_date(self, annee, mois): """ vérifie que le mois et l'année présents sur la ligne sont bien ceux espérés :param annee: année selon paramètres d'édition :param mois: mois selon paramètres d'édition :return: 0 si ok, 1 sinon """ if self.verifie_date == 1: print(self.libelle + ": date déjà vérifiée") return 0 msg = "" position = 1 for donnee in self.donnees: try: if (int(donnee['mois']) != mois) or (int(donnee['annee']) != annee): msg += "date incorrect ligne " + str(position) + "\n" except ValueError: msg += "année ou mois n'est pas valable" + str(position) + "\n" position += 1 del self.donnees[0] self.verifie_date = 1 if msg != "": msg = self.libelle + "\n" + msg print("msg : " + msg) Outils.affiche_message(msg) return 1 return 0
def __init__(self, dossier_source, nom_fichier, annee, mois): """ initialisation et importation des données :param dossier_source: Une instance de la classe dossier.DossierSource :param nom_fichier: nom du fichier à importer :param annee: année selon paramètres d'édition :param mois: mois selon paramètres d'édition """ self.nom = nom_fichier self.mois = mois self.annee = annee try: fichier_reader = dossier_source.reader(nom_fichier) donnees_csv = [] for ligne in fichier_reader: donnees_csv.append(ligne) self.cles = {} i = 0 for cle in donnees_csv[0]: self.cles[cle] = i i += 1 self.donnees = donnees_csv[1:] self.verifie_date = 0 except IOError as e: Outils.fatal(e, "impossible d'ouvrir le fichier : "+nom_fichier)
def pdfs_pour_client(self, client, type_annexe): """ retourne les pdfs à ajouter en fin d'annexe pour le client :return: pdfs selon position """ if self.verifie_coherence == 0: info = self.libelle + ". vous devez vérifier la cohérence avant de pouvoir obtenir les codes" Outils.affiche_message(info) return [] pdfs = {} for donnee in self.donnees: if donnee['code'] != "" and donnee['code'] != client['code']: continue if donnee['nature'] != "" and donnee['nature'] != client['nature']: continue if donnee[type_annexe] == 'NON': continue if not donnee['position'] in pdfs: pdfs[donnee['position']] = [{ 'chemin': donnee['chemin'], 'nom': donnee['nom'] }] else: pdfs[donnee['position']].append({ 'chemin': donnee['chemin'], 'nom': donnee['nom'] }) return pdfs
def generer(self, trans_vals, paramtexte, dossier_destination, par_plate): """ génération du fichier des usages de labos à partir des transactions :param trans_vals: valeurs des transactions générées :param paramtexte: paramètres textuels :param dossier_destination: Une instance de la classe dossier.DossierDestination :param par_plate: tri des transactions par plateforme, par utilisateur, par client, par jour """ ii = 0 for id_plate in par_plate.keys(): par_user = par_plate[id_plate]['users'] for id_user in par_user.keys(): par_client = par_user[id_user] for code in par_client.keys(): par_jour = par_client[code] for jour in par_jour.keys(): key = par_jour[jour] trans = trans_vals[key] date, info = Outils.est_une_date(trans['transac-date'], "la date de transaction") if info != "": Outils.affiche_message(info) donnee = [] for cle in range(2, len(self.cles)): if self.cles[cle] == 'day': donnee.append(date.day) elif self.cles[cle] == 'week-nbr': donnee.append(date.isocalendar()[1]) else: donnee.append(trans[self.cles[cle]]) self.ajouter_valeur(donnee, ii) ii += 1 self.csv(dossier_destination, paramtexte)
def creation_lignes(subedition, subgeneraux, consolidation): """ génération des lignes de données du bilan :param subedition: paramètres d'édition :param subgeneraux: paramètres généraux :param consolidation: classe de consolidation des données des bilans :return: lignes de données du bilan """ lignes = [] for code_client, client in sorted(consolidation.clients.items()): numbers = {} for id_compte, compte in client['comptes'].items(): numbers[id_compte] = compte['num_compte'] for id_compte, num_compte in sorted(numbers.items(), key=lambda x: x[1]): compte = client['comptes'][id_compte] if compte['subs'] > 0: ligne = [subedition.annee_fin_general, subedition.mois_fin_general, code_client, client['sap'], client['abrev'], client['nom'], client['type'], client['nature'], id_compte, num_compte, compte['intitule'], compte['type'], compte['t3'], Outils.format_2_dec(compte['s-mt'])] for categorie in subgeneraux.codes_d3(): ligne.append(Outils.format_2_dec(compte['s-' + categorie + 't'])) ligne += [Outils.format_2_dec(compte['subs'])] lignes.append(ligne) return lignes
def livraisons_pour_compte_par_categorie(self, id_compte, code_client, prestations): """ retourne les livraisons pour un compte donné, pour une catégorie de prestations donnée :param id_compte: l'id du compte :param code_client: le code du client :param prestations: prestations importées et vérifiées :return: les livraisons pour le projet donné, pour une catégorie de prestations donnée """ if prestations.verifie_coherence == 0: info = self.libelle + ". vous devez vérifier la cohérence des prestations avant de pouvvoir sélectionner " \ "les livraisons par catégorie" Outils.affiche_message(info) return {} donnees_dico = {} for donnee in self.donnees: if (donnee['id_compte'] == id_compte) and (donnee['code_client'] == code_client): categorie = prestations.donnees[ donnee['id_prestation']]['categorie'] if categorie not in donnees_dico: donnees_dico[categorie] = [] liste = donnees_dico[categorie] liste.append(donnee) return donnees_dico
def __init__(self, dossier_source): """ initialisation et importation des données :param dossier_source: Une instance de la classe dossier.DossierSource """ self._chemin = dossier_source.chemin try: fichier_reader = dossier_source.reader(self.nom_fichier) donnees_csv = [] for ligne in fichier_reader: donnees_ligne = self.extraction_ligne(ligne) if donnees_ligne == -1: continue donnees_csv.append(donnees_ligne) self.donnees = donnees_csv except IOError as e: Outils.fatal( e, "impossible d'ouvrir le fichier : " + self.nom_fichier) del self.donnees[0] for donnee in self.donnees: if donnee['nom'] in self.dossiers_annexes: donnee['dossier'] = self.dossiers_annexes[donnee['nom']] else: info = self.libelle + ": nom non-attendu : " + donnee[ 'nom'] + ", pas de nom de dossier " Outils.affiche_message(info) sys.exit("Erreur de consistance")
def calcul_montants(self, prestations, coefprests, comptes, clients, verification): """ calcule le 'montant' et le 'rabais_r' et les ajoute aux données :param prestations: prestations importées et vérifiées :param coefprests: coefficients prestations importés et vérifiés :param comptes: comptes importés et vérifiés :param clients: clients importés et vérifiés :param verification: pour vérifier si les dates et les cohérences sont correctes """ if verification.a_verifier != 0: info = self.libelle + ". vous devez faire les vérifications avant de calculer les montants" print(info) Outils.affiche_message(info) return donnees_list = [] for donnee in self.donnees: prestation = prestations.donnees[donnee['id_prestation']] compte = comptes.donnees[donnee['id_compte']] client = clients.donnees[compte['code_client']] coefprest = coefprests.donnees[client['id_classe_tarif'] + prestation['categorie']] donnee['prix_unit_client'] = round(prestation['prix_unit'] * coefprest['coefficient'], 2) donnee['montant'] = round(donnee['quantite'] * donnee['prix_unit_client'], 2) donnee['rabais_r'] = round(donnee['rabais'], 2) donnees_list.append(donnee) self.donnees = donnees_list
def __init__(self, dossier_source): """ initialisation et importation des données :param dossier_source: Une instance de la classe dossier.DossierSource """ donnees_csv = [] try: for ligne in dossier_source.reader(self.nom_fichier): donnees_csv.append(ligne) except IOError as e: Outils.fatal(e, "impossible d'ouvrir le fichier : "+SuppressionFacture.nom_fichier) num = 4 if len(donnees_csv) != num: Outils.fatal(ErreurConsistance(), SuppressionFacture.libelle + ": nombre de lignes incorrect : " + str(len(donnees_csv)) + ", attendu : " + str(num)) try: self.annee = int(donnees_csv[0][1]) self.mois = int(donnees_csv[1][1]) except ValueError as e: Outils.fatal(e, SuppressionFacture.libelle + "\nle mois et l'année doivent être des nombres entiers") try: self.version = int(donnees_csv[2][1]) except ValueError as e: Outils.fatal(e, SuppressionFacture.libelle + "\nla version doit être un nombre entier") if self.version < 0: Outils.fatal(ErreurConsistance(), SuppressionFacture.libelle + ": la version doit être positive ") self.client_unique = donnees_csv[3][1]
def verification_date(self): """ vérifie que le mois et l'année présents sur la ligne sont bien ceux espérés :return: 0 si ok, 1 sinon """ if self.verifie_date == 1: print(self.nom + ": date déjà vérifiée") return 0 msg = "" position = 1 for donnee in self.donnees: try: if int(donnee[self.cles['mois']]) != self.mois or int(donnee[self.cles['année']]) != self.annee: msg += "date incorrect ligne " + str(position) + "\n" except ValueError: msg += "année ou mois n'est pas valable" + str(position) + "\n" position += 1 self.verifie_date = 1 if msg != "": msg = "L’année et le mois ne correspondent pas à ceux attendus dans " + self.nom Outils.affiche_message(msg) return 1 return 0
def calcul_montants(self, prestations, coefprests, comptes, clients, verification): """ calcule le 'montant' et le 'rabais_r' et les ajoute aux données :param prestations: prestations importées et vérifiées :param coefprests: coefficients prestations importés et vérifiés :param comptes: comptes importés et vérifiés :param clients: clients importés et vérifiés :param verification: pour vérifier si les dates et les cohérences sont correctes """ if verification.a_verifier != 0: info = self.libelle + ". vous devez faire les vérifications avant de calculer les montants" print(info) Outils.affiche_message(info) return donnees_list = [] for donnee in self.donnees: prestation = prestations.donnees[donnee['id_prestation']] compte = comptes.donnees[donnee['id_compte']] client = clients.donnees[compte['code_client']] coefprest = coefprests.donnees[client['id_classe_tarif'] + prestation['categorie']] donnee['prix_unit_client'] = round( prestation['prix_unit'] * coefprest['coefficient'], 2) donnee['montant'] = round( donnee['quantite'] * donnee['prix_unit_client'], 2) donnee['rabais_r'] = round(donnee['rabais'], 2) donnees_list.append(donnee) self.donnees = donnees_list
def verification_date(self, annee, mois): """ vérifie que le mois et l'année présents sur la ligne sont bien ceux espérés :param annee: année selon paramètres d'édition :param mois: mois selon paramètres d'édition :return: 0 si ok, 1 sinon """ if self.verifie_date == 1: print(self.libelle + ": date déjà vérifiée") return 0 msg = "" position = 1 for donnee in self.donnees: donnee['mois'], info = Outils.est_un_entier( donnee['mois'], "le mois ", position, 1, 12) msg += info donnee['annee'], info = Outils.est_un_entier( donnee['annee'], "l'annee ", position, 2000, 2099) msg += info if donnee['mois'] != mois or donnee['annee'] != annee: msg += "date incorrect ligne " + str(position) + "\n" position += 1 del self.donnees[0] self.verifie_date = 1 if msg != "": msg = self.libelle + "\n" + msg Outils.affiche_message(msg) return 1 return 0
def somme_par_categorie(self, comptes): """ calcule les sommes par catégories sous forme de dictionnaire : client->catégorie->clés_sommes :param comptes: comptes importés et vérifiés """ if self.verification.a_verifier != 0: info = "Sommes : vous devez faire les vérifications avant de calculer les sommes" print(info) Outils.affiche_message(info) return if self.sco != 0: spca = {} for code_client, spco_cl in self.sommes_comptes.items(): if code_client not in spca: spca[code_client] = {} spca_cl = spca[code_client] for id_compte, spco_co in spco_cl.items(): cat = comptes.donnees[id_compte]['categorie'] if cat not in spca_cl: spca_cl[cat] = self.nouveau_somme(Sommes.cles_somme_categorie) somme = spca_cl[cat] somme['somme_k_ai'] += spco_co['somme_j_ai'] somme['somme_k_bi'] += spco_co['somme_j_bi'] somme['somme_k_ci'] += spco_co['somme_j_ci'] somme['somme_k_oi'] += spco_co['somme_j_oi'] somme['somme_k_mai'] += spco_co['somme_j_mai'] somme['somme_k_moi'] += spco_co['somme_j_moi'] somme['somme_k_dsi'] += spco_co['somme_j_dsi'] somme['somme_k_dhi'] += spco_co['somme_j_dhi'] somme['somme_k_mm'] += spco_co['somme_j_mm'] somme['somme_k_mr'] += spco_co['somme_j_mr'] somme['mk'] += spco_co['mj'] for categorie in self.categories: somme['sommes_cat_m'][categorie] += spco_co['sommes_cat_m'][categorie] somme['sommes_cat_r'][categorie] += spco_co['sommes_cat_r'][categorie] somme['tot_cat'][categorie] += spco_co['tot_cat'][categorie] # print("") # print("spca") # for code in spca: # if code != "220208": # continue # print(code) # spca_cl = spca[code] # for cat in spca_cl: # somme = spca_cl[cat] # print(" ", cat, somme['somme_k_mai']) self.sca = 1 self.sommes_categories = spca else: info = "Vous devez d'abord faire la somme par compte, avant la somme par catégorie" print(info) Outils.affiche_message(info)
def est_coherent(self, subsides, generaux): """ vérifie que les données du fichier importé sont cohérentes :param subsides: subsides importés :param generaux: paramètres généraux :return: 1 s'il y a une erreur, 0 sinon """ if self.verifie_coherence == 1: print(self.libelle + ": cohérence déjà vérifiée") return 0 msg = "" ligne = 1 donnees_dict = {} couples = [] del self.donnees[0] for donnee in self.donnees: if donnee['type'] == "": msg += "le type de la ligne " + str( ligne) + " ne peut être vide\n" elif subsides.contient_type(donnee['type']) == 0: msg += "le type '" + donnee['type'] + "' de la ligne " + str(ligne) \ + " n'est pas référencé\n" if donnee['code_d'] == "": msg += "la code D de la ligne " + str( ligne) + " ne peut être vide\n" elif donnee['code_d'] not in generaux.obtenir_code_d(): msg += "la code D de la ligne " + str( ligne) + " n'existe pas dans les codes D\n" couple = [donnee['type'], donnee['code_d']] if couple not in couples: couples.append(couple) else: msg += "Couple type '" + donnee['type'] + "' et code D '" + \ donnee['code_d'] + "' de la ligne " + str(ligne) + " pas unique\n" donnee['max_mois'], info = Outils.est_un_nombre( donnee['max_mois'], "le max mensuel", ligne, 2, 0) msg += info donnee['max_compte'], info = Outils.est_un_nombre( donnee['max_compte'], "le max compte", ligne, 2, 0) msg += info donnees_dict[donnee['type'] + donnee['code_d']] = donnee ligne += 1 self.donnees = donnees_dict self.verifie_coherence = 1 if msg != "": msg = self.libelle + "\n" + msg Outils.affiche_message(msg) return 1 return 0
def calcul_montants(self, machines, coefmachines, comptes, clients, verification): """ calcule les montants 'pv' et 'qv' et les ajoute aux données :param machines: machines importées et vérifiées :param coefmachines: coefficients machines importés et vérifiés :param comptes: comptes importés et vérifiés :param clients: clients importés et vérifiés :param verification: pour vérifier si les dates et les cohérences sont correctes """ if verification.a_verifier != 0: info = self.libelle + ". vous devez faire les vérifications avant de calculer les montants" print(info) Outils.affiche_message(info) return donnees_list = [] for donnee in self.donnees: id_compte = donnee['id_compte'] compte = comptes.donnees[id_compte] code_client = compte['code_client'] id_machine = donnee['id_machine'] machine = machines.donnees[id_machine] client = clients.donnees[code_client] coefmachine = coefmachines.donnees[client['id_classe_tarif'] + machine['categorie']] duree_fact_hp, duree_fact_hc = Rabais.rabais_reservation(machine['delai_sans_frais'], donnee['duree_ouvree'], donnee['duree_hp'], donnee['duree_hc']) if code_client not in self.sommes: self.sommes[code_client] = {'comptes': {}, 'machines': {}} scl = self.sommes[code_client] if id_compte not in scl['comptes']: scl['comptes'][id_compte] = {} sco = scl['comptes'][id_compte] if id_machine not in sco: sco[id_machine] = {'res_hp': 0, 'ann_hp': 0, 'res_hc': 0, 'ann_hc': 0} if donnee['si_supprime'] == 'OUI': sco[id_machine]['ann_hp'] += duree_fact_hp sco[id_machine]['ann_hc'] += duree_fact_hc else: sco[id_machine]['res_hp'] += duree_fact_hp sco[id_machine]['res_hc'] += duree_fact_hc if id_machine not in scl['machines']: pu_hp = round(coefmachine['coef_r'] * machine['t_h_reservation_hp'], 2) pu_hc = round(coefmachine['coef_r'] * machine['t_h_reservation_hc'], 2) scl['machines'][id_machine] = {'pu_hp': pu_hp, 'pu_hc': pu_hc} donnee['duree_fact_hp'] = duree_fact_hp donnee['duree_fact_hc'] = duree_fact_hc donnees_list.append(donnee) self.donnees = donnees_list
def creation_annexes(sommes, clients, edition, livraisons, acces, machines, reservations, prestations, comptes, dossier_annexe, plateforme, prefixe, coefprests, coefmachines, generaux, garde): """ création des annexes techniques :param sommes: sommes calculées :param clients: clients importés :param edition: paramètres d'édition :param livraisons: livraisons importées :param acces: accès importés :param machines: machines importées :param reservations: réservations importées :param prestations: prestations importées :param comptes: comptes importés :param dossier_annexe: nom du dossier dans lequel enregistrer les annexes :param plateforme: OS utilisé :param prefixe: prefixe de nom des annexes :param coefprests: coefficients prestations importés :param coefmachines: coefficients machines importés :param generaux: paramètres généraux :param garde: titre page de garde """ if sommes.calculees == 0: info = "Vous devez d'abord faire toutes les sommes avant de pouvoir créer les annexes" print(info) Outils.affiche_message(info) return for code_client in sommes.sommes_clients.keys(): contenu = Latex.entete(plateforme) contenu += r'''\usepackage[margin=10mm, includefoot]{geometry} \usepackage{multirow} \usepackage{longtable} \usepackage{dcolumn} \usepackage{changepage} \usepackage[scriptsize]{caption} \begin{document} \renewcommand{\arraystretch}{1.5} ''' contenu += r''' \vspace*{8cm} \begin{adjustwidth}{5cm}{} \Large\textsc{''' + garde + r'''}\newline\newline''' nom = Latex.echappe_caracteres(clients.donnees[code_client]['abrev_labo']) code_sap = clients.donnees[code_client]['code_sap'] contenu += code_client + " - " + code_sap + " - " + nom + r'''\newpage \end{adjustwidth}''' contenu += Annexes.contenu_client(sommes, clients, code_client, edition, livraisons, acces, machines, reservations, prestations, comptes, coefprests, coefmachines, generaux) contenu += r'''\end{document}''' nom = prefixe + str(edition.annee) + "_" + Outils.mois_string(edition.mois) + "_" + \ str(edition.version) + "_" + code_client Latex.creer_latex_pdf(nom, contenu, dossier_annexe)
def table_points_xbmu(code_client, scl, sommes_acces, machines, users): """ Points XB/M/U - Table Client Récap Bonus/MAchine/User :param code_client: code du client concerné :param scl: sommes client calculées :param sommes_acces: sommes des accès importés :param machines: machines importées :param users: users importés :return: table au format latex """ if scl['somme_t_mb'] > 0: structure = r'''{|l|c|r|r|}''' legende = r'''Récapitulatif des bonus d’utilisation en heures creuses''' contenu = r''' \cline{3-4} \multicolumn{2}{l|}{} & \multicolumn{1}{c|}{Temps Mach.} & \multicolumn{1}{c|}{Points Bonus} \\ \hline ''' somme = sommes_acces[code_client]['machines'] machines_utilisees = Outils.machines_in_somme(somme, machines) for id_categorie, mics in sorted(machines_utilisees.items()): for nom_machine, id_machine in sorted(mics.items()): if somme[id_machine]['dhm'] > 0: dico_machine = {'machine': Latex.echappe_caracteres(nom_machine), 'hc': Outils.format_heure(somme[id_machine]['duree_hc']), 'dhm': somme[id_machine]['dhm']} contenu += r''' \hspace{2mm} %(machine)s & HC & %(hc)s & %(dhm)s \\ \hline ''' % dico_machine utilisateurs = Outils.utilisateurs_in_somme(somme[id_machine]['users'], users) for nom, upi in sorted(utilisateurs.items()): for prenom, ids in sorted(upi.items()): for id_user in sorted(ids): smu = somme[id_machine]['users'][id_user] if smu['duree_hc'] > 0: dico_user = {'user': Latex.echappe_caracteres(nom + " " + prenom), 'hc': Outils.format_heure(smu['duree_hc'])} contenu += r''' \hspace{5mm} %(user)s & HC & %(hc)s \hspace{5mm} & \\ \hline ''' % dico_user dico = {'bht': scl['somme_t_mb']} contenu += r''' \multicolumn{3}{|r|}{\textbf{Total points de bonus}} & %(bht)s \\ \hline ''' % dico return Latex.long_tableau(contenu, structure, legende) else: return ""
def verification_coherence(self, generaux, edition, acces, clients, emoluments, coefprests, comptes, users, livraisons, machines, prestations, reservations, categories, categprix, docpdf): """ vérifie la cohérence des données importées :param generaux: paramètres généraux :param edition: paramètres d'édition :param acces: accès importés :param clients: clients importés :param emoluments: émoluments importés :param coefprests: coefficients prestations importés :param comptes: comptes importés :param users: users importés :param livraisons: livraisons importées :param machines: machines importées :param prestations: prestations importées :param reservations: réservations importées :param categories: catégories importées :param categprix: catégories prix importées :param docpdf: paramètres d'ajout de document pdf :return: 0 si ok, sinon le nombre d'échecs à la vérification """ verif = 0 verif += acces.est_coherent(comptes, machines, users) verif += livraisons.est_coherent(comptes, prestations, users) verif += categories.est_coherent() verif += users.est_coherent() verif += machines.est_coherent(categories) verif += prestations.est_coherent(generaux, coefprests) verif += emoluments.est_coherent(generaux) verif += categprix.est_coherent(generaux, categories) verif += coefprests.est_coherent(generaux) verif += clients.est_coherent(emoluments, generaux) verif += reservations.est_coherent(comptes, machines, users) verif += docpdf.est_coherent(generaux, clients) verif += comptes.est_coherent(clients, generaux) if verif > 0: return verif comptes_actifs = Verification.obtenir_comptes_actifs(acces, livraisons) clients_actifs = Verification.obtenir_clients_actifs( comptes_actifs, comptes) if edition.version > 0 and len(clients_actifs) > 0: if len(clients_actifs) > 1: Outils.affiche_message( "Si version différente de 0, un seul client autorisé") sys.exit("Trop de clients pour version > 0") if edition.client_unique != clients_actifs[0]: Outils.affiche_message( "Le client unique des paramètres d'édition n'est pas le même que celui présent dans " "les transactions") sys.exit("clients non-correspondants pour version > 0") self.a_verifier = 0 return verif
def est_coherent(self, subcomptes): """ vérifie que les données du fichier importé sont cohérentes :param subcomptes: comptes subsides importés :return: 1 s'il y a une erreur, 0 sinon """ if self.verifie_coherence == 1: print(self.libelle + ": cohérence déjà vérifiée") return 0 msg = "" ligne = 1 donnees_dict = {} ids = [] for donnee in self.donnees: if donnee['id_compte'] == "": msg += "le compte id de la ligne " + str( ligne) + " ne peut être vide\n" elif donnee['id_compte'] not in ids: ids.append(donnee['id_compte']) else: msg += "le compte id '" + donnee['id_compte'] + "' de la ligne " + str(ligne) +\ " n'est pas unique\n" if donnee['id_compte'] not in subcomptes.obtenir_ids(): msg += "le compte id '" + donnee['id_compte'] + "' de la ligne " + str(ligne) +\ " n'est pas référencée dans les comptes subisdes\n" donnee['m_mois'], info = Outils.est_un_nombre( donnee['m_mois'], "le maximum m mois", ligne) msg += info donnee['m_compte'], info = Outils.est_un_nombre( donnee['m_compte'], "le maximum m compte", ligne) msg += info donnees_dict[donnee['id_compte']] = donnee ligne += 1 for id_compte in subcomptes.obtenir_ids(): if id_compte not in ids: msg += "Le compte id '" + id_compte + "' dans les comptes subsides n'est pas présente dans " \ "les plafonds machines\n" self.donnees = donnees_dict self.verifie_coherence = 1 if msg != "": msg = self.libelle + "\n" + msg Outils.affiche_message(msg) return 1 return 0
def creation_lignes(edition, sommes, clients, generaux, acces, livraisons, comptes, categories, prestations): """ génération des lignes de données du détail :param edition: paramètres d'édition :param sommes: sommes calculées :param clients: clients importés :param generaux: paramètres généraux :param acces: accès importés :param livraisons: livraisons importées :param comptes: comptes importés :param categories: catégories importées :param prestations: prestations importées :return: lignes de données du détail """ if sommes.calculees == 0: info = "Vous devez d'abord faire toutes les sommes avant de pouvoir créer le détail des coûts" Outils.affiche_message(info) return None lignes = [] for code_client in sorted(sommes.sommes_clients.keys()): client = clients.donnees[code_client] if code_client in sommes.sommes_comptes: sclo = sommes.sommes_comptes[code_client] comptes_utilises = Outils.comptes_in_somme(sclo, comptes) base_client = [edition.annee, edition.mois, code_client, client['code_sap'], client['abrev_labo'], 'U', client['nature']] for id_compte, num_compte in sorted(comptes_utilises.items(), key=lambda x: x[1]): compte = comptes.donnees[id_compte] base_compte = base_client + [id_compte, num_compte, compte['intitule'], compte['type_subside']] if code_client in acces.sommes and id_compte in acces.sommes[code_client]['categories']: som_cats = acces.sommes[code_client]['categories'][id_compte]['machine'] for id_categorie, som_cat in sorted(som_cats.items()): duree = som_cat['duree_hp'] + som_cat['duree_hc'] ligne = base_compte + ['M', id_categorie, categories.donnees[id_categorie]['intitule'], duree, som_cat['mo'], 0, 0, 0, 0, "", "", "", "", "", "", ""] lignes.append(ligne) if code_client in livraisons.sommes and id_compte in livraisons.sommes[code_client]: somme = livraisons.sommes[code_client][id_compte] for article in generaux.articles_d3: if article.code_d in somme: for no_prestation, sip in sorted(somme[article.code_d].items()): prestation = prestations.prestation_de_num(no_prestation) ligne = base_compte + [article.code_d, "", "", "", "", "", "", "", "", article.intitule_court, no_prestation, sip['nom'], Outils.format_2_dec(sip['montantx']), Outils.format_2_dec(sip['rabais']), prestation['categ_stock'], prestation['affiliation']] lignes.append(ligne) return lignes
def obtenir_comptes(self): """ retourne la liste de tous les comptes clients :return: liste des comptes clients présents dans les données livraisons importées """ if self.verifie_coherence == 0: info = self.libelle + ". vous devez vérifier la cohérence avant de pouvoir obtenir les comptes" Outils.affiche_message(info) return [] return self.comptes
def obtenir_codes(self): """ retourne les codes de tous les clients :return: codes de tous les clients """ if self.verifie_coherence == 0: info = self.libelle + ". vous devez vérifier la cohérence avant de pouvoir obtenir les codes" Outils.affiche_message(info) return [] return self.codes
def est_coherent(self, clients, generaux): """ vérifie que les données du fichier importé sont cohérentes (code client dans clients, id compte unique), et efface les colonnes mois et année :param clients: clients importés :param generaux: paramètres généraux :return: 1 s'il y a une erreur, 0 sinon """ if self.verifie_date == 0: info = self.libelle + ". vous devez vérifier la date avant de vérifier la cohérence" Outils.affiche_message(info) return 1 if self.verifie_coherence == 1: print(self.libelle + ": cohérence déjà vérifiée") return 0 msg = "" ligne = 1 ids = [] donnees_dict = {} for donnee in self.donnees: if donnee['code_client'] == "": msg += "le code client de la ligne " + str( ligne) + " ne peut être vide\n" elif donnee['code_client'] not in clients.donnees: msg += "le code client " + donnee['code_client'] + " de la ligne " + str(ligne) + \ " n'est pas référencé\n" if donnee['id_compte'] == "": msg += "le compte id de la ligne " + str( ligne) + " ne peut être vide\n" elif donnee['id_compte'] not in ids: ids.append(donnee['id_compte']) else: msg += "l'id compte '" + donnee['id_compte'] + "' de la ligne " + str(ligne) +\ " n'est pas unique\n" if donnee['type_tarif'] != generaux.code_t: msg += "le type de tarif de la ligne " + str( ligne) + " n'est pas correct\n" del donnee['annee'] del donnee['mois'] donnees_dict[donnee['id_compte']] = donnee ligne += 1 self.donnees = donnees_dict self.verifie_coherence = 1 if msg != "": msg = self.libelle + "\n" + msg Outils.affiche_message(msg) return 1 return 0
def table_prix_lvr_jd(code_client, id_compte, intitule_compte, sco, sommes_livraisons, generaux): """ Prix LVR J/D - Table Compte Récap Prestations livrées/code D :param code_client: code du client concerné :param id_compte: id du compte concerné :param intitule_compte: intitulé du compte concerné :param sco: sommes compte calculées :param sommes_livraisons: sommes des livraisons importées :param generaux: paramètres généraux :return: table au format latex """ if code_client in sommes_livraisons and id_compte in sommes_livraisons[code_client]: somme = sommes_livraisons[code_client][id_compte] structure = r'''{|l|r|c|r|r|r|}''' legende = r'''Consommables et autres prestations''' contenu_prests = "" for article in generaux.articles_d3: if article.code_d in somme and sco['sommes_cat_m'][article.code_d] > 0: if contenu_prests != "": contenu_prests += r''' \multicolumn{6}{c}{} \\ ''' contenu_prests += r''' \hline \multicolumn{1}{|l|}{ \textbf{''' + intitule_compte + " - " + Latex.echappe_caracteres(article.intitule_long) + r''' }} & \multicolumn{1}{c|}{Quantité} & Unité & \multicolumn{1}{c|}{P.U.} & \multicolumn{1}{c|}{Montant} & \multicolumn{1}{c|}{Rabais} \\ \hline ''' for no_prestation, sip in sorted(somme[article.code_d].items()): if sip['montant'] > 0: dico_prestations = {'nom': Latex.echappe_caracteres(sip['nom']), 'num': no_prestation, 'quantite': "%.1f" % sip['quantite'], 'unite': Latex.echappe_caracteres(sip['unite']), 'pn': Outils.format_2_dec(sip['pn']), 'montant': Outils.format_2_dec(sip['montant']), 'rabais': Outils.format_2_dec(sip['rabais'])} contenu_prests += r''' %(num)s - %(nom)s & \hspace{5mm} %(quantite)s & %(unite)s & %(pn)s & %(montant)s & %(rabais)s \\ \hline ''' % dico_prestations dico_prestations = {'montant': Outils.format_2_dec(sco['sommes_cat_m'][article.code_d]), 'rabais': Outils.format_2_dec(sco['sommes_cat_r'][article.code_d])} contenu_prests += r''' \multicolumn{4}{|r|}{Total} & %(montant)s & %(rabais)s \\ \hline ''' % dico_prestations return Latex.tableau(contenu_prests, structure, legende) else: return ""
def somme_par_compte(self, comptes): """ calcule les sommes par comptes sous forme de dictionnaire : client->compte->clés_sommes :param comptes: comptes importés et vérifiés """ if self.sp != 0: spc = {} for code_client, client in self.sommes_projets.items(): if code_client not in spc: spc[code_client] = {} cl = spc[code_client] for id_compte, compte in client.items(): cc = comptes.donnees[id_compte] cl[id_compte] = self.nouveau_somme(Sommes.cles_somme_compte) somme = cl[id_compte] for num_projet, projet in compte.items(): somme["somme_j_pu"] += projet["somme_p_pu"] somme["somme_j_pv"] += projet["somme_p_pv"] somme["somme_j_pm"] += projet["somme_p_pm"] somme["somme_j_qu"] += projet["somme_p_qu"] somme["somme_j_qv"] += projet["somme_p_qv"] somme["somme_j_qm"] += projet["somme_p_qm"] somme["somme_j_om"] += projet["somme_p_om"] somme["somme_j_nm"] += projet["somme_p_nm"] for categorie in self.categories: somme["sommes_cat_m"][categorie] += projet["sommes_cat_m"][categorie] somme["sommes_cat_r"][categorie] += projet["sommes_cat_r"][categorie] somme["tot_cat"][categorie] += projet["tot_cat"][categorie] somme["prj"], somme["qrj"], somme["orj"] = Rabais.rabais_plafonnement( somme["somme_j_pm"], cc["seuil"], cc["pourcent"] ) somme["pj"] = somme["somme_j_pm"] - somme["prj"] somme["qj"] = somme["somme_j_qm"] - somme["qrj"] somme["oj"] = somme["somme_j_om"] - somme["orj"] somme["nrj"] = somme["qrj"] + somme["orj"] somme["nj"] = somme["somme_j_nm"] - somme["nrj"] tot = somme["somme_j_pm"] + somme["somme_j_qm"] + somme["somme_j_om"] for categorie in self.categories: tot += somme["sommes_cat_m"][categorie] if tot > 0: somme["si_facture"] = 1 self.sco = 1 self.sommes_comptes = spc else: info = "Vous devez d'abord faire la somme par projet, avant la somme par compte" print(info) Outils.affiche_message(info)
def obtenir_ids(self): """ retourne les ids de tous les comptes :return: ids de tous les comptes """ if self.verifie_coherence == 0: info = self.libelle + ". vous devez vérifier la cohérence avant de pouvoir obtenir les ids" print(info) Outils.affiche_message(info) return [] return self._ids
def obtenir_classes(self): """ retourne toutes les classes de tarif présentes :return: toutes les classes de tarif présentes """ if self.verifie_coherence == 0: info = self.libelle + ". vous devez vérifier la cohérence avant de pouvoir obtenir les classes" print(info) Outils.affiche_message(info) return [] return self.classes
def obtenir_codes(self): """ retourne les codes de tous les clients :return: codes de tous les clients """ if self.verifie_coherence == 0: info = self.libelle + ". vous devez vérifier la cohérence avant de pouvoir obtenir les codes" print(info) Outils.affiche_message(info) return [] return self.codes
def somme_par_categorie(self, comptes): """ calcule les sommes par catégories sous forme de dictionnaire : client->catégorie->clés_sommes :param comptes: comptes importés et vérifiés """ if self.verification.a_verifier != 0: info = "Sommes : vous devez faire les vérifications avant de calculer les sommes" print(info) Outils.affiche_message(info) return if self.sco != 0: spc = {} for code_client, client in self.sommes_comptes.items(): if code_client not in spc: spc[code_client] = {} cl = spc[code_client] for id_compte, compte in client.items(): co = comptes.donnees[id_compte] cat = co["categorie"] if cat not in cl: cl[cat] = self.nouveau_somme(Sommes.cles_somme_categorie) somme = cl[cat] somme["somme_k_pu"] += compte["somme_j_pu"] somme["somme_k_pv"] += compte["somme_j_pv"] somme["somme_k_pm"] += compte["somme_j_pm"] somme["somme_k_prj"] += compte["prj"] somme["pk"] += compte["pj"] somme["somme_k_qu"] += compte["somme_j_qu"] somme["somme_k_qv"] += compte["somme_j_qv"] somme["somme_k_qm"] += compte["somme_j_qm"] somme["somme_k_qrj"] += compte["qrj"] somme["qk"] += compte["qj"] somme["somme_k_om"] += compte["somme_j_om"] somme["somme_k_orj"] += compte["orj"] somme["ok"] += compte["oj"] somme["somme_k_nm"] += compte["somme_j_nm"] somme["somme_k_nrj"] += compte["nrj"] somme["nk"] += compte["nj"] for categorie in self.categories: somme["sommes_cat_m"][categorie] += compte["sommes_cat_m"][categorie] somme["sommes_cat_r"][categorie] += compte["sommes_cat_r"][categorie] somme["tot_cat"][categorie] += compte["tot_cat"][categorie] self.sca = 1 self.sommes_categories = spc else: info = "Vous devez d'abord faire la somme par compte, avant la somme par catégorie" print(info) Outils.affiche_message(info)
def obtenir_comptes(self): """ retourne la liste de tous les comptes clients :return: liste des comptes clients présents dans les données livraisons importées """ if self.verifie_coherence == 0: info = self.libelle + ". vous devez vérifier la cohérence avant de pouvoir obtenir les comptes" print(info) Outils.affiche_message(info) return [] return self.comptes
def table_prix_cae_jk(code_client, id_compte, intitule_compte, sco, sommes_acces, categories): """ Prix CAE J/K - Table Compte Récap Procédés/Catégorie Machine :param code_client: code du client concerné :param id_compte: id du compte concerné :param intitule_compte: intitulé du compte concerné :param sco: sommes compte calculées :param sommes_acces: sommes des accès importés :param categories: catégories importées :return: table au format latex """ if code_client in sommes_acces and id_compte in sommes_acces[code_client]['comptes'] and sco['somme_j_mk'] > 0: structure = r'''{|l|c|c|r|r|}''' legende = r'''Services''' contenu = r''' \hline \textbf{''' + intitule_compte + r'''} & Unité & Quantité & \multicolumn{1}{c|}{PU} & \multicolumn{1}{c|}{Montant} \\ \hline ''' for cat, som_cat in sorted(sommes_acces[code_client]['categories'][id_compte].items()): for id_categorie, cats in sorted(som_cat.items()): montant = cats['mk'] unite = categories.donnees[id_categorie]['unite'] if unite == 'hh_mm': quantite = Outils.format_heure(cats['quantite']) else: quantite = cats['quantite'] if montant > 0: dico_cat = {'intitule': Latex.echappe_caracteres(categories.donnees[id_categorie]['intitule']), 'pk': Outils.format_2_dec(cats['pk']), 'unite': Latex.echappe_caracteres(unite), 'quantite': quantite, 'mk': Outils.format_2_dec(montant)} contenu += r''' %(intitule)s & %(unite)s & %(quantite)s & %(pk)s & %(mk)s \\ \hline ''' % dico_cat dico_cat = {'mkj': Outils.format_2_dec(sco['somme_j_mk'])} contenu += r''' \multicolumn{4}{|r|}{Total} & %(mkj)s \\ \hline ''' % dico_cat return Latex.tableau(contenu, structure, legende) else: return ""
def appel_des_outils(self): """ Méthode qui permet de lancer la fenêtre qui contient les outils """ # Création d'une instance de la classe Outils self._outils = Outils(self._instance_fenetre_principale) # Lancement de l'instance self._outils.exec_() self.accept()
def annuler(suffixe, client_unique, mois, annee, dossier_source, dossier_destination, dossier_source_backup): """ annulation de modification des résumés mensuels au niveau du client dont la facture est supprimée :param suffixe: suffixe dossier version :param client_unique: client concerné :param mois: mois concerné :param annee: année concernée :param dossier_source: Une instance de la classe dossier.DossierSource :param dossier_destination: Une instance de la classe dossier.DossierDestination :param dossier_source_backup: Une instance de la classe dossier.DossierSource pour récupérer les données à remettre """ for i in range(len(Resumes.fichiers)): fichier_backup = Resumes.fichiers[i] + "_" + str( annee) + "_" + Outils.mois_string(mois) + suffixe + ".csv" donnees_backup = Resumes.ouvrir_csv_seulement_client( dossier_source_backup, fichier_backup, client_unique, Resumes.positions[i]) fichier_complet = Resumes.fichiers[i] + "_" + str( annee) + "_" + Outils.mois_string(mois) + ".csv" donnees_csv = Resumes.ouvrir_csv_sans_client( dossier_source, fichier_complet, client_unique, Resumes.positions[i]) with dossier_destination.writer(fichier_complet) as fichier_writer: for ligne in donnees_csv: fichier_writer.writerow(ligne) for ligne in donnees_backup: fichier_writer.writerow(ligne) ticket_backup = "ticket_" + str(annee) + "_" + Outils.mois_string( mois) + suffixe + ".html" ticket_backup_texte = dossier_source_backup.string_lire(ticket_backup) index1, index2 = Resumes.section_position(ticket_backup_texte, client_unique) section = "" if index1 is not None: section = ticket_backup_texte[index1:index2] nom_client = "" index1, index2, clients_liste_backup = Resumes.select_clients( ticket_backup_texte) for nom in clients_liste_backup: if client_unique in nom: nom_client = nom break ticket_complet = "ticket_" + str(annee) + "_" + Outils.mois_string( mois) + ".html" Resumes.maj_ticket(dossier_source, dossier_destination, ticket_complet, section, client_unique, nom_client)
def est_coherent(self, comptes_actifs): """ vérifie que les données du fichier importé sont cohérentes (code client dans clients, ou alors absent des clients actifs, id compte unique), et efface les colonnes mois et année :param comptes_actifs: codes des clients présents dans accès, réservations et livraisons :return: 1 s'il y a une erreur, 0 sinon """ if self.verifie_date == 0: info = self.libelle + ". vous devez vérifier la date avant de vérifier la cohérence" print(info) Outils.affiche_message(info) return 1 if self.verifie_coherence == 1: print(self.libelle + ": cohérence déjà vérifiée") return 0 msg = "" ligne = 1 ids = [] donnees_dict = {} for donnee in self.donnees: if donnee['code_client'] == "": if donnee['id_compte'] in comptes_actifs: print("code client du compte vide") msg += "le code client de la ligne " + str(ligne) + " ne peut être vide si le compte est utilisé\n" continue if donnee['id_compte'] == "": msg += "le compte id de la ligne " + str(ligne) + " ne peut être vide\n" elif donnee['id_compte'] not in ids: ids.append(donnee['id_compte']) del donnee['annee'] del donnee['mois'] donnees_dict[donnee['id_compte']] = donnee else: msg += "l'id compte '" + donnee['id_compte'] + "' de la ligne " + str(ligne) +\ " n'est pas unique\n" ligne += 1 self.donnees = donnees_dict self.verifie_coherence = 1 if msg != "": msg = self.libelle + "\n" + msg print("msg : " + msg) Outils.affiche_message(msg) return 1 return 0
def obtenir_noms_categories(self, categorie): """ retourne le nom lié à une catégorie :return: nom lié à une catégorie """ if self.verifie_coherence == 0: info = self.libelle + ". vous devez vérifier la cohérence avant de pouvoir obtenir les catégories" print(info) Outils.affiche_message(info) return [] if categorie not in self.noms_cat: return categorie else: return self.noms_cat[categorie]
def extraction_ligne(self, ligne): """ extracte une ligne de données du csv :param ligne: ligne lue du fichier :return: tableau représentant la ligne, indexé par les clés """ num = len(self.cles) if len(ligne) != num: info = self.libelle + ": nombre de colonnes incorrect : " + str(len(ligne)) + ", attendu : " + str(num) print(info) Outils.affiche_message(info) sys.exit("Erreur de consistance") donnees_ligne = {} for xx in range(0, num): donnees_ligne[self.cles[xx]] = ligne[xx] return donnees_ligne
def ligne_tableau(article, poste, net, rabais, consommateur, edition): """ retourne une ligne de tableau html :param article: Une instance de la classe generaux.Article :param poste: indice de poste :param net: montant net :param rabais: rabais sur le montant :param consommateur: consommateur :param edition: paramètres d'édition :return: ligne de tableau html """ montant = net - rabais date_livraison = str(edition.dernier_jour) + "." + Outils.mois_string(edition.mois) + "." + str(edition.annee) description = article.code_d + " : " + article.code_sap dico_tab = {'poste': poste, 'date': date_livraison, 'descr': description, 'texte': article.texte_sap, 'nom': Latex.echappe_caracteres(consommateur), 'unit': article.unite, 'quantity': article.quantite, 'unit_p': "%.2f" % net, 'discount': "%.2f" % rabais, 'net': "%.2f" % montant} ligne = r'''<tr> <td> %(poste)s </td><td> %(date)s </td><td> %(nom)s </td><td> %(descr)s <br /> %(texte)s </td> <td> %(unit)s </td><td id="toright"> %(quantity)s </td><td id="toright"> %(unit_p)s </td> <td id="toright"> %(discount)s </td><td id="toright"> %(net)s </td> </tr> ''' % dico_tab return ligne
def ligne_facture(generaux, article, poste, net, rabais, op_centre, consommateur, edition): """ retourne une ligne de facturation formatée :param generaux: paramètres généraux :param article: Une instance de la classe generaux.Article :param poste: indice de poste :param net: montant net :param rabais: rabais sur le montant :param op_centre: centre d'opération :param consommateur: consommateur :param edition: paramètres d'édition :return: ligne de facturation formatée """ net = "%.2f" % net rabais = "%.2f" % rabais if rabais == 0: rabais = "" code_op = generaux.code_t + op_centre + article.code_d date_livraison = str(edition.annee) + Outils.mois_string(edition.mois) + str(edition.dernier_jour) return [poste, "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", article.code_sap, "", article.quantite, article.unite, article.type_prix, net, article.type_rabais, rabais, date_livraison, generaux.centre_financier, "", generaux.fonds, "", "", code_op, "", "", "", article.texte_sap, consommateur]
def est_coherent(self, comptes, machines): """ vérifie que les données du fichier importé sont cohérentes (id compte parmi comptes, id machine parmi machines), et efface les colonnes mois et année :param comptes: comptes importés :param machines: machines importées :return: 1 s'il y a une erreur, 0 sinon """ if self.verifie_date == 0: info = self.libelle + ". vous devez vérifier la date avant de vérifier la cohérence" print(info) Outils.affiche_message(info) return 1 if self.verifie_coherence == 1: print(self.libelle + ": cohérence déjà vérifiée") return 0 msg = "" ligne = 1 donnees_list = [] for donnee in self.donnees: if donnee['id_compte'] == "": msg += "le compte id de la ligne " + str(ligne) + " ne peut être vide\n" elif comptes.contient_id(donnee['id_compte']) == 0: msg += "le compte id '" + donnee['id_compte'] + "' de la ligne " + str(ligne) + " n'est pas référencé\n" elif donnee['code_client'] not in self.comptes: self.comptes[donnee['code_client']] = [donnee['id_compte']] elif donnee['id_compte'] not in self.comptes[donnee['code_client']]: self.comptes[donnee['code_client']].append(donnee['id_compte']) if donnee['id_machine'] == "": msg += "le machine id de la ligne " + str(ligne) + " ne peut être vide\n" elif machines.contient_id(donnee['id_machine']) == 0: msg += "le machine id '" + donnee['id_machine'] + "' de la ligne " + str(ligne) \ + " n'est pas référencé\n" donnee['duree_hp'], info = Outils.est_un_nombre(donnee['duree_hp'], "la durée réservée HP", ligne) msg += info donnee['duree_hc'], info = Outils.est_un_nombre(donnee['duree_hc'], "la durée réservée HC", ligne) msg += info donnee['duree_ouvree'], info = Outils.est_un_nombre(donnee['duree_ouvree'], "la durée ouvrée", ligne) msg += info del donnee['annee'] del donnee['mois'] donnees_list.append(donnee) ligne += 1 self.donnees = donnees_list self.verifie_coherence = 1 if msg != "": msg = self.libelle + "\n" + msg print("msg : " + msg) Outils.affiche_message(msg) return 1 return 0
def __init__(self, dossier_source): """ initialisation et importation des données :param dossier_source: Une instance de la classe dossier.DossierSource """ try: fichier_reader = dossier_source.reader(self.nom_fichier) donnees_csv = [] for ligne in fichier_reader: donnees_ligne = self.extraction_ligne(ligne) if donnees_ligne == -1: continue donnees_csv.append(donnees_ligne) self.donnees = donnees_csv self.verifie_date = 0 self.verifie_coherence = 0 except IOError as e: Outils.fatal(e, "impossible d'ouvrir le fichier : " + self.nom_fichier)
def calcul_montants(self, machines, coefmachines, comptes, clients, verification): """ calcule les montants 'pu', 'qu' et 'mo' et les ajoute aux données :param machines: machines importées :param coefmachines: coefficients machines importés et vérifiés :param comptes: comptes importés et vérifiés :param clients: clients importés et vérifiés :param verification: pour vérifier si les dates et les cohérences sont correctes """ if verification.a_verifier != 0: info = self.libelle + ". vous devez faire les vérifications avant de calculer les montants" print(info) Outils.affiche_message(info) return donnees_list = [] for donnee in self.donnees: compte = comptes.donnees[donnee['id_compte']] machine = machines.donnees[donnee['id_machine']] client = clients.donnees[compte['code_client']] coefmachine = coefmachines.donnees[client['id_classe_tarif'] + machine['categorie']] donnee['pu'] = round(donnee['duree_machine_hp'] / 60 * round(machine['t_h_machine_hp_p'] * coefmachine['coef_p'], 2) + donnee['duree_machine_hc'] / 60 * round(machine['t_h_machine_hc_p'] * coefmachine['coef_p']), 2) donnee['qu'] = round(donnee['duree_machine_hp'] / 60 * round(machine['t_h_machine_hp_np'] * coefmachine['coef_np'], 2) + donnee['duree_machine_hc'] / 60 * round(machine['t_h_machine_hc_np'] * coefmachine['coef_np']), 2) donnee['om'] = round(donnee['duree_operateur_hp'] / 60 * round(machine['t_h_operateur_hp_mo'] * coefmachine['coef_mo'], 2) + donnee['duree_operateur_hc'] / 60 * round(machine['t_h_operateur_hc_mo'] * coefmachine['coef_mo']), 2) donnees_list.append(donnee) self.donnees = donnees_list
def __init__(self, dossier_source): """ initialisation et importation des données :param dossier_source: Une instance de la classe dossier.DossierSource """ donnees_csv = [] try: for ligne in dossier_source.reader(self.nom_fichier): donnees_csv.append(ligne) except IOError as e: Outils.fatal(e, "impossible d'ouvrir le fichier : " + Edition.nom_fichier) num = 3 if len(donnees_csv) != num: Outils.fatal( ErreurConsistance(), Edition.libelle + ": nombre de lignes incorrect : " + str(len(donnees_csv)) + ", attendu : " + str(num), ) try: self.annee = int(donnees_csv[0][1]) self.mois = int(donnees_csv[1][1]) except ValueError as e: Outils.fatal(e, Edition.libelle + "\nle mois et l'année doivent être des nombres") self.version = donnees_csv[2][1] self.client_unique = "" jours = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] if self.mois != 2: jour = jours[self.mois - 1] else: if self.annee % 4 == 0: if self.annee % 100 == 0: if self.annee % 400 == 0: jour = 29 else: jour = 28 else: jour = 29 else: jour = 28 self.dernier_jour = jour mois_fr = [ "janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre", ] self.mois_txt = mois_fr[self.mois - 1]
def calcul_montants(self, machines, coefmachines, comptes, clients, verification): """ calcule les montants 'pv' et 'qv' et les ajoute aux données :param machines: machines importées et vérifiées :param coefmachines: coefficients machines importés et vérifiés :param comptes: comptes importés et vérifiés :param clients: clients importés et vérifiés :param verification: pour vérifier si les dates et les cohérences sont correctes """ if verification.a_verifier != 0: info = self.libelle + ". vous devez faire les vérifications avant de calculer les montants" print(info) Outils.affiche_message(info) return donnees_list = [] for donnee in self.donnees: compte = comptes.donnees[donnee['id_compte']] machine = machines.donnees[donnee['id_machine']] client = clients.donnees[compte['code_client']] coefmachine = coefmachines.donnees[client['id_classe_tarif'] + machine['categorie']] duree_fact_hp, duree_fact_hc = Rabais.rabais_reservation(machine['delai_sans_frais'], donnee['duree_ouvree'], donnee['duree_hp'], donnee['duree_hc']) donnee['pv'] = round(duree_fact_hp / 60 * round(machine['t_h_reservation_hp_p'] * coefmachine['coef_p'], 2) + duree_fact_hc / 60 * round(machine['t_h_reservation_hc_p'] * coefmachine['coef_p']), 2) donnee['qv'] = round(duree_fact_hp / 60 * round(machine['t_h_reservation_hp_np'] * coefmachine['coef_np'], 2) + duree_fact_hc / 60 * round(machine['t_h_reservation_hc_np'] * coefmachine['coef_np']), 2) donnee['duree_fact_hp'] = duree_fact_hp donnee['duree_fact_hc'] = duree_fact_hc donnees_list.append(donnee) self.donnees = donnees_list
def verification_cohérence(self, generaux, edition, acces, clients, coefmachines, coefprests, comptes, livraisons, machines, prestations, reservations): """ vérifie la cohérence des données importées :param generaux: paramètres généraux :param edition: paramètres d'édition :param acces: accès importés :param clients: clients importés :param coefmachines: coefficients machines importés :param coefprests: coefficients prestations importés :param comptes: comptes importés :param livraisons: livraisons importées :param machines: machines importées :param prestations: prestations importées :param reservations: réservations importées :return: 0 si ok, sinon le nombre d'échecs à la vérification """ verif = 0 verif += acces.est_coherent(comptes, machines) verif += reservations.est_coherent(comptes, machines) verif += livraisons.est_coherent(comptes, prestations) verif += machines.est_coherent(coefmachines) verif += prestations.est_coherent(generaux, coefprests) verif += coefmachines.est_coherent() verif += coefprests.est_coherent(generaux) verif += clients.est_coherent(coefmachines, coefprests, generaux) comptes_actifs, clients_actifs = Verification.obtenir_comptes_clients_actifs(acces, reservations, livraisons) if (edition.version != '0') and (len(clients_actifs) > 1): Outils.affiche_message("Si version différente de 0, un seul client autorisé") sys.exit("Trop de clients pour version > 0") verif += comptes.est_coherent(comptes_actifs) self.a_verifier = 0 if len(clients_actifs) == 1: edition.client_unique = clients_actifs[0] return verif
def ligne_tableau(self, article, poste, net, rabais, consommateur, edition): montant = net - rabais date_livraison = str(edition.dernier_jour) + "." + Outils.mois_string(edition.mois) + "." + str(edition.annee) description = article.code_d + " : " + article.code_sap dico_tab = {'poste': poste, 'date': date_livraison, 'descr': description, 'texte': article.texte_sap, 'nom': Latex.echappe_caracteres(consommateur), 'unit': article.unite, 'quantity': article.quantite, 'unit_p': "%.2f" % net, 'discount': "%.2f" % rabais, 'net': "%.2f" % montant} ligne = r'''<tr> <td> %(poste)s </td><td> %(date)s </td><td> %(nom)s </td><td> %(descr)s <br /> %(texte)s </td> <td> %(unit)s </td><td id="toright"> %(quantity)s </td><td id="toright"> %(unit_p)s </td> <td id="toright"> %(discount)s </td><td id="toright"> %(net)s </td> </tr> ''' % dico_tab return ligne
def somme_par_client(self, clients, reservations): """ calcule les sommes par clients sous forme de dictionnaire : client->clés_sommes :param clients: clients importés et vérifiés :param reservations: réservations importées et vérifiées """ if self.verification.a_verifier != 0: info = "Sommes : vous devez faire les vérifications avant de calculer les sommes" print(info) Outils.affiche_message(info) return if self.sca != 0: spcl = {} for code_client, spca_cl in self.sommes_categories.items(): spcl[code_client] = self.nouveau_somme(Sommes.cles_somme_client) somme = spcl[code_client] for cat, som_cat in spca_cl.items(): somme['somme_t_ai'] += som_cat['somme_k_ai'] somme['somme_t_bi'] += som_cat['somme_k_bi'] somme['somme_t_ci'] += som_cat['somme_k_ci'] somme['somme_t_oi'] += som_cat['somme_k_oi'] somme['mat'] += som_cat['somme_k_mai'] somme['mot'] += som_cat['somme_k_moi'] somme['dst'] += som_cat['somme_k_dsi'] somme['dht'] += som_cat['somme_k_dhi'] somme['somme_t_mm'] += som_cat['somme_k_mm'] somme['somme_t_mr'] += som_cat['somme_k_mr'] somme['mt'] += som_cat['mk'] for categorie in self.categories: somme['sommes_cat_m'][categorie] += som_cat['sommes_cat_m'][categorie] somme['sommes_cat_r'][categorie] += som_cat['sommes_cat_r'][categorie] somme['tot_cat'][categorie] += som_cat['tot_cat'][categorie] spco_cl = self.sommes_comptes[code_client] somme['res'] = {} somme['rm'] = 0 for id_co, spco_co in spco_cl.items(): for id_mach, mach in spco_co['res'].items(): if id_mach not in somme['res']: somme['res'][id_mach] = {'pen_hp': 0, 'pen_hc': 0, 'm_hp': 0, 'm_hc': 0} som_m = somme['res'][id_mach] som_m['pen_hp'] += mach['pen_hp'] som_m['pen_hc'] += mach['pen_hc'] for id_mach, som_m in somme['res'].items(): if som_m['pen_hp'] > 0: som_m['m_hp'] += som_m['pen_hp'] * reservations.sommes[code_client]['machines'][id_mach]['pu_hp'] somme['rm'] += som_m['m_hp'] if som_m['pen_hc'] > 0: som_m['m_hc'] += som_m['pen_hc'] * reservations.sommes[code_client]['machines'][id_mach]['pu_hc'] somme['rm'] += som_m['m_hc'] somme['rr'] = Rabais.rabais_reservation_petit_montant(somme['rm'], self.min_fact_rese) somme['r'] = somme['rm'] - somme['rr'] client = clients.donnees[code_client] somme['somme_eq'], somme['somme_t'], somme['em'], somme['er0'], somme['er'] = \ Rabais.rabais_emolument(somme['r'], somme['mt'], somme['mot'], somme['tot_cat'], client['emol_base_mens'], client['emol_fixe'], client['coef'], client['emol_sans_activite']) somme['e'] = somme['em'] - somme['er'] # print("") # print("spcl") # for code in spcl: # if code != "220208": # continue # somme = spcl[code] # print(code, somme['mat']) self.calculees = 1 self.sommes_clients = spcl else: info = "Vous devez d'abord faire la somme par catégorie, avant la somme par client" print(info) Outils.affiche_message(info)
import sys from docopt import docopt from importes import Client, Acces, CoefMachine, CoefPrest, Compte, Livraison, Machine, Prestation, Reservation, DossierSource, DossierDestination from outils import Outils from parametres import Edition, Generaux from traitement import Annexes, BilanMensuel, Facture, Sommes, Verification from prod2qual import Prod2Qual from latex import Latex arguments = docopt(__doc__) plateforme = sys.platform if arguments["--sansgraphiques"]: Outils.interface_graphique(False) if arguments["--entrees"] : dossier_data = arguments["--entrees"] else: dossier_data = Outils.choisir_dossier(plateforme) dossier_source = DossierSource(dossier_data) edition = Edition(dossier_source) acces = Acces(dossier_source) clients = Client(dossier_source) coefmachines = CoefMachine(dossier_source) coefprests = CoefPrest(dossier_source) comptes = Compte(dossier_source) livraisons = Livraison(dossier_source)
def sommes_par_projet(self, livraisons, acces, prestations, comptes): """ calcule les sommes par projets sous forme de dictionnaire : client->compte->projet->clés_sommes :param livraisons: livraisons importées et vérifiées :param acces: accès machines importés et vérifiés :param prestations: prestations importées et vérifiées :param comptes: comptes importés et vérifiés """ if self.verification.a_verifier != 0: info = "Sommes : vous devez faire les vérifications avant de calculer les sommes" print(info) Outils.affiche_message(info) return spp = {} for acce in acces.donnees: id_compte = acce['id_compte'] code_client = comptes.donnees[id_compte]['code_client'] if code_client not in spp: spp[code_client] = {} spp_cl = spp[code_client] if id_compte not in spp_cl: spp_cl[id_compte] = {} num_projet = acce['num_projet'] spp_co = spp_cl[id_compte] if num_projet not in spp_co: spp_co[num_projet] = self.nouveau_somme(Sommes.cles_somme_projet) projet = spp_co[num_projet] projet['intitule'] = acce['intitule_projet'] else: projet = spp_co[num_projet] projet['somme_p_ai'] += acce['ai'] projet['somme_p_bi'] += acce['bi'] projet['somme_p_ci'] += acce['ci'] projet['somme_p_oi'] += acce['oi'] projet['somme_p_mai'] += acce['mai'] projet['somme_p_moi'] += acce['moi'] projet['somme_p_dsi'] += acce['dsi'] projet['somme_p_dhi'] += acce['dhi'] projet['somme_p_mm'] += acce['mm'] projet['somme_p_mr'] += acce['mr'] projet['mp'] += acce['m'] for livraison in livraisons.donnees: id_compte = livraison['id_compte'] code_client = comptes.donnees[id_compte]['code_client'] if code_client not in spp: spp[code_client] = {} spp_cl = spp[code_client] if id_compte not in spp_cl: spp_cl[id_compte] = {} num_projet = livraison['num_projet'] spp_co = spp_cl[id_compte] if num_projet not in spp_co: spp_co[num_projet] = self.nouveau_somme(Sommes.cles_somme_projet) projet = spp_co[num_projet] projet['intitule'] = livraison['intitule_projet'] else: projet = spp_co[num_projet] id_prestation = livraison['id_prestation'] prestation = prestations.donnees[id_prestation] projet['sommes_cat_m'][prestation['categorie']] += livraison['montant'] projet['sommes_cat_r'][prestation['categorie']] += livraison['rabais_r'] projet['tot_cat'][prestation['categorie']] += livraison['montant'] - livraison['rabais_r'] # print("spp") # for code in spp: # if code != "220208": # continue # print(code) # spp_cl = spp[code] # for id in spp_cl: # print(" ", id) # spp_co = spp_cl[id] # for num in spp_co: # projet = spp_co[num] # print(" ", " ", num, projet['somme_p_mai']) self.sp = 1 self.sommes_projets = spp
def __init__(self, dossier_source, prod2qual=None): """ initialisation et importation des données :param dossier_source: Une instance de la classe dossier.DossierSource :param prod2qual: Une instance de la classe Prod2Qual si on souhaite éditer des factures et annexes avec les codes d'articles de qualification """ self._donnees = {} try: for ligne in dossier_source.reader(self.nom_fichier): cle = ligne.pop(0) if cle not in self.cles_autorisees: Outils.fatal(ErreurConsistance(), "Clé inconnue dans %s: %s" % (self.nom_fichier, cle)) if cle != "texte_sap": while "" in ligne: ligne.remove("") self._donnees[cle] = ligne except IOError as e: Outils.fatal(e, "impossible d'ouvrir le fichier : "+Generaux.nom_fichier) if prod2qual and 'code_sap_qas' in self._donnees: self._donnees['code_sap'] = self._donnees['code_sap_qas'] erreurs = "" for cle in self.cles_obligatoires: if cle not in self._donnees: erreurs += "\nClé manquante dans %s: %s" % (self.nom_fichier, cle) try: for quantite in self._donnees['quantite'][1:]: int(quantite) except ValueError: erreurs += "les quantités doivent être des nombres entiers\n" codes_n = [] for nn in self._donnees['code_n'][1:]: if nn not in codes_n: codes_n.append(nn) else: erreurs += "le code N '" + nn + "' n'est pas unique\n" codes_d = [] for dd in self._donnees['code_d'][1:]: if dd not in codes_d: codes_d.append(dd) else: erreurs += "le code D '" + dd + "' n'est pas unique\n" if len(self._donnees['code_n']) != len(self._donnees['nature_client']): erreurs += "le nombre de colonees doit être le même pour le code N et pour la nature du client\n" if (len(self._donnees['code_d']) != len(self._donnees['code_sap'])) or (len(self._donnees['code_d']) != len(self._donnees['quantite'])) or (len(self._donnees['code_d']) != len(self._donnees['unite'])) or (len(self._donnees['code_d']) != len(self._donnees['type_prix'])) or (len(self._donnees['code_d']) != len(self._donnees['type_rabais'])) or (len(self._donnees['code_d']) != len(self._donnees['texte_sap'])): erreurs += "le nombre de colonees doit être le même pour le code D, le code SAP, la quantité, l'unité, " \ "le type de prix, le type de rabais et le texte SAP\n" if erreurs != "": Outils.fatal(ErreurConsistance(), self.libelle + "\n" + erreurs)
def somme_par_client(self, clients): """ calcule les sommes par clients sous forme de dictionnaire : client->clés_sommes :param clients: clients importés et vérifiés """ if self.verification.a_verifier != 0: info = "Sommes : vous devez faire les vérifications avant de calculer les sommes" print(info) Outils.affiche_message(info) return if self.sca != 0: spc = {} for code_client, client in self.sommes_categories.items(): spc[code_client] = self.nouveau_somme(Sommes.cles_somme_client) somme = spc[code_client] for cat, som_cat in client.items(): somme["somme_t_pu"] += som_cat["somme_k_pu"] somme["somme_t_pv"] += som_cat["somme_k_pv"] somme["somme_t_pm"] += som_cat["somme_k_pm"] somme["somme_t_prj"] += som_cat["somme_k_prj"] somme["pt"] += som_cat["pk"] somme["somme_t_qu"] += som_cat["somme_k_qu"] somme["somme_t_qv"] += som_cat["somme_k_qv"] somme["somme_t_qm"] += som_cat["somme_k_qm"] somme["somme_t_qrj"] += som_cat["somme_k_qrj"] somme["qt"] += som_cat["qk"] somme["somme_t_om"] += som_cat["somme_k_om"] somme["somme_t_orj"] += som_cat["somme_k_orj"] somme["ot"] += som_cat["ok"] somme["somme_t_nm"] += som_cat["somme_k_nm"] somme["somme_t_nrj"] += som_cat["somme_k_nrj"] somme["nt"] += som_cat["nk"] for categorie in self.categories: somme["sommes_cat_m"][categorie] += som_cat["sommes_cat_m"][categorie] somme["sommes_cat_r"][categorie] += som_cat["sommes_cat_r"][categorie] somme["tot_cat"][categorie] += som_cat["tot_cat"][categorie] cl = clients.donnees[code_client] somme["somme_eq"], somme["somme_sb"], somme["somme_t"], somme["em"], somme["er0"], somme[ "er" ] = Rabais.rabais_emolument( somme["pt"], somme["qt"], somme["ot"], somme["tot_cat"], cl["emol_base_mens"], cl["emol_fixe"], cl["coef"], cl["emol_sans_activite"], ) somme["e"] = somme["em"] - somme["er"] self.calculees = 1 self.sommes_clients = spc else: info = "Vous devez d'abord faire la somme par catégorie, avant la somme par client" print(info) Outils.affiche_message(info)
def bilan(dossier_destination, edition, sommes, clients, generaux, acces, reservations, livraisons, comptes): """ création du bilan :param dossier_destination: Une instance de la classe dossier.DossierDestination :param edition: paramètres d'édition :param sommes: sommes calculées :param clients: clients importés :param generaux: paramètres généraux :param acces: accès importés :param reservations: réservations importés :param livraisons: livraisons importées :param comptes: comptes importés """ if sommes.calculees == 0: info = "Vous devez d'abord faire toutes les sommes avant de pouvoir créer le bilan mensuel" print(info) Outils.affiche_message(info) return nom = "bilan_" + str(edition.annee) + "_" + Outils.mois_string(edition.mois) + "_" + \ str(edition.version) + ".csv" with dossier_destination.writer(nom) as fichier_writer: ligne = ["année", "mois", "référence", "code client", "code client sap", "abrév. labo", "nom labo", "type client", "nature client", "Em base", "somme EQ", "rabais Em", "règle", "nb utilisateurs", "nb tot comptes", "nb comptes cat 1", "nb comptes cat 2", "nb comptes cat 3", "nb comptes cat 4", "total M cat 1", "total M cat 2", "total M cat 3", "total M cat 4", "MAt", "MOt", "DSt", "DHt", "Et", "Rt", "Mt"] for categorie in generaux.codes_d3(): ligne.append(categorie + "t") ligne.append("total facturé HT") fichier_writer.writerow(ligne) for code_client in sorted(sommes.sommes_clients.keys()): scl = sommes.sommes_clients[code_client] sca = sommes.sommes_categories[code_client] client = clients.donnees[code_client] nature = generaux.nature_client_par_code_n(client['type_labo']) reference = nature + str(edition.annee)[2:] + Outils.mois_string(edition.mois) + "." + code_client nb_u = len(BilanMensuel.utilisateurs(acces, livraisons, reservations, code_client)) cptes = BilanMensuel.comptes(acces, livraisons, reservations, code_client) cat = {'1': 0, '2': 0, '3': 0, '4': 0} nb_c = 0 for cpte in cptes: nb_c += 1 cat[comptes.donnees[cpte]['categorie']] += 1 mk = {'1': 0, '2': 0, '3': 0, '4': 0} for num in mk.keys(): if num in sca: mk[num] = sca[num]['mk'] total = scl['somme_t'] + scl['e'] ligne = [edition.annee, edition.mois, reference, code_client, client['code_sap'], client['abrev_labo'], client['nom_labo'], 'U', client['type_labo'], scl['em'], "%.2f" % scl['somme_eq'], scl['er'], client['emol_sans_activite'], nb_u, nb_c, cat['1'], cat['2'], cat['3'], cat['4'], "%.2f" % mk['1'], "%.2f" % mk['2'], "%.2f" % mk['3'], "%.2f" % mk['4'], "%.2f" % scl['mat'], scl['mot'], scl['dst'], scl['dht'], scl['e'], scl['r'], "%.2f" % scl['mt']] for categorie in generaux.codes_d3(): ligne.append(scl['tot_cat'][categorie]) ligne.append("%.2f" % total) fichier_writer.writerow(ligne)
def est_coherent(self, coefmachines, coefprests, generaux): """ vérifie que les données du fichier importé sont cohérentes (code client unique, classe tarif présente dans coefficients, type de labo dans paramètres), et efface les colonnes mois et année :param coefmachines: coefficients machines importés :param coefprests: coefficients prestations importés :param generaux: paramètres généraux :return: 1 s'il y a une erreur, 0 sinon """ if self.verifie_date == 0: info = self.libelle + ". vous devez vérifier la date avant de vérifier la cohérence" print(info) Outils.affiche_message(info) return 1 if self.verifie_coherence == 1: print(self.libelle + ": cohérence déjà vérifiée") return 0 msg = "" ligne = 1 classes = [] donnees_dict = {} for donnee in self.donnees: if donnee['id_classe_tarif'] == "": msg += "la classe de tarif de la ligne " + str(ligne) + " ne peut être vide\n" elif donnee['id_classe_tarif'] not in classes: classes.append(donnee['id_classe_tarif']) if donnee['code_sap'] == "": msg += "le code sap de la ligne " + str(ligne) + " ne peut être vide\n" if donnee['code'] == "": msg += "le code client de la ligne " + str(ligne) + " ne peut être vide\n" elif donnee['code'] not in self.codes: self.codes.append(donnee['code']) del donnee['annee'] del donnee['mois'] donnees_dict[donnee['code']] = donnee else: msg += "le code client '" + donnee['code'] + "' de la ligne " + str(ligne) +\ " n'est pas unique\n" if donnee['type_labo'] == "": msg += "le type de labo de la ligne " + str(ligne) + " ne peut être vide\n" elif donnee['type_labo'] not in generaux.obtenir_code_n(): msg += "le type de labo '" + donnee['type_labo'] + "' de la ligne " + str(ligne) +\ " n'existe pas dans les types N\n" if (donnee['mode'] != "") and (donnee['mode'] not in generaux.obtenir_modes_envoi()): msg += "le mode d'envoi '" + donnee['mode'] + "' de la ligne " + str(ligne) +\ " n'existe pas dans les modes d'envoi généraux\n" if (donnee['email'] != "") and (not re.match("[^@]+@[^@]+\.[^@]+", donnee['email'])): msg += "le format de l'e-mail '" + donnee['email'] + "' de la ligne " + str(ligne) +\ " n'est pas correct\n" if not((donnee['emol_sans_activite'] == "NON") or (donnee['emol_sans_activite'] == "ZERO") or (donnee['emol_sans_activite'] == "OUI")): msg += "l'émolument à payer même sans activité de la ligne " + str(ligne) + " doit valoir ZERO, NON ou OUI\n" donnee['emol_base_mens'], info = Outils.est_un_nombre(donnee['emol_base_mens'], "l'émolument de base", ligne) msg += info donnee['emol_fixe'], info = Outils.est_un_nombre(donnee['emol_fixe'], "l'émolument fixe", ligne) msg += info donnee['coef'], info = Outils.est_un_nombre(donnee['coef'], "le coefficient a", ligne) msg += info ligne += 1 self.donnees = donnees_dict self.verifie_coherence = 1 for classe in classes: if classe not in coefmachines.obtenir_classes(): msg += "la classe de tarif '" + classe + "' n'est pas présente dans les coefficients machines\n" if classe not in coefprests.obtenir_classes(): msg += "la classe de tarif '" + classe + "' n'est pas présente dans les coefficients prestations\n" if msg != "": msg = self.libelle + "\n" + msg print("msg : " + msg) Outils.affiche_message(msg) return 1 return 0
def sommes_par_projet(self, livraisons, reservations, acces, prestations, comptes): """ calcule les sommes par projets sous forme de dictionnaire : client->compte->projet->clés_sommes :param livraisons: livraisons importées et vérifiées :param reservations: réservations importées et vérifiées :param acces: accès machines importés et vérifiés :param prestations: prestations importées et vérifiées :param comptes: comptes importés et vérifiés """ if self.verification.a_verifier != 0: info = "Sommes : vous devez faire les vérifications avant de calculer les sommes" print(info) Outils.affiche_message(info) return spp = {} for acce in acces.donnees: id_compte = acce["id_compte"] co = comptes.donnees[id_compte] code_client = co["code_client"] if code_client not in spp: spp[code_client] = {} client = spp[code_client] if id_compte not in client: client[id_compte] = {} num_projet = acce["num_projet"] compte = client[id_compte] if num_projet not in compte: compte[num_projet] = self.nouveau_somme(Sommes.cles_somme_projet) projet = compte[num_projet] projet["intitule"] = acce["intitule_projet"] else: projet = compte[num_projet] projet["somme_p_pu"] += acce["pu"] projet["somme_p_pm"] += acce["pu"] projet["somme_p_qu"] += acce["qu"] projet["somme_p_qm"] += acce["qu"] projet["somme_p_om"] += acce["om"] projet["somme_p_nm"] += acce["om"] projet["somme_p_nm"] += acce["qu"] for reservation in reservations.donnees: id_compte = reservation["id_compte"] co = comptes.donnees[id_compte] code_client = co["code_client"] if code_client not in spp: spp[code_client] = {} client = spp[code_client] if id_compte not in client: client[id_compte] = {} num_projet = reservation["num_projet"] compte = client[id_compte] if num_projet not in compte: compte[num_projet] = self.nouveau_somme(Sommes.cles_somme_projet) projet = compte[num_projet] projet["intitule"] = reservation["intitule_projet"] else: projet = compte[num_projet] projet["somme_p_pv"] += reservation["pv"] projet["somme_p_pm"] += reservation["pv"] projet["somme_p_qv"] += reservation["qv"] projet["somme_p_qm"] += reservation["qv"] projet["somme_p_nm"] += reservation["qv"] for livraison in livraisons.donnees: id_compte = livraison["id_compte"] co = comptes.donnees[id_compte] code_client = co["code_client"] if code_client not in spp: spp[code_client] = {} client = spp[code_client] if id_compte not in client: client[id_compte] = {} num_projet = livraison["num_projet"] compte = client[id_compte] if num_projet not in compte: compte[num_projet] = self.nouveau_somme(Sommes.cles_somme_projet) projet = compte[num_projet] projet["intitule"] = livraison["intitule_projet"] else: projet = compte[num_projet] id_prestation = livraison["id_prestation"] prestation = prestations.donnees[id_prestation] projet["sommes_cat_m"][prestation["categorie"]] += livraison["montant"] projet["sommes_cat_r"][prestation["categorie"]] += livraison["rabais_r"] projet["tot_cat"][prestation["categorie"]] += livraison["montant"] - livraison["rabais_r"] self.sp = 1 self.sommes_projets = spp