| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- """
- Importe les données géographiques des essais de compactage depuis les fichiers Shapefile
- recus des exploitants vers la base Postgis de ControlesSig
- - Ajoute de nouveaux chantiers / points de compactage à la base POSTGIS
- - Les chantiers créés sont issus des dossiers du répertoire 'compactage_dir'
- - Une fois importés, ces dossiers sont renommés 'XXXXXX' > 'I_XXXXXX'
- - Les noms complets des chantiers sont récupérés dans la base Controles
- Pour lancer l'import de tous les chantiers (pas de prompt pour la selection), utilisez l'option --all
- Pour répondre automatiquement à la demande "Voulez-vous remplacer le chantier existant", utilisez les options --yes ou --no
- @author: olivier.massot, mai 2018
- """
- import logging
- import re
- import sys
- from path import Path
- import shapefile
- from core import logconf
- from core.pde import ControlesDb, CSigDb, COMPACTAGE_DIR, QGisChantier, \
- QGisPoint, SRID
- logger = logging.getLogger("qgis_sync_compactage")
- logconf.start("qgis_sync_compactage", logging.DEBUG)
- # # POUR TESTER, décommenter les lignes suivantes
- ##-----------------------------------------------
- # ControlesDb._path = Path(r"\\h2o\local\4-transversal\BDD\mdb_test\cg67Parc_data.mdb")
- # CSigDb.server = "TR-POSTGIS-02"
- # CSigDb.pwd = "Am5VOMkdFHU7WwrfVOs9"
- # COMPACTAGE_DIR = Path(__file__).parent / "resources" / "test_qgis_sync_compactage"
- # logger.handlers = [h for h in logger.handlers if (type(h) == logging.StreamHandler)]
- # logger.warning("<<<<<<<<<<<<<< Mode TEST >>>>>>>>>>>>>>>>>")
- ##-----------------------------------------------
- def main():
- # Connexion à ControlesSig (postgres)
- csig_db = CSigDb(autocommit=False)
- # Connexion à Controles
- controles_db = ControlesDb(autocommit=False)
- # Regex pour parser les noms de repertoires
- rxi = re.compile(r"^(\d{5,6})([-_]S?\d*)?[\s_]?(.*)$") # non importés
- a_importer = [subdir for subdir in COMPACTAGE_DIR.dirs() if rxi.search(subdir.name)]
- if a_importer and not "--all" in sys.argv:
- reponse = input("""Les chantiers suivants peuvent être importés.
- Tapez les numéros correpsondant aux chantiers à importer, séparés par une virgule (ou * pour tout importer)
- Ex: "1", "1,2,5", "*"
- {}""".format("\n".join(["{} - {}".format(i, item.name) for i, item in enumerate(a_importer)])))
- if reponse != "*":
- a_importer = [item for i, item in enumerate(a_importer) if str(i) in reponse.split(",")]
- if not a_importer:
- logger.info("Aucun nouveau dossier à importer")
- sys.exit()
- chantiers = []
- # ** Read the data in the shapefiles and store it in memory **
- for chantier_dir_path in a_importer:
- logger.info("Lecture de : %s", chantier_dir_path)
- # instanciate a new Chantier
- chantier = QGisChantier()
- chantier.dir_path = chantier_dir_path
- logger.debug("> parse path")
- parsed = rxi.search(chantier_dir_path.name)
- chantier.number = parsed.group(1)
- chantier.complement = parsed.group(2).replace("_", "-") if parsed.group(2) else ""
- logger.debug("> number: %s, compl: %s", chantier.number, chantier.complement)
- # query for name in ControlesDb
- logger.debug("> Query ControlesDb for chantier's name")
- row = controles_db.first("""SELECT tblChantiers.lngChantierId, tblCollectivites.strNom
- FROM tblChantiers INNER JOIN tblCollectivites
- ON tblChantiers.strCollectiviteId = tblCollectivites.strCollectiviteId
- WHERE lngChantierId = {lngChantierId};""".format(lngChantierId=chantier.number))
- chantier.name = "{}{} {}".format(chantier.number, chantier.complement, row.strNom)
- logger.debug("> {}".format(chantier.name))
- # importe le fichier shape dans une couche temp
- shp_path = chantier_dir_path / "{}_p_PointCompactage.shp".format(chantier_dir_path.name)
- logger.debug("Read the shapefile: %s", shp_path)
- sf = shapefile.Reader(shp_path)
- # should we check? :
- if sf.shapeType != 1:
- logger.error("Le fichier shapefile n'est pas de type POINT")
- sys.exit(1)
- sh_points = sf.shapeRecords()
- if not sh_points:
- logger.error("Le fichier shapefile ne contient aucune donnees")
- return
- chantier.points = []
- for sh_point in sh_points:
- # create the Point instance
- point = QGisPoint()
- point.number = sh_point.record[0]
- point.name = sh_point.record[1]
- point.x, point.y = sh_point.shape.points[0]
- logger.debug("> {}".format(point))
- chantier.points.append(point)
- del sf, sh_points
- # compute the chantier's rect coordinates
- logger.debug("Compute the chantier's rect coordinates")
- chantier.x0 = min([point.x for point in chantier.points]) - 5
- chantier.x1 = max([point.x for point in chantier.points]) + 5
- chantier.y0 = min([point.y for point in chantier.points]) - 5
- chantier.y1 = max([point.y for point in chantier.points]) + 5
- logger.debug("> ({}, {}, {}, {})".format(chantier.x0, chantier.x1, chantier.y0, chantier.y1))
- chantiers.append(chantier)
- # ** Insère les chantiers dans la base **
- for chantier in chantiers:
- logger.debug("** Chantier {}: {} points".format(chantier.name, len(chantier.points)))
- # Contrôle si un chantier de compactage portant ce nom n'existe pas déjà dans la base
- qry = csig_db.read(u"SELECT id FROM t_chantiers WHERE nom = '{}' AND id_type_chantier=2;".format(chantier.name))
- cancelled = False
- for row in qry:
- logger.warning("Un chantier de compactage portant ce nom existe déjà '{}' (id {})".format(chantier.name, row.id))
- if not "--no" in sys.argv and ("--yes" in sys.argv or input("Voulez-vous le remplacer? (o/n)") == "o"):
- # delete the old chantier
- csig_db.execute("""DELETE FROM t_points_compactage
- WHERE id_chantier = {};""".format(row.id))
- csig_db.execute("""DELETE FROM t_chantiers
- WHERE id = {};""".format(row.id))
- logger.info("> L'ancien chantier a été supprimé".format(chantier.name, row.id))
- else:
- cancelled = True
- break
- if cancelled:
- logger.warning("Import du chantier annulé")
- continue
- # Créé le chantier
- q = csig_db.first("""INSERT INTO t_chantiers(id_type_chantier, numero, nom, geom, archive)
- VALUES ({chantier_type}, {number}, '{name}', {geom}, {archive})
- RETURNING id;
- """.format(
- chantier_type=2,
- number=chantier.number,
- name=chantier.name,
- geom="ST_GeomFromText('POLYGON(({x0} {y0}, \
- {x0} {y1}, {x1} {y1}, {x1} {y0}, {x0} {y0}))', {srid})".format(x0=chantier.x0,
- x1=chantier.x1,
- y0=chantier.y0,
- y1=chantier.y1,
- srid=SRID),
- archive="FALSE"
- )
- )
- # get its postgis ID
- logger.debug("Getting newly created ID")
- chantier.pgid = q.id
- logger.debug("> {}".format(chantier.pgid))
- q = None
- # create the points
- for point in chantier.points:
- csig_db.execute("""INSERT INTO t_points_compactage(numero, nom, id_chantier, geom, archive)
- VALUES ({number}, '{name}', {chantier_id}, ST_GeomFromText('POINT({x} {y})', {srid}), False);
- """.format(
- number=point.number,
- name=point.name,
- chantier_id=chantier.pgid,
- x=point.x,
- y=point.y,
- srid=SRID
- )
- )
- csig_db.commit()
- # rename the directory to mark it as imported ('I_')
- new_path = r"{}\I_{}".format(chantier.dir_path.parent, chantier.dir_path.name)
- logger.debug("Rename {} to {}".format(chantier.dir_path, new_path))
- try:
- chantier.dir_path.rename(new_path)
- except:
- logger.error("Impossible de renommer le dossier")
- logger.info("Le chantier %s a été importé", chantier.name)
- csig_db.close()
- controles_db.close()
- if __name__ == "__main__":
- main()
- logger.info("-- Fin --")
|