|
|
@@ -0,0 +1,160 @@
|
|
|
+'''
|
|
|
+
|
|
|
+ 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
|
|
|
+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)
|
|
|
+debug = False
|
|
|
+
|
|
|
+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")
|
|
|
+debug = True
|
|
|
+logger.handlers = [h for h in logger.handlers if (type(h) == logging.StreamHandler)]
|
|
|
+logger.warning("<<<<<<<<<<<<<< Mode TEST >>>>>>>>>>>>>>>>>")
|
|
|
+
|
|
|
+##-----------------------------------------------
|
|
|
+
|
|
|
+# Connexion à Wincan
|
|
|
+wincan_db = WincanDb(autocommit=False)
|
|
|
+
|
|
|
+# Regex pour parser les noms de repertoires
|
|
|
+rx = re.compile(r"^(I_)?(\d{5,6})(-S?\d{1,2})?[\s_]?(.*)$") # tous
|
|
|
+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")
|
|
|
+ sys.exit()
|
|
|
+
|
|
|
+
|
|
|
+for chantier_dir in a_importer:
|
|
|
+ # Ici, les noms de chantier sont de la forme 000000, 000000-0, ou 000000-S0
|
|
|
+ dir_name = chantier_dir.name
|
|
|
+ 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)
|
|
|
+ query = wincan_db.exec_(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))
|
|
|
+ if not query.first():
|
|
|
+ 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)
|
|
|
+
|
|
|
+
|
|
|
+ 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 |= wincan_db.readall(Sql.format("""SELECT S_T.S_EndNode
|
|
|
+ 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 |= wincan_db.readall(Sql.format("""SELECT S_T.S_StartNode
|
|
|
+ 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("Regards manquant dans Wincan ({})".format(regard_name))
|
|
|
+ for regard_name in wincan_regards_name - shp_regards_name:
|
|
|
+ logger.error("Regards manquant dans le shapefile ({})".format(regard_name))
|
|
|
+ if shp_regards_name != wincan_regards_name:
|
|
|
+ continue
|
|
|
+
|
|
|
+ # # Update the coordinates of the regards in WincanDb
|
|
|
+
|
|
|
+ for point in points:
|
|
|
+ q = 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))
|
|
|
+ q = 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 = r"{}\I_{}".format(chantier_dir.parent, chantier_dir.name)
|
|
|
+ logger.debug("> Renomme {} en {}".format(chantier_dir.name, new_path.name))
|
|
|
+
|
|
|
+ if not debug:
|
|
|
+ try:
|
|
|
+ chantier_dir.rename(new_path)
|
|
|
+ except:
|
|
|
+ logger.error("Impossible de renommer le dossier")
|