diff --git a/src/main/java/uk/gov/hmcts/reform/civil/handler/callback/user/RespondToClaimSpecCallbackHandler.java b/src/main/java/uk/gov/hmcts/reform/civil/handler/callback/user/RespondToClaimSpecCallbackHandler.java index 5640b94350a..701d9c1c912 100644 --- a/src/main/java/uk/gov/hmcts/reform/civil/handler/callback/user/RespondToClaimSpecCallbackHandler.java +++ b/src/main/java/uk/gov/hmcts/reform/civil/handler/callback/user/RespondToClaimSpecCallbackHandler.java @@ -184,7 +184,7 @@ protected Map callbacks() { .put(callbackKey(MID, "upload"), this::emptyCallbackResponse) .put(callbackKey(MID, "statement-of-truth"), this::resetStatementOfTruth) .put(callbackKey(MID, "validate-payment-date"), this::validateRespondentPaymentDate) - .put(callbackKey(MID, "specCorrespondenceAddress"), this::validateCorrespondenceApplicantAddress) + .put(callbackKey(MID, "specCorrespondenceAddress"), this::validateCorrespondenceAddress) .put(callbackKey(MID, "determineLoggedInSolicitor"), this::determineLoggedInSolicitor) .put(callbackKey(MID, "track"), this::handleDefendAllClaim) .put(callbackKey(MID, "specHandleResponseType"), this::handleRespondentResponseTypeForSpec) @@ -1060,12 +1060,26 @@ private AllocatedTrack getAllocatedTrack(CaseData caseData) { ); } - private CallbackResponse validateCorrespondenceApplicantAddress(CallbackParams callbackParams) { - if (SpecJourneyConstantLRSpec.DEFENDANT_RESPONSE_SPEC.equals(callbackParams.getRequest().getEventId())) { - return validateCorrespondenceApplicantAddress(callbackParams, postcodeValidator); + private CallbackResponse validateCorrespondenceAddress(CallbackParams callbackParams) { + CaseData caseData = callbackParams.getCaseData(); + if (caseData.getIsRespondent1() == YES + && caseData.getRespondentSolicitor1ServiceAddressRequired() == NO) { + List errors = postcodeValidator.validate( + caseData.getRespondentSolicitor1ServiceAddress().getPostCode()); + + return AboutToStartOrSubmitCallbackResponse.builder() + .errors(errors) + .build(); + } else if (caseData.getIsRespondent2() == YES + && caseData.getRespondentSolicitor2ServiceAddressRequired() == NO) { + List errors = postcodeValidator.validate( + caseData.getRespondentSolicitor2ServiceAddress().getPostCode()); + + return AboutToStartOrSubmitCallbackResponse.builder() + .errors(errors) + .build(); } - return AboutToStartOrSubmitCallbackResponse.builder() - .build(); + return AboutToStartOrSubmitCallbackResponse.builder().build(); } private CallbackResponse determineLoggedInSolicitor(CallbackParams callbackParams) { @@ -1118,6 +1132,10 @@ private CallbackResponse populateRespondent1Copy(CallbackParams callbackParams) .respondent1Copy(caseData.getRespondent1()) .respondent1ClaimResponseTestForSpec(caseData.getRespondent1ClaimResponseTypeForSpec()) .respondent2ClaimResponseTestForSpec(caseData.getRespondent2ClaimResponseTypeForSpec()) + .respondentSolicitor1ServiceAddress(Address.builder().build()) + .respondentSolicitor2ServiceAddress(Address.builder().build()) + .respondentSolicitor1ServiceAddressRequired(null) + .respondentSolicitor2ServiceAddressRequired(null) .showConditionFlags(initialShowTags); updatedCaseData.respondent1DetailsForClaimDetailsTab(caseData.getRespondent1().toBuilder().flags(null).build()); @@ -1265,9 +1283,9 @@ private CallbackResponse validateUnavailableDates(CallbackParams callbackParams) } private CallbackResponse validateDateOfBirth(CallbackParams callbackParams) { - Party respondent = callbackParams.getCaseData().getRespondent1(); - if (respondent == null && callbackParams.getCaseData().getRespondent2() != null) { - respondent = callbackParams.getCaseData().getRespondent2(); + Party respondent = callbackParams.getCaseData().getRespondent1Copy(); + if (respondent == null && callbackParams.getCaseData().getRespondent2Copy() != null) { + respondent = callbackParams.getCaseData().getRespondent2Copy(); } List errors = dateOfBirthValidator.validate(respondent); @@ -1345,9 +1363,9 @@ private CallbackResponse setApplicantResponseDeadline(CallbackParams callbackPar AllocatedTrack allocatedTrack = caseData.getAllocatedTrack(); Party updatedRespondent1; - if (NO.equals(caseData.getSpecAoSApplicantCorrespondenceAddressRequired())) { + if (NO.equals(caseData.getTempAddress1Required())) { updatedRespondent1 = caseData.getRespondent1().toBuilder() - .primaryAddress(caseData.getSpecAoSApplicantCorrespondenceAddressdetails()).build(); + .primaryAddress(caseData.getTempAddress1()).build(); } else { updatedRespondent1 = caseData.getRespondent1().toBuilder() .primaryAddress(caseData.getRespondent1Copy().getPrimaryAddress()) @@ -1424,21 +1442,8 @@ && ifResponseTypeIsPartOrFullAdmission(caseData)) { .businessProcess(BusinessProcess.ready(DEFENDANT_RESPONSE_SPEC)); if (caseData.getRespondent2() != null && caseData.getRespondent2Copy() != null) { - Party updatedRespondent2; - - if (NO.equals(caseData.getSpecAoSRespondent2HomeAddressRequired())) { - updatedRespondent2 = caseData.getRespondent2().toBuilder() - .primaryAddress(caseData.getSpecAoSRespondent2HomeAddressDetails()).build(); - } else { - updatedRespondent2 = caseData.getRespondent2().toBuilder() - .primaryAddress(caseData.getRespondent2Copy().getPrimaryAddress()).build(); - } - - updatedData - .respondent2(updatedRespondent2.toBuilder() - .flags(caseData.getRespondent2Copy().getFlags()).build()) - .respondent2Copy(null); - updatedData.respondent2DetailsForClaimDetailsTab(updatedRespondent2.toBuilder().flags(null).build()); + Party updatedRespondent2 = applyRespondent2Address(caseData, updatedData); + updatedData.respondent2DetailsForClaimDetailsTab(updatedRespondent2); } // moving statement of truth value to correct field, this was not possible in mid event. @@ -1495,8 +1500,10 @@ && ifResponseTypeIsPartOrFullAdmission(caseData)) { .build()); } - UnavailabilityDatesUtils.rollUpUnavailabilityDatesForRespondent(updatedData, - toggleService.isUpdateContactDetailsEnabled()); + UnavailabilityDatesUtils.rollUpUnavailabilityDatesForRespondent( + updatedData, + toggleService.isUpdateContactDetailsEnabled() + ); updatedData.respondent1DetailsForClaimDetailsTab(updatedData.build().getRespondent1().toBuilder().flags(null).build()); if (ofNullable(caseData.getRespondent2()).isPresent()) { @@ -1568,6 +1575,21 @@ && isAwaitingAnotherDefendantResponse(caseData)) { .build(); } + private static Party applyRespondent2Address(CaseData caseData, CaseData.CaseDataBuilder updatedData) { + Party updatedRespondent2; + + if (NO.equals(caseData.getTempAddress2Required())) { + updatedRespondent2 = caseData.getRespondent2().toBuilder() + .primaryAddress(caseData.getTempAddress2()).build(); + } else { + updatedRespondent2 = caseData.getRespondent2().toBuilder() + .primaryAddress(caseData.getRespondent2Copy().getPrimaryAddress()).build(); + } + + updatedData.respondent2(updatedRespondent2).respondent2Copy(null); + return updatedRespondent2; + } + private boolean ifResponseTypeIsPartOrFullAdmission(CaseData caseData) { return (RespondentResponseTypeSpec.PART_ADMISSION.equals(caseData.getRespondent1ClaimResponseTypeForSpec()) || RespondentResponseTypeSpec.PART_ADMISSION.equals( @@ -1582,19 +1604,19 @@ private void updateCorrespondenceAddress(CallbackParams callbackParams, CaseData.CaseDataBuilder updatedCaseData, CaseData caseData) { if (solicitorHasCaseRole(callbackParams, RESPONDENTSOLICITORONE) - && caseData.getSpecAoSRespondentCorrespondenceAddressRequired() == YesOrNo.NO) { - Address newAddress = caseData.getSpecAoSRespondentCorrespondenceAddressdetails(); + && caseData.getRespondentSolicitor1ServiceAddressRequired() == YesOrNo.NO) { + Address newAddress = caseData.getRespondentSolicitor1ServiceAddress(); updatedCaseData.specRespondentCorrespondenceAddressdetails(newAddress) - .specAoSRespondentCorrespondenceAddressdetails(Address.builder().build()); + .respondentSolicitor1ServiceAddress(Address.builder().build()); if (getMultiPartyScenario(caseData) == ONE_V_TWO_ONE_LEGAL_REP) { // to keep with heading tab updatedCaseData.specRespondent2CorrespondenceAddressdetails(newAddress); } } else if (solicitorHasCaseRole(callbackParams, RESPONDENTSOLICITORTWO) - && caseData.getSpecAoSRespondent2CorrespondenceAddressRequired() == YesOrNo.NO) { + && caseData.getRespondentSolicitor2ServiceAddressRequired() == YesOrNo.NO) { updatedCaseData.specRespondent2CorrespondenceAddressdetails( - caseData.getSpecAoSRespondent2CorrespondenceAddressdetails()) - .specAoSRespondent2CorrespondenceAddressdetails(Address.builder().build()); + caseData.getRespondentSolicitor2ServiceAddress()) + .respondentSolicitor2ServiceAddress(Address.builder().build()); } } diff --git a/src/main/java/uk/gov/hmcts/reform/civil/model/CaseDataParent.java b/src/main/java/uk/gov/hmcts/reform/civil/model/CaseDataParent.java index 7d2a5546ce9..08b9556caf8 100644 --- a/src/main/java/uk/gov/hmcts/reform/civil/model/CaseDataParent.java +++ b/src/main/java/uk/gov/hmcts/reform/civil/model/CaseDataParent.java @@ -723,6 +723,23 @@ public boolean isApplicantNotRepresented() { private FastTrackAllocation fastTrackAllocation; + /** + * used to temporary hold addresses. + */ + private final Address tempAddress1; + /** + * used with tempAddress1. + */ + private final YesOrNo tempAddress1Required; + /** + * used to temporary hold addresses. + */ + private final Address tempAddress2; + /** + * used with tempAddress1. + */ + private final YesOrNo tempAddress2Required; + @JsonIgnore public boolean isResponseAcceptedByClaimant() { return applicant1AcceptAdmitAmountPaidSpec == YesOrNo.YES diff --git a/src/main/java/uk/gov/hmcts/reform/civil/utils/UnavailabilityDatesUtils.java b/src/main/java/uk/gov/hmcts/reform/civil/utils/UnavailabilityDatesUtils.java index 5c394d09ee5..81a5e845f2e 100644 --- a/src/main/java/uk/gov/hmcts/reform/civil/utils/UnavailabilityDatesUtils.java +++ b/src/main/java/uk/gov/hmcts/reform/civil/utils/UnavailabilityDatesUtils.java @@ -76,7 +76,7 @@ public static void rollUpUnavailabilityDatesForRespondent(CaseData.CaseDataBuild .getUnavailableDates(); List> updatedUnavailableDates = addEventAndDate( - caseData.getRespondent1ResponseDate().toLocalDate(), + caseData.getRespondent2ResponseDate().toLocalDate(), DEFENDANT_RESPONSE_EVENT, respondent2DQUnavailableDates ); diff --git a/src/test/java/uk/gov/hmcts/reform/civil/handler/callback/user/RespondToClaimSpecCallbackHandlerTest.java b/src/test/java/uk/gov/hmcts/reform/civil/handler/callback/user/RespondToClaimSpecCallbackHandlerTest.java index 6fbfc1fb527..1ae04095de2 100644 --- a/src/test/java/uk/gov/hmcts/reform/civil/handler/callback/user/RespondToClaimSpecCallbackHandlerTest.java +++ b/src/test/java/uk/gov/hmcts/reform/civil/handler/callback/user/RespondToClaimSpecCallbackHandlerTest.java @@ -19,6 +19,7 @@ import uk.gov.hmcts.reform.ccd.client.model.CallbackRequest; import uk.gov.hmcts.reform.ccd.client.model.CallbackResponse; import uk.gov.hmcts.reform.ccd.client.model.SubmittedCallbackResponse; +import uk.gov.hmcts.reform.civil.callback.CallbackException; import uk.gov.hmcts.reform.civil.callback.CallbackParams; import uk.gov.hmcts.reform.civil.callback.CallbackType; import uk.gov.hmcts.reform.civil.constants.SpecJourneyConstantLRSpec; @@ -55,23 +56,26 @@ import uk.gov.hmcts.reform.civil.model.UnavailableDate; import uk.gov.hmcts.reform.civil.model.common.DynamicList; import uk.gov.hmcts.reform.civil.model.common.Element; -import uk.gov.hmcts.reform.civil.model.dq.RequestedCourt; import uk.gov.hmcts.reform.civil.model.dq.Respondent1DQ; import uk.gov.hmcts.reform.civil.model.dq.Respondent2DQ; -import uk.gov.hmcts.reform.civil.model.dq.SmallClaimHearing; import uk.gov.hmcts.reform.civil.model.dq.Witness; import uk.gov.hmcts.reform.civil.model.dq.Witnesses; +import uk.gov.hmcts.reform.civil.model.dq.RequestedCourt; +import uk.gov.hmcts.reform.civil.model.dq.Expert; +import uk.gov.hmcts.reform.civil.model.dq.Experts; +import uk.gov.hmcts.reform.civil.model.dq.ExpertDetails; +import uk.gov.hmcts.reform.civil.model.dq.SmallClaimHearing; import uk.gov.hmcts.reform.civil.referencedata.LocationRefDataService; import uk.gov.hmcts.reform.civil.referencedata.model.LocationRefData; import uk.gov.hmcts.reform.civil.sampledata.AddressBuilder; import uk.gov.hmcts.reform.civil.sampledata.CaseDataBuilder; import uk.gov.hmcts.reform.civil.sampledata.PartyBuilder; -import uk.gov.hmcts.reform.civil.service.CoreCaseUserService; import uk.gov.hmcts.reform.civil.service.DeadlinesCalculator; import uk.gov.hmcts.reform.civil.service.ExitSurveyContentService; import uk.gov.hmcts.reform.civil.service.FeatureToggleService; import uk.gov.hmcts.reform.civil.service.Time; import uk.gov.hmcts.reform.civil.service.UserService; +import uk.gov.hmcts.reform.civil.service.CoreCaseUserService; import uk.gov.hmcts.reform.civil.service.citizenui.responsedeadline.DeadlineExtensionCalculatorService; import uk.gov.hmcts.reform.civil.service.flowstate.FlowFlag; import uk.gov.hmcts.reform.civil.service.flowstate.StateFlowEngine; @@ -79,8 +83,8 @@ import uk.gov.hmcts.reform.civil.utils.AssignCategoryId; import uk.gov.hmcts.reform.civil.utils.CaseFlagsInitialiser; import uk.gov.hmcts.reform.civil.utils.CourtLocationUtils; -import uk.gov.hmcts.reform.civil.utils.ElementUtils; import uk.gov.hmcts.reform.civil.utils.MonetaryConversions; +import uk.gov.hmcts.reform.civil.utils.ElementUtils; import uk.gov.hmcts.reform.civil.validation.DateOfBirthValidator; import uk.gov.hmcts.reform.civil.validation.PaymentDateValidator; import uk.gov.hmcts.reform.civil.validation.PostcodeValidator; @@ -99,7 +103,9 @@ import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; @@ -119,6 +125,7 @@ import static uk.gov.hmcts.reform.civil.enums.CaseRole.RESPONDENTSOLICITORTWO; import static uk.gov.hmcts.reform.civil.enums.RespondentResponsePartAdmissionPaymentTimeLRspec.IMMEDIATELY; import static uk.gov.hmcts.reform.civil.enums.RespondentResponseTypeSpec.FULL_ADMISSION; +import static uk.gov.hmcts.reform.civil.enums.RespondentResponseTypeSpec.FULL_DEFENCE; import static uk.gov.hmcts.reform.civil.enums.YesOrNo.NO; import static uk.gov.hmcts.reform.civil.enums.YesOrNo.YES; import static uk.gov.hmcts.reform.civil.helpers.DateFormatHelper.DATE; @@ -198,15 +205,82 @@ public void setup() { ); } + @Test + void whenCallBackEventNotImplementedOrEventInvalid() { + // Given + String postCode = "postCode"; + CaseData caseData = CaseData.builder() + .build().toBuilder() + .respondentSolicitor1ServiceAddressRequired(NO) + .respondentSolicitor1ServiceAddress(Address.builder().postCode(postCode).build()) + .isRespondent1(YES) + .build(); + CallbackParams callbackParams = callbackParamsOf(caseData, CallbackType.MID, " ").toBuilder() + .request(CallbackRequest.builder().eventId(SpecJourneyConstantLRSpec.DEFENDANT_RESPONSE_SPEC) + .build()).build(); + + //When + CallbackException ex = assertThrows(CallbackException.class, () -> handler.handle(callbackParams), + + "A CallbackException was expected to be thrown but wasn't."); + // Then + assertThat(ex.getMessage()).contains("Callback for event"); + } + + @Test + void resetStatementOfTruth() { + CaseData caseData = CaseDataBuilder.builder().build(); + CallbackParams params = callbackParamsOf(caseData, CallbackType.MID, "statement-of-truth"); + CallbackRequest request = CallbackRequest.builder() + .eventId(SpecJourneyConstantLRSpec.DEFENDANT_RESPONSE_SPEC) + .build(); + params = params.toBuilder().request(request).build(); + + // When + CallbackResponse response = handler.handle(params); + + // Then + assertNotNull(response); + } + @Test void midSpecCorrespondenceAddress_checkAddressIfWasIncorrect() { // Given String postCode = "postCode"; CaseData caseData = CaseData.builder() - .specAoSApplicantCorrespondenceAddressRequired(YesOrNo.NO) - .specAoSApplicantCorrespondenceAddressdetails(Address.builder() - .postCode(postCode) - .build()) + .build().toBuilder() + .respondentSolicitor1ServiceAddressRequired(NO) + .respondentSolicitor1ServiceAddress(Address.builder().postCode(postCode).build()) + .isRespondent1(YES) + .build(); + CallbackParams params = callbackParamsOf(caseData, CallbackType.MID, "specCorrespondenceAddress"); + CallbackRequest request = CallbackRequest.builder() + .eventId(SpecJourneyConstantLRSpec.DEFENDANT_RESPONSE_SPEC) + .build(); + params = params.toBuilder().request(request).build(); + + List errors = Collections.singletonList("error 1"); + Mockito.when(postcodeValidator.validate(postCode)).thenReturn(errors); + + // When + CallbackResponse response = handler.handle(params); + + // Then + assertEquals(errors, ((AboutToStartOrSubmitCallbackResponse) response).getErrors()); + } + + @Test + void midSpecCorrespondenceAddress_checkAddressIfWasIncorrectForSol2() { + // Given + String postCode = "postCode"; + CaseData caseData = CaseData.builder() + .build().toBuilder() + .respondentSolicitor1ServiceAddressRequired(YES) + .respondentSolicitor1ServiceAddress(Address.builder().postCode(postCode).build()) + .isRespondent1(YES) + .isRespondent2(YES) + .respondentSolicitor2ServiceAddressRequired(NO) + .respondentSolicitor2ServiceAddress(Address.builder().postCode(postCode).build()) .build(); CallbackParams params = callbackParamsOf(caseData, CallbackType.MID, "specCorrespondenceAddress"); CallbackRequest request = CallbackRequest.builder() @@ -314,10 +388,8 @@ void testSpecDefendantResponseFastTrackOneVTwoLegalRep() { assertThat(response.getData()).isNotNull(); assertThat(response.getData()).containsEntry("responseClaimTrack", AllocatedTrack.FAST_CLAIM.name()); assertThat(response.getData()).containsEntry("specDisputesOrPartAdmission", "No"); - assertThat(response.getData()).containsEntry( - "specPaidLessAmountOrDisputesOrPartAdmission", - "No" - ); + assertThat(response.getData()).containsEntry("specPaidLessAmountOrDisputesOrPartAdmission", + "No"); } @Test @@ -347,10 +419,8 @@ void testSpecDefendantResponseFastTrackOneVTwoSameLegalRep() { assertThat(response.getData()).isNotNull(); assertThat(response.getData()).containsEntry("responseClaimTrack", AllocatedTrack.FAST_CLAIM.name()); assertThat(response.getData()).containsEntry("specDisputesOrPartAdmission", "No"); - assertThat(response.getData()).containsEntry( - "specPaidLessAmountOrDisputesOrPartAdmission", - "No" - ); + assertThat(response.getData()).containsEntry("specPaidLessAmountOrDisputesOrPartAdmission", + "No"); } @Test @@ -376,10 +446,8 @@ void testSpecDefendantResponseFastTrackTwoVOne() { assertThat(response.getData()).isNotNull(); assertThat(response.getData()).containsEntry("responseClaimTrack", AllocatedTrack.FAST_CLAIM.name()); assertThat(response.getData()).containsEntry("specDisputesOrPartAdmission", "No"); - assertThat(response.getData()).containsEntry( - "specPaidLessAmountOrDisputesOrPartAdmission", - "No" - ); + assertThat(response.getData()).containsEntry("specPaidLessAmountOrDisputesOrPartAdmission", + "No"); } @Test @@ -662,9 +730,6 @@ public void testValidateRespondentPaymentDate() { AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler .handle(params); - List expectedErrorArray = new ArrayList<>(); - expectedErrorArray.add("Date for when will the amount be paid must be today or in the future."); - // Then assertThat(response).isNotNull(); /* @@ -723,8 +788,9 @@ void updateRespondent1AddressWhenUpdated() { CaseData caseData = CaseDataBuilder.builder() .respondent1(PartyBuilder.builder().individual().build()) .atStateApplicantRespondToDefenceAndProceed() - .atSpecAoSApplicantCorrespondenceAddressRequired(NO) - .atSpecAoSApplicantCorrespondenceAddressDetails(AddressBuilder.maximal().build()) + .build().toBuilder() + .tempAddress1Required(NO) + .tempAddress1(AddressBuilder.maximal().build()) .build(); CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); @@ -755,15 +821,21 @@ void updateRespondent2AddressWhenUpdated() { when(stateFlowEngine.evaluate(any(CaseData.class))).thenReturn(mockedStateFlow); when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORTWO))).thenReturn(true); + Address newAddress2 = AddressBuilder.defaults().build(); CaseData caseData = CaseDataBuilder.builder().atStateApplicantRespondToDefenceAndProceed() .respondent2DQ() .respondent1Copy(PartyBuilder.builder().individual().build()) - .atSpecAoSApplicantCorrespondenceAddressRequired(YES) .addRespondent2(YES) .respondent2(PartyBuilder.builder().individual().build()) .respondent2Copy(PartyBuilder.builder().individual().build()) - .atSpecAoSRespondent2HomeAddressRequired(NO) - .atSpecAoSRespondent2HomeAddressDetails(AddressBuilder.maximal().build()) + .build().toBuilder() + .tempAddress1Required(YES) + .tempAddress1(Address.builder().build()) + .build().toBuilder() + .tempAddress2Required(NO) + .tempAddress2(newAddress2) + .respondentSolicitor2ServiceAddressRequired(NO) + .respondentSolicitor2ServiceAddress(newAddress2) .build(); CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); @@ -777,28 +849,52 @@ void updateRespondent2AddressWhenUpdated() { // Then assertThat(response.getData()) .extracting("respondent2").extracting("primaryAddress") - .extracting("AddressLine1").isEqualTo("address line 1"); + .extracting("AddressLine1").isEqualTo(newAddress2.getAddressLine1()); assertThat(response.getData()) .extracting("respondent2").extracting("primaryAddress") - .extracting("AddressLine2").isEqualTo("address line 2"); + .extracting("AddressLine2").isEqualTo(newAddress2.getAddressLine2()); assertThat(response.getData()) .extracting("respondent2").extracting("primaryAddress") - .extracting("AddressLine3").isEqualTo("address line 3"); + .extracting("AddressLine3").isEqualTo(newAddress2.getAddressLine3()); } @Test - void updateRespondent2AddressWhenSpecAoSRespondent2HomeAddressRequiredIsNO() { + void defendantResponsePopulatesWitnessesData() { // Given + LocalDateTime dateTime = LocalDateTime.of(2023, 6, 6, 6, 6, 6); + LocalDate date = dateTime.toLocalDate(); when(userService.getUserInfo(anyString())).thenReturn(UserInfo.builder().uid("uid").build()); + when(time.now()).thenReturn(dateTime); when(mockedStateFlow.isFlagSet(any())).thenReturn(true); when(stateFlowEngine.evaluate(any(CaseData.class))).thenReturn(mockedStateFlow); - - Party partyWithPrimaryAddress = PartyBuilder.builder().individual().build(); - partyWithPrimaryAddress.setPrimaryAddress(AddressBuilder.maximal() - .addressLine1("address line 1") - .addressLine2("address line 2") - .addressLine3("address line 3") - .build()); + when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORTWO))).thenReturn(true); + when(toggleService.isHmcEnabled()).thenReturn(true); + + Witnesses res1witnesses = Witnesses.builder().details( + wrapElements( + Witness.builder() + .firstName("Witness") + .lastName("One") + .emailAddress("test-witness-one@example.com") + .phoneNumber("07865456789") + .reasonForWitness("great reasons") + .eventAdded("Defendant Response Event") + .dateAdded(date) + .build()) + ).build(); + + Witnesses res2witnesses = Witnesses.builder().details( + wrapElements( + Witness.builder() + .firstName("Witness") + .lastName("Two") + .emailAddress("test-witness-two@example.com") + .phoneNumber("07532628263") + .reasonForWitness("good reasons") + .eventAdded("Defendant Response Event") + .dateAdded(date) + .build()) + ).build(); CaseData caseData = CaseDataBuilder.builder().atStateApplicantRespondToDefenceAndProceed() .respondent2DQ() @@ -806,422 +902,693 @@ void updateRespondent2AddressWhenSpecAoSRespondent2HomeAddressRequiredIsNO() { .addRespondent2(YES) .respondent2(PartyBuilder.builder().individual().build()) .respondent2Copy(PartyBuilder.builder().individual().build()) - .atSpecAoSRespondent2HomeAddressRequired(NO) - .atSpecAoSRespondent2HomeAddressDetails(AddressBuilder.maximal() - .addressLine1("new address line 1") - .build()) + .build().toBuilder() + .respondent1DQWitnessesSmallClaim(res1witnesses) + .respondent2DQWitnessesSmallClaim(res2witnesses) + .build().toBuilder() + .tempAddress1Required(YES) + .tempAddress1(Address.builder().build()) + .respondent2ResponseDate(dateTime) + .respondent1ResponseDate(dateTime).build().toBuilder() + .tempAddress2Required(NO) + .tempAddress2(AddressBuilder.maximal().build()) .build(); + CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); + when(deadlinesCalculator.calculateApplicantResponseDeadlineSpec(any(), any())) + .thenReturn(LocalDateTime.now()); + // When - AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler.handle( - callbackParamsOf(caseData, ABOUT_TO_SUBMIT)); + AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler + .handle(params); + + var objectMapper = new ObjectMapper(); + objectMapper.findAndRegisterModules(); + objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); // Then - assertThat(response.getData()) - .extracting("respondent2") - .extracting("primaryAddress") - .extracting("AddressLine1") - .isEqualTo("new address line 1"); + + Witnesses actualRespondent1DQWitnesses = objectMapper.convertValue(response.getData().get("respondent1DQWitnesses"), new TypeReference<>() {}); + Witness actualRespondent1Witness = unwrapElements(actualRespondent1DQWitnesses.getDetails()).get(0); + assertThat(actualRespondent1Witness.getPartyID()).isNotNull(); + assertThat(actualRespondent1Witness.getFirstName()).isEqualTo("Witness"); + assertThat(actualRespondent1Witness.getLastName()).isEqualTo("One"); + assertThat(actualRespondent1Witness.getEmailAddress()).isEqualTo("test-witness-one@example.com"); + assertThat(actualRespondent1Witness.getPhoneNumber()).isEqualTo("07865456789"); + assertThat(actualRespondent1Witness.getReasonForWitness()).isEqualTo("great reasons"); + assertThat(actualRespondent1Witness.getEventAdded()).isEqualTo("Defendant Response Event"); + assertThat(actualRespondent1Witness.getDateAdded()).isEqualTo(date); + + Witnesses actualRespondent2DQWitnesses = objectMapper.convertValue(response.getData().get("respondent2DQWitnesses"), new TypeReference<>() {}); + Witness respondent2Witness = unwrapElements(actualRespondent2DQWitnesses.getDetails()).get(0); + assertThat(respondent2Witness.getPartyID()).isNotNull(); + assertThat(respondent2Witness.getFirstName()).isEqualTo("Witness"); + assertThat(respondent2Witness.getLastName()).isEqualTo("Two"); + assertThat(respondent2Witness.getEmailAddress()).isEqualTo("test-witness-two@example.com"); + assertThat(respondent2Witness.getPhoneNumber()).isEqualTo("07532628263"); + assertThat(respondent2Witness.getReasonForWitness()).isEqualTo("good reasons"); + assertThat(respondent2Witness.getEventAdded()).isEqualTo("Defendant Response Event"); + assertThat(respondent2Witness.getDateAdded()).isEqualTo(date); + } - @Test - void updateRespondent2AddressWhenSpecAoSRespondent2HomeAddressRequiredIsNotNO() { - // Given - when(userService.getUserInfo(anyString())).thenReturn(UserInfo.builder().uid("uid").build()); - when(mockedStateFlow.isFlagSet(any())).thenReturn(true); - when(stateFlowEngine.evaluate(any(CaseData.class))).thenReturn(mockedStateFlow); + @Nested + class HandleLocations { + + @Test + void oneVOne() { + // Given + DynamicList locationValues = DynamicList.fromList(List.of("Value 1")); + DynamicList preferredCourt = DynamicList.builder() + .listItems(locationValues.getListItems()) + .value(locationValues.getListItems().get(0)) + .build(); + Party defendant1 = Party.builder() + .type(Party.Type.COMPANY) + .companyName("company") + .build(); + CaseData caseData = CaseData.builder() + .caseAccessCategory(SPEC_CLAIM) + .ccdCaseReference(354L) + .respondent1(defendant1) + .respondent1Copy(defendant1) + .respondent1DQ( + Respondent1DQ.builder() + .respondToCourtLocation( + RequestedCourt.builder() + .responseCourtLocations(preferredCourt) + .reasonForHearingAtSpecificCourt("Reason") + .build() + ) + .build() + ) + .showConditionFlags(EnumSet.of( + DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_1 + )) + .build(); + CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); + + List locations = List.of(LocationRefData.builder().build()); + when(locationRefDataService.getCourtLocationsForDefaultJudgments(any())) + .thenReturn(locations); + LocationRefData completePreferredLocation = LocationRefData.builder() + .regionId("regionId") + .epimmsId("epimms") + .courtLocationCode("code") + .build(); + when(courtLocationUtils.findPreferredLocationData( + locations, preferredCourt + )).thenReturn(completePreferredLocation); + StateFlow flow = mock(StateFlow.class); + when(flow.isFlagSet(FlowFlag.TWO_RESPONDENT_REPRESENTATIVES)).thenReturn(false); + when(stateFlowEngine.evaluate(caseData)) + .thenReturn(flow); + when(coreCaseUserService.userHasCaseRole(anyString(), anyString(), any(CaseRole.class))) + .thenReturn(true); + UserInfo userInfo = UserInfo.builder().uid("798").build(); + when(userService.getUserInfo(anyString())).thenReturn(userInfo); + + // When + AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler + .handle(params); + + // Then + AbstractObjectAssert sent1 = assertThat(response.getData()) + .extracting("respondent1DQRequestedCourt"); + sent1.extracting("caseLocation") + .extracting("region") + .isEqualTo(completePreferredLocation.getRegionId()); + sent1.extracting("caseLocation") + .extracting("baseLocation") + .isEqualTo(completePreferredLocation.getEpimmsId()); + sent1.extracting("responseCourtCode") + .isEqualTo(completePreferredLocation.getCourtLocationCode()); + sent1.extracting("reasonForHearingAtSpecificCourt") + .isEqualTo("Reason"); + } + + @Test + void oneVTwo_SecondDefendantRepliesSameLegalRep() { + // Given + DynamicList locationValues = DynamicList.fromList(List.of("Value 1")); + DynamicList preferredCourt = DynamicList.builder() + .listItems(locationValues.getListItems()) + .value(locationValues.getListItems().get(0)) + .build(); + Party defendant1 = Party.builder() + .type(Party.Type.COMPANY) + .companyName("company") + .build(); + Party defendant2 = Party.builder() + .type(Party.Type.COMPANY) + .companyName("company2") + .build(); + CaseData caseData = CaseData.builder() + .respondent2SameLegalRepresentative(YES) + .caseAccessCategory(SPEC_CLAIM) + .ccdCaseReference(354L) + .defenceAdmitPartPaymentTimeRouteRequired(IMMEDIATELY) + .respondent2ClaimResponseTypeForSpec(FULL_ADMISSION) + .respondent1(defendant1) + .respondent1Copy(defendant1) + .respondent2(defendant2) + .respondent2Copy(defendant2) + .respondent1DQ( + Respondent1DQ.builder() + .respondToCourtLocation( + RequestedCourt.builder() + .responseCourtLocations(preferredCourt) + .reasonForHearingAtSpecificCourt("Reason") + .build() + ) + .build() + ) + .respondent2DQ( + Respondent2DQ.builder() + .respondToCourtLocation2( + RequestedCourt.builder() + .responseCourtLocations(preferredCourt) + .reasonForHearingAtSpecificCourt("Reason123") + .build() + ) + .build() + ) + .showConditionFlags(EnumSet.of( + DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_1, + DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_2 + )) + .build(); + CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); + + List locations = List.of(LocationRefData.builder().build()); + when(locationRefDataService.getCourtLocationsForDefaultJudgments(any())) + .thenReturn(locations); + LocationRefData completePreferredLocation = LocationRefData.builder() + .regionId("regionId") + .epimmsId("epimms") + .courtLocationCode("code") + .build(); + when(courtLocationUtils.findPreferredLocationData( + locations, preferredCourt + )).thenReturn(completePreferredLocation); + StateFlow flow = mock(StateFlow.class); + when(flow.isFlagSet(FlowFlag.TWO_RESPONDENT_REPRESENTATIVES)).thenReturn(true); + when(stateFlowEngine.evaluate(caseData)).thenReturn(flow); + when(coreCaseUserService.userHasCaseRole(anyString(), anyString(), any(CaseRole.class))) + .thenReturn(true); + UserInfo userInfo = UserInfo.builder().uid("798").build(); + when(userService.getUserInfo(anyString())).thenReturn(userInfo); + LocalDate whenWillPay = LocalDate.now().plusDays(5); + given(deadlineExtensionCalculatorService.calculateExtendedDeadline(any(), anyInt())).willReturn(whenWillPay); + // When + AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); + + // Then + AbstractObjectAssert sent2 = assertThat(response.getData()) + .extracting("respondent2DQRequestedCourt"); + sent2.extracting("caseLocation") + .extracting("region") + .isEqualTo(completePreferredLocation.getRegionId()); + sent2.extracting("caseLocation") + .extracting("baseLocation") + .isEqualTo(completePreferredLocation.getEpimmsId()); + sent2.extracting("responseCourtCode") + .isEqualTo(completePreferredLocation.getCourtLocationCode()); + sent2.extracting("reasonForHearingAtSpecificCourt") + .isEqualTo("Reason123"); + } + + @Test + void oneVTwo_SecondDefendantReplies() { + // Given + DynamicList locationValues = DynamicList.fromList(List.of("Value 1")); + DynamicList preferredCourt = DynamicList.builder() + .listItems(locationValues.getListItems()) + .value(locationValues.getListItems().get(0)) + .build(); + Party defendant1 = Party.builder() + .type(Party.Type.COMPANY) + .companyName("company") + .build(); + Party defendant2 = Party.builder() + .type(Party.Type.COMPANY) + .companyName("company 2") + .build(); + CaseData caseData = CaseData.builder() + .caseAccessCategory(SPEC_CLAIM) + .ccdCaseReference(354L) + .respondent1(defendant1) + .respondent1Copy(defendant1) + .respondent2(defendant2) + .respondent2Copy(defendant2) + .respondent1DQ( + Respondent1DQ.builder() + .respondToCourtLocation( + RequestedCourt.builder() + .responseCourtLocations(preferredCourt) + .reasonForHearingAtSpecificCourt("Reason") + .build() + ) + .build() + ) + .respondent2DQ( + Respondent2DQ.builder() + .respondToCourtLocation2( + RequestedCourt.builder() + .responseCourtLocations(preferredCourt) + .reasonForHearingAtSpecificCourt("Reason123") + .build() + ) + .build() + ) + .showConditionFlags(EnumSet.of( + DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_1, + DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_2 + )) + .build(); + CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); + + List locations = List.of(LocationRefData.builder().build()); + when(locationRefDataService.getCourtLocationsForDefaultJudgments(any())) + .thenReturn(locations); + LocationRefData completePreferredLocation = LocationRefData.builder() + .regionId("regionId") + .epimmsId("epimms") + .courtLocationCode("code") + .build(); + when(courtLocationUtils.findPreferredLocationData( + locations, preferredCourt + )).thenReturn(completePreferredLocation); + StateFlow flow = mock(StateFlow.class); + when(flow.isFlagSet(FlowFlag.TWO_RESPONDENT_REPRESENTATIVES)).thenReturn(true); + when(stateFlowEngine.evaluate(caseData)).thenReturn(flow); + when(coreCaseUserService.userHasCaseRole(anyString(), anyString(), any(CaseRole.class))) + .thenReturn(true); + UserInfo userInfo = UserInfo.builder().uid("798").build(); + when(userService.getUserInfo(anyString())).thenReturn(userInfo); + + // When + AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler + .handle(params); + + // Then + AbstractObjectAssert sent2 = assertThat(response.getData()) + .extracting("respondent2DQRequestedCourt"); + sent2.extracting("caseLocation") + .extracting("region") + .isEqualTo(completePreferredLocation.getRegionId()); + sent2.extracting("caseLocation") + .extracting("baseLocation") + .isEqualTo(completePreferredLocation.getEpimmsId()); + sent2.extracting("responseCourtCode") + .isEqualTo(completePreferredLocation.getCourtLocationCode()); + sent2.extracting("reasonForHearingAtSpecificCourt") + .isEqualTo("Reason123"); + } + } - Party partyWithPrimaryAddress = PartyBuilder.builder().individual().build(); - partyWithPrimaryAddress.setPrimaryAddress(AddressBuilder.maximal() - .addressLine1("address line 1") - .addressLine2("address line 2") - .addressLine3("address line 3") - .build()); + } - CaseData caseData = CaseDataBuilder.builder().atStateApplicantRespondToDefenceAndProceed() - .respondent2DQ() - .respondent1Copy(PartyBuilder.builder().individual().build()) - .addRespondent2(YES) - .respondent2(PartyBuilder.builder().individual().build()) - .respondent2Copy(PartyBuilder.builder().individual().build()) - .atSpecAoSRespondent2HomeAddressRequired(YES) - .build(); + @Test + void shouldNullDocuments_whenInvokedAndCaseFileEnabled() { + // Given + when(userService.getUserInfo(anyString())).thenReturn(UserInfo.builder().uid("uid").build()); + when(mockedStateFlow.isFlagSet(any())).thenReturn(true); + when(stateFlowEngine.evaluate(any(CaseData.class))).thenReturn(mockedStateFlow); + when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORTWO))).thenReturn(true); + when(toggleService.isCaseFileViewEnabled()).thenReturn(true); + var testDocument = ResponseDocument.builder() + .file(Document.builder().documentUrl("fake-url").documentFileName("file-name").documentBinaryUrl("binary-url").build()).build(); - // When - AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler.handle( - callbackParamsOf(caseData, ABOUT_TO_SUBMIT)); + CaseData caseData = CaseData.builder() + .respondent1(PartyBuilder.builder().individual().build()) + .respondent1Copy(PartyBuilder.builder().individual().build()) + .respondent1DQ(Respondent1DQ.builder().build()) + .respondent2(PartyBuilder.builder().individual().build()) + .respondent2Copy(PartyBuilder.builder().individual().build()) + .respondent2DQ(Respondent2DQ.builder().build()) + .respondent1ClaimResponseTypeForSpec(RespondentResponseTypeSpec.FULL_DEFENCE) + .respondent2ClaimResponseTypeForSpec(RespondentResponseTypeSpec.FULL_DEFENCE) + .ccdCaseReference(354L) + .respondent1SpecDefenceResponseDocument(testDocument) + .respondent2SpecDefenceResponseDocument(testDocument) + .build(); - // Then - assertThat(response.getData()) - .extracting("respondent2") - .extracting("primaryAddress") - .extracting("AddressLine1") - .isEqualTo("address line 1"); - assertThat(response.getData()) - .extracting("respondent2") - .extracting("primaryAddress") - .extracting("AddressLine2") - .isEqualTo("address line 2"); - assertThat(response.getData()) - .extracting("respondent2") - .extracting("primaryAddress") - .extracting("AddressLine3") - .isEqualTo("address line 3"); - } + CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); + + // When + AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler + .handle(params); + + // Then + assertThat(response.getData().get("respondent1SpecDefenceResponseDocument")).isNull(); + assertThat(response.getData().get("respondent2SpecDefenceResponseDocument")).isNull(); } @Test - void defendantResponsePopulatesWitnessesData() { + void shouldUpdateExpertEvents_whenInvokedAndUpdateContactDetailsEnabled_For2DivergeResponse() { // Given LocalDateTime dateTime = LocalDateTime.of(2023, 6, 6, 6, 6, 6); - LocalDate date = dateTime.toLocalDate(); when(userService.getUserInfo(anyString())).thenReturn(UserInfo.builder().uid("uid").build()); - when(time.now()).thenReturn(dateTime); when(mockedStateFlow.isFlagSet(any())).thenReturn(true); when(stateFlowEngine.evaluate(any(CaseData.class))).thenReturn(mockedStateFlow); when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORTWO))).thenReturn(true); - when(toggleService.isHmcEnabled()).thenReturn(true); - - Witnesses res1witnesses = Witnesses.builder().details( - wrapElements( - Witness.builder() - .firstName("Witness") - .lastName("One") - .emailAddress("test-witness-one@example.com") - .phoneNumber("07865456789") - .reasonForWitness("great reasons") - .eventAdded("Defendant Response Event") - .dateAdded(date) - .build()) - ).build(); - - Witnesses res2witnesses = Witnesses.builder().details( - wrapElements( - Witness.builder() - .firstName("Witness") - .lastName("Two") - .emailAddress("test-witness-two@example.com") - .phoneNumber("07532628263") - .reasonForWitness("good reasons") - .eventAdded("Defendant Response Event") - .dateAdded(date) - .build()) - ).build(); - - CaseData caseData = CaseDataBuilder.builder().atStateApplicantRespondToDefenceAndProceed() - .respondent2DQ() + when(toggleService.isUpdateContactDetailsEnabled()).thenReturn(true); + + CaseData caseData = CaseData.builder() + .respondent1(PartyBuilder.builder().individual().build()) .respondent1Copy(PartyBuilder.builder().individual().build()) - .atSpecAoSApplicantCorrespondenceAddressRequired(YES) - .addRespondent2(YES) + .respondent1DQ(Respondent1DQ.builder() + .respondent1DQExperts(Experts.builder() + .details(wrapElements(Expert.builder().build())).build()) + .build()) .respondent2(PartyBuilder.builder().individual().build()) .respondent2Copy(PartyBuilder.builder().individual().build()) - .atSpecAoSRespondent2HomeAddressRequired(NO) - .atSpecAoSRespondent2HomeAddressDetails(AddressBuilder.maximal().build()) - .build().toBuilder() - .respondent1DQWitnessesSmallClaim(res1witnesses) - .respondent2DQWitnessesSmallClaim(res2witnesses) - .build().toBuilder() - .respondent2ResponseDate(dateTime) - .respondent1ResponseDate(dateTime).build(); + .respondent2DQ(Respondent2DQ.builder().build()) + .claimant1ClaimResponseTypeForSpec(FULL_DEFENCE) + .claimant2ClaimResponseTypeForSpec(FULL_ADMISSION) + .ccdCaseReference(354L) + .respondent1ResponseDate(dateTime).build().toBuilder() + .respondent2SameLegalRepresentative(YES) + .build(); + + CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); + + // When + AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler + .handle(params); + + // Then + assertThat(response.getData().get("respondent1DQExperts")).isNotNull(); + assertThat(response.getData().get("respondent2DQExperts")).isNull(); + + } + + @Test + void shouldUpdateExpertEvents_whenInvokedAndUpdateContactDetailsEnabled_CanAddApplicant2() { + // Given + LocalDateTime dateTime = LocalDateTime.of(2023, 6, 6, 6, 6, 6); + when(userService.getUserInfo(anyString())).thenReturn(UserInfo.builder().uid("uid").build()); + when(mockedStateFlow.isFlagSet(any())).thenReturn(true); + when(stateFlowEngine.evaluate(any(CaseData.class))).thenReturn(mockedStateFlow); + when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORTWO))).thenReturn(true); + when(toggleService.isUpdateContactDetailsEnabled()).thenReturn(true); + + CaseData caseData = CaseData.builder() + .respondent1(PartyBuilder.builder().individual().build()) + .respondent1Copy(PartyBuilder.builder().individual().build()) + .respondent1DQ(Respondent1DQ.builder() + .respondent1DQExperts(Experts.builder() + .details(wrapElements(Expert.builder().build())).build()) + .build()) + .respondent2(PartyBuilder.builder().individual().build()) + .respondent2Copy(PartyBuilder.builder().individual().build()) + .respondent2DQ(Respondent2DQ.builder().build()) + .claimant1ClaimResponseTypeForSpec(FULL_DEFENCE) + .claimant2ClaimResponseTypeForSpec(FULL_ADMISSION) + .ccdCaseReference(354L) + .respondent1ResponseDate(dateTime).build().toBuilder() + .addApplicant2(YES) + .build(); CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); - when(deadlinesCalculator.calculateApplicantResponseDeadlineSpec(any(), any())) - .thenReturn(LocalDateTime.now()); // When AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler .handle(params); - var objectMapper = new ObjectMapper(); - objectMapper.findAndRegisterModules(); - objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + // Then + assertThat(response.getData().get("respondent1DQExperts")).isNotNull(); + assertThat(response.getData().get("respondent2DQExperts")).isNull(); + + } + + @Test + void shouldUpdateExpertEvents_whenInvokedAndUpdateContactDetailsEnabled_FullAdmission() { + // Given + LocalDateTime dateTime = LocalDateTime.of(2023, 6, 6, 6, 6, 6); + when(userService.getUserInfo(anyString())).thenReturn(UserInfo.builder().uid("uid").build()); + when(mockedStateFlow.isFlagSet(any())).thenReturn(true); + when(stateFlowEngine.evaluate(any(CaseData.class))).thenReturn(mockedStateFlow); + when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORTWO))).thenReturn(true); + when(toggleService.isUpdateContactDetailsEnabled()).thenReturn(true); + + CaseData caseData = CaseData.builder() + .respondent1(PartyBuilder.builder().individual().build()) + .respondent1Copy(PartyBuilder.builder().individual().build()) + .respondent1DQ(Respondent1DQ.builder() + .respondent1DQExperts(Experts.builder() + .details(wrapElements(Expert.builder().build())).build()) + .build()) + .respondent2(PartyBuilder.builder().individual().build()) + .respondent2Copy(PartyBuilder.builder().individual().build()) + .respondent2DQ(Respondent2DQ.builder().build()) + .respondent1ClaimResponseTypeForSpec(RespondentResponseTypeSpec.FULL_ADMISSION) + .respondent2ClaimResponseTypeForSpec(RespondentResponseTypeSpec.FULL_ADMISSION) + .ccdCaseReference(354L) + .respondent1ResponseDate(dateTime).build().toBuilder() + .build(); + + CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); + + // When + AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler + .handle(params); // Then + assertThat(response.getData().get("respondent1DQExperts")).isNotNull(); + assertThat(response.getData().get("respondent2DQExperts")).isNull(); + + } + + @Test + void shouldUpdateExpertEvents_whenInvokedAndUpdateContactDetailsEnabled() { + // Given + LocalDateTime dateTime = LocalDateTime.of(2023, 6, 6, 6, 6, 6); + when(userService.getUserInfo(anyString())).thenReturn(UserInfo.builder().uid("uid").build()); + when(mockedStateFlow.isFlagSet(any())).thenReturn(true); + when(stateFlowEngine.evaluate(any(CaseData.class))).thenReturn(mockedStateFlow); + when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORTWO))).thenReturn(true); + when(toggleService.isUpdateContactDetailsEnabled()).thenReturn(true); + + CaseData caseData = CaseData.builder() + .respondent1(PartyBuilder.builder().individual().build()) + .respondent1Copy(PartyBuilder.builder().individual().build()) + .respondent1DQ(Respondent1DQ.builder() + .respondent1DQExperts(Experts.builder() + .details(wrapElements(Expert.builder().build())).build()) + .build()) + .respondent2(PartyBuilder.builder().individual().build()) + .respondent2Copy(PartyBuilder.builder().individual().build()) + .respondent2DQ(Respondent2DQ.builder().build()) + .respondent1ClaimResponseTypeForSpec(RespondentResponseTypeSpec.FULL_DEFENCE) + .respondent2ClaimResponseTypeForSpec(RespondentResponseTypeSpec.FULL_DEFENCE) + .ccdCaseReference(354L) + .respondent1ResponseDate(dateTime).build().toBuilder() + .build(); - Witnesses actualRespondent1DQWitnesses = objectMapper.convertValue(response.getData().get( - "respondent1DQWitnesses"), new TypeReference<>() { - }); - Witness actualRespondent1Witness = unwrapElements(actualRespondent1DQWitnesses.getDetails()).get(0); - assertThat(actualRespondent1Witness.getPartyID()).isNotNull(); - assertThat(actualRespondent1Witness.getFirstName()).isEqualTo("Witness"); - assertThat(actualRespondent1Witness.getLastName()).isEqualTo("One"); - assertThat(actualRespondent1Witness.getEmailAddress()).isEqualTo("test-witness-one@example.com"); - assertThat(actualRespondent1Witness.getPhoneNumber()).isEqualTo("07865456789"); - assertThat(actualRespondent1Witness.getReasonForWitness()).isEqualTo("great reasons"); - assertThat(actualRespondent1Witness.getEventAdded()).isEqualTo("Defendant Response Event"); - assertThat(actualRespondent1Witness.getDateAdded()).isEqualTo(date); - - Witnesses actualRespondent2DQWitnesses = objectMapper.convertValue(response.getData().get( - "respondent2DQWitnesses"), new TypeReference<>() { - }); - Witness respondent2Witness = unwrapElements(actualRespondent2DQWitnesses.getDetails()).get(0); - assertThat(respondent2Witness.getPartyID()).isNotNull(); - assertThat(respondent2Witness.getFirstName()).isEqualTo("Witness"); - assertThat(respondent2Witness.getLastName()).isEqualTo("Two"); - assertThat(respondent2Witness.getEmailAddress()).isEqualTo("test-witness-two@example.com"); - assertThat(respondent2Witness.getPhoneNumber()).isEqualTo("07532628263"); - assertThat(respondent2Witness.getReasonForWitness()).isEqualTo("good reasons"); - assertThat(respondent2Witness.getEventAdded()).isEqualTo("Defendant Response Event"); - assertThat(respondent2Witness.getDateAdded()).isEqualTo(date); + CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); + + // When + AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler + .handle(params); + + // Then + assertThat(response.getData().get("respondent1DQExperts")).isNotNull(); + assertThat(response.getData().get("respondent2DQExperts")).isNull(); } - @Nested - class HandleLocations { + @Test + void shouldUpdateExpertEvents_whenInvokedAndUpdateContactDetailsEnabled_V2DraftDirections() { + // Given + LocalDateTime dateTime = LocalDateTime.of(2023, 6, 6, 6, 6, 6); + when(userService.getUserInfo(anyString())).thenReturn(UserInfo.builder().uid("uid").build()); + when(mockedStateFlow.isFlagSet(any())).thenReturn(true); + when(stateFlowEngine.evaluate(any(CaseData.class))).thenReturn(mockedStateFlow); + when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORTWO))).thenReturn(true); + when(toggleService.isUpdateContactDetailsEnabled()).thenReturn(true); - @Test - void oneVOne() { - // Given - DynamicList locationValues = DynamicList.fromList(List.of("Value 1")); - DynamicList preferredCourt = DynamicList.builder() - .listItems(locationValues.getListItems()) - .value(locationValues.getListItems().get(0)) - .build(); - Party defendant1 = Party.builder() - .type(Party.Type.COMPANY) - .companyName("company") - .build(); - CaseData caseData = CaseData.builder() - .caseAccessCategory(SPEC_CLAIM) - .ccdCaseReference(354L) - .respondent1(defendant1) - .respondent1Copy(defendant1) - .respondent1DQ( - Respondent1DQ.builder() - .respondToCourtLocation( - RequestedCourt.builder() - .responseCourtLocations(preferredCourt) - .reasonForHearingAtSpecificCourt("Reason") - .build() - ) - .build() - ) - .showConditionFlags(EnumSet.of( - DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_1 - )) - .build(); - CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); + CaseData caseData = CaseData.builder() + .respondent1(PartyBuilder.builder().individual().build()) + .respondent1Copy(PartyBuilder.builder().individual().build()) + .respondent1DQ(Respondent1DQ.builder() + .respondent1DQExperts(Experts.builder() + .details(wrapElements(Expert.builder().build())).build()) + .build()) + .respondent2(PartyBuilder.builder().individual().build()) + .respondent2Copy(PartyBuilder.builder().individual().build()) + .respondent2DQ(Respondent2DQ.builder() + .respondent2DQDraftDirections(Document.builder().build()).build()) + .respondent1ClaimResponseTypeForSpec(RespondentResponseTypeSpec.FULL_DEFENCE) + .respondent2ClaimResponseTypeForSpec(RespondentResponseTypeSpec.FULL_DEFENCE) + .ccdCaseReference(354L) + .respondent1ResponseDate(dateTime).build().toBuilder() + .build(); - List locations = List.of(LocationRefData.builder().build()); - when(locationRefDataService.getCourtLocationsForDefaultJudgments(any())) - .thenReturn(locations); - LocationRefData completePreferredLocation = LocationRefData.builder() - .regionId("regionId") - .epimmsId("epimms") - .courtLocationCode("code") - .build(); - when(courtLocationUtils.findPreferredLocationData( - locations, preferredCourt - )).thenReturn(completePreferredLocation); - StateFlow flow = mock(StateFlow.class); - when(flow.isFlagSet(FlowFlag.TWO_RESPONDENT_REPRESENTATIVES)).thenReturn(false); - when(stateFlowEngine.evaluate(caseData)) - .thenReturn(flow); - when(coreCaseUserService.userHasCaseRole(anyString(), anyString(), any(CaseRole.class))) - .thenReturn(true); - UserInfo userInfo = UserInfo.builder().uid("798").build(); - when(userService.getUserInfo(anyString())).thenReturn(userInfo); + CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); - // When - AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler - .handle(params); + // When + AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler + .handle(params); - // Then - AbstractObjectAssert sent1 = assertThat(response.getData()) - .extracting("respondent1DQRequestedCourt"); - sent1.extracting("caseLocation") - .extracting("region") - .isEqualTo(completePreferredLocation.getRegionId()); - sent1.extracting("caseLocation") - .extracting("baseLocation") - .isEqualTo(completePreferredLocation.getEpimmsId()); - sent1.extracting("responseCourtCode") - .isEqualTo(completePreferredLocation.getCourtLocationCode()); - sent1.extracting("reasonForHearingAtSpecificCourt") - .isEqualTo("Reason"); - } + // Then + assertThat(response.getData().get("respondent1DQExperts")).isNotNull(); + assertThat(response.getData().get("respondent2DQExperts")).isNull(); - @Test - void oneVTwo_SecondDefendantRepliesSameLegalRep() { - // Given - DynamicList locationValues = DynamicList.fromList(List.of("Value 1")); - DynamicList preferredCourt = DynamicList.builder() - .listItems(locationValues.getListItems()) - .value(locationValues.getListItems().get(0)) - .build(); - Party defendant1 = Party.builder() - .type(Party.Type.COMPANY) - .companyName("company") - .build(); - CaseData caseData = CaseData.builder() - .respondent2SameLegalRepresentative(YES) - .caseAccessCategory(SPEC_CLAIM) - .ccdCaseReference(354L) - .defenceAdmitPartPaymentTimeRouteRequired(IMMEDIATELY) - .respondent2ClaimResponseTypeForSpec(FULL_ADMISSION) - .respondent1(defendant1) - .respondent1Copy(defendant1) - .respondent1DQ( - Respondent1DQ.builder() - .respondToCourtLocation( - RequestedCourt.builder() - .responseCourtLocations(preferredCourt) - .reasonForHearingAtSpecificCourt("Reason") - .build() - ) - .build() - ) - .respondent2DQ( - Respondent2DQ.builder() - .respondToCourtLocation2( - RequestedCourt.builder() - .responseCourtLocations(preferredCourt) - .reasonForHearingAtSpecificCourt("Reason123") - .build() - ) - .build() - ) - .showConditionFlags(EnumSet.of( - DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_1, - DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_2 - )) - .build(); + } + + @Test + void shouldUpdateWitnessEvents_whenInvokedAndUpdateContactDetailsEnabled() { + // Given + LocalDateTime dateTime = LocalDateTime.of(2023, 6, 6, 6, 6, 6); + when(userService.getUserInfo(anyString())).thenReturn(UserInfo.builder().uid("uid").build()); + when(mockedStateFlow.isFlagSet(any())).thenReturn(true); + when(stateFlowEngine.evaluate(any(CaseData.class))).thenReturn(mockedStateFlow); + when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORTWO))).thenReturn(true); + when(toggleService.isUpdateContactDetailsEnabled()).thenReturn(true); + + CaseData caseData = CaseData.builder() + .respondent1(PartyBuilder.builder().individual().build()) + .respondent1Copy(PartyBuilder.builder().individual().build()) + .respondent1DQ(Respondent1DQ.builder() + .respondent1DQWitnesses(Witnesses.builder() + .details(wrapElements(Witness.builder().build())).build()) + .build()) + + .respondent2(PartyBuilder.builder().individual().build()) + .respondent2Copy(PartyBuilder.builder().individual().build()) + .respondent2DQ(Respondent2DQ.builder().build()) + .respondent1ClaimResponseTypeForSpec(RespondentResponseTypeSpec.FULL_DEFENCE) + .respondent2ClaimResponseTypeForSpec(RespondentResponseTypeSpec.FULL_DEFENCE) + .ccdCaseReference(354L) + .respondent1ResponseDate(dateTime).build().toBuilder() + .build(); + + CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); + + // When + AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler + .handle(params); + + // Then + assertThat(response.getData().get("respondent1DQWitnesses")).isNotNull(); + assertThat(response.getData().get("respondent2DQWitnesses")).isNull(); + + } + + @Test + void shouldUpdateCorrespondence1_whenProvided() { + // Given + when(userService.getUserInfo(anyString())).thenReturn(UserInfo.builder().uid("uid").build()); + when(mockedStateFlow.isFlagSet(any())).thenReturn(true); + when(stateFlowEngine.evaluate(any(CaseData.class))).thenReturn(mockedStateFlow); + when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORONE))).thenReturn(true); + when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORTWO))).thenReturn(false); + when(toggleService.isCaseFileViewEnabled()).thenReturn(true); + var testDocument = ResponseDocument.builder() + .file(Document.builder().documentUrl("fake-url").documentFileName("file-name").documentBinaryUrl("binary-url").build()).build(); + + CaseData caseData = CaseData.builder() + .respondent1(PartyBuilder.builder().individual().build()) + .respondent1Copy(PartyBuilder.builder().individual().build()) + .respondent1DQ(Respondent1DQ.builder().build()) + .respondent2DQ(Respondent2DQ.builder().build()) + .ccdCaseReference(354L) + .respondent1SpecDefenceResponseDocument(testDocument) + .respondent2SpecDefenceResponseDocument(testDocument) + .isRespondent1(YesOrNo.YES) + .respondentSolicitor1ServiceAddressRequired(YesOrNo.NO) + .respondentSolicitor1ServiceAddress( + Address.builder() + .postCode("new postcode") + .build() + ) + .build(); - List locations = List.of(LocationRefData.builder().build()); - when(locationRefDataService.getCourtLocationsForDefaultJudgments(any())) - .thenReturn(locations); - LocationRefData completePreferredLocation = LocationRefData.builder() - .regionId("regionId") - .epimmsId("epimms") - .courtLocationCode("code") - .build(); - when(courtLocationUtils.findPreferredLocationData( - locations, preferredCourt - )).thenReturn(completePreferredLocation); - StateFlow flow = mock(StateFlow.class); - when(flow.isFlagSet(FlowFlag.TWO_RESPONDENT_REPRESENTATIVES)).thenReturn(true); - when(stateFlowEngine.evaluate(caseData)).thenReturn(flow); - when(coreCaseUserService.userHasCaseRole(anyString(), anyString(), any(CaseRole.class))) - .thenReturn(true); - UserInfo userInfo = UserInfo.builder().uid("798").build(); - when(userService.getUserInfo(anyString())).thenReturn(userInfo); - LocalDate whenWillPay = LocalDate.now().plusDays(5); - given(deadlineExtensionCalculatorService.calculateExtendedDeadline(any(), anyInt())).willReturn(whenWillPay); + CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); - CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); + // When + AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler + .handle(params); - // When - AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); + // Then + assertThat(response.getData().get("specRespondentCorrespondenceAddressdetails")) + .extracting("PostCode") + .isEqualTo("new postcode"); + assertThat(response.getData().get("respondentSolicitor1ServiceAddress")) + .extracting("PostCode") + .isNull(); + } - // Then - AbstractObjectAssert sent2 = assertThat(response.getData()) - .extracting("respondent2DQRequestedCourt"); - sent2.extracting("caseLocation") - .extracting("region") - .isEqualTo(completePreferredLocation.getRegionId()); - sent2.extracting("caseLocation") - .extracting("baseLocation") - .isEqualTo(completePreferredLocation.getEpimmsId()); - sent2.extracting("responseCourtCode") - .isEqualTo(completePreferredLocation.getCourtLocationCode()); - sent2.extracting("reasonForHearingAtSpecificCourt") - .isEqualTo("Reason123"); - } + @Test + void shouldUpdateCorrespondence1_whenProvided1v2ss() { + // Given + when(userService.getUserInfo(anyString())).thenReturn(UserInfo.builder().uid("uid").build()); + when(mockedStateFlow.isFlagSet(any())).thenReturn(true); + when(stateFlowEngine.evaluate(any(CaseData.class))).thenReturn(mockedStateFlow); + when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORONE))).thenReturn(true); + when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORTWO))).thenReturn(false); + when(toggleService.isCaseFileViewEnabled()).thenReturn(true); + var testDocument = ResponseDocument.builder() + .file(Document.builder().documentUrl("fake-url").documentFileName("file-name").documentBinaryUrl("binary-url").build()).build(); - @Test - void oneVTwo_SecondDefendantReplies() { - // Given - DynamicList locationValues = DynamicList.fromList(List.of("Value 1")); - DynamicList preferredCourt = DynamicList.builder() - .listItems(locationValues.getListItems()) - .value(locationValues.getListItems().get(0)) - .build(); - Party defendant1 = Party.builder() - .type(Party.Type.COMPANY) - .companyName("company") - .build(); - CaseData caseData = CaseData.builder() - .caseAccessCategory(SPEC_CLAIM) - .ccdCaseReference(354L) - .respondent1(defendant1) - .respondent1Copy(defendant1) - .respondent1DQ( - Respondent1DQ.builder() - .respondToCourtLocation( - RequestedCourt.builder() - .responseCourtLocations(preferredCourt) - .reasonForHearingAtSpecificCourt("Reason") - .build() - ) - .build() - ) - .respondent2DQ( - Respondent2DQ.builder() - .respondToCourtLocation2( - RequestedCourt.builder() - .responseCourtLocations(preferredCourt) - .reasonForHearingAtSpecificCourt("Reason123") - .build() - ) - .build() - ) - .showConditionFlags(EnumSet.of( - DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_1, - DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_2 - )) - .build(); - CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); + CaseData caseData = CaseData.builder() + .respondent1(PartyBuilder.builder().individual().build()) + .respondent1Copy(PartyBuilder.builder().individual().build()) + .respondent1DQ(Respondent1DQ.builder().build()) + .respondent2DQ(Respondent2DQ.builder().build()) + .ccdCaseReference(354L) + .respondent1SpecDefenceResponseDocument(testDocument) + .respondent2SpecDefenceResponseDocument(testDocument) + .isRespondent1(YesOrNo.YES) + .respondentSolicitor1ServiceAddressRequired(YesOrNo.NO) + .respondentSolicitor1ServiceAddress( + Address.builder() + .postCode("new postcode") + .build() + ) + .respondent2(Party.builder() + .type(Party.Type.COMPANY) + .companyName("Company 3") + .build()) + .respondent2SameLegalRepresentative(YES) + .build(); - List locations = List.of(LocationRefData.builder().build()); - when(locationRefDataService.getCourtLocationsForDefaultJudgments(any())) - .thenReturn(locations); - LocationRefData completePreferredLocation = LocationRefData.builder() - .regionId("regionId") - .epimmsId("epimms") - .courtLocationCode("code") - .build(); - when(courtLocationUtils.findPreferredLocationData( - locations, preferredCourt - )).thenReturn(completePreferredLocation); - StateFlow flow = mock(StateFlow.class); - when(flow.isFlagSet(FlowFlag.TWO_RESPONDENT_REPRESENTATIVES)).thenReturn(true); - when(stateFlowEngine.evaluate(caseData)).thenReturn(flow); - when(coreCaseUserService.userHasCaseRole(anyString(), anyString(), any(CaseRole.class))) - .thenReturn(true); - UserInfo userInfo = UserInfo.builder().uid("798").build(); - when(userService.getUserInfo(anyString())).thenReturn(userInfo); + CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); - // When - AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler - .handle(params); + // When + AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler + .handle(params); - // Then - AbstractObjectAssert sent2 = assertThat(response.getData()) - .extracting("respondent2DQRequestedCourt"); - sent2.extracting("caseLocation") - .extracting("region") - .isEqualTo(completePreferredLocation.getRegionId()); - sent2.extracting("caseLocation") - .extracting("baseLocation") - .isEqualTo(completePreferredLocation.getEpimmsId()); - sent2.extracting("responseCourtCode") - .isEqualTo(completePreferredLocation.getCourtLocationCode()); - sent2.extracting("reasonForHearingAtSpecificCourt") - .isEqualTo("Reason123"); - } + // Then + assertThat(response.getData().get("specRespondentCorrespondenceAddressdetails")) + .extracting("PostCode") + .isEqualTo("new postcode"); + assertThat(response.getData().get("respondentSolicitor1ServiceAddress")) + .extracting("PostCode") + .isNull(); + assertEquals( + response.getData().get("specRespondentCorrespondenceAddressdetails"), + response.getData().get("specRespondent2CorrespondenceAddressdetails") + ); + assertEquals( + response.getData().get("specRespondentCorrespondenceAddressRequired"), + response.getData().get("specRespondent2CorrespondenceAddressRequired") + ); } @Test - void shouldNullDocuments_whenInvokedAndCaseFileEnabled() { + void shouldUpdateCorrespondence1_whenProvided1v2ss_withSameResponse() { // Given when(userService.getUserInfo(anyString())).thenReturn(UserInfo.builder().uid("uid").build()); when(mockedStateFlow.isFlagSet(any())).thenReturn(true); when(stateFlowEngine.evaluate(any(CaseData.class))).thenReturn(mockedStateFlow); - when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORTWO))).thenReturn(true); + when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORONE))).thenReturn(true); + when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORTWO))).thenReturn(false); when(toggleService.isCaseFileViewEnabled()).thenReturn(true); var testDocument = ResponseDocument.builder() - .file(Document.builder().documentUrl("fake-url").documentFileName("file-name").documentBinaryUrl( - "binary-url").build()).build(); + .file(Document.builder().documentUrl("fake-url").documentFileName("file-name").documentBinaryUrl("binary-url").build()).build(); CaseData caseData = CaseData.builder() .respondent1(PartyBuilder.builder().individual().build()) @@ -1231,6 +1598,19 @@ void shouldNullDocuments_whenInvokedAndCaseFileEnabled() { .ccdCaseReference(354L) .respondent1SpecDefenceResponseDocument(testDocument) .respondent2SpecDefenceResponseDocument(testDocument) + .isRespondent1(YesOrNo.YES) + .respondentResponseIsSame(YES) + .respondentSolicitor1ServiceAddressRequired(YesOrNo.NO) + .respondentSolicitor1ServiceAddress( + Address.builder() + .postCode("new postcode") + .build() + ) + .respondent2(Party.builder() + .type(Party.Type.COMPANY) + .companyName("Company 3") + .build()) + .respondent2SameLegalRepresentative(YES) .build(); CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); @@ -1240,12 +1620,24 @@ void shouldNullDocuments_whenInvokedAndCaseFileEnabled() { .handle(params); // Then - assertThat(response.getData().get("respondent1SpecDefenceResponseDocument")).isNull(); - assertThat(response.getData().get("respondent2SpecDefenceResponseDocument")).isNull(); + assertThat(response.getData().get("specRespondentCorrespondenceAddressdetails")) + .extracting("PostCode") + .isEqualTo("new postcode"); + assertThat(response.getData().get("respondentSolicitor1ServiceAddress")) + .extracting("PostCode") + .isNull(); + assertEquals( + response.getData().get("specRespondentCorrespondenceAddressdetails"), + response.getData().get("specRespondent2CorrespondenceAddressdetails") + ); + assertEquals( + response.getData().get("specRespondentCorrespondenceAddressRequired"), + response.getData().get("specRespondent2CorrespondenceAddressRequired") + ); } @Test - void shouldUpdateCorrespondence1_whenProvided() { + void shouldUpdateCorrespondence1_whenProvided1v2ss_withSameResponse_withv2copy() { // Given when(userService.getUserInfo(anyString())).thenReturn(UserInfo.builder().uid("uid").build()); when(mockedStateFlow.isFlagSet(any())).thenReturn(true); @@ -1254,8 +1646,7 @@ void shouldUpdateCorrespondence1_whenProvided() { when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORTWO))).thenReturn(false); when(toggleService.isCaseFileViewEnabled()).thenReturn(true); var testDocument = ResponseDocument.builder() - .file(Document.builder().documentUrl("fake-url").documentFileName("file-name").documentBinaryUrl( - "binary-url").build()).build(); + .file(Document.builder().documentUrl("fake-url").documentFileName("file-name").documentBinaryUrl("binary-url").build()).build(); CaseData caseData = CaseData.builder() .respondent1(PartyBuilder.builder().individual().build()) @@ -1266,12 +1657,19 @@ void shouldUpdateCorrespondence1_whenProvided() { .respondent1SpecDefenceResponseDocument(testDocument) .respondent2SpecDefenceResponseDocument(testDocument) .isRespondent1(YesOrNo.YES) - .specAoSRespondentCorrespondenceAddressRequired(YesOrNo.NO) - .specAoSRespondentCorrespondenceAddressdetails( + .respondentResponseIsSame(YES) + .respondentSolicitor1ServiceAddressRequired(YesOrNo.NO) + .respondentSolicitor1ServiceAddress( Address.builder() .postCode("new postcode") .build() ) + .respondent2(Party.builder() + .type(Party.Type.COMPANY) + .companyName("Company 3") + .build()) + .respondent2Copy(PartyBuilder.builder().individual().build()) + .respondent2SameLegalRepresentative(YES) .build(); CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); @@ -1284,13 +1682,21 @@ void shouldUpdateCorrespondence1_whenProvided() { assertThat(response.getData().get("specRespondentCorrespondenceAddressdetails")) .extracting("PostCode") .isEqualTo("new postcode"); - assertThat(response.getData().get("specAoSRespondentCorrespondenceAddressdetails")) + assertThat(response.getData().get("respondentSolicitor1ServiceAddress")) .extracting("PostCode") .isNull(); + assertEquals( + response.getData().get("specRespondentCorrespondenceAddressdetails"), + response.getData().get("specRespondent2CorrespondenceAddressdetails") + ); + assertEquals( + response.getData().get("specRespondentCorrespondenceAddressRequired"), + response.getData().get("specRespondent2CorrespondenceAddressRequired") + ); } @Test - void shouldUpdateCorrespondence1_whenProvided1v2ss() { + void shouldUpdateCorrespondence1_whenProvided1v2ss_withSameResponse_withv2copyAndNoTempAdr() { // Given when(userService.getUserInfo(anyString())).thenReturn(UserInfo.builder().uid("uid").build()); when(mockedStateFlow.isFlagSet(any())).thenReturn(true); @@ -1299,8 +1705,7 @@ void shouldUpdateCorrespondence1_whenProvided1v2ss() { when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORTWO))).thenReturn(false); when(toggleService.isCaseFileViewEnabled()).thenReturn(true); var testDocument = ResponseDocument.builder() - .file(Document.builder().documentUrl("fake-url").documentFileName("file-name").documentBinaryUrl( - "binary-url").build()).build(); + .file(Document.builder().documentUrl("fake-url").documentFileName("file-name").documentBinaryUrl("binary-url").build()).build(); CaseData caseData = CaseData.builder() .respondent1(PartyBuilder.builder().individual().build()) @@ -1311,8 +1716,9 @@ void shouldUpdateCorrespondence1_whenProvided1v2ss() { .respondent1SpecDefenceResponseDocument(testDocument) .respondent2SpecDefenceResponseDocument(testDocument) .isRespondent1(YesOrNo.YES) - .specAoSRespondentCorrespondenceAddressRequired(YesOrNo.NO) - .specAoSRespondentCorrespondenceAddressdetails( + .respondentResponseIsSame(YES) + .respondentSolicitor1ServiceAddressRequired(YesOrNo.NO) + .respondentSolicitor1ServiceAddress( Address.builder() .postCode("new postcode") .build() @@ -1321,7 +1727,9 @@ void shouldUpdateCorrespondence1_whenProvided1v2ss() { .type(Party.Type.COMPANY) .companyName("Company 3") .build()) + .respondent2Copy(PartyBuilder.builder().individual().build()) .respondent2SameLegalRepresentative(YES) + .tempAddress2Required(NO) .build(); CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); @@ -1334,7 +1742,7 @@ void shouldUpdateCorrespondence1_whenProvided1v2ss() { assertThat(response.getData().get("specRespondentCorrespondenceAddressdetails")) .extracting("PostCode") .isEqualTo("new postcode"); - assertThat(response.getData().get("specAoSRespondentCorrespondenceAddressdetails")) + assertThat(response.getData().get("respondentSolicitor1ServiceAddress")) .extracting("PostCode") .isNull(); assertEquals( @@ -1356,20 +1764,21 @@ void shouldUpdateCorrespondence2_whenProvided() { when(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORTWO))).thenReturn(true); when(toggleService.isCaseFileViewEnabled()).thenReturn(true); var testDocument = ResponseDocument.builder() - .file(Document.builder().documentUrl("fake-url").documentFileName("file-name").documentBinaryUrl( - "binary-url").build()).build(); + .file(Document.builder().documentUrl("fake-url").documentFileName("file-name").documentBinaryUrl("binary-url").build()).build(); CaseData caseData = CaseData.builder() .respondent1(PartyBuilder.builder().individual().build()) .respondent1Copy(PartyBuilder.builder().individual().build()) .respondent1DQ(Respondent1DQ.builder().build()) + .respondent2(PartyBuilder.builder().individual().build()) + .respondent2Copy(PartyBuilder.builder().individual().build()) .respondent2DQ(Respondent2DQ.builder().build()) .ccdCaseReference(354L) .respondent1SpecDefenceResponseDocument(testDocument) .respondent2SpecDefenceResponseDocument(testDocument) .isRespondent2(YesOrNo.YES) - .specAoSRespondent2CorrespondenceAddressRequired(YesOrNo.NO) - .specAoSRespondent2CorrespondenceAddressdetails( + .respondentSolicitor2ServiceAddressRequired(YesOrNo.NO) + .respondentSolicitor2ServiceAddress( Address.builder() .postCode("new postcode") .build() @@ -1386,7 +1795,7 @@ void shouldUpdateCorrespondence2_whenProvided() { assertThat(response.getData().get("specRespondent2CorrespondenceAddressdetails")) .extracting("PostCode") .isEqualTo("new postcode"); - assertThat(response.getData().get("specAoSRespondent2CorrespondenceAddressdetails")) + assertThat(response.getData().get("respondentSolicitor2ServiceAddress")) .extracting("PostCode") .isNull(); } @@ -1416,6 +1825,58 @@ void shouldPopulateRespondent2Flag_WhenInvoked() { assertThat(response.getData().get("respondent2DocumentGeneration")).isEqualTo("userRespondent2"); } + @Test + void shouldPopulateRespondent2Flag_WhenInvokedWithSmallClaimExperts_1DQ() { + // Given + when(toggleService.isCaseFileViewEnabled()).thenReturn(true); + when(userService.getUserInfo(anyString())).thenReturn(UserInfo.builder().uid("uid").build()); + when(stateFlowEngine.evaluate(any(CaseData.class))).thenReturn(mockedStateFlow); + given(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORTWO))).willReturn(true); + given(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORONE))).willReturn(false); + CaseData caseData = CaseDataBuilder.builder() + .atStateClaimDetailsNotified() + .respondent2(PartyBuilder.builder().individual().build()) + .addRespondent2(YES) + .respondent1(PartyBuilder.builder().individual().build()) + .respondent1Copy(PartyBuilder.builder().individual().build()) + .respondent1DQ(Respondent1DQ.builder() + .respondToClaimExperts(ExpertDetails.builder().build()).build()) + .respondent2DQ(Respondent2DQ.builder().build()) + .build(); + CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); + // When + AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler + .handle(params); + // Given + assertThat(response.getData().get("respondent2DocumentGeneration")).isEqualTo("userRespondent2"); + } + + @Test + void shouldPopulateRespondent2Flag_WhenInvokedWithSmallClaimExperts_2DQ() { + // Given + when(toggleService.isCaseFileViewEnabled()).thenReturn(true); + when(userService.getUserInfo(anyString())).thenReturn(UserInfo.builder().uid("uid").build()); + when(stateFlowEngine.evaluate(any(CaseData.class))).thenReturn(mockedStateFlow); + given(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORTWO))).willReturn(true); + given(coreCaseUserService.userHasCaseRole(any(), any(), eq(RESPONDENTSOLICITORONE))).willReturn(false); + CaseData caseData = CaseDataBuilder.builder() + .atStateClaimDetailsNotified() + .respondent2(PartyBuilder.builder().individual().build()) + .addRespondent2(YES) + .respondent1(PartyBuilder.builder().individual().build()) + .respondent1Copy(PartyBuilder.builder().individual().build()) + .respondent2DQ(Respondent2DQ.builder() + .respondToClaimExperts2(ExpertDetails.builder().build()).build()) + .respondent1DQ(Respondent1DQ.builder().build()) + .build(); + CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); + // When + AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler + .handle(params); + // Given + assertThat(response.getData().get("respondent2DocumentGeneration")).isEqualTo("userRespondent2"); + } + @Test void shouldNotPopulateRespondent2Flag_WhenInvoked() { // Given @@ -1478,6 +1939,26 @@ void shouldSetMultiPartyResponseTypeFlags_Counter_Admit_OR_Admit_Part_combinatio .isEqualTo("COUNTER_ADMIT_OR_ADMIT_PART"); } + @Test + void shouldSetMultiPartyResponseTypeFlags_Counter_Admit_OR_Admit_Part_combination2_CanAddApplicant2() { + // Given + CaseData caseData = CaseDataBuilder.builder().atStateRespondent2v1BothNotFullDefence_CounterClaimX2() + .addApplicant2(YES) + .respondent1ClaimResponseTypeForSpec(FULL_ADMISSION) + .respondent1ClaimResponseTypeForSpec(FULL_ADMISSION) + .build(); + + CallbackParams params = callbackParamsOf(caseData, MID, PAGE_ID); + + // When + var response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); + + // Then + assertThat(response.getData()).extracting("multiPartyResponseTypeFlags") + .isEqualTo("COUNTER_ADMIT_OR_ADMIT_PART"); + } + + /** * if solicitor says that each defendant gets their response but then chooses the same * option from full defence/part admit/full admit/counterclaim, then it is not different response. @@ -1568,7 +2049,6 @@ void shouldReturnError_whenWitnessRequiredAndNullDetails() { void shouldReturnNoError_whenWitnessRequiredAndDetailsProvided() { // Given List> testWitness = wrapElements(Witness.builder().name("test witness").build()); - Witnesses witnesses = Witnesses.builder().witnessesToAppear(YES).details(testWitness).build(); CaseData caseData = CaseDataBuilder.builder() .respondent1DQ(Respondent1DQ.builder().build()) .respondent1DQWitnessesRequiredSpec(YES) @@ -1657,9 +2137,6 @@ void specificSummary_whenPartialAdmitNotPay() { // When SubmittedCallbackResponse response = (SubmittedCallbackResponse) handler.handle(params); - LocalDateTime responseDeadline = caseData.getApplicant1ResponseDeadline(); - String claimNumber = caseData.getLegacyCaseReference(); - // Then assertThat(response.getConfirmationBody()) .contains(caseData.getApplicant1().getPartyName()) @@ -2067,12 +2544,12 @@ void whenProvided_thenValidateCorrespondence1() { CaseData caseData = CaseDataBuilder.builder().atStateClaimDetailsNotified().build() .toBuilder() .isRespondent1(YES) - .specAoSRespondentCorrespondenceAddressRequired(YesOrNo.NO) - .specAoSRespondentCorrespondenceAddressdetails(Address.builder() + .respondentSolicitor1ServiceAddressRequired(YesOrNo.NO) + .respondentSolicitor1ServiceAddress(Address.builder() .postCode("postal code") .build()) .build(); - CallbackParams params = callbackParamsOf(caseData, MID, "confirm-details"); + CallbackParams params = callbackParamsOf(caseData, MID, "specCorrespondenceAddress"); when(postcodeValidator.validate("postal code")).thenReturn(Collections.emptyList()); // When @@ -2089,12 +2566,12 @@ void whenProvided_thenValidateCorrespondence2() { CaseData caseData = CaseDataBuilder.builder().atStateClaimDetailsNotified().build() .toBuilder() .isRespondent2(YES) - .specAoSRespondent2CorrespondenceAddressRequired(YesOrNo.NO) - .specAoSRespondent2CorrespondenceAddressdetails(Address.builder() - .postCode("postal code") - .build()) + .respondentSolicitor2ServiceAddressRequired(YesOrNo.NO) + .respondentSolicitor2ServiceAddress(Address.builder() + .postCode("postal code") + .build()) .build(); - CallbackParams params = callbackParamsOf(caseData, MID, "confirm-details"); + CallbackParams params = callbackParamsOf(caseData, MID, "specCorrespondenceAddress"); when(postcodeValidator.validate("postal code")).thenReturn(Collections.emptyList()); // When @@ -2324,10 +2801,55 @@ public void shouldThrowError_whenValidateRespondentExpertsMultipartyWithNoUnavai // Then assertThat(response.getErrors()).isNotEmpty(); } + + @Test + public void shouldThrowError_whenValidateRespondentExpertsMultipartyWithNoUnavailableDates_DisputesTheClaim() { + // Given + CaseData caseData = CaseDataBuilder.builder().atStateClaimDetailsNotified() + .responseClaimTrack(SpecJourneyConstantLRSpec.DISPUTES_THE_CLAIM) + .respondent1DQ(Respondent1DQ.builder() + .respondent1DQHearingSmallClaim(SmallClaimHearing.builder().unavailableDatesRequired( + YES).build()).build()) + .build(); + List errors = Collections.singletonList("error 1"); + Mockito.when(dateValidator.validateFastClaimHearing(any())).thenReturn(errors); + CallbackParams params = callbackParamsOf(caseData, MID, "validate-unavailable-dates"); + // When + AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler + .handle(params); + + // Then + assertThat(response.getErrors()).isNotEmpty(); + } + + @Test + public void shouldThrowError_whenValidateRespondentExpertsMultipartyWithNoUnavailableDates_V2() { + // Given + CaseData caseData = CaseDataBuilder.builder().atStateClaimDetailsNotified() + .responseClaimTrack(SpecJourneyConstantLRSpec.SMALL_CLAIM) + .respondent1DQ(Respondent1DQ.builder() + .respondent1DQHearingSmallClaim(SmallClaimHearing.builder().unavailableDatesRequired( + YES).build()).build()) + .respondent2DQ(Respondent2DQ.builder() + .respondent2DQHearingSmallClaim(SmallClaimHearing.builder().unavailableDatesRequired( + YES).build()).build()) + .isRespondent2(YES) + .build(); + List errors = Collections.singletonList("error 1"); + Mockito.when(dateValidator.validateSmallClaimsHearing(any())).thenReturn(errors); + CallbackParams params = callbackParamsOf(caseData, MID, "validate-unavailable-dates"); + // When + AboutToStartOrSubmitCallbackResponse response = (AboutToStartOrSubmitCallbackResponse) handler + .handle(params); + + // Then + assertThat(response.getErrors()).isNotEmpty(); + } } @Test void handleEventsReturnsTheExpectedCallbackEvents() { assertThat(handler.handledEvents()).containsOnly(DEFENDANT_RESPONSE_SPEC); } + }