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 5c2f5409f26..c3f2ac5355c 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 @@ -14,35 +14,28 @@ import uk.gov.hmcts.reform.civil.constants.SpecJourneyConstantLRSpec; import uk.gov.hmcts.reform.civil.documentmanagement.model.CaseDocument; import uk.gov.hmcts.reform.civil.documentmanagement.model.DocumentType; +import uk.gov.hmcts.reform.civil.enums.AllocatedTrack; import uk.gov.hmcts.reform.civil.enums.CaseRole; import uk.gov.hmcts.reform.civil.enums.CaseState; import uk.gov.hmcts.reform.civil.enums.DocCategory; +import uk.gov.hmcts.reform.civil.enums.MultiPartyResponseTypeFlags; +import uk.gov.hmcts.reform.civil.enums.MultiPartyScenario; import uk.gov.hmcts.reform.civil.enums.RespondentResponsePartAdmissionPaymentTimeLRspec; import uk.gov.hmcts.reform.civil.enums.RespondentResponseTypeSpec; +import uk.gov.hmcts.reform.civil.enums.RespondentResponseTypeSpecPaidStatus; +import uk.gov.hmcts.reform.civil.enums.TimelineUploadTypeSpec; import uk.gov.hmcts.reform.civil.enums.YesOrNo; -import uk.gov.hmcts.reform.civil.handler.callback.user.respondtoclaimspeccallbackhandlertaskstests.DetermineLoggedInSolicitor; -import uk.gov.hmcts.reform.civil.handler.callback.user.respondtoclaimspeccallbackhandlertaskstests.HandleAdmitPartOfClaim; -import uk.gov.hmcts.reform.civil.handler.callback.user.respondtoclaimspeccallbackhandlertaskstests.HandleDefendAllClaim; -import uk.gov.hmcts.reform.civil.handler.callback.user.respondtoclaimspeccallbackhandlertaskstests.HandleRespondentResponseTypeForSpec; -import uk.gov.hmcts.reform.civil.handler.callback.user.respondtoclaimspeccallbackhandlertaskstests.PopulateRespondent1Copy; -import uk.gov.hmcts.reform.civil.handler.callback.user.respondtoclaimspeccallbackhandlertaskstests.SetGenericResponseTypeFlag; -import uk.gov.hmcts.reform.civil.handler.callback.user.respondtoclaimspeccallbackhandlertaskstests.SetUploadTimelineTypeFlag; -import uk.gov.hmcts.reform.civil.handler.callback.user.respondtoclaimspeccallbackhandlertaskstests.ValidateDateOfBirth; -import uk.gov.hmcts.reform.civil.handler.callback.user.respondtoclaimspeccallbackhandlertaskstests.ValidateLengthOfUnemployment; -import uk.gov.hmcts.reform.civil.handler.callback.user.respondtoclaimspeccallbackhandlertaskstests.ValidateMediationUnavailableDates; -import uk.gov.hmcts.reform.civil.handler.callback.user.respondtoclaimspeccallbackhandlertaskstests.ValidateRespondentExperts; -import uk.gov.hmcts.reform.civil.handler.callback.user.respondtoclaimspeccallbackhandlertaskstests.ValidateRespondentPaymentDate; -import uk.gov.hmcts.reform.civil.handler.callback.user.respondtoclaimspeccallbackhandlertaskstests.ValidateRespondentWitnesses; -import uk.gov.hmcts.reform.civil.handler.callback.user.respondtoclaimspeccallbackhandlertaskstests.ValidateUnavailableDates; import uk.gov.hmcts.reform.civil.handler.callback.user.spec.CaseDataToTextGenerator; import uk.gov.hmcts.reform.civil.handler.callback.user.spec.RespondToClaimConfirmationHeaderSpecGenerator; import uk.gov.hmcts.reform.civil.handler.callback.user.spec.RespondToClaimConfirmationTextSpecGenerator; +import uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag; import uk.gov.hmcts.reform.civil.helpers.LocationHelper; import uk.gov.hmcts.reform.civil.model.Address; import uk.gov.hmcts.reform.civil.model.BusinessProcess; import uk.gov.hmcts.reform.civil.model.CaseData; import uk.gov.hmcts.reform.civil.model.Party; import uk.gov.hmcts.reform.civil.model.RepaymentPlanLRspec; +import uk.gov.hmcts.reform.civil.model.RespondToClaim; import uk.gov.hmcts.reform.civil.model.RespondToClaimAdmitPartLRspec; import uk.gov.hmcts.reform.civil.model.ResponseDocument; import uk.gov.hmcts.reform.civil.model.StatementOfTruth; @@ -50,9 +43,11 @@ import uk.gov.hmcts.reform.civil.model.common.Element; 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.Hearing; 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.Witnesses; import uk.gov.hmcts.reform.civil.referencedata.model.LocationRefData; import uk.gov.hmcts.reform.civil.service.CoreCaseUserService; @@ -69,7 +64,10 @@ import uk.gov.hmcts.reform.civil.utils.DQResponseDocumentUtils; import uk.gov.hmcts.reform.civil.utils.ElementUtils; import uk.gov.hmcts.reform.civil.utils.FrcDocumentsUtils; +import uk.gov.hmcts.reform.civil.utils.MonetaryConversions; import uk.gov.hmcts.reform.civil.utils.UnavailabilityDatesUtils; +import uk.gov.hmcts.reform.civil.validation.DateOfBirthValidator; +import uk.gov.hmcts.reform.civil.validation.PaymentDateValidator; import uk.gov.hmcts.reform.civil.validation.PostcodeValidator; import uk.gov.hmcts.reform.civil.validation.UnavailableDateValidator; import uk.gov.hmcts.reform.civil.validation.interfaces.DefendantAddressValidator; @@ -77,14 +75,18 @@ import uk.gov.hmcts.reform.civil.validation.interfaces.WitnessesValidator; import uk.gov.hmcts.reform.idam.client.models.UserInfo; +import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collections; +import java.util.EnumSet; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.Set; import static java.lang.String.format; import static java.util.Objects.nonNull; @@ -95,17 +97,42 @@ import static uk.gov.hmcts.reform.civil.callback.CallbackType.MID; import static uk.gov.hmcts.reform.civil.callback.CallbackType.SUBMITTED; import static uk.gov.hmcts.reform.civil.callback.CaseEvent.DEFENDANT_RESPONSE_SPEC; +import static uk.gov.hmcts.reform.civil.constants.SpecJourneyConstantLRSpec.DISPUTES_THE_CLAIM; +import static uk.gov.hmcts.reform.civil.enums.CaseRole.APPLICANTSOLICITORONE; import static uk.gov.hmcts.reform.civil.enums.CaseRole.RESPONDENTSOLICITORONE; import static uk.gov.hmcts.reform.civil.enums.CaseRole.RESPONDENTSOLICITORTWO; +import static uk.gov.hmcts.reform.civil.enums.MultiPartyScenario.ONE_V_ONE; import static uk.gov.hmcts.reform.civil.enums.MultiPartyScenario.ONE_V_TWO_ONE_LEGAL_REP; import static uk.gov.hmcts.reform.civil.enums.MultiPartyScenario.ONE_V_TWO_TWO_LEGAL_REP; import static uk.gov.hmcts.reform.civil.enums.MultiPartyScenario.TWO_V_ONE; import static uk.gov.hmcts.reform.civil.enums.MultiPartyScenario.getMultiPartyScenario; import static uk.gov.hmcts.reform.civil.enums.RespondentResponsePartAdmissionPaymentTimeLRspec.IMMEDIATELY; +import static uk.gov.hmcts.reform.civil.enums.RespondentResponsePartAdmissionPaymentTimeLRspec.SUGGESTION_OF_REPAYMENT_PLAN; +import static uk.gov.hmcts.reform.civil.enums.RespondentResponseTypeSpec.COUNTER_CLAIM; +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.RespondentResponseTypeSpec.PART_ADMISSION; 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.handler.callback.user.spec.show.DefendantResponseShowTag.BOTH_RESPONDENTS_DISPUTE; +import static uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_1; +import static uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_2; +import static uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag.CURRENT_ADMITS_PART_OR_FULL; +import static uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag.NEED_FINANCIAL_DETAILS_1; +import static uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag.NEED_FINANCIAL_DETAILS_2; +import static uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag.ONLY_RESPONDENT_1_DISPUTES; +import static uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag.ONLY_RESPONDENT_2_DISPUTES; +import static uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag.REPAYMENT_PLAN_2; +import static uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag.RESPONDENT_1_ADMITS_PART_OR_FULL; +import static uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag.RESPONDENT_1_PAID_LESS; +import static uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag.RESPONDENT_2_ADMITS_PART_OR_FULL; +import static uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag.RESPONDENT_2_PAID_LESS; +import static uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag.SOMEONE_DISPUTES; +import static uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag.TIMELINE_MANUALLY; +import static uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag.TIMELINE_UPLOAD; +import static uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag.WHEN_WILL_CLAIM_BE_PAID; +import static uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag.WHY_1_DOES_NOT_PAY_IMMEDIATELY; +import static uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.DefendantResponseShowTag.WHY_2_DOES_NOT_PAY_IMMEDIATELY; import static uk.gov.hmcts.reform.civil.helpers.DateFormatHelper.DATE; import static uk.gov.hmcts.reform.civil.helpers.DateFormatHelper.formatLocalDateTime; import static uk.gov.hmcts.reform.civil.model.dq.Expert.fromSmallClaimExpertDetails; @@ -113,6 +140,7 @@ import static uk.gov.hmcts.reform.civil.utils.ElementUtils.buildElemCaseDocument; import static uk.gov.hmcts.reform.civil.utils.ElementUtils.wrapElements; import static uk.gov.hmcts.reform.civil.utils.ExpertUtils.addEventAndDateAddedToRespondentExperts; +import static uk.gov.hmcts.reform.civil.utils.MediationUnavailableDatesUtils.checkUnavailable; import static uk.gov.hmcts.reform.civil.utils.PartyUtils.populateDQPartyIds; import static uk.gov.hmcts.reform.civil.utils.WitnessUtils.addEventAndDateAddedToRespondentWitnesses; @@ -124,11 +152,13 @@ public class RespondToClaimSpecCallbackHandler extends CallbackHandler private static final List EVENTS = Collections.singletonList(DEFENDANT_RESPONSE_SPEC); private static final String DEF2 = "Defendant 2"; + private final DateOfBirthValidator dateOfBirthValidator; private final UnavailableDateValidator unavailableDateValidator; private final ObjectMapper objectMapper; private final Time time; private final DeadlinesCalculator deadlinesCalculator; private final PostcodeValidator postcodeValidator; + private final PaymentDateValidator paymentDateValidator; private final List confirmationTextSpecGenerators; private final List confirmationHeaderGenerators; private final FeatureToggleService toggleService; @@ -142,20 +172,6 @@ public class RespondToClaimSpecCallbackHandler extends CallbackHandler private final DeadlineExtensionCalculatorService deadlineCalculatorService; private final FrcDocumentsUtils frcDocumentsUtils; private final DQResponseDocumentUtils dqResponseDocumentUtils; - private final ValidateMediationUnavailableDates validateMediationUnavailableDates; - private final HandleDefendAllClaim handleDefendAllClaim; - private final HandleAdmitPartOfClaim handleAdmitPartOfClaim; - private final HandleRespondentResponseTypeForSpec handleRespondentResponseTypeForSpec; - private final SetGenericResponseTypeFlag setGenericResponseTypeFlag; - private final SetUploadTimelineTypeFlag setUploadTimelineTypeFlag; - private final DetermineLoggedInSolicitor determineLoggedInSolicitor; - private final PopulateRespondent1Copy populateRespondent1Copy; - private final ValidateRespondentWitnesses validateRespondentWitnesses; - private final ValidateRespondentExperts validateRespondentExperts; - private final ValidateUnavailableDates validateUnavailableDates; - private final ValidateDateOfBirth validateDateOfBirth; - private final ValidateRespondentPaymentDate validateRespondentPaymentDate; - private final ValidateLengthOfUnemployment validateLengthOfUnemployment; @Override public List handledEvents() { @@ -190,27 +206,869 @@ protected Map callbacks() { } private CallbackResponse validateMediationUnavailableDates(CallbackParams callbackParams) { - return validateMediationUnavailableDates.execute(callbackParams); + CaseData caseData = callbackParams.getCaseData(); + List errors = new ArrayList<>(); + if ((caseData.getResp1MediationAvailability() != null + && YES.equals(caseData.getResp1MediationAvailability().getIsMediationUnavailablityExists()))) { + checkUnavailable(errors, caseData.getResp1MediationAvailability().getUnavailableDatesForMediation()); + } else if (caseData.getResp2MediationAvailability() != null + && YES.equals(caseData.getResp2MediationAvailability().getIsMediationUnavailablityExists())) { + checkUnavailable(errors, caseData.getResp2MediationAvailability().getUnavailableDatesForMediation()); + } + + return AboutToStartOrSubmitCallbackResponse.builder() + .errors(errors) + .build(); } private CallbackResponse handleDefendAllClaim(CallbackParams callbackParams) { - return handleDefendAllClaim.execute(callbackParams); + CaseData caseData = callbackParams.getCaseData(); + List errors = paymentDateValidator.validate(Optional.ofNullable(caseData.getRespondToClaim()) + .orElseGet(() -> RespondToClaim.builder().build())); + if (!errors.isEmpty()) { + return AboutToStartOrSubmitCallbackResponse.builder() + .errors(errors) + .build(); + } + CaseData.CaseDataBuilder updatedCase = caseData.toBuilder(); + updatedCase.showConditionFlags(whoDisputesFullDefence(caseData)); + if (SpecJourneyConstantLRSpec.DEFENDANT_RESPONSE_SPEC.equals(callbackParams.getRequest().getEventId())) { + populateRespondentResponseTypeSpecPaidStatus(caseData, updatedCase); + if (caseData.getRespondent1ClaimResponsePaymentAdmissionForSpec() + == RespondentResponseTypeSpecPaidStatus.PAID_LESS_THAN_CLAIMED_AMOUNT + || DISPUTES_THE_CLAIM.equals(caseData.getDefenceRouteRequired()) + || DISPUTES_THE_CLAIM.equals(caseData.getDefenceRouteRequired2()) + || caseData.getRespondent1ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.PART_ADMISSION + || caseData.getRespondent2ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.PART_ADMISSION) { + updatedCase.specPaidLessAmountOrDisputesOrPartAdmission(YES); + } else { + updatedCase.specPaidLessAmountOrDisputesOrPartAdmission(NO); + } + if (YES.equals(caseData.getIsRespondent2())) { + if (RespondentResponseTypeSpecPaidStatus.PAID_LESS_THAN_CLAIMED_AMOUNT + != caseData.getRespondent1ClaimResponsePaymentAdmissionForSpec() + && (DISPUTES_THE_CLAIM.equals(caseData.getDefenceRouteRequired2()) + || caseData.getRespondent2ClaimResponseTypeForSpec() + == RespondentResponseTypeSpec.PART_ADMISSION)) { + updatedCase.specDisputesOrPartAdmission(YES); + } else { + updatedCase.specDisputesOrPartAdmission(NO); + } + } else { + if (RespondentResponseTypeSpecPaidStatus.PAID_LESS_THAN_CLAIMED_AMOUNT + != caseData.getRespondent1ClaimResponsePaymentAdmissionForSpec() + && (DISPUTES_THE_CLAIM.equals(caseData.getDefenceRouteRequired()) + || caseData.getRespondent1ClaimResponseTypeForSpec() + == RespondentResponseTypeSpec.PART_ADMISSION)) { + updatedCase.specDisputesOrPartAdmission(YES); + } else { + updatedCase.specDisputesOrPartAdmission(NO); + } + } + AllocatedTrack allocatedTrack = getAllocatedTrack(caseData); + updatedCase.responseClaimTrack(allocatedTrack.name()); + } + return AboutToStartOrSubmitCallbackResponse.builder() + .data(updatedCase.build().toMap(objectMapper)) + .build(); } + // called on full_admit, also called after whenWillClaimBePaid private CallbackResponse handleAdmitPartOfClaim(CallbackParams callbackParams) { - return handleAdmitPartOfClaim.execute(callbackParams); + CaseData caseData = callbackParams.getCaseData(); + List errors = paymentDateValidator.validate(Optional.ofNullable(caseData.getRespondToAdmittedClaim()) + .orElseGet(() -> RespondToClaim.builder().build())); + if (!errors.isEmpty()) { + return AboutToStartOrSubmitCallbackResponse.builder() + .errors(errors) + .build(); + } + CaseData.CaseDataBuilder updatedCaseData = caseData.toBuilder(); + + if (YES.equals(caseData.getIsRespondent2()) && YES.equals(caseData.getSpecDefenceFullAdmitted2Required())) { + updatedCaseData.fullAdmissionAndFullAmountPaid(YES); + } else if (YES.equals(caseData.getIsRespondent1()) + && YES.equals(caseData.getSpecDefenceFullAdmittedRequired())) { + updatedCaseData.fullAdmissionAndFullAmountPaid(YES); + } else { + updatedCaseData.fullAdmissionAndFullAmountPaid(NO); + } + + if (YES.equals(caseData.getIsRespondent1()) && caseData.getDefenceAdmitPartPaymentTimeRouteRequired() != null) { + updatedCaseData.defenceAdmitPartPaymentTimeRouteGeneric( + caseData.getDefenceAdmitPartPaymentTimeRouteRequired()); + } else if (YES.equals(caseData.getIsRespondent2()) + && caseData.getDefenceAdmitPartPaymentTimeRouteRequired2() != null) { + updatedCaseData.defenceAdmitPartPaymentTimeRouteGeneric( + caseData.getDefenceAdmitPartPaymentTimeRouteRequired2()); + } + + if (YES.equals(caseData.getIsRespondent2()) && YES.equals(caseData.getSpecDefenceAdmitted2Required())) { + updatedCaseData.partAdmittedByEitherRespondents(YES); + } else if (YES.equals(caseData.getIsRespondent1()) && YES.equals(caseData.getSpecDefenceAdmittedRequired())) { + updatedCaseData.partAdmittedByEitherRespondents(YES); + } else { + updatedCaseData.partAdmittedByEitherRespondents(NO); + } + + if (YES.equals(caseData.getDefenceAdmitPartEmploymentTypeRequired())) { + updatedCaseData.respondToClaimAdmitPartEmploymentTypeLRspecGeneric( + caseData.getRespondToClaimAdmitPartEmploymentTypeLRspec()); + } + if (YES.equals(caseData.getDefenceAdmitPartEmploymentType2Required())) { + updatedCaseData.respondToClaimAdmitPartEmploymentTypeLRspecGeneric( + caseData.getRespondToClaimAdmitPartEmploymentTypeLRspec2()); + } + if (caseData.getRespondToAdmittedClaimOwingAmount() != null) { + BigDecimal valuePounds = MonetaryConversions + .penniesToPounds(caseData.getRespondToAdmittedClaimOwingAmount()); + updatedCaseData.respondToAdmittedClaimOwingAmountPounds(valuePounds); + } + if (YES.equals(caseData.getDefenceAdmitPartEmploymentType2Required())) { + updatedCaseData.respondToClaimAdmitPartEmploymentTypeLRspecGeneric( + caseData.getRespondToClaimAdmitPartEmploymentTypeLRspec2()); + } + Optional.ofNullable(caseData.getRespondToAdmittedClaimOwingAmount()) + .map(MonetaryConversions::penniesToPounds) + .ifPresent(updatedCaseData::respondToAdmittedClaimOwingAmountPounds); + Optional.ofNullable(caseData.getRespondToAdmittedClaimOwingAmount2()) + .map(MonetaryConversions::penniesToPounds) + .ifPresent(updatedCaseData::respondToAdmittedClaimOwingAmountPounds2); + if (RespondentResponseTypeSpecPaidStatus.PAID_LESS_THAN_CLAIMED_AMOUNT + == caseData.getRespondent1ClaimResponsePaymentAdmissionForSpec() + || DISPUTES_THE_CLAIM.equals(caseData.getDefenceRouteRequired()) + || RespondentResponseTypeSpec.PART_ADMISSION == caseData.getRespondent1ClaimResponseTypeForSpec()) { + updatedCaseData.specPaidLessAmountOrDisputesOrPartAdmission(YES); + } else { + updatedCaseData.specPaidLessAmountOrDisputesOrPartAdmission(NO); + } + if (RespondentResponseTypeSpecPaidStatus.PAID_LESS_THAN_CLAIMED_AMOUNT + != caseData.getRespondent1ClaimResponsePaymentAdmissionForSpec() + && (DISPUTES_THE_CLAIM.equals(caseData.getDefenceRouteRequired()) + || caseData.getRespondent1ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.PART_ADMISSION)) { + updatedCaseData.specDisputesOrPartAdmission(YES); + } else { + updatedCaseData.specDisputesOrPartAdmission(NO); + } + if (caseData.getRespondent1ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.PART_ADMISSION + && caseData.getSpecDefenceAdmittedRequired() == NO) { + updatedCaseData.specPartAdmitPaid(NO); + } else if (caseData.getRespondent1ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.FULL_ADMISSION + && caseData.getSpecDefenceFullAdmittedRequired() == NO) { + updatedCaseData.specFullAdmitPaid(NO); + } + if (SpecJourneyConstantLRSpec.DEFENDANT_RESPONSE_SPEC.equals(callbackParams.getRequest().getEventId())) { + AllocatedTrack allocatedTrack = getAllocatedTrack(caseData); + updatedCaseData.responseClaimTrack(allocatedTrack.name()); + } + Set currentShowFlags = new HashSet<>(caseData.getShowConditionFlags()); + currentShowFlags.removeAll(EnumSet.of( + NEED_FINANCIAL_DETAILS_1, + NEED_FINANCIAL_DETAILS_2, + WHY_1_DOES_NOT_PAY_IMMEDIATELY, + WHY_2_DOES_NOT_PAY_IMMEDIATELY, + WHEN_WILL_CLAIM_BE_PAID + )); + currentShowFlags.addAll(checkNecessaryFinancialDetails(caseData)); + if (mustWhenWillClaimBePaidBeShown(caseData)) { + currentShowFlags.add(WHEN_WILL_CLAIM_BE_PAID); + } + updatedCaseData.showConditionFlags(currentShowFlags); + + return AboutToStartOrSubmitCallbackResponse.builder() + .data(updatedCaseData.build().toMap(objectMapper)) + .build(); + } + + private Set checkNecessaryFinancialDetails(CaseData caseData) { + Set necessary = EnumSet.noneOf(DefendantResponseShowTag.class); + MultiPartyScenario scenario = MultiPartyScenario.getMultiPartyScenario(caseData); + if (caseData.getShowConditionFlags().contains(CAN_ANSWER_RESPONDENT_1)) { + if (caseData.getRespondent1().getType() != Party.Type.COMPANY + && caseData.getRespondent1().getType() != Party.Type.ORGANISATION && needFinancialInfo1(caseData)) { + necessary.add(NEED_FINANCIAL_DETAILS_1); + } + + if (respondent1doesNotPayImmediately(caseData, scenario)) { + necessary.add(WHY_1_DOES_NOT_PAY_IMMEDIATELY); + } + } + + if (caseData.getShowConditionFlags().contains(CAN_ANSWER_RESPONDENT_2)) { + if (caseData.getRespondent2().getType() != Party.Type.COMPANY + && caseData.getRespondent2().getType() != Party.Type.ORGANISATION) { + if ((scenario == ONE_V_TWO_TWO_LEGAL_REP && needFinancialInfo21v2ds(caseData)) + || (scenario == ONE_V_TWO_ONE_LEGAL_REP + && ((caseData.getRespondentResponseIsSame() != YES && needFinancialInfo21v2ds(caseData)) + || (needFinancialInfo1(caseData) && caseData.getRespondentResponseIsSame() == YES)))) { + necessary.add(NEED_FINANCIAL_DETAILS_2); + } + + if (respondent2doesNotPayImmediately(caseData, scenario)) { + necessary.add(WHY_2_DOES_NOT_PAY_IMMEDIATELY); + } + } + + if (respondent2doesNotPayImmediately(caseData, scenario)) { + necessary.add(WHY_2_DOES_NOT_PAY_IMMEDIATELY); + } + + if ((caseData.getRespondentResponseIsSame() == YES + && caseData.getDefenceAdmitPartPaymentTimeRouteRequired() == SUGGESTION_OF_REPAYMENT_PLAN) + || caseData.getDefenceAdmitPartPaymentTimeRouteRequired2() == SUGGESTION_OF_REPAYMENT_PLAN) { + necessary.add(REPAYMENT_PLAN_2); + } + } + + return necessary; + } + + private boolean respondent1doesNotPayImmediately(CaseData caseData, MultiPartyScenario scenario) { + if (YES.equals(caseData.getIsRespondent1()) + && caseData.getRespondentClaimResponseTypeForSpecGeneric() != COUNTER_CLAIM + && caseData.getRespondentClaimResponseTypeForSpecGeneric() != FULL_DEFENCE + && (scenario != ONE_V_TWO_ONE_LEGAL_REP || caseData.getRespondentResponseIsSame() == YES)) { + return caseData.getDefenceAdmitPartPaymentTimeRouteRequired() != IMMEDIATELY + && caseData.getSpecDefenceFullAdmittedRequired() != YES + && caseData.getSpecDefenceAdmittedRequired() != YES; + } + return false; + } + + private boolean respondent2doesNotPayImmediately(CaseData caseData, MultiPartyScenario scenario) { + if (caseData.getRespondentClaimResponseTypeForSpecGeneric() != COUNTER_CLAIM + && caseData.getRespondentClaimResponseTypeForSpecGeneric() != FULL_DEFENCE) { + if (scenario == ONE_V_TWO_ONE_LEGAL_REP && caseData.getRespondentResponseIsSame() == YES) { + return caseData.getDefenceAdmitPartPaymentTimeRouteRequired() != IMMEDIATELY + && caseData.getSpecDefenceFullAdmittedRequired() != YES + && caseData.getSpecDefenceAdmittedRequired() != YES; + } else if (caseData.getRespondentResponseIsSame() != null || scenario == ONE_V_TWO_TWO_LEGAL_REP) { + return caseData.getDefenceAdmitPartPaymentTimeRouteRequired2() != IMMEDIATELY + && caseData.getSpecDefenceFullAdmitted2Required() != YES + && caseData.getSpecDefenceAdmitted2Required() != YES; + } + } + return false; } + /** + * this condition has been copied from ccd's on the moment of writing. + * + * @param caseData the case data + * @return true if the financial details for r1 are needed. Doesn't consider if the r1 + */ + private boolean needFinancialInfo1(CaseData caseData) { + return caseData.getDefenceAdmitPartPaymentTimeRouteRequired() != IMMEDIATELY + && caseData.getSpecDefenceAdmittedRequired() != YES + && caseData.getSpecDefenceFullAdmittedRequired() != YES + && caseData.getRespondentClaimResponseTypeForSpecGeneric() != FULL_DEFENCE + && caseData.getRespondentClaimResponseTypeForSpecGeneric() != RespondentResponseTypeSpec.COUNTER_CLAIM + && caseData.getMultiPartyResponseTypeFlags() != MultiPartyResponseTypeFlags.COUNTER_ADMIT_OR_ADMIT_PART + && (caseData.getSameSolicitorSameResponse() != NO + || MultiPartyScenario.getMultiPartyScenario(caseData) == ONE_V_TWO_TWO_LEGAL_REP) + && caseData.getDefendantSingleResponseToBothClaimants() != NO; + } + + /** + * Adapts the conditions from needFinancialInfo1 for use with 2nd solicitor. + * + * @param caseData case data + * @return true if the financial details for 2nd defendant are needed, in a 1v2 different solicitor claim. + */ + private boolean needFinancialInfo21v2ds(CaseData caseData) { + return caseData.getDefenceAdmitPartPaymentTimeRouteRequired2() != IMMEDIATELY + && caseData.getSpecDefenceAdmitted2Required() != YES + && caseData.getSpecDefenceFullAdmitted2Required() != YES + && caseData.getRespondentClaimResponseTypeForSpecGeneric() != FULL_DEFENCE + && caseData.getRespondentClaimResponseTypeForSpecGeneric() != RespondentResponseTypeSpec.COUNTER_CLAIM; + } + + /** + * From the responseType, if we choose A, advance for a while, then backtrack and choose B, part of our responses + * in A stay in frontend and may influence screens that A and B have in common. + * + *

Why does that happen? + * Frontend keeps an object with the CaseData information. + * In mid callbacks frontend sends part of that object, which gets deserialized into an instance of CaseData. + * We can modify that caseData, but since where using objectMapper.setSerializationInclusion(Include.NON_EMPTY) + * we only send anything not empty, not null. That means we cannot signal frontend to "clean" info. + * What we can do, however, is change info.

+ * + *

For instance, the field specDefenceFullAdmittedRequired is only accessible from FULL_ADMISSION. + * If the user went to full admission, checked specDefenceFullAdmittedRequired = yes + * and then went back and to part admit, a bunch of screens common to both options won't appear because their + * condition to show include that specDefenceFullAdmittedRequired != yes. So, if in this method we say that whenever + * responseType is not full admission, then specDefenceFullAdmittedRequired = No, since that is not empty, gets sent + * to frontend and frontend overwrites that field on its copy.

+ * + * @param callbackParams parameters from frontend. + * @return caseData cleaned from backtracked paths. + */ private CallbackResponse handleRespondentResponseTypeForSpec(CallbackParams callbackParams) { - return handleRespondentResponseTypeForSpec.execute(callbackParams); + CaseData caseData = callbackParams.getCaseData(); + if (caseData.getRespondent1ClaimResponseTypeForSpec() != RespondentResponseTypeSpec.FULL_ADMISSION + || caseData.getRespondent2ClaimResponseTypeForSpec() != RespondentResponseTypeSpec.FULL_ADMISSION) { + caseData = caseData.toBuilder().specDefenceFullAdmittedRequired(NO).build(); + } + return AboutToStartOrSubmitCallbackResponse.builder() + .data(caseData.toMap(objectMapper)) + .build(); } private CallbackResponse setGenericResponseTypeFlag(CallbackParams callbackParams) { - return setGenericResponseTypeFlag.execute(callbackParams); + CaseData caseData = callbackParams.getCaseData(); + CaseData.CaseDataBuilder updatedData = + caseData.toBuilder().multiPartyResponseTypeFlags(MultiPartyResponseTypeFlags.NOT_FULL_DEFENCE); + + if ((RespondentResponseTypeSpec.FULL_ADMISSION.equals(caseData.getClaimant1ClaimResponseTypeForSpec()) + || RespondentResponseTypeSpec.PART_ADMISSION.equals(caseData.getClaimant1ClaimResponseTypeForSpec()) + || RespondentResponseTypeSpec.COUNTER_CLAIM.equals(caseData.getClaimant1ClaimResponseTypeForSpec())) + && + (RespondentResponseTypeSpec.FULL_ADMISSION.equals(caseData.getClaimant2ClaimResponseTypeForSpec()) + || RespondentResponseTypeSpec.PART_ADMISSION.equals(caseData.getClaimant2ClaimResponseTypeForSpec()) + || RespondentResponseTypeSpec.COUNTER_CLAIM.equals(caseData.getClaimant2ClaimResponseTypeForSpec()))) { + updatedData.multiPartyResponseTypeFlags(MultiPartyResponseTypeFlags.COUNTER_ADMIT_OR_ADMIT_PART); + } + //this logic to be removed when ccd supports AND-OR combinations + MultiPartyScenario multiPartyScenario = getMultiPartyScenario(caseData); + if (ONE_V_ONE.equals(multiPartyScenario)) { + updatedData.respondentClaimResponseTypeForSpecGeneric(caseData.getRespondent1ClaimResponseTypeForSpec()); + if (caseData.getRespondent1ClaimResponseTypeForSpec() == FULL_DEFENCE) { + updatedData.multiPartyResponseTypeFlags(MultiPartyResponseTypeFlags.FULL_DEFENCE); + } else if (caseData.getRespondent1ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.COUNTER_CLAIM) { + updatedData.multiPartyResponseTypeFlags(MultiPartyResponseTypeFlags.COUNTER_ADMIT_OR_ADMIT_PART); + } else if (caseData.getRespondent1ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.FULL_ADMISSION + || caseData.getRespondent2ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.FULL_ADMISSION) { + updatedData.multiPartyResponseTypeFlags(MultiPartyResponseTypeFlags.FULL_ADMISSION); + } + } + + Set someAdmission = EnumSet.of(PART_ADMISSION, FULL_ADMISSION); + if (TWO_V_ONE.equals(multiPartyScenario) + && someAdmission.contains(caseData.getRespondent1ClaimResponseTypeForSpec()) + && someAdmission.contains(caseData.getRespondent2ClaimResponseTypeForSpec())) { + updatedData.specFullAdmissionOrPartAdmission(YES); + } else { + updatedData.specFullAdmissionOrPartAdmission(NO); + } + + if (ONE_V_TWO_ONE_LEGAL_REP.equals(multiPartyScenario) + && Objects.equals( + caseData.getRespondent1ClaimResponseTypeForSpec(), + caseData.getRespondent2ClaimResponseTypeForSpec() + )) { + updatedData.respondentResponseIsSame(YES); + caseData = caseData.toBuilder() + .respondentResponseIsSame(YES) + .build(); + } + if (ONE_V_TWO_ONE_LEGAL_REP.equals(multiPartyScenario) + && caseData.getRespondentResponseIsSame().equals(NO)) { + updatedData.sameSolicitorSameResponse(NO); + if (FULL_DEFENCE.equals(caseData.getRespondent1ClaimResponseTypeForSpec()) + || FULL_DEFENCE.equals(caseData.getRespondent2ClaimResponseTypeForSpec())) { + updatedData.respondentClaimResponseTypeForSpecGeneric(FULL_DEFENCE); + } + } else if (ONE_V_TWO_ONE_LEGAL_REP.equals(multiPartyScenario) + && caseData.getRespondentResponseIsSame().equals(YES)) { + updatedData.sameSolicitorSameResponse(YES); + updatedData.respondentClaimResponseTypeForSpecGeneric(caseData.getRespondent1ClaimResponseTypeForSpec()); + if (FULL_DEFENCE.equals(caseData.getRespondent1ClaimResponseTypeForSpec()) + || RespondentResponseTypeSpec.COUNTER_CLAIM.equals(caseData.getRespondent1ClaimResponseTypeForSpec())) { + updatedData.multiPartyResponseTypeFlags(MultiPartyResponseTypeFlags.FULL_DEFENCE); + } + } else { + updatedData.respondentClaimResponseTypeForSpecGeneric(caseData.getRespondent1ClaimResponseTypeForSpec()); + } + + UserInfo userInfo = userService.getUserInfo(callbackParams.getParams().get(BEARER_TOKEN).toString()); + if (ONE_V_TWO_TWO_LEGAL_REP.equals(multiPartyScenario)) { + if (coreCaseUserService.userHasCaseRole( + caseData.getCcdCaseReference().toString(), + userInfo.getUid(), + RESPONDENTSOLICITORTWO + )) { + updatedData.respondentClaimResponseTypeForSpecGeneric( + caseData.getRespondent2ClaimResponseTypeForSpec()); + } else { + updatedData.respondentClaimResponseTypeForSpecGeneric( + caseData.getRespondent1ClaimResponseTypeForSpec()); + } + } + + if (ONE_V_TWO_TWO_LEGAL_REP.equals(multiPartyScenario) + && ((YES.equals(caseData.getIsRespondent1()) + && RespondentResponseTypeSpec.PART_ADMISSION.equals(caseData.getRespondent1ClaimResponseTypeForSpec())) + || (YES.equals(caseData.getIsRespondent2()) + && RespondentResponseTypeSpec.PART_ADMISSION.equals(caseData.getRespondent2ClaimResponseTypeForSpec())))) { + updatedData.multiPartyResponseTypeFlags(MultiPartyResponseTypeFlags.PART_ADMISSION); + } + + if (YES.equals(caseData.getIsRespondent2())) { + updatedData.respondentClaimResponseTypeForSpecGeneric(caseData.getRespondent2ClaimResponseTypeForSpec()); + } + + if (caseData.getRespondent1ClaimResponseTypeForSpec() == FULL_DEFENCE + || caseData.getRespondent2ClaimResponseTypeForSpec() == FULL_DEFENCE + || caseData.getClaimant1ClaimResponseTypeForSpec() == FULL_DEFENCE + || caseData.getClaimant2ClaimResponseTypeForSpec() == FULL_DEFENCE) { + updatedData.multiPartyResponseTypeFlags(MultiPartyResponseTypeFlags.FULL_DEFENCE); + } + + if ((YES.equals(caseData.getIsRespondent1()) + && (caseData.getRespondent1ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.PART_ADMISSION + || caseData.getRespondent1ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.FULL_ADMISSION)) + || (YES.equals(caseData.getIsRespondent2()) + && (caseData.getRespondent2ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.PART_ADMISSION + || caseData.getRespondent2ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.FULL_ADMISSION))) { + updatedData.specFullAdmissionOrPartAdmission(YES); + } + if (RespondentResponseTypeSpec.FULL_ADMISSION.equals(caseData.getRespondent2ClaimResponseTypeForSpec()) + || RespondentResponseTypeSpec.PART_ADMISSION.equals(caseData.getRespondent2ClaimResponseTypeForSpec()) + || RespondentResponseTypeSpec.COUNTER_CLAIM.equals(caseData.getRespondent2ClaimResponseTypeForSpec())) { + updatedData.multiPartyResponseTypeFlags(MultiPartyResponseTypeFlags.COUNTER_ADMIT_OR_ADMIT_PART); + } + if (caseData.getRespondent1ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.PART_ADMISSION + || caseData.getRespondent1ClaimResponseTypeForSpec() == FULL_DEFENCE) { + updatedData.specFullDefenceOrPartAdmission1V1(YES); + } + if (caseData.getRespondent1ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.PART_ADMISSION + || caseData.getRespondent1ClaimResponseTypeForSpec() == FULL_DEFENCE + || caseData.getRespondent2ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.PART_ADMISSION + || caseData.getRespondent2ClaimResponseTypeForSpec() == FULL_DEFENCE) { + updatedData.specFullDefenceOrPartAdmission(YES); + } else { + updatedData.specFullDefenceOrPartAdmission(NO); + } + if (caseData.getRespondent1ClaimResponseTypeForSpec() != RespondentResponseTypeSpec.FULL_ADMISSION + || caseData.getRespondent2ClaimResponseTypeForSpec() != RespondentResponseTypeSpec.FULL_ADMISSION) { + updatedData.specDefenceFullAdmittedRequired(NO); + } + + if (YES.equals(caseData.getSpecPaidLessAmountOrDisputesOrPartAdmission()) + && !MultiPartyResponseTypeFlags.COUNTER_ADMIT_OR_ADMIT_PART + .equals(caseData.getMultiPartyResponseTypeFlags()) + && (!RespondentResponseTypeSpecPaidStatus.PAID_FULL_OR_MORE_THAN_CLAIMED_AMOUNT + .equals(caseData.getRespondent1ClaimResponsePaymentAdmissionForSpec()))) { + updatedData.showHowToAddTimeLinePage(YES); + } + + if (YES.equals(caseData.getIsRespondent1())) { + if (RespondentResponseTypeSpec.COUNTER_CLAIM.equals(caseData.getRespondent1ClaimResponseTypeForSpec())) { + updatedData.showHowToAddTimeLinePage(NO); + updatedData.multiPartyResponseTypeFlags(MultiPartyResponseTypeFlags.COUNTER_ADMIT_OR_ADMIT_PART); + } else if (RespondentResponseTypeSpec.FULL_ADMISSION + .equals(caseData.getRespondent1ClaimResponseTypeForSpec())) { + updatedData.showHowToAddTimeLinePage(NO); + } + } else if (YES.equals(caseData.getIsRespondent2())) { + if (RespondentResponseTypeSpec.COUNTER_CLAIM.equals(caseData.getRespondent2ClaimResponseTypeForSpec())) { + updatedData.showHowToAddTimeLinePage(NO); + updatedData.multiPartyResponseTypeFlags(MultiPartyResponseTypeFlags.COUNTER_ADMIT_OR_ADMIT_PART); + } else if (RespondentResponseTypeSpec.FULL_ADMISSION + .equals(caseData.getRespondent2ClaimResponseTypeForSpec())) { + updatedData.showHowToAddTimeLinePage(NO); + } + } + + if (YES.equals(caseData.getIsRespondent2()) && YES.equals(caseData.getSpecDefenceAdmittedRequired())) { + updatedData.partAdmittedByEitherRespondents(YES); + } else if (YES.equals(caseData.getIsRespondent1()) && YES.equals(caseData.getSpecDefenceAdmitted2Required())) { + updatedData.partAdmittedByEitherRespondents(YES); + } else { + updatedData.partAdmittedByEitherRespondents(NO); + } + + if (YES.equals(caseData.getIsRespondent2()) && YES.equals(caseData.getSpecDefenceFullAdmitted2Required())) { + updatedData.fullAdmissionAndFullAmountPaid(YES); + } else if (YES.equals(caseData.getIsRespondent1()) + && YES.equals(caseData.getSpecDefenceFullAdmittedRequired())) { + updatedData.fullAdmissionAndFullAmountPaid(YES); + } else { + updatedData.fullAdmissionAndFullAmountPaid(NO); + } + + if (YES.equals(caseData.getIsRespondent1()) && caseData.getDefenceAdmitPartPaymentTimeRouteRequired() != null) { + updatedData.defenceAdmitPartPaymentTimeRouteGeneric( + caseData.getDefenceAdmitPartPaymentTimeRouteRequired()); + } else if (YES.equals(caseData.getIsRespondent2()) + && caseData.getDefenceAdmitPartPaymentTimeRouteRequired2() != null) { + updatedData.defenceAdmitPartPaymentTimeRouteGeneric( + caseData.getDefenceAdmitPartPaymentTimeRouteRequired2()); + } else { + //workaround + updatedData.defenceAdmitPartPaymentTimeRouteGeneric( + IMMEDIATELY); + } + + Set updatedShowConditions = whoDisputesPartAdmission(caseData); + EnumSet anyAdmission = EnumSet.of( + RespondentResponseTypeSpec.PART_ADMISSION, + RespondentResponseTypeSpec.FULL_ADMISSION + ); + if (updatedShowConditions.contains(CAN_ANSWER_RESPONDENT_1) + && anyAdmission.contains(caseData.getRespondent1ClaimResponseTypeForSpec())) { + updatedShowConditions.add(RESPONDENT_1_ADMITS_PART_OR_FULL); + if (caseData.getRespondentResponseIsSame() == YES) { + updatedShowConditions.add(RESPONDENT_2_ADMITS_PART_OR_FULL); + } + } + if (caseData.getShowConditionFlags().contains(CAN_ANSWER_RESPONDENT_2) + && anyAdmission.contains(caseData.getRespondent2ClaimResponseTypeForSpec())) { + updatedShowConditions.add(RESPONDENT_2_ADMITS_PART_OR_FULL); + } + if (someoneDisputes(caseData)) { + updatedShowConditions.add(SOMEONE_DISPUTES); + } + if ((anyAdmission.contains(caseData.getRespondent1ClaimResponseTypeForSpec()) + && YES.equals(caseData.getIsRespondent1())) + || (anyAdmission.contains(caseData.getRespondent2ClaimResponseTypeForSpec()) + && YES.equals(caseData.getIsRespondent2()))) { + updatedShowConditions.removeIf(EnumSet.of( + CURRENT_ADMITS_PART_OR_FULL + )::contains); + updatedShowConditions.add(CURRENT_ADMITS_PART_OR_FULL); + } + updatedData.showConditionFlags(updatedShowConditions); + + return AboutToStartOrSubmitCallbackResponse.builder() + .data(updatedData.build().toMap(objectMapper)) + .build(); } private CallbackResponse setUploadTimelineTypeFlag(CallbackParams callbackParams) { - return setUploadTimelineTypeFlag.execute(callbackParams); + CaseData caseData = callbackParams.getCaseData(); + CaseData.CaseDataBuilder updatedData = caseData.toBuilder(); + Set updatedShowConditions = new HashSet<>(caseData.getShowConditionFlags()); + updatedShowConditions.removeIf(EnumSet.of( + TIMELINE_UPLOAD, + TIMELINE_MANUALLY + )::contains); + + if ((YES.equals(caseData.getIsRespondent1()) + && caseData.getSpecClaimResponseTimelineList() == TimelineUploadTypeSpec.UPLOAD) + || (YES.equals(caseData.getIsRespondent2()) + && caseData.getSpecClaimResponseTimelineList2() == TimelineUploadTypeSpec.UPLOAD)) { + updatedShowConditions.add(TIMELINE_UPLOAD); + } else if ((YES.equals(caseData.getIsRespondent1()) + && caseData.getSpecClaimResponseTimelineList() == TimelineUploadTypeSpec.MANUAL) + || (YES.equals(caseData.getIsRespondent2()) + && caseData.getSpecClaimResponseTimelineList2() == TimelineUploadTypeSpec.MANUAL)) { + updatedShowConditions.add(TIMELINE_MANUALLY); + } + updatedData.showConditionFlags(updatedShowConditions); + + return AboutToStartOrSubmitCallbackResponse.builder() + .data(updatedData.build().toMap(objectMapper)) + .build(); + } + + /** + * The condition to show the right title for why does X disputes the claim is too complex for the current + * abilities of front, so we have to take care of it in back. + * This method may add the flags only_respondent_1_disputes, only_respondent_2_disputes or both_respondent_dispute. + * + * @param caseData the current case data + * @return updated copy of caseData.showConditionFlag + */ + private Set whoDisputesPartAdmission(CaseData caseData) { + Set tags = new HashSet<>(caseData.getShowConditionFlags()); + removeWhoDisputesAndWhoPaidLess(tags); + tags.addAll(whoDisputesBcoPartAdmission(caseData)); + return tags; + } + + static final String UNKNOWN_MP_SCENARIO = "Unknown mp scenario"; + + /** + * Returns the flags that should be active because part admission has been chosen. + * + * @param caseData the claim info + * @return flags to describe who disputes because a response is part admission + */ + private Set whoDisputesBcoPartAdmission(CaseData caseData) { + Set tags = EnumSet.noneOf(DefendantResponseShowTag.class); + MultiPartyScenario mpScenario = getMultiPartyScenario(caseData); + switch (mpScenario) { + case ONE_V_ONE: + if (caseData.getRespondent1ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.PART_ADMISSION) { + tags.add(ONLY_RESPONDENT_1_DISPUTES); + } + break; + case TWO_V_ONE: + if ((caseData.getDefendantSingleResponseToBothClaimants() == YES + && caseData.getRespondent1ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.PART_ADMISSION) + || caseData.getClaimant1ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.PART_ADMISSION + || caseData.getClaimant2ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.PART_ADMISSION) { + tags.add(ONLY_RESPONDENT_1_DISPUTES); + } + break; + case ONE_V_TWO_ONE_LEGAL_REP: + if (caseData.getRespondent1ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.PART_ADMISSION) { + if (caseData.getRespondentResponseIsSame() == YES + || caseData.getRespondent2ClaimResponseTypeForSpec() + == RespondentResponseTypeSpec.PART_ADMISSION) { + tags.add(DefendantResponseShowTag.BOTH_RESPONDENTS_DISPUTE); + } else { + tags.add(ONLY_RESPONDENT_1_DISPUTES); + } + } else if (caseData.getRespondent2ClaimResponseTypeForSpec() + == RespondentResponseTypeSpec.PART_ADMISSION) { + tags.add(DefendantResponseShowTag.ONLY_RESPONDENT_2_DISPUTES); + } + break; + case ONE_V_TWO_TWO_LEGAL_REP: + if (caseData.getShowConditionFlags().contains(DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_1) + && caseData.getRespondent1ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.PART_ADMISSION) { + tags.add(ONLY_RESPONDENT_1_DISPUTES); + } else if (caseData.getShowConditionFlags().contains(DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_2) + && caseData.getRespondent2ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.PART_ADMISSION) { + tags.add(DefendantResponseShowTag.ONLY_RESPONDENT_2_DISPUTES); + } + break; + default: + throw new UnsupportedOperationException(UNKNOWN_MP_SCENARIO); + } + return tags; + } + + private boolean someoneDisputes(CaseData caseData) { + if (TWO_V_ONE.equals(getMultiPartyScenario(caseData))) { + return ((caseData.getClaimant1ClaimResponseTypeForSpec() == FULL_DEFENCE + || caseData.getClaimant2ClaimResponseTypeForSpec() == FULL_DEFENCE) + || caseData.getRespondent1ClaimResponseTypeForSpec() == FULL_DEFENCE + || caseData.getRespondent1ClaimResponseTypeForSpec() == PART_ADMISSION); + } else { + return someoneDisputes(caseData, CAN_ANSWER_RESPONDENT_1, + caseData.getRespondent1ClaimResponseTypeForSpec() + ) + || someoneDisputes(caseData, CAN_ANSWER_RESPONDENT_2, + caseData.getRespondent2ClaimResponseTypeForSpec() + ); + } + } + + private boolean someoneDisputes(CaseData caseData, DefendantResponseShowTag respondent, + RespondentResponseTypeSpec response) { + return caseData.getShowConditionFlags().contains(respondent) + && (response == FULL_DEFENCE + || (response == PART_ADMISSION && !NO.equals(caseData.getRespondentResponseIsSame()))); + } + + private Set whoDisputesFullDefence(CaseData caseData) { + Set tags = new HashSet<>(caseData.getShowConditionFlags()); + // in case of backtracking + removeWhoDisputesAndWhoPaidLess(tags); + Set bcoPartAdmission = whoDisputesBcoPartAdmission(caseData); + MultiPartyScenario mpScenario = getMultiPartyScenario(caseData); + switch (mpScenario) { + case ONE_V_ONE: + fullDefenceAndPaidLess( + caseData.getRespondent1ClaimResponseTypeForSpec(), + caseData.getDefenceRouteRequired(), + caseData.getRespondToClaim(), + caseData.getTotalClaimAmount(), + ONLY_RESPONDENT_1_DISPUTES, + DefendantResponseShowTag.RESPONDENT_1_PAID_LESS + ).ifPresent(bcoPartAdmission::add); + break; + case TWO_V_ONE: + if (!bcoPartAdmission.contains(ONLY_RESPONDENT_1_DISPUTES)) { + if (caseData.getDefendantSingleResponseToBothClaimants() == YES) { + fullDefenceAndPaidLess( + caseData.getRespondent1ClaimResponseTypeForSpec(), + caseData.getDefenceRouteRequired(), + caseData.getRespondToClaim(), + caseData.getTotalClaimAmount(), + ONLY_RESPONDENT_1_DISPUTES, + DefendantResponseShowTag.RESPONDENT_1_PAID_LESS + ).ifPresent(bcoPartAdmission::add); + } else { + fullDefenceAndPaidLess( + caseData.getClaimant1ClaimResponseTypeForSpec(), + caseData.getDefenceRouteRequired(), + caseData.getRespondToClaim(), + caseData.getTotalClaimAmount(), + ONLY_RESPONDENT_1_DISPUTES, + DefendantResponseShowTag.RESPONDENT_1_PAID_LESS + ).ifPresent(bcoPartAdmission::add); + + fullDefenceAndPaidLess( + caseData.getClaimant2ClaimResponseTypeForSpec(), + caseData.getDefenceRouteRequired(), + caseData.getRespondToClaim(), + caseData.getTotalClaimAmount(), + ONLY_RESPONDENT_1_DISPUTES, + DefendantResponseShowTag.RESPONDENT_1_PAID_LESS + ).ifPresent(bcoPartAdmission::add); + } + } + break; + case ONE_V_TWO_ONE_LEGAL_REP: + if (caseData.getRespondentResponseIsSame() == YES) { + fullDefenceAndPaidLess( + caseData.getRespondent1ClaimResponseTypeForSpec(), + caseData.getDefenceRouteRequired(), + caseData.getRespondToClaim(), + caseData.getTotalClaimAmount(), + BOTH_RESPONDENTS_DISPUTE, + DefendantResponseShowTag.RESPONDENT_1_PAID_LESS + ).ifPresent(tag -> { + bcoPartAdmission.add(tag); + if (tag == DefendantResponseShowTag.RESPONDENT_1_PAID_LESS) { + bcoPartAdmission.add(DefendantResponseShowTag.RESPONDENT_2_PAID_LESS); + } + }); + } else { + fullDefenceAndPaidLess( + caseData.getRespondent1ClaimResponseTypeForSpec(), + caseData.getDefenceRouteRequired(), + caseData.getRespondToClaim(), + caseData.getTotalClaimAmount(), + ONLY_RESPONDENT_1_DISPUTES, + DefendantResponseShowTag.RESPONDENT_1_PAID_LESS + ).ifPresent(bcoPartAdmission::add); + if (caseData.getRespondentResponseIsSame() == YES) { + if (bcoPartAdmission.contains(RESPONDENT_1_PAID_LESS)) { + bcoPartAdmission.add(RESPONDENT_2_PAID_LESS); + } + } else { + fullDefenceAndPaidLess( + caseData.getRespondent2ClaimResponseTypeForSpec(), + // if only 2nd defends, defenceRouteRequired2 field is not used + caseData.getDefenceRouteRequired(), + caseData.getRespondToClaim(), + caseData.getTotalClaimAmount(), + DefendantResponseShowTag.ONLY_RESPONDENT_2_DISPUTES, + DefendantResponseShowTag.RESPONDENT_2_PAID_LESS + ).ifPresent(bcoPartAdmission::add); + } + EnumSet bothOnlyDisputes = EnumSet.of( + DefendantResponseShowTag.ONLY_RESPONDENT_1_DISPUTES, + DefendantResponseShowTag.ONLY_RESPONDENT_2_DISPUTES + ); + if (bcoPartAdmission.containsAll(bothOnlyDisputes)) { + bcoPartAdmission.removeAll(bothOnlyDisputes); + bcoPartAdmission.add(BOTH_RESPONDENTS_DISPUTE); + } + } + break; + case ONE_V_TWO_TWO_LEGAL_REP: + if (tags.contains(DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_1)) { + fullDefenceAndPaidLess( + caseData.getRespondent1ClaimResponseTypeForSpec(), + caseData.getDefenceRouteRequired(), + caseData.getRespondToClaim(), + caseData.getTotalClaimAmount(), + ONLY_RESPONDENT_1_DISPUTES, + DefendantResponseShowTag.RESPONDENT_1_PAID_LESS + ).ifPresent(bcoPartAdmission::add); + } else if (tags.contains(DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_2)) { + fullDefenceAndPaidLess( + caseData.getRespondent2ClaimResponseTypeForSpec(), + caseData.getDefenceRouteRequired2(), + caseData.getRespondToClaim2(), + caseData.getTotalClaimAmount(), + DefendantResponseShowTag.ONLY_RESPONDENT_2_DISPUTES, + DefendantResponseShowTag.RESPONDENT_2_PAID_LESS + ).ifPresent(bcoPartAdmission::add); + } + break; + default: + throw new UnsupportedOperationException(UNKNOWN_MP_SCENARIO); + } + tags.addAll(bcoPartAdmission); + if (tags.contains(ONLY_RESPONDENT_1_DISPUTES) + || tags.contains(ONLY_RESPONDENT_2_DISPUTES) + || tags.contains(BOTH_RESPONDENTS_DISPUTE)) { + tags.add(SOMEONE_DISPUTES); + } + return tags; + } + + private void removeWhoDisputesAndWhoPaidLess(Set tags) { + tags.removeIf(EnumSet.of( + ONLY_RESPONDENT_1_DISPUTES, + DefendantResponseShowTag.ONLY_RESPONDENT_2_DISPUTES, + DefendantResponseShowTag.BOTH_RESPONDENTS_DISPUTE, + SOMEONE_DISPUTES, + DefendantResponseShowTag.CURRENT_ADMITS_PART_OR_FULL, + DefendantResponseShowTag.RESPONDENT_1_PAID_LESS, + DefendantResponseShowTag.RESPONDENT_2_PAID_LESS, + WHEN_WILL_CLAIM_BE_PAID, + RESPONDENT_1_ADMITS_PART_OR_FULL, + RESPONDENT_2_ADMITS_PART_OR_FULL, + NEED_FINANCIAL_DETAILS_1, + NEED_FINANCIAL_DETAILS_2, + DefendantResponseShowTag.WHY_1_DOES_NOT_PAY_IMMEDIATELY, + WHY_2_DOES_NOT_PAY_IMMEDIATELY, + REPAYMENT_PLAN_2, + DefendantResponseShowTag.MEDIATION + )::contains); + } + + private Optional fullDefenceAndPaidLess( + RespondentResponseTypeSpec responseType, + String fullDefenceRoute, + RespondToClaim responseDetails, + BigDecimal claimedAmount, + DefendantResponseShowTag ifDisputing, + DefendantResponseShowTag ifPaidLess) { + if (FULL_DEFENCE == responseType) { + if (DISPUTES_THE_CLAIM.equals(fullDefenceRoute)) { + return Optional.ofNullable(ifDisputing); + } else if (Optional.ofNullable(responseDetails) + .map(RespondToClaim::getHowMuchWasPaid) + .map(MonetaryConversions::penniesToPounds) + .map(wasPaid1 -> wasPaid1.compareTo(claimedAmount) < 0) + .orElse(false)) { + return Optional.ofNullable(ifPaidLess); + } + } + return Optional.empty(); + } + + private void populateRespondentResponseTypeSpecPaidStatus(CaseData caseData, + CaseData.CaseDataBuilder updated) { + if (SpecJourneyConstantLRSpec.HAS_PAID_THE_AMOUNT_CLAIMED.equals(caseData.getDefenceRouteRequired()) + && caseData.getRespondToClaim().getHowMuchWasPaid() != null) { + // CIV-208 howMuchWasPaid is pence, totalClaimAmount is pounds, hence the need for conversion + int comparison = caseData.getRespondToClaim().getHowMuchWasPaid() + .compareTo(new BigDecimal(MonetaryConversions.poundsToPennies(caseData.getTotalClaimAmount()))); + if (comparison < 0) { + updated.respondent1ClaimResponsePaymentAdmissionForSpec( + RespondentResponseTypeSpecPaidStatus.PAID_LESS_THAN_CLAIMED_AMOUNT).build(); + } else { + updated.respondent1ClaimResponsePaymentAdmissionForSpec( + RespondentResponseTypeSpecPaidStatus.PAID_FULL_OR_MORE_THAN_CLAIMED_AMOUNT).build(); + } + } else { + updated.respondent1ClaimResponsePaymentAdmissionForSpec(RespondentResponseTypeSpecPaidStatus.DID_NOT_PAY) + .build(); + } + + if (YES.equals(caseData.getIsRespondent2())) { + if (SpecJourneyConstantLRSpec.HAS_PAID_THE_AMOUNT_CLAIMED.equals(caseData.getDefenceRouteRequired2()) + && caseData.getRespondToClaim2().getHowMuchWasPaid() != null) { + // CIV-208 howMuchWasPaid is pence, totalClaimAmount is pounds, hence the need for conversion + int comparison = caseData.getRespondToClaim2().getHowMuchWasPaid() + .compareTo(new BigDecimal(MonetaryConversions.poundsToPennies(caseData.getTotalClaimAmount()))); + if (comparison < 0) { + updated.respondent1ClaimResponsePaymentAdmissionForSpec( + RespondentResponseTypeSpecPaidStatus.PAID_LESS_THAN_CLAIMED_AMOUNT).build(); + } else { + updated.respondent1ClaimResponsePaymentAdmissionForSpec( + RespondentResponseTypeSpecPaidStatus.PAID_FULL_OR_MORE_THAN_CLAIMED_AMOUNT).build(); + } + } else { + updated.respondent1ClaimResponsePaymentAdmissionForSpec(null).build(); + } + } + } + + private AllocatedTrack getAllocatedTrack(CaseData caseData) { + return AllocatedTrack.getAllocatedTrack(caseData.getTotalClaimAmount(), null, null, + toggleService, caseData); } private CallbackResponse validateCorrespondenceApplicantAddress(CallbackParams callbackParams) { @@ -222,11 +1080,90 @@ private CallbackResponse validateCorrespondenceApplicantAddress(CallbackParams c } private CallbackResponse determineLoggedInSolicitor(CallbackParams callbackParams) { - return determineLoggedInSolicitor.execute(callbackParams); + var caseData = callbackParams.getCaseData(); + + var updatedCaseData = caseData.toBuilder(); + if (solicitorHasCaseRole(callbackParams, RESPONDENTSOLICITORONE)) { + updatedCaseData.isRespondent1(YES); + updatedCaseData.isRespondent2(NO); + updatedCaseData.isApplicant1(NO); + } else if (solicitorHasCaseRole(callbackParams, RESPONDENTSOLICITORTWO)) { + updatedCaseData.isRespondent1(NO); + updatedCaseData.isRespondent2(YES); + updatedCaseData.isApplicant1(NO); + } else if (solicitorHasCaseRole(callbackParams, APPLICANTSOLICITORONE)) { + updatedCaseData.isRespondent1(NO); + updatedCaseData.isRespondent2(NO); + updatedCaseData.isApplicant1(YES); + } + + if (YES.equals(caseData.getIsRespondent2())) { + if (caseData.getRespondent2DetailsForClaimDetailsTab() != null + && ("Company".equals(caseData.getRespondent2DetailsForClaimDetailsTab().getPartyTypeDisplayValue()) + || "Organisation".equals( + caseData.getRespondent2DetailsForClaimDetailsTab().getPartyTypeDisplayValue()))) { + updatedCaseData.neitherCompanyNorOrganisation(NO); + } else { + updatedCaseData.neitherCompanyNorOrganisation(YES); + } + } else { + if ((caseData.getRespondent1DetailsForClaimDetailsTab() != null + && ("Company".equals(caseData.getRespondent1DetailsForClaimDetailsTab().getPartyTypeDisplayValue()) + || "Organisation".equals( + caseData.getRespondent1DetailsForClaimDetailsTab().getPartyTypeDisplayValue())))) { + updatedCaseData.neitherCompanyNorOrganisation(NO); + } else { + updatedCaseData.neitherCompanyNorOrganisation(YES); + } + } + + return AboutToStartOrSubmitCallbackResponse.builder() + .data(updatedCaseData.build().toMap(objectMapper)) + .build(); } private CallbackResponse populateRespondent1Copy(CallbackParams callbackParams) { - return populateRespondent1Copy.execute(callbackParams); + var caseData = callbackParams.getCaseData(); + Set initialShowTags = getInitialShowTags(callbackParams); + var updatedCaseData = caseData.toBuilder() + .respondent1Copy(caseData.getRespondent1()) + .respondent1ClaimResponseTestForSpec(caseData.getRespondent1ClaimResponseTypeForSpec()) + .respondent2ClaimResponseTestForSpec(caseData.getRespondent2ClaimResponseTypeForSpec()) + .showConditionFlags(initialShowTags); + if (toggleService.isCarmEnabledForCase(caseData)) { + updatedCaseData.showCarmFields(YES); + } else { + updatedCaseData.showCarmFields(NO); + } + + updatedCaseData.respondent1DetailsForClaimDetailsTab(caseData.getRespondent1().toBuilder().flags(null).build()); + + ofNullable(caseData.getRespondent2()) + .ifPresent(r2 -> updatedCaseData.respondent2Copy(r2) + .respondent2DetailsForClaimDetailsTab(r2.toBuilder().flags(null).build()) + ); + + DynamicList courtLocationList = courtLocationUtils.getLocationsFromList(fetchLocationData(callbackParams)); + if (initialShowTags.contains(CAN_ANSWER_RESPONDENT_1)) { + updatedCaseData.respondent1DQ(Respondent1DQ.builder() + .respondToCourtLocation( + RequestedCourt.builder() + .responseCourtLocations(courtLocationList) + .build()) + .build()); + } + if (initialShowTags.contains(CAN_ANSWER_RESPONDENT_2)) { + updatedCaseData.respondent2DQ(Respondent2DQ.builder() + .respondToCourtLocation2( + RequestedCourt.builder() + .responseCourtLocations(courtLocationList) + .build()) + .build()); + } + + return AboutToStartOrSubmitCallbackResponse.builder() + .data(updatedCaseData.build().toMap(objectMapper)) + .build(); } private List fetchLocationData(CallbackParams callbackParams) { @@ -234,12 +1171,79 @@ private List fetchLocationData(CallbackParams callbackParams) { return locationRefDataService.getCourtLocationsForDefaultJudgments(authToken); } + private Set getInitialShowTags(CallbackParams callbackParams) { + CaseData caseData = callbackParams.getCaseData(); + MultiPartyScenario mpScenario = getMultiPartyScenario(caseData); + Set set = EnumSet.noneOf(DefendantResponseShowTag.class); + switch (mpScenario) { + case ONE_V_ONE, TWO_V_ONE: + set.add(DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_1); + break; + case ONE_V_TWO_ONE_LEGAL_REP: + set.add(DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_1); + set.add(DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_2); + break; + case ONE_V_TWO_TWO_LEGAL_REP: + UserInfo userInfo = userService.getUserInfo(callbackParams.getParams().get(BEARER_TOKEN).toString()); + List roles = coreCaseUserService.getUserCaseRoles( + callbackParams.getCaseData().getCcdCaseReference().toString(), + userInfo.getUid() + ); + if (roles.contains(RESPONDENTSOLICITORONE.getFormattedName())) { + set.add(DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_1); + } + if (roles.contains(RESPONDENTSOLICITORTWO.getFormattedName())) { + set.add(DefendantResponseShowTag.CAN_ANSWER_RESPONDENT_2); + } + break; + default: + throw new UnsupportedOperationException(UNKNOWN_MP_SCENARIO); + } + return set; + } + private CallbackResponse validateRespondentWitnesses(CallbackParams callbackParams) { - return validateRespondentWitnesses.execute(callbackParams); + CaseData caseData = callbackParams.getCaseData(); + if (!ONE_V_ONE.equals(MultiPartyScenario.getMultiPartyScenario(caseData))) { + if (solicitorRepresentsOnlyOneOfRespondents(callbackParams, RESPONDENTSOLICITORONE)) { + return validateR1Witnesses(caseData); + } else if (solicitorRepresentsOnlyOneOfRespondents(callbackParams, RESPONDENTSOLICITORTWO)) { + return validateWitnesses(callbackParams.getCaseData().getRespondent2DQ()); + } else if (respondent2HasSameLegalRep(caseData) + && caseData.getRespondentResponseIsSame() != null && caseData.getRespondentResponseIsSame() == NO + && caseData.getRespondent2DQ() != null && caseData.getRespondent2DQ().getRespondent2DQWitnesses() != null) { + return validateWitnesses(callbackParams.getCaseData().getRespondent2DQ()); + } + } + return validateR1Witnesses(caseData); + } + + private CallbackResponse validateR1Witnesses(CaseData caseData) { + List errors = new ArrayList<>(); + if (caseData.getRespondent1DQWitnessesRequiredSpec() == YES + && caseData.getRespondent1DQWitnessesDetailsSpec() == null) { + errors.add("Witness details required"); + } + return AboutToStartOrSubmitCallbackResponse.builder() + .errors(errors) + .build(); } private CallbackResponse validateRespondentExperts(CallbackParams callbackParams) { - return validateRespondentExperts.execute(callbackParams); + CaseData caseData = callbackParams.getCaseData(); + if (!ONE_V_ONE.equals(MultiPartyScenario.getMultiPartyScenario(caseData))) { + if (solicitorRepresentsOnlyOneOfRespondents(callbackParams, RESPONDENTSOLICITORONE)) { + return validateExperts(callbackParams.getCaseData().getRespondent1DQ()); + } else if (solicitorRepresentsOnlyOneOfRespondents(callbackParams, RESPONDENTSOLICITORTWO)) { + return validateExperts(callbackParams.getCaseData().getRespondent2DQ()); + } else if (respondent2HasSameLegalRep(caseData) + && caseData.getRespondentResponseIsSame() != null && caseData.getRespondentResponseIsSame() == NO + && caseData.getRespondent2DQ() != null + && caseData.getRespondent2DQ().getRespondent2DQExperts() != null) { + return validateExperts(callbackParams.getCaseData().getRespondent2DQ()); + } + } + return validateExperts(callbackParams.getCaseData().getRespondent1DQ()); } private boolean respondent2HasSameLegalRep(CaseData caseData) { @@ -248,11 +1252,86 @@ private boolean respondent2HasSameLegalRep(CaseData caseData) { } private CallbackResponse validateUnavailableDates(CallbackParams callbackParams) { - return validateUnavailableDates.execute(callbackParams); + // UnavailableDates validation & field (model) needs to be created. + // This will be taken care via different story, + // because we don't have AC around this date field validation in ROC-9455 + CaseData caseData = callbackParams.getCaseData(); + List errors; + if (SpecJourneyConstantLRSpec.SMALL_CLAIM.equals(caseData.getResponseClaimTrack())) { + SmallClaimHearing smallClaimHearing = caseData.getRespondent1DQ().getRespondent1DQHearingSmallClaim(); + if (YES.equals(caseData.getIsRespondent2())) { + smallClaimHearing = caseData.getRespondent2DQ().getRespondent2DQHearingSmallClaim(); + } + errors = unavailableDateValidator.validateSmallClaimsHearing(smallClaimHearing); + + } else { + Hearing hearingLRspec = caseData.getRespondent1DQ().getRespondent1DQHearingFastClaim(); + errors = unavailableDateValidator.validateFastClaimHearing(hearingLRspec); + } + + return AboutToStartOrSubmitCallbackResponse.builder() + .errors(errors) + .build(); } private CallbackResponse validateDateOfBirth(CallbackParams callbackParams) { - return validateDateOfBirth.execute(callbackParams); + Party respondent = callbackParams.getCaseData().getRespondent1(); + if (respondent == null && callbackParams.getCaseData().getRespondent2() != null) { + respondent = callbackParams.getCaseData().getRespondent2(); + } + List errors = dateOfBirthValidator.validate(respondent); + + CaseData caseData = callbackParams.getCaseData(); + errors.addAll(correspondenceAddressCorrect(caseData)); + CaseData.CaseDataBuilder updatedData = caseData.toBuilder(); + if (ONE_V_TWO_TWO_LEGAL_REP.equals(getMultiPartyScenario(caseData)) + && YES.equals(caseData.getAddRespondent2())) { + if (solicitorRepresentsOnlyOneOfRespondents(callbackParams, RESPONDENTSOLICITORTWO) + && solicitorRepresentsOnlyOneOfRespondents(callbackParams, RESPONDENTSOLICITORONE)) { + updatedData.sameSolicitorSameResponse(YES).build(); + } else { + updatedData.sameSolicitorSameResponse(NO).build(); + } + } else if (ONE_V_TWO_ONE_LEGAL_REP.equals(getMultiPartyScenario(caseData)) + && YES.equals(caseData.getAddRespondent2())) { + if (NO.equals(caseData.getRespondentResponseIsSame())) { + updatedData.sameSolicitorSameResponse(NO).build(); + } else { + updatedData.sameSolicitorSameResponse(YES).build(); + } + + } + + return AboutToStartOrSubmitCallbackResponse.builder() + .data(updatedData.build().toMap(objectMapper)) + .errors(errors) + .build(); + } + + /** + * Checks that the address of case data was ok when the applicant set it, or that its postcode is correct + * if the defendant has modified. + * + * @param caseData the case data + * @return errors of the correspondence address (if any) + */ + private List correspondenceAddressCorrect(CaseData caseData) { + if (caseData.getIsRespondent1() == YesOrNo.YES + && caseData.getSpecAoSRespondentCorrespondenceAddressRequired() == YesOrNo.NO) { + return postcodeValidator.validate( + Optional.ofNullable(caseData.getSpecAoSRespondentCorrespondenceAddressdetails()) + .map(Address::getPostCode) + .orElse(null) + ); + } else if (caseData.getIsRespondent2() == YesOrNo.YES + && caseData.getSpecAoSRespondent2CorrespondenceAddressRequired() == YesOrNo.NO) { + return postcodeValidator.validate( + Optional.ofNullable(caseData.getSpecAoSRespondent2CorrespondenceAddressdetails()) + .map(Address::getPostCode) + .orElse(null) + ); + } + return Collections.emptyList(); } private CallbackResponse resetStatementOfTruth(CallbackParams callbackParams) { @@ -524,10 +1603,10 @@ private boolean ifResponseTypeIsPartOrFullAdmission(CaseData caseData) { return (RespondentResponseTypeSpec.PART_ADMISSION.equals(caseData.getRespondent1ClaimResponseTypeForSpec()) || RespondentResponseTypeSpec.PART_ADMISSION.equals( caseData.getRespondent2ClaimResponseTypeForSpec()) - ) || (RespondentResponseTypeSpec.FULL_ADMISSION.equals(caseData.getRespondent1ClaimResponseTypeForSpec()) + ) || (RespondentResponseTypeSpec.FULL_ADMISSION.equals(caseData.getRespondent1ClaimResponseTypeForSpec()) || RespondentResponseTypeSpec.FULL_ADMISSION.equals( caseData.getRespondent2ClaimResponseTypeForSpec()) - ); + ); } private void updateCorrespondenceAddress(CallbackParams callbackParams, @@ -785,11 +1864,35 @@ private String getDefaultConfirmationBody(CaseData caseData) { } private CallbackResponse validateRespondentPaymentDate(CallbackParams callbackParams) { - return validateRespondentPaymentDate.execute(callbackParams); + + CaseData caseData = callbackParams.getCaseData(); + + List errors = paymentDateValidator + .validate(Optional.ofNullable(caseData.getRespondToClaimAdmitPartLRspec()) + .orElseGet(() -> RespondToClaimAdmitPartLRspec.builder().build())); + + return AboutToStartOrSubmitCallbackResponse.builder() + .errors(errors) + .build(); } private CallbackResponse validateLengthOfUnemployment(CallbackParams callbackParams) { - return validateLengthOfUnemployment.execute(callbackParams); + + CaseData caseData = callbackParams.getCaseData(); + List errors = new ArrayList<>(); + + if (caseData.getRespondToClaimAdmitPartUnemployedLRspec() != null + && caseData.getRespondToClaimAdmitPartUnemployedLRspec().getLengthOfUnemployment() != null + && caseData.getRespondToClaimAdmitPartUnemployedLRspec().getLengthOfUnemployment() + .getNumberOfYearsInUnemployment().contains(".") + || caseData.getRespondToClaimAdmitPartUnemployedLRspec() + .getLengthOfUnemployment().getNumberOfMonthsInUnemployment().contains(".")) { + errors.add("Length of time unemployed must be a whole number, for example, 10."); + } + + return AboutToStartOrSubmitCallbackResponse.builder() + .errors(errors) + .build(); } private CallbackResponse validateDefendant1RepaymentPlan(CallbackParams callbackParams) { @@ -816,6 +1919,29 @@ private CallbackResponse validateRepaymentPlan(RepaymentPlanLRspec repaymentPlan .build(); } + /** + * WhenWillClaimBePaid has to be shown if the respondent admits (full or part) and say they didn't pay. + * At the moment of writing, full admit doesn't ask for how much the respondent paid (if they say they paid) + * and part admit doesn't ask when will the amount be paid even if paid less. + * + * @param caseData claim data + * @return true if pageId WhenWillClaimBePaid must be shown + */ + public boolean mustWhenWillClaimBePaidBeShown(CaseData caseData) { + // 1v1 or 1v2 dif sol + if (caseData.getShowConditionFlags().contains(CAN_ANSWER_RESPONDENT_1)) { + // admit part not pay or admit full not pay + return caseData.getSpecDefenceFullAdmittedRequired() == NO + || caseData.getSpecDefenceAdmittedRequired() == NO; + } else if (caseData.getShowConditionFlags().contains(CAN_ANSWER_RESPONDENT_2)) { + // admit part not pay or admit full not pay + return caseData.getSpecDefenceFullAdmitted2Required() == NO + || caseData.getSpecDefenceAdmitted2Required() == NO; + } + + return false; + } + private void clearTempDocuments(CaseData.CaseDataBuilder builder) { CaseData caseData = builder.build(); // these documents are added to defendantUploads, if we do not remove/null the original, @@ -830,4 +1956,5 @@ private void clearTempDocuments(CaseData.CaseDataBuilder builder) { builder.respondent2DQ(builder.build().getRespondent2DQ().toBuilder().respondent2DQDraftDirections(null).build()); } } + }