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

Ajout du reliquat (actions antérieures ajoutées ou mises à jour) dans le bilan hebdo #2078

Merged
merged 3 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/* Update analytics_actions views */
DROP MATERIALIZED VIEW analytics_actions;

CREATE MATERIALIZED VIEW public.analytics_actions AS

SELECT
a.id,
a.mission_id,
action_start_datetime_utc,
action_end_datetime_utc,
EXTRACT(year FROM action_start_datetime_utc) AS year,
m.start_datetime_utc AS mission_start_datetime_utc,
m.end_datetime_utc AS mission_end_datetime_utc,
m.created_at_utc AS mission_created_at_utc,
m.updated_at_utc AS mission_updated_at_utc,
mission_type,
action_type,
COALESCE(m.facade, 'Hors façade') AS mission_facade,
cu.id AS control_unit_id,
cu.name AS control_unit,
adm.name AS administration,
cu.name ILIKE 'ulam%' OR (
adm.name = 'DIRM / DM' AND
cu.name ILIKE 'PAM%'
) AS is_aff_mar,
(
cu.name ILIKE 'ulam%' OR (
adm.name = 'DIRM / DM' AND
cu.name ILIKE 'PAM%'
)
) OR adm.name IN ('Gendarmerie Nationale', 'Gendarmerie Maritime', 'Douane', 'Marine Nationale') AS is_aem,
CASE
WHEN cu.name ILIKE 'ulam%' OR (adm.name = 'DIRM / DM' AND cu.name ILIKE 'PAM%') THEN 'Affaires Maritimes'
WHEN adm.name IN ('Gendarmerie Nationale', 'Gendarmerie Maritime', 'Douane', 'Marine Nationale') THEN adm.name
ELSE 'Administrations hors AEM'
END AS administration_aem,
COALESCE(a.facade, 'Hors façade') AS action_facade,
COALESCE(a.department, 'Hors département') AS action_department,
CASE COALESCE(t3.theme, 'Aucun thème')
WHEN 'Activités et manifestations soumises à évaluation d’incidence Natura 2000' THEN 'EIN2000'
ELSE COALESCE(t3.theme, 'Aucun thème')
END AS theme_level_1,
COALESCE(t2.subtheme, 'Aucun sous-thème') AS theme_level_2,
CASE
WHEN t3.theme LIKE '%êche%' THEN 'PIRC'
ELSE 'PSCEM'
END AS plan,
CASE WHEN action_type = 'CONTROL' THEN ST_X(geom_element.geom) END AS longitude,
CASE WHEN action_type = 'CONTROL' THEN ST_Y(geom_element.geom) END AS latitude,
CASE WHEN action_type = 'CONTROL' THEN CASE WHEN jsonb_array_length(a.value->'infractions') > 0 THEN true ELSE false END END AS infraction,
(a.value->>'actionNumberOfControls')::DOUBLE PRECISION AS number_of_controls,
CASE WHEN action_type = 'SURVEILLANCE' THEN EXTRACT(epoch FROM a.action_end_datetime_utc - a.action_start_datetime_utc) / 3600.0 END AS surveillance_duration,
m.observations_cacem
FROM env_actions a
LEFT JOIN ST_Dump(a.geom) AS geom_element
ON true
LEFT JOIN env_actions_control_plan_themes t0 on t0.env_action_id = a.id
LEFT JOIN env_actions_control_plan_sub_themes t1 on t1.env_action_id = a.id
LEFT JOIN control_plan_sub_themes t2 on t2.id = t1.subtheme_id
LEFT JOIN control_plan_themes t3 on t3.id = t0.theme_id
JOIN missions m
ON a.mission_id = m.id
LEFT JOIN LATERAL unnest(mission_types) mission_type ON true
LEFT JOIN missions_control_units mcu
ON mcu.mission_id = m.id
LEFT JOIN control_units cu
ON cu.id = mcu.control_unit_id
LEFT JOIN administrations adm
ON adm.id = cu.administration_id
WHERE
NOT m.deleted AND
completion = 'COMPLETED' AND
action_type IN ('CONTROL', 'SURVEILLANCE') AND
(t2.id IS NULL OR t3.id IS NULL OR t2.theme_id = t3.id) AND
cu.id IS NOT NULL
ORDER BY action_start_datetime_utc DESC;

CREATE INDEX ON analytics_actions USING BRIN(action_start_datetime_utc);
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@ h1 {

h2 {
font-size: 1.414rem;
}

h3 {
font-size: 1.2rem;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,31 @@
<section>
<p>Bonjour,</p>
<p>Vous trouverez ci-dessous les données des <strong>contrôles</strong> et des <strong>surveillances de l'environnement marin</strong> effectués par votre unité
(<strong>{{ control_unit_name }}</strong>) <strong>entre le {{ from_date }} et le {{ to_date }}</strong> que vous avez rapportés au Centre d'Appui au Contrôle de l'Environnement Marin (CACEM).</p>
(<strong>{{ control_unit_name }}</strong>) <strong>entre le {{ from_date }} et le {{ to_date }}</strong> que vous avez rapportés au Centre d'Appui au Contrôle de l'Environnement Marin (CACEM),
ainsi que les éventuels contrôles et surveillances de l'environnement marin réalisés antérieurement et ayant été rapportés ou mis à jour pendant cette période.</p>
<p>Seuls les contrôles et surveillances dont les données sont complètes sont transmis dans ce bilan hebdomadaire. Si certaines données n'ont pas encore été transmises (par ex. l'établissement d'un PV ou non),
il est normal que le contrôle ne figure pas encore dans le rapport.</p>
<p>Si des données sont manquantes, incorrectes ou incomplètes, ou pour toute remarque concernant ce bilan, n'hésitez pas à <strong>contacter le CACEM : <a href="mailto:{{ cacem_email_address }}">{{ cacem_email_address }}</a></strong>.</p>
</section>
<hr />
<section>
<h2>Contrôles</h2>
<h2>Contrôles et surveillances réalisés la semaine passée</h2>
<h3>Contrôles</h3>
{{ controls }}

<h2>Surveillances</h2>
<h3>Surveillances</h3>
{{ surveillances }}
</section>
<hr />
<section>
<h2>Contrôles et surveillances antérieurs rapportés ou mis à jour la semaine passée</h2>
<h3>Contrôles</h3>
{{ late_controls }}

<h3>Surveillances</h3>
{{ late_surveillances }}
</section>
<hr />
<section>
<p>
Pour réaliser vos bilans, ces données sont stockées, mises en forme en tableaux de bord et accessibles en temps réel sur
Expand Down
2 changes: 2 additions & 0 deletions datascience/src/pipeline/entities/actions_emailing.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ class ControlUnitActions:
control_unit: ControlUnit
period: Period
controls: pd.DataFrame
late_controls: pd.DataFrame
surveillances: pd.DataFrame
late_surveillances: pd.DataFrame


@dataclass
Expand Down
55 changes: 45 additions & 10 deletions datascience/src/pipeline/flows/email_actions_to_units.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,22 @@ def to_control_unit_actions(
controls=env_actions[
(env_actions.action_type == EnvActionType.CONTROL.value)
& (env_actions.control_unit_id == control_unit.control_unit_id)
& (~env_actions.is_late_update)
].reset_index(drop=True),
late_controls=env_actions[
(env_actions.action_type == EnvActionType.CONTROL.value)
& (env_actions.control_unit_id == control_unit.control_unit_id)
& (env_actions.is_late_update)
].reset_index(drop=True),
surveillances=env_actions[
(env_actions.action_type == EnvActionType.SURVEILLANCE.value)
& (env_actions.control_unit_id == control_unit.control_unit_id)
& (~env_actions.is_late_update)
].reset_index(drop=True),
late_surveillances=env_actions[
(env_actions.action_type == EnvActionType.SURVEILLANCE.value)
& (env_actions.control_unit_id == control_unit.control_unit_id)
& (env_actions.is_late_update)
].reset_index(drop=True),
)
for control_unit in control_units
Expand Down Expand Up @@ -168,9 +180,8 @@ def format_themes(themes: dict) -> str:

return ", ".join(formatted_themes)

if len(control_unit_actions.controls) > 0:

controls = control_unit_actions.controls.copy(deep=True)
def render_controls(controls: pd.DataFrame) -> str:
controls = controls.copy(deep=True)

controls["number_of_controls"] = controls.number_of_controls.fillna(
0
Expand Down Expand Up @@ -200,13 +211,10 @@ def format_themes(themes: dict) -> str:

controls = controls[columns.keys()].rename(columns=columns)
controls = controls.to_html(index=False, border=1)
return controls

else:
controls = "Aucun"

if len(control_unit_actions.surveillances) > 0:

surveillances = control_unit_actions.surveillances.copy(deep=True)
def render_surveillances(surveillances: pd.DataFrame) -> str:
surveillances = surveillances.copy(deep=True)
surveillances[
"action_start_datetime_utc"
] = surveillances.action_start_datetime_utc.map(
Expand Down Expand Up @@ -234,13 +242,38 @@ def format_themes(themes: dict) -> str:

surveillances = surveillances[columns.keys()].rename(columns=columns)
surveillances = surveillances.to_html(index=False, border=1)
return surveillances

if len(control_unit_actions.controls) > 0:
controls = render_controls(control_unit_actions.controls)
else:
controls = "Aucun"

if len(control_unit_actions.surveillances) > 0:
surveillances = render_surveillances(
control_unit_actions.surveillances
)
else:
surveillances = "Aucune"

if len(control_unit_actions.late_controls) > 0:
late_controls = render_controls(control_unit_actions.late_controls)
else:
late_controls = "Aucun"

if len(control_unit_actions.late_surveillances) > 0:
late_surveillances = render_surveillances(
control_unit_actions.late_surveillances
)
else:
late_surveillances = "Aucune"

html = template.render(
control_unit_name=control_unit_actions.control_unit.control_unit_name,
controls=controls,
late_controls=late_controls,
surveillances=surveillances,
late_surveillances=late_surveillances,
from_date=control_unit_actions.period.start.strftime(
"%d/%m/%Y %H:%M UTC"
),
Expand Down Expand Up @@ -398,7 +431,9 @@ def send_env_actions_email(
actions_min_datetime_utc=actions.period.start,
actions_max_datetime_utc=actions.period.end,
number_of_actions=len(actions.controls)
+ len(actions.surveillances),
+ len(actions.surveillances)
+ len(actions.late_controls)
+ len(actions.late_surveillances),
success=success,
error_code=error_code,
error_message=error_message,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,37 @@ WITH actions_to_export AS (
action_department,
infraction,
number_of_controls,
surveillance_duration
surveillance_duration,
CASE
WHEN action_type = 'SURVEILLANCE' AND action_end_datetime_utc < :min_datetime_utc THEN true
WHEN action_type = 'CONTROL' AND action_start_datetime_utc < :min_datetime_utc THEN true
ELSE false
END AS is_late_update
FROM analytics_actions
WHERE (
action_type = 'SURVEILLANCE'
AND action_end_datetime_utc >= :min_datetime_utc
AND action_end_datetime_utc < :max_datetime_utc
AND (
(
action_end_datetime_utc >= :min_datetime_utc AND
action_end_datetime_utc < :max_datetime_utc
) OR (
action_end_datetime_utc < :min_datetime_utc AND
mission_updated_at_utc >= :min_datetime_utc AND
mission_updated_at_utc < :max_datetime_utc
)
)
) OR (
action_type = 'CONTROL'
AND action_start_datetime_utc >= :min_datetime_utc
AND action_start_datetime_utc < :max_datetime_utc
AND (
(
action_start_datetime_utc >= :min_datetime_utc AND
action_start_datetime_utc < :max_datetime_utc
) OR (
action_start_datetime_utc < :min_datetime_utc AND
mission_updated_at_utc >= :min_datetime_utc AND
mission_updated_at_utc < :max_datetime_utc
)
)
)
),

Expand All @@ -32,8 +53,7 @@ controls_average_positions AS (
FROM analytics_actions
WHERE
action_type = 'CONTROL'
AND action_start_datetime_utc >= :min_datetime_utc
AND action_start_datetime_utc < :max_datetime_utc
AND id IN (SELECT id FROM actions_to_export)
AND latitude IS NOT NULL
AND longitude IS NOT NULL
GROUP BY id
Expand Down
63 changes: 60 additions & 3 deletions datascience/tests/test_data/emails/expected_rendered_email.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ <h1 style="margin: 1.414rem 0 .5rem;font-weight: inherit;line-height: 1.42;margi
<section>
<p style="color: #777;font-size: 1rem;margin-bottom: 1.3rem;">Bonjour,</p>
<p style="color: #777;font-size: 1rem;margin-bottom: 1.3rem;">Vous trouverez ci-dessous les données des <strong style="font-weight: bold;">contrôles</strong> et des <strong style="font-weight: bold;">surveillances de l'environnement marin</strong> effectués par votre unité
(<strong style="font-weight: bold;">Nom de l'unité</strong>) <strong style="font-weight: bold;">entre le 23/06/2020 00:00 UTC et le 06/05/2020 18:45 UTC</strong> que vous avez rapportés au Centre d'Appui au Contrôle de l'Environnement Marin (CACEM).</p>
(<strong style="font-weight: bold;">Nom de l'unité</strong>) <strong style="font-weight: bold;">entre le 23/06/2020 00:00 UTC et le 06/05/2020 18:45 UTC</strong> que vous avez rapportés au Centre d'Appui au Contrôle de l'Environnement Marin (CACEM),
ainsi que les éventuels contrôles et surveillances de l'environnement marin réalisés antérieurement et ayant été rapportés ou mis à jour pendant cette période.</p>
<p style="color: #777;font-size: 1rem;margin-bottom: 1.3rem;">Seuls les contrôles et surveillances dont les données sont complètes sont transmis dans ce bilan hebdomadaire. Si certaines données n'ont pas encore été transmises (par ex. l'établissement d'un PV ou non),
il est normal que le contrôle ne figure pas encore dans le rapport.</p>
<p style="color: #777;font-size: 1rem;margin-bottom: 1.3rem;">Si des données sont manquantes, incorrectes ou incomplètes, ou pour toute remarque concernant ce bilan, n'hésitez pas à <strong style="font-weight: bold;">contacter le CACEM : <a href="mailto:[email protected]" style="color: #3498db;">[email protected]</a></strong>.</p>
</section>
<hr>
<section>
<h2 style="margin: 1.414rem 0 .5rem;font-weight: inherit;line-height: 1.42;font-size: 1.414rem;">Contrôles</h2>
<h2 style="margin: 1.414rem 0 .5rem;font-weight: inherit;line-height: 1.42;font-size: 1.414rem;">Contrôles et surveillances réalisés la semaine passée</h2>
<h3 style="margin: 1.414rem 0 .5rem;font-weight: inherit;line-height: 1.42;font-size: 1.2rem;">Contrôles</h3>
<table class="dataframe" border="1" style="border-collapse: collapse;margin: 25px 0;font-size: 1em;min-width: 400px;box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);margin-left: auto;margin-right: auto;">
<thead>
<tr style="text-align: right;background-color: rgb(59, 69, 89);color: #ffffff">
Expand All @@ -45,7 +47,7 @@ <h2 style="margin: 1.414rem 0 .5rem;font-weight: inherit;line-height: 1.42;font-
</tbody>
</table>

<h2 style="margin: 1.414rem 0 .5rem;font-weight: inherit;line-height: 1.42;font-size: 1.414rem;">Surveillances</h2>
<h3 style="margin: 1.414rem 0 .5rem;font-weight: inherit;line-height: 1.42;font-size: 1.2rem;">Surveillances</h3>
<table class="dataframe" border="1" style="border-collapse: collapse;margin: 25px 0;font-size: 1em;min-width: 400px;box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);margin-left: auto;margin-right: auto;">
<thead>
<tr style="text-align: right;background-color: rgb(59, 69, 89);color: #ffffff">
Expand Down Expand Up @@ -78,6 +80,61 @@ <h2 style="margin: 1.414rem 0 .5rem;font-weight: inherit;line-height: 1.42;font-
<td style="padding: 12px 15px;">Activités et manifestations soumises à évaluation d’incidence Natura 2000 (Aucun sous-thème)</td>
</tr>
</tbody>
</table>
</section>
<hr>
<section>
<h2 style="margin: 1.414rem 0 .5rem;font-weight: inherit;line-height: 1.42;font-size: 1.414rem;">Contrôles et surveillances antérieurs rapportés ou mis à jour la semaine passée</h2>
<h3 style="margin: 1.414rem 0 .5rem;font-weight: inherit;line-height: 1.42;font-size: 1.2rem;">Contrôles</h3>
<table class="dataframe" border="1" style="border-collapse: collapse;margin: 25px 0;font-size: 1em;min-width: 400px;box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);margin-left: auto;margin-right: auto;">
<thead>
<tr style="text-align: right;background-color: rgb(59, 69, 89);color: #ffffff">
<th style="padding: 12px 15px;">Date du contrôle</th>
<th style="padding: 12px 15px;">Type de mission</th>
<th style="padding: 12px 15px;">Façade</th>
<th style="padding: 12px 15px;">Département</th>
<th style="padding: 12px 15px;">Infraction relevée</th>
<th style="padding: 12px 15px;">Nombre de contrôles</th>
<th style="padding: 12px 15px;">Thématique(s) de contrôle</th>
</tr>
</thead>
<tbody>
<tr style="border-bottom: 2px solid rgb(59, 69, 89);">
<td style="padding: 12px 15px;">2022-11-24 20:31</td>
<td style="padding: 12px 15px;">Mer</td>
<td style="padding: 12px 15px;">Hors façade</td>
<td style="padding: 12px 15px;">Hors département</td>
<td style="padding: 12px 15px;">Non</td>
<td style="padding: 12px 15px;">0</td>
<td style="padding: 12px 15px;">Aucun thème (Aucun sous-thème)</td>
</tr>
</tbody>
</table>

<h3 style="margin: 1.414rem 0 .5rem;font-weight: inherit;line-height: 1.42;font-size: 1.2rem;">Surveillances</h3>
<table class="dataframe" border="1" style="border-collapse: collapse;margin: 25px 0;font-size: 1em;min-width: 400px;box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);margin-left: auto;margin-right: auto;">
<thead>
<tr style="text-align: right;background-color: rgb(59, 69, 89);color: #ffffff">
<th style="padding: 12px 15px;">Début de surveillance</th>
<th style="padding: 12px 15px;">Fin de surveillance</th>
<th style="padding: 12px 15px;">Type de mission</th>
<th style="padding: 12px 15px;">Façade</th>
<th style="padding: 12px 15px;">Département</th>
<th style="padding: 12px 15px;">Durée (h)</th>
<th style="padding: 12px 15px;">Thématique(s) de surveillance</th>
</tr>
</thead>
<tbody>
<tr style="border-bottom: 2px solid rgb(59, 69, 89);">
<td style="padding: 12px 15px;">2022-11-28 13:59</td>
<td style="padding: 12px 15px;">2022-12-05 19:59</td>
<td style="padding: 12px 15px;">Mer</td>
<td style="padding: 12px 15px;">Hors façade</td>
<td style="padding: 12px 15px;">Hors département</td>
<td style="padding: 12px 15px;">54.0</td>
<td style="padding: 12px 15px;">Culture marine (Implantation), Police des espèces protégées et de leurs habitats (faune et flore) (Dérogations concernant les espèces protégées, Détention d'espèces protégées)</td>
</tr>
</tbody>
</table>
</section>
<hr>
Expand Down
Loading
Loading