# -*- coding: utf-8 -*- """ /*************************************************************************** ParcelleToActe A QGIS plugin Permet d'associer des parcelles à des actes ------------------- begin : 2015-06-19 git sha : $Format:%H$ copyright : (C) 2015 by CEN Savoie email : a.lesconnec@cen-savoie.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ """ from PyQt5 import QtCore, QtGui from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import QAction, QTableWidgetItem, QMessageBox # Initialize Qt resources from file resources.py from pluginsCenSavoie_v3 import resources # Import the code for the dialog from pluginsCenSavoie_v3.tools.parcelle_to_acte_dialog import ParcelleToActeDialog # Import du fichier de configuration from pluginsCenSavoie_v3.tools.confPython import bd_cen_host, bd_cen_port, bd_cen_name, bd_cen_mdp_1st_cnx import os.path import sys import qgis import os import psycopg2 import psycopg2.extras import base64 import re from time import localtime, strftime class ParcelleToActe: """QGIS Plugin Implementation.""" def __init__(self, iface, cenToolbar): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Variable HOTE de l'accès à la base de données global host host = bd_cen_host global port port = bd_cen_port global bdd bdd = bd_cen_name global mdp_1st_cnx mdp_1st_cnx = bd_cen_mdp_1st_cnx global os_user if sys.platform in ('linux','darwin'): os_user = os.environ['USER'] else: os_user = os.environ['USERNAME'] # Save reference to the QGIS interface self.iface = iface self.canvas = self.iface.mapCanvas() # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) # Create the dialog (after translation) and keep reference self.dlg = ParcelleToActeDialog() # Add toolbar button self.action= QAction(QIcon(":/plugins/pluginsCenSavoie_v3/icons/parcelleToActe.png"), QCoreApplication.translate('ParcelleToActe', u'Associer des parcelles à un acte'), self.iface.mainWindow()) self.action.triggered.connect(self.run) self.action.setEnabled(False) cenToolbar.addAction(self.action) self.canvas.selectionChanged.connect(self.toggle) self.iface.layerTreeView().currentLayerChanged.connect(self.toggle) def toggle(self): layer = self.iface.activeLayer() if layer and layer.type() == layer.VectorLayer: if layer.selectedFeatureCount() > 0: provider = layer.dataProvider() source_postgis = provider.dataSourceUri() source_postgis = source_postgis.replace('"', '') if (source_postgis.count('table=foncier.parcelles_dispo ') == 1): self.action.setEnabled(True) else: self.action.setEnabled(False) else: self.action.setEnabled(False) else: self.action.setEnabled(False) def changeCellValue(self, ligne, col): self.dlg.tbl_detail.blockSignals(True) if self.dlg.tbl_detail.item(ligne, 2).text() == 'OUI' and col != 0: self.dlg.tbl_detail.setItem(ligne, 2, QTableWidgetItem('NON')) self.dlg.tbl_detail.item(ligne, 1).setBackground(QtGui.QColor(255, 145, 145)) self.dlg.tbl_detail.item(ligne, 2).setBackground(QtGui.QColor(255, 145, 145)) elif self.dlg.tbl_detail.item(ligne, 2).text() == 'NON' and col != 0: self.dlg.tbl_detail.setItem(ligne, 2, QTableWidgetItem('OUI')) self.dlg.tbl_detail.item(ligne, 1).setBackground(QtGui.QColor(115, 215, 115)) self.dlg.tbl_detail.item(ligne, 2).setBackground(QtGui.QColor(115, 215, 115)) self.dlg.tbl_detail.item(ligne, col).setSelected(False) self.dlg.tbl_detail.blockSignals(False) def chg_date_modif(self): self.dlg.cal_date_modif.setEnabled(True) self.dlg.cal_date_modif.setVisible(1) def chg_cal_date_modif(self, date): current_date_modif = date.toString('yyyy-MM-dd') self.dlg.date_modif.setText(str(current_date_modif)) self.dlg.cal_date_modif.setEnabled(False) self.dlg.cal_date_modif.setVisible(0) if self.dlg.lst_actes.currentIndex() != -1 and self.dlg.date_modif.text() != 'N.P.' and self.dlg.lst_motif_maj.currentIndex() != -1 : self.dlg.button_box.setEnabled(True) else: self.dlg.button_box.setEnabled(False) def run(self): """Run method that performs all the real work""" # initialise le contenant du formulaire self.dlg.tbl_detail.setColumnCount(4) self.dlg.tbl_detail.setHorizontalHeaderItem(0, QTableWidgetItem('Par ID')) self.dlg.tbl_detail.setHorizontalHeaderItem(1, QTableWidgetItem('Lot ID')) self.dlg.tbl_detail.setHorizontalHeaderItem(2, QTableWidgetItem('A Associer')) self.dlg.tbl_detail.setHorizontalHeaderItem(3, QTableWidgetItem('cad_site_id')) self.dlg.tbl_detail.setColumnHidden(3, True) self.dlg.btn_date_modif.clicked.connect(self.chg_date_modif) self.dlg.cal_date_modif.clicked.connect(self.chg_cal_date_modif) self.dlg.tbl_detail.cellClicked.connect(self.changeCellValue) first_conn = psycopg2.connect("host=" + host + " port=" + port + " dbname=" + bdd + " user=first_cnx password=" + mdp_1st_cnx) first_cur = first_conn.cursor(cursor_factory = psycopg2.extras.DictCursor) first_cur.execute("SELECT mdp_cen, usename FROM pg_catalog.pg_user t1, admin_sig.utilisateurs t2 WHERE t2.oid = t1.usesysid AND (utilisateur_id = '" + os_user + "' OR utilisateur_os = '" + os_user + "')") res_ident = first_cur.fetchone() mdp = base64.b64decode(str(res_ident[0])).decode('utf-8') user = res_ident[1] conn = psycopg2.connect("host=" + host + " port=" + port + " dbname=" + bdd + " user=" + user + " password=" + mdp) cur = conn.cursor(cursor_factory = psycopg2.extras.DictCursor) first_conn.close() site_id = [] tbl_dnulot = [] tbl_cad_site_id = [] self.canvas = self.iface.mapCanvas() global layer layer = self.iface.activeLayer() rowCount = 0 for feature in layer.selectedFeatures(): site_id.append(feature["site_id"]) tbl_dnulot = re.split(',', feature["tbl_dnulot"]) if len(tbl_dnulot) > 0: j = 0 while j < len(tbl_dnulot): rowCount += 1 j+=1 self.dlg.tbl_detail.setRowCount(rowCount) for id_site in site_id: rq_lst_sites_around = """ SELECT site_id FROM sites.sites WHERE st_distance(geom_ecolo, (SELECT geom_ecolo FROM sites.sites WHERE site_id = '"""+id_site+"""')) < 1000 AND site_id != '"""+id_site+"""' """ with conn: with conn.cursor() as cur: cur.execute(rq_lst_sites_around) res_lst_sites_around = cur.fetchall() site_id_around = [] if len(res_lst_sites_around) > 0: i = 0 while i < len(res_lst_sites_around): if res_lst_sites_around[i][0] not in site_id and res_lst_sites_around[i][0] not in site_id_around: site_id_around.append(res_lst_sites_around[i][0]) i=i+1 site_id = [*site_id, *site_id_around] if rowCount > 0: ligne = 0 col = 0 for feature in layer.selectedFeatures(): tbl_dnulot = re.split(',', feature["tbl_dnulot"]) tbl_cad_site_id = re.split(',', feature["tbl_cad_site_id"]) if len(tbl_dnulot) > 0: self.dlg.tbl_detail.setItem(ligne, 0, QTableWidgetItem(feature["par_id"])) self.dlg.tbl_detail.setSpan(ligne, 0, len(tbl_dnulot), 1) j = 0 while j < len(tbl_dnulot): self.dlg.tbl_detail.setItem(ligne, 1, QTableWidgetItem(tbl_dnulot[j])) self.dlg.tbl_detail.item(ligne, 1).setBackground(QtGui.QColor(115, 215, 115)) self.dlg.tbl_detail.setItem(ligne, 2, QTableWidgetItem('OUI')) self.dlg.tbl_detail.item(ligne, 2).setBackground(QtGui.QColor(115, 215, 115)) self.dlg.tbl_detail.setItem(ligne, 3, QTableWidgetItem(tbl_cad_site_id[j])) ligne += 1 j+=1 self.dlg.tbl_detail.setEnabled(True) self.dlg.no_lot.setVisible(0) else: self.dlg.tbl_detail.setEnabled(False) self.dlg.no_lot.setVisible(1) self.dlg.tbl_detail.resizeColumnsToContents() if (len(set(site_id)) < 1): QMessageBox.warning(None, "Oups:", 'Selection invalide') else: tbl_site_id = list(set(site_id)) self.dlg.InitFormulaire(tbl_site_id, 'load', user, mdp) self.dlg.img_logo.setPixmap(QPixmap(":/plugins/pluginsCenSavoie_v3/tools/images/Logo_CEN_Savoie.png")) self.dlg.lbl_fond.setPixmap(QPixmap("%s/images/fond_70.png"%self.plugin_dir)) self.dlg.lbl_fond.stackUnder(self.dlg.button_box) # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: curs = QCursor() curs.setShape(Qt.WaitCursor) qgis.utils.iface.mainWindow().centralWidget().setCursor(curs) mfu_id = self.dlg.lst_actes.currentText() motif_maj_id = self.dlg.motif_maj_id.text() mfu_table = self.dlg.type_acte_sel.text() aujourdhui = strftime("%Y-%m-%d %H:%M:%S", localtime()) date_modif = self.dlg.date_modif.text() maj_table = 'NON' with conn: with conn.cursor() as cur: rq_check_droit = """ WITH RECURSIVE t(oid) AS ( VALUES ((SELECT oid FROM admin_sig.utilisateurs WHERE utilisateur_id = '""" + os_user + """' OR utilisateur_os = '""" + os_user + """')) UNION ALL SELECT grosysid FROM pg_catalog.pg_group JOIN t ON (t.oid = ANY (grolist)) ), t_group AS ( SELECT DISTINCT groname FROM pg_catalog.pg_group JOIN t ON (t.oid = pg_group.grosysid)) SELECT count(*) FILTER (WHERE grant_elt_id = 3 AND grant_group_droit = 't' AND grant_group_id IN (groname)) as parc FROM foncier.grant_group JOIN t_group ON (groname = grant_group_id)""" cur.execute(rq_check_droit) can_parc_site = cur.fetchone() if can_parc_site[0] == 0: QMessageBox.warning(None, "ERROR:", """Le traitement a échoué
Vous n'êtes pas autorisé à modifier la liste des parcelles d'un acte""") else: rq_statut_mfu = "SELECT statutmfu_id AS statut_id FROM alertes.v_tdb_mfu WHERE mfu_id = '"+mfu_id+"'" cur.execute(rq_statut_mfu) statut_mfu = cur.fetchone() if (int(statut_mfu[0]) == 0): date_modif = '0000-00-00' else: date_modif = date_modif + ' 00:00:00' if mfu_table == 'r_cad_site_mf': rq_date_debut_acte = "SELECT date_sign_acte FROM foncier.mf_acquisitions WHERE mf_id = '"+mfu_id+"'" suffixe = 'mf' else: rq_date_debut_acte = "SELECT date_effet_conv FROM foncier.mu_conventions WHERE mu_id = '"+mfu_id+"'" suffixe = 'mu' error_date = 'RAS' tbl_cad_site_id = [] for i in range(self.dlg.tbl_detail.rowCount()): tbl_cad_site_id.append(self.dlg.tbl_detail.item(i, 3).text()) lst_cad_site_id = ','.join(tbl_cad_site_id) rq_check_mfu = """ WITH t1 AS ( SELECT cad_site_id FROM alertes.v_tdb_mfu JOIN foncier.r_cad_site_mu ON (mu_id = mfu_id) WHERE statutmfu_id = 1 UNION SELECT cad_site_id FROM alertes.v_tdb_mfu JOIN foncier.r_cad_site_mf ON (mf_id = mfu_id) WHERE statutmfu_id = 1 ) SELECT cad_site_id FROM t1 WHERE cad_site_id IN (""" + str(lst_cad_site_id) + """)""" cur.execute(rq_check_mfu) res_check_mfu = cur.fetchall() if len(res_check_mfu) > 0 and int(statut_mfu[0]) == 1: error_date = 'PROB' QMessageBox.warning(None, "ERROR:", """Le traitement a échoué
Au moins une parcelle est déjà maitrisée""") elif int(motif_maj_id) in [3, 10]: rq_check_date = """ SELECT cad_site_id FROM foncier.cadastre_site JOIN cadastre.cadastre_cen USING (cad_cen_id) WHERE cad_site_id IN (""" + str(lst_cad_site_id) + """) AND '"""+date_modif+"""'::character varying(10) < ("""+rq_date_debut_acte+""")::character varying(10)""" cur.execute(rq_check_date) res_check_date = cur.fetchall() if len(res_check_date) > 0: error_date = 'PROB' QMessageBox.warning(None, "ERROR:", """Le traitement a échoué
Au moins une parcelle ajoutée avant la création de l'acte""") elif int(motif_maj_id) == 9: rq_check_date = """ SELECT cad_site_id FROM foncier.cadastre_site JOIN cadastre.cadastre_cen USING (cad_cen_id) WHERE cad_site_id IN ("""+str(lst_cad_site_id)+""") AND cadastre_cen.date_deb::character varying(10) < ("""+rq_date_debut_acte+""")::character varying(10)""" cur.execute(rq_check_date) res_check_date = cur.fetchall() if len(res_check_date) > 0: error_date = 'PROB' QMessageBox.warning(None, "ERROR:", """Le traitement a échoué
Au moins une parcelle ajoutée avant la création de l'acte""") if error_date == 'RAS': rq_ajout = "INSERT INTO foncier.r_cad_site_"+suffixe+" (cad_site_id, "+suffixe+"_id, date_entree, date_sortie, motif_entree_id, motif_sortie_id) VALUES "; for i in range(self.dlg.tbl_detail.rowCount()): if self.dlg.tbl_detail.item(i, 2).text() == 'OUI': if int(motif_maj_id) == 1 and int(statut_mfu[0]) != 0: rq_ajout += "("+self.dlg.tbl_detail.item(i, 3).text()+", '"+mfu_id+"', ("+rq_date_debut_acte+"), 'N.D.', "+motif_maj_id+", 1), " elif int(motif_maj_id) == 9: rq_ajout += "("+self.dlg.tbl_detail.item(i, 3).text()+", '"+mfu_id+"', (SELECT cadastre_cen.date_deb FROM cadastre.cadastre_cen JOIN foncier.cadastre_site USING (cad_cen_id) WHERE cad_site_id = "+self.dlg.tbl_detail.item(i, 3).text()+"), 'N.D.', "+motif_maj_id+", 1), " else: rq_ajout += "("+self.dlg.tbl_detail.item(i, 3).text()+", '"+mfu_id+"', '"+date_modif+"', 'N.D.', "+motif_maj_id+", 1), " if rq_ajout[-2:] == ', ': rq_ajout = rq_ajout[0:-2] if self.dlg.tbl_detail.rowCount() > 0 and rq_ajout != "INSERT INTO foncier.r_cad_site_"+suffixe+" (cad_site_id, "+suffixe+"_id, date_entree, date_sortie, motif_entree_id, motif_sortie_id) VALUES ": cur.execute(rq_ajout) conn.commit() maj_table = 'OUI' if maj_table == 'OUI': rq_refresh = """ WITH t1 AS ( SELECT array_to_string(array_agg(DISTINCT site_id), ',') as lst_site_id FROM foncier."""+mfu_table+""" JOIN foncier.cadastre_site USING (cad_site_id) WHERE """+mfu_table[len(mfu_table)-2:len(mfu_table)]+"""_id = '"""+mfu_id+"""' ) SELECT admin_sig.refresh_mview_foncier(t1.lst_site_id) FROM t1""" cur.execute(rq_refresh) conn.commit() if mfu_table == 'r_cad_site_mu': rq_update = "UPDATE foncier.mu_conventions SET maj_date = '"+aujourdhui+"', maj_user = '"+os_user+"' WHERE mu_id = '"+mfu_id+"'" elif mfu_table == 'r_cad_site_mf': rq_update = "UPDATE foncier.mf_acquisitions SET maj_date = '"+aujourdhui+"', maj_user = '"+os_user+"' WHERE mf_id = '"+mfu_id+"'" cur.execute(rq_update) conn.commit() curs = QCursor() curs.setShape(Qt.ArrowCursor) qgis.utils.iface.mainWindow().centralWidget().setCursor(curs) self.canvas.refresh()