From 6f6b91a452551353eb5652a06885cb4747a9c840 Mon Sep 17 00:00:00 2001
From: jacquesfize
Date: Fri, 10 Jan 2025 15:22:08 +0100
Subject: [PATCH 01/13] feat(changelog): update changelog
---
docs/CHANGELOG.md | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 0f6785e27a..ff941afdb6 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -1,27 +1,27 @@
# CHANGELOG
-## 2.15.1 (unreleased)
+## 2.15.1 (2025-01-10)
**🚀 Nouveautés**
-- Amélioration de la recherche libre des métadonnées en cherchant chaque mot indépendamment (#3295, par @jbrieuclp)
-- Amélioration de l'affichage de la photo du taxon sur les fiches taxon (#3287, par @edelclaux)
-- Conversion du changelog en format markdown (#3297, par @jacquesfize)
-- Ajout d'un fichier `Makefile` pour faciliter l'usage des commandes de développement (#3300, par @jacquesfize & @edelclaux)
-- Complément et mise en forme de la documentation et publication sur Readthedocs (#3306, par @jacquesfize)
-- Ajout des nouvelles mailles INPN lors de l'installation de GeoNature (#3293, par @jacquesfize)
+- [Métadonnées]Amélioration de la recherche libre des métadonnées en cherchant chaque mot indépendamment (#3295, par @jbrieuclp)
+- [FicheTaxon] Amélioration de l'affichage de la photo du taxon sur les fiches taxon (#3287, par @edelclaux)
+- [Documentation] Conversion du changelog en format markdown (#3297, par @jacquesfize)
+- [Documentation] Complément et mise en forme de la documentation et publication sur Readthedocs (#3306, par @jacquesfize)
+- [Dévelopement] Ajout d'un fichier `Makefile` pour faciliter l'usage des commandes de développement (#3300, par @jacquesfize & @edelclaux)
+- [Installation] Ajout des nouvelles mailles INPN lors de l'installation de GeoNature (#3293, par @jacquesfize)
**🐛 Corrections**
-- Correction de la pagination quand on filtre les discussions de la page d'accueil sur "Mes discussions" (#3288, par @edelclaux)
-- Correction du nombre de taxons sur les fiches des cadres d'acquisition (#3228, par @jacquesfize)
-- Correction de la redirection de l'authentification (#3305, par @jacquesfize)
-- Correction des performances de la requête de récupération des discussions (#3307, par @jacquesfize)
-- [Import] Correction de l'export des rapports d'import Occhab (#3293, par @jacquesfize)
+- [Discussions] Correction de la pagination quand on filtre les discussions de la page d'accueil sur "Mes discussions" (#3288, par @edelclaux)
+- [Discussions] Correction des performances de la requête de récupération des discussions (#3307, par @jacquesfize)
+- [Métadonnées] Correction du nombre de taxons sur les fiches des cadres d'acquisition (#3228, par @jacquesfize)
+- [Authentification] Correction des redirections lors de l'authentification (#3305, par @jacquesfize)
- [Import] Correction de la selection automatique du JDD lors de l'import depuis la fiche d'un JDD (#3293, par @jacquesfize)
- [Import] Correction de la mise à jour des mappings publics (#3293, par @jacquesfize)
- [Import] Correction de la sauvegarde des checkbox dans le mapping des champs (#3293, par @Pierre-Narcisi)
- [Import] Correction de la sélection des champs `auto_generate` (#3293, par @Pierre-Narcisi)
+- [Import] Correction du template des notifications d'un import terminé (#3310 par @jacquesfize)
## 2.15.0 - Pavo cristatus 🦚 (2025-12-11)
From 9a017861bca799271bf5b3e959ae2191a6cc0985 Mon Sep 17 00:00:00 2001
From: Jacques Fize <4259846+jacquesfize@users.noreply.github.com>
Date: Mon, 13 Jan 2025 14:40:53 +0100
Subject: [PATCH 02/13] feat(home): optimize `general_stats` route (#3313)
* feat(home): optimize `general_stats` route
* feat(synthese): add index on gn_synthese.observers to increase perf of `general_stats` computation
Co-authored-by: dba-sig-sfepm
---
backend/geonature/core/gn_synthese/routes.py | 34 +++++++++++-------
...669c_create_index_on_synthese_observers.py | 35 +++++++++++++++++++
.../tests/benchmarks/test_benchmark_home.py | 24 +++++++++++++
3 files changed, 80 insertions(+), 13 deletions(-)
create mode 100644 backend/geonature/migrations/versions/5cf0ce9e669c_create_index_on_synthese_observers.py
create mode 100644 backend/geonature/tests/benchmarks/test_benchmark_home.py
diff --git a/backend/geonature/core/gn_synthese/routes.py b/backend/geonature/core/gn_synthese/routes.py
index e2dc80e61e..f5cb9b0cab 100644
--- a/backend/geonature/core/gn_synthese/routes.py
+++ b/backend/geonature/core/gn_synthese/routes.py
@@ -939,21 +939,29 @@ def general_stats(permissions):
.select_from(TDatasets)
.where(TDatasets.filter_by_readable().whereclause)
)
- query = select(
- func.count(Synthese.id_synthese),
- func.count(func.distinct(Synthese.cd_nom)),
- func.count(func.distinct(Synthese.observers)),
- )
- synthese_query_obj = SyntheseQuery(Synthese, query, {})
- synthese_query_obj.filter_query_with_cruved(g.current_user, permissions)
- result = DB.session.execute(synthese_query_obj.query)
- synthese_counts = result.fetchone()
+ results = {"nb_allowed_datasets": nb_allowed_datasets}
+
+ queries = {
+ "nb_obs": select(
+ func.count(Synthese.id_synthese),
+ ),
+ "nb_distinct_species": select(
+ func.count(func.distinct(Synthese.cd_nom)),
+ ),
+ "nb_distinct_observer": select(
+ func.count(func.distinct(Synthese.observers)),
+ ),
+ }
+ for key, query in queries.items():
+ synthese_query = SyntheseQuery(Synthese, query, {})
+ synthese_query.filter_query_with_cruved(g.current_user, permissions)
+ results[key] = db.session.scalar(synthese_query.query)
data = {
- "nb_data": synthese_counts[0],
- "nb_species": synthese_counts[1],
- "nb_observers": synthese_counts[2],
- "nb_dataset": nb_allowed_datasets,
+ "nb_data": results["nb_obs"],
+ "nb_species": results["nb_distinct_species"],
+ "nb_observers": results["nb_distinct_observer"],
+ "nb_dataset": results["nb_allowed_datasets"],
}
return data
diff --git a/backend/geonature/migrations/versions/5cf0ce9e669c_create_index_on_synthese_observers.py b/backend/geonature/migrations/versions/5cf0ce9e669c_create_index_on_synthese_observers.py
new file mode 100644
index 0000000000..2c82e2f298
--- /dev/null
+++ b/backend/geonature/migrations/versions/5cf0ce9e669c_create_index_on_synthese_observers.py
@@ -0,0 +1,35 @@
+"""create_index_on_synthese_observers
+
+Revision ID: 5cf0ce9e669c
+Revises: 9df933cc3c7a
+Create Date: 2025-01-13 14:14:30.085725
+
+"""
+
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = "5cf0ce9e669c"
+down_revision = "9df933cc3c7a"
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ op.create_index(
+ "synthese_observers_idx",
+ "synthese",
+ ["observers"],
+ if_not_exists=True,
+ schema="gn_synthese",
+ )
+
+
+def downgrade():
+ op.drop_index(
+ "synthese_observers_idx",
+ table_name="synthese",
+ schema="gn_synthese",
+ )
diff --git a/backend/geonature/tests/benchmarks/test_benchmark_home.py b/backend/geonature/tests/benchmarks/test_benchmark_home.py
new file mode 100644
index 0000000000..0b4bd842aa
--- /dev/null
+++ b/backend/geonature/tests/benchmarks/test_benchmark_home.py
@@ -0,0 +1,24 @@
+import logging
+import pytest
+from geonature.tests.benchmarks import *
+from geonature.tests.test_pr_occhab import stations
+
+from .benchmark_generator import BenchmarkTest, CLater
+from .utils import activate_profiling_sql
+
+logging.basicConfig()
+logger = logging.getLogger("logger-name")
+logger.setLevel(logging.DEBUG)
+
+from .utils import CLIENT_GET, CLIENT_POST
+
+
+@pytest.mark.benchmark(group="home")
+@pytest.mark.usefixtures("client_class", "temporary_transaction", "activate_profiling_sql")
+class TestBenchmarkHome:
+
+ test_general_stats = BenchmarkTest(
+ CLIENT_GET,
+ [CLater("""url_for("gn_synthese.general_stats")""")],
+ dict(user_profile="admin_user", fixtures=[]),
+ )()
From 6c38ec559d304c5083d05eb423ccbd7b9b2f0090 Mon Sep 17 00:00:00 2001
From: Jacques Fize <4259846+jacquesfize@users.noreply.github.com>
Date: Mon, 13 Jan 2025 15:49:41 +0100
Subject: [PATCH 03/13] Fix sensitivity remove message (#3314)
* fix(sensitivity): fix delete sensitivity rule message
* feat(test): add test for deletion of sensitivity rules
---
backend/geonature/core/sensitivity/utils.py | 7 +++-
backend/geonature/tests/test_sensitivity.py | 39 +++++++++++++++++++++
2 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/backend/geonature/core/sensitivity/utils.py b/backend/geonature/core/sensitivity/utils.py
index 5ec278ff83..42106d0151 100644
--- a/backend/geonature/core/sensitivity/utils.py
+++ b/backend/geonature/core/sensitivity/utils.py
@@ -131,4 +131,9 @@ def insert_sensitivity_referential(source, csvfile):
def remove_sensitivity_referential(source):
- return db.session.execute(sa.delete(SensitivityRule).where(SensitivityRule.source == source))
+ whereclause = SensitivityRule.source == source
+ count_source = db.session.scalar(
+ sa.select(sa.func.count()).where(whereclause),
+ )
+ db.session.execute(sa.delete(SensitivityRule).where(whereclause))
+ return count_source
diff --git a/backend/geonature/tests/test_sensitivity.py b/backend/geonature/tests/test_sensitivity.py
index 9166d9fdde..0eaba67951 100644
--- a/backend/geonature/tests/test_sensitivity.py
+++ b/backend/geonature/tests/test_sensitivity.py
@@ -19,6 +19,35 @@
from ref_geo.models import LAreas, BibAreasTypes
from apptax.taxonomie.models import Taxref
from pypnnomenclature.models import TNomenclatures, BibNomenclaturesTypes
+from geonature.core.sensitivity.utils import remove_sensitivity_referential
+from click.testing import CliRunner
+
+
+@pytest.fixture
+def sensitivity_rule_source_name():
+ return "sensitivity_rules_test"
+
+
+@pytest.fixture(scope="function")
+def sensitivity_rules(sensitivity_rule_source_name):
+ with db.session.begin_nested():
+ cd_nom = db.session.scalar(sa.select(Taxref.cd_nom).limit(1))
+ sensitivity_nomenc_type = db.session.execute(
+ sa.select(BibNomenclaturesTypes).filter_by(mnemonique="SENSIBILITE")
+ ).scalar_one()
+ diffusion_maille = db.session.execute(
+ sa.select(TNomenclatures).filter_by(
+ id_type=sensitivity_nomenc_type.id_type, mnemonique="2"
+ )
+ ).scalar_one()
+ for _ in range(100):
+ rule = SensitivityRule(
+ cd_nom=cd_nom,
+ sensitivity_duration=5,
+ source=sensitivity_rule_source_name,
+ id_nomenclature_sensitivity=diffusion_maille.id_nomenclature,
+ )
+ db.session.add(rule)
@pytest.fixture(scope="function")
@@ -28,8 +57,14 @@ def clean_all_sensitivity_rules():
db.session.execute(sa.delete(SensitivityRule))
+@pytest.fixture
+def client_click():
+ return CliRunner()
+
+
@pytest.mark.usefixtures("client_class", "temporary_transaction", "clean_all_sensitivity_rules")
class TestSensitivity:
+
def test_get_id_nomenclature_sensitivity(self, app):
taxon = db.session.scalars(sa.select(Taxref)).first()
geom = WKTElement("POINT(6.15 44.85)", srid=4326)
@@ -363,3 +398,7 @@ def test_synthese_sensitivity(self, app, source):
s.date_max = date_obs
db.session.refresh(s)
assert s.id_nomenclature_sensitivity == nomenc_not_sensitive.id_nomenclature
+
+ def test_remove_sensitivy_rule(self, sensitivity_rules, sensitivity_rule_source_name):
+ res = remove_sensitivity_referential(sensitivity_rule_source_name)
+ assert res == 100
From c5443bce220c4391be5d00196279b1f209c7b02f Mon Sep 17 00:00:00 2001
From: jacquesfize
Date: Mon, 13 Jan 2025 16:25:59 +0100
Subject: [PATCH 04/13] fix(synthese): fix id_import form value disappearance
---
frontend/src/app/syntheseModule/synthese.component.ts | 1 -
1 file changed, 1 deletion(-)
diff --git a/frontend/src/app/syntheseModule/synthese.component.ts b/frontend/src/app/syntheseModule/synthese.component.ts
index 2faaafd4e1..599d34e01a 100644
--- a/frontend/src/app/syntheseModule/synthese.component.ts
+++ b/frontend/src/app/syntheseModule/synthese.component.ts
@@ -85,7 +85,6 @@ export class SyntheseComponent implements OnInit {
this._changeDetector.detectChanges();
this.loadAndStoreData(this._fs.formatParams());
- this._fs.processedDefaultFilters['id_import'] = null;
});
});
}
From 19010fa3a9ab55f0a90cb16658b1554389b4fcf0 Mon Sep 17 00:00:00 2001
From: Jacques Fize <4259846+jacquesfize@users.noreply.github.com>
Date: Mon, 13 Jan 2025 17:54:15 +0100
Subject: [PATCH 05/13] feat(commands): watch for .toml files changes when
dev_back running (#3316)
* feat(commands): dev-back now watch for geonature_config.toml changes
* extend to other toml files
---
backend/geonature/core/command/main.py | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/backend/geonature/core/command/main.py b/backend/geonature/core/command/main.py
index a5db10d0e4..dd2df1bc94 100644
--- a/backend/geonature/core/command/main.py
+++ b/backend/geonature/core/command/main.py
@@ -10,7 +10,7 @@
import click
from flask.cli import run_command
-from geonature.utils.env import GEONATURE_VERSION
+from geonature.utils.env import GEONATURE_VERSION, ROOT_DIR
from geonature.utils.module import iter_modules_dist
from geonature import create_app
from geonature.utils.config import config
@@ -19,6 +19,8 @@
create_frontend_module_config,
build_frontend,
)
+from os.path import join
+import glob
from flask.cli import FlaskGroup
@@ -57,7 +59,13 @@ def dev_back(ctx, host, port):
"""
if not environ.get("FLASK_DEBUG"):
environ["FLASK_DEBUG"] = "true"
- ctx.invoke(run_command, host=host, port=port)
+
+ ctx.invoke(
+ run_command,
+ host=host,
+ port=port,
+ extra_files=[file for file in glob.glob(join(ROOT_DIR, "config", "*.toml"))],
+ )
@main.command()
From ef7c9c34a0275500ebe5d0fd393e0ce2169e5d97 Mon Sep 17 00:00:00 2001
From: Etienne Delclaux <150020787+edelclaux@users.noreply.github.com>
Date: Wed, 15 Jan 2025 10:33:24 +0100
Subject: [PATCH 06/13] [CONFIG] Taxon sheet can be disabled + ENABLE_PROFILE
value now impact ENABLE_TAB_PROFILE (#3312)
* feat: add 'ENABLE_TAXON_SHEETS' option in 'SYNTHESE'
* feat: ENABLE_XXX to ENABLE_TAB_XXX for taxon sheet tab
* feat: add a relation between 'FRONTEND.ENABLE_PROFILES' and 'SYNTHESE.TAXON_SHEET.ENABLE_TAB_PROFILE'
Co-authored-by: Jacques Fize <4259846+jacquesfize@users.noreply.github.com>
* feat: add test for config processing
---------
Co-authored-by: jacquesfize
Co-authored-by: Jacques Fize <4259846+jacquesfize@users.noreply.github.com>
---
backend/geonature/core/gn_synthese/routes.py | 138 +++++++++---------
backend/geonature/tests/test_utils.py | 68 ++++++++-
backend/geonature/utils/config_schema.py | 15 +-
config/default_config.toml.example | 18 ++-
.../synthese-info-obs.component.html | 2 +-
.../synthese-list.component.html | 5 +-
.../src/app/syntheseModule/synthese.module.ts | 1 +
.../taxon-sheet/taxon-sheet.route.service.ts | 17 ++-
8 files changed, 182 insertions(+), 82 deletions(-)
diff --git a/backend/geonature/core/gn_synthese/routes.py b/backend/geonature/core/gn_synthese/routes.py
index f5cb9b0cab..de822af52f 100644
--- a/backend/geonature/core/gn_synthese/routes.py
+++ b/backend/geonature/core/gn_synthese/routes.py
@@ -82,6 +82,7 @@
VMTaxrefListForautocomplete,
)
+from geonature import app
routes = Blueprint("gn_synthese", __name__)
@@ -966,80 +967,87 @@ def general_stats(permissions):
return data
-@routes.route("/taxon_stats/", methods=["GET"])
-@permissions.check_cruved_scope("R", get_scope=True, module_code="SYNTHESE")
-@json_resp
-def taxon_stats(scope, cd_nom):
- """Return stats for a specific taxon"""
+## ############################################################################
+## TAXON SHEET ROUTES
+## ############################################################################
- area_type = request.args.get("area_type")
+if app.config["SYNTHESE"]["ENABLE_TAXON_SHEETS"]:
- if not area_type:
- raise BadRequest("Missing area_type parameter")
+ @routes.route("/taxon_stats/", methods=["GET"])
+ @permissions.check_cruved_scope("R", get_scope=True, module_code="SYNTHESE")
+ @json_resp
+ def taxon_stats(scope, cd_nom):
+ """Return stats for a specific taxon"""
- # Ensure area_type is valid
- valid_area_types = (
- db.session.query(BibAreasTypes.type_code)
- .distinct()
- .filter(BibAreasTypes.type_code == area_type)
- .scalar()
- )
- if not valid_area_types:
- raise BadRequest("Invalid area_type")
-
- # Subquery to fetch areas based on area_type
- areas_subquery = (
- select([LAreas.id_area])
- .where(LAreas.id_type == BibAreasTypes.id_type)
- .where(BibAreasTypes.type_code == area_type)
- .alias("areas")
- )
- cd_ref = db.session.scalar(select(Taxref.cd_ref).where(Taxref.cd_nom == cd_nom))
- taxref_cd_nom_list = db.session.scalars(select(Taxref.cd_nom).where(Taxref.cd_ref == cd_ref))
+ area_type = request.args.get("area_type")
- # Main query to fetch stats
- query = (
- select(
- [
- func.count(distinct(Synthese.id_synthese)).label("observation_count"),
- func.count(distinct(Synthese.observers)).label("observer_count"),
- func.count(distinct(areas_subquery.c.id_area)).label("area_count"),
- func.min(Synthese.altitude_min).label("altitude_min"),
- func.max(Synthese.altitude_max).label("altitude_max"),
- func.min(Synthese.date_min).label("date_min"),
- func.max(Synthese.date_max).label("date_max"),
- ]
+ if not area_type:
+ raise BadRequest("Missing area_type parameter")
+
+ # Ensure area_type is valid
+ valid_area_types = (
+ db.session.query(BibAreasTypes.type_code)
+ .distinct()
+ .filter(BibAreasTypes.type_code == area_type)
+ .scalar()
)
- .select_from(
- sa.join(
- Synthese,
- CorAreaSynthese,
- Synthese.id_synthese == CorAreaSynthese.id_synthese,
- )
- .join(areas_subquery, CorAreaSynthese.id_area == areas_subquery.c.id_area)
- .join(LAreas, CorAreaSynthese.id_area == LAreas.id_area)
- .join(BibAreasTypes, LAreas.id_type == BibAreasTypes.id_type)
+ if not valid_area_types:
+ raise BadRequest("Invalid area_type")
+
+ # Subquery to fetch areas based on area_type
+ areas_subquery = (
+ select(LAreas.id_area)
+ .where(LAreas.id_type == BibAreasTypes.id_type, BibAreasTypes.type_code == area_type)
+ .alias("areas")
+ )
+ cd_ref = db.session.scalar(select(Taxref.cd_ref).where(Taxref.cd_nom == cd_nom))
+ taxref_cd_nom_list = db.session.scalars(
+ select(Taxref.cd_nom).where(Taxref.cd_ref == cd_ref)
)
- .where(Synthese.cd_nom.in_(taxref_cd_nom_list))
- )
- synthese_query_obj = SyntheseQuery(Synthese, query, {})
- synthese_query_obj.filter_query_with_cruved(g.current_user, scope)
- result = DB.session.execute(synthese_query_obj.query)
- synthese_stats = result.fetchone()
+ # Main query to fetch stats
+ query = (
+ select(
+ [
+ func.count(distinct(Synthese.id_synthese)).label("observation_count"),
+ func.count(distinct(Synthese.observers)).label("observer_count"),
+ func.count(distinct(areas_subquery.c.id_area)).label("area_count"),
+ func.min(Synthese.altitude_min).label("altitude_min"),
+ func.max(Synthese.altitude_max).label("altitude_max"),
+ func.min(Synthese.date_min).label("date_min"),
+ func.max(Synthese.date_max).label("date_max"),
+ ]
+ )
+ .select_from(
+ sa.join(
+ Synthese,
+ CorAreaSynthese,
+ Synthese.id_synthese == CorAreaSynthese.id_synthese,
+ )
+ .join(areas_subquery, CorAreaSynthese.id_area == areas_subquery.c.id_area)
+ .join(LAreas, CorAreaSynthese.id_area == LAreas.id_area)
+ .join(BibAreasTypes, LAreas.id_type == BibAreasTypes.id_type)
+ )
+ .where(Synthese.cd_nom.in_(taxref_cd_nom_list))
+ )
- data = {
- "cd_ref": cd_nom,
- "observation_count": synthese_stats["observation_count"],
- "observer_count": synthese_stats["observer_count"],
- "area_count": synthese_stats["area_count"],
- "altitude_min": synthese_stats["altitude_min"],
- "altitude_max": synthese_stats["altitude_max"],
- "date_min": synthese_stats["date_min"],
- "date_max": synthese_stats["date_max"],
- }
+ synthese_query_obj = SyntheseQuery(Synthese, query, {})
+ synthese_query_obj.filter_query_with_cruved(g.current_user, scope)
+ result = DB.session.execute(synthese_query_obj.query)
+ synthese_stats = result.fetchone()
+
+ data = {
+ "cd_ref": cd_nom,
+ "observation_count": synthese_stats["observation_count"],
+ "observer_count": synthese_stats["observer_count"],
+ "area_count": synthese_stats["area_count"],
+ "altitude_min": synthese_stats["altitude_min"],
+ "altitude_max": synthese_stats["altitude_max"],
+ "date_min": synthese_stats["date_min"],
+ "date_max": synthese_stats["date_max"],
+ }
- return data
+ return data
@routes.route("/taxons_tree", methods=["GET"])
diff --git a/backend/geonature/tests/test_utils.py b/backend/geonature/tests/test_utils.py
index f3055e97da..0e4559d292 100644
--- a/backend/geonature/tests/test_utils.py
+++ b/backend/geonature/tests/test_utils.py
@@ -8,10 +8,14 @@
from marshmallow.exceptions import ValidationError
+#############################################################################
+# BASIC TEMPLATE CONFIG FILE
+#############################################################################
+
TEMPLATE_CONFIG_FILE = """
SQLALCHEMY_DATABASE_URI = "postgresql://monuser:monpassachanger@localhost:5432/mabase"
URL_APPLICATION = 'http://url.com/geonature'
-API_ENDPOINT = 'http://url.com/geonature/api'
+API_ENDPOINT = 'http://url.com/geonature/api'
SECRET_KEY = 'super secret key'
@@ -37,6 +41,44 @@
[MEDIAS]
"""
+#############################################################################
+# TAXON SHEET CONFIG FILE
+#############################################################################
+
+TEMPLATE_TAXON_SHEET_CONFIG_FILE = """
+ SQLALCHEMY_DATABASE_URI = "postgresql://monuser:monpassachanger@localhost:5432/mabase"
+ URL_APPLICATION = 'http://url.com/geonature'
+ API_ENDPOINT = 'http://url.com/geonature/api'
+
+ SECRET_KEY = 'super secret key'
+
+ DEFAULT_LANGUAGE=fr
+ [HOME]
+ TITLE = "Bienvenue dans GeoNature"
+ INTRODUCTION = "Texte d'introduction, configurable pour le modifier régulièrement ou le masquer"
+ FOOTER = ""
+
+ # Configuration liée aux ID de BDD
+ [BDD]
+
+ # Configuration générale du frontend
+ [FRONTEND]
+ ENABLE_PROFILES={ENABLE_PROFILES}
+
+ # Configuration de la Synthese
+ [SYNTHESE]
+ ENABLE_TAXON_SHEETS={ENABLE_TAXON_SHEETS}
+ [SYNTHESE.TAXON_SHEET]
+ ENABLE_TAB_TAXONOMY={ENABLE_TAB_TAXONOMY}
+ ENABLE_TAB_PROFILE={ENABLE_TAB_PROFILE}
+
+ # Configuration cartographique
+ [MAPCONFIG]
+
+ # Configuration médias
+ [MEDIAS]
+ """
+
@pytest.mark.usefixtures("temporary_transaction")
class TestUtils:
@@ -59,3 +101,27 @@ def test_utilstoml(self):
with pytest.raises(ConfigError):
load_and_validate_toml(f.name, GnPySchemaConf)
+
+ @pytest.mark.parametrize(
+ "enable_profiles,enable_tab_profile,expected_enable_tab_profile",
+ [(True, True, True), (True, False, False), (False, False, False), (False, True, False)],
+ )
+ def test_config_profiles_consistency(
+ self, enable_profiles, enable_tab_profile, expected_enable_tab_profile
+ ):
+
+ profiles_config = TEMPLATE_TAXON_SHEET_CONFIG_FILE.format(
+ ENABLE_TAXON_SHEETS=True,
+ ENABLE_TAB_TAXONOMY=True,
+ ENABLE_PROFILES=enable_profiles,
+ ENABLE_TAB_PROFILE=enable_tab_profile,
+ )
+
+ with tempfile.NamedTemporaryFile(mode="w") as f:
+ f.write(profiles_config)
+ with pytest.raises(ConfigError):
+ config = load_and_validate_toml(f.name, GnPySchemaConf)
+ assert (
+ config["SYNTHESE"]["TAXON_SHEET"]["ENABLE_TAB_PROFILE"]
+ == expected_enable_tab_profile
+ )
diff --git a/backend/geonature/utils/config_schema.py b/backend/geonature/utils/config_schema.py
index 4d21312bba..d6c9574263 100644
--- a/backend/geonature/utils/config_schema.py
+++ b/backend/geonature/utils/config_schema.py
@@ -279,8 +279,8 @@ class ExportObservationSchema(Schema):
class TaxonSheet(Schema):
# --------------------------------------------------------------------
# SYNTHESE - TAXON_SHEET
- ENABLE_PROFILE = fields.Boolean(load_default=True)
- ENABLE_TAXONOMY = fields.Boolean(load_default=True)
+ ENABLE_TAB_PROFILE = fields.Boolean(load_default=True)
+ ENABLE_TAB_TAXONOMY = fields.Boolean(load_default=True)
class Synthese(Schema):
@@ -439,6 +439,7 @@ class Synthese(Schema):
# --------------------------------------------------------------------
# SYNTHESE - TAXON_SHEET
+ ENABLE_TAXON_SHEETS = fields.Boolean(load_default=True)
TAXON_SHEET = fields.Nested(TaxonSheet, load_default=TaxonSheet().load({}))
@pre_load
@@ -612,3 +613,13 @@ def insert_module_config(self, data, **kwargs):
continue
data[module_code] = get_module_config(dist)
return data
+
+ @post_load
+ def profile_display_coherence(self, data, **kwargs):
+ if (
+ data["SYNTHESE"]["TAXON_SHEET"]["ENABLE_TAB_PROFILE"]
+ and not data["FRONTEND"]["ENABLE_PROFILES"]
+ ):
+ data["SYNTHESE"]["TAXON_SHEET"]["ENABLE_TAB_PROFILE"] = False
+
+ return data
diff --git a/config/default_config.toml.example b/config/default_config.toml.example
index c6a2e164c6..773c0d2459 100644
--- a/config/default_config.toml.example
+++ b/config/default_config.toml.example
@@ -441,12 +441,14 @@ MEDIA_CLEAN_CRONTAB = "0 1 * * *"
# Seulement les données de présence
cd_nomenclature_observation_status = ['Pr']
+ # Activer l'affichage des informations liées à la fiche taxon dans la synthèse
+ ENABLE_TAXON_SHEETS = true
[SYNTHESE.TAXON_SHEET]
# Options dédiées à la fiche taxon
# Permet d'activer ou non l'onglet "Profil"
- ENABLE_PROFILE = true
+ ENABLE_TAB_PROFILE = true
# Permet d'activer ou non l'onglet "Taxonomie"
- ENABLE_TAXONOMY = true
+ ENABLE_TAB_TAXONOMY = true
# Gestion des demandes d'inscription
[ACCOUNT_MANAGEMENT]
@@ -623,8 +625,8 @@ MEDIA_CLEAN_CRONTAB = "0 1 * * *"
# Encodage des fichiers importés autorisées
ENCODAGE = ["UTF-8"]
- # Bounding box des données de l'instance.
- # Utilisé pour lever des warning lorsque les données sont en dehors.
+ # Bounding box des données de l'instance.
+ # Utilisé pour lever des warning lorsque les données sont en dehors.
# Format: [XMIN, YMIN, XMAX, YMAX]
# Par défaut: France métropolitaine incluant la Corse
INSTANCE_BOUNDING_BOX = [-5.0, 41.0, 10.0, 51.15]
@@ -643,7 +645,7 @@ MEDIA_CLEAN_CRONTAB = "0 1 * * *"
# SRID autorisés pour les fichiers en entrée
SRID = [
- {name = "WGS84", code = 4326},
+ {name = "WGS84", code = 4326},
{name = "Lambert93", code = 2154}
]
# Extensions autorisées (seul le csv est accepté actuellement)
@@ -655,7 +657,7 @@ MEDIA_CLEAN_CRONTAB = "0 1 * * *"
# Si le mapping des valeurs est désactivé, specifier l'identifiant du mapping qui doit être utilisé
DEFAULT_VALUE_MAPPING_ID = 3
- # rempli les valeurs de nomenclature erroné par la valeur par defaut
+ # rempli les valeurs de nomenclature erroné par la valeur par defaut
# Leve un warning et non une erreur sur les lignes concernées
FILL_MISSING_NOMENCLATURE_WITH_DEFAULT_VALUE = false
@@ -676,7 +678,7 @@ MEDIA_CLEAN_CRONTAB = "0 1 * * *"
# Customiser le nom du fichier de rapport de l'import
# Pour indiquer des données liés à l'import dans le nom du fichier ajouter le nom de la variable
- # contenant cette dernière. Les variables suivantes sont accessibles :
+ # contenant cette dernière. Les variables suivantes sont accessibles :
# - date_create_import -> date de création de l'import
# - dataset.dataset_name -> nom du jeu de données de destination
# - dataset.active -> Si le jeu de données de destination est actif
@@ -703,7 +705,7 @@ MEDIA_CLEAN_CRONTAB = "0 1 * * *"
# Id d'une liste de taxons permettant de restreindre l'import d'observations de taxons comprises dans cette dernière
- # Lève une exception si un taxon n'appartenant pas à liste indiquée apparaît dans les donnés importées.
+ # Lève une exception si un taxon n'appartenant pas à liste indiquée apparaît dans les donnés importées.
ID_LIST_TAXA_RESTRICTION = fields.Integer(load_default=None)
# URL d'accès au module d'import
diff --git a/frontend/src/app/shared/syntheseSharedModule/synthese-info-obs/synthese-info-obs.component.html b/frontend/src/app/shared/syntheseSharedModule/synthese-info-obs/synthese-info-obs.component.html
index 5e0dfbcef3..876dfde2c8 100644
--- a/frontend/src/app/shared/syntheseSharedModule/synthese-info-obs/synthese-info-obs.component.html
+++ b/frontend/src/app/shared/syntheseSharedModule/synthese-info-obs/synthese-info-obs.component.html
@@ -191,7 +191,7 @@
{%- endfor %}
diff --git a/frontend/src/app/metadataModule/af/af-card.component.html b/frontend/src/app/metadataModule/af/af-card.component.html
index 1a812625f2..8b6aff2f33 100644
--- a/frontend/src/app/metadataModule/af/af-card.component.html
+++ b/frontend/src/app/metadataModule/af/af-card.component.html
@@ -421,12 +421,6 @@ Jeux de données associés
{{ dataset.unique_dataset_id }}
- 0">
- Nombre d'observations dans la Synthèse : {{ dataset['obs_count'] }}
-
-
- Nombre d'habitats dans occhab : {{ dataset['hab_count'] }}
-
From e0790c6746ed636d7719a306a10d1bd3153ac99a Mon Sep 17 00:00:00 2001
From: Jacques Fize <4259846+jacquesfize@users.noreply.github.com>
Date: Wed, 15 Jan 2025 12:31:22 +0100
Subject: [PATCH 08/13] refact(sensitivity): instead of count query use
rowcount to get number of removed sensitivity rule (#3323)
---
backend/geonature/core/sensitivity/utils.py | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/backend/geonature/core/sensitivity/utils.py b/backend/geonature/core/sensitivity/utils.py
index 42106d0151..bf4a881884 100644
--- a/backend/geonature/core/sensitivity/utils.py
+++ b/backend/geonature/core/sensitivity/utils.py
@@ -132,8 +132,4 @@ def insert_sensitivity_referential(source, csvfile):
def remove_sensitivity_referential(source):
whereclause = SensitivityRule.source == source
- count_source = db.session.scalar(
- sa.select(sa.func.count()).where(whereclause),
- )
- db.session.execute(sa.delete(SensitivityRule).where(whereclause))
- return count_source
+ return db.session.execute(sa.delete(SensitivityRule).where(whereclause)).rowcount
From 0f031f4a855460896ba95af55e09ea62a0251477 Mon Sep 17 00:00:00 2001
From: Jacques Fize <4259846+jacquesfize@users.noreply.github.com>
Date: Wed, 15 Jan 2025 12:47:59 +0100
Subject: [PATCH 09/13] fix(login): fix bad login redirection when request
admin panel (#3322)
---
backend/geonature/core/errors.py | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/backend/geonature/core/errors.py b/backend/geonature/core/errors.py
index cdf2a45ca5..cad5bc5ab8 100644
--- a/backend/geonature/core/errors.py
+++ b/backend/geonature/core/errors.py
@@ -26,13 +26,7 @@ def handle_unauthenticated_request(e):
else:
base_url = current_app.config["URL_APPLICATION"]
login_path = "/#/login" # FIXME: move in config
- api_endpoint = current_app.config["API_ENDPOINT"]
- url_application = current_app.config["URL_APPLICATION"]
- if urlparse(api_endpoint).netloc == urlparse(url_application).netloc:
- next_url = request.full_path
- else:
- next_url = request.url
- query_string = urlencode({"next": next_url})
+ query_string = urlencode({"next": request.url})
return redirect(f"{base_url}{login_path}?{query_string}")
From 36eaf474d688de89bed70a1ffde8f4d3577ccd5c Mon Sep 17 00:00:00 2001
From: Camille Monchicourt
Date: Wed, 15 Jan 2025 13:52:25 +0100
Subject: [PATCH 10/13] feat(doc): complete validation and sensitivity
documentation (#3317)
---
docs/admin-manual.rst | 14 ++++++++------
docs/sensitivity.rst | 6 ++++--
2 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/docs/admin-manual.rst b/docs/admin-manual.rst
index 4afedc6090..539e0e9cee 100644
--- a/docs/admin-manual.rst
+++ b/docs/admin-manual.rst
@@ -521,7 +521,7 @@ Pour chaque taxon (cd_ref) disposant de données dans la vue ``gn_profiles.v_syn
Ces profils sont déclinés sur :
-- Le module de validation permet d'attirer l'attention des validateurs sur les données qui sortent du "cadre" déjà connu pour le taxon considéré, et d'apporter des éléments de contexte en complément de la donnée en cours de validation
+- Le module Validation permet d'attirer l'attention des validateurs sur les données qui sortent du "cadre" déjà connu pour le taxon considéré, et d'apporter des éléments de contexte en complément de la donnée en cours de validation
- Le module Synthèse (fiche d'information, onglet validation) permet d'apporter des éléments de contexte en complément des données brutes consultées
- Le module Occtax permet d'alerter les utilisateurs lors de la saisie de données qui sortent du "cadre" déjà connu pour un taxon considéré
- Le processus de validation automatique permet de valider automatiquement les observations respectant le profil de taxons (non activé par défaut).
@@ -2318,11 +2318,11 @@ D'autres élements sont paramètrables dans le module Synthese. La liste complè
Module VALIDATION
-----------------
-Le module VALIDATION, integré depuis la version 2.1.0 dans le coeur de GeoNature permet de valider des occurrences de taxon en s'appuyant sur les données présentes dans la SYNTHESE. Le module s'appuie sur le `standard Validation `_ du SINP et sur ses `nomenclatures officiels `_.
+Le module VALIDATION, integré depuis la version 2.1.0 dans le coeur de GeoNature (mais optionnel) permet de valider des occurrences de taxon en s'appuyant sur les données présentes dans la SYNTHESE. Le module s'appuie sur le standard Validation du SINP et sur ses `nomenclatures officielles `_.
-Afin de valider une occurrence, celle-ci doit impérativement avoir un UUID. En effet, la validation est stockée en BDD dans la table transversale ``gn_commons.t_validations`` (`voir doc `_ ) qui impose la présence de cet UUID.
+Afin de valider une occurrence de taxons, celle-ci doit impérativement avoir un UUID. En effet, la validation est stockée en BDD dans la table transversale ``gn_commons.t_validations`` (`voir doc `_ ) qui impose la présence de cet UUID.
-La table ``gn_commons.t_validations`` contient l'ensemble de l'historique de validation des occurrences. Pour une même occurrence (identifiée par un UUID unique) on peut donc retrouver plusieurs lignes dans la table correspondant au différents statuts de validation attribués à cet occurrence dans le temps.
+La table ``gn_commons.t_validations`` contient l'ensemble de l'historique de validation des occurrences de taxons. Pour une même occurrence (identifiée par un UUID unique) on peut donc retrouver plusieurs lignes dans la table correspondant aux différents statuts de validation attribués à cette occurrence dans le temps.
La vue ``gn_commons.v_latest_validation`` permet de récupérer le dernier statut de validation d'une occurrence.
@@ -2353,10 +2353,10 @@ Gestion de l'affichage des colonnes de la liste via le paramètre ``COLUMN_LIST`
E-mail
``````
-Il est possible de personnaliser le message du mail envoyé aux observateurs.
+Il est possible de personnaliser le message de l'email envoyé aux observateurs d'une observation quand on clique sur le bouton dédié à cela depuis la fiche détail d'une observation.
Pour ce faire il faut modifier les paramètres ``MAIL_BODY`` et ``MAIL_SUBJECT``
-Pour afficher dans le mail des données relatives à l'observation ou au taxon il faut respecter la syntaxe suivante:
+Pour afficher dans l'email des données relatives à l'observation ou au taxon il faut respecter la syntaxe suivante :
``${ d.NOM_PROPRIETE }``
Liste des propriétés disponibles :
@@ -2367,6 +2367,8 @@ Liste des propriétés disponibles :
- tous les champs de la synthèse (acquisition_framework, altitude_max, altitude_min, bio_status, blurring, cd_hab, cd_nom, comment_context, comment_description, date_min, depth_max, depth_min, determiner, diffusion_level, digital_proof, entity_source_pk_value, exist_proof, grp_method, grp_typ, last_action, life_stage, meta_create_date, meta_update_date, meta_v_taxref, meta_validation_date, nat_obj_geo, naturalness, nom_cite, non_digital_proof, obj_count, obs_technique, observation_status, observers, occ_behaviour, occ_stat_biogeo, place_name, precision, sample_number_proof, sensitivity, sex, source, type_count, unique_id_sinp, unique_id_sinp_grp, valid_status, validation_comment)
- tous les champs du taxon (cd_nom, cd_ref, cd_sup, cd_taxsup, regne, ordre, classe, famille, group1_inpn, group2_inpn, id_rang, nom_complet, nom_habitat, nom_rang, nom_statut, nom_valide, nom_vern)
+Il est aussi possible de modifier la structure du message de notification envoyé automatiquement à un observateur quand une de ses observations voit son statut de validation modifié, dans la table `gn_notifications.bib_notifications_templates`.
+
Validation automatique
""""""""""""""""""""""
diff --git a/docs/sensitivity.rst b/docs/sensitivity.rst
index d32e303209..13f4983946 100644
--- a/docs/sensitivity.rst
+++ b/docs/sensitivity.rst
@@ -73,8 +73,10 @@ que l’un des critères ou l’une des zones correspond à l’observation.
Si des règles de sensibilité sont définies avec des conditions de critères
sur une nomenclature (Statut biologique ou Comportement),
alors ces règles sont appliquées aussi si la nomenclature n'est pas renseignée
-(par principe de précaution), en dupliquant les règles pour les valeurs de
-nomenclature "Non renseigné", "Ne sait pas", "Indéterminé",... (https://github.com/PnX-SI/GeoNature/blob/30c27266495b4affc635f79748c9984feb81a6d7/backend/geonature/core/sensitivity/utils.py#L37-L54).
+(par principe de précaution), en associant aussi des critères à ces règles
+(dans la table `gn_sensitivity.cor_sensitivity_criteria`) pour les valeurs
+de nomenclature "Non renseigné", "Ne sait pas", "Indéterminé",...
+(https://github.com/PnX-SI/GeoNature/blob/30c27266495b4affc635f79748c9984feb81a6d7/backend/geonature/core/sensitivity/utils.py#L37-L54).
Certaines règles sont définies non pas pour une espèce donnée mais pour un
rang supérieur. Ces règles sont artificiellement dupliquées pour chaques espèces
From 6ce72e41d0a7f59d9e3fe2f11b530933500e0db1 Mon Sep 17 00:00:00 2001
From: Jacques Fize <4259846+jacquesfize@users.noreply.github.com>
Date: Wed, 15 Jan 2025 13:52:48 +0100
Subject: [PATCH 11/13] bump : taxhub 2.1.1 (#3321)
---
backend/dependencies/TaxHub | 2 +-
backend/requirements-dependencies.in | 2 +-
backend/requirements-dev.txt | 6 ++++--
backend/requirements.txt | 8 +++++---
4 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/backend/dependencies/TaxHub b/backend/dependencies/TaxHub
index 8e36e7e39a..1e505008fa 160000
--- a/backend/dependencies/TaxHub
+++ b/backend/dependencies/TaxHub
@@ -1 +1 @@
-Subproject commit 8e36e7e39a3df2e1e1c1bff47038d29e21b5011d
+Subproject commit 1e505008fa74b9cdc6ccf096db00a5b6dfd8568e
diff --git a/backend/requirements-dependencies.in b/backend/requirements-dependencies.in
index be8cd5e56f..a70d9dca40 100644
--- a/backend/requirements-dependencies.in
+++ b/backend/requirements-dependencies.in
@@ -3,5 +3,5 @@ pypnnomenclature>=1.6.4,<2
pypn_habref_api>=0.4.1,<1
utils-flask-sqlalchemy-geo>=0.3.2,<1
utils-flask-sqlalchemy>=0.4.1,<1
-taxhub==2.1.0
+taxhub==2.1.1
pypn-ref-geo>=1.5.3,<2
diff --git a/backend/requirements-dev.txt b/backend/requirements-dev.txt
index 9e231c07b8..b628e5b45e 100644
--- a/backend/requirements-dev.txt
+++ b/backend/requirements-dev.txt
@@ -104,7 +104,7 @@ cligj==0.7.2
# via fiona
contourpy==1.3.0
# via bokeh
-cryptography==44.0.0
+cryptography==43.0.3
# via authlib
cssselect2==0.7.0
# via weasyprint
@@ -180,7 +180,9 @@ flask-wtf==1.2.2
# -r requirements-common.in
# usershub
fonttools[woff]==4.55.3
- # via weasyprint
+ # via
+ # fonttools
+ # weasyprint
geoalchemy2==0.16.0
# via utils-flask-sqlalchemy-geo
geojson==3.2.0
diff --git a/backend/requirements.txt b/backend/requirements.txt
index 36b85df8b9..683da3c34d 100644
--- a/backend/requirements.txt
+++ b/backend/requirements.txt
@@ -72,7 +72,7 @@ cligj==0.7.2
# via fiona
contourpy==1.3.0
# via bokeh
-cryptography==44.0.0
+cryptography==43.0.3
# via authlib
cssselect2==0.7.0
# via weasyprint
@@ -143,7 +143,9 @@ flask-weasyprint==1.1.0
flask-wtf==1.2.2
# via -r requirements-common.in
fonttools[woff]==4.55.3
- # via weasyprint
+ # via
+ # fonttools
+ # weasyprint
geoalchemy2==0.16.0
# via utils-flask-sqlalchemy-geo
geojson==3.2.0
@@ -312,7 +314,7 @@ sqlalchemy==1.4.54
# utils-flask-sqlalchemy
# utils-flask-sqlalchemy-geo
# wtforms-sqlalchemy
-taxhub==2.1.0
+taxhub==2.1.1
# via
# -r requirements-dependencies.in
# pypnnomenclature
From 03322ed7f65cb62503f4262a0d50aabe3445cca3 Mon Sep 17 00:00:00 2001
From: Camille Monchicourt
Date: Wed, 15 Jan 2025 14:11:52 +0100
Subject: [PATCH 12/13] Changelog 2.15.2
---
docs/CHANGELOG.md | 24 +++++++++++++++++++++---
1 file changed, 21 insertions(+), 3 deletions(-)
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index ff941afdb6..047160207a 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -1,14 +1,32 @@
# CHANGELOG
+## 2.15.2 (2025-01-15)
+
+**🚀 Nouveautés**
+
+- [Accueil] Optimisation du calcul des statistiques (#3309, par @dba-sig-sfepm et @jacquesfize)
+- [Profils de taxon] Amélioration, homogénéisation et mise en cohérence des paramètres d'activation ou non des profils de taxons (#3311, par @edelclaux)
+- [TaxHub] Mise à jour de TaxHub en version 2.1.1 (#3321, par @amandine-sahl et @jacquesfize)
+- [Documentation] Compléments de la documentation du module Validation et de la sensibilité (#3317, par @camillemonchicourt)
+- [Développement] Redémarrage automatique du backend quand un fichier de configuration `.toml` est modifié (#3316, par @jacquesfize)
+
+**🐛 Corrections**
+
+- [Accueil] Correction de la prise en compte de la portée des permissions dans le calcul des statistiques (#3166, par @jacquesfize et @edelclaux)
+- [Sensibilité] Correction du comptage du nombre de règles supprimées dans la commande `geonature sensitivity remove-referential` (#3323, par @jacquesfize)
+- [Synthèse] Correction de la disparition du filtre par `id_import` après l'affichage d'une fiche observation (par @jacquesfize)
+- [Authentification] Correction des redirections du module Admin lors de l'authentification (#3322, par @jacquesfize)
+- Correction d'une régression de performances de la récupération des JDD, introduite dans la 2.15.1 (#3320, par @Pierre-Narcisi)
+
## 2.15.1 (2025-01-10)
**🚀 Nouveautés**
-- [Métadonnées]Amélioration de la recherche libre des métadonnées en cherchant chaque mot indépendamment (#3295, par @jbrieuclp)
+- [Métadonnées] Amélioration de la recherche libre des métadonnées en cherchant chaque mot indépendamment (#3295, par @jbrieuclp)
- [FicheTaxon] Amélioration de l'affichage de la photo du taxon sur les fiches taxon (#3287, par @edelclaux)
- [Documentation] Conversion du changelog en format markdown (#3297, par @jacquesfize)
- [Documentation] Complément et mise en forme de la documentation et publication sur Readthedocs (#3306, par @jacquesfize)
-- [Dévelopement] Ajout d'un fichier `Makefile` pour faciliter l'usage des commandes de développement (#3300, par @jacquesfize & @edelclaux)
+- [Développement] Ajout d'un fichier `Makefile` pour faciliter l'usage des commandes de développement (#3300, par @jacquesfize & @edelclaux)
- [Installation] Ajout des nouvelles mailles INPN lors de l'installation de GeoNature (#3293, par @jacquesfize)
**🐛 Corrections**
@@ -17,7 +35,7 @@
- [Discussions] Correction des performances de la requête de récupération des discussions (#3307, par @jacquesfize)
- [Métadonnées] Correction du nombre de taxons sur les fiches des cadres d'acquisition (#3228, par @jacquesfize)
- [Authentification] Correction des redirections lors de l'authentification (#3305, par @jacquesfize)
-- [Import] Correction de la selection automatique du JDD lors de l'import depuis la fiche d'un JDD (#3293, par @jacquesfize)
+- [Import] Correction de la sélection automatique du JDD lors de l'import depuis la fiche d'un JDD (#3293, par @jacquesfize)
- [Import] Correction de la mise à jour des mappings publics (#3293, par @jacquesfize)
- [Import] Correction de la sauvegarde des checkbox dans le mapping des champs (#3293, par @Pierre-Narcisi)
- [Import] Correction de la sélection des champs `auto_generate` (#3293, par @Pierre-Narcisi)
From 3361d27ccd57b0b8fc2b41b406e25605158bf161 Mon Sep 17 00:00:00 2001
From: Jacques Fize <4259846+jacquesfize@users.noreply.github.com>
Date: Wed, 15 Jan 2025 14:40:03 +0100
Subject: [PATCH 13/13] fix(general_stats): re-enable cruved on the stats
computed (#3327)
* fix(general_stats): fix problem where cruved had no impact on the stats computed
---
backend/geonature/core/gn_synthese/routes.py | 19 +++++++++----------
.../gn_synthese/utils/query_select_sqla.py | 3 ++-
.../tests/benchmarks/test_benchmark_home.py | 6 ++++++
3 files changed, 17 insertions(+), 11 deletions(-)
diff --git a/backend/geonature/core/gn_synthese/routes.py b/backend/geonature/core/gn_synthese/routes.py
index de822af52f..3df6e82d7c 100644
--- a/backend/geonature/core/gn_synthese/routes.py
+++ b/backend/geonature/core/gn_synthese/routes.py
@@ -943,20 +943,19 @@ def general_stats(permissions):
results = {"nb_allowed_datasets": nb_allowed_datasets}
queries = {
- "nb_obs": select(
- func.count(Synthese.id_synthese),
- ),
+ "nb_obs": select(Synthese.id_synthese),
"nb_distinct_species": select(
- func.count(func.distinct(Synthese.cd_nom)),
- ),
- "nb_distinct_observer": select(
- func.count(func.distinct(Synthese.observers)),
+ func.distinct(Synthese.cd_nom),
),
+ "nb_distinct_observer": select(func.distinct(Synthese.observers)),
}
+
for key, query in queries.items():
synthese_query = SyntheseQuery(Synthese, query, {})
- synthese_query.filter_query_with_cruved(g.current_user, permissions)
- results[key] = db.session.scalar(synthese_query.query)
+ synthese_query.filter_query_with_permissions(g.current_user, permissions)
+ results[key] = db.session.scalar(
+ sa.select(func.count("*")).select_from(synthese_query.query)
+ )
data = {
"nb_data": results["nb_obs"],
@@ -1561,7 +1560,7 @@ def list_all_reports(permissions):
# On vérifie les permissions en lecture sur la synthese
synthese_query = select(Synthese.id_synthese).select_from(Synthese)
synthese_query_obj = SyntheseQuery(Synthese, synthese_query, {})
- synthese_query_obj.filter_query_with_cruved(g.current_user, permissions)
+ synthese_query_obj.filter_query_with_permissions(g.current_user, permissions)
cte_synthese = synthese_query_obj.query.cte("cte_synthese")
query = query.where(TReport.id_synthese == cte_synthese.c.id_synthese)
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 732d0b5df2..6496c0888d 100644
--- a/backend/geonature/core/gn_synthese/utils/query_select_sqla.py
+++ b/backend/geonature/core/gn_synthese/utils/query_select_sqla.py
@@ -204,10 +204,11 @@ def filter_query_with_permissions(self, user, permissions):
where_clause = self.build_permissions_filter(user=user, permissions=permissions)
self.query = self.query.where(where_clause)
- def filter_query_with_cruved(self, user, scope):
+ def filter_query_with_cruved(self, user, scope: int):
"""
Filter the query with the cruved authorization of a user
"""
+ assert isinstance(scope, int)
if scope in (1, 2):
# get id synthese where user is observer
subquery_observers = (
diff --git a/backend/geonature/tests/benchmarks/test_benchmark_home.py b/backend/geonature/tests/benchmarks/test_benchmark_home.py
index 0b4bd842aa..ba5ae4303e 100644
--- a/backend/geonature/tests/benchmarks/test_benchmark_home.py
+++ b/backend/geonature/tests/benchmarks/test_benchmark_home.py
@@ -18,6 +18,12 @@
class TestBenchmarkHome:
test_general_stats = BenchmarkTest(
+ CLIENT_GET,
+ [CLater("""url_for("gn_synthese.general_stats")""")],
+ dict(user_profile="user", fixtures=[]),
+ )()
+
+ test_general_stats_admin = BenchmarkTest(
CLIENT_GET,
[CLater("""url_for("gn_synthese.general_stats")""")],
dict(user_profile="admin_user", fixtures=[]),