From d837a2ed0f4b60da7c695f393e5610d4c0c6d6cf Mon Sep 17 00:00:00 2001 From: ZAYTOUN abdellatif <zaytoun.abdellatif@gmail.com> Date: Fri, 4 Apr 2025 02:13:40 +0200 Subject: [PATCH] feat(): Emails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Internationaliser les sujets des emails. - Arrêter l'envoi des mails : ATTENTION : un expert non-activé a été sollicité. --- .../selexpert/service/MessagingService.java | 75 ++++++++---------- src/main/resources/lang/messages.properties | 24 +++++- .../resources/lang/messages_en.properties | 24 +++++- .../emails/expert-not-activated.ftlh | 8 -- .../en/emails/expert-not-activated.ftlh | 8 -- .../service/MessagingServiceTest.java | 77 ++++++++++++------- 6 files changed, 126 insertions(+), 90 deletions(-) delete mode 100644 src/main/resources/templates/emails/expert-not-activated.ftlh delete mode 100644 src/main/resources/templates/en/emails/expert-not-activated.ftlh diff --git a/src/main/java/fr/gouv/beta/selexpert/service/MessagingService.java b/src/main/java/fr/gouv/beta/selexpert/service/MessagingService.java index 3adc80f..10eb462 100644 --- a/src/main/java/fr/gouv/beta/selexpert/service/MessagingService.java +++ b/src/main/java/fr/gouv/beta/selexpert/service/MessagingService.java @@ -410,17 +410,7 @@ public class MessagingService { request.getId(), "selexpertUrl", selexpertUrl)); - if (!activated) { // non activated user, warn ourselves - var emailModelForUs = new HashMap<String, Object>(); - emailModelForUs.put("expert", expert.getName()); - emailModelForUs.put("expertAppealCourt", expert.getAppealCourt().getName()); - emailModelForUs.put("procedureId", request.getProcedureId()); - emailModelForUs.put("requestId", request.getId()); - emailModelForUs.put("jurisdiction", request.getJurisdiction().getName()); - emailModelForUs.put( - "appealCourt", request.getJurisdiction().getAppealCourt().getName()); - send(senderEmail, Email.EXPERT_NOT_ACTIVATED, emailModelForUs); - } + toSend.updateStatus(RequestExpertStatus.SENT); toSend.setSentOn(now); // all requestExperts should have the same time // if urgent, possibly problematic if re1 sent at 23:59:59 and re2 at 00:00 @@ -458,7 +448,7 @@ public class MessagingService { try { mailService.send( to, - email.subject, + translationService.getMessage(email.subjectKey), FreeMarkerTemplateUtils.processTemplateIntoString( freeMarkerConfiguration.getTemplate(email.template + ".ftlh"), emailModel)); } catch (Exception e) { @@ -521,50 +511,45 @@ public class MessagingService { public enum Email { // AUTH - USER_ACTIVATION("Lien d'activation de compte", "user-activation"), - PASSWORD_RESET("Réinitialisation de votre mot de passe", "password-reset"), + USER_ACTIVATION("user-activation"), + PASSWORD_RESET("password-reset"), // COURT (MAGISTRATE / CLERK) - REQUEST_ACCEPTED("Demande acceptée", "request-accepted"), - REQUEST_REFUSED("Un expert a refusé", "request-refused", true), - REQUEST_REFUSED_ALL("Tous les experts ont refusé", "request-refused-all"), - REQUEST_DELIBERATION_REMINDER( - "La date du délibéré approche", "request-deliberation-reminder", true), - QUESTION_ASKED("Une question a été posée", "question-asked"), - QUESTION_REMINDER("Rappel : une question a été posée", "question-reminder"), + REQUEST_ACCEPTED("request-accepted"), + REQUEST_REFUSED("request-refused", true), + REQUEST_REFUSED_ALL("request-refused-all"), + REQUEST_DELIBERATION_REMINDER("request-deliberation-reminder", true), + QUESTION_ASKED("question-asked"), + QUESTION_REMINDER("question-reminder"), // CLERK - REQUEST_ASSIGNED("Rattachement à une demande d'expertise", "request-assigned", true), + REQUEST_ASSIGNED("request-assigned", true), // EXPERT - REQUEST_CREATED("Nouvelle demande d'expertise", "request-created"), - REQUEST_ACCEPTED_ACK("Demande acceptée", "request-accepted-ack"), - REQUEST_FULFILLED("Demande annulée", "request-fulfilled"), - REQUEST_CANCELLED("Demande annulée", "request-cancelled"), - REQUEST_REFUSED_AUTO("Refus automatique d'une demande", "request-refused-auto"), - REQUEST_REFUSED_ACK("Demande refusée", "request-refused-ack"), - DECISION_ADDED("Décision disponible", "decision-added"), - EXPERT_IS_NOW_AVAILABLE("Votre disponibilité", "expert-is-now-available"), - EXPERT_IS_STILL_UNAVAILABLE("Votre indisponibilité", "expert-is-still-unavailable"), - QUESTION_ANSWERED("Réponse à votre question", "question-answered"), - EXPERT_REMINDER("Rappel : demande d'expertise", "expert-reminder"), - DEADLINE_EXTENDED("Prolongation du délai de réponse", "request-deadline-extended"), - - // ADMIN - EXPERT_NOT_ACTIVATED( - "ATTENTION : un expert non-activé a été sollicité", "expert-not-activated"); - - private final String subject; + REQUEST_CREATED("request-created"), + REQUEST_ACCEPTED_ACK("request-accepted-ack"), + REQUEST_FULFILLED("request-fulfilled"), + REQUEST_CANCELLED("request-cancelled"), + REQUEST_REFUSED_AUTO("request-refused-auto"), + REQUEST_REFUSED_ACK("request-refused-ack"), + DECISION_ADDED("decision-added"), + EXPERT_IS_NOW_AVAILABLE("expert-is-now-available"), + EXPERT_IS_STILL_UNAVAILABLE("expert-is-still-unavailable"), + QUESTION_ANSWERED("question-answered"), + EXPERT_REMINDER("expert-reminder"), + DEADLINE_EXTENDED("request-deadline-extended"); + + private final String subjectKey; private final String template; private final boolean optional; - Email(String subject, String template, boolean optional) { - this.subject = subject; - this.template = "emails/" + template; + Email(String subjectKey, boolean optional) { + this.subjectKey = subjectKey; + this.template = "emails/" + subjectKey; this.optional = optional; } - Email(String subject, String template) { - this(subject, template, false); + Email(String subjectKey) { + this(subjectKey, false); } } diff --git a/src/main/resources/lang/messages.properties b/src/main/resources/lang/messages.properties index 878d576..1f410c8 100644 --- a/src/main/resources/lang/messages.properties +++ b/src/main/resources/lang/messages.properties @@ -2,4 +2,26 @@ requestType.penal=p\u00E9nale requestType.civil=civile (autre que r\u00E9f\u00E9r\u00E9) requestType.summary_proceedings=en r\u00E9f\u00E9r\u00E9 requestType.control_penal=de contr\u00F4le des expertises p\u00E9nales -requestType.control_civil=de contr\u00F4le des expertises civiles \ No newline at end of file +requestType.control_civil=de contr\u00F4le des expertises civiles +# Emails subjects +user-activation=Lien d'activation de compte +password-reset=R\u00E9initialisation de votre mot de passe +request-accepted=Demande accept\u00E9e +request-refused=Un expert a refus\u00E9 +request-refused-all=Tous les experts ont refus\u00E9 +request-deliberation-reminder=La date du d\u00E9lib\u00E9r\u00E9 approche +question-asked=Une question a \u00E9t\u00E9 pos\u00E9e +question-reminder=Rappel : une question a \u00E9t\u00E9 pos\u00E9e +request-assigned=Rattachement \u00E0 une demande d'expertise +request-created=Nouvelle demande d'expertise +request-accepted-ack=Demande accept\u00E9e +request-fulfilled=Demande annul\u00E9e +request-cancelled=Demande annul\u00E9e +request-refused-auto=Refus automatique d'une demande +request-refused-ack=Demande refus\u00E9e +decision-added=D\u00E9cision disponible +expert-is-now-available=Votre disponibilit\u00E9 +expert-is-still-unavailable=Votre indisponibilit\u00E9 +question-answered=R\u00E9ponse \u00E0 votre question +expert-reminder=Rappel : demande d'expertise +request-deadline-extended=Prolongation du d\u00E9lai de r\u00E9ponse \ No newline at end of file diff --git a/src/main/resources/lang/messages_en.properties b/src/main/resources/lang/messages_en.properties index 5633589..6af6ed4 100644 --- a/src/main/resources/lang/messages_en.properties +++ b/src/main/resources/lang/messages_en.properties @@ -2,4 +2,26 @@ requestType.penal=penal requestType.civil=civil requestType.summary_proceedings=summary proceedings requestType.control_penal=penal expert Report Review -requestType.control_civil=civil expert Report Review \ No newline at end of file +requestType.control_civil=civil expert Report Review +# Emails subjects +user-activation=Account activation link +password-reset=Password reset +request-accepted=Request accepted +request-refused=An expert has refused +request-refused-all=All experts refused +request-deliberation-reminder=Deliberation date approaching +question-asked=A question has been asked +question-reminder=Reminder: a question has been asked +request-assigned=Assigned to an expertise request +request-created=New expertise request +request-accepted-ack=Request accepted +request-fulfilled=Request cancelled +request-cancelled=Request cancelled +request-refused-auto=Automatic request refusal +request-refused-ack=Request refused +decision-added=Decision available +expert-is-now-available=Your availability +expert-is-still-unavailable=Your unavailability +question-answered=Answer to your question +expert-reminder=Reminder: expertise request +request-deadline-extended=Response deadline extended \ No newline at end of file diff --git a/src/main/resources/templates/emails/expert-not-activated.ftlh b/src/main/resources/templates/emails/expert-not-activated.ftlh deleted file mode 100644 index 3d39763..0000000 --- a/src/main/resources/templates/emails/expert-not-activated.ftlh +++ /dev/null @@ -1,8 +0,0 @@ -<#import "common.ftlh" as c> -<@c.base> - <p>L'expert <b>${expert}</b> (${expertAppealCourt}) n'a toujours pas activé son compte. - </p> - <p>Il vient d'être sollicité pour la - <a href="${selexpertUrl}/demande/${requestId?c}">demande ${procedureId}</a> - (${appealCourt} > ${jurisdiction}).</p> -</@c.base> \ No newline at end of file diff --git a/src/main/resources/templates/en/emails/expert-not-activated.ftlh b/src/main/resources/templates/en/emails/expert-not-activated.ftlh deleted file mode 100644 index e6b0226..0000000 --- a/src/main/resources/templates/en/emails/expert-not-activated.ftlh +++ /dev/null @@ -1,8 +0,0 @@ -<#import "common.ftlh" as c> -<@c.base> - <p>The expert <b>${expert}</b> (${expertAppealCourt}) has not yet activated their account. - </p> - <p>They have just been approached for the - <a href="${selexpertUrl}/demande/${requestId?c}">request ${procedureId}</a> - (${appealCourt} > ${jurisdiction}).</p> -</@c.base> \ No newline at end of file diff --git a/src/test/java/fr/gouv/beta/selexpert/service/MessagingServiceTest.java b/src/test/java/fr/gouv/beta/selexpert/service/MessagingServiceTest.java index 47a9bac..43e4d72 100644 --- a/src/test/java/fr/gouv/beta/selexpert/service/MessagingServiceTest.java +++ b/src/test/java/fr/gouv/beta/selexpert/service/MessagingServiceTest.java @@ -138,6 +138,8 @@ class MessagingServiceTest { .willReturn(List.of(requestExpert, requestExpert2, requestExpert3)); when(translationService.format(anyString(), any(LocalDateTime.class))).thenReturn(""); + when(translationService.getMessage(Email.REQUEST_CREATED.getSubjectKey())) + .thenReturn("request-created"); // WHEN messagingService.onRequestCreated(new RequestCreatedEvent(request)); @@ -147,11 +149,9 @@ class MessagingServiceTest { then(requestExpert2.getStatus()).isEqualTo(RequestExpertStatus.SENT); then(requestExpert.getSentOn()).isNotNull(); then(requestExpert.getSentOn()).isEqualTo(requestExpert2.getSentOn()); - verify(mailService).send("1@expert.com", Email.REQUEST_CREATED.getSubject(), ""); - verify(mailService).send("2@userexpert.com", Email.REQUEST_CREATED.getSubject(), ""); - verify(mailService).send("3@userexpert.com", Email.REQUEST_CREATED.getSubject(), ""); - verify(mailService) - .send("contact@selexpert.beta.gouv.fr", Email.EXPERT_NOT_ACTIVATED.getSubject(), ""); + verify(mailService).send("1@expert.com", "request-created", ""); + verify(mailService).send("2@userexpert.com", "request-created", ""); + verify(mailService).send("3@userexpert.com", "request-created", ""); verify(smsService).send("0606060603", ""); verify(smsService, times(0)).send("0606060602", ""); } @@ -168,12 +168,15 @@ class MessagingServiceTest { given(requestExpertRepository.findByRequestAndStatus(request, RequestExpertStatus.SENDING)) .willReturn(List.of()); + when(translationService.getMessage(Email.REQUEST_ASSIGNED.getSubjectKey())) + .thenReturn("request-assigned"); + // WHEN messagingService.onRequestCreated(new RequestCreatedEvent(request)); // THEN - verify(mailService, times(0)).send("1@clerk.com", Email.REQUEST_ASSIGNED.getSubject(), ""); - verify(mailService, times(1)).send("2@clerk.com", Email.REQUEST_ASSIGNED.getSubject(), ""); + verify(mailService, times(0)).send("1@clerk.com", "request-assigned", ""); + verify(mailService, times(1)).send("2@clerk.com", "request-assigned", ""); } @Test @@ -184,15 +187,18 @@ class MessagingServiceTest { UserClerk clerkAllNotifsTrue = makeClerk(2, true); UserClerk clerkAllNotifsFalse = makeClerk(3, false); + when(translationService.getMessage(Email.REQUEST_ASSIGNED.getSubjectKey())) + .thenReturn("request-assigned"); + // WHEN messagingService.onClerksAdded( new ClerksAddedEvent( new Request(), List.of(clerkAllNotifsNull, clerkAllNotifsTrue, clerkAllNotifsFalse))); // THEN - verify(mailService, times(1)).send("1@clerk.com", Email.REQUEST_ASSIGNED.getSubject(), ""); - verify(mailService, times(1)).send("2@clerk.com", Email.REQUEST_ASSIGNED.getSubject(), ""); - verify(mailService, times(0)).send("3@clerk.com", Email.REQUEST_ASSIGNED.getSubject(), ""); + verify(mailService, times(1)).send("1@clerk.com", "request-assigned", ""); + verify(mailService, times(1)).send("2@clerk.com", "request-assigned", ""); + verify(mailService, times(0)).send("3@clerk.com", "request-assigned", ""); } @Test @@ -208,16 +214,23 @@ class MessagingServiceTest { request.getRequestExperts().addAll(List.of(requestExpertAccepted, requestExpertFulfilled)); request.setRequestClerks(List.of(makeClerk(1, true), makeClerk(2, false))); + when(translationService.getMessage(Email.REQUEST_ACCEPTED.getSubjectKey())) + .thenReturn("request-accepted"); + when(translationService.getMessage(Email.REQUEST_ACCEPTED_ACK.getSubjectKey())) + .thenReturn("request-accepted-ack"); + when(translationService.getMessage(Email.REQUEST_FULFILLED.getSubjectKey())) + .thenReturn("request-fulfilled"); + // WHEN messagingService.onRequestAccepted( new RequestAcceptedEvent(request, requestExpertAccepted.getExpert())); // THEN - verify(mailService).send("1@magistrate.com", Email.REQUEST_ACCEPTED.getSubject(), ""); - verify(mailService).send("1@clerk.com", Email.REQUEST_ACCEPTED.getSubject(), ""); - verify(mailService).send("2@clerk.com", Email.REQUEST_ACCEPTED.getSubject(), ""); - verify(mailService).send("1@userexpert.com", Email.REQUEST_ACCEPTED_ACK.getSubject(), ""); - verify(mailService).send("2@expert.com", Email.REQUEST_FULFILLED.getSubject(), ""); + verify(mailService).send("1@magistrate.com", "request-accepted", ""); + verify(mailService).send("1@clerk.com", "request-accepted", ""); + verify(mailService).send("2@clerk.com", "request-accepted", ""); + verify(mailService).send("1@userexpert.com", "request-accepted-ack", ""); + verify(mailService).send("2@expert.com", "request-fulfilled", ""); } @ParameterizedTest @@ -241,10 +254,19 @@ class MessagingServiceTest { .willReturn(List.of(requestExpertSending)); when(requestService.isRequestAtFinalExpert(request)).thenReturn(true); + + when(translationService.getMessage(Email.REQUEST_REFUSED.getSubjectKey())) + .thenReturn("request-refused"); + when(translationService.getMessage(Email.REQUEST_CREATED.getSubjectKey())) + .thenReturn("request-created"); + } else { + when(translationService.getMessage(Email.REQUEST_REFUSED_ALL.getSubjectKey())) + .thenReturn("request-refused-all"); } - when(translationService.format(anyString(), any(LocalDateTime.class))) - .thenReturn(""); + when(translationService.format(anyString(), any(LocalDateTime.class))).thenReturn(""); + when(translationService.getMessage(Email.REQUEST_REFUSED_ACK.getSubjectKey())) + .thenReturn("request-refused-ack"); // WHEN messagingService.onRequestRefused( @@ -253,13 +275,9 @@ class MessagingServiceTest { // THEN verify(mailService) - .send( - "1@magistrate.com", - open ? Email.REQUEST_REFUSED.getSubject() : Email.REQUEST_REFUSED_ALL.getSubject(), - ""); - verify(mailService).send("1@userexpert.com", Email.REQUEST_REFUSED_ACK.getSubject(), ""); - verify(mailService, times(open ? 1 : 0)) - .send("2@userexpert.com", Email.REQUEST_CREATED.getSubject(), ""); + .send("1@magistrate.com", open ? "request-refused" : "request-refused-all", ""); + verify(mailService).send("1@userexpert.com", "request-refused-ack", ""); + verify(mailService, times(open ? 1 : 0)).send("2@userexpert.com", "request-created", ""); } @Test @@ -275,6 +293,11 @@ class MessagingServiceTest { makeRequestExpert(RequestExpertStatus.REFUSED_AUTO, request, 2, true).build(); request.getRequestExperts().add(requestExpertAuto2); + when(translationService.getMessage(Email.REQUEST_REFUSED_ALL.getSubjectKey())) + .thenReturn("request-refused-all"); + when(translationService.getMessage(Email.REQUEST_REFUSED_AUTO.getSubjectKey())) + .thenReturn("request-refused-auto"); + // WHEN messagingService.onRequestRefusedAuto( new RequestRefusedAutoEvent( @@ -283,8 +306,8 @@ class MessagingServiceTest { List.of(requestExpertAuto2.getExpert()))); // THEN - verify(mailService).send("1@magistrate.com", Email.REQUEST_REFUSED_ALL.getSubject(), ""); - verify(mailService).send("1@expert.com", Email.REQUEST_REFUSED_AUTO.getSubject(), ""); - verify(mailService).send("2@userexpert.com", Email.REQUEST_REFUSED_AUTO.getSubject(), ""); + verify(mailService).send("1@magistrate.com", "request-refused-all", ""); + verify(mailService).send("1@expert.com", "request-refused-auto", ""); + verify(mailService).send("2@userexpert.com", "request-refused-auto", ""); } } -- GitLab