def finish_feature_creation(self, layerId, features): if len(features) != 1: return SpacialSourceFinishFeatureCreationArgs(added_features_amount=len(features)) fid = features[0].id() # editing layer Name? if not self.__editing_layer.getFeature(fid).isValid(): # self.logger.warning(__name__, "Feature not found in layer {}...".format(self.__editing_layer_name)) # TODO send this info to controller return SpacialSourceFinishFeatureCreationArgs(SpacialSourceFinishFeatureCreationArgs(is_valid=False)) # feature_rrr_id: generic name used for represent id for right, restriction # feature_rrr_id = self._layers[self.EDITING_LAYER_NAME].getFeature(fid)[self.names.T_ID_F] feature_tid = self.__editing_layer.getFeature(fid)[self.__db.names.T_ID_F] administrative_source_ids = LADMData.get_list_of_features_ids(self.__layers[self.names.LC_ADMINISTRATIVE_SOURCE_T], self.names.T_ID_F) # Fill rrrfuente table new_features = [] attr_fk = None if self.__editing_layer_name == self.names.LC_RIGHT_T: attr_fk = self.names.COL_RRR_SOURCE_T_LC_RIGHT_F elif self.__editing_layer_name == self.names.LC_RESTRICTION_T: attr_fk = self.names.COL_RRR_SOURCE_T_LC_RESTRICTION_F new_features = LADMData.save_relations(self.__layers[self.names.COL_RRR_SOURCE_T], self.names.COL_RRR_SOURCE_T_SOURCE_F, administrative_source_ids, attr_fk, feature_tid) return SpacialSourceFinishFeatureCreationArgs(True, feature_tid, 1, None)
def finish_feature_creation(self, layerId, features): if len(features) != 1: # TODO send this info to controller # message = QCoreApplication.translate("WizardTranslations", "'{}' tool has been closed. We should have got only one {} by we have {}").format(self.WIZARD_TOOL_NAME, self.WIZARD_FEATURE_NAME, len(features)) # self.logger.warning(__name__, "We should have got only one {}, but we have {}".format(self.WIZARD_FEATURE_NAME, len(features))) return SpacialSourceFinishFeatureCreationArgs( added_features_amount=len(features)) feature = features[0] if not feature.isValid(): # TODO send this info to controller # self.logger.warning(__name__, "Feature not found in layer Spatial Source...") return SpacialSourceFinishFeatureCreationArgs(is_valid=False) feature_tid = feature[self.names.T_ID_F] feature_ids = LADMData.get_list_of_features_ids( self.__layers[self.names.LC_PLOT_T], self.names.T_ID_F) new_features = LADMData.save_relations( self.__layers[self.names.COL_UE_SOURCE_T], self.names.COL_UE_SOURCE_T_LC_PLOT_F, feature_ids, self.names.COL_UE_SOURCE_T_SOURCE_F, feature_tid) # all_new_features.extend(new_features) feature_ids = LADMData.get_list_of_features_ids( self.__layers[self.names.LC_BOUNDARY_T], self.names.T_ID_F) new_features = LADMData.save_relations( self.__layers[self.names.COL_CCL_SOURCE_T], self.names.COL_CCL_SOURCE_T_BOUNDARY_F, feature_ids, self.names.COL_CCL_SOURCE_T_SOURCE_F, feature_tid) feature_ids = LADMData.get_list_of_features_ids( self.__layers[self.names.LC_BOUNDARY_POINT_T], self.names.T_ID_F) new_features = LADMData.save_relations( self.__layers[self.names.COL_POINT_SOURCE_T], self.names.COL_POINT_SOURCE_T_LC_BOUNDARY_POINT_F, feature_ids, self.names.COL_POINT_SOURCE_T_SOURCE_F, feature_tid) feature_ids = LADMData.get_list_of_features_ids( self.__layers[self.names.LC_SURVEY_POINT_T], self.names.T_ID_F) new_features = LADMData.save_relations( self.__layers[self.names.COL_POINT_SOURCE_T], self.names.COL_POINT_SOURCE_T_LC_SURVEY_POINT_F, feature_ids, self.names.COL_POINT_SOURCE_T_SOURCE_F, feature_tid) feature_ids = LADMData.get_list_of_features_ids( self.__layers[self.names.LC_CONTROL_POINT_T], self.names.T_ID_F) new_features = LADMData.save_relations( self.__layers[self.names.COL_POINT_SOURCE_T], self.names.COL_POINT_SOURCE_T_LC_CONTROL_POINT_F, feature_ids, self.names.COL_POINT_SOURCE_T_SOURCE_F, feature_tid) return SpacialSourceFinishFeatureCreationArgs(True, feature_tid, 1, None)
def setUp(self): restore_schema(SCHEMA_LADM_COL_EMPTY, True) self.db_pg = get_pg_conn(SCHEMA_LADM_COL_EMPTY) self.names = self.db_pg.names self.ladm_data = LADMData() self.geometry = GeometryUtils() res, code, msg = self.db_pg.test_connection() self.assertTrue(res, msg) self.assertIsNotNone(self.names.LC_BOUNDARY_POINT_T, 'Names is None')
def _validate(self, db, db_qr, layer_dict, tolerance, **kwargs): self.progress_changed.emit(5) ladm_queries = self._get_ladm_queries(db.engine) pre_res, pre_obj = self._check_prerrequisite_layers(layer_dict) if not pre_res: return pre_obj error_state = None # Check boundary point with duplicate records table = db.names.LC_BOUNDARY_POINT_T fields = [ db.names.LC_BOUNDARY_POINT_T_AGREEMENT_F, db.names.LC_BOUNDARY_POINT_T_PHOTO_IDENTIFICATION_F, db.names.LC_BOUNDARY_POINT_T_VERTICAL_ACCURACY_F, db.names.LC_BOUNDARY_POINT_T_HORIZONTAL_ACCURACY_F, db.names.COL_POINT_T_INTERPOLATION_POSITION_F, db.names.COL_POINT_T_PRODUCTION_METHOD_F, db.names.LC_BOUNDARY_POINT_T_POINT_TYPE_F, db.names.COL_POINT_T_ORIGINAL_LOCATION_F ] res, records = ladm_queries.get_duplicate_records_in_table( db, table, fields) count = len(records) self.progress_changed.emit(50) if res: error_state = LADMData().get_domain_code_from_value( db_qr, db_qr.names.ERR_ERROR_STATE_D, LADMNames.ERR_ERROR_STATE_D_ERROR_V) errors = {'geometries': list(), 'data': list()} for record in records: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] record['duplicate_uuids'].split(','), None, None, 'Punto Lindero repetido {} veces'.format( record['duplicate_total']), error_state ] errors['data'].append(error_data) self._save_errors(db_qr, self._ERROR_01, errors) self.progress_changed.emit(85) if count > 0: res_type = EnumQualityRuleResult.ERRORS msg = QCoreApplication.translate( "QualityRules", "{} boundary points with repeated records.").format(count) else: res_type = EnumQualityRuleResult.SUCCESS msg = QCoreApplication.translate( "QualityRules", "No duplicate boundary points were found.") self.progress_changed.emit(100) return QualityRuleExecutionResult(res_type, msg, count)
def _validate(self, db, db_qr, layer_dict, tolerance, **kwargs): self.progress_changed.emit(5) ladm_queries = self._get_ladm_queries(db.engine) pre_res, pre_obj = self._check_prerrequisite_layers(layer_dict) if not pre_res: return pre_obj error_state = None # Check administrative source with duplicate records table = db.names.LC_ADMINISTRATIVE_SOURCE_T fields = [ db.names.LC_ADMINISTRATIVE_SOURCE_T_EMITTING_ENTITY_F, db.names.COL_ADMINISTRATIVE_SOURCE_T_SOURCE_NUMBER_F, db.names.COL_ADMINISTRATIVE_SOURCE_T_OBSERVATION_F, db.names.LC_ADMINISTRATIVE_SOURCE_T_TYPE_F, db.names.COL_SOURCE_T_DATE_DOCUMENT_F, db.names.COL_SOURCE_T_AVAILABILITY_STATUS_F, db.names.COL_SOURCE_T_MAIN_TYPE_F ] res, records = ladm_queries.get_duplicate_records_in_table( db, table, fields) count = len(records) self.progress_changed.emit(50) if res: error_state = LADMData().get_domain_code_from_value( db_qr, db_qr.names.ERR_ERROR_STATE_D, LADMNames.ERR_ERROR_STATE_D_ERROR_V) errors = {'geometries': list(), 'data': list()} for record in records: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] record['duplicate_uuids'].split(','), None, None, 'Fuente administrativa repetida {} veces'.format( record['duplicate_total']), error_state ] errors['data'].append(error_data) self._save_errors(db_qr, self._ERROR_01, errors) self.progress_changed.emit(85) if count > 0: res_type = EnumQualityRuleResult.ERRORS msg = QCoreApplication.translate( "QualityRules", "{} administrative sources " "with duplicate records were found.").format(count) else: res_type = EnumQualityRuleResult.SUCCESS msg = QCoreApplication.translate( "QualityRules", "No duplicate administrative sources were found.") self.progress_changed.emit(100) return QualityRuleExecutionResult(res_type, msg, count)
def setUpClass(cls): import_qgis_model_baker() cls.db_gpkg = get_copy_gpkg_conn('test_ladm_survey_model_gpkg') res, code, msg = cls.db_gpkg.test_connection() cls.assertTrue(res, msg) cls.app = AppInterface() cls.ladm_data = LADMData()
def __get_error_state_value(self, state_t_id): if state_t_id not in self.__error_state_dict: db = self.__qr_engine.get_db_quality() self.__error_state_dict[state_t_id] = LADMData( ).get_domain_value_from_code(db, db.names.ERR_ERROR_STATE_D, state_t_id) return self.__error_state_dict.get(state_t_id, "")
def get_dict_automatic_values(db, layer_name, models): names = db.names ladm_data = LADMData() dict_automatic_values = dict() for model_key in models: if model_key == LADMNames.SURVEY_MODEL_KEY: if layer_name == names.LC_BOUNDARY_T: dict_automatic_values = { names.LC_BOUNDARY_T_LENGTH_F: "$length" } elif layer_name == names.LC_PARTY_T: dict_automatic_values = { names.LC_PARTY_T_TYPE_F: "{}".format( ladm_data.get_domain_code_from_value( db, names.LC_PARTY_TYPE_D, LADMNames. LC_PARTY_TYPE_D_ILICODE_F_NATURAL_PARTY_V)) } elif layer_name == names.LC_PARCEL_T: dict_automatic_values = { # names.LC_PARCEL_T_DEPARTMENT_F: 'substr("{}", 0, 2)'.format(names.LC_PARCEL_T_PARCEL_NUMBER_F), # names.LC_PARCEL_T_MUNICIPALITY_F: 'substr("{}", 3, 3)'.format(names.LC_PARCEL_T_PARCEL_NUMBER_F) } elif layer_name == names.LC_ADMINISTRATIVE_SOURCE_T: dict_automatic_values = { names.COL_SOURCE_T_MAIN_TYPE_F: "{}".format( ladm_data.get_domain_code_from_value( db, names.CI_CODE_PRESENTATION_FORM_D, LADMNames. CI_CODE_PRESENTATION_FORM_D_DOCUMENT_V)) } elif model_key == LADMNames.FIELD_DATA_CAPTURE_MODEL_KEY: if layer_name == names.FDC_USER_T: dict_automatic_values = { names.FDC_USER_T_DOCUMENT_TYPE_F: "{}".format( ladm_data.get_domain_code_from_value( db, names.FDC_PARTY_DOCUMENT_TYPE_D, LADMNames. FDC_PARTY_DOCUMENT_TYPE_D_ILICODE_F_CC_V)) } return dict_automatic_values
def setUpClass(cls): print("INFO: Restoring databases to be used") restore_schema('test_change_detections') cls.db_pg = get_pg_conn('test_change_detections') res, code, msg = cls.db_pg.test_connection() cls.assertTrue(res, msg) cls.app = AppInterface() cls.ladm_data = LADMData()
def _validate(self, db, db_qr, layer_dict, tolerance, **kwargs): self.progress_changed.emit(5) ladm_queries = self._get_ladm_queries(db.engine) pre_res, pre_obj = self._check_prerrequisite_layers(layer_dict) if not pre_res: return pre_obj error_state = None # Check building with duplicate records table = db.names.LC_BUILDING_T fields = [ db.names.LC_BUILDING_T_BUILDING_VALUATION_F, db.names.LC_BUILDING_T_BUILDING_AREA_F, db.names.COL_SPATIAL_UNIT_T_DIMENSION_F, db.names.COL_SPATIAL_UNIT_T_LABEL_F, db.names.COL_SPATIAL_UNIT_T_SURFACE_RELATION_F, db.names.COL_SPATIAL_UNIT_T_GEOMETRY_F ] res, records = ladm_queries.get_duplicate_records_in_table( db, table, fields) count = len(records) self.progress_changed.emit(50) if res: error_state = LADMData().get_domain_code_from_value( db_qr, db_qr.names.ERR_ERROR_STATE_D, LADMNames.ERR_ERROR_STATE_D_ERROR_V) errors = {'geometries': list(), 'data': list()} for record in records: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] record['duplicate_uuids'].split(','), None, None, 'Construcción repetida {} veces'.format( record['duplicate_total']), error_state ] errors['data'].append(error_data) self._save_errors(db_qr, self._ERROR_01, errors) self.progress_changed.emit(85) if count > 0: res_type = EnumQualityRuleResult.ERRORS msg = QCoreApplication.translate( "QualityRules", "{} buildings with repeated records.").format(count) else: res_type = EnumQualityRuleResult.SUCCESS msg = QCoreApplication.translate( "QualityRules", "No duplicate buildings were found.") self.progress_changed.emit(100) return QualityRuleExecutionResult(res_type, msg, count)
def _validate(self, db, db_qr, layer_dict, tolerance, **kwargs): self.progress_changed.emit(5) ladm_queries = self._get_ladm_queries(db.engine) pre_res, pre_obj = self._check_prerrequisite_layers(layer_dict) if not pre_res: return pre_obj error_state = None table = db.names.LC_RIGHT_T fields = [ db.names.LC_RIGHT_T_TYPE_F, db.names.COL_RRR_T_DESCRIPTION_F, db.names.COL_RRR_PARTY_T_LC_GROUP_PARTY_F, db.names.COL_RRR_PARTY_T_LC_PARTY_F, db.names.COL_BAUNIT_RRR_T_UNIT_F ] res, records = ladm_queries.get_duplicate_records_in_table( db, table, fields) count = len(records) self.progress_changed.emit(50) if res: error_state = LADMData().get_domain_code_from_value( db_qr, db_qr.names.ERR_ERROR_STATE_D, LADMNames.ERR_ERROR_STATE_D_ERROR_V) errors = {'geometries': list(), 'data': list()} for record in records: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] record['duplicate_uuids'].split(','), None, None, 'Derecho repetido {} veces'.format( record['duplicate_total']), error_state ] errors['data'].append(error_data) self._save_errors(db_qr, self._ERROR_01, errors) self.progress_changed.emit(85) if count > 0: res_type = EnumQualityRuleResult.ERRORS msg = QCoreApplication.translate( "QualityRules", "{} right " "with duplicate records were found.").format(count) else: res_type = EnumQualityRuleResult.SUCCESS msg = QCoreApplication.translate("QualityRules", "No duplicate right were found.") self.progress_changed.emit(100) return QualityRuleExecutionResult(res_type, msg, count)
def _validate(self, db, db_qr, layer_dict, tolerance, **kwargs): self.progress_changed.emit(5) point_layer = self._get_layer(layer_dict) pre_res, res_obj = self._check_prerrequisite_layer( QCoreApplication.translate("QualityRules", "Boundary point"), point_layer) if not pre_res: return res_obj overlapping = GeometryUtils.get_overlapping_points(point_layer) flat_overlapping = [fid for items in overlapping for fid in items] # Build a flat list of ids self.progress_changed.emit(70) dict_uuids = { f.id(): f[db.names.T_ILI_TID_F] for f in point_layer.getFeatures(flat_overlapping) } error_state = LADMData().get_domain_code_from_value( db_qr, db_qr.names.ERR_ERROR_STATE_D, LADMNames.ERR_ERROR_STATE_D_ERROR_V) errors = {'geometries': list(), 'data': list()} for items in overlapping: # We need a feature geometry, pick the first id to get it feature = point_layer.getFeature(items[0]) errors['geometries'].append(feature.geometry()) error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [str(dict_uuids.get(i)) for i in items], None, json.dumps({"conteo": len(items)}), None, error_state ] errors['data'].append(error_data) self._save_errors(db_qr, self._ERROR_01, errors) self.progress_changed.emit(100) if len(flat_overlapping) > 0: return QualityRuleExecutionResult( EnumQualityRuleResult.ERRORS, QCoreApplication.translate( "QualityRules", "{} overlapping boundary points were found!").format( len(flat_overlapping)), len(errors['data'])) else: return QualityRuleExecutionResult( EnumQualityRuleResult.SUCCESS, QCoreApplication.translate( "QualityRules", "There are no overlapping boundary points."))
def __get_error_state_t_id(self, state_value): # Use __error_state_dict to read cached values, but this time we have the value, # not the key, so check in dict values and if not found, go for its t_id if state_value not in self.__error_state_dict.values(): db = self.__qr_engine.get_db_quality() t_id = LADMData().get_domain_code_from_value( db, db.names.ERR_ERROR_STATE_D, state_value) self.__error_state_dict[t_id] = state_value # Get key by value in a dict: return next((k for k in self.__error_state_dict if self.__error_state_dict[k] == state_value), None)
def setUpClass(cls): # DB with single child model cls.db_gpkg = get_copy_gpkg_conn('test_ladm_survey_model_gpkg') res, code, msg = cls.db_gpkg.test_connection() cls.assertTrue(res, msg) # DB with multiple child models and domains cls.db_multi_gpkg = get_copy_gpkg_conn('test_ladm_multiple_child_domains_gpkg') res, code, msg = cls.db_multi_gpkg.test_connection() cls.assertTrue(res, msg) cls.app = AppInterface() cls.ladm_data = LADMData()
def load_error_results_data(self): """ Go to table and bring data to the dict. We should keep this dict updated with changes from the user. From time to time we reflect this dict changes in the original data source. """ db = self.__qr_engine.get_db_quality() names = db.names layers = {names.ERR_QUALITY_ERROR_T: None, names.ERR_RULE_TYPE_T: None} self.app.core.get_layers(db, layers, load=False) if not layers: self.logger.critical( __name__, "Quality error layers ('{}') not found!".format(",".join( list(layers.keys())))) return # First go for the selected quality error's t_id features = LADMData.get_features_from_t_ids( layers[names.ERR_RULE_TYPE_T], names.ERR_RULE_TYPE_T_CODE_F, [self.__selected_qr.id()]) t_id = features[0][names.T_ID_F] if features else None if not t_id: self.logger.critical( __name__, "Quality error rule ('{}') not found!".format( self.__selected_qr.id())) return # Now go for all features that match the selected quality rule features = LADMData.get_features_from_t_ids( layers[names.ERR_QUALITY_ERROR_T], names.ERR_QUALITY_ERROR_T_RULE_TYPE_F, [t_id]) self.__error_results_data[self.__selected_qr.id()] = { feature[names.T_ID_F]: feature for feature in features }
def _validate(self, db, db_qr, layer_dict, tolerance, **kwargs): self.progress_changed.emit(5) right_of_way_layer = self._get_layer(layer_dict) pre_res, res_obj = self._check_prerrequisite_layer( QCoreApplication.translate("QualityRules", "Right of way"), right_of_way_layer) if not pre_res: return res_obj self.progress_changed.emit(10) multi_parts, right_of_way_ids = GeometryUtils.get_multipart_geoms( right_of_way_layer) self.progress_changed.emit(70) error_state = LADMData().get_domain_code_from_value( db_qr, db_qr.names.ERR_ERROR_STATE_D, LADMNames.ERR_ERROR_STATE_D_ERROR_V) errors = {'geometries': list(), 'data': list()} if multi_parts: for right_of_way_geom, right_of_way_id in zip( multi_parts, right_of_way_ids): errors['geometries'].append(right_of_way_geom) error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [ right_of_way_layer.getFeature(right_of_way_id)[ db.names.T_ILI_TID_F] ], None, None, self._errors[self._ERROR_01], error_state ] errors['data'].append(error_data) self._save_errors(db_qr, self._ERROR_01, errors) self.progress_changed.emit(90) count = len(errors['data']) if count > 0: res_type = EnumQualityRuleResult.ERRORS msg = QCoreApplication.translate( "QualityRules", "{} rights of way with " "multipart geometry were found.").format(count) else: res_type = EnumQualityRuleResult.SUCCESS msg = QCoreApplication.translate( "QualityRules", "All rights of way have simple geometry!!") self.progress_changed.emit(100) return QualityRuleExecutionResult(res_type, msg, count)
def get_field_values_by_key_values(layer, field, field_values, expected_field): """ Returns the fields associated with a field based on another field. Same order coming in field_values must be preserved in the returned array. :param layer: QgsMapLayer :param field: Field name, it must be a unique field in the table :param field_values: List of values to use for filtering the layer by field name :param expected_field: name of the field from which the values are expected :return: List of values associated with the expected field. Order is preserved """ features = LADMData.get_features_from_t_ids( layer, field, field_values, only_attributes=[expected_field]) return [f[expected_field] for f in features]
def _validate(self, db, db_qr, layer_dict, tolerance, **kwargs): self.progress_changed.emit(5) ladm_queries = self._get_ladm_queries(db.engine) pre_res, pre_obj = self._check_prerrequisite_layers(layer_dict) if not pre_res: return pre_obj error_state = None # Check parcel with incorrect department code res, records = ladm_queries.get_parcels_with_invalid_department_code( db) count = len(records) self.progress_changed.emit(50) if res: error_state = LADMData().get_domain_code_from_value( db_qr, db_qr.names.ERR_ERROR_STATE_D, LADMNames.ERR_ERROR_STATE_D_ERROR_V) errors = {'geometries': list(), 'data': list()} for record in records: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [record[db.names.T_ILI_TID_F]], None, None, 'El código de departamento de la tabla predio debe tener dos caracteres numéricos', error_state ] errors['data'].append(error_data) self._save_errors(db_qr, self._ERROR_01, errors) self.progress_changed.emit(85) if count > 0: res_type = EnumQualityRuleResult.ERRORS msg = QCoreApplication.translate( "QualityRules", "{} parcels with invalid department code were found.").format( count) else: res_type = EnumQualityRuleResult.SUCCESS msg = QCoreApplication.translate( "QualityRules", "All parcels have valid department code.") self.progress_changed.emit(100) return QualityRuleExecutionResult(res_type, msg, count)
def _validate(self, db, db_qr, layer_dict, tolerance, **kwargs): self.progress_changed.emit(5) building_layer = self._get_layer(layer_dict) pre_res, res_obj = self._check_prerrequisite_layer(QCoreApplication.translate("QualityRules", "Building"), building_layer) if not pre_res: return res_obj overlapping = GeometryUtils.get_overlapping_polygons(self, building_layer) flat_overlapping = [fid for items in overlapping for fid in items] # Build a flat list of ids flat_overlapping = list(set(flat_overlapping)) # unique values self.progress_changed.emit(70) dict_uuids = {f.id(): f[db.names.T_ILI_TID_F] for f in building_layer.getFeatures(flat_overlapping)} error_state = LADMData().get_domain_code_from_value(db_qr, db_qr.names.ERR_ERROR_STATE_D, LADMNames.ERR_ERROR_STATE_D_ERROR_V) errors = {'geometries': list(), 'data': list()} for items in overlapping: polygon_id_field = items[0] overlapping_id_field = items[1] polygon_intersection = GeometryUtils.get_intersection_polygons(building_layer, polygon_id_field, overlapping_id_field) if polygon_intersection is not None: errors['geometries'].append(polygon_intersection) error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [dict_uuids.get(polygon_id_field)], [dict_uuids.get(overlapping_id_field)], None, self._errors[self._ERROR_01], error_state] errors['data'].append(error_data) self._save_errors(db_qr, self._ERROR_01, errors) if len(flat_overlapping) > 0: res_type = EnumQualityRuleResult.ERRORS msg = QCoreApplication.translate("QualityRules", "{} overlapping buildings were found!").format(len(flat_overlapping)) else: res_type = EnumQualityRuleResult.SUCCESS msg = QCoreApplication.translate("QualityRules", "There are no overlapping buildings!") self.progress_changed.emit(100) return QualityRuleExecutionResult(res_type, msg, len(flat_overlapping))
def error_type_code_and_display(self, feature): db = self.__qr_engine.get_db_quality() names = db.names layer = self.app.core.get_layer(db, names.ERR_ERROR_TYPE_T, load=False) features = LADMData.get_features_from_t_ids( layer, names.T_ID_F, [feature[db.names.ERR_QUALITY_ERROR_T_ERROR_TYPE_F]]) # tid return features[0][ names. ERR_ERROR_TYPE_T_CODE_F] if features else QCoreApplication.translate( "QualityRules", "No error type found!" ), features[0][ names. ERR_ERROR_TYPE_T_DESCRIPTION_F] if features else QCoreApplication.translate( "QualityRules", "No error description found!")
def get_dict_automatic_values(db, layer_name, models): names = db.names ladm_data = LADMData() dict_automatic_values = dict() for model_key in models: if model_key == LADMNames.SURVEY_MODEL_KEY: if layer_name == names.LC_BOUNDARY_T: dict_automatic_values = {names.LC_BOUNDARY_T_LENGTH_F: "$length"} elif layer_name == names.LC_PARTY_T: dict_automatic_values = { names.COL_PARTY_T_NAME_F: """ CASE WHEN {party_type} = get_domain_code_from_value('{domain_party_type}', '{LC_PARTY_TYPE_D_ILICODE_F_NATURAL_PARTY_V}', True, False) THEN concat({surname_1}, ' ', {surname_2}, ' ', {first_name_1}, ' ', {first_name_2}) WHEN {party_type} = get_domain_code_from_value('{domain_party_type}', '{LC_PARTY_TYPE_D_ILICODE_F_NOT_NATURAL_PARTY_V}', True, False) THEN {business_name} END """.format(party_type=names.LC_PARTY_T_TYPE_F, domain_party_type=names.LC_PARTY_TYPE_D, surname_1=names.LC_PARTY_T_SURNAME_1_F, surname_2=names.LC_PARTY_T_SURNAME_2_F, first_name_1=names.LC_PARTY_T_FIRST_NAME_1_F, first_name_2=names.LC_PARTY_T_FIRST_NAME_2_F, business_name=names.LC_PARTY_T_BUSINESS_NAME_F, LC_PARTY_TYPE_D_ILICODE_F_NOT_NATURAL_PARTY_V=LADMNames.LC_PARTY_TYPE_D_ILICODE_F_NOT_NATURAL_PARTY_V, LC_PARTY_TYPE_D_ILICODE_F_NATURAL_PARTY_V=LADMNames.LC_PARTY_TYPE_D_ILICODE_F_NATURAL_PARTY_V), names.LC_PARTY_T_TYPE_F: "{}".format(ladm_data.get_domain_code_from_value(db, names.LC_PARTY_TYPE_D, LADMNames.LC_PARTY_TYPE_D_ILICODE_F_NATURAL_PARTY_V)), names.LC_PARTY_T_ETHNIC_GROUP_F: "{}".format(ladm_data.get_domain_code_from_value(db, names.LC_ETHNIC_GROUP_TYPE_D, LADMNames.LC_PARTY_ETHNIC_GROUP_TYPE_D_NONE_V)) } elif layer_name == names.LC_PARCEL_T: dict_automatic_values = { names.LC_PARCEL_T_DEPARTMENT_F: 'substr("{}", 0, 2)'.format(names.LC_PARCEL_T_PARCEL_NUMBER_F), names.LC_PARCEL_T_MUNICIPALITY_F: 'substr("{}", 3, 3)'.format(names.LC_PARCEL_T_PARCEL_NUMBER_F) } elif layer_name == names.LC_ADMINISTRATIVE_SOURCE_T: dict_automatic_values = { names.COL_SOURCE_T_MAIN_TYPE_F: "{}".format(ladm_data.get_domain_code_from_value(db, names.CI_CODE_PRESENTATION_FORM_D, LADMNames.CI_CODE_PRESENTATION_FORM_D_DOCUMENT_V)) } elif model_key == LADMNames.FIELD_DATA_CAPTURE_MODEL_KEY: if layer_name == names.FDC_USER_T: dict_automatic_values = {names.FDC_USER_T_DOCUMENT_TYPE_F: "{}".format( ladm_data.get_domain_code_from_value(db, names.FDC_PARTY_DOCUMENT_TYPE_D, LADMNames.FDC_PARTY_DOCUMENT_TYPE_D_ILICODE_F_CC_V))} return dict_automatic_values
def set_fixed_error(self, error_t_id, fixed): # Save to the intermediate dict of data and to the underlying data source whether an error is fixed or not db = self.__qr_engine.get_db_quality() idx_state = self.__get_error_layer().fields().indexOf( db.names.ERR_QUALITY_ERROR_T_ERROR_STATE_F) value = LADMNames.ERR_ERROR_STATE_D_FIXED_V if fixed else LADMNames.ERR_ERROR_STATE_D_ERROR_V fixed_or_error_t_id = self.__get_error_state_t_id(value) if fixed_or_error_t_id is None: self.logger.critical( __name__, "The error state t_id couldn't be found for value '{}'!". format(value)) return # Save to dict self.get_error_results_data()[error_t_id].setAttribute( idx_state, fixed_or_error_t_id) fids = LADMData.get_fids_from_key_values(self.__get_error_layer(), db.names.T_ID_F, [error_t_id]) # Save to underlying data source if fids: res = self.__get_error_layer().dataProvider( ).changeAttributeValues( {fids[0]: { idx_state: fixed_or_error_t_id }}) if not res: self.logger.critical(__name__, "Error modifying the error state value!") else: self.logger.critical( __name__, "Error with t_id '' not found!".format(error_t_id))
def save_errors(db_qr, rule_code, error_code, error_data, target_layer, ili_name=None): """ Save error data in the quality error model by error_code, which means that you should call this function once per error type. Accepts both, spatial and non-spatial errors. :param db_qr: DB Connector :param rule_code: Rule code as specified in the external catalogs. :param error_code: Error code as specified in the external catalogs. :param error_data: Dict of lists: {'geometries': [geometries], 'data': [obj_uuids, rel_obj_uuids, values, details, state]} Note: this dict will always have 2 elements. Note 2: For geometry errors, this dict will always have the same number of elements in each of the two lists (and the element order matters!). Note 3: For geometryless errors, the 'geometries' value won't be even read. :param target_layer: Value of EnumQualityRuleType. :param ili_name: Interlis name of the class where the object uuids can be found. :return: Tuple (res: boolean, msg: string) """ if not hasattr(db_qr.names, "T_ID_F"): db_qr.test_connection() names = db_qr.names layers = { names.ERR_QUALITY_ERROR_T: None, names.ERR_RULE_TYPE_T: None, names.ERR_ERROR_TYPE_T: None } if target_layer == EnumQualityRuleType.POINT: layers[names.ERR_POINT_T] = None elif target_layer == EnumQualityRuleType.LINE: layers[names.ERR_LINE_T] = None elif target_layer == EnumQualityRuleType.POLYGON: layers[names.ERR_POLYGON_T] = None app.core.get_layers(db_qr, layers, load=True) if not layers: return False, "At least one layer was not found in the quality error db!" # We do now a soon check of rule code and error code to stop if cannot be found fids = LADMData.get_fids_from_key_values(layers[names.ERR_RULE_TYPE_T], names.ERR_RULE_TYPE_T_CODE_F, [rule_code]) if not fids: return False, "There was a problem saving quality error data. The rule '{}' cannot be found in the database. Is that rule in any registered catalog?".format( rule_code) rule_code_id = fids[0] fids = LADMData.get_fids_from_key_values( layers[names.ERR_ERROR_TYPE_T], names.ERR_ERROR_TYPE_T_CODE_F, [error_code]) if not fids: return False, "There was a problem saving quality error data. The error '{}' cannot be found in the database. Is that error in any registered catalog?".format( error_code) error_code_id = fids[0] qr_error_layer = layers[names.ERR_QUALITY_ERROR_T] # First we deal with geometries geom_layer = None idx_geometry_fk = None geom_t_ids = list() # To store fks (geom t_id) if target_layer == EnumQualityRuleType.POINT: geom_layer = layers[names.ERR_POINT_T] idx_geometry_fk = qr_error_layer.fields().indexOf( names.ERR_QUALITY_ERROR_T_POINT_F) elif target_layer == EnumQualityRuleType.LINE: geom_layer = layers[names.ERR_LINE_T] idx_geometry_fk = qr_error_layer.fields().indexOf( names.ERR_QUALITY_ERROR_T_LINE_F) elif target_layer == EnumQualityRuleType.POLYGON: geom_layer = layers[names.ERR_POLYGON_T] idx_geometry_fk = qr_error_layer.fields().indexOf( names.ERR_QUALITY_ERROR_T_POLYGON_F) if geom_layer: idx_t_ili_tid_geom = geom_layer.fields().indexOf(names.T_ILI_TID_F) geometries = error_data['geometries'] features = list() for geometry in geometries: new_feature = QgsVectorLayerUtils().createFeature( geom_layer, geometry, {idx_t_ili_tid_geom: str(uuid.uuid4())}) features.append(new_feature) res_geom, out_features = geom_layer.dataProvider().addFeatures( features) if res_geom: geom_t_ids = [ out_feature[names.T_ID_F] for out_feature in out_features ] else: return False, "There was a problem saving error geometries for error code '{}'!".format( error_code) # Now we deal with the alphanumeric data idx_t_ili_tid = qr_error_layer.fields().indexOf(names.T_ILI_TID_F) idx_rule_type = qr_error_layer.fields().indexOf( names.ERR_QUALITY_ERROR_T_RULE_TYPE_F) idx_error_type = qr_error_layer.fields().indexOf( names.ERR_QUALITY_ERROR_T_ERROR_TYPE_F) idx_object_ids = qr_error_layer.fields().indexOf( names.ERR_QUALITY_ERROR_T_OBJECT_IDS_F) idx_rel_object_ids = qr_error_layer.fields().indexOf( names.ERR_QUALITY_ERROR_T_RELATED_OBJECT_IDS_F) idx_values = qr_error_layer.fields().indexOf( names.ERR_QUALITY_ERROR_T_VALUES_F) idx_ili_name = qr_error_layer.fields().indexOf( names.ERR_QUALITY_ERROR_T_ILI_NAME_F) idx_details = qr_error_layer.fields().indexOf( names.ERR_QUALITY_ERROR_T_DETAILS_F) idx_error_state = qr_error_layer.fields().indexOf( names.ERR_QUALITY_ERROR_T_ERROR_STATE_F) features = list() for i, data in enumerate(error_data['data']): attr_map = { idx_t_ili_tid: str(uuid.uuid4()), idx_rule_type: rule_code_id, idx_error_type: error_code_id, idx_object_ids: data[0], idx_rel_object_ids: data[1], idx_values: data[2], idx_details: data[3], idx_ili_name: ili_name, idx_error_state: data[4] } if geom_layer: attr_map[idx_geometry_fk] = geom_t_ids[ i] # We take advantage of the preserved order here features.append(QgsVectorLayerUtils().createFeature( qr_error_layer, attributes=attr_map)) res_data, out_features = qr_error_layer.dataProvider().addFeatures( features) if not res_data: return False, "There was a problem saving error alphanumeric data for error code '{}'! Details from the provider: {}".format( error_code, qr_error_layer.dataProvider().lastError()) return True, "Success!"
class TestCopy(unittest.TestCase): @classmethod def setUpClass(cls): print("\nINFO: Setting up copy CSV points to DB validation...") print("INFO: Restoring databases to be used") import_asistente_ladm_col() cls.app = AppInterface() cls.app.core.initialize_ctm12() # We need to initialize CTM12 def setUp(self): restore_schema(SCHEMA_LADM_COL_EMPTY, True) self.db_pg = get_pg_conn(SCHEMA_LADM_COL_EMPTY) self.names = self.db_pg.names self.ladm_data = LADMData() self.geometry = GeometryUtils() res, code, msg = self.db_pg.test_connection() self.assertTrue(res, msg) self.assertIsNotNone(self.names.LC_BOUNDARY_POINT_T, 'Names is None') def test_copy_csv_to_db(self): print("\nINFO: Validating copy CSV points to DB...") clean_table(SCHEMA_LADM_COL_EMPTY, self.names.LC_BOUNDARY_POINT_T) layer = self.app.core.get_layer(self.db_pg, self.names.LC_BOUNDARY_POINT_T, True) self.app.core.disable_automatic_fields(layer) csv_path = get_test_path('csv/puntos_fixed_ladm_v1_1.csv') txt_delimiter = ';' cbo_longitude = 'x' cbo_latitude = 'y' csv_layer = self.app.core.csv_to_layer(csv_path, txt_delimiter, cbo_longitude, cbo_latitude, "EPSG:9377", reproject=False) self.upload_points_from_csv(csv_layer, SCHEMA_LADM_COL_EMPTY) self.validate_points_in_db(SCHEMA_LADM_COL_EMPTY) test_layer = self.app.core.get_layer(self.db_pg, self.names.LC_BOUNDARY_POINT_T, load=True) delete_features(test_layer) self.assertEqual(test_layer.featureCount(), 0) def boundary_point_layer_resolve_domains_for_test(self, csv_layer): data_provider = csv_layer.dataProvider() data_provider.addAttributes([ QgsField('acuerdo', QVariant.Int), QgsField('puntotipo', QVariant.Int), QgsField('metodoproduccion', QVariant.Int) ]) csv_layer.updateFields() idx_agreement_field = data_provider.fieldNameIndex('acuerdo') idx_point_type_field = data_provider.fieldNameIndex('puntotipo') idx_production_method_field = data_provider.fieldNameIndex( 'metodoproduccion') with edit(csv_layer): for feature in csv_layer.getFeatures(): feature.setAttribute( idx_agreement_field, self.ladm_data.get_domain_code_from_value( self.db_pg, self.names.LC_AGREEMENT_TYPE_D, feature['_acuerdo'])) feature.setAttribute( idx_point_type_field, self.ladm_data.get_domain_code_from_value( self.db_pg, self.names.COL_POINT_TYPE_D, feature['_puntotipo'])) feature.setAttribute( idx_production_method_field, self.ladm_data.get_domain_code_from_value( self.db_pg, self.names.COL_PRODUCTION_METHOD_TYPE_D, feature['_metodoproduccion'])) csv_layer.updateFeature(feature) def upload_points_from_csv(self, csv_layer, schema): print("Copying CSV data with no elevation...") self.boundary_point_layer_resolve_domains_for_test(csv_layer) test_layer = self.app.core.get_layer(self.db_pg, self.names.LC_BOUNDARY_POINT_T, load=True) run_etl_model(self.names, csv_layer, test_layer, self.names.LC_BOUNDARY_POINT_T) self.assertEqual(test_layer.featureCount(), 51) self.validate_number_of_boundary_points_in_db(schema, 51) def test_upload_points_from_csv_crs_wgs84(self): print("\nINFO: Copying CSV data with EPSG:4326...") layer = self.app.core.get_layer(self.db_pg, self.names.LC_BOUNDARY_POINT_T, True) self.app.core.disable_automatic_fields(layer) csv_path = get_test_path('csv/puntos_crs_4326_wgs84_ladm_v1_1.csv') txt_delimiter = ';' cbo_longitude = 'x' cbo_latitude = 'y' crs = 'EPSG:4326' csv_layer = self.app.core.csv_to_layer(csv_path, txt_delimiter, cbo_longitude, cbo_latitude, crs, reproject=False) csv_layer = reproject_to_ctm12(csv_layer) self.upload_points_from_csv_crs_wgs84(csv_layer, SCHEMA_LADM_COL_EMPTY) self.validate_points_in_db_from_wgs84(SCHEMA_LADM_COL_EMPTY) test_layer = self.app.core.get_layer(self.db_pg, self.names.LC_BOUNDARY_POINT_T, load=True) delete_features(test_layer) self.assertEqual(test_layer.featureCount(), 0) def upload_points_from_csv_crs_wgs84(self, csv_layer, schema): print("Copying CSV data in WGS84...") self.boundary_point_layer_resolve_domains_for_test(csv_layer) test_layer = self.app.core.get_layer(self.db_pg, self.names.LC_BOUNDARY_POINT_T, load=True) run_etl_model(self.names, csv_layer, test_layer, self.names.LC_BOUNDARY_POINT_T) self.validate_number_of_boundary_points_in_db(schema, 3) def validate_points_in_db_from_wgs84(self, schema): print('\nINFO: Validating points in db from wgs84') cur = self.db_pg.conn.cursor(cursor_factory=psycopg2.extras.DictCursor) cur.execute( """SELECT st_x(geometria), st_y(geometria) FROM {}.{};""".format( schema, self.names.LC_BOUNDARY_POINT_T)) results = cur.fetchall() self.assertEqual(len(results), 3) self.assertEqual( [round(result, 3) for result in results[0]], [round(item_test, 3) for item_test in [4843984.711, 2143385.632]]) self.assertEqual( [round(result, 3) for result in results[1]], [round(item_test, 3) for item_test in [4843918.478, 2143442.584]]) self.assertEqual( [round(result, 3) for result in results[2]], [round(item_test, 3) for item_test in [4843979.173, 2143379.773]]) def test_copy_csv_with_z_to_db(self): print("\nINFO: Validating copy CSV points with Z to DB...") clean_table(SCHEMA_LADM_COL_EMPTY, self.names.LC_BOUNDARY_POINT_T) layer = self.app.core.get_layer(self.db_pg, self.names.LC_BOUNDARY_POINT_T, True) self.app.core.disable_automatic_fields(layer) csv_path = get_test_path('csv/puntos_fixed_ladm_v1_1.csv') txt_delimiter = ';' cbo_longitude = 'x' cbo_latitude = 'y' elevation = 'z' csv_layer = self.app.core.csv_to_layer(csv_path, txt_delimiter, cbo_longitude, cbo_latitude, "EPSG:9377", elevation, reproject=False) self.upload_points_from_csv_with_elevation(csv_layer, SCHEMA_LADM_COL_EMPTY) self.validate_points_in_db(SCHEMA_LADM_COL_EMPTY, with_z=True) test_layer = self.app.core.get_layer(self.db_pg, self.names.LC_BOUNDARY_POINT_T, load=True) delete_features(test_layer) self.assertEqual(test_layer.featureCount(), 0) def upload_points_from_csv_with_elevation(self, csv_layer, schema): print("\nINFO: Copying CSV data with elevation...") self.boundary_point_layer_resolve_domains_for_test(csv_layer) test_layer = self.app.core.get_layer(self.db_pg, self.names.LC_BOUNDARY_POINT_T, load=True) run_etl_model(self.names, csv_layer, test_layer, self.names.LC_BOUNDARY_POINT_T) self.assertEqual(test_layer.featureCount(), 51) self.validate_number_of_boundary_points_in_db(schema, 51) def validate_points_in_db(self, schema, with_z=False): cur = self.db_pg.conn.cursor(cursor_factory=psycopg2.extras.DictCursor) print( '\nValidating points {}(both spatial and alphanumeric attributes)'. format('with Z ' if with_z else '')) cur.execute("""SELECT * FROM {}.{};""".format( schema, self.names.LC_BOUNDARY_POINT_T)) results = cur.fetchall() colnames = { desc[0]: cur.description.index(desc) for desc in cur.description } self.assertEqual(len(results), 51) for row in results: if row[colnames['id_punto_lindero']] == '50': break self.assertEqual(row[colnames['id_punto_lindero']], '50') self.assertEqual(row[colnames['puntotipo']], 17) self.assertEqual(row[colnames['acuerdo']], 596) self.assertEqual(row[colnames['fotoidentificacion']], None) self.assertEqual(row[colnames['exactitud_horizontal']], 1.000) self.assertEqual(row[colnames['exactitud_vertical']], None) self.assertEqual(row[colnames['posicion_interpolacion']], None) self.assertEqual(row[colnames['metodoproduccion']], 1) self.assertEqual(row[colnames['espacio_de_nombres']], 'LC_PUNTOLINDERO') self.assertIsNotNone(row[colnames['local_id']]) self.assertIsNone(row[colnames['ue_lc_servidumbretransito']]) self.assertIsNone(row[colnames['ue_lc_construccion']]) self.assertIsNone(row[colnames['ue_lc_terreno']]) self.assertIsNone(row[colnames['ue_lc_unidadconstruccion']]) self.assertIsNone(row[colnames['fin_vida_util_version']]) geom = '01010000A0A1240000EC51B836A57A5241CDCCCC7C8D5A40410000000000000000' if with_z: geom = '01010000A0A1240000EC51B836A57A5241CDCCCC7C8D5A404123DBF97EEA2E9640' self.assertEqual(row[colnames['geometria']], geom) def test_copy_csv_overlapping_to_db(self): print('\nINFO: Validating copy csv overlapping to db') clean_table(SCHEMA_LADM_COL_EMPTY, self.names.LC_BOUNDARY_POINT_T) csv_path = get_test_path('csv/puntos_overlapping_ladm_v1_1.csv') txt_delimiter = ';' cbo_longitude = 'x' cbo_latitude = 'y' csv_layer = self.app.core.csv_to_layer(csv_path, txt_delimiter, cbo_longitude, cbo_latitude, "EPSG:9377", reproject=False) self.upload_points_from_csv_overlapping(csv_layer, SCHEMA_LADM_COL_EMPTY) self.validate_number_of_boundary_points_in_db(SCHEMA_LADM_COL_EMPTY, 0) test_layer = self.app.core.get_layer(self.db_pg, self.names.LC_BOUNDARY_POINT_T, load=True) delete_features(test_layer) self.assertEqual(test_layer.featureCount(), 0) def upload_points_from_csv_overlapping(self, csv_layer, schema): print('Uploading points from csv overlapping...') overlapping = self.geometry.get_overlapping_points(csv_layer) if not overlapping: self.boundary_point_layer_resolve_domains_for_test(csv_layer) test_layer = self.app.core.get_layer( self.db_pg, self.names.LC_BOUNDARY_POINT_T, load=True) run_etl_model(self.names, csv_layer, test_layer, self.names.LC_BOUNDARY_POINT_T) self.validate_number_of_boundary_points_in_db(schema, 0) def validate_number_of_boundary_points_in_db(self, schema, num=0): print( '\nINFO: Validating number of boundary points in schema {}'.format( schema)) cur = self.db_pg.conn.cursor(cursor_factory=psycopg2.extras.DictCursor) cur.execute("""SELECT count(t_id) FROM {}.{};""".format( schema, self.names.LC_BOUNDARY_POINT_T)) result = cur.fetchone() self.assertEqual(result[0], num) def tearDown(self): print("INFO: Closing open connections to databases") self.db_pg.conn.close() @classmethod def tearDownClass(cls): pass
class QGISLADMQuery: def __init__(self): self.app = AppInterface() self.ladm_data = LADMData() def get_igac_property_record_card_info(self, db, **kwargs): return self._execute_ladm_query( db, EnumLADMQueryType.IGAC_PROPERTY_RECORD_CARD_INFO, kwargs) def get_igac_economic_info(self, db, **kwargs): return self._execute_ladm_query(db, EnumLADMQueryType.IGAC_ECONOMIC_INFO, kwargs) def get_igac_physical_info(self, db, **kwargs): return self._execute_ladm_query(db, EnumLADMQueryType.IGAC_PHYSICAL_INFO, kwargs) def get_igac_legal_info(self, db, **kwargs): return self._execute_ladm_query(db, EnumLADMQueryType.IGAC_LEGAL_INFO, kwargs) def get_igac_basic_info(self, db, **kwargs): return self._execute_ladm_query(db, EnumLADMQueryType.IGAC_BASIC_INFO, kwargs) def _execute_ladm_query(self, db, query_type, kwargs): params = QGISLADMQuery._get_parameters(kwargs) filter_field_values = self._get_plot_ids_from_params(db, params) response = dict() query = dict() ladm_units = db.get_ladm_units() if EnumLADMQueryType.IGAC_BASIC_INFO == query_type: query = get_igac_basic_query(db.names, ladm_units) elif EnumLADMQueryType.IGAC_PHYSICAL_INFO == query_type: query = get_igac_physical_query(db.names, ladm_units) elif EnumLADMQueryType.IGAC_LEGAL_INFO == query_type: query = get_igac_legal_query(db.names, ladm_units) elif EnumLADMQueryType.IGAC_ECONOMIC_INFO == query_type: query = get_igac_economic_query(db.names, ladm_units) elif EnumLADMQueryType.IGAC_PROPERTY_RECORD_CARD_INFO == query_type: query = get_igac_property_record_card_query(db.names, ladm_units) self._execute_query(db, response, query[QueryNames.LEVEL_TABLE], filter_field_values) return response def _get_plot_ids_from_params(self, db, params): """ Get plot ids depending on a defined filter in params SEARCH_KEY_PARCEL_FMI: Get plots id associated with parcel filter by parcel FMI SEARCH_KEY_PARCEL_NUMBER: Get plots id associated with parcel filter by parcel number SEARCH_KEY_PREVIOUS_PARCEL_NUMBER: Get plots id associated with parcel filter by previous parcel number """ plot_ids = list() if params[QueryNames.SEARCH_KEY_PLOT_T_IDS] != 'NULL': plot_ids = params[QueryNames.SEARCH_KEY_PLOT_T_IDS] if params[QueryNames.SEARCH_KEY_PARCEL_FMI] != 'NULL' or params[ QueryNames.SEARCH_KEY_PARCEL_NUMBER] != 'NULL' or params[ QueryNames.SEARCH_KEY_PREVIOUS_PARCEL_NUMBER] != 'NULL': layers = { db.names.LC_PARCEL_T: None, db.names.COL_UE_BAUNIT_T: None } self.app.core.get_layers(db, layers, False) if layers: parcel_layer = layers[db.names.LC_PARCEL_T] ue_baunit_layer = layers[db.names.COL_UE_BAUNIT_T] if params[QueryNames.SEARCH_KEY_PARCEL_FMI] != 'NULL': expr = QgsExpression("{} like '{}'".format( db.names.LC_PARCEL_T_FMI_F, params[QueryNames.SEARCH_KEY_PARCEL_FMI])) plot_ids.extend( self._filter_plots_ids_from_expresion( db, parcel_layer, ue_baunit_layer, expr)) if params[QueryNames.SEARCH_KEY_PARCEL_NUMBER] != 'NULL': expr = QgsExpression("{} like '{}'".format( db.names.LC_PARCEL_T_PARCEL_NUMBER_F, params[QueryNames.SEARCH_KEY_PARCEL_NUMBER])) plot_ids.extend( self._filter_plots_ids_from_expresion( db, parcel_layer, ue_baunit_layer, expr)) if params[QueryNames. SEARCH_KEY_PREVIOUS_PARCEL_NUMBER] != 'NULL': expr = QgsExpression("{} like '{}'".format( db.names.LC_PARCEL_T_PREVIOUS_PARCEL_NUMBER_F, params[QueryNames.SEARCH_KEY_PREVIOUS_PARCEL_NUMBER])) plot_ids.extend( self._filter_plots_ids_from_expresion( db, parcel_layer, ue_baunit_layer, expr)) return plot_ids @staticmethod def _filter_plots_ids_from_expresion(db, parcel_layer, ue_baunit_layer, expression_select_parcels): """ Get plots ids depending of a defined filter expression """ # Only required field in parcel layer fields_idx = list() for field in [ db.names.T_ID_F, db.names.LC_PARCEL_T_FMI_F, db.names.LC_PARCEL_T_PARCEL_NUMBER_F, db.names.LC_PARCEL_T_PREVIOUS_PARCEL_NUMBER_F ]: fields_idx.append(parcel_layer.fields().indexFromName(field)) request = QgsFeatureRequest(expression_select_parcels) request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes(fields_idx) # Note: this adds a new flag parcels = parcel_layer.getFeatures(request) parcel_ids = [ select_parcel[db.names.T_ID_F] for select_parcel in parcels ] # Only required field in ue baunit layer field_idx = parcel_layer.fields().indexFromName( db.names.COL_UE_BAUNIT_T_LC_PLOT_F) expression_select_plots = QgsExpression( '{} in ({}) AND {} IS NOT NULL'.format( db.names.COL_UE_BAUNIT_T_PARCEL_F, ','.join([str(parcel_id) for parcel_id in parcel_ids]), db.names.COL_UE_BAUNIT_T_LC_PLOT_F)) request = QgsFeatureRequest(expression_select_plots) request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes([field_idx ]) # Note: this adds a new flag plots = ue_baunit_layer.getFeatures(request) return [plot[db.names.COL_UE_BAUNIT_T_LC_PLOT_F] for plot in plots] # Plot ids def _execute_query(self, db, response, level_dict, filter_field_values): """ Recursive function that allows solving the queries defined using the LADM Query Objects. Recursion ends when the last nesting level is reached. :param db: database connection instance :param response: object that is recursively built with the response. :param level_dict: nesting level dictionary to solve :param filter_field_values: list of filter field values :return dictionary with the query result """ table_name = level_dict[QueryNames.LEVEL_TABLE_NAME] level_alias = level_dict[QueryNames.LEVEL_TABLE_ALIAS] layer = self.app.core.get_layer(db, table_name, False) filter_sub_level = level_dict[QueryNames.FILTER_SUB_LEVEL] t_id_features = self._get_features_ids_sub_level( db, filter_sub_level, filter_field_values) response[level_alias] = list() dict_fields_and_alias = dict() for required_table_field in level_dict[QueryNames.TABLE_FIELDS]: if isinstance(required_table_field, OwnField): dict_fields_and_alias[ required_table_field. field_name] = required_table_field.field_alias field_names = list(dict_fields_and_alias.keys()) features = self._get_features(layer, db.names.T_ID_F, field_names, t_id_features) for feature in features: node_response = dict() node_response[QueryNames.ID_FEATURE_RESPONSE] = feature[ db.names.T_ID_F] node_fields_response = dict() for field in level_dict[QueryNames.TABLE_FIELDS]: if isinstance(field, DomainOwnField): domain_table = field.domain_table domain_code = feature[field.field_name] domain_value = self.ladm_data.get_domain_value_from_code( db, domain_table, domain_code, False) node_fields_response[field.field_alias] = domain_value elif isinstance(field, OwnField): node_fields_response[field.field_alias] = feature[ field.field_name] if feature[ field.field_name] != NULL else None elif isinstance(field, EvalExpressionOwnField): node_fields_response[ field.field_alias] = self._get_eval_expr_value( layer, feature, field.expression) elif isinstance(field, AbsRelatedFields): if isinstance(field, RelatedRemoteFieldObject): node_fields_response[ field. field_alias] = self._get_relate_remote_field_object( db, field, [feature[db.names.T_ID_F]]) elif isinstance(field, RelatedRemoteFieldValue): node_fields_response[ field. field_alias] = self._get_relate_remote_field_value( db, field, [feature[db.names.T_ID_F]]) elif isinstance(field, RelatedOwnFieldObject): node_fields_response[ field. field_alias] = self._get_relate_own_field_object( db, field, [feature[db.names.T_ID_F]]) elif isinstance(field, RelatedOwnFieldValue): node_fields_response[ field. field_alias] = self._get_relate_own_field_value( db, field, [feature[db.names.T_ID_F]]) for dict_key in level_dict: if dict_key.endswith(QueryNames.LEVEL_TABLE): self._execute_query(db, node_fields_response, level_dict[dict_key], [feature[db.names.T_ID_F]]) node_response[ QueryNames.ATTRIBUTES_RESPONSE] = node_fields_response response[level_alias].append(node_response) def _get_relate_remote_field_object(self, db, field, filter_field_values): t_id_features = self._get_relate_own_field_object( db, field.filter_sub_level, filter_field_values) return self._get_relate_own_field_value(db, field, t_id_features) def _get_relate_remote_field_value(self, db, field, filter_field_values): t_id_features = self._get_features_ids_sub_level( db, field.filter_sub_level, filter_field_values) return self._get_relate_own_field_value(db, field, t_id_features) def _get_relate_own_field_object(self, db, field, filter_field_values): """ Get relate own field object :param db: database connection instance :param field: AbsRelatedFields :param filter_field_values: list of field values used to apply the filter return list of dict with required fields """ referenced_layer = self.app.core.get_layer(db, field.referenced_layer, False) dict_fields_and_alias = self._get_dict_fields_and_alias( field.required_fields_referenced_layer) field_names = list(dict_fields_and_alias.keys()) field_names.append(db.names.T_ID_F) features = self._get_features(referenced_layer, field.referenced_field, field_names, filter_field_values) list_result = list() for feature in features: dict_referenced_field = dict() dict_referenced_field[QueryNames.ID_FEATURE_RESPONSE] = feature[ db.names.T_ID_F] dict_attributes = dict() for field_relation in field.required_fields_referenced_layer: if isinstance(field_relation, DomainOwnField): domain_table = field_relation.domain_table domain_code = feature[field_relation.field_name] domain_value = self.ladm_data.get_domain_value_from_code( db, domain_table, domain_code, False) dict_attributes[field_relation.field_alias] = domain_value elif isinstance(field_relation, OwnField): dict_attributes[field_relation.field_alias] = feature[ field_relation.field_name] if feature[ field_relation.field_name] != NULL else None elif isinstance(field_relation, EvalExpressionOwnField): dict_attributes[field_relation. field_alias] = self._get_eval_expr_value( referenced_layer, feature, field_relation.expression) dict_referenced_field[ QueryNames.ATTRIBUTES_RESPONSE] = dict_attributes list_result.append(dict_referenced_field) return list_result def _get_relate_own_field_value(self, db, field, filter_field_values): """ Get relate own field value. :param db: database connection instance :param field: AbsRelatedFields :param filter_field_values: list of field values used to apply the filter :return required field value """ referenced_layer = self.app.core.get_layer(db, field.referenced_layer, False) required_field_referenced_layer = field.required_field_referenced_layer dict_fields_and_alias = self._get_dict_fields_and_alias( [required_field_referenced_layer]) field_names = list(dict_fields_and_alias.keys()) field_names.append(db.names.T_ID_F) features = self._get_features(referenced_layer, field.referenced_field, field_names, filter_field_values) field_value = None for feature in features: if isinstance(required_field_referenced_layer, DomainOwnField): domain_table = required_field_referenced_layer.domain_table domain_code = feature[ required_field_referenced_layer.field_name] domain_value = self.ladm_data.get_domain_value_from_code( db, domain_table, domain_code, False) field_value = domain_value elif isinstance(required_field_referenced_layer, OwnField): field_value = feature[ required_field_referenced_layer. field_name] if feature[required_field_referenced_layer. field_name] != NULL else None elif isinstance(required_field_referenced_layer, EvalExpressionOwnField): field_value = self._get_eval_expr_value( referenced_layer, feature, required_field_referenced_layer.expression) return field_value def _get_features_ids_by_filter(self, db, filter_sub_level, filter_field_values): """ Get feature ids using filter. :param db: database connection instance :param filter_sub_level: LADM Query filter :param filter_field_values: it is a list with only one item return list feature ids filters """ referenced_layer = filter_sub_level.referenced_layer required_field_referenced_layer = filter_sub_level.required_field_referenced_layer sub_level_layer = self.app.core.get_layer(db, referenced_layer, False) if isinstance(filter_sub_level, FilterSubLevel): referenced_field = filter_sub_level.referenced_field expression = QgsExpression("{} in ({}) and {} is not null".format( referenced_field, ', '.join( str(filter_field_value) for filter_field_value in filter_field_values), required_field_referenced_layer)) request = QgsFeatureRequest(expression) field_idx = sub_level_layer.fields().indexFromName( required_field_referenced_layer) request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes([field_idx ]) # Note: this adds a new flag feature_ids = [ feature[required_field_referenced_layer] for feature in sub_level_layer.getFeatures(request) ] return feature_ids elif isinstance(filter_sub_level, SpatialFilterSubLevel): referencing_layer = filter_sub_level.referencing_layer spatial_operation = filter_sub_level.spatial_operation level_layer = self.app.core.get_layer(db, referencing_layer, False) filter_level_layer = processing.run( "native:extractbyattribute", { 'INPUT': level_layer, 'FIELD': db.names.T_ID_F, 'OPERATOR': 0, 'VALUE': filter_field_values[0], 'OUTPUT': 'memory:' })['OUTPUT'] parameters = { 'INPUT': sub_level_layer, 'INTERSECT': filter_level_layer, 'OUTPUT': 'memory:' } if spatial_operation == EnumSpatialOperationType.INTERSECTS: parameters['PREDICATE'] = [0] # Intersects elif spatial_operation == EnumSpatialOperationType.OVERLAPS: parameters['PREDICATE'] = [5] # Overlaps elif spatial_operation == EnumSpatialOperationType.CONTAINS: parameters['PREDICATE'] = [1] # Contains filter_sub_level_layer = processing.run("native:extractbylocation", parameters)['OUTPUT'] feature_ids = [ feature[required_field_referenced_layer] for feature in filter_sub_level_layer.getFeatures() ] return feature_ids def _get_features_ids_sub_level(self, db, filter_sub_level, filter_field_values): """ Get feature t_id values associated to sub level filter. This method is recursive and its recursion ends when all the filters it has nested are resolved. :param db: database connection instance :param filter_sub_level: custom LADM Query Filter :param filter_field_values: list of field values to be filtered return list of t_ids """ t_id_features = list() for filter_field_value in filter_field_values: t_id_features.extend( self._get_features_ids_by_filter(db, filter_sub_level, [filter_field_value])) sub_filter_sub_level = filter_sub_level.filter_sub_level # Recursivity to get features t_ids associate to the first filter if sub_filter_sub_level: return self._get_features_ids_sub_level(db, sub_filter_sub_level, t_id_features) else: return t_id_features @staticmethod def _get_eval_expr_value(layer, feature, expression): eval_feature = layer.getFeature( feature.id() ) # this is necessary because the feature is filtered and may not have all the necessary fields context = QgsExpressionContext() scope = QgsExpressionContextScope() scope.setFeature(eval_feature) context.appendScope(scope) expression.prepare(context) return expression.evaluate(context) @staticmethod def _get_dict_fields_and_alias(table_fields): dict_fields_and_alias = dict() for required_table_field in table_fields: if isinstance(required_table_field, OwnField): dict_fields_and_alias[ required_table_field. field_name] = required_table_field.field_alias return dict_fields_and_alias @staticmethod def _get_features(layer, referenced_field, field_names, t_id_features): if not t_id_features: return list() fields_idx = [ layer.fields().indexFromName(field) for field in field_names ] expression = QgsExpression('{} in ({})'.format( referenced_field, ', '.join(str(t_id_feature) for t_id_feature in t_id_features))) request = QgsFeatureRequest(expression) request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes(fields_idx) # Note: this adds a new flag features = [feature for feature in layer.getFeatures(request)] return features @staticmethod def _get_parameters(kwargs): params = { QueryNames.SEARCH_KEY_PLOT_T_IDS: 'NULL', QueryNames.SEARCH_KEY_PARCEL_FMI: 'NULL', QueryNames.SEARCH_KEY_PARCEL_NUMBER: 'NULL', QueryNames.SEARCH_KEY_PREVIOUS_PARCEL_NUMBER: 'NULL' } params.update(kwargs) return params @staticmethod def get_duplicate_records_in_table(db, table_name, fields_to_check): raise NotImplementedError @staticmethod def get_group_party_fractions_that_do_not_make_one(db): raise NotImplementedError @staticmethod def get_invalid_col_party_type_natural(db): raise NotImplementedError @staticmethod def get_invalid_col_party_type_no_natural(db): raise NotImplementedError @staticmethod def get_parcels_with_invalid_department_code(db): raise NotImplementedError @staticmethod def get_parcels_with_invalid_municipality_code(db): raise NotImplementedError @staticmethod def get_parcels_with_invalid_parcel_number(db): raise NotImplementedError @staticmethod def get_parcels_with_invalid_parcel_type_and_22_position_number(db): raise NotImplementedError @staticmethod def get_parcels_with_invalid_previous_parcel_number(db): raise NotImplementedError @staticmethod def get_parcels_with_no_right(db): raise NotImplementedError @staticmethod def get_parcels_with_repeated_domain_right(db): raise NotImplementedError @staticmethod def get_uebaunit_parcel(db): raise NotImplementedError
def finish_feature_creation(self, layerId, features): if len(features) != 1: # TODO send this info to controller # message = QCoreApplication.translate("WizardTranslations", "'{}' tool has been closed. We should have got only one {} by we have {}").format(self.WIZARD_TOOL_NAME, self.WIZARD_FEATURE_NAME, len(features)) # self.logger.warning(__name__, "We should have got only one {}, but we have {}".format(self.WIZARD_FEATURE_NAME, len(features))) return ParcelFinishFeatureCreationArgs( added_features_amount=len(features)) if not self.is_each_layer_valid(): return ParcelFinishFeatureCreationArgs(valid_constraints=False) feature = features[0] if not feature.isValid(): # TODO send this info to controller # self.logger.warning(__name__, "Feature not found in layer Spatial Source...") return ParcelFinishFeatureCreationArgs(is_valid=False) # TODO What is the difference? # feature_tid = feature[self.__db.names.T_ID_F] feature_tid = self.__editing_layer.getFeature( feature.id())[self.__db.names.T_ID_F] plot_ids = list() building_ids = list() building_unit_ids = list() # Apply restriction to the selection # add plot associated if self.__db.names.LC_PLOT_T in self.__constraint_types_of_parcels[ self.parcel_type_ili_code]: add_features = self.__constraint_types_of_parcels[ self.parcel_type_ili_code][ self.__db.names.LC_PLOT_T] is not None else: add_features = True if add_features: plot_ids = LADMData.get_list_of_features_ids( self.__layers[self.__db.names.LC_PLOT_T], self.__db.names.T_ID_F) new_features = LADMData.save_relations( self.__layers[self.__db.names.COL_UE_BAUNIT_T], self.__db.names.COL_UE_BAUNIT_T_LC_PLOT_F, plot_ids, self.__db.names.COL_UE_BAUNIT_T_PARCEL_F, feature_tid) # add building associated if self.__db.names.LC_BUILDING_T in self.__constraint_types_of_parcels[ self.parcel_type_ili_code]: add_features = self.__constraint_types_of_parcels[ self.parcel_type_ili_code][ self.__db.names.LC_BUILDING_T] is not None else: add_features = True if add_features: building_ids = LADMData.get_list_of_features_ids( self.__layers[self.__db.names.LC_BUILDING_T], self.__db.names.T_ID_F) new_features = LADMData.save_relations( self.__layers[self.__db.names.COL_UE_BAUNIT_T], self.__db.names.COL_UE_BAUNIT_T_LC_BUILDING_F, building_ids, self.__db.names.COL_UE_BAUNIT_T_PARCEL_F, feature_tid) # add building unit associated if self.__db.names.LC_BUILDING_UNIT_T in self.__constraint_types_of_parcels[ self.parcel_type_ili_code]: add_features = self.__constraint_types_of_parcels[ self.parcel_type_ili_code][ self.__db.names.LC_BUILDING_UNIT_T] is not None else: add_features = True if add_features: building_unit_ids = LADMData.get_list_of_features_ids( self.__layers[self.__db.names.LC_BUILDING_UNIT_T], self.__db.names.T_ID_F) new_features = LADMData.save_relations( self.__layers[self.__db.names.COL_UE_BAUNIT_T], self.__db.names.COL_UE_BAUNIT_T_LC_BUILDING_UNIT_F, building_unit_ids, self.__db.names.COL_UE_BAUNIT_T_PARCEL_F, feature_tid) return ParcelFinishFeatureCreationArgs(True, feature_tid, 1, None)
def _validate(self, db, db_qr, layer_dict, tolerance, **kwargs): self.progress_changed.emit(5) ladm_queries = self._get_ladm_queries(db.engine) pre_res, pre_obj = self._check_prerrequisite_layers(layer_dict) if not pre_res: return pre_obj error_state = None res, records = ladm_queries.get_invalid_col_party_type_natural(db) self.progress_changed.emit(40) if res: error_state = LADMData().get_domain_code_from_value( db_qr, db_qr.names.ERR_ERROR_STATE_D, LADMNames.ERR_ERROR_STATE_D_ERROR_V) errors_rules = { self._ERROR_01: { 'geometries': list(), 'data': list() }, self._ERROR_02: { 'geometries': list(), 'data': list() }, self._ERROR_03: { 'geometries': list(), 'data': list() }, self._ERROR_04: { 'geometries': list(), 'data': list() }, self._ERROR_05: { 'geometries': list(), 'data': list() }, self._ERROR_06: { 'geometries': list(), 'data': list() }, self._ERROR_07: { 'geometries': list(), 'data': list() }, self._ERROR_08: { 'geometries': list(), 'data': list() }, self._ERROR_09: { 'geometries': list(), 'data': list() }, self._ERROR_10: { 'geometries': list(), 'data': list() }, self._ERROR_11: { 'geometries': list(), 'data': list() }, self._ERROR_12: { 'geometries': list(), 'data': list() }, self._ERROR_13: { 'geometries': list(), 'data': list() } } progress = 40 record_count = 0 for record in records: record_count += 1 if record[db.names.LC_PARTY_T_BUSINESS_NAME_F] > 0: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [record[db.names.T_ILI_TID_F]], None, None, self._errors[self._ERROR_01], error_state ] errors_rules[self._ERROR_01]['data'].append(error_data) if record[db.names.LC_PARTY_T_SURNAME_1_F] > 0: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [record[db.names.T_ILI_TID_F]], None, None, self._errors[self._ERROR_02], error_state ] errors_rules[self._ERROR_02]['data'].append(error_data) if record[db.names.LC_PARTY_T_FIRST_NAME_1_F] > 0: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [record[db.names.T_ILI_TID_F]], None, None, self._errors[self._ERROR_03], error_state ] errors_rules[self._ERROR_03]['data'].append(error_data) if record[db.names.LC_PARTY_T_DOCUMENT_TYPE_F] > 0: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [record[db.names.T_ILI_TID_F]], None, None, self._errors[self._ERROR_04], error_state ] errors_rules[self._ERROR_04]['data'].append(error_data) if record[db.names.LC_PARTY_T_GENRE_F] > 0: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [record[db.names.T_ILI_TID_F]], None, None, self._errors[self._ERROR_05], error_state ] errors_rules[self._ERROR_05]['data'].append(error_data) if record[db.names.LC_PARTY_T_SURNAME_1_F + '_' + SPECIAL_CHARACTERS] > 0: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [record[db.names.T_ILI_TID_F]], None, None, self._errors[self._ERROR_06], error_state ] errors_rules[self._ERROR_06]['data'].append(error_data) if record[db.names.LC_PARTY_T_SURNAME_1_F + '_' + DIGITS] > 0: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [record[db.names.T_ILI_TID_F]], None, None, self._errors[self._ERROR_07], error_state ] errors_rules[self._ERROR_07]['data'].append(error_data) if record[db.names.LC_PARTY_T_FIRST_NAME_1_F + '_' + SPECIAL_CHARACTERS] > 0: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [record[db.names.T_ILI_TID_F]], None, None, self._errors[self._ERROR_08], error_state ] errors_rules[self._ERROR_08]['data'].append(error_data) if record[db.names.LC_PARTY_T_FIRST_NAME_1_F + '_' + DIGITS] > 0: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [record[db.names.T_ILI_TID_F]], None, None, self._errors[self._ERROR_09], error_state ] errors_rules[self._ERROR_09]['data'].append(error_data) if record[db.names.LC_PARTY_T_SURNAME_2_F + '_' + SPECIAL_CHARACTERS] > 0: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [record[db.names.T_ILI_TID_F]], None, None, self._errors[self._ERROR_10], error_state ] errors_rules[self._ERROR_10]['data'].append(error_data) if record[db.names.LC_PARTY_T_SURNAME_2_F + '_' + DIGITS] > 0: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [record[db.names.T_ILI_TID_F]], None, None, self._errors[self._ERROR_11], error_state ] errors_rules[self._ERROR_11]['data'].append(error_data) if record[db.names.LC_PARTY_T_FIRST_NAME_2_F + '_' + SPECIAL_CHARACTERS] > 0: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [record[db.names.T_ILI_TID_F]], None, None, self._errors[self._ERROR_12], error_state ] errors_rules[self._ERROR_12]['data'].append(error_data) if record[db.names.LC_PARTY_T_FIRST_NAME_2_F + '_' + DIGITS] > 0: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [record[db.names.T_ILI_TID_F]], None, None, self._errors[self._ERROR_13], error_state ] errors_rules[self._ERROR_13]['data'].append(error_data) delta_progress = record_count * 50 / len(records) self.progress_changed.emit(progress + delta_progress) count = 0 for error_key, errors_rule in errors_rules.items(): if errors_rule: self._save_errors(db_qr, error_key, errors_rule) count += len(errors_rule['data']) self.progress_changed.emit(90) if count > 0: res_type = EnumQualityRuleResult.ERRORS msg = QCoreApplication.translate( "QualityRules", "{} natural parties with inconsistent were found.").format( count) else: res_type = EnumQualityRuleResult.SUCCESS msg = QCoreApplication.translate( "QualityRules", "All natural parties have valid data.") self.progress_changed.emit(100) return QualityRuleExecutionResult(res_type, msg, count)
def _validate(self, db, db_qr, layer_dict, tolerance, **kwargs): self.progress_changed.emit(5) pre_res, pre_obj = self._check_prerrequisite_layers(layer_dict) if not pre_res: return pre_obj boundary_point_layer = self._get_layer(layer_dict, db.names.LC_BOUNDARY_POINT_T) boundary_layer = self._get_layer(layer_dict, db.names.LC_BOUNDARY_T) point_bfs_layer = self._get_layer(layer_dict, db.names.POINT_BFS_T) id_field = db.names.T_ID_F dict_uuid_boundary = { f[id_field]: f[db.names.T_ILI_TID_F] for f in boundary_layer.getFeatures() } dict_uuid_boundary_point = { f[id_field]: f[db.names.T_ILI_TID_F] for f in boundary_point_layer.getFeatures() } # create dict with layer data id_field_idx = boundary_point_layer.fields().indexFromName(id_field) request = QgsFeatureRequest().setSubsetOfAttributes([id_field_idx]) dict_boundary_point = { feature[id_field]: feature for feature in boundary_point_layer.getFeatures(request) } result = GeometryUtils.get_boundary_points_not_covered_by_boundary_nodes( db, boundary_point_layer, boundary_layer, point_bfs_layer, id_field) boundary_point_without_boundary_node = result[0] no_register_point_bfs = result[1] duplicate_in_point_bfs = result[2] self.progress_changed.emit(70) error_state = LADMData().get_domain_code_from_value( db_qr, db_qr.names.ERR_ERROR_STATE_D, LADMNames.ERR_ERROR_STATE_D_ERROR_V) errors_e01 = {'geometries': list(), 'data': list()} errors_e02 = {'geometries': list(), 'data': list()} errors_e03 = {'geometries': list(), 'data': list()} # boundary point without boundary node if boundary_point_without_boundary_node: for item in boundary_point_without_boundary_node: boundary_point_id = item # boundary_point_id errors_e01['geometries'].append( dict_boundary_point[boundary_point_id].geometry()) error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [dict_uuid_boundary_point.get(boundary_point_id)], None, None, self._errors[self._ERROR_01], error_state ] errors_e01['data'].append(error_data) self._save_errors(db_qr, self._ERROR_01, errors_e01) # No registered in point_bfs if no_register_point_bfs: for error_no_register in set(no_register_point_bfs): boundary_point_id = error_no_register[0] # boundary_point_id boundary_id = error_no_register[1] # boundary_id errors_e02['geometries'].append( dict_boundary_point[boundary_point_id].geometry()) error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [dict_uuid_boundary_point.get(boundary_point_id)], [dict_uuid_boundary.get(boundary_id)], None, self._errors[self._ERROR_02], error_state ] errors_e02['data'].append(error_data) self._save_errors(db_qr, self._ERROR_02, errors_e02) # Duplicate in point_bfs if duplicate_in_point_bfs: for error_duplicate in set(duplicate_in_point_bfs): boundary_point_id = error_duplicate[0] # boundary_point_id boundary_id = error_duplicate[1] # boundary_id errors_e03['geometries'].append( dict_boundary_point[boundary_point_id].geometry()) error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [dict_uuid_boundary_point.get(boundary_point_id)], [dict_uuid_boundary.get(boundary_id)], None, self._errors[self._ERROR_03], error_state ] errors_e03['data'].append(error_data) self._save_errors(db_qr, self._ERROR_03, errors_e03) self.progress_changed.emit(100) count = len(errors_e01['data']) + len(errors_e02['data']) + len( errors_e03['data']) if count > 0: res_type = EnumQualityRuleResult.ERRORS msg = QCoreApplication.translate( "QualityRules", "{} boundary points not covered by boundary nodes were found." ).format(count) else: res_type = EnumQualityRuleResult.SUCCESS msg = QCoreApplication.translate( "QualityRules", "All boundary points are covered by boundary nodes!") self.progress_changed.emit(100) return QualityRuleExecutionResult(res_type, msg, count)
def _validate(self, db, db_qr, layer_dict, tolerance, **kwargs): self.progress_changed.emit(5) ladm_queries = self._get_ladm_queries(db.engine) pre_res, pre_obj = self._check_prerrequisite_layers(layer_dict) if not pre_res: return pre_obj error_state = None # First error type: parcel with no rights res, records = ladm_queries.get_parcels_with_no_right(db) count_e01_records = len(records) self.progress_changed.emit(40) if res: error_state = LADMData().get_domain_code_from_value(db_qr, db_qr.names.ERR_ERROR_STATE_D, LADMNames.ERR_ERROR_STATE_D_ERROR_V) errors = {'geometries': list(), 'data': list()} for record in records: error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [record[db.names.T_ILI_TID_F]], None, None, None, error_state] errors['data'].append(error_data) self._save_errors(db_qr, self._ERROR_01, errors) self.progress_changed.emit(50) # Second error type: parcel with more than one domain right res, records = ladm_queries.get_parcels_with_repeated_domain_right(db) count_e02_records = len(records) self.progress_changed.emit(85) if res: # Reuse it if present, otherwise get it error_state = error_state if error_state is not None else LADMData().get_domain_code_from_value(db_qr, db_qr.names.ERR_ERROR_STATE_D, LADMNames.ERR_ERROR_STATE_D_ERROR_V) errors = {'geometries': list(), 'data': list()} for record in records: related_objects = record['dominios'].split(";") error_data = [ # [obj_uuids, rel_obj_uuids, values, details, state] [record[db.names.T_ILI_TID_F]], related_objects, len(related_objects), None, error_state] errors['data'].append(error_data) self._save_errors(db_qr, self._ERROR_02, errors) self.progress_changed.emit(95) count = count_e01_records + count_e02_records if count > 0: res_type = EnumQualityRuleResult.ERRORS msg = QCoreApplication.translate("QualityRules", "{} parcels with inconsistent rights were found.").format( count) else: res_type = EnumQualityRuleResult.SUCCESS msg = QCoreApplication.translate("QualityRules", "All parcels have valid right relationships.") self.progress_changed.emit(100) return QualityRuleExecutionResult(res_type, msg, count)
def __init__(self): self.app = AppInterface() self.ladm_data = LADMData()