Skip to content

Commit

Permalink
[CCAP-643] - Sends confirmation email when provider agrees to care
Browse files Browse the repository at this point in the history
  • Loading branch information
analoo committed Feb 18, 2025
1 parent 441668f commit 68e897a
Show file tree
Hide file tree
Showing 13 changed files with 410 additions and 31 deletions.
25 changes: 0 additions & 25 deletions src/main/java/org/ilgcc/app/email/EmailConstants.java

This file was deleted.

54 changes: 54 additions & 0 deletions src/main/java/org/ilgcc/app/email/ILGCCEmail.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.ilgcc.app.email;

import lombok.Getter;
import com.sendgrid.helpers.mail.objects.Content;
import com.sendgrid.helpers.mail.objects.Email;
import java.util.UUID;

@Getter
public class ILGCCEmail {

public static final String FROM_ADDRESS = "[email protected]";
public static final String EMAIL_SENDER_KEY = "email.general.sender-name";

private Email senderEmail;
private String subject;
private Content body;
private EmailType emailType;
private UUID submissionId;
private Email recipientEmail;

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;
this.body = body;
this.emailType = emailType;
this.submissionId = 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);
}

@Getter
public enum EmailType {
FAMILY_CONFIRMATION_EMAIL("Family Confirmation Email"), FAMILY_CONFIRMATION_EMAIL_NO_PROVIDER(
"No Provider Family Confirmation Email"), PROVIDER_AGREES_TO_CARE_FAMILY_EMAIL(
"Provider Agrees to Care Family Email"), PROVIDER_CONFIRMATION_EMAIL("Provider confirmation email");

private final String description;

EmailType(String description) {
this.description = description;
}

public String getDescription() {
return description;
}
}

}
12 changes: 11 additions & 1 deletion src/main/java/org/ilgcc/app/email/SendGridEmailService.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class SendGridEmailService {
private final SendGrid sendGrid = new SendGrid(System.getenv("SENDGRID_API_KEY"));

public Response sendEmail(String recipientAddress, String senderName, String subject, Content content) throws IOException {
Email senderEmail = new Email(EmailConstants.FROM_ADDRESS, senderName);
Email senderEmail = new Email(ILGCCEmail.FROM_ADDRESS, senderName);
Email recipientEmail = new Email(recipientAddress);
Mail mail = new Mail(senderEmail, subject, recipientEmail, content);
Request request = new Request();
Expand All @@ -31,4 +31,14 @@ public Response sendEmail(String recipientAddress, String senderName, String sub

return sendGrid.api(request);
}

public Response sendEmail(ILGCCEmail ilgccEmail) throws IOException {
Mail mail = new Mail(ilgccEmail.getSenderEmail(), ilgccEmail.getSubject(), ilgccEmail.getRecipientEmail(), ilgccEmail.getBody());
Request request = new Request();
request.setMethod(Method.POST);
request.setEndpoint("mail/send");
request.setBody(mail.build());

return sendGrid.api(request);
}
}
2 changes: 2 additions & 0 deletions src/main/java/org/ilgcc/app/inputs/Providerresponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,6 @@ public class Providerresponse extends FlowInputs {
// registration-signature
@NotBlank(message = "{errors.validate.provider-signed-name}")
private String providerSignedName;

private String providerConfirmationEmailSent;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import formflow.library.data.SubmissionRepositoryService;
import java.util.Locale;
import lombok.extern.slf4j.Slf4j;
import org.ilgcc.app.email.EmailConstants;
import org.ilgcc.app.email.ILGCCEmail;
import org.ilgcc.app.utils.SubmissionUtilities;
import org.ilgcc.jobs.SendEmailJob;
import org.springframework.context.MessageSource;
Expand Down Expand Up @@ -52,7 +52,7 @@ public void run(Submission familySubmission) {
String senderName = messageSource.getMessage("email.general.sender-name", null, locale);

sendEmailJob.enqueueSendEmailJob(familyEmail, senderName, subject,
EmailConstants.EmailType.FAMILY_CONFIRMATION_EMAIL.getDescription(),
ILGCCEmail.EmailType.FAMILY_CONFIRMATION_EMAIL.getDescription(),
createFamilyConfirmationEmailBody(familySubmission, familySubmissionShortCode, locale), familySubmission);
familySubmission.getInputData().put("familyConfirmationEmailSent", "true");
submissionRepositoryService.save(familySubmission);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import java.util.Optional;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import org.ilgcc.app.email.EmailConstants;
import org.ilgcc.app.email.ILGCCEmail;
import org.ilgcc.app.utils.ProviderSubmissionUtilities;
import org.ilgcc.jobs.SendEmailJob;
import org.springframework.context.MessageSource;
Expand Down Expand Up @@ -74,7 +74,7 @@ public void run(FormSubmission formSubmission, Submission providerSubmission) {
Content body = createProviderResponseConfirmationEmailBody(providerSubmission, familySubmission, familySubmissionConfirmationId, locale);

sendEmailJob.enqueueSendEmailJob(familyEmailAddress, senderName, subject,
EmailConstants.EmailType.PROVIDER_AGREES_TO_CARE_FAMILY_EMAIL.getDescription(),
ILGCCEmail.EmailType.PROVIDER_AGREES_TO_CARE_FAMILY_EMAIL.getDescription(),
body, providerSubmission);
providerSubmission.getInputData().put("providerResponseFamilyConfirmationEmailSent", "true");
submissionRepositoryService.save(providerSubmission);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package org.ilgcc.app.submission.actions;

import static org.ilgcc.app.utils.ProviderSubmissionUtilities.getCombinedDataForEmails;

import com.sendgrid.helpers.mail.objects.Content;
import formflow.library.config.submission.Action;
import formflow.library.data.Submission;
import formflow.library.data.SubmissionRepositoryService;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import org.ilgcc.app.email.ILGCCEmail;
import org.ilgcc.app.utils.ProviderSubmissionUtilities;
import org.ilgcc.jobs.SendEmailJob;
import org.springframework.context.MessageSource;

@Slf4j
public class SendProviderConfirmationEmail implements Action {

protected static String EMAIL_SENT_STATUS_INPUT_NAME = "providerConfirmationEmailSent";
protected static String RECIPIENT_EMAIL_INPUT_NAME = "providerResponseContactEmail";

protected static MessageSource messageSource;

protected final SubmissionRepositoryService submissionRepositoryService;

protected final SendEmailJob sendEmailJob;

public SendProviderConfirmationEmail(SendEmailJob sendEmailJob, SubmissionRepositoryService submissionRepositoryService,
MessageSource messageSource) {
this.sendEmailJob = sendEmailJob;
this.submissionRepositoryService = submissionRepositoryService;
this.messageSource = messageSource;
}

@Override
public void run(Submission submission) {
if (!skipEmailSend(submission)) {
Locale locale =
submission.getInputData().getOrDefault("languageRead", "English").equals("Spanish") ? Locale.forLanguageTag(
"es") : Locale.ENGLISH;
Optional<Map<String, String>> emailData = getEmailData(submission);

if(emailData.isEmpty()){
return;
}

ILGCCEmail email = ILGCCEmail.createProviderConfirmationEmail(getSenderName(locale), getRecipientEmail(submission),
setSubject(emailData.get(), locale), new Content("text/html", setBodyCopy(emailData.get(), locale)),
submission.getId());
sendEmail(email, submission);
}
}

protected Boolean skipEmailSend(Submission submission) {
boolean emailSent = submission.getInputData().getOrDefault(EMAIL_SENT_STATUS_INPUT_NAME, "false").equals("true");
if(emailSent){
return true;
} else {
boolean providerAgreedToCare = submission.getInputData().getOrDefault("providerResponseAgreeToCare", "false").equals("true");
if(providerAgreedToCare){
return true;
} else {
return false;
}
}
}

protected Optional<Map<String, String>> getEmailData(Submission providerSubmission) {
Optional<Submission> familySubmission = getFamilyApplication(providerSubmission);
if (familySubmission.isPresent()) {
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 static String getSenderName(Locale locale) {
return messageSource.getMessage(ILGCCEmail.EMAIL_SENDER_KEY, null, locale);
}

protected static String getRecipientEmail(Submission submission) {
return submission.getInputData().getOrDefault(RECIPIENT_EMAIL_INPUT_NAME, "").toString();
}

protected String setSubject(Map<String, String> emailData, Locale locale) {
return messageSource.getMessage("email.family-confirmation.subject", new Object[]{emailData.get("confirmationCode")},
locale);
}

protected String setBodyCopy(Map<String, String> 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;
}

protected void sendEmail(ILGCCEmail email, Submission submission) {
sendEmailJob.enqueueSendEmailJob(email);
updateEmailStatus(submission);
}

private void updateEmailStatus(Submission submission) {
submission.getInputData().putIfAbsent(EMAIL_SENT_STATUS_INPUT_NAME, "true");
submissionRepositoryService.save(submission);
}

private Optional<Submission> getFamilyApplication(Submission providerSubmission) {
Optional<UUID> familySubmissionId = ProviderSubmissionUtilities.getClientId(providerSubmission);
if (familySubmissionId.isEmpty()) {
log.warn("No family submission is associated with the provider submission with ID: {}",
providerSubmission.getId());
return Optional.empty();
}

return submissionRepositoryService.findById(familySubmissionId.get());
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,22 @@ private static String getApplicantName(Map<String, Object> applicantInputData) {
return String.format("%s %s", firstName, lastName);
}

public static Map<String, String> getCombinedDataForEmails(Submission providerSubmission, Submission familySubmission) {
Map<String, String> applicationData = new HashMap<>();

applicationData.put("providerName", getProviderResponseName(providerSubmission));

applicationData.put("ccrrName", (String) familySubmission.getInputData().getOrDefault("ccrrName", ""));
applicationData.put("ccrrPhoneNumber", (String) familySubmission.getInputData().getOrDefault("ccrrPhoneNumber", ""));
applicationData.put("childrenInitials", ProviderSubmissionUtilities.getChildrenInitialsFromApplication(familySubmission));
applicationData.put("ccapStartDate",
ProviderSubmissionUtilities.getCCAPStartDateFromProviderOrFamilyChildcareStartDate(familySubmission,
providerSubmission));
applicationData.put("confirmationCode", familySubmission.getShortCode());

return applicationData;
}

public static List<Map<String, String>> getChildrenDataForProviderResponse(Submission applicantSubmission) {
List<Map<String, String>> children = new ArrayList<>();

Expand Down Expand Up @@ -206,6 +222,7 @@ public static String getCCAPStartDateFromProviderOrFamilyChildcareStartDate(Subm
return DateUtilities.convertDateToFullWordMonthPattern(familyEarliestChildcareStartDate);
}
}

public static String getChildrenInitialsFromApplication(Submission familySubmission) {
List<Map<String, Object>> children = SubmissionUtilities.getChildrenNeedingAssistance(familySubmission);
var childrenInitials = new ArrayList<String>();
Expand All @@ -217,7 +234,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) {
String providerResponseBusinessName = (String) providerSubmission.getInputData().getOrDefault("providerResponseBusinessName", "");
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/org/ilgcc/jobs/SendEmailJob.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import formflow.library.data.Submission;
import java.io.IOException;
import lombok.extern.slf4j.Slf4j;
import org.ilgcc.app.email.ILGCCEmail;
import org.ilgcc.app.email.SendGridEmailService;
import org.jobrunr.jobs.JobId;
import org.jobrunr.jobs.annotations.Job;
Expand Down Expand Up @@ -50,4 +51,25 @@ public void sendEmailRequest(String recipientAddress, String senderName, String
throw e;
}
}

public void enqueueSendEmailJob(ILGCCEmail email) {
if (emailsEnabled) {
JobId jobId = jobScheduler.enqueue(() -> sendEmailRequest(email));
log.info("Enqueued {} email job with ID: {} for submission with ID: {}", email.getEmailType(), jobId, email.getSubmissionId());
} else {
log.info("Emails disabled. Skipping enqueue {} email job for submission with ID: {}", email.getEmailType(),email.getSubmissionId());
log.info("Would have sent: {} with a subject of: {} from: {}", email.getBody().getValue(), email.getSubject(), email.getSenderEmail().toString()); // Don't log recipient email for security reasons
}
}

@Job(name = "Send Email Request", retries = 3)
public void sendEmailRequest(ILGCCEmail email) throws IOException {
try {
sendGridEmailService.sendEmail(email);
log.info("Successfully sent the {} for submission with ID {} to Sendgrid.", email.getEmailType(), email.getSubmissionId());
} catch (IOException e) {
log.error("There was an error when attempting to send the {} for submission with ID {}: {}", email.getEmailType(), email.getSubmissionId(), e.getMessage());
throw e;
}
}
}
1 change: 1 addition & 0 deletions src/main/resources/flows-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@ flow:
response:
beforeDisplayAction: FindApplicationData
onPostAction: SendProviderAgreesToCareFamilyConfirmationEmail
afterSaveAction: SendProviderConfirmationEmail
nextScreens:
- name: registration-submit-intro
condition: ProviderIsRegistering
Expand Down
6 changes: 6 additions & 0 deletions src/main/resources/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@ email.response-email-for-family.provider-agrees.p3=<p><strong>Provider response:
email.response-email-for-family.provider-agrees.p4=<p><strong>Confirmation code:</strong> {0}</p>
email.response-email-for-family.provider-agrees.p5=<p><strong>Next steps:</strong> You will receive a letter or an email about the status of your case in 13-15 business days. If you have questions, call {0}: <a href="tel:{1}">{1}</a>.</p>

# Provider Confirmation email
email.provider-confirmation.p1=<p>Hello,</p>
email.provider-confirmation.p2=<p>Thank you for completing a family''s Child Care Assistance Program (CCAP) application. Your response has been submitted to {0} for processing.</p>
email.provider-confirmation.p3=<p><strong>Response:</strong> You agreed to care for {0} with a start date of {1} or pending approval.
email.provider-confirmation.p4=<p><strong>Confirmation code:</strong>{0}</p>
email.provider-confirmation.p5=<p><strong>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 {0} at <a href="tel:{1}">{1}</a>.</p>

errors.provide-first-name=Enter a first name
errors.provide-last-name=Enter a last name
Expand Down
Loading

0 comments on commit 68e897a

Please sign in to comment.