From 656a710e17900a551761a02055f5b8d95bfc97f3 Mon Sep 17 00:00:00 2001 From: sankaviv1 <95748224+sankaviv1@users.noreply.github.com> Date: Thu, 14 Nov 2024 15:33:47 +0000 Subject: [PATCH] CIV-15557 DJ fixed costs changes (#5796) * CIV-9276 Claim issue changes for fixed costs * update test * checkstyle fix * update template mapping * CIV-15557 DJ Fixed costs changes * change judgment amount calculator logic * add comments to changes * point back to master --------- Co-authored-by: vasudevganesanhmcts <100689363+vasudevganesanhmcts@users.noreply.github.com> --- .../user/DefaultJudgementSpecHandler.java | 119 +++-- .../reform/civil/model/CaseDataParent.java | 3 + .../dj/DefaultJudgmentFormGenerator.java | 16 +- .../civil/utils/DefaultJudgmentUtils.java | 17 + .../user/DefaultJudgementSpecHandlerTest.java | 423 ++++++++++++++++++ .../dj/DefaultJudgmentFormGeneratorTest.java | 65 +++ .../civil/utils/DefaultJudgmentUtilsTest.java | 41 ++ 7 files changed, 657 insertions(+), 27 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/civil/handler/callback/user/DefaultJudgementSpecHandler.java b/src/main/java/uk/gov/hmcts/reform/civil/handler/callback/user/DefaultJudgementSpecHandler.java index 7194dc9c9e4..6f744ca582f 100644 --- a/src/main/java/uk/gov/hmcts/reform/civil/handler/callback/user/DefaultJudgementSpecHandler.java +++ b/src/main/java/uk/gov/hmcts/reform/civil/handler/callback/user/DefaultJudgementSpecHandler.java @@ -53,6 +53,7 @@ import static uk.gov.hmcts.reform.civil.helpers.DateFormatHelper.formatLocalDate; import static uk.gov.hmcts.reform.civil.helpers.DateFormatHelper.formatLocalDateTime; import static uk.gov.hmcts.reform.civil.utils.DefaultJudgmentUtils.calculateFixedCosts; +import static uk.gov.hmcts.reform.civil.utils.DefaultJudgmentUtils.calculateFixedCostsOnEntry; import static uk.gov.hmcts.reform.civil.utils.ElementUtils.element; import static uk.gov.hmcts.reform.civil.utils.PartyUtils.getPartyNameBasedOnType; import static uk.gov.hmcts.reform.civil.utils.PersistDataUtils.persistFlagsForParties; @@ -269,8 +270,48 @@ private CallbackResponse partialPayment(CallbackParams callbackParams) { } } + if (!errors.isEmpty()) { + return AboutToStartOrSubmitCallbackResponse.builder() + .errors(errors) + .build(); + } + + CaseData.CaseDataBuilder caseDataBuilder = caseData.toBuilder(); + + // show old fixed costs screen if claim was created before new fixed + // costs screen at claim issue was released + if (caseData.getFixedCosts() == null) { + caseDataBuilder.showOldDJFixedCostsScreen(YesOrNo.YES); + } + + // otherwise show new dj fixed costs screen if judgment amount is more + // than 25. judgment amount = claim amount + interest - partial amount + if (caseData.getFixedCosts() != null) { + BigDecimal judgmentAmount = calculateJudgmentAmountForFixedCosts(caseData); + if (YesOrNo.YES.equals(caseData.getFixedCosts().getClaimFixedCosts())) { + if (judgmentAmount.compareTo(BigDecimal.valueOf(25)) > 0) { + caseDataBuilder.showDJFixedCostsScreen(YesOrNo.YES); + } else { + caseDataBuilder.showDJFixedCostsScreen(YesOrNo.NO); + } + } + // if case is applicable to new fixed costs but new screen will not + // be shown due to the above conditions, then skip straight to + // repayment breakdown screen + if (caseDataBuilder.build().getShowDJFixedCostsScreen() == null + || YesOrNo.NO.equals(caseDataBuilder.build().getShowDJFixedCostsScreen())) { + // calculate repayment breakdown + StringBuilder repaymentBreakdown = buildRepaymentBreakdown( + caseData, + callbackParams); + + caseDataBuilder.repaymentSummaryObject(repaymentBreakdown.toString()); + } + } + return AboutToStartOrSubmitCallbackResponse.builder() .errors(errors) + .data(caseDataBuilder.build().toMap(objectMapper)) .build(); } @@ -296,24 +337,10 @@ private CallbackResponse repaymentBreakdownCalculate(CallbackParams callbackPara CaseData caseData = callbackParams.getCaseData(); CaseData.CaseDataBuilder caseDataBuilder = caseData.toBuilder(); - BigDecimal interest = interestCalculator.calculateInterest(caseData); - BigDecimal totalInterest = caseData.getTotalInterest() != null ? caseData.getTotalInterest() : BigDecimal.ZERO; - var claimWithInterest = caseData.getTotalClaimAmount().add(totalInterest); - var claimfee = feesService.getFeeDataByTotalClaimAmount(claimWithInterest); - BigDecimal claimFeePounds; - if (caseData.getOutstandingFeeInPounds() != null) { - claimFeePounds = caseData.getOutstandingFeeInPounds(); - } else { - claimFeePounds = MonetaryConversions.penniesToPounds(claimfee.getCalculatedAmountInPence()); - } - BigDecimal fixedCost = calculateFixedCosts(caseData); + StringBuilder repaymentBreakdown = buildRepaymentBreakdown( caseData, - interest, - claimFeePounds, - fixedCost, - callbackParams - ); + callbackParams); caseDataBuilder.repaymentSummaryObject(repaymentBreakdown.toString()); return AboutToStartOrSubmitCallbackResponse.builder() @@ -322,19 +349,32 @@ private CallbackResponse repaymentBreakdownCalculate(CallbackParams callbackPara } @NotNull - private StringBuilder buildRepaymentBreakdown(CaseData caseData, BigDecimal interest, BigDecimal claimFeePounds, - BigDecimal fixedCost, CallbackParams callbackParams) { + private StringBuilder buildRepaymentBreakdown(CaseData caseData, CallbackParams callbackParams) { + + BigDecimal interest = interestCalculator.calculateInterest(caseData); + BigDecimal totalInterest = caseData.getTotalInterest() != null ? caseData.getTotalInterest() : BigDecimal.ZERO; + var claimWithInterest = caseData.getTotalClaimAmount().add(totalInterest); + var claimfee = feesService.getFeeDataByTotalClaimAmount(claimWithInterest); + BigDecimal claimFeePounds; + if (caseData.getOutstandingFeeInPounds() != null) { + claimFeePounds = caseData.getOutstandingFeeInPounds(); + } else { + claimFeePounds = MonetaryConversions.penniesToPounds(claimfee.getCalculatedAmountInPence()); + } + BigDecimal fixedCost = BigDecimal.valueOf(0); + if (caseData.getFixedCosts() == null) { + fixedCost = calculateFixedCosts(caseData); + } else { + if (caseData.getFixedCosts() != null && caseData.getFixedCosts().getFixedCostAmount() != null) { + fixedCost = calculateFixedCostsOnEntry(caseData, calculateJudgmentAmountForFixedCosts(caseData)); + } + } BigDecimal partialPaymentPounds = getPartialPayment(caseData); //calculate the relevant total, total claim value + interest if any, claim fee for case, // and subtract any partial payment - var subTotal = caseData.getTotalClaimAmount() - .add(interest) - .add(claimFeePounds); - if (caseData.getPaymentConfirmationDecisionSpec() == YesOrNo.YES) { - subTotal = subTotal.add(fixedCost); - } - theOverallTotal = subTotal.subtract(partialPaymentPounds); + BigDecimal subTotal = getSubTotal(caseData, interest, claimFeePounds, fixedCost); + theOverallTotal = calculateOverallTotal(partialPaymentPounds, subTotal); //creates the text on the page, based on calculated values StringBuilder repaymentBreakdown = new StringBuilder(); if (caseData.isLRvLipOneVOne() @@ -360,7 +400,9 @@ private StringBuilder buildRepaymentBreakdown(CaseData caseData, BigDecimal inte repaymentBreakdown.append("\n ### Claim interest amount \n").append("£").append(interest.setScale(2)); } - if (caseData.getPaymentConfirmationDecisionSpec() == YesOrNo.YES) { + if ((caseData.getFixedCosts() != null + && YesOrNo.YES.equals(caseData.getFixedCosts().getClaimFixedCosts())) + || caseData.getPaymentConfirmationDecisionSpec() == YesOrNo.YES) { repaymentBreakdown.append("\n ### Fixed cost amount \n").append("£").append(fixedCost.setScale(2)); } repaymentBreakdown.append("\n").append("### Claim fee amount \n £").append(claimFeePounds.setScale(2)).append( @@ -376,6 +418,19 @@ private StringBuilder buildRepaymentBreakdown(CaseData caseData, BigDecimal inte return repaymentBreakdown; } + @NotNull + private BigDecimal getSubTotal(CaseData caseData, BigDecimal interest, BigDecimal claimFeePounds, BigDecimal fixedCost) { + var subTotal = caseData.getTotalClaimAmount() + .add(interest) + .add(claimFeePounds); + if (caseData.getPaymentConfirmationDecisionSpec() == YesOrNo.YES + || (caseData.getFixedCosts() != null + && YesOrNo.YES.equals(caseData.getFixedCosts().getClaimFixedCosts()))) { + subTotal = subTotal.add(fixedCost); + } + return subTotal; + } + private BigDecimal getPartialPayment(CaseData caseData) { BigDecimal partialPaymentPounds = new BigDecimal(0); @@ -454,6 +509,18 @@ private CallbackResponse generateClaimForm(CallbackParams callbackParams) { .state(nextState) .build(); } + + private BigDecimal calculateOverallTotal(BigDecimal partialPaymentPounds, BigDecimal subTotal) { + return subTotal.subtract(partialPaymentPounds); + } + + private BigDecimal calculateJudgmentAmountForFixedCosts(CaseData caseData) { + BigDecimal interest = interestCalculator.calculateInterest(caseData); + + BigDecimal subTotal = caseData.getTotalClaimAmount().add(interest); + BigDecimal partialPaymentPounds = getPartialPayment(caseData); + return calculateOverallTotal(partialPaymentPounds, subTotal); + } } 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 222494e9727..92b37fb7f44 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 @@ -482,6 +482,9 @@ public boolean isApplicantRepresented() { private SmallClaimsMediation smallClaimsMediationSectionStatement; private FixedCosts fixedCosts; + private YesOrNo showDJFixedCostsScreen; + private YesOrNo showOldDJFixedCostsScreen; + private YesOrNo claimFixedCostsOnEntryDJ; @JsonIgnore public boolean isResponseAcceptedByClaimant() { diff --git a/src/main/java/uk/gov/hmcts/reform/civil/service/docmosis/dj/DefaultJudgmentFormGenerator.java b/src/main/java/uk/gov/hmcts/reform/civil/service/docmosis/dj/DefaultJudgmentFormGenerator.java index b0a98112553..93daf32127c 100644 --- a/src/main/java/uk/gov/hmcts/reform/civil/service/docmosis/dj/DefaultJudgmentFormGenerator.java +++ b/src/main/java/uk/gov/hmcts/reform/civil/service/docmosis/dj/DefaultJudgmentFormGenerator.java @@ -25,6 +25,7 @@ import uk.gov.hmcts.reform.civil.service.docmosis.DocumentGeneratorService; import uk.gov.hmcts.reform.civil.service.docmosis.TemplateDataGenerator; import uk.gov.hmcts.reform.civil.utils.AssignCategoryId; +import uk.gov.hmcts.reform.civil.utils.DefaultJudgmentUtils; import uk.gov.hmcts.reform.civil.utils.InterestCalculator; import uk.gov.hmcts.reform.civil.utils.MonetaryConversions; @@ -284,8 +285,21 @@ private BigDecimal getClaimFee(CaseData caseData) { claimFeePounds = caseData.getOutstandingFeeInPounds(); } - if (caseData.getPaymentConfirmationDecisionSpec() == YesOrNo.YES) { + if (caseData.getPaymentConfirmationDecisionSpec() == YesOrNo.YES + && caseData.getFixedCosts() == null) { claimFeePounds = claimFeePounds.add(calculateFixedCosts(caseData)); + } else if (caseData.getFixedCosts() != null) { + // if new mandatory fixed costs question was answered at claim issue + if (YesOrNo.YES.equals(caseData.getClaimFixedCostsOnEntryDJ())) { + // if new fixed costs was chosen in DJ + claimFeePounds = claimFeePounds.add(DefaultJudgmentUtils.calculateFixedCostsOnEntry( + caseData, JudgmentsOnlineHelper.getDebtAmount(caseData, interestCalculator))); + } else if (YesOrNo.YES.equals(caseData.getFixedCosts().getClaimFixedCosts())) { + // only claimed new fixed costs at claim issue + claimFeePounds = claimFeePounds.add(MonetaryConversions.penniesToPounds( + BigDecimal.valueOf(Integer.parseInt( + caseData.getFixedCosts().getFixedCostAmount())))); + } } return claimFeePounds.equals(BigDecimal.ZERO) ? BigDecimal.ZERO : claimFeePounds.setScale(2); } diff --git a/src/main/java/uk/gov/hmcts/reform/civil/utils/DefaultJudgmentUtils.java b/src/main/java/uk/gov/hmcts/reform/civil/utils/DefaultJudgmentUtils.java index e130ffda369..88cd1993eff 100644 --- a/src/main/java/uk/gov/hmcts/reform/civil/utils/DefaultJudgmentUtils.java +++ b/src/main/java/uk/gov/hmcts/reform/civil/utils/DefaultJudgmentUtils.java @@ -1,5 +1,6 @@ package uk.gov.hmcts.reform.civil.utils; +import uk.gov.hmcts.reform.civil.enums.YesOrNo; import uk.gov.hmcts.reform.civil.model.CaseData; import java.math.BigDecimal; @@ -13,6 +14,9 @@ public class DefaultJudgmentUtils { private static final int ENTRY_FIXED_COST_22 = 22; private static final int ENTRY_FIXED_COST_30 = 30; + private static final BigDecimal JUDGMENT_AMOUNT_5000 = BigDecimal.valueOf(5000); + private static final BigDecimal JUDGMENT_AMOUNT_25 = BigDecimal.valueOf(25); + private DefaultJudgmentUtils() { } @@ -35,4 +39,17 @@ public static BigDecimal calculateFixedCosts(CaseData caseData) { } return new BigDecimal(fixedCost); } + + public static BigDecimal calculateFixedCostsOnEntry(CaseData caseData, BigDecimal judgmentAmount) { + BigDecimal claimIssueFixedCost = MonetaryConversions.penniesToPounds(BigDecimal.valueOf( + Integer.parseInt(caseData.getFixedCosts().getFixedCostAmount()))); + if (YesOrNo.YES.equals(caseData.getClaimFixedCostsOnEntryDJ())) { + if (judgmentAmount.compareTo(JUDGMENT_AMOUNT_5000) > 0) { + return claimIssueFixedCost.add(BigDecimal.valueOf(ENTRY_FIXED_COST_30)); + } else if (judgmentAmount.compareTo(JUDGMENT_AMOUNT_25) > 0) { + return claimIssueFixedCost.add(BigDecimal.valueOf(ENTRY_FIXED_COST_22)); + } + } + return claimIssueFixedCost; + } } diff --git a/src/test/java/uk/gov/hmcts/reform/civil/handler/callback/user/DefaultJudgementSpecHandlerTest.java b/src/test/java/uk/gov/hmcts/reform/civil/handler/callback/user/DefaultJudgementSpecHandlerTest.java index 650ed69438d..3c9ead6cd7c 100644 --- a/src/test/java/uk/gov/hmcts/reform/civil/handler/callback/user/DefaultJudgementSpecHandlerTest.java +++ b/src/test/java/uk/gov/hmcts/reform/civil/handler/callback/user/DefaultJudgementSpecHandlerTest.java @@ -22,6 +22,7 @@ import uk.gov.hmcts.reform.civil.helpers.judgmentsonline.DefaultJudgmentOnlineMapper; import uk.gov.hmcts.reform.civil.model.CaseData; import uk.gov.hmcts.reform.civil.model.Fee; +import uk.gov.hmcts.reform.civil.model.FixedCosts; import uk.gov.hmcts.reform.civil.model.Party; import uk.gov.hmcts.reform.civil.model.breathing.BreathingSpaceEnterInfo; import uk.gov.hmcts.reform.civil.model.breathing.BreathingSpaceInfo; @@ -503,6 +504,139 @@ void shouldNotReturnError_whenPartialPaymentLessFullClaim() { var response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); assertThat(response.getErrors()).isEmpty(); } + + @Test + void shouldShowOldFixedCostsPage_whenNoErrorsAndPreClaimIssueFixedCosts() { + BigDecimal claimAmount = new BigDecimal(2000); + BigDecimal interestAmount = new BigDecimal(100); + + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged().build().toBuilder() + .respondent1ResponseDeadline(LocalDateTime.now().minusDays(15)) + .partialPayment(YesOrNo.YES) + .totalClaimAmount(claimAmount) + .totalInterest(interestAmount) + .partialPaymentAmount("3000") + .build(); + + CallbackParams params = callbackParamsOf(caseData, MID, PAGE_ID); + var response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); + assertThat(response.getData().get("showOldDJFixedCostsScreen")).isEqualTo("Yes"); + assertThat(response.getData().get("repaymentSummaryObject")).isNull(); + } + + @Test + void shouldShowNewFixedCostsPage_whenNoErrorsAndJudgmentAmountMoreThan25AndYesClaimIssueFixedCosts() { + BigDecimal claimAmount = new BigDecimal(2000); + BigDecimal interestAmount = new BigDecimal(100); + when(interestCalculator.calculateInterest(any())) + .thenReturn(BigDecimal.valueOf(1)); + when(feesService.getFeeDataByTotalClaimAmount(any())) + .thenReturn(Fee.builder() + .calculatedAmountInPence(BigDecimal.valueOf(1)) + .version("1") + .code("CODE") + .build()); + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged().build().toBuilder() + .respondent1ResponseDeadline(LocalDateTime.now().minusDays(15)) + .partialPayment(YES) + .totalClaimAmount(claimAmount) + .totalInterest(interestAmount) + .claimFee(Fee.builder() + .calculatedAmountInPence(BigDecimal.valueOf(1)) + .build()) + .fixedCosts(FixedCosts.builder() + .claimFixedCosts(YES) + .fixedCostAmount("10000") + .build()) + .partialPaymentAmount("3000") + .build(); + + CallbackParams params = callbackParamsOf(caseData, MID, PAGE_ID); + var response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); + + assertThat(response.getData().get("showOldDJFixedCostsScreen")).isNull(); + assertThat(response.getData().get("showDJFixedCostsScreen")).isEqualTo("Yes"); + assertThat(response.getData().get("repaymentSummaryObject")).isNull(); + } + + @Test + void shouldNotShowNewFixedCostsPage_whenJudgmentAmountLessThan25AndYesClaimIssueFixedCostsAndCalculateRepaymentBreakdown() { + BigDecimal claimAmount = new BigDecimal(2000); + BigDecimal interestAmount = new BigDecimal(100); + when(interestCalculator.calculateInterest(any())) + .thenReturn(BigDecimal.valueOf(1)); + when(feesService.getFeeDataByTotalClaimAmount(any())) + .thenReturn(Fee.builder() + .calculatedAmountInPence(BigDecimal.valueOf(1)) + .version("1") + .code("CODE") + .build()); + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged().build().toBuilder() + .respondent1ResponseDeadline(LocalDateTime.now().minusDays(15)) + .partialPayment(YES) + .totalClaimAmount(claimAmount) + .totalInterest(interestAmount) + .defendantDetailsSpec(DynamicList.builder() + .value(DynamicListElement.builder() + .label("Test User") + .build()) + .build()) + .claimFee(Fee.builder() + .calculatedAmountInPence(BigDecimal.valueOf(1)) + .build()) + .fixedCosts(FixedCosts.builder() + .claimFixedCosts(YES) + .fixedCostAmount("10000") + .build()) + .partialPaymentAmount("209000") + .build(); + + CallbackParams params = callbackParamsOf(caseData, MID, PAGE_ID); + var response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); + + assertThat(response.getData().get("showOldDJFixedCostsScreen")).isNull(); + assertThat(response.getData().get("showDJFixedCostsScreen")).isEqualTo("No"); + assertThat(response.getData().get("repaymentSummaryObject")).isNotNull(); + } + + @Test + void shouldNotShowNewFixedCostsPage_whenNoErrorsAndNoClaimIssueFixedCosts() { + BigDecimal claimAmount = new BigDecimal(2000); + BigDecimal interestAmount = new BigDecimal(100); + when(interestCalculator.calculateInterest(any())) + .thenReturn(BigDecimal.valueOf(1)); + when(feesService.getFeeDataByTotalClaimAmount(any())) + .thenReturn(Fee.builder() + .calculatedAmountInPence(BigDecimal.valueOf(1)) + .version("1") + .code("CODE") + .build()); + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged().build().toBuilder() + .respondent1ResponseDeadline(LocalDateTime.now().minusDays(15)) + .partialPayment(YES) + .totalClaimAmount(claimAmount) + .totalInterest(interestAmount) + .defendantDetailsSpec(DynamicList.builder() + .value(DynamicListElement.builder() + .label("Test User") + .build()) + .build()) + .claimFee(Fee.builder() + .calculatedAmountInPence(BigDecimal.valueOf(1)) + .build()) + .fixedCosts(FixedCosts.builder() + .claimFixedCosts(NO) + .build()) + .partialPaymentAmount("209000") + .build(); + + CallbackParams params = callbackParamsOf(caseData, MID, PAGE_ID); + var response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); + + assertThat(response.getData().get("showOldDJFixedCostsScreen")).isNull(); + assertThat(response.getData().get("showDJFixedCostsScreen")).isNull(); + assertThat(response.getData().get("repaymentSummaryObject")).isNotNull(); + } } @Nested @@ -622,6 +756,295 @@ class RepaymentBreakdownCallback { private static final String PAGE_ID = "repaymentBreakdown"; + @Test + void shouldReturnFixedAmount_whenJudgmentAmountGreaterThan5000AndClaimIssueFixedCostsYesClaimDJFixedCosts() { + when(interestCalculator.calculateInterest(any())) + .thenReturn(BigDecimal.valueOf(0) + ); + when(feesService.getFeeDataByTotalClaimAmount(any())) + .thenReturn(Fee.builder() + .calculatedAmountInPence(BigDecimal.valueOf(100)) + .version("1") + .code("CODE") + .build()); + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged().build().toBuilder() + .respondent1ResponseDeadline(LocalDateTime.now().minusDays(15)) + .partialPayment(YES) + .paymentSetDate(LocalDate.now().minusDays(15)) + .partialPaymentAmount("100") + .totalClaimAmount(BigDecimal.valueOf(5002)) + .fixedCosts(FixedCosts.builder() + .claimFixedCosts(YES) + .fixedCostAmount("10000") + .build()) + .claimFixedCostsOnEntryDJ(YES) + .defendantDetailsSpec(DynamicList.builder() + .value(DynamicListElement.builder() + .label("Test User") + .build()) + .build()) + .build(); + CallbackParams params = callbackParamsOf(caseData, MID, PAGE_ID); + var response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); + String test = "The judgment will order " + caseData.getDefendantDetailsSpec().getValue().getLabel() + + " to pay £5132.00, including the claim fee and" + + " interest, if applicable, as shown:\n" + + "### Claim amount \n" + + " £5002.00\n" + + " ### Fixed cost amount \n" + + "£130.00\n" + + "### Claim fee amount \n" + + " £1.00\n" + + " ## Subtotal \n" + + " £5133.00\n" + + "\n" + + " ### Amount already paid \n" + + "£1.00\n" + + " ## Total still owed \n" + + " £5132.00"; + assertThat(response.getData().get("repaymentSummaryObject")).isEqualTo(test); + } + + @Test + void shouldReturnFixedAmount_whenJudgmentAmountGreaterThan5000AndClaimIssueFixedCostsYesAndClaimDJFixedCostsNo() { + when(interestCalculator.calculateInterest(any())) + .thenReturn(BigDecimal.valueOf(0) + ); + when(feesService.getFeeDataByTotalClaimAmount(any())) + .thenReturn(Fee.builder() + .calculatedAmountInPence(BigDecimal.valueOf(100)) + .version("1") + .code("CODE") + .build()); + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged().build().toBuilder() + .respondent1ResponseDeadline(LocalDateTime.now().minusDays(15)) + .partialPayment(YES) + .paymentSetDate(LocalDate.now().minusDays(15)) + .partialPaymentAmount("100") + .totalClaimAmount(BigDecimal.valueOf(5001)) + .fixedCosts(FixedCosts.builder() + .claimFixedCosts(YES) + .fixedCostAmount("10000") + .build()) + .claimFixedCostsOnEntryDJ(NO) + .defendantDetailsSpec(DynamicList.builder() + .value(DynamicListElement.builder() + .label("Test User") + .build()) + .build()) + .build(); + CallbackParams params = callbackParamsOf(caseData, MID, PAGE_ID); + var response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); + String test = "The judgment will order " + caseData.getDefendantDetailsSpec().getValue().getLabel() + + " to pay £5101.00, including the claim fee and" + + " interest, if applicable, as shown:\n" + + "### Claim amount \n" + + " £5001.00\n" + + " ### Fixed cost amount \n" + + "£100.00\n" + + "### Claim fee amount \n" + + " £1.00\n" + + " ## Subtotal \n" + + " £5102.00\n" + + "\n" + + " ### Amount already paid \n" + + "£1.00\n" + + " ## Total still owed \n" + + " £5101.00"; + assertThat(response.getData().get("repaymentSummaryObject")).isEqualTo(test); + } + + @Test + void shouldReturnFixedAmount_whenJudgmentAmountMoreThan25LessThan5000AndClaimIssueFixedCostsYesClaimDJFixedCosts() { + when(interestCalculator.calculateInterest(any())) + .thenReturn(BigDecimal.valueOf(0) + ); + when(feesService.getFeeDataByTotalClaimAmount(any())) + .thenReturn(Fee.builder() + .calculatedAmountInPence(BigDecimal.valueOf(100)) + .version("1") + .code("CODE") + .build()); + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged().build().toBuilder() + .respondent1ResponseDeadline(LocalDateTime.now().minusDays(15)) + .partialPayment(YES) + .paymentSetDate(LocalDate.now().minusDays(15)) + .partialPaymentAmount("100") + .totalClaimAmount(BigDecimal.valueOf(3001)) + .fixedCosts(FixedCosts.builder() + .claimFixedCosts(YES) + .fixedCostAmount("10000") + .build()) + .claimFixedCostsOnEntryDJ(YES) + .defendantDetailsSpec(DynamicList.builder() + .value(DynamicListElement.builder() + .label("Test User") + .build()) + .build()) + .build(); + CallbackParams params = callbackParamsOf(caseData, MID, PAGE_ID); + var response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); + String test = "The judgment will order " + caseData.getDefendantDetailsSpec().getValue().getLabel() + + " to pay £3123.00, including the claim fee and" + + " interest, if applicable, as shown:\n" + + "### Claim amount \n" + + " £3001.00\n" + + " ### Fixed cost amount \n" + + "£122.00\n" + + "### Claim fee amount \n" + + " £1.00\n" + + " ## Subtotal \n" + + " £3124.00\n" + + "\n" + + " ### Amount already paid \n" + + "£1.00\n" + + " ## Total still owed \n" + + " £3123.00"; + assertThat(response.getData().get("repaymentSummaryObject")).isEqualTo(test); + } + + @Test + void shouldReturnFixedAmount_whenJudgmentAmountMoreThan25LessThan5000AndClaimIssueFixedCostsYesAndNoClaimDJFixedCosts() { + when(interestCalculator.calculateInterest(any())) + .thenReturn(BigDecimal.valueOf(0) + ); + when(feesService.getFeeDataByTotalClaimAmount(any())) + .thenReturn(Fee.builder() + .calculatedAmountInPence(BigDecimal.valueOf(100)) + .version("1") + .code("CODE") + .build()); + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged().build().toBuilder() + .respondent1ResponseDeadline(LocalDateTime.now().minusDays(15)) + .partialPayment(YES) + .paymentSetDate(LocalDate.now().minusDays(15)) + .partialPaymentAmount("100") + .totalClaimAmount(BigDecimal.valueOf(3001)) + .fixedCosts(FixedCosts.builder() + .claimFixedCosts(YES) + .fixedCostAmount("10000") + .build()) + .claimFixedCostsOnEntryDJ(NO) + .defendantDetailsSpec(DynamicList.builder() + .value(DynamicListElement.builder() + .label("Test User") + .build()) + .build()) + .build(); + CallbackParams params = callbackParamsOf(caseData, MID, PAGE_ID); + var response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); + String test = "The judgment will order " + caseData.getDefendantDetailsSpec().getValue().getLabel() + + " to pay £3101.00, including the claim fee and" + + " interest, if applicable, as shown:\n" + + "### Claim amount \n" + + " £3001.00\n" + + " ### Fixed cost amount \n" + + "£100.00\n" + + "### Claim fee amount \n" + + " £1.00\n" + + " ## Subtotal \n" + + " £3102.00\n" + + "\n" + + " ### Amount already paid \n" + + "£1.00\n" + + " ## Total still owed \n" + + " £3101.00"; + assertThat(response.getData().get("repaymentSummaryObject")).isEqualTo(test); + } + + @Test + void shouldReturnFixedAmount_whenJudgmentAmountLessThan25AndClaimIssueFixedCostsYes() { + when(interestCalculator.calculateInterest(any())) + .thenReturn(BigDecimal.valueOf(0) + ); + when(feesService.getFeeDataByTotalClaimAmount(any())) + .thenReturn(Fee.builder() + .calculatedAmountInPence(BigDecimal.valueOf(100)) + .version("1") + .code("CODE") + .build()); + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged().build().toBuilder() + .respondent1ResponseDeadline(LocalDateTime.now().minusDays(15)) + .partialPayment(YES) + .paymentSetDate(LocalDate.now().minusDays(15)) + .partialPaymentAmount("299500") + .totalClaimAmount(BigDecimal.valueOf(3000)) + .fixedCosts(FixedCosts.builder() + .claimFixedCosts(YES) + .fixedCostAmount("10000") + .build()) + .defendantDetailsSpec(DynamicList.builder() + .value(DynamicListElement.builder() + .label("Test User") + .build()) + .build()) + .build(); + CallbackParams params = callbackParamsOf(caseData, MID, PAGE_ID); + var response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); + String test = "The judgment will order " + caseData.getDefendantDetailsSpec().getValue().getLabel() + + " to pay £106.00, including the claim fee and" + + " interest, if applicable, as shown:\n" + + "### Claim amount \n" + + " £3000.00\n" + + " ### Fixed cost amount \n" + + "£100.00\n" + + "### Claim fee amount \n" + + " £1.00\n" + + " ## Subtotal \n" + + " £3101.00\n" + + "\n" + + " ### Amount already paid \n" + + "£2995.00\n" + + " ## Total still owed \n" + + " £106.00"; + assertThat(response.getData().get("repaymentSummaryObject")).isEqualTo(test); + } + + @Test + void shouldReturnFixedAmount_whenJudgmentAmountLessThan25AndClaimIssueFixedCostsNo() { + when(interestCalculator.calculateInterest(any())) + .thenReturn(BigDecimal.valueOf(0) + ); + when(feesService.getFeeDataByTotalClaimAmount(any())) + .thenReturn(Fee.builder() + .calculatedAmountInPence(BigDecimal.valueOf(100)) + .version("1") + .code("CODE") + .build()); + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged().build().toBuilder() + .respondent1ResponseDeadline(LocalDateTime.now().minusDays(15)) + .partialPayment(YES) + .paymentSetDate(LocalDate.now().minusDays(15)) + .partialPaymentAmount("299500") + .totalClaimAmount(BigDecimal.valueOf(3000)) + .fixedCosts(FixedCosts.builder() + .claimFixedCosts(NO) + .build()) + .defendantDetailsSpec(DynamicList.builder() + .value(DynamicListElement.builder() + .label("Test User") + .build()) + .build()) + .build(); + CallbackParams params = callbackParamsOf(caseData, MID, PAGE_ID); + var response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); + String test = "The judgment will order " + caseData.getDefendantDetailsSpec().getValue().getLabel() + + " to pay £6.00, including the claim fee and" + + " interest, if applicable, as shown:\n" + + "### Claim amount \n" + + " £3000.00\n" + + "### Claim fee amount \n" + + " £1.00\n" + + " ## Subtotal \n" + + " £3001.00\n" + + "\n" + + " ### Amount already paid \n" + + "£2995.00\n" + + " ## Total still owed \n" + + " £6.00"; + assertThat(response.getData().get("repaymentSummaryObject")).isEqualTo(test); + } + @Test void shouldReturnFixedAmount_whenClaimAmountLessthan5000() { when(interestCalculator.calculateInterest(any())) diff --git a/src/test/java/uk/gov/hmcts/reform/civil/service/docmosis/dj/DefaultJudgmentFormGeneratorTest.java b/src/test/java/uk/gov/hmcts/reform/civil/service/docmosis/dj/DefaultJudgmentFormGeneratorTest.java index c27cde76b90..debcd795a97 100644 --- a/src/test/java/uk/gov/hmcts/reform/civil/service/docmosis/dj/DefaultJudgmentFormGeneratorTest.java +++ b/src/test/java/uk/gov/hmcts/reform/civil/service/docmosis/dj/DefaultJudgmentFormGeneratorTest.java @@ -16,6 +16,7 @@ import uk.gov.hmcts.reform.civil.enums.YesOrNo; import uk.gov.hmcts.reform.civil.model.CaseData; import uk.gov.hmcts.reform.civil.model.Fee; +import uk.gov.hmcts.reform.civil.model.FixedCosts; import uk.gov.hmcts.reform.civil.model.citizenui.CaseDataLiP; import uk.gov.hmcts.reform.civil.model.citizenui.HelpWithFees; import uk.gov.hmcts.reform.civil.model.citizenui.HelpWithFeesDetails; @@ -209,6 +210,70 @@ void shouldDefaultJudgmentFormGeneratorOneForm_whenFixedAmountCostSelected() { } + @Test + void shouldDefaultJudgmentFormGeneratorOneForm_whenFixedCostsAtClaimIssueOnly() { + when(documentGeneratorService.generateDocmosisDocument(any(MappableObject.class), eq(N121_SPEC))) + .thenReturn(new DocmosisDocument(N121_SPEC.getDocumentTitle(), bytes)); + + when(documentManagementService + .uploadDocument(BEARER_TOKEN, new PDF(fileName, bytes, DEFAULT_JUDGMENT))) + .thenReturn(CASE_DOCUMENT); + + when(interestCalculator.calculateInterest(any(CaseData.class))) + .thenReturn(new BigDecimal(10)); + + when(feesService.getFeeDataByTotalClaimAmount(new BigDecimal(2000))) + .thenReturn(Fee.builder().calculatedAmountInPence(new BigDecimal(10)).build()); + + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged().build().toBuilder() + .totalClaimAmount(new BigDecimal(2000)) + .fixedCosts(FixedCosts.builder() + .claimFixedCosts(YesOrNo.YES) + .fixedCostAmount("10000") + .build()) + .claimFixedCostsOnEntryDJ(YesOrNo.NO) + .caseDataLiP(CaseDataLiP.builder().helpWithFees(HelpWithFees.builder().helpWithFee(YesOrNo.NO).build()).build()) + .build(); + List caseDocuments = generator.generate(caseData, BEARER_TOKEN, GENERATE_DJ_FORM_SPEC.name()); + + assertThat(caseDocuments.size()).isEqualTo(1); + + verify(documentManagementService) + .uploadDocument(BEARER_TOKEN, new PDF(fileName, bytes, DEFAULT_JUDGMENT)); + } + + @Test + void shouldDefaultJudgmentFormGeneratorOneForm_whenFixedCostsAtClaimIssueAndDJ() { + when(documentGeneratorService.generateDocmosisDocument(any(MappableObject.class), eq(N121_SPEC))) + .thenReturn(new DocmosisDocument(N121_SPEC.getDocumentTitle(), bytes)); + + when(documentManagementService + .uploadDocument(BEARER_TOKEN, new PDF(fileName, bytes, DEFAULT_JUDGMENT))) + .thenReturn(CASE_DOCUMENT); + + when(interestCalculator.calculateInterest(any(CaseData.class))) + .thenReturn(new BigDecimal(10)); + + when(feesService.getFeeDataByTotalClaimAmount(new BigDecimal(2000))) + .thenReturn(Fee.builder().calculatedAmountInPence(new BigDecimal(10)).build()); + + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged().build().toBuilder() + .totalClaimAmount(new BigDecimal(2000)) + .fixedCosts(FixedCosts.builder() + .claimFixedCosts(YesOrNo.YES) + .fixedCostAmount("10000") + .build()) + .claimFixedCostsOnEntryDJ(YesOrNo.YES) + .caseDataLiP(CaseDataLiP.builder().helpWithFees(HelpWithFees.builder().helpWithFee(YesOrNo.NO).build()).build()) + .build(); + List caseDocuments = generator.generate(caseData, BEARER_TOKEN, GENERATE_DJ_FORM_SPEC.name()); + + assertThat(caseDocuments.size()).isEqualTo(1); + + verify(documentManagementService) + .uploadDocument(BEARER_TOKEN, new PDF(fileName, bytes, DEFAULT_JUDGMENT)); + } + @Test void shouldDefaultJudgmentFormGeneratorTwoForms_whenValidDataIsProvided() { when(documentGeneratorService.generateDocmosisDocument(any(MappableObject.class), eq(N121_SPEC))) diff --git a/src/test/java/uk/gov/hmcts/reform/civil/utils/DefaultJudgmentUtilsTest.java b/src/test/java/uk/gov/hmcts/reform/civil/utils/DefaultJudgmentUtilsTest.java index 74b89fe1ea4..eee885d4bda 100644 --- a/src/test/java/uk/gov/hmcts/reform/civil/utils/DefaultJudgmentUtilsTest.java +++ b/src/test/java/uk/gov/hmcts/reform/civil/utils/DefaultJudgmentUtilsTest.java @@ -3,12 +3,14 @@ import org.junit.jupiter.api.Test; import uk.gov.hmcts.reform.civil.enums.YesOrNo; import uk.gov.hmcts.reform.civil.model.CaseData; +import uk.gov.hmcts.reform.civil.model.FixedCosts; import uk.gov.hmcts.reform.civil.sampledata.CaseDataBuilder; import java.math.BigDecimal; import static org.assertj.core.api.Assertions.assertThat; import static uk.gov.hmcts.reform.civil.utils.DefaultJudgmentUtils.calculateFixedCosts; +import static uk.gov.hmcts.reform.civil.utils.DefaultJudgmentUtils.calculateFixedCostsOnEntry; public class DefaultJudgmentUtilsTest { @@ -56,4 +58,43 @@ void shouldReturnFixedCost_whenClaimAmountIsInFourthInstalment() { BigDecimal result = calculateFixedCosts(caseData); assertThat(result).isEqualTo(new BigDecimal(140)); } + + @Test + void shouldReturnFixedCostOnEntry_whenJudgmentAmountIsMoreThan5000() { + CaseData caseData = CaseDataBuilder.builder().atStateClaimDetailsNotified().build().toBuilder() + .addRespondent2(YesOrNo.NO) + .claimFixedCostsOnEntryDJ(YesOrNo.YES) + .fixedCosts(FixedCosts.builder() + .fixedCostAmount("10000") + .build()).build(); + BigDecimal result = calculateFixedCostsOnEntry(caseData, new BigDecimal(5001)); + assertThat(result).isEqualTo(MonetaryConversions.penniesToPounds(BigDecimal.valueOf( + Integer.parseInt("13000")))); + } + + @Test + void shouldReturnFixedCostOnEntry_whenJudgmentAmountIsMoreThan25LessThan5000() { + CaseData caseData = CaseDataBuilder.builder().atStateClaimDetailsNotified().build().toBuilder() + .addRespondent2(YesOrNo.NO) + .claimFixedCostsOnEntryDJ(YesOrNo.YES) + .fixedCosts(FixedCosts.builder() + .fixedCostAmount("10000") + .build()).build(); + BigDecimal result = calculateFixedCostsOnEntry(caseData, new BigDecimal(5000)); + assertThat(result).isEqualTo(MonetaryConversions.penniesToPounds(BigDecimal.valueOf( + Integer.parseInt("12200")))); + } + + @Test + void shouldReturnFixedCostOnEntry_whenJudgmentAmountIsUpto25() { + CaseData caseData = CaseDataBuilder.builder().atStateClaimDetailsNotified().build().toBuilder() + .addRespondent2(YesOrNo.NO) + .claimFixedCostsOnEntryDJ(YesOrNo.YES) + .fixedCosts(FixedCosts.builder() + .fixedCostAmount("10000") + .build()).build(); + BigDecimal result = calculateFixedCostsOnEntry(caseData, new BigDecimal(25)); + assertThat(result).isEqualTo(MonetaryConversions.penniesToPounds(BigDecimal.valueOf( + Integer.parseInt("10000")))); + } }