Skip to content

Commit 016ca30

Browse files
committed
repercussion modif develop
2 parents ac87f58 + 3a935bd commit 016ca30

11 files changed

+164
-133
lines changed

VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.0.1.dev0
1+
1.1.X

docs/changelog.md

+17-3
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,34 @@
11
CHANGELOG
22
=========
33

4+
1.2.0 - unreleased
5+
-------------------
6+
7+
- id_digitiser si pas de création de site ?
48

59
1.1.0
610
-----
711

8-
- Compatibilité avec GeoNature 2.15 (taxhub v2 et monitoring 1.0.0 (?))
12+
- Compatibilité avec GeoNature 2.14 et monitoring 0.7.X
13+
- Possibilité d'utiliser le module sans avoir le module monitoring d'installé
914

1015
Note de version :
1116

1217
- installer le module ODK2GN comme un module geonature :
13-
1418
```
1519
geonature install-gn-module <chemin vers odk2gn> --build=false
1620
```
17-
Vous devrez ensuite associer des permssions au module :
21+
- Supprimez les champs `data` de la configuration de vos modules dans le fichier `odk2gn_config.toml`
22+
- La gestion de la création des sites / visites / observations change. Le fait de pouvoir créer des sites étaient controlé par un paramètre de configuration `create_site` qui pointait vers le nom d'un champs du formulaire ODK. Ce sont désormais 3 booléens qui controle ça au niveau de la configuration ODK2GN de chaque sous module (voir le fichier d'exemple `odk2gn_config.toml.example`). Par défault les valeurs sont à `True` (bien veiller à passer les bonne valeur si vous voulez désactiver la création d'entitité à un niveau)
23+
24+
```
25+
create_site=false
26+
create_visit=true
27+
create_observation=true
28+
```
29+
30+
31+
Vous devrez ensuite associer des permissions au module :
1832

1933
Pour donner tous les droits aux groupe admin :
2034
`geonature permissions supergrant --group --nom "Grp_admin" --yes

odk2gn/gn2_utils.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import os
33
import csv
44
import flatdict
5-
from shapely.geometry import shape, Point, Polygon
5+
from shapely.geometry import shape
66
from shapely.ops import transform
77
from sqlalchemy.exc import SQLAlchemyError
88
from geoalchemy2.shape import from_shape
@@ -14,13 +14,12 @@
1414
from geonature.core.gn_commons.models import TModules
1515
from geonature.utils.utilsmails import send_mail
1616
from geonature.utils.config import config
17-
from geonature.core.gn_monitoring.models import TBaseSites, BibTypeSite
1817

1918

2019
from pypnusershub.db.models import User
2120
from pypnnomenclature.models import TNomenclatures, CorTaxrefNomenclature
2221

23-
from apptax.taxonomie.models import BibListes, cor_nom_liste, Taxref
22+
from apptax.taxonomie.models import BibListes, Taxref
2423
from odk2gn.odk_api import update_review_state
2524

2625
log = logging.getLogger("app")

odk2gn/monitoring/command.py

+79-74
Original file line numberDiff line numberDiff line change
@@ -80,98 +80,103 @@ def synchronize_module(module_code, project_id, form_id):
8080
for sub in form_data:
8181
flatten_data = flat_and_short_dict(sub)
8282
id_digitiser = get_digitiser(flatten_data, module_parser_config)
83-
site = parse_and_create_site(
84-
flatten_data,
85-
module_parser_config,
86-
monitoring_config=monitoring_config,
87-
module=gn_module,
88-
odk_form_schema=odk_form_schema,
89-
)
90-
site.id_digitiser = id_digitiser
91-
get_and_post_medium(
92-
project_id=project_id,
93-
form_id=form_id,
94-
uuid_sub=flatten_data.get("instanceID"),
95-
filename=flatten_data.get(module_parser_config["SITE"]["media"]),
96-
monitoring_table="t_base_sites",
97-
media_type=module_parser_config["SITE"]["media_type"],
98-
uuid_gn_object=site.uuid_base_site,
99-
)
100-
if site:
101-
DB.session.add(site)
102-
103-
visit = parse_and_create_visit(
104-
flatten_data,
105-
module_parser_config,
106-
monitoring_config,
107-
gn_module,
108-
odk_form_schema,
109-
)
110-
if not visit:
111-
# S'il n'y a pas de visites
112-
# Sauvegarde des données et passage à la submission suivante
113-
log.warning("No visit for this site")
83+
if module_parser_config["can_create_site"]:
84+
site = parse_and_create_site(
85+
flatten_data,
86+
module_parser_config,
87+
monitoring_config=monitoring_config,
88+
module=gn_module,
89+
odk_form_schema=odk_form_schema,
90+
)
91+
92+
# Dans certain cas on peut soit créer des site soit selectionner un site existant
93+
if site:
94+
site.id_digitiser = id_digitiser
95+
get_and_post_medium(
96+
project_id=project_id,
97+
form_id=form_id,
98+
uuid_sub=flatten_data.get("instanceID"),
99+
filename=flatten_data.get(module_parser_config["SITE"]["media"]),
100+
monitoring_table="t_base_sites",
101+
media_type=module_parser_config["SITE"]["media_type"],
102+
uuid_gn_object=site.uuid_base_site,
103+
)
104+
DB.session.add(site)
105+
# si pas de visite pour le module
106+
if not "visit" in monitoring_config:
114107
commit_data(project_id, form_id, sub["__id"])
115108
continue
116-
117-
visit.id_digitiser = id_digitiser
118-
119-
get_and_post_medium(
120-
project_id=project_id,
121-
form_id=form_id,
122-
uuid_sub=flatten_data.get("instanceID"),
123-
filename=flatten_data.get(module_parser_config["VISIT"]["media"]),
124-
monitoring_table="t_base_visits",
125-
media_type=module_parser_config["VISIT"]["media_type"],
126-
uuid_gn_object=visit.uuid_base_visit,
127-
)
128-
129-
observations_list = []
130-
try:
131-
observations_list = flatten_data.pop(
132-
module_parser_config["OBSERVATION"]["observations_repeat"]
133-
)
134-
assert type(observations_list) is list
135-
except KeyError:
136-
log.warning("No observation for this visit")
137-
except AssertionError:
138-
log.error("Observation node is not a list")
139-
raise
140-
except Exception as e:
141-
raise
142-
143-
for obs in observations_list:
144-
gn_uuid_obs = uuid.uuid4()
145-
flatten_obs = flat_and_short_dict(obs)
146-
observation = parse_and_create_obs(
147-
flatten_obs,
109+
else:
110+
visit = parse_and_create_visit(
111+
flatten_data,
148112
module_parser_config,
149113
monitoring_config,
114+
gn_module,
150115
odk_form_schema,
151-
gn_uuid_obs,
152116
)
153-
observation.id_digitiser = id_digitiser
117+
if not visit:
118+
# S'il n'y a pas de visites
119+
# Sauvegarde des données et passage à la submission suivante
120+
log.warning("No visit for this site")
121+
commit_data(project_id, form_id, sub["__id"])
122+
continue
123+
124+
visit.id_digitiser = id_digitiser
125+
154126
get_and_post_medium(
155127
project_id=project_id,
156128
form_id=form_id,
157129
uuid_sub=flatten_data.get("instanceID"),
158-
filename=flatten_obs.get(module_parser_config["OBSERVATION"]["media"]),
159-
monitoring_table="t_observations",
160-
media_type=module_parser_config["OBSERVATION"]["media_type"],
161-
uuid_gn_object=gn_uuid_obs,
130+
filename=flatten_data.get(module_parser_config["VISIT"]["media"]),
131+
monitoring_table="t_base_visits",
132+
media_type=module_parser_config["VISIT"]["media_type"],
133+
uuid_gn_object=visit.uuid_base_visit,
162134
)
163-
visit.observations.append(observation)
164-
if site and visit:
165-
site.visits.append(visit)
166-
135+
if "observation" in monitoring_config:
136+
observations_list = []
137+
try:
138+
observations_list = flatten_data.pop(
139+
module_parser_config["OBSERVATION"]["observations_repeat"]
140+
)
141+
assert type(observations_list) is list
142+
except KeyError:
143+
log.warning("No observation for this visit")
144+
except AssertionError:
145+
log.error("Observation node is not a list")
146+
raise
147+
except Exception as e:
148+
raise
149+
150+
for obs in observations_list:
151+
gn_uuid_obs = uuid.uuid4()
152+
flatten_obs = flat_and_short_dict(obs)
153+
observation = parse_and_create_obs(
154+
flatten_obs,
155+
module_parser_config,
156+
monitoring_config,
157+
gn_module,
158+
odk_form_schema,
159+
)
160+
observation.id_digitiser = id_digitiser
161+
get_and_post_medium(
162+
project_id=project_id,
163+
form_id=form_id,
164+
uuid_sub=flatten_data.get("instanceID"),
165+
filename=flatten_obs.get(module_parser_config["OBSERVATION"]["media"]),
166+
monitoring_table="t_observations",
167+
media_type=module_parser_config["OBSERVATION"]["media_type"],
168+
uuid_gn_object=gn_uuid_obs,
169+
)
170+
visit.observations.append(observation)
171+
if site and visit:
172+
site.visits.append(visit)
167173
if visit:
168174
DB.session.add(visit)
169175

170176
commit_data(project_id, form_id, sub["__id"])
171177
log.info(f"--- Finish synchronize for module {module_code} ---")
172178

173179

174-
175180
def upgrade_module(
176181
module_code,
177182
project_id,

odk2gn/monitoring/config_schema.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44

55
class SiteSchema(Schema):
6+
create_site = fields.Str(load_default="create_site")
67
base_site_name = fields.Str(load_default="base_site_name")
78
base_site_code = fields.Str(load_default="base_site_code")
89
base_site_description = fields.Str(load_default="base_site_description")
@@ -19,6 +20,7 @@ class SiteSchema(Schema):
1920

2021

2122
class VisitSchema(Schema):
23+
create_visit = fields.Str(load_default="create_visit")
2224
observers_repeat = fields.Str(load_default="observers")
2325
id_observer = fields.Str(load_default="id_role")
2426
media = fields.Str(load_default="medias_visit")
@@ -42,8 +44,7 @@ class ObservationSchema(Schema):
4244

4345
class ProcoleSchema(Schema):
4446
module_code = fields.Str(required=True)
45-
create_site = fields.Str(load_default="create_site")
46-
create_visit = fields.Str(load_default="create_visit")
47+
can_create_site = fields.Boolean(load_default=True)
4748
SITE = fields.Nested(SiteSchema, load_default=SiteSchema().load({}))
4849
VISIT = fields.Nested(VisitSchema, load_default=VisitSchema().load({}))
4950
OBSERVATION = fields.Nested(ObservationSchema, load_default=ObservationSchema().load({}))

odk2gn/monitoring/utils.py

+11-20
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
from pypnusershub.db.models import User
2121

2222
from odk2gn.odk_api import get_attachment
23+
from odk2gn.gn2_utils import format_jdd_list, get_observers
24+
25+
log = logging.getLogger("app")
26+
27+
from pypnnomenclature.models import TNomenclatures
2328
from odk2gn.gn2_utils import (
2429
format_jdd_list,
2530
to_wkb,
@@ -92,29 +97,21 @@ def process_additional_data(monitoring_config, odk_form_schema, field_name, val)
9297

9398
def get_digitiser(flatten_sub, module_parser_config):
9499
for key, val in flatten_sub.items():
95-
odk_column_name = key.split("/")[-1]
96100
# specifig digitiser column
97-
if odk_column_name == module_parser_config.get("id_digitiser"):
101+
if key == module_parser_config.get("id_digitiser"):
98102
return int(val)
99103

100104

101-
def get_observers(observers_list):
102-
obss = DB.session.query(User).filter(User.id_role.in_(tuple(observers_list))).all()
103-
return obss
104-
105-
106-
107105
def parse_and_create_site(
108106
flatten_sub, module_parser_config, monitoring_config, module, odk_form_schema
109107
):
110-
# Test de création du site
111-
# S'il y a un champ create_site dans le formulaire
112-
# et qu'il est renseigné de façon négative
113-
if module_parser_config.get("create_site") in flatten_sub.keys():
108+
# Le module peut accepter à la fois la création de site et la selection d'un site existant
109+
# Ici on est dans le cas ou le formulaire ODK accepte la création de site
110+
# on va vérifier dans la soumission si l'utilisateur a choisi de créer un site ou non
111+
if module_parser_config["SITE"].get("create_site") in flatten_sub.keys():
114112
create_site_key = module_parser_config.get("create_site")
115113
if flatten_sub[create_site_key] in ("0", 0, "false", "no", False, None):
116114
return None
117-
118115
id_type = None
119116
site_dict_to_post = {
120117
"data": {},
@@ -196,22 +193,17 @@ def parse_and_create_visit(
196193
:type monitoring_config: dict
197194
198195
:param gn_module: the gn_module object
199-
:type monitoring_config: TMpodulesMonitoring
196+
:type monitoring_config: TModulesMonitoring
200197
201198
:param odk_form_schema: a ODKSchema object describing the ODK form
202199
:type odk_form_schema: ODKSchema
203200
204201
205202
"""
206-
if not "visit" in monitoring_config:
207-
# si pas de visite pour le module
208-
return None
209-
210203
visit_generic_column = monitoring_config["visit"]["generic"]
211204
visit_specific_column = monitoring_config["visit"]["specific"]
212205
# get uuid from the submission and use it has visit UUID
213206
visit_uuid = flatten_sub["__id"].split(":")[-1]
214-
# DB.session.query(TMonitoringVisits).filter_by(uuid_base_visit=visit_uuid).exitst()
215207
visit_dict_to_post = {
216208
"uuid_base_visit": visit_uuid,
217209
"id_module": gn_module.id_module,
@@ -297,7 +289,6 @@ def parse_and_create_obs(
297289
:param odk_form_schema: a ODKSchema object describing the ODK form
298290
:type odk_form_schema: ODKSchema
299291
"""
300-
# TODO : make a class and not get these column a each loop
301292
observation_generic_column = monitoring_config["observation"]["generic"]
302293
observation_specific_column = monitoring_config["observation"]["specific"]
303294

odk2gn/odk_api.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def get_attachment(project_id, form_id, uuid_sub, media_name):
2222
if img.status_code == 200:
2323
return img.content
2424
else:
25-
log.warning(f"Image not found for submission {uuid_sub}")
25+
log.warning(f"No image found for submission {uuid_sub}")
2626

2727

2828

0 commit comments

Comments
 (0)