diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/IncomeFrequency.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/IncomeFrequency.java new file mode 100644 index 0000000000..31edfd2090 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/IncomeFrequency.java @@ -0,0 +1,22 @@ +package uk.gov.hmcts.reform.pcs.ccd.domain; + +import uk.gov.hmcts.ccd.sdk.api.HasLabel; + +/** + * Enum representing the frequency of income and benefit payments. + */ +public enum IncomeFrequency implements HasLabel { + WEEKLY("Weekly"), + MONTHLY("Monthly"); + + private final String label; + + IncomeFrequency(String label) { + this.label = label; + } + + @Override + public String getLabel() { + return label; + } +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/respondpossessionclaim/HouseholdCircumstances.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/respondpossessionclaim/HouseholdCircumstances.java index 63b5b90d92..834d41c965 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/respondpossessionclaim/HouseholdCircumstances.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/respondpossessionclaim/HouseholdCircumstances.java @@ -5,8 +5,15 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import jakarta.validation.constraints.Size; import uk.gov.hmcts.ccd.sdk.api.CCD; +import uk.gov.hmcts.ccd.sdk.type.FieldType; import uk.gov.hmcts.ccd.sdk.type.YesOrNo; +import uk.gov.hmcts.reform.pcs.ccd.annotation.JacksonMoneyGBP; +import uk.gov.hmcts.reform.pcs.ccd.domain.IncomeFrequency; + +import java.math.BigDecimal; +import java.time.LocalDate; @Builder @Data @@ -17,4 +24,57 @@ public class HouseholdCircumstances { @CCD private YesOrNo dependantChildren; + @CCD + private YesOrNo shareIncomeExpenseDetails; + + @CCD + private YesOrNo incomeFromJobs; + + @CCD(typeOverride = FieldType.MoneyGBP) + @JacksonMoneyGBP + private BigDecimal incomeFromJobsAmount; + + @CCD + private IncomeFrequency incomeFromJobsFrequency; + + @CCD + private YesOrNo pension; + + @CCD(typeOverride = FieldType.MoneyGBP) + @JacksonMoneyGBP + private BigDecimal pensionAmount; + + @CCD + private IncomeFrequency pensionFrequency; + + @CCD + private YesOrNo universalCredit; + + @CCD + private LocalDate ucApplicationDate; + + @CCD(typeOverride = FieldType.MoneyGBP) + @JacksonMoneyGBP + private BigDecimal universalCreditAmount; + + @CCD + private IncomeFrequency universalCreditFrequency; + + @CCD + private YesOrNo otherBenefits; + + @CCD(typeOverride = FieldType.MoneyGBP) + @JacksonMoneyGBP + private BigDecimal otherBenefitsAmount; + + @CCD + private IncomeFrequency otherBenefitsFrequency; + + @CCD + private YesOrNo moneyFromElsewhere; + + @CCD + @Size(max = 500) + private String moneyFromElsewhereDetails; + } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/respondpossessionclaim/HouseholdCircumstancesEntity.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/respondpossessionclaim/HouseholdCircumstancesEntity.java index 59d01f0769..f528f75e94 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/respondpossessionclaim/HouseholdCircumstancesEntity.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/respondpossessionclaim/HouseholdCircumstancesEntity.java @@ -19,6 +19,7 @@ import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.type.SqlTypes; import uk.gov.hmcts.ccd.sdk.type.YesOrNo; +import uk.gov.hmcts.reform.pcs.ccd.domain.IncomeFrequency; import uk.gov.hmcts.reform.pcs.ccd.domain.YesNoNotSure; import java.math.BigDecimal; @@ -91,6 +92,48 @@ public class HouseholdCircumstancesEntity { private LocalDate ucApplicationDate; + @Enumerated(EnumType.STRING) + @JdbcTypeCode(SqlTypes.NAMED_ENUM) + private YesOrNo incomeFromJobs; + + private BigDecimal incomeFromJobsAmount; + + @Enumerated(EnumType.STRING) + @JdbcTypeCode(SqlTypes.VARCHAR) + private IncomeFrequency incomeFromJobsFrequency; + + @Enumerated(EnumType.STRING) + @JdbcTypeCode(SqlTypes.NAMED_ENUM) + private YesOrNo pension; + + private BigDecimal pensionAmount; + + @Enumerated(EnumType.STRING) + @JdbcTypeCode(SqlTypes.VARCHAR) + private IncomeFrequency pensionFrequency; + + private BigDecimal universalCreditAmount; + + @Enumerated(EnumType.STRING) + @JdbcTypeCode(SqlTypes.VARCHAR) + private IncomeFrequency universalCreditFrequency; + + @Enumerated(EnumType.STRING) + @JdbcTypeCode(SqlTypes.NAMED_ENUM) + private YesOrNo otherBenefits; + + private BigDecimal otherBenefitsAmount; + + @Enumerated(EnumType.STRING) + @JdbcTypeCode(SqlTypes.VARCHAR) + private IncomeFrequency otherBenefitsFrequency; + + @Enumerated(EnumType.STRING) + @JdbcTypeCode(SqlTypes.NAMED_ENUM) + private YesOrNo moneyFromElsewhere; + + private String moneyFromElsewhereDetails; + @Enumerated(EnumType.STRING) @JdbcTypeCode(SqlTypes.NAMED_ENUM) private YesOrNo priorityDebts; diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/respondpossessionclaim/HouseholdCircumstancesService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/respondpossessionclaim/HouseholdCircumstancesService.java index 2c4ec07507..601dd087a0 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/respondpossessionclaim/HouseholdCircumstancesService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/respondpossessionclaim/HouseholdCircumstancesService.java @@ -15,6 +15,22 @@ public HouseholdCircumstancesEntity createHouseholdCircumstancesEntity(Household HouseholdCircumstancesEntity householdCircumstancesEntity = HouseholdCircumstancesEntity.builder() .dependantChildren(circumstances.getDependantChildren()) + .shareIncomeExpenseDetails(circumstances.getShareIncomeExpenseDetails()) + .incomeFromJobs(circumstances.getIncomeFromJobs()) + .incomeFromJobsAmount(circumstances.getIncomeFromJobsAmount()) + .incomeFromJobsFrequency(circumstances.getIncomeFromJobsFrequency()) + .pension(circumstances.getPension()) + .pensionAmount(circumstances.getPensionAmount()) + .pensionFrequency(circumstances.getPensionFrequency()) + .universalCredit(circumstances.getUniversalCredit()) + .ucApplicationDate(circumstances.getUcApplicationDate()) + .universalCreditAmount(circumstances.getUniversalCreditAmount()) + .universalCreditFrequency(circumstances.getUniversalCreditFrequency()) + .otherBenefits(circumstances.getOtherBenefits()) + .otherBenefitsAmount(circumstances.getOtherBenefitsAmount()) + .otherBenefitsFrequency(circumstances.getOtherBenefitsFrequency()) + .moneyFromElsewhere(circumstances.getMoneyFromElsewhere()) + .moneyFromElsewhereDetails(circumstances.getMoneyFromElsewhereDetails()) .build(); return householdCircumstancesEntity; diff --git a/src/main/resources/db/migration/V073__add_regular_income_fields.sql b/src/main/resources/db/migration/V073__add_regular_income_fields.sql new file mode 100644 index 0000000000..118e427262 --- /dev/null +++ b/src/main/resources/db/migration/V073__add_regular_income_fields.sql @@ -0,0 +1,14 @@ +ALTER TABLE household_circumstances + ADD COLUMN income_from_jobs YES_NO, + ADD COLUMN income_from_jobs_amount DECIMAL(18,2), + ADD COLUMN income_from_jobs_frequency VARCHAR(10), + ADD COLUMN pension YES_NO, + ADD COLUMN pension_amount DECIMAL(18,2), + ADD COLUMN pension_frequency VARCHAR(10), + ADD COLUMN universal_credit_amount DECIMAL(18,2), + ADD COLUMN universal_credit_frequency VARCHAR(10), + ADD COLUMN other_benefits YES_NO, + ADD COLUMN other_benefits_amount DECIMAL(18,2), + ADD COLUMN other_benefits_frequency VARCHAR(10), + ADD COLUMN money_from_elsewhere YES_NO, + ADD COLUMN money_from_elsewhere_details VARCHAR(500); diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/respondpossessionclaim/SubmitEventHandlerTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/respondpossessionclaim/SubmitEventHandlerTest.java index 45e3da0444..756bcc2be2 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/respondpossessionclaim/SubmitEventHandlerTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/respondpossessionclaim/SubmitEventHandlerTest.java @@ -9,6 +9,8 @@ import uk.gov.hmcts.ccd.sdk.api.EventPayload; import uk.gov.hmcts.ccd.sdk.api.callback.SubmitResponse; import uk.gov.hmcts.ccd.sdk.type.AddressUK; +import uk.gov.hmcts.ccd.sdk.type.YesOrNo; +import uk.gov.hmcts.reform.pcs.ccd.domain.IncomeFrequency; import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; import uk.gov.hmcts.reform.pcs.ccd.domain.Party; import uk.gov.hmcts.reform.pcs.ccd.domain.State; @@ -16,11 +18,14 @@ import uk.gov.hmcts.reform.pcs.ccd.domain.YesNoNotSure; import uk.gov.hmcts.reform.pcs.ccd.domain.respondpossessionclaim.DefendantContactDetails; import uk.gov.hmcts.reform.pcs.ccd.domain.respondpossessionclaim.DefendantResponses; +import uk.gov.hmcts.reform.pcs.ccd.domain.respondpossessionclaim.HouseholdCircumstances; import uk.gov.hmcts.reform.pcs.ccd.domain.respondpossessionclaim.PossessionClaimResponse; import uk.gov.hmcts.reform.pcs.ccd.service.DraftCaseDataService; import uk.gov.hmcts.reform.pcs.ccd.service.respondpossessionclaim.ClaimResponseService; import uk.gov.hmcts.reform.pcs.ccd.service.respondpossessionclaim.DefendantResponseService; +import java.math.BigDecimal; +import java.time.LocalDate; import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; @@ -54,8 +59,6 @@ void setUp() { underTest = new SubmitEventHandler(draftCaseDataService, claimResponseService, defendantResponseService); } - // ========== VALIDATION ERROR CASES ========== - @Test void shouldReturnErrorWhenPossessionClaimResponseIsNull() { // Given @@ -113,8 +116,6 @@ void shouldReturnErrorWhenDefendantResponsesIsNull() { verify(draftCaseDataService, never()).deleteUnsubmittedCaseData(anyLong(), eq(respondPossessionClaim)); } - // ========== INDEPENDENT FIELD SUBMISSION TESTS ========== - @Test void shouldAllowSubmitWithOnlyDefendantResponses() { DefendantResponses responses = DefendantResponses.builder() @@ -275,6 +276,80 @@ void shouldHandleExceptionFromContactPreferencesService() { verify(claimResponseService).saveDraftData(response, CASE_REFERENCE); } + @Test + void shouldSubmitRegularIncomeFieldsWhenFinalSubmit() { + HouseholdCircumstances householdCircumstances = HouseholdCircumstances.builder() + .shareIncomeExpenseDetails(YesOrNo.YES) + .incomeFromJobs(YesOrNo.YES) + .incomeFromJobsAmount(new BigDecimal("200000")) // £2000.00 in pence + .incomeFromJobsFrequency(IncomeFrequency.MONTHLY) + .pension(YesOrNo.NO) + .universalCredit(YesOrNo.YES) + .ucApplicationDate(LocalDate.of(2024, 2, 10)) + .universalCreditAmount(new BigDecimal("100000")) // £1000.00 in pence + .universalCreditFrequency(IncomeFrequency.MONTHLY) + .otherBenefits(YesOrNo.NO) + .moneyFromElsewhere(YesOrNo.YES) + .moneyFromElsewhereDetails("Receive child support payments") + .build(); + + DefendantResponses defendantResponses = DefendantResponses.builder() + .householdCircumstances(householdCircumstances) + .contactByEmail(VerticalYesNo.YES) + .build(); + + PossessionClaimResponse response = PossessionClaimResponse.builder() + .defendantResponses(defendantResponses) + .build(); + + PCSCase caseData = PCSCase.builder() + .possessionClaimResponse(response) + .build(); + + stubDraft(caseData); + + EventPayload eventPayload = createEventPayload(caseData); + + // When + SubmitResponse result = underTest.submit(eventPayload); + + // Then + assertThat(result).isNotNull(); + assertThat(result.getErrors()).isNullOrEmpty(); + + // Verify the response object with household circumstances is passed to the service + ArgumentCaptor responseCaptor = + ArgumentCaptor.forClass(PossessionClaimResponse.class); + verify(claimResponseService).saveDraftData(responseCaptor.capture(), eq(CASE_REFERENCE)); + + PossessionClaimResponse capturedResponse = responseCaptor.getValue(); + HouseholdCircumstances capturedHousehold = capturedResponse.getDefendantResponses() + .getHouseholdCircumstances(); + + // Assert all regular income fields are submitted correctly + assertThat(capturedHousehold.getShareIncomeExpenseDetails()).isEqualTo(YesOrNo.YES); + + assertThat(capturedHousehold.getIncomeFromJobs()).isEqualTo(YesOrNo.YES); + assertThat(capturedHousehold.getIncomeFromJobsAmount()).isEqualByComparingTo("200000"); + assertThat(capturedHousehold.getIncomeFromJobsFrequency()).isEqualTo(IncomeFrequency.MONTHLY); + + assertThat(capturedHousehold.getPension()).isEqualTo(YesOrNo.NO); + + assertThat(capturedHousehold.getUniversalCredit()).isEqualTo(YesOrNo.YES); + assertThat(capturedHousehold.getUcApplicationDate()).isEqualTo(LocalDate.of(2024, 2, 10)); + assertThat(capturedHousehold.getUniversalCreditAmount()).isEqualByComparingTo("100000"); + assertThat(capturedHousehold.getUniversalCreditFrequency()).isEqualTo(IncomeFrequency.MONTHLY); + + assertThat(capturedHousehold.getOtherBenefits()).isEqualTo(YesOrNo.NO); + + assertThat(capturedHousehold.getMoneyFromElsewhere()).isEqualTo(YesOrNo.YES); + assertThat(capturedHousehold.getMoneyFromElsewhereDetails()) + .isEqualTo("Receive child support payments"); + + verify(defendantResponseService).saveDefendantResponse(CASE_REFERENCE, capturedResponse); + verify(draftCaseDataService).deleteUnsubmittedCaseData(CASE_REFERENCE, respondPossessionClaim); + } + @Test void shouldCallContactPreferencesServiceBeforeReturningSuccess() { // Given diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/respondpossessionsclaim/RespondToPossessionDraftSavePageTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/respondpossessionsclaim/RespondToPossessionDraftSavePageTest.java index ff3f9e4f3a..8709d7a70d 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/respondpossessionsclaim/RespondToPossessionDraftSavePageTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/respondpossessionsclaim/RespondToPossessionDraftSavePageTest.java @@ -10,6 +10,7 @@ import uk.gov.hmcts.ccd.sdk.api.callback.AboutToStartOrSubmitResponse; import uk.gov.hmcts.ccd.sdk.type.AddressUK; import uk.gov.hmcts.ccd.sdk.type.YesOrNo; +import uk.gov.hmcts.reform.pcs.ccd.domain.IncomeFrequency; import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; import uk.gov.hmcts.reform.pcs.ccd.domain.Party; import uk.gov.hmcts.reform.pcs.ccd.domain.State; @@ -27,6 +28,8 @@ import uk.gov.hmcts.reform.pcs.ccd.service.DraftCaseDataService; import uk.gov.hmcts.reform.pcs.ccd.service.respondpossessionclaim.ImmutablePartyFieldValidator; +import java.math.BigDecimal; +import java.time.LocalDate; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @@ -344,6 +347,74 @@ void shouldSkipValidationWhenDefendantContactDetailsIsNull() { assertThat(savedDraft.getPossessionClaimResponse().getDefendantResponses()).isEqualTo(responses); } + @Test + void shouldSaveRegularIncomeFieldsInDraft() { + HouseholdCircumstances householdCircumstances = HouseholdCircumstances.builder() + .shareIncomeExpenseDetails(YesOrNo.YES) + .incomeFromJobs(YesOrNo.YES) + .incomeFromJobsAmount(new BigDecimal("150000")) // £1500.00 in pence + .incomeFromJobsFrequency(IncomeFrequency.MONTHLY) + .pension(YesOrNo.YES) + .pensionAmount(new BigDecimal("50000")) // £500.00 in pence + .pensionFrequency(IncomeFrequency.MONTHLY) + .universalCredit(YesOrNo.YES) + .ucApplicationDate(LocalDate.of(2024, 1, 15)) + .universalCreditAmount(new BigDecimal("80000")) // £800.00 in pence + .universalCreditFrequency(IncomeFrequency.MONTHLY) + .otherBenefits(YesOrNo.YES) + .otherBenefitsAmount(new BigDecimal("20000")) // £200.00 in pence + .otherBenefitsFrequency(IncomeFrequency.WEEKLY) + .moneyFromElsewhere(YesOrNo.YES) + .moneyFromElsewhereDetails("Child maintenance payments of £100 per week") + .build(); + + DefendantResponses responses = DefendantResponses.builder() + .householdCircumstances(householdCircumstances) + .build(); + + PCSCase caseData = buildCaseData(PossessionClaimResponse.builder() + .defendantResponses(responses) + .build()); + + // When + AboutToStartOrSubmitResponse response = callMidEventHandler(caseData); + + // Then + assertThat(response.getErrors()).isNull(); + verify(draftCaseDataService).patchUnsubmittedEventData( + eq(TEST_CASE_REFERENCE), pcsCaseCaptor.capture(), eq(respondPossessionClaim) + ); + + PCSCase savedDraft = pcsCaseCaptor.getValue(); + HouseholdCircumstances savedHousehold = savedDraft.getPossessionClaimResponse() + .getDefendantResponses() + .getHouseholdCircumstances(); + + // Assert all regular income fields are saved correctly + assertThat(savedHousehold.getShareIncomeExpenseDetails()).isEqualTo(YesOrNo.YES); + + assertThat(savedHousehold.getIncomeFromJobs()).isEqualTo(YesOrNo.YES); + assertThat(savedHousehold.getIncomeFromJobsAmount()).isEqualByComparingTo("150000"); + assertThat(savedHousehold.getIncomeFromJobsFrequency()).isEqualTo(IncomeFrequency.MONTHLY); + + assertThat(savedHousehold.getPension()).isEqualTo(YesOrNo.YES); + assertThat(savedHousehold.getPensionAmount()).isEqualByComparingTo("50000"); + assertThat(savedHousehold.getPensionFrequency()).isEqualTo(IncomeFrequency.MONTHLY); + + assertThat(savedHousehold.getUniversalCredit()).isEqualTo(YesOrNo.YES); + assertThat(savedHousehold.getUcApplicationDate()).isEqualTo(LocalDate.of(2024, 1, 15)); + assertThat(savedHousehold.getUniversalCreditAmount()).isEqualByComparingTo("80000"); + assertThat(savedHousehold.getUniversalCreditFrequency()).isEqualTo(IncomeFrequency.MONTHLY); + + assertThat(savedHousehold.getOtherBenefits()).isEqualTo(YesOrNo.YES); + assertThat(savedHousehold.getOtherBenefitsAmount()).isEqualByComparingTo("20000"); + assertThat(savedHousehold.getOtherBenefitsFrequency()).isEqualTo(IncomeFrequency.WEEKLY); + + assertThat(savedHousehold.getMoneyFromElsewhere()).isEqualTo(YesOrNo.YES); + assertThat(savedHousehold.getMoneyFromElsewhereDetails()) + .isEqualTo("Child maintenance payments of £100 per week"); + } + @Test void shouldReturnErrorWhenDraftSaveFails() { //Given