|
|
@@ -3,20 +3,16 @@
|
|
|
la base de données ASTRE-GF vers les tables de la base Analytique
|
|
|
du Parc Départemental d'Erstein
|
|
|
|
|
|
- En cas d'erreur avec les données importées:
|
|
|
- 1. une tentative d'autocorrection est effectuée
|
|
|
- 2. Si les données sont toujours invalides, une ligne est ajoutée au fichier .\\work\\gf2analytique\\err.csv
|
|
|
- pour une correction manuelle.
|
|
|
+ L'import se déroule en trois étapes:
|
|
|
|
|
|
- IMPORTANT: Si le fichier 'err.csv' contient des lignes, le script tentera d'importer
|
|
|
- ces lignes à la place de celles issues de Astre Gf.
|
|
|
- Pour forcer un imprt depuis AstreGf, supprimez le fichier 'err.csv'
|
|
|
-
|
|
|
- Info: Les données sont obtenues via le web service CG67.AstreGf
|
|
|
+ 1- chargement des données issues de Astre (via le web service CG67.AstreGf) dans le fichier /work/gf2analytique/import.csv
|
|
|
+ 2- Contrôle de la validité des données, prompt éventuel pour une correction des donneés
|
|
|
+ 3- Une fois les données valides, import dans Analytique
|
|
|
|
|
|
'''
|
|
|
import logging
|
|
|
import re
|
|
|
+import sys
|
|
|
|
|
|
from path import Path # @UnusedImport
|
|
|
|
|
|
@@ -31,15 +27,18 @@ logconf.start("gf2analytique", logging.DEBUG)
|
|
|
# # POUR TESTER, décommenter les lignes suivantes
|
|
|
##-----------------------------------------------
|
|
|
|
|
|
-logger.warning("<<<<<<<<<<<<<< Mode TEST >>>>>>>>>>>>>>>>>")
|
|
|
-GfWebservice._url = r"http://webservices-t.bas-rhin.fr/CG67.AstreGF.WebServices/public/WsPDE.asmx"
|
|
|
-AnalytiqueDb._path = Path(r"\\h2o\local\4-transversal\BDD\mdb_test\Db_analytique.mdb")
|
|
|
+# logger.warning("<<<<<<<<<<<<<< Mode TEST >>>>>>>>>>>>>>>>>")
|
|
|
+# GfWebservice._url = r"http://webservices-t.bas-rhin.fr/CG67.AstreGF.WebServices/public/WsPDE.asmx"
|
|
|
+# AnalytiqueDb._path = Path(r"\\h2o\local\4-transversal\BDD\mdb_test\Db_analytique.mdb")
|
|
|
|
|
|
##-----------------------------------------------
|
|
|
|
|
|
+# *** Initialisation
|
|
|
+logger.info("Initialisation...")
|
|
|
|
|
|
-
|
|
|
-logger.info("Initialization")
|
|
|
+no_prompt = ("-n" in sys.argv)
|
|
|
+if no_prompt:
|
|
|
+ logger.info("> Lancé en mode automatique (sans interruption)")
|
|
|
|
|
|
# Connect to factures.mdb
|
|
|
analytique_db = AnalytiqueDb(autocommit=False)
|
|
|
@@ -49,80 +48,57 @@ ws = GfWebservice("GetPDEFactures")
|
|
|
|
|
|
# Make the working directory
|
|
|
workdir = mk_workdir("gf2analytique")
|
|
|
-errfile = workdir / "err.csv"
|
|
|
-
|
|
|
-class AlreadyImported(Exception):
|
|
|
- pass
|
|
|
-
|
|
|
-class NotImported(Exception):
|
|
|
- pass
|
|
|
+importfile = workdir / "import.csv"
|
|
|
|
|
|
-class InvalidData(Exception):
|
|
|
- pass
|
|
|
+# > Supprime le fichier d'import s'il existe, et le recréé avec la ligne d'en-tête
|
|
|
+if importfile.exists():
|
|
|
+ logger.debug("Supprime le fichier %s", importfile)
|
|
|
+ importfile.remove()
|
|
|
|
|
|
-class InvalidAxe(Exception):
|
|
|
- pass
|
|
|
|
|
|
class Facture():
|
|
|
- WS_FIELDS = ["numExBudget", "codeColl", "codeBudg", "numEnv", "codeSection", "typeMvt", "numMandat", "numLiqMandat",
|
|
|
+ """ Modèle de données d'une facture """
|
|
|
+ _FIELDS = ["numExBudget", "codeColl", "codeBudg", "numEnv", "codeSection", "typeMvt", "numMandat", "numLiqMandat",
|
|
|
"numLigneMandat", "codeAxe", "libAxe", "codeCout", "libCout", "dateMandat", "numBj", "numTiers",
|
|
|
"libRai", "refIntMandat", "codePeriode", "dateDepDelai", "typeNomencMarche", "mntTtcMandat",
|
|
|
"mntTvaMandat", "mntVent"]
|
|
|
- def __init__(self):
|
|
|
- self._factureId = None
|
|
|
|
|
|
- for fld in self.WS_FIELDS:
|
|
|
+ def __init__(self):
|
|
|
+ """ Génère un objet facture vide, les propriétés sont générrées automatiquement à partir de la variable _FIELDS"""
|
|
|
+ for fld in self._FIELDS:
|
|
|
setattr(self, fld, None)
|
|
|
|
|
|
- @property
|
|
|
- def factureId(self):
|
|
|
- if self._factureId is None:
|
|
|
- try:
|
|
|
- self._factureId = self._get_facture_id()
|
|
|
- except (KeyError, AttributeError, TypeError):
|
|
|
- raise NotImported()
|
|
|
- return self._factureId
|
|
|
-
|
|
|
@classmethod
|
|
|
- def from_webservice(cls, wsdata):
|
|
|
+ def from_dict(cls, data):
|
|
|
+ """ Retourne un objet Facture à partir d'un dictionnaire de données """
|
|
|
facture = cls()
|
|
|
- for key, value in wsdata.items():
|
|
|
+ for key, value in data.items():
|
|
|
setattr(facture, key, value)
|
|
|
- facture.autocorrection()
|
|
|
return facture
|
|
|
|
|
|
- @classmethod
|
|
|
- def from_errfile(cls, line):
|
|
|
- return cls.from_webservice(dict(zip(cls.WS_FIELDS, line.split("\t"))))
|
|
|
-
|
|
|
- def is_imported(self):
|
|
|
- try:
|
|
|
- return self.factureId > 0
|
|
|
- except NotImported:
|
|
|
- return False
|
|
|
-
|
|
|
- def _init_errfile(self):
|
|
|
- try:
|
|
|
- with open(errfile, 'r') as f:
|
|
|
- if f.read(100):
|
|
|
- # File already exists and is not empty
|
|
|
- return
|
|
|
- except FileNotFoundError:
|
|
|
- pass
|
|
|
+ def to_csv(self):
|
|
|
+ """ Renvoie une chaine de caractère correspondant aux données de la Facture au format CSV
|
|
|
+ Le séparateur est une tabulation (car c'est un caractère interdit dans Access) """
|
|
|
+ return "\t".join([str(getattr(self, field)).replace("\t", " ") for field in self._FIELDS] + ["\n"])
|
|
|
|
|
|
- firstline = "\t".join(self.WS_FIELDS + ["\n"])
|
|
|
- with open(errfile, 'a') as f:
|
|
|
- f.write(firstline)
|
|
|
-
|
|
|
- def dump_to_err(self):
|
|
|
- self._init_errfile()
|
|
|
+ @classmethod
|
|
|
+ def from_csv(cls, line):
|
|
|
+ """ Retourne un objet Facture à partir d'une ligne de texte au format CSV
|
|
|
+ Le séparateur est une tabulation (car c'est un caractère interdit dans Access) """
|
|
|
+ return cls.from_dict(dict(zip(cls._FIELDS, line.split("\t"))))
|
|
|
|
|
|
- line = "\t".join([str(getattr(self, field)).replace("\t", " ") for field in self.WS_FIELDS] + ["\n"])
|
|
|
+ def est_importee(self):
|
|
|
+ """ Renvoie True si la facture a déjà été importée dans Analytique
|
|
|
+ ATTENTION: en l'absence d'identifiants uniques, il est difficile de contrôler de manière certaine si une ligne a déjà été importée.
|
|
|
+ C'est pour cette raison que les données sont importées 'par blocs' """
|
|
|
|
|
|
- with open(errfile, 'a') as f:
|
|
|
- f.write(line)
|
|
|
+ sql = """SELECT dblFactureId FROM tbl_Factures
|
|
|
+ WHERE intExercice = {} AND strLiquidation = '{}' AND strEngagement = '{}' AND strService='7710'
|
|
|
+ """.format(self.numExBudget, self.numLiqMandat, self.numMandat)
|
|
|
+ return analytique_db.exists(sql)
|
|
|
|
|
|
def autocorrection(self):
|
|
|
+ """ Procède à certaines corrections automatiques sur les données de la facture """
|
|
|
# correction auto des codes chantiers
|
|
|
if self.codeAxe == "AFFAI" and re.match(r"\d{2}5\d{3}", self.codeCout):
|
|
|
self.codeCout += "/1"
|
|
|
@@ -141,223 +117,197 @@ class Facture():
|
|
|
def is_valid(self):
|
|
|
""" controle la validité des données d'une facture """
|
|
|
if not int(self.numExBudget) > 2000:
|
|
|
- logger.warning("Exercice budgetaire invalide: %s", self.numExBudget)
|
|
|
+ logger.error("Exercice budgetaire invalide: %s", self.numExBudget)
|
|
|
return False
|
|
|
if self.codeColl != "CG67":
|
|
|
- logger.warning("Code collectivité invalide: %s", self.codeColl)
|
|
|
+ logger.error("Code collectivité invalide: %s", self.codeColl)
|
|
|
return False
|
|
|
if self.codeBudg != "02":
|
|
|
- logger.warning("Code budgetaire invalide: %s", self.codeBudg)
|
|
|
+ logger.error("Code budgetaire invalide: %s", self.codeBudg)
|
|
|
return False
|
|
|
if self.codeAxe == "ENGIN":
|
|
|
# Controle l'existence du materiel
|
|
|
if not analytique_db.first("SELECT intlMaterielID FROM tbl_materiel WHERE txtMateriel='{}'".format(self.codeCout)):
|
|
|
- logger.warning("Le materiel n'existe pas: %s", self.codeCout)
|
|
|
+ logger.error("Le materiel n'existe pas: %s", self.codeCout)
|
|
|
return False
|
|
|
elif self.codeAxe == "AFFAI":
|
|
|
# Controle l'existence de l'affaire
|
|
|
if not analytique_db.first("SELECT dblAffaireId FROM tbl_Affaires WHERE strLiaisonControle='{}'".format(self.codeCout)):
|
|
|
- logger.warning("L'affaire n'existe pas: %s", self.codeCout)
|
|
|
+ logger.error("L'affaire n'existe pas: %s", self.codeCout)
|
|
|
return False
|
|
|
else:
|
|
|
# CodeAxe invalide
|
|
|
- logger.warning("Code axe inconnu: %s", self.codeAxe)
|
|
|
+ logger.error("Code axe inconnu: %s", self.codeAxe)
|
|
|
return False
|
|
|
return True
|
|
|
|
|
|
- def send_to_db(self):
|
|
|
|
|
|
- if self.is_imported():
|
|
|
- raise AlreadyImported()
|
|
|
|
|
|
- if not self.is_valid():
|
|
|
- raise InvalidData()
|
|
|
+# *** 1- Parcourt les factures renvoyées par le webservice, et stoque toutes les lignes non-importées dans Analytique dans un fichier import.csv
|
|
|
+logger.info("Parcourt les données fournies par le webservice")
|
|
|
+logger.info("(les ligne à importer sont ajoutées au fichier %s)", importfile)
|
|
|
|
|
|
- self._insert_factures()
|
|
|
+logger.debug("Génère le fichier %s", importfile)
|
|
|
+firstline = "\t".join(Facture._FIELDS + ["\n"])
|
|
|
+with open(importfile, 'w+') as f:
|
|
|
+ f.write(firstline)
|
|
|
|
|
|
- if self.codeAxe == "ENGIN":
|
|
|
- self._insert_factures_engins()
|
|
|
|
|
|
- elif self.codeAxe == "AFFAI":
|
|
|
- self._insert_factures_affaires()
|
|
|
+for data in ws:
|
|
|
+ # Génère la facture à partir des données fournies par le web-service
|
|
|
+ facture = Facture.from_dict(data)
|
|
|
|
|
|
- self._insert_mandatement()
|
|
|
+ # Contrôle si la facture est déjà importée. Si c'est le cas, passe à la facture suivante.
|
|
|
+ if facture.est_importee():
|
|
|
+ continue
|
|
|
|
|
|
- analytique_db.commit()
|
|
|
+ logger.info("* Facture %s/%s/%s: import", facture.numExBudget, facture.numMandat, facture.numLiqMandat)
|
|
|
|
|
|
- logger.info("* imported: %s", self.factureId)
|
|
|
+ # procède à une auto-correction des données
|
|
|
+ facture.autocorrection()
|
|
|
|
|
|
- def _get_facture_id(self):
|
|
|
- sql = """SELECT dblFactureId FROM tbl_Factures
|
|
|
- WHERE intExercice = {}
|
|
|
- AND strLiquidation = '{}'
|
|
|
- AND strEngagement = '{}'
|
|
|
- AND strService='7710'
|
|
|
- """.format(self.numExBudget,
|
|
|
- self.numLiqMandat,
|
|
|
- self.numMandat)
|
|
|
-
|
|
|
- factureId = analytique_db.first(sql).dblFactureId
|
|
|
- return factureId
|
|
|
-
|
|
|
- def _insert_factures(self):
|
|
|
- sql = """INSERT INTO tbl_Factures ( intExercice,
|
|
|
- strLiquidation,
|
|
|
- intLiquidationLigne,
|
|
|
- strEngagement,
|
|
|
- strEnveloppe,
|
|
|
- strService,
|
|
|
- strTiers,
|
|
|
- strTiersLibelle,
|
|
|
- strMotsClefs,
|
|
|
- dtmDeb,
|
|
|
- intOperation,
|
|
|
- strNomenclature0,
|
|
|
- strAXE,
|
|
|
- strCentreCout,
|
|
|
- strObjet,
|
|
|
- dblMontantTotal,
|
|
|
- dblMontantTVA,
|
|
|
- strORIGINE_DONNEES
|
|
|
+ # Ajoute les données au format CSV au fichier d'import
|
|
|
+ with open(importfile, 'a') as f:
|
|
|
+ f.write(facture.to_csv())
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+# *** 2- Contrôle les données. En cas d'erreur, le script est interrompu et la position et la description des erreurs sont loggés.
|
|
|
+errors = -1
|
|
|
+
|
|
|
+while errors:
|
|
|
+ errors = 0
|
|
|
+ logger.info("Contrôle des données")
|
|
|
+
|
|
|
+ # Parcourt les lignes du fichier d'import, et teste la validité de chacune.
|
|
|
+ with open(importfile) as f:
|
|
|
+ next(f) # saute la première ligne
|
|
|
+
|
|
|
+ for line in f:
|
|
|
+ facture = Facture.from_csv(line)
|
|
|
+
|
|
|
+ if not facture.is_valid():
|
|
|
+ errors += 1
|
|
|
+
|
|
|
+ if errors:
|
|
|
+ logger.error("<!> Une ou plusieurs erreurs ont été détectées, voir le fichier de log pour plus d'information <!>")
|
|
|
+ logger.info("Veuillez corriger les données du fichier %s", importfile)
|
|
|
+
|
|
|
+ # En cas d'erreur(s), deux possibilités:
|
|
|
+ # - Le script a été lancé en mode sans interruption avec l'option '-n', on interrompt le script.
|
|
|
+ # - Le script a été lancé normalement, sans option: on attend une correction manuelle de l'utilisateur.
|
|
|
+ if no_prompt:
|
|
|
+ sys.exit(errors)
|
|
|
+ else:
|
|
|
+ input("Presser une touche pour continuer...")
|
|
|
+
|
|
|
+
|
|
|
+logger.info("Les données sont valides.")
|
|
|
+
|
|
|
+# 3- Si toutes les données sont valides, parcourt les lignes du fichier import.csv et les insère dans la table tbl_Facture.
|
|
|
+logger.info("Mise à jour des tables de %s", AnalytiqueDb._path)
|
|
|
+
|
|
|
+with open(importfile) as f:
|
|
|
+ next(f) # saute la première ligne
|
|
|
+
|
|
|
+ for line in f:
|
|
|
+ facture = Facture.from_csv(line)
|
|
|
+
|
|
|
+ logger.info("* Facture %s/%s/%s: traitement", facture.numExBudget, facture.numMandat, facture.numLiqMandat)
|
|
|
+ # NB: les données ne sont committées qu'aprés l'exécution de toutes les requêtes suivantes
|
|
|
+
|
|
|
+ logger.info("> mise à jour de tbl_Factures")
|
|
|
+
|
|
|
+ # Insère les données dans la table tbl_Factures
|
|
|
+ sql = """INSERT INTO tbl_Factures ( intExercice, strLiquidation, intLiquidationLigne, strEngagement,
|
|
|
+ strEnveloppe, strService, strTiers, strTiersLibelle, strMotsClefs,
|
|
|
+ dtmDeb, intOperation, strNomenclature0, strAXE, strCentreCout,
|
|
|
+ strObjet, dblMontantTotal, dblMontantTVA, strORIGINE_DONNEES
|
|
|
)
|
|
|
- VALUES ({intExercice},
|
|
|
- '{strLiquidation}',
|
|
|
- {intLiquidationLigne},
|
|
|
- '{strEngagement}',
|
|
|
- '{strEnveloppe}',
|
|
|
- '{strService}',
|
|
|
- '{strTiers}',
|
|
|
- '{strTiersLibelle}',
|
|
|
- '{strMotsClefs}',
|
|
|
- #{dtmDeb}#,
|
|
|
- {intOperation},
|
|
|
- '{strNomenclature0}',
|
|
|
- '{strAxe}',
|
|
|
- '{strCentreCout}',
|
|
|
- '{strObjet}',
|
|
|
- {dblMontantTotal},
|
|
|
- {dblMontantTVA},
|
|
|
- '{strORIGINE_DONNEES}'
|
|
|
- )
|
|
|
+ VALUES ({intExercice}, '{strLiquidation}', {intLiquidationLigne}, '{strEngagement}',
|
|
|
+ '{strEnveloppe}', '{strService}', '{strTiers}', '{strTiersLibelle}', '{strMotsClefs}',
|
|
|
+ #{dtmDeb}#, {intOperation}, '{strNomenclature0}', '{strAxe}', '{strCentreCout}',
|
|
|
+ '{strObjet}', {dblMontantTotal}, {dblMontantTVA}, '{strORIGINE_DONNEES}')
|
|
|
""".format(
|
|
|
- intExercice=self.numExBudget,
|
|
|
- strLiquidation=self.numLiqMandat,
|
|
|
- intLiquidationLigne=self.numLigneMandat,
|
|
|
- strEngagement=self.numMandat,
|
|
|
- strEnveloppe=self.numEnv,
|
|
|
+ intExercice=facture.numExBudget,
|
|
|
+ strLiquidation=facture.numLiqMandat,
|
|
|
+ intLiquidationLigne=facture.numLigneMandat,
|
|
|
+ strEngagement=facture.numMandat,
|
|
|
+ strEnveloppe=facture.numEnv,
|
|
|
strService='7710',
|
|
|
- strTiers=self.numTiers,
|
|
|
- strTiersLibelle=self.libRai,
|
|
|
- strMotsClefs=AnalytiqueDb.nz(self.refIntMandat),
|
|
|
- dtmDeb=AnalytiqueDb.format_date(self.dateDepDelai),
|
|
|
- intOperation=AnalytiqueDb.nz(self.codePeriode, "Null"),
|
|
|
- strNomenclature0=self.typeNomencMarche,
|
|
|
- strAxe=self.codeAxe,
|
|
|
- strCentreCout=self.codeCout,
|
|
|
- strObjet=AnalytiqueDb.format_date(self.dateMandat, out_format="%d/%m/%Y"),
|
|
|
- dblMontantTVA=self.mntTvaMandat,
|
|
|
- dblMontantTotal=self.mntVent,
|
|
|
+ strTiers=facture.numTiers,
|
|
|
+ strTiersLibelle=facture.libRai,
|
|
|
+ strMotsClefs=AnalytiqueDb.nz(facture.refIntMandat),
|
|
|
+ dtmDeb=AnalytiqueDb.format_date(facture.dateDepDelai),
|
|
|
+ intOperation=AnalytiqueDb.nz(facture.codePeriode, "Null"),
|
|
|
+ strNomenclature0=facture.typeNomencMarche,
|
|
|
+ strAxe=facture.codeAxe,
|
|
|
+ strCentreCout=facture.codeCout,
|
|
|
+ strObjet=AnalytiqueDb.format_date(facture.dateMandat, out_format="%d/%m/%Y"),
|
|
|
+ dblMontantTVA=facture.mntTvaMandat,
|
|
|
+ dblMontantTotal=facture.mntVent,
|
|
|
strORIGINE_DONNEES='ASTRE'
|
|
|
)
|
|
|
logger.debug("> %s", sql)
|
|
|
analytique_db.execute(sql)
|
|
|
|
|
|
- def _insert_factures_engins(self):
|
|
|
- if self.codeAxe != "ENGIN":
|
|
|
- raise InvalidAxe()
|
|
|
-
|
|
|
- materiel = analytique_db.first("SELECT intlMaterielID FROM tbl_Materiel WHERE [txtMateriel]='{}'".format(self.codeCout))
|
|
|
- materielId = materiel.intlMaterielID if materiel else '859'
|
|
|
- logger.debug("retrieve intlMaterielID: %s", materielId)
|
|
|
-
|
|
|
- sql = """INSERT INTO tbl_Facture_Engin ( intlMaterielID, txtMateriel, dblFactureId, strLibelle, dblMontant, strType )
|
|
|
- VALUES ({}, '{}', {}, '{}', {}, '{}')
|
|
|
- """.format(materielId,
|
|
|
- self.codeCout,
|
|
|
- self.factureId,
|
|
|
- AnalytiqueDb.nz(self.libCout),
|
|
|
- self.mntVent,
|
|
|
- self.libRai
|
|
|
- )
|
|
|
- logger.debug("> %s", sql)
|
|
|
- analytique_db.execute(sql)
|
|
|
+ facture.factureId = analytique_db.first("SELECT TOP 1 dblFactureId FROM tbl_Factures ORDER BY dblFactureId DESC").dblFactureId
|
|
|
|
|
|
- def _insert_factures_affaires(self):
|
|
|
- if self.codeAxe != "AFFAI":
|
|
|
- raise InvalidAxe()
|
|
|
-
|
|
|
- sql = """INSERT INTO tbl_Facture_Affaire ( strAffaireId, dblFactureId, strLibelle, dblMontant, strType )
|
|
|
- VALUES ('{}', {}, '{}', {}, '{}')
|
|
|
- """.format(self.codeCout,
|
|
|
- self.factureId,
|
|
|
- self.libRai ,
|
|
|
- self.mntVent,
|
|
|
- AnalytiqueDb.nz(self.libCout),
|
|
|
- )
|
|
|
- logger.debug("> %s", sql)
|
|
|
- analytique_db.execute(sql)
|
|
|
|
|
|
- def _insert_mandatement(self):
|
|
|
+ if facture.codeAxe == "ENGIN":
|
|
|
+ # La ligne concerne un engin: insère les données dans la table tbl_Facture_Engin
|
|
|
+ logger.info("> mise à jour de tbl_Facture_Engin")
|
|
|
+
|
|
|
+ materiel = analytique_db.first("SELECT intlMaterielID FROM tbl_Materiel WHERE [txtMateriel]='{}'".format(facture.codeCout))
|
|
|
+ materielId = materiel.intlMaterielID if materiel else '859'
|
|
|
+ logger.debug("retrieve intlMaterielID: %s", materielId)
|
|
|
+
|
|
|
+ sql = """INSERT INTO tbl_Facture_Engin ( intlMaterielID, txtMateriel, dblFactureId, strLibelle, dblMontant, strType )
|
|
|
+ VALUES ({}, '{}', {}, '{}', {}, '{}')
|
|
|
+ """.format(materielId,
|
|
|
+ facture.codeCout,
|
|
|
+ facture.factureId,
|
|
|
+ AnalytiqueDb.nz(facture.libCout),
|
|
|
+ facture.mntVent,
|
|
|
+ facture.libRai
|
|
|
+ )
|
|
|
+ logger.debug("> %s", sql)
|
|
|
+ analytique_db.execute(sql)
|
|
|
+
|
|
|
+ elif facture.codeAxe == "AFFAI":
|
|
|
+ # La ligne concerne une affaire: insère les données dans la table tbl_Facture_Affaire
|
|
|
+ logger.info("> mise à jour de tbl_Facture_Affaire")
|
|
|
+
|
|
|
+ sql = """INSERT INTO tbl_Facture_Affaire ( strAffaireId, dblFactureId, strLibelle, dblMontant, strType )
|
|
|
+ VALUES ('{}', {}, '{}', {}, '{}')
|
|
|
+ """.format(facture.codeCout,
|
|
|
+ facture.factureId,
|
|
|
+ facture.libRai ,
|
|
|
+ facture.mntVent,
|
|
|
+ AnalytiqueDb.nz(facture.libCout),
|
|
|
+ )
|
|
|
+ logger.debug("> %s", sql)
|
|
|
+ analytique_db.execute(sql)
|
|
|
+
|
|
|
+
|
|
|
+ logger.info("> mise à jour de tbl_Mandatement")
|
|
|
+
|
|
|
+ # Insère les données dans la table tbl_Mandatement
|
|
|
sql = """INSERT INTO tbl_Mandatement ( dblFacture, strNumMandat, dtmMandat, strBordereau )
|
|
|
VALUES ({}, '{}', #{}#, '{}')
|
|
|
- """.format(self.factureId,
|
|
|
- self.numMandat,
|
|
|
- AnalytiqueDb.format_date(self.dateMandat),
|
|
|
- self.numBj
|
|
|
+ """.format(facture.factureId,
|
|
|
+ facture.numMandat,
|
|
|
+ AnalytiqueDb.format_date(facture.dateMandat),
|
|
|
+ facture.numBj
|
|
|
)
|
|
|
logger.debug("> %s", sql)
|
|
|
analytique_db.execute(sql)
|
|
|
|
|
|
- @staticmethod
|
|
|
- def load_errfile_data():
|
|
|
- factures = []
|
|
|
- try:
|
|
|
- firstline = True
|
|
|
- with open(errfile, "r") as f:
|
|
|
- for line in f:
|
|
|
- if firstline:
|
|
|
- firstline = False
|
|
|
- continue
|
|
|
- facture = Facture.from_errfile(line)
|
|
|
- factures.append(facture)
|
|
|
-
|
|
|
- except FileNotFoundError:
|
|
|
- pass
|
|
|
- return factures
|
|
|
-
|
|
|
- @staticmethod
|
|
|
- def process(factures):
|
|
|
- analysed, updated, errors = 0, 0, 0
|
|
|
-
|
|
|
- for facture in factures:
|
|
|
- analysed += 1
|
|
|
- try:
|
|
|
- facture.send_to_db()
|
|
|
- updated += 1
|
|
|
- except AlreadyImported:
|
|
|
- pass
|
|
|
- except InvalidData:
|
|
|
- facture.dump_to_err()
|
|
|
- errors += 1
|
|
|
- return analysed, updated, errors
|
|
|
-
|
|
|
-
|
|
|
-########
|
|
|
-
|
|
|
-if __name__ == "__main__":
|
|
|
+ # Commit les insertions dans la base
|
|
|
+ analytique_db.commit()
|
|
|
|
|
|
- to_retry = Facture.load_errfile_data()
|
|
|
- errfile.remove_p()
|
|
|
+ logger.info("Facture %s : ok", facture.factureId)
|
|
|
|
|
|
- if to_retry:
|
|
|
- logger.info("# Ré-import depuis le fichier d'erreurs")
|
|
|
- logger.info("{} lignes chargées depuis {}".format(len(to_retry), errfile))
|
|
|
- res = Facture.process(to_retry)
|
|
|
- logger.info("> {} lignes traitées / {} importées / {} erreurs".format(res[0], res[1], res[2]))
|
|
|
|
|
|
- else:
|
|
|
- logger.info("# Import depuis Astre-Gf")
|
|
|
- res = Facture.process([Facture.from_webservice(wsdata) for wsdata in ws])
|
|
|
- logger.info("> {} lignes traitées / {} importées / {} erreurs".format(res[0], res[1], res[2]))
|
|
|
|
|
|
- logging.shutdown()
|
|
|
+logging.shutdown()
|