qgis_sync_compactage.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. """
  2. Importe les données géographiques des essais de compactage depuis les fichiers Shapefile
  3. recus des exploitants vers la base Postgis de ControlesSig
  4. - Ajoute de nouveaux chantiers / points de compactage à la base POSTGIS
  5. - Les chantiers créés sont issus des dossiers du répertoire 'compactage_dir'
  6. - Une fois importés, ces dossiers sont renommés 'XXXXXX' > 'I_XXXXXX'
  7. - Les noms complets des chantiers sont récupérés dans la base Controles
  8. @author: olivier.massot, mai 2018
  9. """
  10. import logging
  11. import re
  12. import sys
  13. from path import Path
  14. import shapefile
  15. from core import logconf
  16. from core.pde import ControlesDb, CSigDb, COMPACTAGE_DIR, QGisChantier, \
  17. QGisPoint, SRID
  18. from core.sqlformatter import SqlFormatter
  19. logger = logging.getLogger("qgis_sync_compactage")
  20. logconf.start("qgis_sync_compactage", logging.DEBUG)
  21. # # POUR TESTER, décommenter les lignes suivantes
  22. ##-----------------------------------------------
  23. ControlesDb._path = Path(r"\\h2o\local\4-transversal\BDD\mdb_test\cg67Parc_data.mdb")
  24. logger.handlers = [h for h in logger.handlers if (type(h) == logging.StreamHandler)]
  25. logger.warning("<<<<<<<<<<<<<< Mode TEST >>>>>>>>>>>>>>>>>")
  26. ##-----------------------------------------------
  27. Sql = SqlFormatter()
  28. # Connexion à ControlesSig (postgres)
  29. csig_db = CSigDb(autocommit=False)
  30. # Connexion à Controles
  31. controles_db = ControlesDb(autocommit=False)
  32. # Regex pour parser les noms de repertoires
  33. rx = re.compile(r"^(I_)?(\d{5,6})(-S?\d{1,2})?[\s_]?(.*)$")
  34. a_importer = [subdir for subdir in COMPACTAGE_DIR.dirs() if rx.search(subdir.name) and not subdir.name[:2] == "I_"]
  35. if a_importer:
  36. # !!! Selection des chantiers à importer
  37. pass
  38. if not a_importer:
  39. logger.info("Aucun nouveau dossier à importer")
  40. sys.exit()
  41. chantiers = []
  42. # ** Read the data in the shapefiles and store it in memory **
  43. for chantier_dir_path in a_importer:
  44. logger.info("** %s", chantier_dir_path)
  45. # instanciate a new Chantier
  46. chantier = QGisChantier()
  47. chantier.dir_path = chantier_dir_path
  48. logger.debug("> parse path")
  49. parsed = rx.search(chantier_dir_path.name)
  50. chantier.number = parsed.group(2)
  51. chantier.complement = parsed.group(3)
  52. logger.debug("> number: %s, compl: %s", chantier.number, chantier.complement)
  53. # query for name in ControlesDb
  54. logger.debug("> Query ControlesDb for chantier's name")
  55. row = controles_db.first("""SELECT tblChantiers.lngChantierId, tblCollectivites.strNom
  56. FROM tblChantiers INNER JOIN tblCollectivites
  57. ON tblChantiers.strCollectiviteId = tblCollectivites.strCollectiviteId
  58. WHERE lngChantierId = {lngChantierId};""".format(lngChantierId=chantier.number))
  59. chantier.name = "{} {}".format(chantier.number, row.strNom)
  60. logger.debug("> {}".format(chantier.name))
  61. # importe le fichier shape dans une couche temp
  62. shp_path = chantier_dir_path / "{}_p_PointCompactage.shp".format(chantier_dir_path.name)
  63. logger.debug("Read the shapefile: %s", shp_path)
  64. sf = shapefile.Reader(shp_path)
  65. # should we check? :
  66. if sf.shapeType != 1:
  67. logger.error("Le fichier shapefile n'est pas de type POINT")
  68. sys.exit(1)
  69. sh_points = sf.shapeRecords()
  70. if not sh_points:
  71. logger.error("Le fichier shapefile ne contient aucune donnees")
  72. sys.exit(1)
  73. chantier.points = []
  74. for sh_point in sh_points:
  75. # create the Point instance
  76. point = QGisPoint()
  77. point.number = sh_point.record[0]
  78. point.name = sh_point.record[1]
  79. point.x, point.y = sh_point.shape.points[0]
  80. logger.debug("> {}".format(point))
  81. chantier.points.append(point)
  82. # compute the chantier's rect coordinates
  83. logger.debug("Compute the chantier's rect coordinates")
  84. chantier.x0 = min([point.x for point in chantier.points])
  85. chantier.x1 = max([point.x for point in chantier.points])
  86. chantier.y0 = min([point.y for point in chantier.points])
  87. chantier.y1 = max([point.y for point in chantier.points])
  88. logger.debug("> ({}, {}, {}, {})".format(chantier.x0, chantier.x1, chantier.y0, chantier.y1))
  89. chantiers.append(chantier)
  90. # ** Insère les chantiers dans la base **
  91. for chantier in chantiers:
  92. logger.debug("** Chantier {}: {} points".format(chantier.name, len(chantier.points)))
  93. # Contrôle si un chantier portant ce nom n'existe pas déjà dans la base
  94. row = csig_db.first(u"SELECT id FROM t_chantiers WHERE nom = '{}';".format(chantier.name))
  95. if row:
  96. logger.warning("Un chantier portant ce nom existe déjà {} (id {})".format(chantier.name, row.id))
  97. if input("Voulez-vous le remplacer? (o/n)") == "o":
  98. # delete the old chantier
  99. csig_db.execute("""DELETE FROM t_points_compactage
  100. WHERE id_chantier = {};""".format(row.id))
  101. csig_db.execute("""DELETE FROM t_chantiers
  102. WHERE id = {};""".format(row.id))
  103. logger.info("> L'ancien chantier a été supprimé".format(chantier.name, row.id))
  104. else:
  105. logger.warning("Import du chantier annulé")
  106. continue
  107. # Créé le chantier
  108. q = csig_db.first("""INSERT INTO t_chantiers(id_type_chantier, numero, nom, geom, archive)
  109. VALUES ({chantier_type}, {number}, '{name}', {geom}, {archive})
  110. RETURNING id;
  111. """.format(
  112. chantier_type=2,
  113. number=chantier.number,
  114. name=chantier.name,
  115. geom="ST_GeomFromText('POLYGON(({x0} {y0}, \
  116. {x0} {y1}, {x1} {y1}, {x1} {y0}, {x0} {y0}))', {srid})".format(x0=chantier.x0,
  117. x1=chantier.x1,
  118. y0=chantier.y0,
  119. y1=chantier.y1,
  120. srid=SRID),
  121. archive="FALSE"
  122. )
  123. )
  124. # get its postgis ID
  125. logger.debug("Getting newly created ID")
  126. chantier.pgid = q.id
  127. logger.debug("> {}".format(chantier.pgid))
  128. q = None
  129. # create the points
  130. for point in chantier.points:
  131. csig_db.execute("""INSERT INTO t_points_compactage(numero, nom, id_chantier, geom, archive)
  132. VALUES ({number}, '{name}', {chantier_id}, {geom}, {archive});
  133. """.format(
  134. number=point.number,
  135. name=point.name,
  136. chantier_id=chantier.pgid,
  137. geom="ST_GeomFromText('POINT({x} {y})', {srid})".format(x=point.x, y=point.y, srid=SRID),
  138. archive="FALSE"
  139. )
  140. )
  141. csig_db.commit()
  142. # rename the directory to mark it as imported ('I_')
  143. new_path = r"{}\I_{}".format(chantier.dir_path.parent, chantier.dir_path.name)
  144. logger.debug("Rename {} to {}".format(chantier.dir_path, new_path))
  145. chantier.dir_path.rename(new_path)
  146. logger.info("Chantier importé")