| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- '''
- Met à jour les coordonnées des regards dans la base Wincan
- Les coordonnées sont issues des dossiers du répertoire 'itv_dir'
- Une fois traités, ces dossiers sont renommés 'XXXXXX' > 'I_XXXXXX'
- Plusieurs contrôles sont exécutés au cours de l'opération.
- Les erreurs suivantes sont bloquantes:
- - Le chantier correspondant n'existe pas dans Wincan
- - Le champ SI_Spare1 du tronçon analysé est NULL
- (ce qui signifie que la ligne n'a pas été traitée dans l'application Contrôles)
- - Regards présents dans le shapefile et pas dans Wincan
- - Regards présents dans Wincan et pas dans le shapefile
- - Regards en doublons dans le shapefile
- @author: olivier.massot, mai 2018
- '''
- import logging
- import re
- import sys
- from path import Path # @UnusedImport
- import shapefile
- from core import logconf
- from core.model import Sql
- from core.pde import WincanDb, ITV_DIR, QGisPoint
- logger = logging.getLogger("qgis_sync_wincan")
- logconf.start("qgis_sync_wincan", logging.DEBUG)
- IMPORT_DEPUIS = 24 # Ne cherche des données à importer que sur les X derniers mois (mettre à 0 pour ignorer)
- # # POUR TESTER, décommenter les lignes suivantes
- ##-----------------------------------------------
- # WincanDb._path = Path(r"\\h2o\local\4-transversal\BDD\mdb_test\Wincan\parc_2007\DB\PARC_2007.mdb")
- # ITV_DIR = Path(__file__).parent / "resources" / "test_qgis_sync_wincan"
- # logger.handlers = [h for h in logger.handlers if (type(h) == logging.StreamHandler)]
- # logger.warning("<<<<<<<<<<<<<< Mode TEST >>>>>>>>>>>>>>>>>")
- ##-----------------------------------------------
- def main():
- # Connexion à Wincan
- wincan_db = WincanDb(autocommit=False)
- # Regex pour parser les noms de repertoires
- rxi = re.compile(r"^(\d{5,6})(-S?\d{1,2})?[\s_]?(.*)$") # non importés
- logger.info("Parcours des répertoires")
- a_importer = [subdir for subdir in ITV_DIR.dirs() if rxi.search(subdir.name)]
- if not a_importer:
- logger.info("Aucun nouveau dossier à importer")
- return
- for chantier_dir in a_importer:
- # Ici, les noms de chantier sont de la forme 000000, 000000-0, ou 000000-S0
- logger.info("# Traitement du répertoire: {}".format(chantier_dir.name))
- # check the existence of the chantier in WincanDb, and check if the chantier has been treated in Controles (SI_Spare1 = 1)
- if not wincan_db.exists(Sql.format("""SELECT SI_T.SI_AutoNumber
- FROM SI_T
- WHERE (((SI_T.SI_Spare1) is not null
- AND (SI_T.SI_JobNumber) Like {:text}))""", chantier_dir.name)):
- logger.error("Le chantier n'existe pas dans wincan, ou SI_Spare1 est null")
- continue
- shp_path = chantier_dir / "{}_p_Regards.shp".format(chantier_dir.name)
- logger.debug("> Lecture du fichier shapefile")
- sf = shapefile.Reader(shp_path)
- # should we check? :
- if sf.shapeType != 1:
- logger.error("Le fichier shapefile n'est pas de type POINT")
- continue
- sh_points = sf.shapeRecords()
- if not sh_points:
- logger.error("Le fichier shapefile ne contient aucune donnees")
- continue
- # Génère des objets 'Points' à partir des données du shapefile
- points = []
- for sh_point in sh_points:
- point = QGisPoint()
- point.number = sh_point.record[0]
- point.name = sh_point.record[1]
- point.x, point.y = sh_point.shape.points[0]
- points.append(point)
- del sf, sh_points
- logger.info("> Contrôle des données")
- shp_regards_name = set([point.number for point in points])
- # Vérifie l'absence de duplicats
- if len(shp_regards_name) != len(points):
- logger.error("Shapefile - Doublons dans les noms de regards")
- continue
- # Vérifie l'existence des regards dans WincanDb
- wincan_regards_name = set([]) # Le set garantit l'unicité des items
- wincan_regards_name |= {r.nom for r in wincan_db.read_all(Sql.format("""SELECT S_T.S_EndNode as nom
- FROM S_T INNER JOIN SI_T ON S_T.S_ID = SI_T.SI_Section_ID
- WHERE (S_T.S_EndNode Not Like 'T%' And S_T.S_EndNode Not Like 'BP%'
- AND SI_T.SI_JobNumber Like {:text})""", chantier_dir.name))}
- wincan_regards_name |= {r.nom for r in wincan_db.read_all(Sql.format("""SELECT S_T.S_StartNode as nom
- FROM S_T INNER JOIN SI_T ON S_T.S_ID = SI_T.SI_Section_ID
- WHERE (S_T.S_StartNode Not Like 'T%' And S_T.S_StartNode Not Like 'BP%'
- AND SI_T.SI_JobNumber Like {:text})""", chantier_dir.name))}
- for regard_name in shp_regards_name - wincan_regards_name:
- logger.error("Le regards suivant n'existe pas dans Wincan ({})".format(regard_name))
- for regard_name in wincan_regards_name - shp_regards_name:
- logger.error("Le regards suivant est absent du fichier shapefile ({})".format(regard_name))
- if shp_regards_name != wincan_regards_name:
- logger.info("Mise à jour annulée")
- continue
- # # Update the coordinates of the regards in WincanDb
- for point in points:
- wincan_db.execute(Sql.format("""UPDATE S_T INNER JOIN SI_T ON S_T.S_ID = SI_T.SI_Section_ID
- SET S_T.S_StartNodeCoord_X = {x}, S_T.S_StartNodeCoord_Y = {y}
- WHERE SI_T.SI_InspName Like {chantier:text} AND S_T.S_StartNode={num:text};
- """, chantier=chantier_dir.name + "%",
- num=point.number,
- x=point.x,
- y=point.y))
- wincan_db.execute(Sql.format("""UPDATE S_T INNER JOIN SI_T ON S_T.S_ID = SI_T.SI_Section_ID
- SET S_T.S_EndNodeCoord_X = {x}, S_T.S_EndNodeCoord_Y = {y}
- WHERE SI_T.SI_InspName Like {chantier:text} AND S_T.S_EndNode={num:text};
- """, chantier=chantier_dir.name + "%",
- num=point.number,
- x=point.x,
- y=point.y))
- wincan_db.commit()
- logger.info("> Mise à jour de la base Wincan")
- # rename the directory to mark it as imported ('I_')
- new_path = chantier_dir.parent / "I_{}".format(chantier_dir.name)
- logger.debug("> Renomme {} en {}".format(chantier_dir.name, new_path.name))
- try:
- chantier_dir.rename(new_path)
- except:
- logger.error("Impossible de renommer le dossier")
- if __name__ == "__main__":
- main()
- logger.info("-- Fin --")
|