Skip to content

Commit

Permalink
Notifications pour réutilisateurs : erreurs et ressources indisponibl…
Browse files Browse the repository at this point in the history
…es (#3353)

* Notification pour JDD avec erreurs pour réutilisateurs

* Add missing template

* Different content for resource_unavailable notification

* Add comment to describe :source

* Refactor to use .md template
  • Loading branch information
AntoineAugusti authored Jul 27, 2023
1 parent ab2f338 commit 3b75e8c
Show file tree
Hide file tree
Showing 10 changed files with 239 additions and 84 deletions.
34 changes: 33 additions & 1 deletion apps/transport/lib/db/notification_subscription.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,18 @@ defmodule DB.NotificationSubscription do
@hidden_reasons_related_to_datasets [:dataset_now_on_nap, :resources_changed]
# These notification reasons are *not* linked to a specific dataset, `dataset_id` should be nil
@platform_wide_reasons [:new_dataset, :datasets_switching_climate_resilience_bill, :daily_new_comments]
@possible_roles [:producer, :reuser]
@type role :: :producer | :reuser

typed_schema "notification_subscription" do
field(:reason, Ecto.Enum,
values: @reasons_related_to_datasets ++ @platform_wide_reasons ++ @hidden_reasons_related_to_datasets
)

# Useful to know if the subscription has been created by an admin
# from the backoffice (`:admin`) or by the user (`:user`)
field(:source, Ecto.Enum, values: [:admin, :user])
field(:role, Ecto.Enum, values: [:producer, :reuser])
field(:role, Ecto.Enum, values: @possible_roles)

belongs_to(:contact, DB.Contact)
belongs_to(:dataset, DB.Dataset)
Expand Down Expand Up @@ -83,6 +87,26 @@ defmodule DB.NotificationSubscription do
|> DB.Repo.all()
end

@spec subscriptions_for_reason_dataset_and_role(atom(), DB.Dataset.t(), role()) :: [__MODULE__.t()]
def subscriptions_for_reason_dataset_and_role(reason, %DB.Dataset{id: dataset_id}, role)
when role in @possible_roles do
base_query()
|> preload([:contact])
|> where(
[notification_subscription: ns],
ns.reason == ^reason and ns.dataset_id == ^dataset_id and ns.role == ^role
)
|> DB.Repo.all()
end

@spec subscriptions_for_reason_and_role(atom(), role()) :: [__MODULE__.t()]
def subscriptions_for_reason_and_role(reason, role) when role in @possible_roles do
base_query()
|> preload([:contact])
|> where([notification_subscription: ns], ns.reason == ^reason and is_nil(ns.dataset_id) and ns.role == ^role)
|> DB.Repo.all()
end

@spec subscriptions_for_dataset(DB.Dataset.t()) :: [__MODULE__.t()]
def subscriptions_for_dataset(%DB.Dataset{id: dataset_id}) do
base_query()
Expand All @@ -91,6 +115,14 @@ defmodule DB.NotificationSubscription do
|> DB.Repo.all()
end

@spec subscriptions_for_dataset_and_role(DB.Dataset.t(), role()) :: [__MODULE__.t()]
def subscriptions_for_dataset_and_role(%DB.Dataset{id: dataset_id}, role) when role in @possible_roles do
base_query()
|> preload([:contact])
|> where([notification_subscription: ns], ns.dataset_id == ^dataset_id and ns.role == ^role)
|> DB.Repo.all()
end

@spec subscriptions_to_emails([__MODULE__.t()]) :: [binary()]
def subscriptions_to_emails(subscriptions) do
subscriptions |> Enum.map(& &1.contact.email)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,40 +26,42 @@ defmodule Transport.Jobs.MultiValidationWithErrorNotificationJob do
inserted_at
|> relevant_validations()
|> Enum.each(fn {%DB.Dataset{} = dataset, multi_validations} ->
dataset
|> emails_list()
|> MapSet.difference(notifications_sent_recently(dataset))
|> Enum.each(fn email ->
Transport.EmailSender.impl().send_mail(
"transport.data.gouv.fr",
Application.get_env(:transport, :contact_email),
email,
Application.get_env(:transport, :contact_email),
"Erreurs détectées dans le jeu de données #{dataset.custom_title}",
"""
Bonjour,
producer_emails = dataset |> emails_list(:producer)
send_to_producers(producer_emails, dataset, multi_validations)

Des erreurs bloquantes ont été détectées dans votre jeu de données #{dataset_url(dataset)}. Ces erreurs empêchent la réutilisation de vos données.
Nous vous invitons à les corriger en vous appuyant sur les rapports de validation suivants :
#{Enum.map_join(multi_validations, "\n", &resource_link/1)}
Nous restons disponible pour vous accompagner si besoin.
Merci par avance pour votre action,
reuser_emails = dataset |> emails_list(:reuser)
send_to_reusers(reuser_emails, dataset, producer_warned: not Enum.empty?(producer_emails))
end)
end

À bientôt,
defp send_to_reusers(emails, %DB.Dataset{} = dataset, producer_warned: producer_warned) do
Enum.each(emails, &send_mail(&1, :reuser, dataset: dataset, producer_warned: producer_warned))
end

L'équipe du PAN
""",
""
)
defp send_to_producers(emails, %DB.Dataset{} = dataset, multi_validations) do
Enum.each(
emails,
&send_mail(&1, :producer,
dataset: dataset,
resources: Enum.map(multi_validations, fn mv -> mv.resource_history.resource end)
)
)
end

save_notification(dataset, email)
end)
end)
defp send_mail(email, role, args) do
dataset = Keyword.fetch!(args, :dataset)

Transport.EmailSender.impl().send_mail(
"transport.data.gouv.fr",
Application.get_env(:transport, :contact_email),
email,
Application.get_env(:transport, :contact_email),
"Erreurs détectées dans le jeu de données #{dataset.custom_title}",
"",
Phoenix.View.render_to_string(TransportWeb.EmailView, "#{@notification_reason}_#{role}.html", args)
)

:ok
save_notification(dataset, email)
end

defp notifications_sent_recently(%DB.Dataset{id: dataset_id}) do
Expand Down Expand Up @@ -91,24 +93,11 @@ defmodule Transport.Jobs.MultiValidationWithErrorNotificationJob do
|> Enum.group_by(& &1.resource_history.resource.dataset)
end

defp emails_list(%DB.Dataset{} = dataset) do
defp emails_list(%DB.Dataset{} = dataset, role) do
@notification_reason
|> DB.NotificationSubscription.subscriptions_for_reason(dataset)
|> DB.NotificationSubscription.subscriptions_for_reason_dataset_and_role(dataset, role)
|> DB.NotificationSubscription.subscriptions_to_emails()
|> MapSet.new()
end

defp dataset_url(%DB.Dataset{slug: slug, custom_title: custom_title}) do
url = TransportWeb.Router.Helpers.dataset_url(TransportWeb.Endpoint, :details, slug)

"#{custom_title}#{url}"
end

defp resource_link(%DB.MultiValidation{
resource_history: %DB.ResourceHistory{resource: %DB.Resource{id: id, title: title}}
}) do
url = TransportWeb.Router.Helpers.resource_url(TransportWeb.Endpoint, :details, id) <> "#validation-report"

"* #{title}#{url}"
|> MapSet.difference(notifications_sent_recently(dataset))
end
end
69 changes: 45 additions & 24 deletions apps/transport/lib/jobs/resource_unavailable_notification_job.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,30 +21,50 @@ defmodule Transport.Jobs.ResourceUnavailableNotificationJob do
inserted_at
|> relevant_unavailabilities()
|> Enum.each(fn {%DB.Dataset{} = dataset, unavailabilities} ->
dataset
|> emails_list()
|> MapSet.difference(notifications_sent_recently(dataset))
|> Enum.each(fn email ->
Transport.EmailSender.impl().send_mail(
"transport.data.gouv.fr",
Application.get_env(:transport, :contact_email),
email,
Application.get_env(:transport, :contact_email),
"Ressources indisponibles dans le jeu de données #{dataset.custom_title}",
"",
Phoenix.View.render_to_string(TransportWeb.EmailView, "resource_unavailable.html",
dataset: dataset,
hours_consecutive_downtime: @hours_consecutive_downtime,
deleted_recreated_on_datagouv: deleted_and_recreated_resource_hosted_on_datagouv(dataset, unavailabilities),
resource_titles: Enum.map_join(unavailabilities, ", ", &resource_title/1)
)
)

save_notification(dataset, email)
end)
producer_emails = emails_list(dataset, :producer)
send_to_producers(producer_emails, dataset, unavailabilities)

reuser_emails = emails_list(dataset, :reuser)
send_to_reusers(reuser_emails, dataset, unavailabilities, producer_warned: not Enum.empty?(producer_emails))
end)
end

defp send_to_reusers(emails, %DB.Dataset{} = dataset, unavailabilities, producer_warned: producer_warned) do
Enum.each(emails, fn email ->
send_mail(email, :reuser,
dataset: dataset,
hours_consecutive_downtime: @hours_consecutive_downtime,
producer_warned: producer_warned,
resource_titles: Enum.map_join(unavailabilities, ", ", &resource_title/1)
)
end)
end

defp send_to_producers(emails, dataset, unavailabilities) do
Enum.each(emails, fn email ->
send_mail(email, :producer,
dataset: dataset,
hours_consecutive_downtime: @hours_consecutive_downtime,
deleted_recreated_on_datagouv: deleted_and_recreated_resource_hosted_on_datagouv(dataset, unavailabilities),
resource_titles: Enum.map_join(unavailabilities, ", ", &resource_title/1)
)
end)
end

defp send_mail(email, role, args) do
dataset = Keyword.fetch!(args, :dataset)

Transport.EmailSender.impl().send_mail(
"transport.data.gouv.fr",
Application.get_env(:transport, :contact_email),
email,
Application.get_env(:transport, :contact_email),
"Ressources indisponibles dans le jeu de données #{dataset.custom_title}",
"",
Phoenix.View.render_to_string(TransportWeb.EmailView, "#{@notification_reason}_#{role}.html", args)
)

:ok
save_notification(dataset, email)
end

defp notifications_sent_recently(%DB.Dataset{id: dataset_id}) do
Expand Down Expand Up @@ -105,11 +125,12 @@ defmodule Transport.Jobs.ResourceUnavailableNotificationJob do
DB.Notification.insert!(@notification_reason, dataset, email)
end

defp emails_list(%DB.Dataset{} = dataset) do
defp emails_list(%DB.Dataset{} = dataset, role) do
@notification_reason
|> DB.NotificationSubscription.subscriptions_for_reason(dataset)
|> DB.NotificationSubscription.subscriptions_for_reason_dataset_and_role(dataset, role)
|> DB.NotificationSubscription.subscriptions_to_emails()
|> MapSet.new()
|> MapSet.difference(notifications_sent_recently(dataset))
end

defp resource_title(%DB.ResourceUnavailability{resource: %DB.Resource{title: title}}) do
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Bonjour,

Des erreurs bloquantes ont été détectées dans votre jeu de données <%= link_for_dataset(@dataset, :heex) %>. Ces erreurs empêchent la réutilisation de vos données.

Nous vous invitons à les corriger en vous appuyant sur les rapports de validation suivants :
<%= for resource <- @resources do %>
<%= link_for_resource(resource) %>
<% end %>

Nous restons disponible pour vous accompagner si besoin.

Merci par avance pour votre action,

À bientôt,

L'équipe du PAN
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Bonjour,

Des erreurs bloquantes ont été détectées dans le jeu de données <%= link_for_dataset(@dataset, :heex) %> que vous réutilisez.

<%= if @producer_warned do %>
Le producteur de ces données a été informé de ces erreurs.
<% end %>

L’équipe du PAN
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Bonjour,

Les ressources <%= @resource_titles %> du jeu de données <%= link_for_dataset(@dataset, :heex) %> que vous réutilisez ne sont plus disponibles au téléchargement depuis plus de <%= @hours_consecutive_downtime %>h.

<%= if @producer_warned do %>
Le producteur de ces données a été informé de cette indisponibilité.
<% end %>

L’équipe du PAN
5 changes: 5 additions & 0 deletions apps/transport/lib/transport_web/views/email_view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,9 @@ defmodule TransportWeb.EmailView do
:heex -> link(custom_title, to: url)
end
end

def link_for_resource(%DB.Resource{id: id, title: title}) do
url = TransportWeb.Router.Helpers.resource_url(TransportWeb.Endpoint, :details, id)
link(title, to: url)
end
end
Loading

0 comments on commit 3b75e8c

Please sign in to comment.