Bläddra i källkod

NE analytique2facture - Script ok

olivier.massot 7 år sedan
förälder
incheckning
61e623f021
3 ändrade filer med 152 tillägg och 45 borttagningar
  1. 125 44
      analytique2facture.py
  2. 1 1
      core/db.py
  3. 26 0
      resources/test_analytique2facture.py

+ 125 - 44
analytique2facture.py

@@ -6,6 +6,7 @@
 '''
 from datetime import datetime
 import logging
+import string
 import sys
 
 from path import Path
@@ -19,28 +20,46 @@ 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"]
+    pass
 
 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"]
-
+    def __init__(self):
+        # Valeurs fixes
+        self.bytNbDecQuantite = 2
+        self.dblCnvUniteCoef = 1
+        self.bytNbDecQuantiteConvertie = 2
+        self.bytNbDecPU = 2
+        self.bytLigneSousTotal = 1
+        self.intLigneIdRattachement = 0
+        self.blnLigneVisible = True
+        self.blnLigneGeneree = False
+        self.bytGenerateurId = 0
+        self.bytClasseRemiseArticleId = 0
+        self.bytTVAArticleId = 0
+        self.bytTVAId = 0
+        self.dblTVATaux = 0
+        self.bytUniteIdQuantite = 0
+        self.bytUniteIdPrix = 0
+
+class SqlFormatter(string.Formatter):
+    def format_field(self, value, format_spec):
+        if value is None:
+            value = "Null"
+            format_spec = ""
+        if format_spec == "date":
+            value = "#{:%Y-%m-%d %H:%M:%S}#".format(value)
+            format_spec = ""
+
+        formatted = super().format_field(value, "")
+        formatted = formatted.replace("'", "''")
+        formatted = formatted.replace("\"", "''")
+        formatted = formatted.replace("\t", " ")
+
+        if format_spec == "text":
+            formatted = "'{}'".format(formatted)
+
+        return formatted
+Sql = SqlFormatter()
 
 # # POUR TESTER, décommenter les lignes suivantes
 ##-----------------------------------------------
@@ -61,10 +80,11 @@ 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
+current = "{:%m/%Y}".format(datetime.now())
+# mois_facturation = input("Veuillez renseigner le mois de facturation [defaut: {}] ('q' pour quitter): ".format(current))  # Format: voir avec jacky
 # if mois_facturation == 'q':
 #     sys.exit(1)
-mois_facturation = "1801"
+mois_facturation = "01/2018"
 
 sql = """SELECT * FROM tbl_Tarification
         WHERE strStatut='A facturer'
@@ -82,15 +102,13 @@ if not a_facturer:
     logger.info("Aucune facture à créer - Opération annulée")
     sys.exit(1)
 
-
 # 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 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]:
+    if str(piece_id)[:2] != mois_facturation[-2:]:
         # On démarre une nouvelle année
         piece_id = 10000 * int(mois_facturation[:2]) + 1
 
@@ -115,6 +133,7 @@ for affaireId, interventions in a_facturer.items():
     # 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.strCodeProduit = destinataire.strCodeProduit
     entete.bytTitreId = destinataire.bytTitreId
     entete.strCodeAdresse = destinataire.strCodeAdresse
     entete.strAdresse1 = destinataire.strAdresse1
@@ -155,18 +174,21 @@ for affaireId, interventions in a_facturer.items():
     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"
+    entete.strReglement = "POUR ACQUITTER CET ETAT DE REDEVANCE, ATTENDEZ 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.memObsEntete = "[Mois : {mois_facturation}] " \
+                          "[Lieu de travail : ]{affaire.strLieux} " \
+                          "[V/Cde : ] {affaire.Ref} du {affaire.dtmCommande:%d/%m/%Y}" \
+                          "".format(mois_facturation=mois_facturation,
+                                    affaire=affaire).replace("'", "")
 
-    entete.memObsInterne = "N° Affaire analytique : {}".format(affaire.stLiaisonControle)
+    entete.memObsInterne = "N° Affaire analytique : {}".format(affaire.strLiaisonControle)
 
-    entete.strStatDocEntete = "PC00" if ("/" in affaire.stLiaisonControle or affaire.stLiaisonControle == "RDBOEC") else "PT00"
+    entete.strStatDocEntete = "PC00" if ("/" in affaire.strLiaisonControle or affaire.strLiaisonControle == "RDBOEC") else "PT00"
 
-    entete.strUserIdCreation = "analytique2facture"
-    entete.strUserIdLastMod = "analytique2facture"
+    entete.strUserIdCreation = "script"
+    entete.strUserIdLastMod = "script"
 
     i = 0
     lignes = []
@@ -188,30 +210,29 @@ for affaireId, interventions in a_facturer.items():
         taux = commun_db.first("SELECT dblTVATaux FROM tblTVATaux WHERE bytTVAId={}".format(ligne.bytTVAId))
         ligne.dblTVATaux = taux.dblTVATaux
 
-        ligne.dblQte = interv.dblquantite
+        ligne.dblQte = interv.dblQuantite
 
-        unite = commun_db.first("SELECT * FROM tblUnite WHERE strUniteCourt='{}'".format(interv.strunite))
+        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.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)
+        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_ht = float(sum([ligne.dblPThtNetDev for ligne in lignes]))
+    taux_tva = float(lignes[0].dblTVATaux)
     montant_tva = (0.01 * taux_tva) * montant_ht
     montant_ttc = montant_ht + montant_tva
 
@@ -273,11 +294,71 @@ for affaireId, interventions in a_facturer.items():
     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.
-
 
+    logger.info("* Nouvelle facture: {}".format(entete.lngPieceId))
+
+    # Insertion de l'en-tête
+    sql = Sql.format("""
+            INSERT INTO tblPieceEntete ( lngPieceId, lngDocId, lngTiersId, lngASTRE, strCodeProduit, bytTitreId, strCodeAdresse, strAdresse1, strAdresse2,
+                                        strAdresse3, strAdresse4, strAdresse5, [strPaysIdIso3166-A2], bytTVATiersId, strTelephone, strTelecopie, strPortable,
+                                        strEMail, strWeb, strLangueIdIso639, strCompteComptable, strDeviseIdIso4217, bytReglementId, strReglement,
+                                        bytClasseTarifId, bytClasseRemiseTiersId, bytNbExFacture, strStatTiers, bytSituationIdPrincipale, bytSituationIdSecondaire,
+                                        memObsEntete, memObsInterne, bytTypeDocumentId, strStatDocEntete, dblCoursDevise, dtmCoursDevise,
+                                        strUserIdCreation, strUserIdLastMod )
+            VALUES ({entete.lngPieceId}, {entete.lngDocId}, {entete.lngTiersId}, {entete.lngASTRE}, {entete.strCodeProduit:text}, {entete.bytTitreId},
+                    {entete.strCodeAdresse:text}, {entete.strAdresse1:text}, {entete.strAdresse2:text}, {entete.strAdresse3:text}, {entete.strAdresse4:text}, {entete.strAdresse5:text},
+                    {entete.strPaysIdIso3166:text}, {entete.bytTVATiersId}, {entete.strTelephone:text}, {entete.strTelecopie:text}, {entete.strPortable:text}, {entete.strEMail:text},
+                    {entete.strWeb:text}, {entete.strLangueIdIso639:text}, {entete.strCompteComptable:text}, {entete.strDeviseIdIso4217:text}, {entete.bytReglementId},
+                    {entete.strReglement:text}, {entete.bytClasseTarifId}, {entete.bytClasseRemiseTiersId}, {entete.bytNbExFacture}, {entete.strStatTiers:text},
+                    {entete.bytSituationIdPrincipale}, {entete.bytSituationIdSecondaire}, {entete.memObsEntete:text}, {entete.memObsInterne:text},
+                    {entete.bytTypeDocumentId}, {entete.strStatDocEntete:text}, {entete.dblCoursDevise}, {entete.dtmCoursDevise:date},
+                    {entete.strUserIdCreation:text}, {entete.strUserIdLastMod:text})
+            """, entete=entete)
+
+    logger.debug(sql)
+    facture_db.execute(sql)
+
+    for ligne in lignes:
+
+        # Complete les champs manquants
+        for field in ["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"]:
+            if not hasattr(ligne, field):
+                setattr(ligne, field, None)
+
+
+        sql = Sql.format("""
+                INSERT INTO tblPieceLigne ( 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 )
+                VALUES ({ligne.lngPieceId}, {ligne.intLigneId}, {ligne.strArticleId:text}, {ligne.strArticle:text}, {ligne.bytTVAArticleId}, {ligne.bytTVAId}, {ligne.dblTVATaux},
+                        {ligne.dblQte}, {ligne.bytUniteIdQuantite}, {ligne.bytNbDecQuantite}, {ligne.bytUniteIdPrix}, {ligne.dblCnvUniteCoef}, {ligne.bytNbDecQuantiteConvertie},
+                        {ligne.dblPUhtBrutDev}, {ligne.dblPUttcBrutDev}, {ligne.dblPUhtNetDev}, {ligne.dblPUttcNetDev}, {ligne.bytNbDecPU}, {ligne.dblPThtBrutDev},
+                        {ligne.dblPTttcBrutDev}, {ligne.dblPThtNetDev}, {ligne.dblPTttcNetDev}, {ligne.strStatArticle:text}, {ligne.strStatDocLigne:text},
+                        {ligne.dblTauxRemise1}, {ligne.dblTauxRemise2}, {ligne.dblTauxRemise3}, {ligne.blnPrestation}, {ligne.strCompteComptable:text},
+                        {ligne.memObs:text}, {ligne.memObsInterne:text}, {ligne.bytLigneSousTotal}, {ligne.intLigneIdRattachement}, {ligne.blnLigneVisible},
+                        {ligne.blnLigneGeneree}, {ligne.bytGenerateurId}, {ligne.dblPUhtBrut}, {ligne.dblPUttcBrut}, {ligne.dblPUhtNet}, {ligne.dblPUttcNet},
+                        {ligne.dblPThtBrut}, {ligne.dblPTttcBrut}, {ligne.dblPThtNet}, {ligne.dblPTttcNet}, {ligne.bytClasseRemiseArticleId}, {ligne.dblPUSaisie},
+                        {ligne.strPUAff:text}, {ligne.strQteAff:text})
+                """, ligne=ligne)
+        logger.debug(sql)
+        facture_db.execute(sql)
+
+        # Maj tbl_Tarification.strNumFacture et strStatut pour marquer la ligne comme facturée.
+        sql = Sql.format(""" UPDATE tbl_Tarification SET strStatut = 'Facturée', strNumFacture = '{}'
+                              WHERE DblTarifId={}; """, piece_id, interv.DblTarifId)
+        logger.debug(sql)
+        analytique_db.execute(sql)
+
+    facture_db.commit()
+    analytique_db.commit()
 
 
 

+ 1 - 1
core/db.py

@@ -154,7 +154,7 @@ class AccessSqlHelper(SQLHelper):
         elif type(val) is int or type(val) is bool:
             return "{}".format(val)
         elif type(val) is str:
-            return "'{}'".format(val)
+            return "\"{}\"".format(val)
         elif type(val) is datetime:
             return "#{:%Y-%m-%d %H:%M:%S}#".format(val)
         return "{}".format(val)

+ 26 - 0
resources/test_analytique2facture.py

@@ -0,0 +1,26 @@
+'''
+
+@author: olivier.massot
+'''
+from path import Path
+
+from core.pde import AnalytiqueDb, FacturesDb
+
+
+# reinitialise les données pour les tests de ctrl2analytique.py
+AnalytiqueDb._path = Path(r"\\h2o\local\4-transversal\BDD\mdb_test\Db_analytique.mdb")
+FacturesDb._path = Path(r"\\h2o\local\4-transversal\BDD\mdb_test\Facture_data.mdb")
+
+analytique_db = AnalytiqueDb(autocommit=False)
+facture_db = FacturesDb(autocommit=False)
+
+for num_aff in ("175256/1", "175195/1"):
+
+    num_piece = facture_db.first("SELECT * FROM tblPieceEntete WHERE memObsInterne='N° Affaire analytique : {}'".format(num_aff)).lngPieceId
+
+    facture_db.execute("DELETE * FROM tblPieceEntete WHERE lngPieceId={}".format(num_piece))
+    facture_db.execute("DELETE * FROM tblPieceLigne WHERE lngPieceId={}".format(num_piece))
+    analytique_db.execute("UPDATE tbl_Tarification SET strStatut = 'A facturer', strNumFacture = Null WHERE strNumFacture='{}'".format(num_piece))
+
+    facture_db.commit()
+    analytique_db.commit()