|
13 | 13 | from flask import current_app |
14 | 14 |
|
15 | 15 | import sqlalchemy as sa |
16 | | -from sqlalchemy import func, or_, and_, select, distinct |
| 16 | +from sqlalchemy import func, or_, and_, select, distinct, literal_column |
17 | 17 | from sqlalchemy.sql import text |
18 | 18 | from sqlalchemy.orm import aliased |
| 19 | +from sqlalchemy.dialects.postgresql import array, ARRAY |
19 | 20 | from werkzeug.exceptions import BadRequest |
20 | 21 | from shapely.geometry import shape |
21 | 22 | from geoalchemy2.shape import from_shape |
|
30 | 31 | BibReportsTypes, |
31 | 32 | TReport, |
32 | 33 | TSources, |
| 34 | + SyntheseExtended, |
33 | 35 | ) |
34 | 36 | from geonature.core.gn_meta.models import ( |
35 | 37 | CorDatasetActor, |
|
41 | 43 | TaxrefTree, |
42 | 44 | CorTaxonAttribut, |
43 | 45 | TaxrefBdcStatutTaxon, |
| 46 | + TaxonAreaStatus, |
44 | 47 | bdc_statut_cor_text_area, |
45 | 48 | TaxrefBdcStatutCorTextValues, |
46 | 49 | TaxrefBdcStatutText, |
@@ -311,8 +314,7 @@ def filter_taxonomy(self): |
311 | 314 | aliased_cor_taxon_attr[taxhub_id_attr], |
312 | 315 | [ |
313 | 316 | 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, |
316 | 318 | ], |
317 | 319 | ) |
318 | 320 | self.query = self.query.where( |
@@ -340,7 +342,7 @@ def filter_taxonomy(self): |
340 | 342 | ): |
341 | 343 | value = status_cfg["status_types"] |
342 | 344 |
|
343 | | - protection_status_value += value |
| 345 | + protection_status_value.append(value) |
344 | 346 |
|
345 | 347 | if protection_status_value or red_list_filters: |
346 | 348 | 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): |
601 | 603 | la liste des status selectionnés par l'utilisateur s'appliquant à l'observation est |
602 | 604 | aggrégée de façon à tester le nombre puis jointer sur le département de la donnée |
603 | 605 | """ |
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) |
607 | 606 |
|
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 |
640 | 608 | bdc_status_filters = [] |
641 | 609 | 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() |
648 | 612 | ] |
649 | 613 | 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 | + ] |
653 | 618 |
|
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() |
657 | 630 | ) |
658 | 631 |
|
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") |
669 | 635 | ) |
670 | 636 |
|
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]) |
674 | 638 |
|
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() |
687 | 644 | ) |
688 | 645 |
|
| 646 | + self.query = self.query.where(exists_subq) |
| 647 | + |
689 | 648 |
|
690 | 649 | def remove_accents(input_str): |
691 | 650 | nfkd_form = unicodedata.normalize("NFKD", input_str) |
|
0 commit comments