Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sterf protocole with export + synthese #56

Merged
merged 7 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed .DS_Store
Binary file not shown.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.vscode
custom.json
custom.json

.DS_Store
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Petite signature de l'auteur ! 🤣

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ouais! Mais grâce à ça, tu retrouveras pas ces fichus (je suis poli!) DS_Store de partout

15 changes: 15 additions & 0 deletions sterf/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"tree": {
"module": {
"site": {
"visit": {
"observation": null
}
}
}
},
"data": {
"nomenclature": ["TYPE_SITE", "METH_DETERMIN"],
"user": ["__CODE_LIST_INVENTOR", "__CODE_LIST_OBSERVER"]
}
}
68 changes: 68 additions & 0 deletions sterf/exports/csv/export_csv.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
------- Export des observations STERF ----------
DROP VIEW IF EXISTS gn_monitoring.v_export_sterf_standard;

CREATE OR REPLACE VIEW gn_monitoring.v_export_sterf_standard AS (
SELECT
-- identifiant unique
o.uuid_observation AS uuid_observation,
-- Site et variables associées
s.base_site_name AS nom_transect,
st_astext(s.geom) AS wkt_transect,
st_x(st_centroid(s.geom_local)) AS x_centroid_local,
st_y(st_centroid(s.geom_local)) AS y_centroid_local,
alt.altitude_min AS altitude_min,
alt.altitude_max AS altitude_max,
string_agg(distinct(com.area_name),', ') AS communes,
nullif(sc.data::json ->> 'tirage_site', 'null') AS tirage_site,
nullif(sc.data::json ->> 'habitat_1', 'null') AS habitat_1,
nullif(sc.data::json ->> 'habitat_2', 'null') AS habitat_2,
nullif(sc.data::json ->> 'habitat_3', 'null') AS habitat_3,
nullif(sc.data::json ->> 'habitat_4', 'null') AS habitat_4,
-- Informations sur la visite
v.id_dataset,
d.dataset_name AS jeu_de_donnees,
v.uuid_base_visit AS uuid_visite,
v.visit_date_min AS date_visite,
nullif(vc.data::json ->> 'duration', 'null') AS duree_parcours,
obs.observers,
nullif(vc.data::json ->> 'start_time', 'null') AS heure_debut,
nullif(vc.data::json ->> 'meteo_cond', 'null') AS conditions_meteo,
nullif(vc.data::json ->> 'temperature', 'null') AS temperature,
nullif(vc.data::json ->> 'vent', 'null') AS vent,
nullif(vc.data::json ->> 'ennuagement', 'null') AS ennuagement,
v.comments AS commentaire_visite,
-- Informations sur l'observation
o.cd_nom AS cd_nom,
t.lb_nom AS nom_latin,
t.nom_vern AS nom_francais,
r.prenom_role||' '||r.nom_role AS determinateur,
nullif(oc.data::json ->> 'count_min', 'null') AS count_min,
nullif(oc.data::json ->> 'count_max', 'null') AS count_max,
ref_nomenclatures.get_nomenclature_label(nullif(json_extract_path(oc.data::json,'id_nomenclature_determination_method')::text,'null')::integer, 'fr') AS methode_determ,
o.comments AS commentaire_obs
FROM gn_monitoring.t_observations o
JOIN gn_monitoring.t_observation_complements oc ON oc.id_observation = o.id_observation
JOIN gn_monitoring.t_base_visits v ON o.id_base_visit = v.id_base_visit
JOIN gn_monitoring.t_visit_complements vc ON v.id_base_visit = vc.id_base_visit
JOIN gn_monitoring.t_base_sites s ON s.id_base_site = v.id_base_site
JOIN gn_monitoring.t_site_complements sc ON sc.id_base_site = s.id_base_site
JOIN gn_commons.t_modules m ON m.id_module = v.id_module
JOIN taxonomie.taxref t ON t.cd_nom = o.cd_nom
LEFT JOIN gn_monitoring.cor_site_area csa ON csa.id_base_site = s.id_base_site
LEFT JOIN gn_meta.t_datasets d ON d.id_dataset=v.id_dataset
LEFT JOIN (select la.area_name, csa.id_base_site
FROM ref_geo.l_areas la
JOIN ref_geo.bib_areas_types bat ON la.id_type = bat.id_type
JOIN gn_monitoring.cor_site_area csa ON csa.id_area = la.id_area
WHERE bat.type_code='COM') com ON s.id_base_site = com.id_base_site
LEFT JOIN LATERAL ( SELECT array_agg(r.id_role) AS ids_observers,
string_agg(concat(r.nom_role, ' ', r.prenom_role, ' (',org.nom_organisme,') '), ' ; '::text) AS observers
FROM gn_monitoring.cor_visit_observer cvo
JOIN utilisateurs.t_roles r ON r.id_role = cvo.id_role
LEFT JOIN utilisateurs.bib_organismes org ON org.id_organisme =r.id_organisme
WHERE cvo.id_base_visit = v.id_base_visit) obs ON true
LEFT JOIN LATERAL ref_geo.fct_get_altitude_intersection(s.geom_local) alt(altitude_min, altitude_max) ON true
LEFT JOIN utilisateurs.t_roles r ON nullif(json_extract_path(oc.data::json,'determiner')::text,'null')::integer = r.id_role
WHERE m.module_code = 'sterf'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pour que le script se lance il faut utiliser la synthaxe WHERE m.module_code = :module_code

GROUP BY 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33
amandine-sahl marked this conversation as resolved.
Show resolved Hide resolved
);
Binary file added sterf/img.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions sterf/module.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"module_label":"Suivi Temporel des Rhopalocères de France",
"module_desc":"Module de saisie du protocole STERF",
"export_csv": [
{ "label": "Format observations CSV", "type":"csv" , "method": "standard" }
]
}
18 changes: 18 additions & 0 deletions sterf/nomenclature.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"types": [
{
"mnemonique": "TYPE_SITE",
"label_default": "Type de sites",
"definition_default": "Nomenclature des types de sites suivi dans gn_monitoring."
}
],
"nomenclatures": [
{
"type": "TYPE_SITE",
"cd_nomenclature": "STERF",
"mnemonique": "Site_STERF",
"label_default": "Site STERF",
"definition_default": "Site de relevé du protocole STERF"
}
]
}
58 changes: 58 additions & 0 deletions sterf/observation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"display_properties": [
"cd_nom",
"id_nomenclature_determination_method",
"determiner",
"count_min",
"count_max",
"comments"
],
"display_list": [
"cd_nom",
"id_nomenclature_determination_method",
"count_min",
"count_max"
],
"keep": [
"determiner",
"id_nomenclature_determination_method"
],
"specific": {
"determiner": {
"type_widget": "datalist",
"attribut_label": "Déterminateur",
"api": "users/menu/__MODULE.ID_LIST_OBSERVER",
"application": "GeoNature",
"keyValue": "id_role",
"keyLabel": "nom_complet",
"type_util": "user",
"required": true
},
"id_nomenclature_determination_method": {
"type_widget": "datalist",
"attribut_label": "Méthode de détermination",
"api": "nomenclatures/nomenclature/METH_DETERMIN",
"application": "GeoNature",
"keyValue": "id_nomenclature",
"keyLabel": "label_fr",
"data_path": "values",
"type_util": "nomenclature",
"required": false,
"default": {
"cd_nomenclature": "67"
}
},
"count_min": {
"type_widget": "number",
"attribut_label": "Effectif minimal dénombré",
"required": true,
"min": 1
},
"count_max": {
"type_widget": "number",
"attribut_label": "Effectif maximal dénombré",
"required": true,
"min": "({value}) => value.count_min "
}
}
}
102 changes: 102 additions & 0 deletions sterf/site.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@

{
"genre":"M",
"geometry_type": "LineString",
"label": "Transect",
"label_list": "Transects",
"map_label_field_name": "base_site_name",
"display_properties": [
"base_site_name",
"id_inventor",
"first_use_date",
"last_visit",
"nb_visits",
"tirage_site",
"habitat_1",
"habitat_2",
"habitat_3",
"habitat_4"
],
"display_list": [
"base_site_name",
"first_use_date",
"last_visit",
"nb_visits"
],
"keep": [
"id_inventor",
"tirage_site"
],
"specific": {
"id_nomenclature_type_site": {
"type_widget": "nomenclature",
"attribut_label": "Type site",
"code_nomenclature_type": "TYPE_SITE",
"type_util": "nomenclature",
"required": true,
"value": {
"code_nomenclature_type": "TYPE_SITE",
"cd_nomenclature": "STERF"
},
"hidden": true
},
"tirage_site": {
"type_widget": "select",
"attribut_label": "Modalité de sélection du site *",
"required": true,
"values": ["Tiré aléatoirement", "Choisi"],
"value":"Choisi"
},
"habitat_1": {
"type_widget": "select",
"attribut_label": "Habitat (subdivision 1) *",
"required": true,
"values": ["A. Forêt (arbres > 5m de hauteur)","B. Buissons ou jeune forêt (<5m de hauteur)","C. Pelouses, marais et landes","D. Milieux agricoles","E. Milieux bâtis ou urbanisés","G. Rochers terrestres ou côtiers"]
},
"habitat_2": {
"type_widget": "select",
"required": false,
"attribut_label": "Habitat (subdivision 2)",
"values": [
"({value}) => {",
" if (value.habitat_1 == 'A. Forêt (arbres > 5m de hauteur)') { return [ 'a. Feuillus exclusifs','b. Mixte dom. Feuillus (< 10% conifères)','c. Mixte dom. conifères (< 10% feuillus)','d. Conifères exclusifs','e. Mixte' ] }",
" if (value.habitat_1 == 'B. Buissons ou jeune forêt (<5m de hauteur)') { return [ 'a. Feuillus exclusifs','b. Mixte dom. feuillus (< 10% conifères)','c. Mixte dom. conifères (< 10% feuillus)','d. Conifères exclusifs','e. Mixte' ] }",
" if (value.habitat_1 == 'C. Pelouses, marais et landes') { return [ 'a. Pelouse calcaire sèche','b. Lande herbacée','c. Lande à bruyères','d. Autres pelouses sèches','e. Pelouse d altitude', 'f. Pelouse humide naturelle', 'g. Pelouse inondée/marais pâturé', 'h. Tourbière', 'i. Roselière', 'j. Marais salant (halophile)', 'k. Autres zones humides ouvertes' ] }",
" if (value.habitat_1 == 'D. Milieux agricoles') { return [ 'a. Prairie cultivée','b. Prairie non cultivée','c. Prairie / cultures mixtes','d. Grandes cultures','e. Vergers / vignes / cultures maraîchères','f. Autres types de cultures' ] }",
" if (value.habitat_1 == 'E. Milieux bâtis ou urbanisés') { return [ 'a Zone urbaine résidentielle','b Zone urbaine industrielle','c Zone suburbaine résidentielle','d Zone suburbaine industrelle','e Zone rurale' ] }",
" else { return [ 'a. Falaise','b. Eboulis, pente rocheuse','c. Carrière','d. Autres sols rocheux' ]} ",
"}"
]
},
"habitat_3": {
"type_widget": "select",
"required": false,
"attribut_label": "Habitat (subdivision 3)",
"values": [
"({value}) => {",
" if (value.habitat_1 == 'A. Forêt (arbres > 5m de hauteur)') { return [ '1. Sous-bois dense','2. Sous-bois clair','3. Clairière et lisière','4. Parc (arbres épars et prairies)' ] }",
" if (value.habitat_1 == 'B. Buissons ou jeune forêt (<5m de hauteur)') { return [ '1. Forêt de régénération ou taillis','2. Buissons calcicoles','3. Lande arbustive non calcicole','4. Garrigue (calcaire) (Méditerr)','5. Maquis (non calcaire) (Méditerr)','6. Buissons de zones humides' ] }",
" if (value.habitat_1 == 'C. Pelouses, marais et landes') { return [ '1. Entouré de haies avec arbres','2. Entouré de haies de buissons','3. Entouré de ligne d arbres sans haie','4. Avec buissons épars','5. Sans buissons épars','6. Groupes isolés de 1-10 arbres','7. Autres limites de terrain (digue, fossé, mur, ...)' ] }",
" if (value.habitat_1 == 'D. Milieux agricoles') { return [ '1. Entouré de haies avec arbres','2. Entouré de haies de buissons','3. Entouré de ligne d arbres sans haie','4. Entouré de bandes herbeuses','5. Avec des groupes isolés de 1-10 arbres','6. Autre limite de terrain (digue, fossé, mur, ...)' ] }",
" if (value.habitat_1 == 'E. Milieux bâtis ou urbanisés') { return [ '1. Zones bâties prédominantes','2. Jardin','3. Parc public, zone de loisirs','4. Bord d une route (< 50 m)','5. Bord d un chemin de fer (< 50 m)','6. Décharge d’ordures' ] }",
" else { return [ '1. En montagne','2. En bord de mer','3. En bord de lac ou de rivière','4. Autre' ]} ",
"}"
]
},
"habitat_4": {
"type_widget": "select",
"required": false,
"attribut_label": "Habitat (subdivision 4)",
"values": [
"({value}) => {",
" if (value.habitat_1 == 'A. Forêt (arbres > 5m de hauteur)') { return [ 'a. Non perturbé','b. Peu exploité','c. Fortement exploité','d. Pâturé' ] }",
" if (value.habitat_1 == 'B. Buissons ou jeune forêt (<5m de hauteur)') { return [ 'a. Non perturbé','b. Peu exploité','c. Fortement exploité','d. Pâturé' ] }",
" if (value.habitat_1 == 'C. Pelouses, marais et landes') { return [ 'a. Non perturbé/non exploité','b. Fauché','c. Pâturé' ] }",
" if (value.habitat_1 == 'D. Milieux agricoles') { return [ 'a. Non exploité (jachère)','b. Fauché','c. Pâturé','d. Céréales','e. Arbres fruitiers','f. Autres cultures' ] }",
" if (value.habitat_1 == 'E. Milieux bâtis ou urbanisés') { return [ 'a. Avec peu d espaces verts (< 25 %)','b. Avec des espaces verts surtout composés de pelouses','c. Avec des espaces verts buissonants (parterres, friches)','d. Avec des espaces verts fortement arborés','e. Avec un (des) potager(s)' ] }",
" else { return [ 'a. A dominante calcaire avec végétation herbacée rase','b. A dominante calcaire avec végétation herbacée haute','c. A dominante calcaire avec végétation buissonnante','d. A dominante non calcaire avec végétation herbacée rase','e. A dominante non calcaire avec végétation herbacée haute','f. A dominante non calcaire avec végétation buissonnante' ]} ",
"}"
]
}
}
}
67 changes: 67 additions & 0 deletions sterf/synthese.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
-- #############################
-- Création d'une vue
-- permettant la remonté des données
-- STERF dans la synthèse
-- #############################
DROP VIEW IF EXISTS gn_monitoring.v_synthese_sterf;

-- gn_monitoring.v_synthese_sterf
CREATE OR REPLACE VIEW gn_monitoring.v_synthese_sterf
AS WITH source AS (
SELECT t_sources.id_source
FROM gn_synthese.t_sources
WHERE t_sources.name_source::text = concat('MONITORING_', upper('sterf'::text))
LIMIT 1
)
SELECT o.uuid_observation AS unique_id_sinp,
v.uuid_base_visit AS unique_id_sinp_grp,
( SELECT source.id_source
FROM source) AS id_source,
o.id_observation AS entity_source_pk_value,
v.id_dataset,
ref_nomenclatures.get_id_nomenclature('METH_OBS'::character varying, '0'::character varying) AS id_nomenclature_obs_meth,
ref_nomenclatures.get_id_nomenclature('STADE_VIE'::character varying, '15'::character varying) AS id_nomenclature_life_stage,
ref_nomenclatures.get_id_nomenclature('SEXE'::character varying, '6'::character varying) AS id_nomenclature_sex,
ref_nomenclatures.get_id_nomenclature('OBJ_DENBR'::character varying, 'IND'::character varying) AS id_nomenclature_obj_count,
ref_nomenclatures.get_id_nomenclature('TYP_DENBR'::character varying, 'Co'::character varying) AS id_nomenclature_type_count,
ref_nomenclatures.get_id_nomenclature('STATUT_OBS'::character varying, 'Pr'::character varying) AS id_nomenclature_observation_status,
ref_nomenclatures.get_id_nomenclature('STATUT_SOURCE'::character varying, 'Te'::character varying) AS id_nomenclature_source_status,
ref_nomenclatures.get_id_nomenclature('TYP_INF_GEO'::character varying, '1'::character varying) AS id_nomenclature_info_geo_type,
ref_nomenclatures.get_id_nomenclature('ETA_BIO'::character varying, '2'::character varying) AS id_nomenclature_bio_condition,
((oc.data::json #> '{count_min}'::text[])::text)::integer AS count_min,
((oc.data::json #> '{count_max}'::text[])::text)::integer AS count_max,
o.id_observation,
o.cd_nom,
t.nom_complet AS nom_cite,
alt.altitude_min,
alt.altitude_max,
s.geom AS the_geom_4326,
st_centroid(s.geom) AS the_geom_point,
s.geom_local AS the_geom_local,
v.visit_date_min AS date_min,
v.visit_date_max AS date_max,
obs.observers,
s.id_digitiser,
((oc.data::json #> '{id_nomenclature_determination_method}'::text[])::text)::integer AS id_nomenclature_determination_method,
v.id_module,
v.comments AS comment_context,
o.comments AS comment_description,
obs.ids_observers,
v.id_base_site,
v.id_base_visit,
jsonb_build_object('nom_site', s.base_site_name, 'code_site', s.base_site_code, 'habitat_1', NULLIF(replace((sc.data::json -> 'habitat_1'::text)::text, '"'::text, ''::text), 'null'::text), 'habitat_2', NULLIF(replace((sc.data::json -> 'habitat_2'::text)::text, '"'::text, ''::text), 'null'::text), 'habitat_3', NULLIF(replace((sc.data::json -> 'habitat_3'::text)::text, '"'::text, ''::text), 'null'::text), 'habitat_4', NULLIF(replace((sc.data::json -> 'habitat_4'::text)::text, '"'::text, ''::text), 'null'::text), 'vent', NULLIF(replace((vc.data::json -> 'vent'::text)::text, '"'::text, ''::text), 'null'::text), 'ennuagement', NULLIF(replace((vc.data::json -> 'ennuagement'::text)::text, '"'::text, ''::text), 'null'::text), 'temperature', NULLIF(replace((vc.data::json -> 'temperature'::text)::text, '"'::text, ''::text), 'null'::text), 'meteo_favorable', NULLIF(replace((vc.data::json -> 'meteo_cond'::text)::text, '"'::text, ''::text), 'null'::text), 'duree_transect', NULLIF(replace((vc.data::json -> 'duration'::text)::text, '"'::text, ''::text), 'null'::text), 'heure_debut', NULLIF(replace((vc.data::json -> 'start_time'::text)::text, '"'::text, ''::text), 'null'::text)) AS additional_data
FROM gn_monitoring.t_base_visits v
JOIN gn_monitoring.t_visit_complements vc ON v.id_base_visit = vc.id_base_visit
JOIN gn_monitoring.t_base_sites s ON s.id_base_site = v.id_base_site
JOIN gn_monitoring.t_site_complements sc ON s.id_base_site = sc.id_base_site
JOIN gn_commons.t_modules m ON m.id_module = v.id_module
JOIN gn_monitoring.t_observations o ON o.id_base_visit = v.id_base_visit
JOIN gn_monitoring.t_observation_complements oc ON oc.id_observation = o.id_observation
JOIN taxonomie.taxref t ON t.cd_nom = o.cd_nom
LEFT JOIN LATERAL ( SELECT array_agg(r.id_role) AS ids_observers,
string_agg(concat(r.nom_role, ' ', r.prenom_role), ' ; '::text) AS observers
FROM gn_monitoring.cor_visit_observer cvo
JOIN utilisateurs.t_roles r ON r.id_role = cvo.id_role
WHERE cvo.id_base_visit = v.id_base_visit) obs ON true
LEFT JOIN LATERAL ref_geo.fct_get_altitude_intersection(s.geom_local) alt(altitude_min, altitude_max) ON true
WHERE m.module_code::text = 'sterf'::text;
Loading