''' Met à jour la base controle avec les données d'un chantier Wincan usage: wincan2ctrl [-c ] [-i ] [-o] Options: -c Passe le code chantier -i Passe le nom de l'inpection wincan -o Ne demande pas confirmation avant de lancer le traitement -h, --help Affiche l'aide Attention: Si un des arguments comporte des espaces, pensez à le mettre entre guillemets @olivier.massot, mai 2018 ''' import logging import sys from docopt import docopt from path import Path from core import logconf from core.pde import ControlesDb, WincanDb, InspectionTronconWincan, \ InterventionITV, PiracaDb from core.sqlformatter import SqlFormatter logger = logging.getLogger("wincan2ctrl") logconf.start("wincan2ctrl", logging.DEBUG) # # POUR TESTER, décommenter les lignes suivantes # > Lancer le script /resources/test_wincan2ctrl.py pour reinitialiser les données de la base de test ##----------------------------------------------- # ControlesDb._path = Path(r"\\h2o\local\4-transversal\BDD\mdb_test\cg67Parc_data.mdb") # WincanDb._path = Path(r"\\h2o\local\4-transversal\BDD\mdb_test\Wincan\parc_2007\DB\PARC_2007.mdb") # PiracaDb._path = Path(r"\\h2o\local\4-transversal\BDD\mdb_test\db_Piraca.mdb") # logger.handlers = [h for h in logger.handlers if (type(h) == logging.StreamHandler)] # logger.warning("<<<<<<<<<<<<<< Mode TEST >>>>>>>>>>>>>>>>>") ##----------------------------------------------- def main(): logger.info("Initialisation...") Sql = SqlFormatter() # Connexion à Controles controles_db = ControlesDb(autocommit=False) # Connexion à Wincan wincan_db = WincanDb(autocommit=False) # Connexion à CommunDb piraca_db = PiracaDb(autocommit=False) def get_lib(lib_id, tbl_id): row = piraca_db.first(Sql.format("""SELECT LIB_ID, LIB_LIB, TLB_ID FROM LISTE_LIBELLE_WINCAN WHERE TLB_ID='{}' AND LIB_ID='{}'""", tbl_id, lib_id)) if not row: logger.error("Aucun libelle trouvé dans la table LISTE_LIBELLE_WINCAN pour %s, id=%s", tbl_id, lib_id) raise KeyError() return row.LIB_LIB def get_materiau(wincan_id): return controles_db.first(Sql.format("""SELECT strMateriauCourt FROM tblMateriaux WHERE strWincanId='{}'""", wincan_id)).strMateriauCourt # Parse les arguments args = docopt(__doc__, help=False) chantier_id = args["-c"] if args["-c"] else 0 inspname = args["-i"] if args["-i"] else "" # Demande à l'utilisateur de saisir les informations qui n'ont pas été passées en argument if not inspname: # Propose une liste d'inspections possibles sql = """SELECT SI_InspName FROM SI_T WHERE SI_Spare1 Is Null OR Len([SI_Spare1])=0 GROUP BY SI_InspName """ candidats = wincan_db.read_all(sql) print("Veuillez choisir une inspection Wincan à traiter en saisissant son numéro:") for i, candidat in enumerate(candidats): print("[{}] - {}".format(i, candidat.SI_InspName)) while not inspname: reponse = input("> ") try: inspname = candidats[int(reponse)].SI_InspName except ValueError: print("Valeur invalide!") if not chantier_id: try: default = int(inspname[:6]) chantier_id = input("Veuillez saisir le code chantier [{}]: ".format(default)) if not chantier_id: chantier_id = default except ValueError: chantier_id = input("Veuillez saisir le code chantier: ") if not chantier_id: logger.error("Code chantier invalide") return # Calcul du numéro d'intervention last_interv_id = controles_db.first("SELECT max(bytIntervId) as last_interv_id FROM tblVideoIntervs WHERE lngChantierId={}".format(chantier_id)).last_interv_id interv_id = last_interv_id + 1 if last_interv_id else 1 # Récupération du numéro de commande en cours commande_id = controles_db.first("SELECT bytCommandeId FROM tblVideoBases WHERE lngChantierId={}".format(chantier_id)).bytCommandeId # Affiche les infos et demande confirmation avant ed lancer le traitement logger.info("## Traitement de l'inspection Wincan") logger.info("Nom chantier: %s", inspname) logger.info("Code chantier: %s", chantier_id) logger.info("Numero d'intervention: %s", interv_id) logger.info("Numero de commande: %s", commande_id) if not args["-o"]: if not input("Voulez-vous continuer? (o/n)") == 'o': if input("Etes-vous sûr de vouloir annuler l'opération? (o/n)") == 'o': logger.info("Opération annulée par l'utilisateur") return # Recuperation des données de l'intervention sql = """SELECT SI_T.SI_InspName, Sum(S_T.S_Sectionlength) AS Long_insp, Min(SI_T.SI_Date) AS mindate, Max(SI_T.SI_Date) AS maxdate, First(SI_T.SI_Operator) AS Equipe, First(SI_T.SI_Vehicle) AS Mat, First(SI_T.SI_InspMethod) AS InspMethod, First(SI_T.SI_ReasonOfInspection) AS SI_ReasonOfInspection, First(S_T.S_SectionPurpose) AS nature, First(S_T.S_SectionUse) AS Fonction, First(S_T.S_SectionType) AS Type FROM S_T INNER JOIN SI_T ON S_T.S_ID = SI_T.SI_Section_ID WHERE (((SI_T.[SI_InspName])='{}')) GROUP BY SI_T.SI_InspName HAVING Sum(S_T.S_Sectionlength) Is Not Null AND First(SI_T.SI_Operator) Is Not Null AND First(SI_T.SI_Vehicle) Is Not Null AND First(SI_T.SI_InspMethod) Is Not Null """.format(inspname) try: inspection = next(wincan_db.read(sql)) except StopIteration: logger.error("Aucune inspection trouvée pour le nom '%s'", inspname) raise # Insère l'inspection dans la table tblVideoIntervs de Controles logger.info("Création de l'intervention dans tblVideoIntervs") interv = InterventionITV() interv.lngChantierId = chantier_id interv.bytIntervId = interv_id interv.dtmIntervDu = inspection.mindate interv.dtmIntervAu = inspection.maxdate interv.strEquipeId = inspection.Equipe interv.intlMaterielID = inspection.Mat interv.bytCommandeId = commande_id interv.lngTroncon = inspection.Long_insp interv.SI_InspMethod = inspection.InspMethod interv.SI_ReasonOfInspection = get_lib(inspection.SI_ReasonOfInspection, "SI_REASONOfINSPECTION") sql = Sql.format("""INSERT INTO tblVideoIntervs ( lngChantierId, bytIntervId, dtmIntervDu, dtmIntervAu, strEquipeId, intlMaterielID, bytCommandeId, lngTroncon, SI_InspMethod, SI_ReasonOfInspection ) VALUES ({interv.lngChantierId}, {interv.bytIntervId}, {interv.dtmIntervDu:date}, {interv.dtmIntervAu:date}, {interv.strEquipeId:text}, {interv.intlMaterielID}, {interv.bytCommandeId}, {interv.lngTroncon}, {interv.SI_InspMethod:text}, {interv.SI_ReasonOfInspection:text}) """, interv=interv) controles_db.execute(sql) # Met a jour les champs SI_Spare1 et SI_Spare2 de la table Wincan en retour logger.info("Mise à jour en retour de SI_T") sql = """UPDATE SI_T SET SI_Spare1='{}', SI_Spare2='{}' WHERE SI_InspName='{}' """.format(chantier_id, interv_id, inspection.SI_InspName) wincan_db.execute(sql) # Met a jour la table tbl_so_rate de Controles logger.info("Traitement des inspections") # Extrait les données des tronçons sql = """SELECT SI_T.SI_ID, S_T.S_ID, SI_T.SI_InspName, SI_T.SI_Spare1, SI_T.SI_Spare2, SI_T.SI_AutoNumber, SI_T.SI_MediaNumber1, S_T.S_SectionFlow, S_T.S_StartNode, S_T.S_EndNode, S_T.S_StartNodeType, S_T.S_EndNodeType, S_T.S_StartNodeCoord_Z, S_T.S_EndNodeCoord_Z, S_T.S_Sectionlength, S_T.S_SectionPurpose, S_T.S_SectionUse, S_T.S_SectionType, S_T.S_PipeMaterial, S_T.S_YearLayed, S_T.S_PipeDia, S_T.S_Situation, S_T.S_Spare1, S_T.S_PipeShape, S_T.S_Pipelength, S_T.S_Spare3, SI_T.SI_Spare0, SI_T.SI_Date FROM S_T INNER JOIN SI_T ON S_T.S_ID = SI_T.SI_Section_ID WHERE SI_T.SI_Spare1='{}' AND SI_T.SI_Spare2='{}' """.format(chantier_id, interv_id) for data in wincan_db.read(sql): logger.info("* Traitement de %s (S_ID: %s)", data.SI_InspName, data.S_ID) inspection = InspectionTronconWincan() inspection.s_guid = data.S_ID[2:-1] if (data.S_ID[:2] == "b'" and data.S_ID[-1:] == "'") else data.S_ID inspection.si_guid = data.SI_ID[2:-1] if (data.SI_ID[:2] == "b'" and data.SI_ID[-1:] == "'") else data.SI_ID inspection.nom_chantier = data.SI_InspName inspection.lng_chantier_id = data.SI_Spare1 inspection.byt_interv_id = data.SI_Spare2 inspection.si_autonumber = data.SI_AutoNumber inspection.classement_troncons = data.SI_MediaNumber1 inspection.nom_troncon = "{r1}-{r2}".format(r1=data.S_StartNode, r2=data.S_EndNode) if data.S_SectionFlow == '2' else "{r2}-{r1}".format(r1=data.S_StartNode, r2=data.S_EndNode) inspection.startnode_type = get_lib(data.S_StartNodeType, "S_StartNodeType") inspection.endnode_type = get_lib(data.S_StartNodeType, "S_EndNodeType") inspection.sens_ecoul = ">>" if data.S_SectionFlow == '1' else ('<<' if data.S_SectionFlow == '2' else '') inspection.startnode_z = data.S_StartNodeCoord_Z inspection.endnode_z = data.S_EndNodeCoord_Z inspection.section_length = data.S_Sectionlength inspection.section_purpose = data.S_SectionPurpose inspection.section_use = data.S_SectionUse inspection.section_type = data.S_SectionType inspection.materiau = get_materiau(data.S_PipeMaterial) inspection.annee_pose = data.S_YearLayed inspection.diametre = get_lib(int(data.S_PipeDia), "S_PipeDia") inspection.route = get_lib(data.S_Situation, "S_Situation") inspection.n_route = data.S_Spare1 inspection.pipe_shape = data.S_PipeShape inspection.pipe_length = data.S_Pipelength if data.S_Spare3: inspection.arbres = get_lib(data.S_Spare3, "S_Spare3") inspection.test_ecoulement = data.SI_Spare0 inspection.si_date = data.SI_Date sql = """ SELECT SO_T.SO_ID, SO_T.SO_Rate, SO_T.SO_Photonumber1, SO_T.SO_Photonumber2 FROM SO_T WHERE SO_T.SO_Inspecs_ID='{}' """.format(inspection.si_guid) # Parcours les opérations réalisées au cours de l'inspection du tronçon for opdata in wincan_db.read(sql): inspection.nb_ops += 1 if opdata.SO_Rate == 1: inspection.rate_1 = inspection.rate_1 + 1 if inspection.rate_1 else 1 elif opdata.SO_Rate == 2: inspection.rate_2 = inspection.rate_2 + 1 if inspection.rate_2 else 1 elif opdata.SO_Rate == 3: inspection.rate_3 = inspection.rate_3 + 1 if inspection.rate_3 else 1 elif opdata.SO_Rate == 4: inspection.rate_4 = inspection.rate_4 + 1 if inspection.rate_4 else 1 elif opdata.SO_Rate == 5: inspection.rate_5 = inspection.rate_5 + 1 if inspection.rate_5 else 1 elif not opdata.SO_Rate: pass elif opdata.SO_Rate >= 6: logger.error("Attention: une valeur de [SO_Rate] supérieure à 5 a été enregistrée (SO_ID: %s)", opdata.SO_ID) if opdata.SO_Photonumber1: inspection.nb_photos += 1 if opdata.SO_Photonumber2: inspection.nb_photos += 1 if not any([inspection.rate_1, inspection.rate_2, inspection.rate_3, inspection.rate_4, inspection.rate_5]): inspection.DG = 'ABS' # Absence de défauts elif not any([inspection.rate_1, inspection.rate_2, inspection.rate_3]): inspection.DG = 'ACC' # Défauts acceptables else: inspection.DG = 'INT' # Défauts non-acceptables logger.info("\t- Mise à jour de tblso_Rate_Analyse") sql = Sql.format("""INSERT INTO tblso_Rate_Analyse ( lngChantierId, bytIntervId, SI_InspName, SI_AutoNumber, [Classement tronons], Nom_troncon, S_StartNodeType, Sens_ecoul, S_EndNodeType, S_PipeShape, MateriauCourt, SI_Date, nb_Arbres, ANNEE_POSE, Route, NRoute, Test_ecoulement, MaxDeS_StartNodeCoord_Z, MaxDeS_EndNodeCoord_Z, MaxDeS_Sectionlength, MaxDeS_Pipelength, MaxDeDiametre, cpt_Photos, [Total de SO_ID], 1, 2, 3, 4, 5, DG ) VALUES ({inspection.lng_chantier_id}, {inspection.byt_interv_id}, {inspection.nom_chantier:text}, {inspection.si_autonumber}, {inspection.classement_troncons:text}, {inspection.nom_troncon:text}, {inspection.startnode_type:text}, {inspection.sens_ecoul:text}, {inspection.endnode_type:text}, {inspection.pipe_shape:text}, {inspection.materiau:text}, {inspection.si_date:date}, {inspection.arbres:text}, {inspection.annee_pose}, {inspection.route:text}, {inspection.n_route:text}, {inspection.test_ecoulement:text}, {inspection.startnode_z}, {inspection.endnode_z}, {inspection.section_length}, {inspection.pipe_length}, {inspection.diametre:text}, {inspection.nb_photos}, {inspection.nb_ops}, {inspection.rate_1}, {inspection.rate_2}, {inspection.rate_3}, {inspection.rate_4}, {inspection.rate_5}, {inspection.DG:text} ) """, inspection=inspection) controles_db.execute(sql) # Met à jour tblvideointervs.strResGlobal avec le resultat global # le resultat global vaut '-' si un de ces trois champs n'est pas nul: tbl_so_rate.1, tbl_so_rate.2, tbl_so_rate.3 # >> On peut peut-être rassembler cette partie et l'insertion dans cette table au debut? logger.info("\t- Mise à jour du resultat global dans tblVideoIntervs") sql = """UPDATE tblVideoIntervs SET strResGlobal='{}' WHERE lngChantierId= {} AND bytIntervId= {} """.format('-' if inspection.DG == 'INT' else '+', chantier_id, interv_id) controles_db.execute(sql) # Met à jour la table tblVideoBases pour marquer le chantier comme traité logger.info("\t- Mise à jour de tblVideoBases") sql = """UPDATE tblVideoBases SET blnWincan=True,bytNbInterv={} WHERE lngChantierId={} """.format(inspection.byt_interv_id, inspection.lng_chantier_id) controles_db.execute(sql) # Met à jour les données du réseau dans tblChantiers logger.info("\t- Mise à jour des données du réseau dans tblChantiers") sql = """UPDATE tblChantiers SET bytFoncReseauId ={} , bytNatureReseauId={}, bytTypeReseauId={} WHERE lngChantierId={} """.format(inspection.section_use, inspection.section_purpose, inspection.section_type, inspection.lng_chantier_id) controles_db.execute(sql) logger.info("Commit des modifications") controles_db.commit() wincan_db.commit() if __name__ == "__main__": main() logger.info("-- Fin --")