diff --git a/src/main/java/org/ilgcc/app/email/ILGCCEmail.java b/src/main/java/org/ilgcc/app/email/ILGCCEmail.java index 137615e92..6a7ad2a70 100644 --- a/src/main/java/org/ilgcc/app/email/ILGCCEmail.java +++ b/src/main/java/org/ilgcc/app/email/ILGCCEmail.java @@ -7,8 +7,9 @@ @Getter public class ILGCCEmail { + public static final String FROM_ADDRESS = "contact@getchildcareil.org"; - public static final String EMAIL_SENDER_KEY = "email.sender-name"; + public static final String EMAIL_SENDER_KEY = "email.general.sender-name"; private Email senderEmail; private String subject; @@ -17,7 +18,8 @@ public class ILGCCEmail { private UUID submissionId; private Email recipientEmail; - public ILGCCEmail(String senderName, String recipientAddress, String subject, Content body, EmailType emailType, UUID submissionId) { + public ILGCCEmail(String senderName, String recipientAddress, String subject, Content body, EmailType emailType, + UUID submissionId) { this.senderEmail = new Email(FROM_ADDRESS, senderName); this.recipientEmail = new Email(recipientAddress); this.subject = subject; @@ -27,11 +29,13 @@ public ILGCCEmail(String senderName, String recipientAddress, String subject, Co } - public static ILGCCEmail createFamilyConfirmationEmail(String senderName, String recipientAddress, String subject, Content body, UUID submissionId){ + public static ILGCCEmail createFamilyConfirmationEmail(String senderName, String recipientAddress, String subject, + Content body, UUID submissionId) { return new ILGCCEmail(senderName, recipientAddress, subject, body, EmailType.FAMILY_CONFIRMATION_EMAIL, submissionId); } - public static ILGCCEmail createProviderConfirmationEmail(String senderName, String recipientAddress, String subject, Content body, UUID submissionId){ + public static ILGCCEmail createProviderConfirmationEmail(String senderName, String recipientAddress, String subject, + Content body, UUID submissionId) { return new ILGCCEmail(senderName, recipientAddress, subject, body, EmailType.PROVIDER_CONFIRMATION_EMAIL, submissionId); } @@ -49,6 +53,4 @@ public enum EmailType { this.description = description; } } - - } diff --git a/src/main/java/org/ilgcc/app/submission/actions/Mailer.java b/src/main/java/org/ilgcc/app/submission/actions/Mailer.java index 3f245e6c5..00b6dfcb3 100644 --- a/src/main/java/org/ilgcc/app/submission/actions/Mailer.java +++ b/src/main/java/org/ilgcc/app/submission/actions/Mailer.java @@ -1,6 +1,5 @@ package org.ilgcc.app.submission.actions; -import com.sendgrid.helpers.mail.objects.Content; import formflow.library.config.submission.Action; import formflow.library.data.Submission; import formflow.library.data.SubmissionRepositoryService; @@ -9,7 +8,6 @@ import java.util.UUID; import lombok.extern.slf4j.Slf4j; import org.ilgcc.app.email.ILGCCEmail; -import org.ilgcc.app.email.ILGCCEmail.EmailType; import org.ilgcc.app.utils.ProviderSubmissionUtilities; import org.ilgcc.jobs.SendEmailJob; import org.springframework.context.MessageSource; @@ -23,42 +21,25 @@ abstract class Mailer implements Action { protected final SendEmailJob sendEmailJob; - protected static String EMAIL_SENT_STATUS_INPUT_NAME; - protected static String RECIPIENT_EMAIL_INPUT_NAME; + protected static String emailSentStatusInputName; + protected static String recipientEmailInputName; public Mailer(SendEmailJob sendEmailJob, SubmissionRepositoryService submissionRepositoryService, - MessageSource messageSource) { + MessageSource messageSource, String emailSentStatusInputName, String recipientEmailInputName) { this.sendEmailJob = sendEmailJob; this.submissionRepositoryService = submissionRepositoryService; this.messageSource = messageSource; + this.emailSentStatusInputName = emailSentStatusInputName; + this.recipientEmailInputName = recipientEmailInputName; } - protected static String setSenderName(Locale locale) { + protected static String getSenderName(Locale locale) { return messageSource.getMessage(ILGCCEmail.EMAIL_SENDER_KEY, null, locale); } - protected static String setRecipientName(Submission submission) { - return submission.getInputData().getOrDefault(RECIPIENT_EMAIL_INPUT_NAME, "").toString(); - } - - protected String setSubject(Submission submission, Locale locale) { - return messageSource.getMessage("email.family-confirmation.subject", null, locale); - } - - protected Content setBodyCopy(Submission submission, Locale locale) { - return new Content(); - } - - - protected ILGCCEmail prepareEmailCopy(Submission submission, EmailType emailType) { - Locale locale = - submission.getInputData().getOrDefault("languageRead", "English").equals("Spanish") ? Locale.forLanguageTag( - "es") : Locale.ENGLISH; - - return new ILGCCEmail(setSenderName(locale), setRecipientName(submission), setSubject(submission, locale), - setBodyCopy(submission, locale), emailType, submission.getId()); - + protected static String getRecipientEmail(Submission submission) { + return submission.getInputData().getOrDefault(recipientEmailInputName, "").toString(); } protected void sendEmail(ILGCCEmail email, Submission submission) { @@ -67,18 +48,19 @@ protected void sendEmail(ILGCCEmail email, Submission submission) { } protected Boolean skipEmailSend(Submission submission) { - return submission.getInputData().getOrDefault(EMAIL_SENT_STATUS_INPUT_NAME, "false").equals("true"); + return submission.getInputData().getOrDefault(emailSentStatusInputName, "false").equals("true"); } private void updateEmailStatus(Submission submission) { - submission.getInputData().putIfAbsent(EMAIL_SENT_STATUS_INPUT_NAME, "true"); + submission.getInputData().putIfAbsent(emailSentStatusInputName, "true"); submissionRepositoryService.save(submission); } protected Optional getFamilyApplication(Submission providerSubmission) { Optional familySubmissionId = ProviderSubmissionUtilities.getClientId(providerSubmission); if (familySubmissionId.isEmpty()) { - log.warn("No family submission is associated with the provider submission with ID: {}", providerSubmission.getId()); + log.warn(String.format("No family submission is associated with the provider submission with ID: {}", + providerSubmission.getId())); return Optional.empty(); } diff --git a/src/main/java/org/ilgcc/app/submission/actions/SendProviderConfirmationEmail.java b/src/main/java/org/ilgcc/app/submission/actions/SendProviderConfirmationEmail.java index 2a034557c..9897315cc 100644 --- a/src/main/java/org/ilgcc/app/submission/actions/SendProviderConfirmationEmail.java +++ b/src/main/java/org/ilgcc/app/submission/actions/SendProviderConfirmationEmail.java @@ -10,7 +10,6 @@ import java.util.Optional; import lombok.extern.slf4j.Slf4j; import org.ilgcc.app.email.ILGCCEmail; -import org.ilgcc.app.email.ILGCCEmail.EmailType; import org.ilgcc.jobs.SendEmailJob; import org.springframework.context.MessageSource; @@ -23,46 +22,56 @@ public class SendProviderConfirmationEmail extends Mailer { public SendProviderConfirmationEmail(SendEmailJob sendEmailJob, SubmissionRepositoryService submissionRepositoryService, MessageSource messageSource) { - super(sendEmailJob, submissionRepositoryService, messageSource); + super(sendEmailJob, submissionRepositoryService, messageSource, EMAIL_SENT_STATUS_INPUT_NAME, RECIPIENT_EMAIL_INPUT_NAME); } @Override public void run(Submission submission) { if (!skipEmailSend(submission)) { - ILGCCEmail email = prepareEmailCopy(submission, EmailType.PROVIDER_CONFIRMATION_EMAIL); + Locale locale = + submission.getInputData().getOrDefault("languageRead", "English").equals("Spanish") ? Locale.forLanguageTag( + "es") : Locale.ENGLISH; + Optional> emailData = getEmailData(submission); + String subject = emailData.isPresent() ? setSubject(emailData.get(), locale) : ""; + Content body = emailData.isPresent() ? new Content("text/html", setBodyCopy(emailData.get(), locale)) : new Content(); + + ILGCCEmail email = ILGCCEmail.createProviderConfirmationEmail(getSenderName(locale), getRecipientEmail(submission), + subject, body, + submission.getId()); sendEmail(email, submission); } } - @Override - protected String setSubject(Submission submission, Locale locale) { - return messageSource.getMessage("email.family-confirmation.subject", null, locale); - } - - @Override - protected Content setBodyCopy(Submission providerSubmission, Locale locale) { + protected Optional> getEmailData(Submission providerSubmission) { Optional familySubmission = getFamilyApplication(providerSubmission); if (familySubmission.isPresent()) { - Map emailData = getCombinedDataForEmails(providerSubmission, familySubmission.get()); - - String p1 = messageSource.getMessage("email.provider-confirmation.p1", null, locale); - String p2 = messageSource.getMessage("email.provider-confirmation.p2", new Object[]{emailData.get("ccrrName")}, - locale); - String p3 = messageSource.getMessage("email.provider-confirmation.p3", - new Object[]{emailData.get("childrenInitials"), emailData.get("ccapStartDate")}, locale); - String p4 = messageSource.getMessage("email.provider-confirmation.p4", - new Object[]{emailData.get("confirmationCode")}, locale); - String p5 = messageSource.getMessage("email.provider-confirmation.p5", - new Object[]{emailData.get("ccrrName"), emailData.get("ccrrPhoneNumber")}, - locale); - String p6 = messageSource.getMessage("email.general.footer.automated-response", null, locale); - String p7 = messageSource.getMessage("email.general.footer.cfa", null, locale); - return new Content("text/html", p1 + p2 + p3 + p4 + p5 + p6 + p7); + return Optional.of(getCombinedDataForEmails(providerSubmission, familySubmission.get())); + } else { + log.warn("Could not send Email: {}: No family submission is associated with the familSubmissionID: {}", + providerSubmission.getId()); + return Optional.empty(); } + } + + protected String setSubject(Map emailData, Locale locale) { + return messageSource.getMessage("email.family-confirmation.subject", new Object[]{emailData.get("confirmationCode")}, + locale); + } - log.warn("Could not send Email: {}: No family submission is associated with the familSubmissionID: {}", - providerSubmission.getId()); - return new Content(); + protected String setBodyCopy(Map emailData, Locale locale) { + String p1 = messageSource.getMessage("email.provider-confirmation.p1", null, locale); + String p2 = messageSource.getMessage("email.provider-confirmation.p2", new Object[]{emailData.get("ccrrName")}, + locale); + String p3 = messageSource.getMessage("email.provider-confirmation.p3", + new Object[]{emailData.get("childrenInitials"), emailData.get("ccapStartDate")}, locale); + String p4 = messageSource.getMessage("email.provider-confirmation.p4", + new Object[]{emailData.get("confirmationCode")}, locale); + String p5 = messageSource.getMessage("email.provider-confirmation.p5", + new Object[]{emailData.get("ccrrName"), emailData.get("ccrrPhoneNumber")}, + locale); + String p6 = messageSource.getMessage("email.general.footer.automated-response", null, locale); + String p7 = messageSource.getMessage("email.general.footer.cfa", null, locale); + return p1 + p2 + p3 + p4 + p5 + p6 + p7; } } diff --git a/src/main/java/org/ilgcc/app/utils/ProviderSubmissionUtilities.java b/src/main/java/org/ilgcc/app/utils/ProviderSubmissionUtilities.java index 6da308274..0588ea6ac 100644 --- a/src/main/java/org/ilgcc/app/utils/ProviderSubmissionUtilities.java +++ b/src/main/java/org/ilgcc/app/utils/ProviderSubmissionUtilities.java @@ -237,7 +237,17 @@ public static String getChildrenInitialsFromApplication(Submission familySubmiss String lastName = (String) child.get("childLastName"); childrenInitials.add(String.format("%s.%s.", firstName.toUpperCase().charAt(0), lastName.toUpperCase().charAt(0))); } - return String.join(", ", childrenInitials); + if (childrenInitials.isEmpty()) { + return ""; + } else if (childrenInitials.size() == 1) { + return childrenInitials.get(0); // Single name, no 'and' + } else if (childrenInitials.size() == 2) { + return String.join(" and ", childrenInitials); // Two childrenInitials, join with 'and' + } else { + // More than 2 childrenInitials, use comma for all but the last one + String last = childrenInitials.remove(childrenInitials.size() - 1); // Remove and keep the last name + return String.join(", ", childrenInitials) + " and " + last; // Join remaining with commas, append 'and last' + } } public static String getProviderResponseName(Submission providerSubmission) { diff --git a/src/main/resources/flows-config.yaml b/src/main/resources/flows-config.yaml index bdcfd8233..b6c8f40be 100644 --- a/src/main/resources/flows-config.yaml +++ b/src/main/resources/flows-config.yaml @@ -536,6 +536,7 @@ flow: response: beforeDisplayAction: FindApplicationData onPostAction: SendProviderAgreesToCareFamilyConfirmationEmail + onSaveAction: SendProviderConfirmationEmail nextScreens: - name: registration-submit-intro condition: ProviderIsRegistering diff --git a/src/test/java/org/ilgcc/app/submission/actions/SendProviderConfirmationEmailTest.java b/src/test/java/org/ilgcc/app/submission/actions/SendProviderConfirmationEmailTest.java index e4ff421ac..0f11d3cf6 100644 --- a/src/test/java/org/ilgcc/app/submission/actions/SendProviderConfirmationEmailTest.java +++ b/src/test/java/org/ilgcc/app/submission/actions/SendProviderConfirmationEmailTest.java @@ -1,11 +1,16 @@ package org.ilgcc.app.submission.actions; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.verify; import formflow.library.data.Submission; import formflow.library.data.SubmissionRepositoryService; import java.time.OffsetDateTime; import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import org.ilgcc.app.email.ILGCCEmail; import org.ilgcc.app.utils.SubmissionTestBuilder; import org.ilgcc.jobs.SendEmailJob; import org.junit.jupiter.api.BeforeEach; @@ -21,7 +26,7 @@ @SpringBootTest public class SendProviderConfirmationEmailTest { - @Autowired + @MockitoSpyBean SendEmailJob sendEmailJob; @Autowired @@ -30,14 +35,11 @@ public class SendProviderConfirmationEmailTest { @Autowired MessageSource messageSource; - private SendProviderConfirmationEmail action = new SendProviderConfirmationEmail(sendEmailJob, submissionRepositoryService, messageSource); - private Submission providerSubmission; - private Submission familySubmission; - - private Locale englishLocale = Locale.ENGLISH; + private Submission familySubmission; + private SendProviderConfirmationEmail action; @BeforeEach @@ -46,35 +48,95 @@ void setUp() { .withFlow("gcc") .with("parentPreferredName", "FirstName").withChild("First", "Child", "Yes").withChild("Second", "Child", "Yes") .withSubmittedAtDate(OffsetDateTime.now()) + .withCCRR() .withShortCode("ABC123") .build(); submissionRepositoryService.save(familySubmission); - } - @Test - void whenCompleteProviderInformation(){ providerSubmission = new SubmissionTestBuilder() .withFlow("providerresponse") .with("familySubmissionId", familySubmission.getId().toString()) .with("providerResponseContactEmail", "provideremail@test.com") - .with("providerCareStartDay", "01/10/2025") + .with("providerResponseFirstName", "ProviderFirst") + .with("providerResponseLastName", "ProviderLast") + .with("providerResponseBusinessName", "BusinessName") + .with("providerCareStartDate", "01/10/2025") .build(); submissionRepositoryService.save(providerSubmission); - action.run(providerSubmission); + action = new SendProviderConfirmationEmail(sendEmailJob, submissionRepositoryService, messageSource); + } - assertThat(action.setSubject(providerSubmission, englishLocale)).containsIgnoringCase("Hi There"); + @Test + void correctlySetsEmailData() { + Optional> emailDataOptional = action.getEmailData(providerSubmission); + assertThat(emailDataOptional.isPresent()).isTrue(); -// assert that the providerSubmission providerConfirmationEmailSent is set to true - // assert that sendEmailJob.enqueueSendEmailJob is called with the expected parameters + Map emailData = emailDataOptional.get(); - // or call each method and and confirm that the correct email copy etc is called - // assert that SendEmailJob.enqueuSendEmailJob was called once + assertThat(emailData.get("confirmationCode")).isEqualTo("ABC123"); + assertThat(emailData.get("childrenInitials")).isEqualTo("F.C. and S.C."); + assertThat(emailData.get("providerName")).isEqualTo("BusinessName"); + assertThat(emailData.get("ccrrName")).isEqualTo("Sample Test CCRRR"); + assertThat(emailData.get("ccrrPhoneNumber")).isEqualTo("(603) 555-1244"); + assertThat(emailData.get("ccapStartDate")).isEqualTo("January 10, 2025"); + } + + @Test + void correctlySetsEmailSubject() { + Optional> emailDataOptional = action.getEmailData(providerSubmission); + Map emailData = emailDataOptional.get(); + assertThat(action.setSubject(emailData, Locale.ENGLISH)).isEqualTo("Your CCAP confirmation code: ABC123"); + } + + @Test + void correctlySetsEmailBody() { + Optional> emailDataOptional = action.getEmailData(providerSubmission); + Map emailData = emailDataOptional.get(); + + String emailCopy = action.setBodyCopy(emailData, Locale.ENGLISH); + + assertThat(emailCopy).contains( + "Thank you for completing a family's Child Care Assistance Program (CCAP) application. Your response has been submitted to Sample Test CCRRR for processing."); + assertThat(emailCopy).contains( + "Response: You agreed to care for F.C. and S.C. with a start date of January 10, 2025 or pending approval."); + assertThat(emailCopy).contains("ABC123"); + assertThat(emailCopy).contains( + "Next steps:You will receive a letter or email about the status of the family's application within 13-15 business days. If you want an update on the application, call Sample Test CCRRR at"); + assertThat(emailCopy).contains("(603) 555-1244"); + } + @Test + void correctlySetsEmailSender() { + assertThat(action.getSenderName(Locale.ENGLISH)).isEqualTo( + "Child Care Assistance Program Applications - Code for America on behalf of the Illinois Department of Human Services"); + } + + @Test + void correctlyUpdatesEmailSendStatus() { + assertThat(providerSubmission.getInputData().containsKey("providerConfirmationEmailSent")).isFalse(); + action.run(providerSubmission); + + assertThat(providerSubmission.getInputData().containsKey("providerConfirmationEmailSent")).isTrue(); + assertThat(providerSubmission.getInputData().get("providerConfirmationEmailSent")).isEqualTo("true"); + } + + @Test + void correctlySkipsEmailSendWhenEmailStatusIsTrue() { + assertThat(action.skipEmailSend(providerSubmission)).isFalse(); + + providerSubmission.getInputData().put("providerConfirmationEmailSent", "true"); + assertThat(action.skipEmailSend(providerSubmission)).isTrue(); + } + + @Test + void correctlyEnqueuesSendEmailJob() { + action.run(providerSubmission); + verify(sendEmailJob).enqueueSendEmailJob(any(ILGCCEmail.class)); } } \ No newline at end of file diff --git a/src/test/java/org/ilgcc/app/utils/SubmissionTestBuilder.java b/src/test/java/org/ilgcc/app/utils/SubmissionTestBuilder.java index 1a8ac99b2..09ecabe4e 100644 --- a/src/test/java/org/ilgcc/app/utils/SubmissionTestBuilder.java +++ b/src/test/java/org/ilgcc/app/utils/SubmissionTestBuilder.java @@ -36,7 +36,13 @@ public SubmissionTestBuilder withSubmittedAtDate(OffsetDateTime date) { return this; } - public SubmissionTestBuilder withFlow(String flow){ + public SubmissionTestBuilder withCCRR() { + submission.getInputData().put("ccrrPhoneNumber", "(603) 555-1244"); + submission.getInputData().put("ccrrName", "Sample Test CCRRR"); + return this; + } + + public SubmissionTestBuilder withFlow(String flow) { submission.setFlow(flow); return this; }