From 75739158ced5c79b97ff0c84004e7ef1de566927 Mon Sep 17 00:00:00 2001 From: Jean-Pascal MILCENT Date: Fri, 5 Nov 2021 14:40:25 +0100 Subject: [PATCH] Fix: remove all references to old status and red lists Also, remove dead code. Use TaxHub dependency for "taxonomie" schema models. Resolve #1492. --- backend/geonature/core/gn_synthese/routes.py | 103 ----- .../geonature/core/gn_synthese/utils/query.py | 262 ------------ .../gn_synthese/utils/query_select_sqla.py | 14 +- backend/geonature/core/taxonomie/models.py | 141 ------ backend/geonature/core/taxonomie/schemas.py | 3 +- .../backend/gn_module_validation/query.py | 116 ----- contrib/occtax/backend/occtax/models.py | 2 +- .../GN2CommonModule/form/data-form.service.ts | 4 - .../synthese-advanced-form-store.service.ts | 7 +- .../synthese-advanced-form.component.html | 12 - .../synthese-info-obs.component.html | 10 - .../syntheseModule/services/form.service.ts | 122 ------ .../syntheseModule/services/store.service.ts | 7 - .../modal-info-obs.component.html | 401 ------------------ 14 files changed, 5 insertions(+), 1199 deletions(-) delete mode 100644 backend/geonature/core/gn_synthese/utils/query.py delete mode 100644 backend/geonature/core/taxonomie/models.py delete mode 100644 contrib/gn_module_validation/backend/gn_module_validation/query.py delete mode 100644 frontend/src/app/syntheseModule/services/form.service.ts delete mode 100644 frontend/src/app/syntheseModule/services/store.service.ts delete mode 100644 frontend/src/app/syntheseModule/synthese-results/synthese-list/synthese-info-obs/modal-info-obs.component.html diff --git a/backend/geonature/core/gn_synthese/routes.py b/backend/geonature/core/gn_synthese/routes.py index 238dd75712..6fd00bff37 100644 --- a/backend/geonature/core/gn_synthese/routes.py +++ b/backend/geonature/core/gn_synthese/routes.py @@ -34,16 +34,11 @@ VColorAreaTaxon, ) from geonature.core.gn_synthese.synthese_config import MANDATORY_COLUMNS -from geonature.core.taxonomie.models import ( - TaxrefProtectionArticles, - TaxrefProtectionEspeces, -) from geonature.core.ref_geo.models import ( CorAreaStatus, BibAreasTypes, LAreas, ) -from geonature.core.gn_synthese.utils import query as synthese_query from geonature.core.gn_synthese.utils.query_select_sqla import SyntheseQuery from geonature.core.gn_permissions import decorators as permissions @@ -197,53 +192,6 @@ def get_observations_for_web(info_role): } -@routes.route("", methods=["GET"]) -@permissions.check_cruved_scope("R", True, module_code="SYNTHESE") -@json_resp -def get_synthese(info_role): - """Return synthese row(s) filtered by form params. NOT USED ANY MORE FOR PERFORMANCE ISSUES - - .. :quickref: Synthese; Deprecated - - .. deprecated:: 2? - Use :route: /for_web instead - - Params must have same synthese fields names - - :parameter str info_role: Role used to get the associated filters - :returns dict[dict, int, bool]: See description above - """ - # change all args in a list of value - filters = {key: request.args.getlist(key) for key, value in request.args.items()} - if "limit" in filters: - result_limit = filters.pop("limit")[0] - else: - result_limit = current_app.config["SYNTHESE"]["NB_MAX_OBS_MAP"] - - query = select([VSyntheseForWebApp]).order_by(VSyntheseForWebApp.date_min.desc()) - synthese_query_class = SyntheseQuery(VSyntheseForWebApp, query, filters) - synthese_query_class.filter_query_all_filters(info_role) - data = DB.engine.execute(synthese_query_class.query.limit(result_limit)) - - - # q = synthese_query.filter_query_all_filters(VSyntheseForWebApp, q, filters, info_role) - - # data = q.limit(result_limit) - columns = current_app.config["SYNTHESE"]["COLUMNS_API_SYNTHESE_WEB_APP"] + MANDATORY_COLUMNS - features = [] - for d in data: - feature = d.get_geofeature(fields=columns) - feature["properties"]["nom_vern_or_lb_nom"] = ( - d.lb_nom if d.nom_vern is None else d.nom_vern - ) - features.append(feature) - return { - "data": FeatureCollection(features), - "nb_obs_limited": len(features) == current_app.config["SYNTHESE"]["NB_MAX_OBS_MAP"], - "nb_total": len(features), - } - - @routes.route("/vsynthese/", methods=["GET"]) def get_one_synthese(id_synthese): """Get one synthese record for web app with all decoded nomenclature @@ -981,54 +929,3 @@ def get_taxa_distribution(): data = query.group_by(rank).all() return [{"count": d[0], "group": d[1]} for d in data] - - -# @routes.route("/test", methods=["GET"]) -# @json_resp -# def test(): -# from shapely.geometry import asShape -# from geoalchemy2.shape import from_shape -# from shapely.geometry import Point -# import random - -# s = DB.session.query(Synthese).get(2) - -# s_as_dict = s.as_dict() -# s_as_dict.pop("unique_id_sinp") -# # wkt = asShape(s.the_geom_4326) -# # print(wkt) -# # releve.geom_4326 = from_shape(shape, srid=4326) -# import datetime - -# DB.session.query() -# for i in range(1000): -# new_point = Point(random.uniform(6.1, 7.5), random.uniform(44.0, 45.2)) -# wkb = from_shape(new_point, 4326) -# s_as_dict["id_synthese"] = random.randint(1500, 999999999) - -# # with random cd_nom -# random_cd_nom = DB.engine.execute( -# """ -# SELECT cd_nom FROM taxonomie.bib_noms OFFSET random() * (select count(*) from taxonomie.bib_noms) limit 1 ;""" -# ) -# cd_nom = None -# for cd in random_cd_nom: -# s_as_dict["cd_nom"] = cd[0] -# new_synthese = Synthese(**s_as_dict) -# new_synthese.the_geom_4326 = wkb -# new_synthese.the_geom_local = func.st_transform(wkb, 2154) - -# new_date = datetime.datetime.now() -# new_date = new_date.replace(year=random.randint(2000, 2016)) -# new_synthese.date_min = new_date -# new_synthese.date_max = new_date -# print(new_synthese.the_geom_local) -# q = DB.session.add(new_synthese) -# # DB.session.flush() -# DB.session.commit() - -# # s = TSources(name_source="lalala") - -# # DB.session.add(s) -# # DB.session.commit() -# return "la" diff --git a/backend/geonature/core/gn_synthese/utils/query.py b/backend/geonature/core/gn_synthese/utils/query.py deleted file mode 100644 index b652db9902..0000000000 --- a/backend/geonature/core/gn_synthese/utils/query.py +++ /dev/null @@ -1,262 +0,0 @@ -""" -Utility function to manage cruved and all filter of Synthese -Depreciated (but still use in validation module and export taxon in synthese) -For performance reason, use query_select_sqla.py -""" - -import datetime - -from flask import current_app, request -from shapely.wkt import loads -from geoalchemy2.shape import from_shape -from sqlalchemy import func, or_, and_, select -from sqlalchemy.sql import text -from sqlalchemy.orm import aliased - -from utils_flask_sqla_geo.utilsgeometry import circle_from_point - -from geonature.utils.env import DB -from geonature.core.taxonomie.models import Taxref, CorTaxonAttribut, TaxrefLR -from geonature.core.gn_synthese.models import ( - Synthese, - CorObserverSynthese, - TSources, - CorAreaSynthese, - TDatasets, -) -from geonature.core.gn_meta.models import TAcquisitionFramework, CorDatasetActor -from geonature.utils.errors import GeonatureApiError - - -def filter_query_with_cruved( - model, - q, - user, - id_synthese_column="id_synthese", - id_dataset_column="id_dataset", - observers_column="observers", - id_digitiser_column="id_digitiser", - with_generic_table=False, -): - """ - Filter the query with the cruved authorization of a user - - Returns: - - A SQLA Query object - """ - # if with geniric table , the column are located in model.columns, else in model - if with_generic_table: - model_temp = model.columns - else: - model_temp = model - allowed_datasets = TDatasets.get_user_datasets(user) - # get the mandatory column - try: - model_id_syn_col = getattr(model_temp, id_synthese_column) - model_id_dataset_column = getattr(model_temp, id_dataset_column) - model_observers_column = getattr(model_temp, observers_column) - model_id_digitiser_column = getattr(model_temp, id_digitiser_column) - except AttributeError as e: - raise GeonatureApiError( - """the {model} table does not have a column {e} - If you change the {model} table, please edit your synthese config (cf EXPORT_***_COL) - """.format( - e=e, model=model - ) - ) - - if user.value_filter in ("1", "2"): - sub_query_observers = ( - DB.session.query(CorObserverSynthese.id_synthese) - .filter(CorObserverSynthese.id_role == user.id_role) - .subquery("sub_query_observers") - ) - ors_filters = [ - model_id_syn_col.in_(sub_query_observers), - model_id_digitiser_column == user.id_role, - ] - if current_app.config["SYNTHESE"]["CRUVED_SEARCH_WITH_OBSERVER_AS_TXT"]: - user_fullname1 = user.nom_role + " " + user.prenom_role + "%" - user_fullname2 = user.prenom_role + " " + user.nom_role + "%" - ors_filters.append(model_observers_column.ilike(user_fullname1)) - ors_filters.append(model_observers_column.ilike(user_fullname2)) - - if user.value_filter == "1": - q = q.filter(or_(*ors_filters)) - elif user.value_filter == "2": - ors_filters.append(model_id_dataset_column.in_(allowed_datasets)) - q = q.filter(or_(*ors_filters)) - return q - - -def filter_taxonomy(model, q, filters): - """ - Filters the query with taxonomic attributes - Parameters: - - q (SQLAchemyQuery): an SQLAchemy query - - filters (dict): a dict of filter - Returns: - -Tuple: the SQLAlchemy query and the filter dictionnary - """ - cd_ref_childs = [] - if "cd_ref_parent" in filters: - # find all taxon child from cd_ref parent - cd_ref_parent_int = list(map(lambda x: int(x), filters.pop("cd_ref_parent"))) - sql = text( - """SELECT DISTINCT cd_ref FROM taxonomie.find_all_taxons_children(:id_parent)""" - ) - result = DB.engine.execute(sql, id_parent=cd_ref_parent_int) - if result: - cd_ref_childs = [r[0] for r in result] - - cd_ref_selected = [] - if "cd_ref" in filters: - cd_ref_selected = filters.pop("cd_ref") - # concat cd_ref child and just selected cd_ref - cd_ref_childs.extend(cd_ref_selected) - - if len(cd_ref_childs) > 0: - sub_query_synonym = ( - DB.session.query(Taxref.cd_nom) - .filter(Taxref.cd_ref.in_(cd_ref_childs)) - .subquery("sub_query_synonym") - ) - q = q.filter(model.cd_nom.in_(sub_query_synonym)) - - if "taxonomy_group2_inpn" in filters: - q = q.filter(Taxref.group2_inpn.in_(filters.pop("taxonomy_group2_inpn"))) - - if "taxonomy_id_hab" in filters: - q = q.filter(Taxref.id_habitat.in_(filters.pop("taxonomy_id_hab"))) - - if "taxonomy_lr" in filters: - sub_query_lr = ( - DB.session.query(TaxrefLR.cd_nom) - .filter(TaxrefLR.id_categorie_france.in_(filters.pop("taxonomy_lr"))) - .subquery("sub_query_lr") - ) - # est-ce qu'il faut pas filtrer sur le cd_ ref ? - # quid des protection définit à rang superieur de la saisie ? - q = q.filter(model.cd_nom.in_(sub_query_lr)) - - aliased_cor_taxon_attr = {} - join_on_taxref = False - for colname, value in filters.items(): - if colname.startswith("taxhub_attribut"): - if not join_on_taxref: - q = q.join(Taxref, Taxref.cd_nom == model.cd_nom) - join_on_taxref = True - taxhub_id_attr = colname[16:] - aliased_cor_taxon_attr[taxhub_id_attr] = aliased(CorTaxonAttribut) - q = q.join( - aliased_cor_taxon_attr[taxhub_id_attr], - and_( - aliased_cor_taxon_attr[taxhub_id_attr].id_attribut == taxhub_id_attr, - aliased_cor_taxon_attr[taxhub_id_attr].cd_ref - == func.taxonomie.find_cdref(model.cd_nom), - ), - ).filter(aliased_cor_taxon_attr[taxhub_id_attr].valeur_attribut.in_(value)) - join_on_bibnoms = True - - # remove attributes taxhub from filters - filters = { - colname: value - for colname, value in filters.items() - if not colname.startswith("taxhub_attribut") - } - return q, filters - - -def filter_query_all_filters(model, q, filters, user): - """ - Return a query filtered with the cruved and all - the filters available in the synthese form - parameters: - - q (SQLAchemyQuery): an SQLAchemy query - - filters (dict): a dict of filter - - user (User): a user object from User - - allowed datasets (List): an array of ID dataset where the users have autorization - - """ - q = filter_query_with_cruved(model, q, user) - - if "observers" in filters: - q = q.filter(model.observers.ilike("%" + filters.pop("observers")[0] + "%")) - - if "id_organism" in filters: - id_datasets = ( - DB.session.query(CorDatasetActor.id_dataset) - .filter(CorDatasetActor.id_organism.in_(filters.pop("id_organism"))) - .all() - ) - formated_datasets = [d[0] for d in id_datasets] - q = q.filter(model.id_dataset.in_(formated_datasets)) - - if "date_min" in filters: - q = q.filter(model.date_min >= filters.pop("date_min")[0]) - - if "date_max" in filters: - # set the date_max at 23h59 because a hour can be set in timestamp - date_max = datetime.datetime.strptime(filters.pop("date_max")[0], "%Y-%m-%d") - date_max = date_max.replace(hour=23, minute=59, second=59) - q = q.filter(model.date_max <= date_max) - - if "id_acquisition_framework" in filters: - q = q.join( - TAcquisitionFramework, - model.id_acquisition_framework == TAcquisitionFramework.id_acquisition_framework, - ) - q = q.filter( - TAcquisitionFramework.id_acquisition_framework.in_( - filters.pop("id_acquisition_framework") - ) - ) - - if "geoIntersection" in filters: - # Intersect with the geom send from the map - ors = [] - for str_wkt in filters["geoIntersection"]: - # if the geom is a circle - if "radius" in filters: - radius = filters.pop("radius")[0] - wkt = loads(str_wkt) - wkt = circle_from_point(wkt, float(radius)) - else: - wkt = loads(str_wkt) - geom_wkb = from_shape(wkt, srid=4326) - ors.append(model.the_geom_4326.ST_Intersects(geom_wkb)) - - q = q.filter(or_(*ors)) - filters.pop("geoIntersection") - - if "period_start" in filters and "period_end" in filters: - period_start = filters.pop("period_start")[0] - period_end = filters.pop("period_end")[0] - q = q.filter( - or_( - func.gn_commons.is_in_period( - func.date(model.date_min), - func.to_date(period_start, "DD-MM"), - func.to_date(period_end, "DD-MM"), - ), - func.gn_commons.is_in_period( - func.date(model.date_max), - func.to_date(period_start, "DD-MM"), - func.to_date(period_end, "DD-MM"), - ), - ) - ) - q, filters = filter_taxonomy(model, q, filters) - - # generic filters - join_on_cor_area = False - for colname, value in filters.items(): - if colname.startswith("area"): - if not join_on_cor_area: - q = q.join(CorAreaSynthese, CorAreaSynthese.id_synthese == model.id_synthese) - q = q.filter(CorAreaSynthese.id_area.in_(value)) - join_on_cor_area = True - else: - col = getattr(model.__table__.columns, colname) - q = q.filter(col.in_(value)) - return q diff --git a/backend/geonature/core/gn_synthese/utils/query_select_sqla.py b/backend/geonature/core/gn_synthese/utils/query_select_sqla.py index 3c79f37226..7c18da9ff2 100644 --- a/backend/geonature/core/gn_synthese/utils/query_select_sqla.py +++ b/backend/geonature/core/gn_synthese/utils/query_select_sqla.py @@ -17,9 +17,6 @@ from utils_flask_sqla_geo.utilsgeometry import circle_from_point from geonature.utils.env import DB -from geonature.core.taxonomie.models import ( - TaxrefLR -) from geonature.core.gn_synthese.models import ( Synthese, CorObserverSynthese, @@ -204,14 +201,6 @@ def filter_taxonomy(self): Taxref.id_habitat.in_(self.filters.pop("taxonomy_id_hab")) ) - if "taxonomy_lr" in self.filters: - sub_query_lr = select([TaxrefLR.cd_nom]).where( - TaxrefLR.id_categorie_france.in_(self.filters.pop("taxonomy_lr")) - ) - # TODO est-ce qu'il faut pas filtrer sur le cd_ ref ? - # quid des protection définit à rang superieur de la saisie ? - self.query = self.query.where(self.model.cd_nom.in_(sub_query_lr)) - aliased_cor_taxon_attr = {} for colname, value in self.filters.items(): if colname.startswith("taxhub_attribut"): @@ -425,13 +414,14 @@ def filter_other_filters(self): self.query = self.query.where(col.in_(value)) elif hasattr(self.model.__table__.columns, colname): col = getattr(self.model.__table__.columns, colname) + print(f"Column type: {col.type}") if str(col.type) == "INTEGER": if colname in ["precision"]: self.query = self.query.where(col <= value[0]) else: self.query = self.query.where(col == value[0]) else: - self.query = self.query.where(col.ilike("%{}%".format(value[0]))) + self.query = self.query.where(col.ilike("%{}%".format(value[0]))) def filter_query_all_filters(self, user): """High level function to manage query with all filters. diff --git a/backend/geonature/core/taxonomie/models.py b/backend/geonature/core/taxonomie/models.py deleted file mode 100644 index 0ac77221a8..0000000000 --- a/backend/geonature/core/taxonomie/models.py +++ /dev/null @@ -1,141 +0,0 @@ -from utils_flask_sqla.serializers import serializable - -from geonature.utils.env import DB - - -@serializable -class TaxrefProtectionArticles(DB.Model): - __tablename__ = "taxref_protection_articles" - __table_args__ = {"schema": "taxonomie"} - cd_protection = DB.Column(DB.Unicode, primary_key=True) - article = DB.Column(DB.Unicode) - intitule = DB.Column(DB.Unicode) - arrete = DB.Column(DB.Unicode) - cd_arrete = DB.Column(DB.Integer) - url_inpn = DB.Column(DB.Unicode) - cd_doc = DB.Column(DB.Integer) - url = DB.Column(DB.Unicode) - date_arrete = DB.Column(DB.Integer) - type_protection = DB.Column(DB.Unicode) - concerne_mon_territoire = DB.Column(DB.Boolean) - - def __str__(self): - return "" % self.article - - -@serializable -class TaxrefProtectionEspeces(DB.Model): - __tablename__ = "taxref_protection_especes" - __table_args__ = {"schema": "taxonomie"} - cd_nom = DB.Column(DB.Unicode, primary_key=True) - cd_protection = DB.Column(DB.Unicode, primary_key=True) - nom_cite = DB.Column(DB.Unicode) - syn_cite = DB.Column(DB.Unicode) - nom_francais_cite = DB.Column(DB.Unicode) - precisions = DB.Column(DB.Unicode) - cd_nom_cite = DB.Column(DB.Unicode, primary_key=True) - - -@serializable -class Taxref(DB.Model): - __tablename__ = "taxref" - __table_args__ = {"schema": "taxonomie"} - cd_nom = DB.Column(DB.Integer, primary_key=True) - id_statut = DB.Column(DB.Unicode) - id_habitat = DB.Column(DB.Integer) - id_rang = DB.Column(DB.Unicode) - regne = DB.Column(DB.Unicode) - phylum = DB.Column(DB.Unicode) - classe = DB.Column(DB.Unicode) - regne = DB.Column(DB.Unicode) - ordre = DB.Column(DB.Unicode) - famille = DB.Column(DB.Unicode) - sous_famille = DB.Column(DB.Unicode) - tribu = DB.Column(DB.Unicode) - cd_taxsup = DB.Column(DB.Integer) - cd_sup = DB.Column(DB.Integer) - cd_ref = DB.Column(DB.Integer) - lb_nom = DB.Column(DB.Unicode) - lb_auteur = DB.Column(DB.Unicode) - nom_complet = DB.Column(DB.Unicode) - nom_complet_html = DB.Column(DB.Unicode) - nom_vern = DB.Column(DB.Unicode) - nom_valide = DB.Column(DB.Unicode) - nom_vern_eng = DB.Column(DB.Unicode) - group1_inpn = DB.Column(DB.Unicode) - group2_inpn = DB.Column(DB.Unicode) - url = DB.Column(DB.Unicode) - - def __str__(self): - return "" % self.nom_complet - - -class CorTaxonAttribut(DB.Model): - __tablename__ = "cor_taxon_attribut" - __table_args__ = {"schema": "taxonomie"} - id_attribut = DB.Column(DB.Integer, nullable=False, primary_key=True) - cd_ref = DB.Column(DB.Integer, nullable=False, primary_key=True) - valeur_attribut = DB.Column(DB.Text, nullable=False) - - def __str__(self): - return "" % self.valeur_attribut - - -class TaxrefLR(DB.Model): - __tablename__ = "taxref_liste_rouge_fr" - __table_args__ = {"schema": "taxonomie"} - id_lr = DB.Column(DB.Integer, primary_key=True) - ordre_statut = DB.Column(DB.Integer) - vide = DB.Column(DB.Unicode) - cd_nom = DB.Column(DB.Integer) - cd_ref = DB.Column(DB.Integer) - nomcite = DB.Column(DB.Unicode) - nom_scientifique = DB.Column(DB.Unicode) - auteur = DB.Column(DB.Unicode) - nom_vernaculaire = DB.Column(DB.Unicode) - nom_commun = DB.Column(DB.Unicode) - rang = DB.Column(DB.Unicode) - famille = DB.Column(DB.Unicode) - endemisme = DB.Column(DB.Unicode) - population = DB.Column(DB.Unicode) - commentaire = DB.Column(DB.Unicode) - id_categorie_france = DB.Column(DB.Unicode) - criteres_france = DB.Column(DB.Unicode) - liste_rouge = DB.Column(DB.Unicode) - fiche_espece = DB.Column(DB.Unicode) - tendance = DB.Column(DB.Unicode) - liste_rouge_source = DB.Column(DB.Unicode) - annee_publication = DB.Column(DB.Unicode) - categorie_lr_europe = DB.Column(DB.Unicode) - categorie_lr_mondiale = DB.Column(DB.Unicode) - - -@serializable -class VMTaxrefListForautocomplete(DB.Model): - __tablename__ = "vm_taxref_list_forautocomplete" - __table_args__ = {"schema": "taxonomie"} - cd_nom = DB.Column(DB.Integer, primary_key=True) - search_name = DB.Column(DB.Unicode, primary_key=True) - cd_ref = DB.Column(DB.Integer) - nom_valide = DB.Column(DB.Unicode) - lb_nom = DB.Column(DB.Unicode) - regne = DB.Column(DB.Unicode) - group2_inpn = DB.Column(DB.Unicode) - - def __str__(self): - return "" % self.search_name - - -@serializable -class BibListes(DB.Model): - __tablename__ = "bib_listes" - __table_args__ = {"schema": "taxonomie"} - id_liste = DB.Column(DB.Integer, primary_key=True) - nom_liste = DB.Column(DB.Unicode) - desc_liste = DB.Column(DB.Text) - picto = DB.Column(DB.Unicode) - regne = DB.Column(DB.Unicode) - group2_inpn = DB.Column(DB.Unicode) - - def __str__(self): - return "" % self.nom_liste diff --git a/backend/geonature/core/taxonomie/schemas.py b/backend/geonature/core/taxonomie/schemas.py index 90dbb56e01..2fe1df533d 100644 --- a/backend/geonature/core/taxonomie/schemas.py +++ b/backend/geonature/core/taxonomie/schemas.py @@ -1,7 +1,6 @@ from geonature.utils.env import MA from marshmallow import pre_load, fields -from .models import Taxref - +from apptax.taxonomie.models import Taxref class TaxrefSchema(MA.SQLAlchemyAutoSchema): class Meta: diff --git a/contrib/gn_module_validation/backend/gn_module_validation/query.py b/contrib/gn_module_validation/backend/gn_module_validation/query.py deleted file mode 100644 index 5a39abf2ff..0000000000 --- a/contrib/gn_module_validation/backend/gn_module_validation/query.py +++ /dev/null @@ -1,116 +0,0 @@ -import datetime - -from flask import current_app, request -from shapely.wkt import loads -from geoalchemy2.shape import from_shape -from sqlalchemy import func, or_, and_ -from sqlalchemy.orm import aliased - -from utils_flask_sqla_geo.utilsgeometry import circle_from_point - -from geonature.utils.env import DB -from geonature.core.taxonomie.models import Taxref, CorTaxonAttribut, TaxrefLR -from geonature.core.gn_synthese.models import ( - Synthese, - CorObserverSynthese, - TSources, - CorAreaSynthese, -) -from geonature.core.gn_meta.models import TDatasets, TAcquisitionFramework - -from geonature.core.gn_synthese.utils.query import ( - filter_query_with_cruved, - filter_taxonomy, -) - - -def filter_query_all_filters(model, q, filters, user): - """ - Return a query filtered with the cruved and all - the filters available in the synthese form - parameters: - - q (SQLAchemyQuery): an SQLAchemy query - - filters (dict): a dict of filter - - user (User): a user object from User - - allowed datasets (List): an array of ID dataset where the users have autorization - - """ - q = filter_query_with_cruved(model, q, user) - - if "observers" in filters: - q = q.filter(model.observers.ilike( - "%" + filters.pop("observers")[0] + "%")) - - if "date_min" in filters: - q = q.filter(model.date_min >= filters.pop("date_min")[0]) - - if "date_max" in filters: - # set the date_max at 23h59 because a hour can be set in timestamp - date_max = datetime.datetime.strptime( - filters.pop("date_max")[0], '%Y-%m-%d') - date_max = date_max.replace(hour=23, minute=59, second=59) - q = q.filter(model.date_max <= date_max) - - if "id_acquisition_frameworks" in filters: - q = q.join( - TAcquisitionFramework, - model.id_acquisition_framework - == TAcquisitionFramework.id_acquisition_framework, - ) - q = q.filter( - TAcquisitionFramework.id_acquisition_framework.in_( - filters.pop("id_acquisition_frameworks") - ) - ) - - if "geoIntersection" in filters: - # Insersect with the geom send from the map - ors = [] - for str_wkt in filters["geoIntersection"]: - # if the geom is a circle - if "radius" in filters: - radius = filters.pop("radius")[0] - wkt = circle_from_point(loads(str_wkt), float(radius)) - else: - wkt = loads(str_wkt) - geom_wkb = from_shape(wkt, srid=4326) - ors.append(model.the_geom_4326.ST_Intersects(geom_wkb)) - - q = q.filter(or_(*ors)) - filters.pop("geoIntersection") - - if "period_start" in filters and "period_end" in filters: - period_start = filters.pop("period_start")[0] - period_end = filters.pop("period_end")[0] - q = q.filter( - or_( - func.gn_commons.is_in_period( - func.date(model.date_min), - func.to_date(period_start, "DD-MM"), - func.to_date(period_end, "DD-MM"), - ), - func.gn_commons.is_in_period( - func.date(model.date_max), - func.to_date(period_start, "DD-MM"), - func.to_date(period_end, "DD-MM"), - ), - ) - ) - q, filters = filter_taxonomy(model, q, filters) - - # generic filters - join_on_cor_area = False - for colname, value in filters.items(): - if colname.startswith("area"): - if not join_on_cor_area: - q = q.join( - CorAreaSynthese, CorAreaSynthese.id_synthese == model.id_synthese - ) - q = q.filter(CorAreaSynthese.id_area.in_(value)) - join_on_cor_area = True - elif colname.startswith("modif_since_validation"): - q = q.filter(model.meta_update_date > model.validation_date) - else: - col = getattr(model.__table__.columns, colname) - q = q.filter(col.in_(value)) - return q diff --git a/contrib/occtax/backend/occtax/models.py b/contrib/occtax/backend/occtax/models.py index cb48600ef0..0028b4cdb6 100644 --- a/contrib/occtax/backend/occtax/models.py +++ b/contrib/occtax/backend/occtax/models.py @@ -11,7 +11,7 @@ from utils_flask_sqla_geo.serializers import geoserializable from pypn_habref_api.models import Habref -from geonature.core.taxonomie.models import Taxref +from apptax.taxonomie.models import Taxref from geonature.core.gn_commons.models import TMedias from geonature.core.gn_meta.models import TDatasets from geonature.utils.env import DB diff --git a/frontend/src/app/GN2CommonModule/form/data-form.service.ts b/frontend/src/app/GN2CommonModule/form/data-form.service.ts index c90d7e56d4..ce8c5bb6fa 100644 --- a/frontend/src/app/GN2CommonModule/form/data-form.service.ts +++ b/frontend/src/app/GN2CommonModule/form/data-form.service.ts @@ -236,10 +236,6 @@ export class DataFormService { return this._http.get(`${AppConfig.API_TAXHUB}/bibattributs/`); } - getTaxonomyLR() { - return this._http.get(`${AppConfig.API_TAXHUB}/taxref/bib_lr`); - } - getTaxonomyHabitat() { return this._http.get(`${AppConfig.API_TAXHUB}/taxref/bib_habitats`); } diff --git a/frontend/src/app/GN2CommonModule/form/synthese-form/advanced-form/synthese-advanced-form-store.service.ts b/frontend/src/app/GN2CommonModule/form/synthese-form/advanced-form/synthese-advanced-form-store.service.ts index 044761bf07..c31c7d2317 100644 --- a/frontend/src/app/GN2CommonModule/form/synthese-form/advanced-form/synthese-advanced-form-store.service.ts +++ b/frontend/src/app/GN2CommonModule/form/synthese-form/advanced-form/synthese-advanced-form-store.service.ts @@ -17,7 +17,6 @@ export class TaxonAdvancedStoreService { public taxonTreeState: any; public taxhubAttributes: any; public formBuilded: boolean; - public taxonomyLR: Array; public taxonomyHab: Array; public taxonomyGroup2Inpn: Array; public redListsValues: any = {}; @@ -82,11 +81,7 @@ export class TaxonAdvancedStoreService { }); this.formBuilded = true; }); - // Load LR, habitat and group2inpn - this._dataService.getTaxonomyLR().subscribe(data => { - this.taxonomyLR = data; - }); - + // Load habitat and group2inpn this._dataService.getTaxonomyHabitat().subscribe(data => { this.taxonomyHab = data; }); diff --git a/frontend/src/app/GN2CommonModule/form/synthese-form/advanced-form/synthese-advanced-form.component.html b/frontend/src/app/GN2CommonModule/form/synthese-form/advanced-form/synthese-advanced-form.component.html index 019262fb08..91f5fdada0 100644 --- a/frontend/src/app/GN2CommonModule/form/synthese-form/advanced-form/synthese-advanced-form.component.html +++ b/frontend/src/app/GN2CommonModule/form/synthese-form/advanced-form/synthese-advanced-form.component.html @@ -190,18 +190,6 @@
Listes rouges
Attributs TaxRef
-
- - -
Echantillon de preuve {{selectedObs?.sample_number_proof}} - Type de regroupement {{selectedObs?.grp_typ}} @@ -282,15 +281,6 @@
Attribut(s) Taxonomique(s) locau -
Réglementation
- - - - -
- {{arrete.intitule}} -
-
Statuts
; - - constructor( - private _fb: FormBuilder, - private _dateParser: NgbDateParserFormatter, - private _periodFormatter: NgbDatePeriodParserFormatter - ) { - this.searchForm = this._fb.group({ - cd_nom: null, - observers: null, - id_organism: null, - id_dataset: null, - id_acquisition_framework: null, - date_min: null, - date_max: null, - period_start: null, - period_end: null, - geoIntersection: null, - radius: null, - taxonomy_lr: null, - taxonomy_id_hab: null, - taxonomy_group2_inpn: null - }); - - this.searchForm.setValidators([this.periodValidator()]); - - AppConfig.SYNTHESE.AREA_FILTERS.forEach(area => { - const control_name = 'area_' + area.id_type; - this.searchForm.addControl(control_name, new FormControl(new Array())); - const control = this.searchForm.controls[control_name]; - area['control'] = control; - }); - // init the dynamic form with the user parameters - // remove the filters which are in AppConfig.SYNTHESE.EXCLUDED_COLUMNS - this.dynamycFormDef = DYNAMIC_FORM_DEF.filter(formDef => { - return AppConfig.SYNTHESE.EXCLUDED_COLUMNS.indexOf(formDef.attribut_name) === -1; - }); - this.formBuilded = true; - } - - getCurrentTaxon($event) { - this.selectedtaxonFromComponent.push($event.item); - $event.preventDefault(); - this.searchForm.controls.cd_nom.reset(); - } - - removeTaxon(index) { - this.selectedtaxonFromComponent.splice(index, 1); - } - - formatParams() { - // function which take parameters from the form and format them correctly - // before build url query string - const params = Object.assign({}, this.searchForm.value); - const updatedParams = {}; - // tslint:disable-next-line:forin - for (let key in params) { - if ((key === 'date_min' && params.date_min) || (key === 'date_max' && params.date_max)) { - updatedParams[key] = this._dateParser.format(params[key]); - } else if ( - (key === 'period_end' && params.period_end) || - (key === 'period_start' && params.period_start) - ) { - updatedParams[key] = this._periodFormatter.format(params[key]); - } else if (key === 'geoIntersection' && params['geoIntersection']) { - const wktArray = []; - // if geointersection is an array of geojson (from filelayer) convert each one in WKT - if (isArray(params['geoIntersection'])) { - params['geoIntersection'].forEach(geojson => { - wktArray.push(toWKT(geojson)); - }); - updatedParams['geoIntersection'] = wktArray; - } else { - updatedParams['geoIntersection'] = toWKT(params['geoIntersection']); - } - } else if (params[key]) { - // if its an Array push only if > 0 - if (Array.isArray(params[key]) && params[key].length > 0) { - updatedParams[key] = params[key]; - // else if its not an array, alway send the parameter - } else if (!Array.isArray(params[key])) { - updatedParams[key] = params[key]; - } - } - } - if (this.selectedtaxonFromComponent.length > 0) { - updatedParams['cd_ref'] = this.selectedtaxonFromComponent.map(taxon => taxon.cd_ref); - } - if (this.selectedCdRefFromTree.length > 0) { - updatedParams['cd_ref_parent'] = this.selectedCdRefFromTree; - } - return updatedParams; - } - - periodValidator(): ValidatorFn { - return (formGroup: FormGroup): { [key: string]: boolean } => { - const perioStart = formGroup.controls.period_start.value; - const periodEnd = formGroup.controls.period_end.value; - if ((perioStart && !periodEnd) || (!perioStart && periodEnd)) { - return { - invalidPeriod: true - }; - } - return null; - }; - } -} diff --git a/frontend/src/app/syntheseModule/services/store.service.ts b/frontend/src/app/syntheseModule/services/store.service.ts deleted file mode 100644 index 7530cdc8a7..0000000000 --- a/frontend/src/app/syntheseModule/services/store.service.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Injectable } from '@angular/core'; - -@Injectable() -export class SyntheseStoreService { - public idSyntheseList: Array; - constructor() {} -} diff --git a/frontend/src/app/syntheseModule/synthese-results/synthese-list/synthese-info-obs/modal-info-obs.component.html b/frontend/src/app/syntheseModule/synthese-results/synthese-list/synthese-info-obs/modal-info-obs.component.html deleted file mode 100644 index 60a3b3b421..0000000000 --- a/frontend/src/app/syntheseModule/synthese-results/synthese-list/synthese-info-obs/modal-info-obs.component.html +++ /dev/null @@ -1,401 +0,0 @@ -
-
- - -
- - - - - - - - - - - - - - - - -
Jeu de données {{selectedObs?.datasets?.dataset_name}}
Cadre d'acquisition {{selectedObs?.acquisition_framework.acquisition_framework_name}}
- Acteurs - -
    -
  • - {{act}} -
  • -
-
Module de provenance {{selectedObs?.source.name_source}}
- - -
Médias -
- - - - - - - - - - - - - - - - - - -
Titre {{media.title_fr}}
Description {{ media.description_fr }}
Auteur {{ media.author }}
- -
-
- -
-
-
Détail de l'occurrence
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Statut de l'observation {{selectedObs?.observation_status}}
Technique d'observation {{selectedObs?.obs_technique}}
Etat biologique {{selectedObs?.bio_condition}}
Statut biologique {{selectedObs?.bio_status}}
Comportement {{selectedObs?.occ_behaviour}}
Sexe {{selectedObs?.sex}}
Stade de vie {{selectedObs?.life_stage}}
Denombrement min {{selectedObs?.count_min}}
Denombrement max {{selectedObs?.count_max}}
Type de dénombrement {{selectedObs?.type_count}}
Objet du dénombrement {{selectedObs?.obj_count}}
Naturalité {{selectedObs?.naturalness}}
Commentaire relevé {{selectedObs?.comment_context}}
Commentaire occurrence {{selectedObs?.comment_description}}
Determinateur {{selectedObs?.determiner}}
Preuve d'existence {{selectedObs?.exist_proof}}
Preuve numérique {{selectedObs?.digital_proof}}
Preuve non numérique {{selectedObs?.non_digital_proof}}
Echantillon de preuve {{selectedObs?.sample_number_proof}}
Type de regroupement {{selectedObs?.grp_typ}}
Méthode de regroupement {{selectedObs?.grp_method}}
Source de la donnée {{selectedObs?.source_status}}
Statut de validation {{selectedObs?.valid_status}}
Sensibilité {{selectedObs?.sensitivity}}
Niveau de diffusion {{selectedObs?.diffusion_level}}
Nature de l'objet géographique {{selectedObs?.nat_obj_geo}}
Floutage {{selectedObs?.blurring}}
Identifiant unique SINP {{selectedObs?.unique_id_sinp}}
{{data.key}} {{data.value}}
- -
- - -
- -
Taxonomie
- - - - - - - - - - - - - - - -
- Groupe taxonomique - {{ selectedObsTaxonDetail?.classe }}
- Ordre - {{ selectedObsTaxonDetail?.ordre }}
- Famille - {{ selectedObsTaxonDetail?.famille }}
- -
Attribut(s) Taxonomique(s) locaux
- - - - - -
{{attr.label_attribut}} {{attr.valeur_attribut}}
- - -
Réglementation
- - - - - -
- {{arrete.intitule}} -
- - - - -
- - -
- -
- - - - - - - - - - - - - - - - - - - -
Date de validation Statut Validateur Commentaire
{{row.validation_date | date:'dd-MM-yyyy'}} {{row.validation_label.label_default}} - {{row.validator_role.prenom_role}} {{row.validator_role.nom_role}} - - Validation automatique - {{row.validation_comment}}
-
-
- - - - - - - - - - - - - - - -
Type de zonage Zones
- {{ area_type.area_type }} - - - {{area.area_name}}, - - -
-
- - - - - - - - -