diff --git a/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java b/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java index 6400c3cd8..1fef1e5d7 100644 --- a/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java +++ b/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java @@ -3140,8 +3140,8 @@ public class SavingsAccount extends AbstractAuditableWithUTCDateTimeCustom throw new PlatformApiDataValidationException(dataValidationErrors); } - if (!DateUtils.isEqual(annualFeeDueDate, transactionDate)) { - baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("invalid.date"); + if (DateUtils.isBefore(transactionDate, annualFeeDueDate)) { + baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("transaction.before.dueDate"); throw new PlatformApiDataValidationException(dataValidationErrors); } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java index 70f16b3b9..395e67674 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java @@ -2954,6 +2954,80 @@ public class ClientSavingsIntegrationTest { Assertions.assertNotNull(payChargeId); } + @SuppressWarnings("unchecked") + @Test + public void testAnnualChargePaymentAfterDueDate() { + Integer savingsId = null; + try { + globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_BUSINESS_DATE, + new PutGlobalConfigurationsRequest().enabled(true)); + + LocalDate submittedDate = LocalDate.of(2023, 1, 1); + String submittedDateString = "01 January 2023"; + BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, submittedDate); + + this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); + + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + + final String minBalanceForInterestCalculation = null; + final String minRequiredBalance = null; + final String enforceMinRequiredBalance = "false"; + final boolean allowOverdraft = false; + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, "1000", + minBalanceForInterestCalculation, minRequiredBalance, enforceMinRequiredBalance, allowOverdraft); + Assertions.assertNotNull(savingsProductID); + + savingsId = this.savingsAccountHelper.applyForSavingsApplicationOnDate(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL, + submittedDateString); + Assertions.assertNotNull(savingsId); + + HashMap savingsStatusHashMap = SavingsStatusChecker.getStatusOfSavings(this.requestSpec, this.responseSpec, savingsId); + SavingsStatusChecker.verifySavingsIsPending(savingsStatusHashMap); + + savingsStatusHashMap = this.savingsAccountHelper.approveSavingsOnDate(savingsId, submittedDateString); + SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap); + + savingsStatusHashMap = this.savingsAccountHelper.activateSavings(savingsId, submittedDateString); + SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap); + + final Integer chargeId = ChargesHelper.createCharges(this.requestSpec, this.responseSpec, + ChargesHelper.getSavingsAnnualFeeJSON()); + Assertions.assertNotNull(chargeId); + + this.savingsAccountHelper.addChargesForSavingsWithDueDateAndFeeOnMonthDay(savingsId, chargeId, "15 February 2023", 100, + "15 February"); + + ArrayList charges = this.savingsAccountHelper.getSavingsCharges(savingsId); + Assertions.assertEquals(1, charges.size()); + + HashMap savingsChargeForPay = charges.get(0); + Integer annualSavingsChargeId = (Integer) savingsChargeForPay.get("id"); + float chargeAmount = (Float) savingsChargeForPay.get("amount"); + + LocalDate paymentDate = LocalDate.of(2023, 3, 1); + BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, paymentDate); + + Integer payChargeTransactionId = this.savingsAccountHelper.payCharge(annualSavingsChargeId, savingsId, + String.valueOf(chargeAmount), paymentDate); + Assertions.assertNotNull(payChargeTransactionId); + + HashMap paidCharge = this.savingsAccountHelper.getSavingsCharge(savingsId, annualSavingsChargeId); + Float amountPaid = (Float) paidCharge.get("amountPaid"); + assertTrue(Math.abs(chargeAmount - amountPaid) < 0.01); + + } finally { + if (savingsId != null) { + BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, + LocalDate.of(2024, 11, 11)); + savingsAccountHelper.closeSavingsAccountOnDate(savingsId, "true", "11 November 2024"); + } + globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_BUSINESS_DATE, + new PutGlobalConfigurationsRequest().enabled(false)); + } + } + @Test public void testRunningBalanceAfterWithdrawalWithBackdateConfigurationOn() { this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);