| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 |
- '''
- Génère les affaires dans la base Analytique à partir des données de la base Contrôles.
- **IMPORTANT**: pour lancer le script sans interaction avec l'utilisateur
- (par ex, dans le cas d'une tâche planifiée), appeller le script avec l'option '-n'.
- @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 ControlesDb, AnalytiqueDb, mk_workdir, CommunDb
- logger = logging.getLogger("ctrl2analytique")
- logconf.start("ctrl2analytique", logging.DEBUG)
- # # POUR TESTER, décommenter les lignes suivantes
- ##-----------------------------------------------
- logger.warning("<<<<<<<<<<<<<< Mode TEST >>>>>>>>>>>>>>>>>")
- ControlesDb._path = Path(r"\\h2o\local\4-transversal\BDD\mdb_test\cg67Parc_data.mdb")
- AnalytiqueDb._path = Path(r"\\h2o\local\4-transversal\BDD\mdb_test\Db_analytique.mdb")
- CommunDb._path = Path(r"\\h2o\local\4-transversal\BDD\mdb_test\Commun_Data.mdb")
- ##-----------------------------------------------
- # *** Initialisation
- logger.info("Initialisation...")
- no_prompt = ("-n" in sys.argv)
- if no_prompt:
- logger.info("> Lancé en mode automatique (sans interruption)")
- # Connexion à Analytique
- analytique_db = AnalytiqueDb(autocommit=False)
- # Connexion à Controles
- controles_db = ControlesDb(autocommit=False)
- # Connexion à CommunDb
- commun_db = CommunDb(autocommit=False)
- # Make the working directory
- workdir = mk_workdir("ctrl2analytique")
- affaires_file = workdir / "affaires.csv"
- intervs_file = workdir / "intervs.csv"
- errors = []
- # > Supprime les fichiers d'import s'il existent
- for file in (affaires_file, intervs_file):
- if file.exists():
- logger.debug("Supprime le fichier %s", file)
- file.remove()
- class Affaire(Model):
- _FIELDS = ["strLiaisonControle", "strMOeId", "strCommneId", "strLieux",
- "strEntrepriseId", "strMOId", "dtmCommande", "Ref", "blnMarche",
- "dblMarche", "intDevisId", "strCT", "strTypeId",
- "intCoefFG", "strSituation"]
- def get_type_id(lngChantierId, bytCommandeId):
- """ Recupère le type de chantier.
- 'ZP': Chantier de contrôle d'étanchéité
- 'ZC': Chantier de contrôle du compactage
- 'ZI': Chantier d'inspection vidéo
- 'ZZ': Chantier mixte.
- '': Inconnu
- """
- sql = """SELECT lngChantierId, 'ZP' as type FROM tblEtancheiteBases WHERE [lngChantierId] = {chantier} AND [bytCommandeId] = {commande}
- UNION
- SELECT lngChantierId, 'ZC' as type FROM tblCompactageBases WHERE [lngChantierId] = {chantier}
- UNION
- SELECT lngChantierId, 'ZI' as type FROM tblVideoBases WHERE [lngChantierId] = {chantier};
- """.format(chantier=lngChantierId,
- commande=bytCommandeId)
- res = controles_db.read_all(sql)
- if len(res) == 0:
- return ""
- elif len(res) == 1:
- return res[0].type
- else:
- return "ZZ"
- def get_coeff_k(lngChantierId):
- # On déduit l'année du chantier à partir du code chantier
- annee = "20" + str(lngChantierId)[:2] if len(str(lngChantierId)) == 6 else "200" + str(lngChantierId)[:1]
- # On retrouve dans la table tbl_COEFFG le coefficient correspondant
- return analytique_db.first("SELECT [COEFFG] FROM tbl_COEFFG WHERE [ANNEE] = {}".format(annee)).COEFFG / 100
- # *** 1- Import des chantiers Contrôles dans le fichier affaires.csv
- nb_affaires, nb_intervs = 0, 0
- logger.debug("Génère le fichier %s", affaires_file)
- firstline = "\t".join(Affaire._FIELDS + ["\n"])
- with open(affaires_file, 'w+') as f:
- f.write(firstline)
- # on insère les affaires depuis tblCommandes et tblChantier (le lien est strLiaisonControle)
- compteur = 0
- sql = """ SELECT tblCommandes.lngChantierId, tblCommandes.bytCommandeId, tblChantiers.strSubdivisionId, tblChantiers.strCollectiviteId as ChantierCollectiviteId, tblChantiers.strLocChantier,
- tblChantiers.strEntrepriseId, tblCommandes.strCollectiviteId as CommandeCollectiviteId, tblCommandes.dtmCommande, tblCommandes.strRefCommande, tblCommandes.blnMarche, tblCommandes.dblMtMarche, tblCommandes.strdevis
- FROM tblChantiers INNER JOIN tblCommandes ON tblChantiers.lngChantierId = tblCommandes.lngChantierId
- WHERE (((tblCommandes.sngAffaireIdMos) Is Null Or (tblCommandes.sngAffaireIdMos)=0))
- """
- for data in controles_db.read(sql):
- affaire = Affaire()
- affaire.strLiaisonControle = "{}/{}".format(data.lngChantierId, data.bytCommandeId)
- affaire.strMOeId = data.strSubdivisionId
- affaire.strCommneId = data.ChantierCollectiviteId
- affaire.strLieux = data.strLocChantier
- affaire.strEntrepriseId = data.strEntrepriseId
- affaire.strMOId = data.CommandeCollectiviteId
- affaire.dtmCommande = data.dtmCommande
- affaire.Ref = data.strRefCommande
- affaire.blnMarche = data.blnMarche
- affaire.dblMarche = data.dblMtMarche
- affaire.intDevisId = data.strdevis
- affaire.strCT = '1'
- affaire.strTypeId = get_type_id(data.lngChantierId, data.bytCommandeId)
- affaire.intCoefFG = get_coeff_k(data.lngChantierId)
- affaire.strSituation = "En cours"
- with open(affaires_file, 'a') as f:
- f.write(affaire.to_csv())
- compteur += 1
- logger.info("> {} affaires ajoutées à {}".format(compteur, affaires_file))
- # *** 2- Import des interventions de contrôle du compactage dans le fichier intervs.csv
- class Interv(Model):
- _FIELDS = ["strEquipeId", "strEnginId", "strRapportId", "strTypeInterventionId",
- "strTypeInterventionId", "strCatégorieInterventionId", "dblquantite", "strunite", "dtmIntervention",
- "dtmDureeIntervention", "dtmDureeInstallation", "strLiaisonControle", "strArticleId", "intPeriode",
- "remarques", "strgrandeur1", "strgrandeur2", "strgrandeur3",
- "strcaracteristique1", "strcaracteristique2", "strcaracteristique3",
- "dtmImportation", "strTest", "LienAff"
- ]
- logger.debug("Génère le fichier %s", intervs_file)
- firstline = "\t".join(Interv._FIELDS + ["\n"])
- with open(intervs_file, 'w+') as f:
- f.write(firstline)
- def engin_existe(strEnginId):
- return analytique_db.exists("SELECT strEnginId FROM tbl_Engin WHERE strEnginId='{}'".format(strEnginId))
- def get_periode_validite(date_interv):
- sql = """SELECT intPeriodeValiditeId FROM tblTarifValidite
- WHERE [dtmValiditeDebut] <= #{date_interv}# AND [dtmValiditeFin] > #{date_interv}# AND [bytClasseTarifId]=1
- """.format(date_interv=date_interv)
- return commun_db.first(sql).intPeriodeValiditeId
- compteur = 0
- sql = """SELECT tblCompactageIntervs.lngChantierId, tblCompactageIntervs.bytCommandeId, tblCompactageIntervs.bytIntervId, tblCompactageIntervs.strEquipeId,
- tblCompactageEngins.strEnginId, tblCompactageIntervs.lngRapportId, tblCompactageBases.memTravaux, tblCompactageResultats.dtmEssai,
- tblCompactageResultats.dtmDuree, tblCompactagePartChantiers.strTrcRegard, tblMateriaux.strMatériau,
- tblCompactageResultats.bytPartChantierId, tblCompactageIntervs.sngIntervIdMos
- FROM ((tblMateriaux RIGHT JOIN ((((tblCompactageIntervs LEFT JOIN tblCompactageEngins ON tblCompactageIntervs.strEquipeId = tblCompactageEngins.strEquipeId)
- INNER JOIN tblCompactageResultats ON (tblCompactageIntervs.bytIntervId = tblCompactageResultats.bytIntervId)
- AND (tblCompactageIntervs.lngChantierId = tblCompactageResultats.lngChantierId)) INNER JOIN tblCompactagePartChantiers
- ON (tblCompactageResultats.bytPartChantierId = tblCompactagePartChantiers.bytPartChantierId)
- AND (tblCompactageResultats.lngChantierId = tblCompactagePartChantiers.lngChantierId)) INNER JOIN tblCompactageBases
- ON tblCompactageIntervs.lngChantierId = tblCompactageBases.lngChantierId) ON tblMateriaux.strMateriauId = tblCompactagePartChantiers.strMateriauRemblaiId)
- LEFT JOIN tblMateriaux AS tblMateriaux_1 ON tblCompactagePartChantiers.strMateriauEnrobageId = tblMateriaux_1.strMateriauId)
- LEFT JOIN tblMateriaux AS tblMateriaux_2 ON tblCompactagePartChantiers.strMateriauLitId = tblMateriaux_2.strMateriauId
- WHERE (((tblCompactageIntervs.sngIntervIdMos)=0 Or (tblCompactageIntervs.sngIntervIdMos) Is Null))
- """
- def get_type_compactage_interv(observation):
- if "ASSAINISEMENT" or "ASSAINISEMENT" in observation:
- return "CC3"
- elif "CABLE" in observation:
- return "CC1"
- elif "A.E.P" in observation:
- return "CC2"
- elif "GAZ" in observation:
- return "CC4"
- else:
- return "CC3"
- for data in controles_db.read(sql):
- interv = Interv()
- if not engin_existe(data.strEnginId):
- errors.append("""Intervention compactage {}/{}/{}/{}: l'engin {} n'existe pas"""
- .format(data.lngChantierId, data.bytCommandeId, data.bytIntervId, data.bytPartChantierId, data.strEnginId))
- interv.strEquipeId = "C{}".format(data.strEquipeId)
- interv.strEnginId = data.strEnginId
- interv.strRapportId = data.strRapportId
- interv.strTypeInterventionId = get_type_compactage_interv(data.memTravaux)
- interv.strCatégorieInterventionId = "CC"
- interv.dblquantite = 1
- interv.strunite = "u"
- interv.dtmIntervention = data.dtmEssai
- interv.dtmDureeIntervention = data.dtmDuree
- interv.dtmDureeInstallation = 0 # Les temps d'installation seront recalculés en fin de traitement
- interv.strLiaisonControle = "{}/{}/{}".format(data.lngChantierId, data.bytCommandeId, data.bytIntervId)
- interv.strArticleId = data.strEnginId
- interv.intPeriode = get_periode_validite(data.dtmEssai)
- interv.remarques = data.strTrcRegard
- interv.strgrandeur1 = data.strMatériau
- interv.strgrandeur2 = data.strMatériau
- interv.strgrandeur3 = data.strMatériau
- interv.strcaracteristique1 = "Matériau remblai"
- interv.strcaracteristique2 = "Matériau lit de pose"
- interv.strcaracteristique3 = "Matériau enrobage"
- interv.dtmImportation = "{}".format(datetime.now().strftime("%Y-%m-%d"))
- interv.strTest = "{}/{}/{}/{}".format(data.lngChantierId, data.bytCommandeId, data.bytIntervId, data.bytPartChantierId)
- interv.LienAff = "{}/{}".format(data.lngChantierId, data.bytCommandeId)
- with open(intervs_file, 'a') as f:
- f.write(interv.to_csv())
- compteur += 1
- logger.info("> {} interventions Compactage ajoutées à {}".format(compteur, intervs_file))
- # *** 3- Import des interventions de contrôle d'étanchéité dans le fichier intervs.csv
- compteur = 0
- sql = """SELECT tblEtancheiteIntervs.lngChantierId, tblEtancheiteIntervs.bytCommandeId, tblEtancheiteIntervs.bytIntervId, tblEtancheiteIntervs.strEquipeId,
- tblEtancheiteIntervs.lngRapportId, tblEtancheitePartChantiers.bytTypeEssai, tblMateriaux.strMateriauId, tblMateriaux.strMatériau,
- tblEtancheitePartChantiers.intDiametre, tblEtancheitePartChantiers.sngLgHt, tblEtancheitePartChantiers.intNbJoint, tblEtancheiteResultats.dtmDuree,
- tblEtancheiteResultats.dtmEssai, tblEtancheitePartChantiers.strTrcRegard, tblEtancheiteResultats.bytPartChantierId
- FROM ((tblEtancheiteIntervs INNER JOIN tblEtancheiteResultats ON (tblEtancheiteIntervs.lngChantierId = tblEtancheiteResultats.lngChantierId)
- AND (tblEtancheiteIntervs.bytIntervId = tblEtancheiteResultats.bytIntervId)) INNER JOIN tblEtancheitePartChantiers
- ON (tblEtancheiteResultats.lngChantierId = tblEtancheitePartChantiers.lngChantierId)
- AND (tblEtancheiteResultats.bytPartChantierId = tblEtancheitePartChantiers.bytPartChantierId)) INNER JOIN tblMateriaux
- ON tblEtancheitePartChantiers.strMateriauId = tblMateriaux.strMateriauId
- WHERE (((tblEtancheiteIntervs.sngIntervIdMos)=0 Or (tblEtancheiteIntervs.sngIntervIdMos) Is Null));
- """
- def get_engin_etancheite(equipe, diametre, materiau, type_essai):
- """ retourne l'engin correspondant à l'essai en fonction eds caractéristiques de l'essai """
- sql = """SELECT strEnginId FROM tblEtancheiteEngins
- WHERE ([strEquipeId] = '{}') AND ([intDiametre] = {}) AND ([strMateriauId] = '{}') AND ([bytTypeEssaiId] ={})
- """.format(equipe, diametre, materiau, type_essai)
- row = controles_db.first(sql)
- return row.strEnginId if row else ""
- for data in controles_db.read(sql):
- interv = Interv()
- interv.strEquipeId = "C{}".format(data.strEquipeId)
- interv.strEnginId = get_engin_etancheite(data.strEquipeId, data.intDiametre, data.strMateriauId, data.bytTypeEssai)
- interv.strRapportId = data.lngRapportId
- interv.strTypeInterventionId = "CE{}".format(data.bytTypeEssai)
- interv.strCatégorieInterventionId = "CE"
- interv.dblquantite = data.intNbJoint
- interv.strunite = "u"
- interv.dtmIntervention = data.dtmEssai
- interv.dtmDureeIntervention = data.dtmDuree
- interv.dtmDureeInstallation = 0 # Les temps d'installation seront recalculés en fin de traitement
- interv.strLiaisonControle = "{}/{}/{}".format(data.lngChantierId, data.bytCommandeId, data.bytIntervId)
- interv.strArticleId = interv.strEnginId
- interv.intPeriode = get_periode_validite(data.dtmEssai)
- interv.remarques = data.strTrcRegard
- interv.strgrandeur1 = data.strMatériau
- interv.strgrandeur2 = data.intDiametre
- interv.strgrandeur3 = data.sngLgHt
- interv.strcaracteristique1 = "Matériau"
- interv.strcaracteristique2 = "Diamètre"
- interv.strcaracteristique3 = "Longueur"
- interv.strunite2 = "mm"
- interv.strunite3 = "m"
- interv.dtmImportation = "{}".format(datetime.now().strftime("%Y-%m-%d"))
- interv.strTest = "{}/{}/{}/{}".format(data.lngChantierId, data.bytCommandeId, data.bytIntervId, data.bytPartChantierId)
- interv.LienAff = "{}/{}".format(data.lngChantierId, data.bytCommandeId)
- with open(intervs_file, 'a') as f:
- f.write(interv.to_csv())
- compteur += 1
- logger.info("> {} interventions Etanchéité ajoutées à {}".format(compteur, intervs_file))
- # *** 4- Import des interventions d'inspection vidéo dans le fichier intervs.csv
- compteur = 0
- sql = """SELECT tblVideoIntervs.lngChantierId, tblVideoIntervs.bytCommandeId, tblVideoIntervs.bytIntervId, tblVideoIntervs.strEquipeId,
- tblVideoEngins.strEnginId, tblVideoIntervs.lngRapportId, First(tblso_rate_Analyse.MateriauCourt) AS strmateriau, tblVideoIntervs.lngTroncon,
- tblVideoIntervs.sngNbJourFact, First(tblso_rate_Analyse.MaxDeDiametre) AS diam, tblVideoIntervs.dtmDuree, tblVideoIntervs.dtmIntervDu,
- First(tblVideoIntervs.memObservation) AS memObservation, tblChantiers.strEntrepriseId
- FROM ((tblVideoEngins RIGHT JOIN tblVideoIntervs ON tblVideoEngins.strEquipeId = tblVideoIntervs.strEquipeId) INNER JOIN tblso_rate_Analyse ON
- (tblVideoIntervs.lngChantierId = tblso_rate_Analyse.lngChantierId) AND (tblVideoIntervs.bytIntervId = tblso_rate_Analyse.bytIntervId)) INNER JOIN
- tblChantiers ON tblVideoIntervs.lngChantierId = tblChantiers.lngChantierId
- WHERE (((tblVideoIntervs.sngIntervIdMos) Is Null Or (tblVideoIntervs.sngIntervIdMos)=0))
- GROUP BY tblVideoIntervs.lngChantierId, tblVideoIntervs.bytCommandeId, tblVideoIntervs.bytIntervId, tblVideoIntervs.strEquipeId,
- tblVideoIntervs.lngRapportId, tblVideoIntervs.lngTroncon, tblVideoIntervs.sngNbJourFact, tblVideoIntervs.dtmDuree,
- tblVideoIntervs.dtmIntervDu, tblVideoEngins.strEnginId, tblChantiers.strEntrepriseId
- """
- for data in controles_db.read(sql):
- interv = Interv()
- if not engin_existe(data.strEnginId):
- errors.append("""Intervention compactage {}/{}/{}/1: l'engin {} n'existe pas"""
- .format(data.lngChantierId, data.bytCommandeId, data.bytIntervId, data.strEnginId))
- interv.strEquipeId = "C{}".format(data.strEquipeId)
- interv.strEnginId = data.strEnginId
- interv.strRapportId = data.lngRapportId
- interv.strTypeInterventionId = "CI1" if data.strEntrepriseId != 195 else "CI2"
- interv.strCatégorieInterventionId = "CI"
- interv.dblquantite = data.sngNbJourFact
- interv.strunite = "j"
- interv.dtmIntervention = data.dtmIntervDu
- interv.dtmDureeIntervention = data.dtmDuree
- interv.dtmDureeInstallation = 0 # Les temps d'installation seront recalculés en fin de traitement
- interv.strLiaisonControle = "{}/{}/{}".format(data.lngChantierId, data.bytCommandeId, data.bytIntervId)
- interv.strArticleId = data.strEnginId
- interv.intPeriode = get_periode_validite(data.dtmIntervDu)
- interv.remarques = data.memObservation
- interv.strgrandeur1 = data.strmateriau
- interv.strgrandeur2 = data.diam
- interv.strgrandeur3 = data.lngTroncon
- interv.strcaracteristique1 = "Matériau"
- interv.strcaracteristique2 = "Diamètre"
- interv.strcaracteristique3 = "Longueur inspectée"
- interv.strunite2 = "mm"
- interv.strunite3 = "m"
- interv.dtmImportation = "{}".format(datetime.now().strftime("%Y-%m-%d"))
- interv.strTest = "{}/{}/{}/1".format(data.lngChantierId, data.bytCommandeId, data.bytIntervId)
- interv.LienAff = "{}/{}".format(data.lngChantierId, data.bytCommandeId)
- with open(intervs_file, 'a') as f:
- f.write(interv.to_csv())
- compteur += 1
- logger.info("> {} interventions ITV ajoutées à {}".format(compteur, intervs_file))
- # *** 5- Interruption pour corection manuelle des données (si nécessaire)
- logging.info("Les données à importer ont été ajoutées aux fichiers '{}' et '{}'".format(affaires_file, intervs_file))
- if errors:
- logging.error("<!> Des erreurs ont été détectées dans les données à importer. <!>")
- for msg in errors:
- logging.error(msg)
- prompt = ""
- while prompt != "v":
- prompt = input(">> Veuillez contrôler les données, puis taper 'v' pour continuer, ou 'q' pour quitter...")
- if prompt == "q":
- sys.exit(1)
- # *** 6- Insertion des données dans les tables Analytique
- with open(affaires_file) as f:
- next(f) # saute la première ligne
- for line in f:
- affaire = Affaire.from_csv(line)
- sql = """ INSERT INTO tbl_Affaires ( strMOId, strMOeId, strEntrepriseId, strCommneId, strLieux, strTypeId, dtmCommande, Ref,
- blnMarche, dblMarche, intTypeContrat, strCT, strAvancement, strLiaisonControle, intDevisId, blnTarification,
- blnAnalyse, remarques, strSituation, dtmFin, intCoefFG )
- SELECT {strMOId}, {strMOeId}, {strEntrepriseId}, {strCommneId}, {strLieux}, {strTypeId}, {dtmCommande},
- {Ref}, {blnMarche}, {dblMarche}, {intTypeContrat}, {strCT}, {strAvancement}, {strLiaisonControle}, {intDevisId},
- {blnTarification}, {blnAnalyse}, {remarques}, {strSituation}, {dtmFin}, {intCoefFG}
- """.format(strMOId=affaire.strMOId,
- strMOeId=affaire.strMOeId,
- strEntrepriseId=affaire.strEntrepriseId,
- strCommneId=affaire.strCommneId,
- dtmCommande=affaire.dtmCommande,
- Ref=affaire.Ref,
- blnMarche=affaire.blnMarche,
- dblMarche=affaire.dblMarche,
- intTypeContrat=affaire.intTypeContrat,
- strCT=affaire.strCT,
- strAvancement=affaire.strAvancement,
- strLiaisonControle=affaire.strLiaisonControle,
- intDevisId=affaire.intDevisId,
- blnTarification=affaire.blnTarification,
- blnAnalyse=affaire.blnAnalyse,
- remarques=affaire.remarques,
- strSituation=affaire.strSituation,
- dtmFin=affaire.dtmFin,
- intCoefFG=affaire.intCoefFG)
- analytique_db.execute(sql)
- affaire.affaireId = analytique_db.first("SELECT TOP 1 DblAffaireId FROM tbl_Affaires ORDER BY DblAffaireId DESC").DblAffaireId
- # Stocker cette valeur dans un dico associéeau strLiaisonControle, pour la maj de tblIntervs
- # Insérer ici les intervs liées à l'affaire (?)
- # Maj champs MOS, puis committer
- with open(intervs_file) as f:
- next(f) # saute la première ligne
- for line in f:
- interv = Interv.from_csv(line)
- # Reprendre la fonction PostVerif
- # Maj des temps d'installation
|