Skip to content

Commit 7ea4d98

Browse files
authored
Merge pull request #486 from PnX-SI/dev
Dev
2 parents efe03dd + fc79086 commit 7ea4d98

26 files changed

Lines changed: 1982 additions & 1113 deletions

CHANGELOG.md

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# CHANGELOG
22

3+
## 1.3.3 - 2026-04-15
4+
5+
> [!WARNING]
6+
> **Version 1.3.x will be the latest release compatible with python 3.9**
7+
8+
### :bug: Fixes
9+
10+
* Fix taxa set to undefined within validation module when using taxa `select` type input.
11+
* Fix missing translations on validation modal button (fix [#467 issue comment](https://github.com/PnX-SI/GeoNature-citizen/issues/467#issuecomment-4163231028)).
12+
* Enable `0` value in count input (fix #472).
13+
* Improve documentation for validation module (fix #467)
14+
15+
316
## 1.3.2 - 2025-12-01
417

518
> [!WARNING]
@@ -35,12 +48,12 @@
3548
* Taxons search in programs is now based on observed taxons
3649
* If no photo is added to an observation and if an image is available for this to taxa in TaxHub, then this image is displayed on the Congrats popup
3750
* Observation name displayed in program observations list is based on this order:
38-
* 'nom_francais'
39-
* 'taxref.nom_vern'
40-
* 'taxref.nom_valide'
41-
* 'taxref.nom_complet'
42-
* 'taxref.lb_nom'
43-
* 'taxref.cd_nom'
51+
* 'nom_francais'
52+
* 'taxref.nom_vern'
53+
* 'taxref.nom_valide'
54+
* 'taxref.nom_complet'
55+
* 'taxref.lb_nom'
56+
* 'taxref.cd_nom'
4457

4558
### :technologist: Development
4659

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.3.2
1+
1.3.3

backend/gncitizen/core/observations/routes.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919
from gncitizen.utils.media import save_upload_files
2020
from gncitizen.utils.taxonomy import (
2121
get_taxa_by_cd_nom,
22-
taxhub_rest_get_taxon_list,
2322
set_taxa_info_from_taxhub,
23+
taxhub_rest_get_taxon_list,
2424
)
2525
from server import db
26-
from shapely.geometry import shape
26+
from shapely.geometry import Point, shape
2727
from sqlalchemy import desc
2828
from utils_flask_sqla.response import json_resp
2929

@@ -247,6 +247,7 @@ def post_observation():
247247
ObservationMediaModel,
248248
)
249249
current_app.logger.debug("[post_observation] ObsTax UPLOAD FILE {}".format(file))
250+
250251
newobs = (
251252
db.session.query(ObservationModel)
252253
.options(db.joinedload(ObservationModel.medias))
@@ -300,7 +301,6 @@ def get_all_observations() -> Union[FeatureCollection, Tuple[Dict, int]]:
300301
paginate = "per_page" in args
301302
per_page = int(args.pop("per_page", 1000))
302303
page = int(args.pop("page", 1))
303-
cd_nom_list = []
304304
id_role = get_id_role_if_exists()
305305

306306
if validation_process and id_role:
@@ -329,16 +329,18 @@ def get_all_observations() -> Union[FeatureCollection, Tuple[Dict, int]]:
329329
observations = query.all()
330330
features = [obs.get_feature() for obs in observations]
331331

332+
id_taxonomy_list = None
333+
params = {}
332334
if observations:
333335
id_taxonomy_list = observations[0].program_ref.taxonomy_list
334-
cd_nom_list = ",".join(map(str, {obs.cd_nom for obs in observations}))
335-
params = {"cd_nom": cd_nom_list} if cd_nom_list else {}
336-
else:
337-
id_taxonomy_list = None
338-
params = {}
339-
340-
if id_taxonomy_list:
341-
taxon_list_data = taxhub_rest_get_taxon_list(id_taxonomy_list, params)
336+
cd_nom_list = map(str, {obs.cd_nom for obs in observations})
337+
if cd_nom_list:
338+
params["cd_nom"] = ",".join(cd_nom_list)
339+
if id_taxonomy_list:
340+
params["id_liste"] = id_taxonomy_list
341+
342+
if id_taxonomy_list or cd_nom_list:
343+
taxon_list_data = taxhub_rest_get_taxon_list(params_to_update=params)
342344
features_with_taxhub_info = set_taxa_info_from_taxhub(taxon_list_data, features)
343345
else:
344346
features_with_taxhub_info = features
@@ -503,7 +505,10 @@ def update_observation():
503505
try:
504506
observer = obs_to_update_obj.observer
505507
send_user_email(
506-
subject=current_app.config["VALIDATION_EMAIL"]["SUBJECT"],
508+
subject=current_app.config["VALIDATION_EMAIL"]["SUBJECT"].format(
509+
program=f"{obs_to_update_obj.program_ref.title}",
510+
observation=f"{obs_to_update_obj.name} (#{obs_to_update_obj.id_observation})",
511+
),
507512
to=observer.email,
508513
html_message=current_app.config["VALIDATION_EMAIL"][
509514
"HTML_TEMPLATE"

backend/gncitizen/core/taxonomy/routes.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1-
from flask import Blueprint, request
2-
from typing import List, Dict, Any, Union
3-
from utils_flask_sqla.response import json_resp
1+
from typing import Any, Dict, List, Union
42

3+
from flask import Blueprint, current_app, request
54
from gncitizen.utils.taxonomy import (
6-
taxhub_rest_get_all_lists,
7-
taxhub_rest_get_taxon_list,
8-
reformat_taxa,
9-
get_taxa_by_cd_nom,
10-
get_all_medias_types,
115
get_all_attributes,
6+
get_all_medias_types,
7+
get_taxa_by_cd_nom,
8+
reformat_taxa,
129
refresh_taxonlist,
10+
taxhub_rest_get_all_lists,
11+
taxhub_rest_get_taxon_list,
1312
)
13+
from utils_flask_sqla.response import json_resp
1414

1515
taxo_api = Blueprint("taxonomy", __name__)
1616

17+
logger = current_app.logger
18+
1719

1820
@taxo_api.route("/taxonomy/refresh", methods=["GET"])
1921
@json_resp
@@ -257,12 +259,12 @@ def get_list(id) -> Union[List[Dict[str, Any]], Dict[str, str]]:
257259

258260
try:
259261
params = request.args.to_dict()
260-
res = taxhub_rest_get_taxon_list(id, params)
262+
res = taxhub_rest_get_taxon_list(taxhub_list_id=id, params_to_update=params)
261263
if isinstance(res, dict) and "items" in res:
262264
reformatted_taxa = reformat_taxa(res)
263265
else:
264266
reformatted_taxa = []
265-
print(reformatted_taxa)
267+
logger.debug(reformatted_taxa)
266268
return reformatted_taxa
267269
except Exception as e:
268270
return {"message": str(e)}, 400

backend/gncitizen/utils/mail_check.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from flask import current_app
77
from itsdangerous import URLSafeTimedSerializer
88

9+
logger = current_app.logger
10+
911
default_mail_from_addr = current_app.config["MAIL"]["MAIL_AUTH_LOGIN"]
1012

1113

@@ -64,7 +66,7 @@ def send_user_email(
6466
server.quit()
6567

6668
except Exception as e:
67-
current_app.logger.warning("send email failled. %s", str(e))
69+
logger.warning("send email failled. %s", str(e))
6870
return {"message": """ send email failled: "{}".""".format(str(e))}
6971

7072

@@ -99,7 +101,7 @@ def confirm_user_email(newuser, with_confirm_link=True):
99101
)
100102

101103
except Exception as e:
102-
current_app.logger.warning("send confirm_email failled. %s", str(e))
104+
logger.warning("send confirm_email failled. %s", str(e))
103105
return {"message": """ send confirm_email failled: "{}".""".format(str(e))}
104106

105107

@@ -116,5 +118,5 @@ def confirm_token(token):
116118
salt=current_app.config["CONFIRM_MAIL_SALT"],
117119
)
118120
except Exception as e:
119-
current_app.logger.warning("confirm_token failled. %s", str(e))
121+
logger.warning("confirm_token failled. %s", str(e))
120122
return email

backend/gncitizen/utils/media.py

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
from gncitizen.utils.errors import GeonatureApiError
1414
from server import db
1515

16+
logger = current_app.logger
17+
1618

1719
def allowed_file(filename):
1820
"""Check if uploaded file type is allowed
@@ -67,15 +69,15 @@ def save_upload_files(
6769
if isinstance(file, FileStorage):
6870
i = i + 1
6971
filename = file.filename
70-
current_app.logger.debug(
72+
logger.debug(
7173
"[save_upload_files] {} is an allowed filename : {}".format(
7274
filename, allowed_file(filename)
7375
)
7476
)
7577

7678
if allowed_file(filename):
7779
# save file
78-
current_app.logger.debug(
80+
logger.debug(
7981
'[save_upload_files] Preparing file "{}" saving'.format(
8082
filename
8183
)
@@ -85,25 +87,21 @@ def save_upload_files(
8587
filename = "{}_{}_{}_{}.{}".format(
8688
prefix, str(cdnom), i, timestamp, ext
8789
)
88-
current_app.logger.debug(
90+
logger.debug(
8991
"[save_upload_files] new filename : {}".format(filename)
9092
)
9193
file.save(os.path.join(str(MEDIA_DIR), filename))
9294
# Save media filename to Database
9395
try:
9496
newmedia = MediaModel(filename=filename)
95-
current_app.logger.debug(
96-
"[save_upload_files] newmedia {}".format(newmedia)
97-
)
97+
logger.debug("[save_upload_files] newmedia {}".format(newmedia))
9898
db.session.add(newmedia)
9999
db.session.commit()
100100
id_media = newmedia.id_media
101-
current_app.logger.debug(
102-
f"[save_upload_files] id_media : {str(id_media)}]"
103-
)
101+
logger.debug(f"[save_upload_files] id_media : {str(id_media)}]")
104102
# return id_media
105103
except Exception as e:
106-
current_app.logger.debug(
104+
logger.debug(
107105
"[save_upload_files] ERROR MEDIAMODEL: {}".format(e)
108106
)
109107
raise GeonatureApiError(e)
@@ -115,25 +113,21 @@ def save_upload_files(
115113
db.session.add(newmatch)
116114
db.session.commit()
117115
id_match = newmatch.id_match
118-
current_app.logger.debug(
119-
"[save_upload_files] id_match {}".format(id_match)
120-
)
116+
logger.debug("[save_upload_files] id_match {}".format(id_match))
121117
except Exception as e:
122-
current_app.logger.debug(
118+
logger.debug(
123119
"[save_upload_files] ERROR MATCH MEDIA: {}".format(e)
124120
)
125121
raise GeonatureApiError(e)
126122

127123
# log
128-
current_app.logger.debug(
124+
logger.debug(
129125
"[save_upload_files] Fichier {} enregistré".format(filename)
130126
)
131127
files.append(filename)
132128

133129
except Exception as e:
134-
current_app.logger.debug(
135-
"[save_upload_files] ERROR save_upload_file : {}".format(e)
136-
)
130+
logger.debug("[save_upload_files] ERROR save_upload_file : {}".format(e))
137131
raise GeonatureApiError(e)
138132

139133
return files

backend/gncitizen/utils/taxonomy.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"""A module to manage taxonomy"""
44

55
from threading import Thread
6-
import unicodedata
76
from typing import Dict, List, Optional, Union
87

98
import requests
@@ -39,16 +38,21 @@
3938
taxonomy_lists = []
4039

4140

42-
def taxhub_rest_get_taxon_list(taxhub_list_id: int, params_to_update: Dict = {}) -> Dict:
41+
def taxhub_rest_get_taxon_list(
42+
taxhub_list_id: Optional[int] = None,
43+
params_to_update: Dict = {},
44+
) -> Dict:
4345
url = f"{TAXHUB_API}taxref"
4446
params = {
45-
"id_liste": taxhub_list_id,
4647
"fields": "medias,attributs",
4748
"existing": "true",
4849
"order": "asc",
4950
"orderby": "nom_complet",
5051
"limit": 100,
5152
}
53+
if taxhub_list_id:
54+
params["id_liste"] = taxhub_list_id
55+
5256
if params_to_update:
5357
params.update(params_to_update)
5458
res = session.get(
@@ -78,7 +82,12 @@ def taxhub_rest_get_all_lists() -> Optional[Dict]:
7882
f'[{taxa_list["code_liste"]}] {taxa_list["nom_liste"]} ({taxa_list["nb_taxons"]} taxon(s))',
7983
)
8084
)
81-
print(f"taxonomy_lists {taxonomy_lists}")
85+
logger.info(
86+
"%s taxonomy lists have been found on %s",
87+
len(taxonomy_lists),
88+
TAXHUB_API,
89+
)
90+
logger.debug("Taxonomy list items are %s", taxonomy_lists)
8291
except Exception as e:
8392
logger.critical(str(e))
8493
return res.json().get("data", [])

0 commit comments

Comments
 (0)