소스 검색

NEW analytique2facture: squelette ok

olivier.massot 7 년 전
부모
커밋
8793999664
2개의 변경된 파일236개의 추가작업 그리고 9개의 파일을 삭제
  1. 231 8
      analytique2facture.py
  2. 5 1
      logging.yaml

+ 231 - 8
analytique2facture.py

@@ -4,18 +4,44 @@
 
     @author: olivier.massot, févr. 2018
 '''
+from datetime import datetime
 import logging
 import sys
 
 from path import Path
 
 from core import logconf
+from core.model import Model
 from core.pde import FacturesDb, AnalytiqueDb, CommunDb
 
 
 logger = logging.getLogger("analytique2facture")
 logconf.start("analytique2facture", logging.DEBUG)
 
+class EnTete(Model):
+    _FIELDS = ["lngPieceId", "lngDocId", "lngTiersId", "lngASTRE", "strCodeProduit", "bytTitreId",
+               "strCodeAdresse", "strAdresse1", "strAdresse2", "strAdresse3", "strAdresse4", "strAdresse5",
+               "strPaysIdIso3166", "bytTVATiersId", "strTelephone", "strTelecopie", "strPortable",
+               "strEMail", "strWeb", "strLangueIdIso639", "strCompteComptable", "strDeviseIdIso4217",
+               "bytReglementId", "strReglement", "bytClasseTarifId", "bytClasseRemiseTiersId", "bytNbExFacture",
+               "strStatTiers", "bytSituationIdPrincipale", "bytSituationIdSecondaire", "memObsEntete",
+               "memObsPied", "memObsInterne", "bytTypeDocumentId", "strStatDocEntete", "dblCoursDevise",
+               "dtmCoursDevise", "dtmCreation", "strUserIdCreation", "dtmLastMod", "strUserIdLastMod",
+               "dtmPiece", "dtmFirstPrint", "dtmLastPrint", "dtmCompta", "dtmLivraison", "dtmEcheance",
+               "bytTypeTarif", "idEtatEmission"]
+
+class Ligne(Model):
+    _FIELDS = ["lngPieceId", "intLigneId", "strArticleId", "strArticle", "bytTVAArticleId", "bytTVAId", "dblTVATaux",
+               "dblQte", "bytUniteIdQuantite", "bytNbDecQuantite", "bytUniteIdPrix", "dblCnvUniteCoef",
+               "bytNbDecQuantiteConvertie", "dblPUhtBrutDev", "dblPUttcBrutDev", "dblPUhtNetDev", "dblPUttcNetDev",
+               "bytNbDecPU", "dblPThtBrutDev", "dblPTttcBrutDev", "dblPThtNetDev", "dblPTttcNetDev", "strStatArticle",
+               "strStatDocLigne", "dblTauxRemise1", "dblTauxRemise2", "dblTauxRemise3", "blnPrestation",
+               "strCompteComptable", "memObs", "memObsInterne", "bytLigneSousTotal", "intLigneIdRattachement",
+               "blnLigneVisible", "blnLigneGeneree", "bytGenerateurId", "dblPUhtBrut", "dblPUttcBrut", "dblPUhtNet",
+               "dblPUttcNet", "dblPThtBrut", "dblPTttcBrut", "dblPThtNet", "dblPTttcNet", "bytClasseRemiseArticleId",
+               "dblPUSaisie", "strPUAff", "strQteAff"]
+
+
 # # POUR TESTER, décommenter les lignes suivantes
 ##-----------------------------------------------
 
@@ -35,26 +61,223 @@ facture_db = FacturesDb(autocommit=False)
 # Connexion à CommunDb
 commun_db = CommunDb(autocommit=False)
 
-mois_facturation = input("Veuillez renseigner le mois de facturation ('q' pour quitter): ")  # Format: voir avec jacky
-if mois_facturation == 'q':
-    sys.exit(1)
+# mois_facturation = input("Veuillez renseigner le mois de facturation ('q' pour quitter): ")  # Format: voir avec jacky
+# if mois_facturation == 'q':
+#     sys.exit(1)
+mois_facturation = "1801"
 
 sql = """SELECT * FROM tbl_Tarification
         WHERE strStatut='A facturer'
         ORDER BY DblAffaireId, DblTarifId DESC;
         """
 
-if not analytique_db.exists(sql):
+# Liste les interventions à facturer par affaire
+a_facturer = {}
+for interv in analytique_db.read(sql):
+    if not interv.DblAffaireId in a_facturer.keys():
+        a_facturer[interv.DblAffaireId] = []
+    a_facturer[interv.DblAffaireId].append(interv)
+
+if not a_facturer:
     logger.info("Aucune facture à créer - Opération annulée")
     sys.exit(1)
 
 
-# On va créer une facture commune à toutes les interventions 'à facturer' d'une même affaire (cad qui ont un numéro de pièce commun)
-# > Pour chaque facture, on va ajouter une ligne dans tblPieceEntete, et une ligne par intervention dans tblPieceLigne
+# Pour chaque facture, on va ajouter une ligne dans tblPieceEntete, et une ligne par intervention dans tblPieceLigne
 # > NB: On ne touche pas aux interventions de cette affaire qui ont déja été facturées
 
-for tarif in analytique_db.read(sql):
-    pass
+
+for affaireId, interventions in a_facturer.items():
+
+    piece_id = facture_db.first("SELECT Max(lngpieceId) As Id FROM tblPieceEntete").Id + 1
+    if str(piece_id)[:2] != mois_facturation[:2]:
+        # On démarre une nouvelle année
+        piece_id = 10000 * int(mois_facturation[:2]) + 1
+
+    affaire = analytique_db.first("SELECT * FROM tbl_Affaires WHERE dblAffaireId={}".format(affaireId))
+    if not affaire:
+        logger.error("Affaire {} - L'affaire n'existe pas dans tbl_Affaires".format(affaireId))
+        continue
+
+    if not affaire.strMOId:
+        logger.error("Affaire {} - Destinataire manquant dans tbl_Affaires".format(affaireId))
+        continue
+
+    destinataire = commun_db.first("SELECT * FROM tblTiers WHERE lngTiersId={}".format(affaire.strMOId))
+    if not destinataire:
+        logger.warning("Affaire {} - Destinataire introuvable dans tblTiers ('{}'), remplacé par tiers n°190".format(affaireId, affaire.strMOId))
+        destinataire = commun_db.first("SELECT * FROM tblTiers WHERE lngTiersId=190")
+
+    entete = EnTete()
+    entete.lngPieceId = piece_id
+
+    # on recupere les champs de tblTiers depuis le champ lngASTRE (champ n°3) jusqu'au champ strCodeProduit (champ n°26)
+    # ATTENTION: le champ 'strPaysIdIso3166-A2' n'etant pas un nom de propriété valide, il est renomme en strPaysIdIso3166 dans le modèle.
+    entete.lngTiersId = destinataire.lngTiersId
+    entete.lngASTRE = destinataire.lngASTRE
+    entete.bytTitreId = destinataire.bytTitreId
+    entete.strCodeAdresse = destinataire.strCodeAdresse
+    entete.strAdresse1 = destinataire.strAdresse1
+    entete.strAdresse2 = destinataire.strAdresse2
+    entete.strAdresse3 = destinataire.strAdresse3
+    entete.strAdresse4 = destinataire.strAdresse4
+    entete.strAdresse5 = destinataire.strAdresse5
+    entete.strPaysIdIso3166 = destinataire.field_11
+    entete.bytTVATiersId = destinataire.bytTVATiersId
+    entete.strTelephone = destinataire.strTelephone
+    entete.strTelecopie = destinataire.strTelecopie
+    entete.strPortable = destinataire.strPortable
+    entete.strEMail = destinataire.strEMail
+    entete.strWeb = destinataire.strWeb
+    entete.strLangueIdIso639 = destinataire.strLangueIdIso639
+    entete.strCompteComptable = destinataire.strCompteComptable
+    entete.strDeviseIdIso4217 = destinataire.strDeviseIdIso4217
+    entete.bytReglementId = destinataire.bytReglementId
+    entete.bytClasseTarifId = destinataire.bytClasseTarifId
+    entete.bytNbExFacture = destinataire.bytNbExFacture
+    entete.bytClasseRemiseTiersId = destinataire.bytClasseRemiseTiersId
+    entete.bytNbExFacture = destinataire.bytNbExFacture
+    entete.strStatTiers = destinataire.strStatTiers
+
+    # Valeurs fixes
+    entete.lngDocId = 0
+    entete.strLangueIdIso639 = "fr"
+    entete.strDeviseIdIso4217 = "EUR"
+    entete.bytReglementId = 1
+    entete.bytClasseTarifId = 1
+    entete.bytClasseRemiseTiersId = 1
+    entete.bytNbExFacture = 1
+    entete.strStatTiers = ""
+    entete.bytSituationIdPrincipale = 2
+    entete.bytSituationIdSecondaire = 41
+    entete.bytTypeDocumentId = 50
+    entete.strStatDocEntete = "PI00"
+    entete.dblCoursDevise = 1
+    entete.dtmCoursDevise = datetime(2002, 1, 1)
+    entete.bytTypeTarif = 1
+    entete.strReglement = "POUR ACQUITTER CET ETAT DE REDEVANCE,\nATTENDEZ IMPERATIVEMENT DE RECEVOIR LE TITRE DE PERCEPTION EMANANT DE LA PAIERIE DEPARTEMENTALE"
+
+    # Commentaires
+    entete.memObsEntete = """[Mois : {mois_facturation}]\n [Lieu de travail : ] {affaire.strLieux}\n [V/Cde : ] {affaire.Ref} du {affaire.dtmCommande}
+                          """.format(mois_facturation, affaire)
+
+    entete.memObsInterne = "N° Affaire analytique : {}".format(affaire.stLiaisonControle)
+
+    entete.strStatDocEntete = "PC00" if ("/" in affaire.stLiaisonControle or affaire.stLiaisonControle == "RDBOEC") else "PT00"
+
+    entete.strUserIdCreation = "analytique2facture"
+    entete.strUserIdLastMod = "analytique2facture"
+
+    i = 0
+    lignes = []
+    for interv in interventions:
+        i += 1
+
+        ligne = Ligne()
+        ligne.lngPieceId = piece_id
+        ligne.intLigneId = i
+        ligne.strArticleId = interv.strArticleId
+
+        article = commun_db.first("SELECT * FROM tblArticle WHERE strArticleId='{}'".format(interv.strArticleId))
+        ligne.strArticle = article.strArticle if article else ""
+        ligne.bytTVAArticleId = article.bytTVAArticleId if article else 0
+
+        tva = commun_db.first("SELECT bytTVAId FROM tblTVA WHERE bytTVATiersId={} AND bytTVAArticleId={}".format(destinataire.bytTVATiersId, ligne.bytTVAArticleId))
+        ligne.bytTVAId = tva.bytTVAId
+
+        taux = commun_db.first("SELECT dblTVATaux FROM tblTVATaux WHERE bytTVAId={}".format(ligne.bytTVAId))
+        ligne.dblTVATaux = taux.dblTVATaux
+
+        ligne.dblQte = interv.dblquantite
+
+        unite = commun_db.first("SELECT * FROM tblUnite WHERE strUniteCourt='{}'".format(interv.strunite))
+        ligne.bytUniteIdQuantite = unite.bytUniteId
+        ligne.bytUniteIdPrix = unite.bytUniteId
+        ligne.dblPUhtBrutDev = interv.dblPrixUnitaire
+        ligne.dblPUhtNetDev = interv.dblPrixUnitaire
+        ligne.dblPThtNetDev = interv.dblPrixTotal
+        ligne.blnPrestation = True
+        ligne.memObs = "Intervention le {}{}".format(interv.dtmFin,
+                                                                             "\nRapport no : {}".format(interv.strRapportId) if interv.strRapportId else "")
+        ligne.blnLigneGeneree = True
+        ligne.bytGenerateurId = 1
+        ligne.dblPThtNet = interv.dblPrixTotal
+        ligne.bytClasseRemiseArticleId = 1
+        ligne.dblPUSaisie = interv.dblPrixUnitaire
+        ligne.strPUAff = "{} EUR/{}".format(interv.dblPrixUnitaire, interv.strunite)
+        ligne.strQteAff = "{:03.02f} {}".format(interv.dblquantite, interv.strunite)
+
+        lignes.append(ligne)
+
+    # Toutes les lignes ont été ajoutées: on créé maintenant les lignes de totaux
+    montant_ht = sum([ligne.dblPThtNetDev for ligne in lignes])
+    taux_tva = lignes[0].dblTVATaux
+    montant_tva = (0.01 * taux_tva) * montant_ht
+    montant_ttc = montant_ht + montant_tva
+
+    # Sous-total HT (ligne 32000)
+    ligne_total_1 = Ligne()
+    ligne_total_1.lngPieceId = piece_id
+    ligne_total_1.intLigneId = 32000
+    ligne_total_1.strArticleId = ""
+    ligne_total_1.strArticle = "Total H.T."
+    ligne_total_1.dblPThtNetDev = montant_ht
+    ligne_total_1.dblPTttcNetDev = montant_ttc
+    ligne_total_1.bytLigneSousTotal = 10
+    ligne_total_1.blnLigneVisible = False
+    ligne_total_1.dblPThtNet = montant_ht
+    ligne_total_1.dblPTttcNet = round(montant_ttc, 2)
+    ligne_total_1.dblPUSaisie = round(montant_ht, 2)
+    ligne_total_1.strPUAff = "{:03.02f} EUR".format(montant_ht)
+
+    lignes.append(ligne_total_1)
+
+    # Sous-total TVA (ligne 32001)
+    ligne_total_2 = Ligne()
+    ligne_total_2.lngPieceId = piece_id
+    ligne_total_2.intLigneId = 32001
+    ligne_total_2.strArticleId = ""
+    ligne_total_2.strArticle = """TVA 1 : {taux_tva}% H.T. : {montant_ht:03.02f} T.V.A. :
+                                 {montant_tva:03.02f} T.T.C. : {montant_ttc:03.02f}:""".format(taux_tva=taux_tva,
+                                                                                               montant_ht=montant_ht,
+                                                                                               montant_tva=montant_tva,
+                                                                                               montant_ttc=montant_ttc)
+    ligne_total_2.bytTVAId = lignes[0].bytTVAId
+    ligne_total_2.dblTVATaux = taux_tva
+    ligne_total_2.dblPThtNetDev = montant_ht
+    ligne_total_2.dblPTttcNetDev = montant_ttc
+    ligne_total_2.bytLigneSousTotal = 11
+    ligne_total_2.blnLigneVisible = False
+    ligne_total_2.dblPThtNet = montant_ht
+    ligne_total_2.dblPTttcNet = round(ligne_total_1.dblPTttcNetDev, 2)
+    ligne_total_2.dblPUSaisie = round(montant_tva, 2)
+    ligne_total_2.strPUAff = "{:03.02f} EUR".format(montant_tva)
+
+    lignes.append(ligne_total_2)
+
+    # Sous-total TTC (ligne 32500)
+    ligne_total_3 = Ligne()
+    ligne_total_3.lngPieceId = piece_id
+    ligne_total_3.intLigneId = 32500
+    ligne_total_3.strArticleId = ""
+    ligne_total_3.strArticle = "Total T.T.C."
+    ligne_total_3.dblPThtNetDev = montant_ht
+    ligne_total_3.dblPTttcNetDev = montant_ttc
+    ligne_total_3.bytLigneSousTotal = 12
+    ligne_total_3.blnLigneVisible = False
+    ligne_total_3.dblPThtNet = montant_ttc
+    ligne_total_3.dblPTttcNet = round(montant_ttc, 2)
+    ligne_total_3.dblPUSaisie = round(montant_ttc, 2)
+    ligne_total_3.strPUAff = "{:03.02f} EUR".format(montant_ttc)
+
+    lignes.append(ligne_total_3)
+
+
+# Insérer les données dans tbl_Facture
+
+# Maj tbl_Tarification.strNumFacture et strStatut pour marquer la ligne comme facturée.
+
+
 
 
 

+ 5 - 1
logging.yaml

@@ -47,6 +47,10 @@ loggers:
         level: DEBUG
         handlers: [console, file, mail]
         propagate: no
+    analytique2facture:
+        level: DEBUG
+        handlers: [console, file, mail]
+        propagate: no
     pda2suiviactivite:
         level: DEBUG
         handlers: [console]
@@ -54,7 +58,7 @@ loggers:
     mails_rappel_ctrl:
         level: DEBUG
         handlers: [console, file,mail]
-        propagate: no       
+        propagate: no
           
 root:
     level: DEBUG