Skip to content

Commit 2240213

Browse files
jbrieuclpjpm-cbna
authored andcommitted
feat(backend): rebuild status filters in SyntheseQuery
1 parent 35487ef commit 2240213

1 file changed

Lines changed: 35 additions & 76 deletions

File tree

backend/geonature/core/gn_synthese/utils/query_select_sqla.py

Lines changed: 35 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@
1313
from flask import current_app
1414

1515
import sqlalchemy as sa
16-
from sqlalchemy import func, or_, and_, select, distinct
16+
from sqlalchemy import func, or_, and_, select, distinct, literal_column
1717
from sqlalchemy.sql import text
1818
from sqlalchemy.orm import aliased
19+
from sqlalchemy.dialects.postgresql import array, ARRAY
1920
from werkzeug.exceptions import BadRequest
2021
from shapely.geometry import shape
2122
from geoalchemy2.shape import from_shape
@@ -30,6 +31,7 @@
3031
BibReportsTypes,
3132
TReport,
3233
TSources,
34+
SyntheseExtended,
3335
)
3436
from geonature.core.gn_meta.models import (
3537
CorDatasetActor,
@@ -41,6 +43,7 @@
4143
TaxrefTree,
4244
CorTaxonAttribut,
4345
TaxrefBdcStatutTaxon,
46+
TaxonAreaStatus,
4447
bdc_statut_cor_text_area,
4548
TaxrefBdcStatutCorTextValues,
4649
TaxrefBdcStatutText,
@@ -311,8 +314,7 @@ def filter_taxonomy(self):
311314
aliased_cor_taxon_attr[taxhub_id_attr],
312315
[
313316
aliased_cor_taxon_attr[taxhub_id_attr].id_attribut == taxhub_id_attr,
314-
aliased_cor_taxon_attr[taxhub_id_attr].cd_ref
315-
== self.model.cd_ref,
317+
aliased_cor_taxon_attr[taxhub_id_attr].cd_ref == self.model.cd_ref,
316318
],
317319
)
318320
self.query = self.query.where(
@@ -340,7 +342,7 @@ def filter_taxonomy(self):
340342
):
341343
value = status_cfg["status_types"]
342344

343-
protection_status_value += value
345+
protection_status_value.append(value)
344346

345347
if protection_status_value or red_list_filters:
346348
self.build_bdc_status_filters(protection_status_value, red_list_filters)
@@ -601,91 +603,48 @@ def build_bdc_status_filters(self, protection_status_value, red_list_filters):
601603
la liste des status selectionnés par l'utilisateur s'appliquant à l'observation est
602604
aggrégée de façon à tester le nombre puis jointer sur le département de la donnée
603605
"""
604-
# Ajout jointure permettant d'avoir le département pour chaque donnée
605-
cas_dep = aliased(CorAreaSynthese)
606-
self.add_join(cas_dep, cas_dep.id_synthese, self.model.id_synthese)
607606

608-
# Creation requête CTE : taxon, zone d'application départementale des textes
609-
# pour les taxons répondant aux critères de selection
610-
bdc_status_by_type_cte = (
611-
select(
612-
TaxrefBdcStatutTaxon.cd_ref,
613-
bdc_statut_cor_text_area.c.id_area,
614-
TaxrefBdcStatutText.cd_type_statut,
615-
)
616-
.distinct()
617-
.select_from(
618-
TaxrefBdcStatutTaxon.__table__.join(
619-
TaxrefBdcStatutCorTextValues,
620-
TaxrefBdcStatutCorTextValues.id_value_text
621-
== TaxrefBdcStatutTaxon.id_value_text,
622-
)
623-
.join(
624-
TaxrefBdcStatutText,
625-
TaxrefBdcStatutText.id_text == TaxrefBdcStatutCorTextValues.id_text,
626-
)
627-
.join(
628-
TaxrefBdcStatutValues,
629-
TaxrefBdcStatutValues.id_value == TaxrefBdcStatutCorTextValues.id_value,
630-
)
631-
.join(
632-
bdc_statut_cor_text_area,
633-
bdc_statut_cor_text_area.c.id_text == TaxrefBdcStatutText.id_text,
634-
)
635-
)
636-
.where(TaxrefBdcStatutText.enable == True)
637-
)
638-
639-
# ajout des filtres de selection des textes
607+
# Préparation des filtres de statuts à ajouter dans le where du CTE
640608
bdc_status_filters = []
641609
if red_list_filters:
642-
bdc_status_filters = [
643-
and_(
644-
TaxrefBdcStatutValues.code_statut.in_(v),
645-
TaxrefBdcStatutText.cd_type_statut == k,
646-
)
647-
for k, v in red_list_filters.items()
610+
bdc_status_filters += [
611+
TaxonAreaStatus.status[k].has_any(array(v)) for k, v in red_list_filters.items()
648612
]
649613
if protection_status_value:
650-
bdc_status_filters.append(
651-
TaxrefBdcStatutText.cd_type_statut.in_(protection_status_value)
652-
)
614+
bdc_status_filters += [
615+
TaxonAreaStatus.status.has_any(array(status_value))
616+
for status_value in protection_status_value
617+
]
653618

654-
bdc_status_by_type_cte = bdc_status_by_type_cte.where(or_(*bdc_status_filters))
655-
bdc_status_by_type_cte = bdc_status_by_type_cte.cte(
656-
name="bdc_status_by_type_" + str(uuid.uuid4())[:4]
619+
# Creation requête CTE : taxon, zone d'application départementale des textes
620+
# pour les taxons répondant aux critères de selection
621+
subquery = (
622+
select(CorAreaSynthese.id_synthese, TaxonAreaStatus.status)
623+
.join(TaxonAreaStatus, CorAreaSynthese.id_area == TaxonAreaStatus.id_area)
624+
.where(
625+
TaxonAreaStatus.cd_ref == SyntheseExtended.cd_ref,
626+
CorAreaSynthese.id_synthese == SyntheseExtended.id_synthese,
627+
sa.and_(*bdc_status_filters),
628+
)
629+
.lateral()
657630
)
658631

659-
# group by de façon à ne selectionner que les taxons
660-
# qui ont l'ensemble des textes selectionnés par l'utilisateur
661-
# c-a-d dont le nombre de cd_type_statut correspond au nombre demandé
662-
bdc_status_cte = select(
663-
bdc_status_by_type_cte.c.cd_ref,
664-
func.array_agg(bdc_status_by_type_cte.c.id_area).label("ids_area"),
665-
)
666-
bdc_status_cte = bdc_status_cte.group_by(bdc_status_by_type_cte.c.cd_ref).having(
667-
func.count(distinct(bdc_status_by_type_cte.c.cd_type_statut))
668-
== (len(protection_status_value) + len(red_list_filters))
632+
# Requête principale
633+
status_cte = select(SyntheseExtended.id_synthese, subquery.c.status).join(
634+
subquery, literal_column("true")
669635
)
670636

671-
bdc_status_cte = bdc_status_cte.cte(
672-
name="bdc_status_cte_" + str(uuid.uuid4())[:4]
673-
)
637+
status_cte = status_cte.cte(name="status" + str(uuid.uuid4())[:4])
674638

675-
# Jointure sur le taxon
676-
# et vérification que l'ensemble des textes
677-
# soit sur bien sur le département de l'observation
678-
self.add_join_multiple_cond(
679-
bdc_status_cte,
680-
[
681-
bdc_status_cte.c.cd_ref == self.model.cd_ref,
682-
func.array_length(
683-
func.array_positions(bdc_status_cte.c.ids_area, cas_dep.id_area), 1
684-
)
685-
== (len(protection_status_value) + len(red_list_filters)),
686-
],
639+
exists_subq = (
640+
select(literal_column("1"))
641+
.select_from(status_cte)
642+
.where(and_(status_cte.c.id_synthese == SyntheseExtended.id_synthese))
643+
.exists()
687644
)
688645

646+
self.query = self.query.where(exists_subq)
647+
689648

690649
def remove_accents(input_str):
691650
nfkd_form = unicodedata.normalize("NFKD", input_str)

0 commit comments

Comments
 (0)