Skip to content

Commit

Permalink
FPL-35: Send notifications to CAFCASS on case submission (#144)
Browse files Browse the repository at this point in the history
  • Loading branch information
swalker125 authored and DamianDunajski committed Dec 12, 2018
1 parent 6990e2c commit d380aaa
Show file tree
Hide file tree
Showing 11 changed files with 284 additions and 27 deletions.
2 changes: 1 addition & 1 deletion Jenkinsfile_CNP
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!groovy

@Library("Infrastructure")
@Library("Infrastructure@fd7aef62b5503c45b4998a072175d94d62aab70e")

import uk.gov.hmcts.contino.Kubectl

Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ services:
- FPL_LOCAL_AUTHORITY_CODE_TO_NAME_MAPPING=SA=>Swansea Local Authority;HN=>Hillingdon Local Authority
- FPL_LOCAL_AUTHORITY_USER_MAPPING=SA=>25,26,27;HN=>28,29
- FPL_LOCAL_AUTHORITY_CODE_TO_HMCTS_COURT_MAPPING=SA=>Swansea Family Court:[email protected];HN=>Portsmouth Combined Court:[email protected]
- FPL_LOCAL_AUTHORITY_CODE_TO_CAFCASS_MAPPING=SA=>Cafcass Cymru:[email protected];HN=>Cafcass:[email protected]
- NOTIFY_API_KEY
- CCD_UI_BASE_URL=http://localhost:3451
# these environment variables are used by java-logging library
Expand Down
6 changes: 6 additions & 0 deletions infrastructure/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ data "azurerm_key_vault_secret" "local_authority_code_to_hmcts_court_mapping" {
vault_uri = "${module.key-vault.key_vault_uri}"
}

data "azurerm_key_vault_secret" "local_authority_code_to_cafcass_mapping" {
name = "local-authority-code-to-cafcass-mapping"
vault_uri = "${module.key-vault.key_vault_uri}"
}

data "azurerm_key_vault_secret" "notify_api_key" {
name = "notify-api-key"
vault_uri = "${module.key-vault.key_vault_uri}"
Expand Down Expand Up @@ -76,6 +81,7 @@ module "case-service" {
FPL_LOCAL_AUTHORITY_CODE_TO_NAME_MAPPING = "${data.azurerm_key_vault_secret.local_authority_code_to_name_mapping.value}"
FPL_LOCAL_AUTHORITY_USER_MAPPING = "${data.azurerm_key_vault_secret.local_authority_user_mapping.value}"
FPL_LOCAL_AUTHORITY_CODE_TO_HMCTS_COURT_MAPPING = "${data.azurerm_key_vault_secret.local_authority_code_to_hmcts_court_mapping.value}"
FPL_LOCAL_AUTHORITY_CODE_TO_CAFCASS_MAPPING = "${data.azurerm_key_vault_secret.local_authority_code_to_cafcass_mapping.value}"
NOTIFY_API_KEY = "${data.azurerm_key_vault_secret.notify_api_key.value}"

LOGBACK_REQUIRE_ALERT_LEVEL = false
Expand Down
3 changes: 2 additions & 1 deletion kubernetes/deployment.template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ data:
CCD_UI_BASE_URL: "https://ccd-case-management-web-${SERVICE_FQDN}"
FPL_LOCAL_AUTHORITY_EMAIL_TO_CODE_MAPPING: "swansea.gov.uk=>SA;hillingdon.gov.uk=>HN"
FPL_LOCAL_AUTHORITY_CODE_TO_NAME_MAPPING: "SA=>Swansea Local Authority;HN=>Hillingdon Local Authority"
FPL_LOCAL_AUTHORITY_USER_MAPPING: "SA=>25,26,27;HN=>28,29"
FPL_LOCAL_AUTHORITY_USER_MAPPING: "SA=>22,23,24;HN=>25,26"
FPL_LOCAL_AUTHORITY_CODE_TO_HMCTS_COURT_MAPPING: "SA=>Swansea Family Court:[email protected];HN=>Portsmouth Combined Court:[email protected]"
FPL_LOCAL_AUTHORITY_CODE_TO_CAFCASS_MAPPING: "SA=>Cafcass Cymru:[email protected];HN=>Cafcass:[email protected]"
NOTIFY_API_KEY: ${NOTIFY_API_KEY}

---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static uk.gov.hmcts.reform.fpl.CaseDefinitionConstants.CASE_TYPE;
import static uk.gov.hmcts.reform.fpl.CaseDefinitionConstants.JURISDICTION;
import static uk.gov.hmcts.reform.fpl.NotifyTemplates.CAFCASS_SUBMISSION_TEMPLATE;
import static uk.gov.hmcts.reform.fpl.NotifyTemplates.HMCTS_COURT_SUBMISSION_TEMPLATE;
import static uk.gov.hmcts.reform.fpl.utils.DocumentManagementStoreLoader.document;
import static uk.gov.hmcts.reform.fpl.utils.ResourceReader.readBytes;
Expand Down Expand Up @@ -103,10 +104,12 @@ void shouldReturnUnsuccessfulResponseWithMalformedData() throws Exception {
}

@Test
void shouldBuildTemplateWithCompleteValues() throws Exception {
Map<String, String> expectedParameters = ImmutableMap.<String, String>builder()
void shouldBuildNotificationTemplatesWithCompleteValues() throws Exception {
Map<String, String> expectedHmctsParameters = ImmutableMap.<String, String>builder()
.put("court", "Family Court")
.put("localAuthority", "Example Local Authority")
.put("dataPresent", "Yes")
.put("fullStop", "No")
.put("orders0", "^Emergency protection order")
.put("orders1", "")
.put("orders2", "")
Expand All @@ -119,6 +122,21 @@ void shouldBuildTemplateWithCompleteValues() throws Exception {
.put("caseUrl", "http://fake-url/case/" + JURISDICTION + "/" + CASE_TYPE + "/12345")
.build();

Map<String, String> expectedCafcassParameters = ImmutableMap.<String, String>builder()
.put("cafcass", "cafcass")
.put("localAuthority", "Example Local Authority")
.put("dataPresent", "Yes")
.put("fullStop", "No")
.put("orders0", "^Emergency protection order")
.put("orders1", "")
.put("orders2", "")
.put("orders3", "")
.put("orders4", "")
.put("directionsAndInterim", "^Information on the whereabouts of the child")
.put("reference", "12345")
.put("caseUrl", "http://fake-url/case/" + JURISDICTION + "/" + CASE_TYPE + "/12345")
.build();

mockMvc
.perform(post("/callback/case-submission/submitted")
.header("authorization", AUTH_TOKEN)
Expand All @@ -128,12 +146,16 @@ void shouldBuildTemplateWithCompleteValues() throws Exception {
.andExpect(status().isOk());

verify(notificationClient, times(1)).sendEmail(
eq(HMCTS_COURT_SUBMISSION_TEMPLATE), eq("[email protected]"), eq(expectedParameters), eq("12345")
eq(HMCTS_COURT_SUBMISSION_TEMPLATE), eq("[email protected]"), eq(expectedHmctsParameters), eq("12345")
);

verify(notificationClient, times(1)).sendEmail(
eq(CAFCASS_SUBMISSION_TEMPLATE), eq("[email protected]"), eq(expectedCafcassParameters), eq("12345")
);
}

@Test
void shouldBuildTemplateWithValuesMissingInCallback() throws Exception {
void shouldBuildNotificationTemplatesWithValuesMissingInCallback() throws Exception {
CallbackRequest request = CallbackRequest.builder()
.caseDetails(CaseDetails.builder()
.id(12345L)
Expand All @@ -142,9 +164,11 @@ void shouldBuildTemplateWithValuesMissingInCallback() throws Exception {
.build())
.build();

Map<String, String> expectedParameters = ImmutableMap.<String, String>builder()
Map<String, String> expectedHmctsParameters = ImmutableMap.<String, String>builder()
.put("court", "Family Court")
.put("localAuthority", "Example Local Authority")
.put("dataPresent", "No")
.put("fullStop", "Yes")
.put("orders0", "")
.put("orders1", "")
.put("orders2", "")
Expand All @@ -157,6 +181,21 @@ void shouldBuildTemplateWithValuesMissingInCallback() throws Exception {
.put("caseUrl", "http://fake-url/case/" + JURISDICTION + "/" + CASE_TYPE + "/12345")
.build();

Map<String, String> expectedCafcassParameters = ImmutableMap.<String, String>builder()
.put("cafcass", "cafcass")
.put("localAuthority", "Example Local Authority")
.put("dataPresent", "No")
.put("fullStop", "Yes")
.put("orders0", "")
.put("orders1", "")
.put("orders2", "")
.put("orders3", "")
.put("orders4", "")
.put("directionsAndInterim", "")
.put("reference", "12345")
.put("caseUrl", "http://fake-url/case/" + JURISDICTION + "/" + CASE_TYPE + "/12345")
.build();

mockMvc
.perform(post("/callback/case-submission/submitted")
.header("authorization", AUTH_TOKEN)
Expand All @@ -166,7 +205,11 @@ void shouldBuildTemplateWithValuesMissingInCallback() throws Exception {
.andExpect(status().isOk());

verify(notificationClient, times(1)).sendEmail(
eq(HMCTS_COURT_SUBMISSION_TEMPLATE), eq("[email protected]"), eq(expectedParameters), eq("12345")
eq(HMCTS_COURT_SUBMISSION_TEMPLATE), eq("[email protected]"), eq(expectedHmctsParameters), eq("12345")
);

verify(notificationClient, times(1)).sendEmail(
eq(CAFCASS_SUBMISSION_TEMPLATE), eq("[email protected]"), eq(expectedCafcassParameters), eq("12345")
);
}

Expand Down
2 changes: 2 additions & 0 deletions service/src/integrationTest/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@ fpl.local_authority_user.mapping=example=>1,2,3

fpl.local_authority_code_to_hmcts_court.mapping=example=>Family Court:[email protected]

fpl.local_authority_code_to_cafcass.mapping=example=>cafcass:[email protected]

notify.api_key=testApiKey
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ private NotifyTemplates() {
//NO-OP
}

public static final String HMCTS_COURT_SUBMISSION_TEMPLATE = "1b1be684-9b0a-4e58-8e51-f0c3c2dba37c";
public static final String HMCTS_COURT_SUBMISSION_TEMPLATE = "c76d4fb2-d2b0-4ac5-9c3a-fb1fb964a257";
public static final String CAFCASS_SUBMISSION_TEMPLATE = "186e1aa7-6668-4b01-bf78-87d7e7476ef8";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package uk.gov.hmcts.reform.fpl.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import uk.gov.hmcts.reform.fpl.config.utils.LookupConfigParser;

import java.util.Map;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.emptyToNull;

@Configuration
public class CafcassLookupConfiguration {

private final Map<String, Cafcass> mapping;

public CafcassLookupConfiguration(@Value("${fpl.local_authority_code_to_cafcass.mapping}")
String config) {
this.mapping = LookupConfigParser.parse(config, value -> {
String[] entrySplit = value.split(":", 2);
return new Cafcass(
checkNotNull(emptyToNull(entrySplit[0]), "Cafcass name cannot be empty"),
checkNotNull(emptyToNull(entrySplit[1]), "Cafcass email cannot be empty")
);
});
}

public Cafcass getCafcass(String localAuthorityCode) {
checkNotNull(localAuthorityCode, "Local authority code cannot be null");

return checkNotNull(mapping.get(localAuthorityCode), "Local authority '" + localAuthorityCode + "' not found");
}

public static class Cafcass {
private final String name;
private final String email;

public Cafcass(String name, String email) {
this.name = name;
this.email = email;
}

public String getName() {
return name;
}

public String getEmail() {
return email;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import uk.gov.hmcts.reform.ccd.client.model.CaseDetails;
import uk.gov.hmcts.reform.fpl.config.CafcassLookupConfiguration;
import uk.gov.hmcts.reform.fpl.config.HmctsCourtLookupConfiguration;
import uk.gov.hmcts.reform.fpl.config.LocalAuthorityNameLookupConfiguration;
import uk.gov.hmcts.reform.fpl.events.SubmittedCaseEvent;
Expand All @@ -21,23 +22,27 @@

import static uk.gov.hmcts.reform.fpl.CaseDefinitionConstants.CASE_TYPE;
import static uk.gov.hmcts.reform.fpl.CaseDefinitionConstants.JURISDICTION;
import static uk.gov.hmcts.reform.fpl.NotifyTemplates.CAFCASS_SUBMISSION_TEMPLATE;
import static uk.gov.hmcts.reform.fpl.NotifyTemplates.HMCTS_COURT_SUBMISSION_TEMPLATE;

@Component
public class NotificationHandler {

private final HmctsCourtLookupConfiguration hmctsCourtLookupConfiguration;
private final CafcassLookupConfiguration cafcassLookupConfiguration;
private final LocalAuthorityNameLookupConfiguration localAuthorityNameLookupConfiguration;
private final NotificationClient notificationClient;
private final Logger logger = LoggerFactory.getLogger(getClass());
private final String uiBaseUrl;

@Autowired
public NotificationHandler(HmctsCourtLookupConfiguration hmctsCourtLookupConfiguration,
CafcassLookupConfiguration cafcassLookupConfiguration,
LocalAuthorityNameLookupConfiguration localAuthorityNameLookupConfiguration,
NotificationClient notificationClient,
@Value("${ccd.ui.base.url}") String uiBaseUrl) {
this.hmctsCourtLookupConfiguration = hmctsCourtLookupConfiguration;
this.cafcassLookupConfiguration = cafcassLookupConfiguration;
this.localAuthorityNameLookupConfiguration = localAuthorityNameLookupConfiguration;
this.notificationClient = notificationClient;
this.uiBaseUrl = uiBaseUrl;
Expand All @@ -47,28 +52,30 @@ public NotificationHandler(HmctsCourtLookupConfiguration hmctsCourtLookupConfigu
public void sendNotificationToHmctsAdmin(SubmittedCaseEvent event) {
CaseDetails caseDetails = event.getCallbackRequest().getCaseDetails();
String localAuthorityCode = (String) caseDetails.getData().get("caseLocalAuthority");
Map<String, String> parameters = buildEmailData(caseDetails, localAuthorityCode);
Map<String, String> parameters = buildHmctsSubmissionNotification(caseDetails, localAuthorityCode);
String reference = Long.toString(caseDetails.getId());

String email = hmctsCourtLookupConfiguration.getCourt(localAuthorityCode).getEmail();
logger.debug(
"Sending submission notification (with template id: {}) to {}", HMCTS_COURT_SUBMISSION_TEMPLATE, email);

try {
notificationClient.sendEmail(HMCTS_COURT_SUBMISSION_TEMPLATE, email, parameters, reference);
} catch (NotificationClientException ex) {
logger.error("Failed to send submission notification (with template id: {}) to {}",
HMCTS_COURT_SUBMISSION_TEMPLATE, email, ex);
}
sendNotification(HMCTS_COURT_SUBMISSION_TEMPLATE, email, parameters, reference);
}

private Map<String, String> buildEmailData(CaseDetails caseDetails, String localAuthorityCode) {
Map orders =
Optional.ofNullable((Map) caseDetails.getData().get("orders")).orElse(ImmutableMap.builder().build());
@EventListener
public void sendNotificationToCafcass(SubmittedCaseEvent event) {
CaseDetails caseDetails = event.getCallbackRequest().getCaseDetails();
String localAuthorityCode = (String) caseDetails.getData().get("caseLocalAuthority");
Map<String, String> parameters = buildCafcassSubmissionNotification(caseDetails, localAuthorityCode);
String reference = (String.valueOf(caseDetails.getId()));
String email = cafcassLookupConfiguration.getCafcass(localAuthorityCode).getEmail();

List orderType = (List) Optional.ofNullable(orders.get("orderType")).orElse(ImmutableList.builder().build());
sendNotification(CAFCASS_SUBMISSION_TEMPLATE, email, parameters, reference);
}

private Map<String, String> buildHmctsSubmissionNotification(CaseDetails caseDetails, String localAuthorityCode) {
String ordersKey = "orders";
Map orders =
Optional.ofNullable((Map) caseDetails.getData().get(ordersKey)).orElse(ImmutableMap.builder().build());

List orderType = (List) Optional.ofNullable(orders.get("orderType")).orElse(ImmutableList.builder().build());

ImmutableMap.Builder<String, String> orderTypeArray = ImmutableMap.builder();
for (int i = 0; i < 5; i++) {
Expand All @@ -87,13 +94,55 @@ private Map<String, String> buildEmailData(CaseDetails caseDetails, String local
return ImmutableMap.<String, String>builder()
.put("court", hmctsCourtLookupConfiguration.getCourt(localAuthorityCode).getName())
.put("localAuthority", localAuthorityNameLookupConfiguration.getLocalAuthorityName(localAuthorityCode))
.put("dataPresent", orderType.isEmpty() ? ("No") : ("Yes"))
.put("fullStop", orderType.isEmpty() ? ("Yes") : ("No"))
.putAll(orderTypeArray.build())
.put(directionsAndInterimKey, (orders.containsKey(directionsAndInterimKey))
.put(directionsAndInterimKey, orders.containsKey(directionsAndInterimKey)
? ("^" + orders.get(directionsAndInterimKey)) : (""))
.put("timeFramePresent", (hearing.containsKey("timeFrame")) ? ("Yes") : ("No"))
.put("timeFramePresent", hearing.containsKey("timeFrame") ? ("Yes") : ("No"))
.put("timeFrameValue", Optional.ofNullable((String) hearing.get("timeFrame")).orElse(""))
.put("reference", String.valueOf(caseDetails.getId()))
.put("caseUrl", uiBaseUrl + "/case/" + JURISDICTION + "/" + CASE_TYPE + "/" + caseDetails.getId())
.build();
}

private Map<String, String> buildCafcassSubmissionNotification(CaseDetails caseDetails, String localAuthorityCode) {
String ordersKey = "orders";
Map orders =
Optional.ofNullable((Map) caseDetails.getData().get(ordersKey)).orElse(ImmutableMap.builder().build());

List orderType = (List) Optional.ofNullable(orders.get("orderType")).orElse(ImmutableList.builder().build());

ImmutableMap.Builder<String, String> orderTypeArray = ImmutableMap.builder();
for (int i = 0; i < 5; i++) {
if (i < orderType.size()) {
orderTypeArray.put(ordersKey + i, "^" + orderType.get(i));
} else {
orderTypeArray.put(ordersKey + i, "");
}
}

String directionsAndInterimKey = "directionsAndInterim";

return ImmutableMap.<String, String>builder()
.put("cafcass", cafcassLookupConfiguration.getCafcass(localAuthorityCode).getName())
.put("localAuthority", localAuthorityNameLookupConfiguration.getLocalAuthorityName(localAuthorityCode))
.putAll(orderTypeArray.build())
.put("dataPresent", orderType.isEmpty() ? ("No") : ("Yes"))
.put("fullStop", orderType.isEmpty() ? ("Yes") : ("No"))
.put(directionsAndInterimKey, orders.containsKey(directionsAndInterimKey)
? "^" + (orders.get(directionsAndInterimKey)) : "")
.put("reference", String.valueOf(caseDetails.getId()))
.put("caseUrl", uiBaseUrl + "/case/" + JURISDICTION + "/" + CASE_TYPE + "/" + caseDetails.getId())
.build();
}

private void sendNotification(String templateId, String email, Map<String, String> parameters, String reference) {
logger.debug("Sending submission notification (with template id: {}) to {}", templateId, email);
try {
notificationClient.sendEmail(templateId, email, parameters, reference);
} catch (NotificationClientException e) {
logger.error("Failed to send submission notification (with template id: {}) to {}", templateId, email, e);
}
}
}
Loading

0 comments on commit d380aaa

Please sign in to comment.