diff --git a/src/main/java/uk/gov/hmcts/ccd/domain/service/common/CaseService.java b/src/main/java/uk/gov/hmcts/ccd/domain/service/common/CaseService.java index dca4df2ae5..9f3d9ea480 100644 --- a/src/main/java/uk/gov/hmcts/ccd/domain/service/common/CaseService.java +++ b/src/main/java/uk/gov/hmcts/ccd/domain/service/common/CaseService.java @@ -23,7 +23,6 @@ import java.util.Map; import java.util.Optional; -import static java.util.stream.Collectors.toList; import static uk.gov.hmcts.ccd.config.JacksonUtils.MAPPER; // TODO CaseService and CaseDataService could probably be merged together. @@ -76,12 +75,24 @@ public CaseDetails createNewCaseDetails(String caseTypeId, String jurisdictionId * @return Optional<CaseDetails> - CaseDetails wrapped in Optional */ public CaseDetails populateCurrentCaseDetailsWithEventFields(CaseDataContent content, CaseDetails caseDetails) { - if (content.getEventData() != null) { - content.getEventData().forEach((key, value) -> caseDetails.getData().put(key, value)); - } + applyEventData(caseDetails, content.getEventData()); + applyEventData(caseDetails, content.getData()); return caseDetails; } + private void applyEventData(CaseDetails caseDetails, Map updates) { + if (updates == null || updates.isEmpty()) { + return; + } + updates.forEach((key, value) -> { + if (value == null || value.isNull()) { + caseDetails.getData().remove(key); + } else { + caseDetails.getData().put(key, value); + } + }); + } + public CaseDetails clone(CaseDetails source) { final CaseDetails clone; @@ -135,7 +146,7 @@ public Map buildJsonFromCaseFieldsWithDefaultValue( .filter(e -> !e.getReference().isBlank()) .map(caseEventFieldComplex -> JacksonUtils .buildFromDottedPath(caseEventFieldComplex.getReference(), - caseEventFieldComplex.getDefaultValue())).collect(toList()); + caseEventFieldComplex.getDefaultValue())).toList(); if (!collect.isEmpty()) { // to prevent construct like "FieldA": {} ObjectNode objectNode = MAPPER.getNodeFactory().objectNode(); diff --git a/src/test/java/uk/gov/hmcts/ccd/domain/service/common/CaseServiceTest.java b/src/test/java/uk/gov/hmcts/ccd/domain/service/common/CaseServiceTest.java index 7a82565bc3..448c3df0d2 100644 --- a/src/test/java/uk/gov/hmcts/ccd/domain/service/common/CaseServiceTest.java +++ b/src/test/java/uk/gov/hmcts/ccd/domain/service/common/CaseServiceTest.java @@ -236,17 +236,23 @@ void populateCurrentCaseDetailsWithEventFields() throws Exception { Map eventData = JacksonUtils.convertValue(MAPPER.readTree( - "{\n" - + " \"PersonFirstName\": \"First Name\",\n" - + " \"PersonLastName\": \"Last Name\"\n" - + "}")); + """ + { + "PersonFirstName": "First Name", + "PersonLastName": "Last Name" + } + """ + )); Map resultData = JacksonUtils.convertValue(MAPPER.readTree( - "{\n" - + " \"PersonFirstName\": \"First Name\",\n" - + " \"PersonLastName\": \"Last Name\",\n" - + " \"Person\":{\"Names\":{\"FirstName\":\"Jack\"}}\n" - + "}")); + """ + { + "PersonFirstName": "First Name", + "PersonLastName": "Last Name", + "Person":{"Names":{"FirstName":"Jack"}} + } + """ + )); CaseDataContent caseDataContent = newCaseDataContent() .withCaseReference(CASE_REFERENCE) @@ -262,6 +268,47 @@ void populateCurrentCaseDetailsWithEventFields() throws Exception { ); } + @Test + @DisplayName("should remove deleted fields from event data when latest data contains nulls") + void shouldRemoveFieldsDeletedOnPage() throws Exception { + CaseDetails caseDetails = buildCaseDetails(); + caseDetails.setId("299"); + caseDetails.getData().put("TextField", MAPPER.getNodeFactory().textNode("old")); + caseDetails.getData().put("OtherField", MAPPER.getNodeFactory().textNode("old2")); + + Map eventData = JacksonUtils.convertValue(MAPPER.readTree( + """ + { + "TextField": "value", + "OtherField": "event" + } + """ + )); + + Map pageData = JacksonUtils.convertValue(MAPPER.readTree( + """ + { + "TextField": null, + "NewField": "new" + } + """ + )); + + CaseDataContent caseDataContent = newCaseDataContent() + .withCaseReference(CASE_REFERENCE) + .withEventData(eventData) + .withData(pageData) + .build(); + + CaseDetails result = caseService.populateCurrentCaseDetailsWithEventFields(caseDataContent, caseDetails); + + assertAll( + () -> assertThat(result.getData().containsKey("TextField"), is(false)), + () -> assertThat(result.getData().get("OtherField").asText(), is("event")), + () -> assertThat(result.getData().get("NewField").asText(), is("new")) + ); + } + @Test @DisplayName("should fail for bad CASE_REFERENCE") void shouldThrowBadRequestException() {