This is an automated email from the ASF dual-hosted git repository.

arnold pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git

commit 8610368a18c9bedb5593a3fb28a2928a7d0e38ec
Author: Oleksii Novikov <[email protected]>
AuthorDate: Thu Dec 18 14:24:47 2025 +0200

    FINERACT-2181: Improve validation for reschedule fromDate parameter
---
 .../test/data/LoanRescheduleErrorMessage.java      |  2 ++
 .../test/resources/features/LoanReschedule.feature | 24 +++++++++++++++++++++-
 ...gressiveLoanRescheduleRequestDataValidator.java |  6 ++++--
 3 files changed, 29 insertions(+), 3 deletions(-)

diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/LoanRescheduleErrorMessage.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/LoanRescheduleErrorMessage.java
index f14725ce58..67da5f5125 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/LoanRescheduleErrorMessage.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/LoanRescheduleErrorMessage.java
@@ -22,6 +22,8 @@ public enum LoanRescheduleErrorMessage {
 
     LOAN_CHARGED_OFF("Loan: %s reschedule installment is not allowed. Loan 
Account is Charged-off"), //
     LOAN_RESCHEDULE_DATE_NOT_IN_FUTURE("Loan Reschedule From date (%s) for 
Loan: %s should be in the future."), //
+    LOAN_RESCHEDULE_FROM_DATE_INSTALLMENT_NOT_FOUND(
+            "Validation errors: [rescheduleFromDate] Failed data validation 
due to: repayment.schedule.installment.does.not.exist."), //
     LOAN_LOCKED_BY_COB("Loan is locked by the COB job. Loan ID: %s"), //
     LOAN_RESCHEDULE_NOT_ALLOWED_FROM_ZERO_TO_NEW_INTEREST_RATE("Failed data 
validation due to: newInterestRate."), //
     LOAN_RESCHEDULE_NOT_ALLOWED_FROM_CURRENT_INTEREST_RATE_TO_ZERO("The 
parameter `newInterestRate` must be greater than 0."), //
diff --git 
a/fineract-e2e-tests-runner/src/test/resources/features/LoanReschedule.feature 
b/fineract-e2e-tests-runner/src/test/resources/features/LoanReschedule.feature
index eb8a5e45fa..0454408d7e 100644
--- 
a/fineract-e2e-tests-runner/src/test/resources/features/LoanReschedule.feature
+++ 
b/fineract-e2e-tests-runner/src/test/resources/features/LoanReschedule.feature
@@ -1432,4 +1432,26 @@ Feature: LoanReschedule
       | 3  | 43   | 15 March 2024    |                  | 45.56           | 
14.67         | 0.69     | 0.0  | 0.0       | 15.36 | 0.0   | 0.0        | 0.0  
| 15.36       |
       | 4  | 31   | 15 April 2024    |                  | 30.56           | 
15.0          | 0.36     | 0.0  | 0.0       | 15.36 | 0.0   | 0.0        | 0.0  
| 15.36       |
       | 5  | 30   | 15 May 2024      |                  | 15.44           | 
15.12         | 0.24     | 0.0  | 0.0       | 15.36 | 0.0   | 0.0        | 0.0  
| 15.36       |
-      | 6  | 31   | 15 June 2024     |                  | 0.0             | 
15.44         | 0.12     | 0.0  | 0.0       | 15.56 | 0.0   | 0.0        | 0.0  
| 15.56       |
\ No newline at end of file
+      | 6  | 31   | 15 June 2024     |                  | 0.0             | 
15.44         | 0.12     | 0.0  | 0.0       | 15.56 | 0.0   | 0.0        | 0.0  
| 15.56       |
+
+  Scenario: Verify Progressive Loan reschedule with non-existing installment 
due date results in validation error
+    When Admin sets the business date to "01 January 2024"
+    When Admin creates a client with random data
+    When Admin creates a fully customized loan with the following data:
+      | LoanProduct                                                   | 
submitted on date | with Principal | ANNUAL interest rate % | interest type     
| interest calculation period | amortization type  | loanTermFrequency | 
loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | 
numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | 
interest free period | Payment strategy            |
+      | LP2_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 01 
January 2024   | 100            | 7                      | DECLINING_BALANCE | 
DAILY                       | EQUAL_INSTALLMENTS | 6                 | MONTHS   
             | 1              | MONTHS                 | 6                  | 0 
                      | 0                      | 0                    | 
ADVANCED_PAYMENT_ALLOCATION |
+    And Admin successfully approves the loan on "01 January 2024" with "100" 
amount and expected disbursement date on "01 January 2024"
+    And Admin successfully disburse the loan on "01 January 2024" with "100" 
EUR transaction amount
+    Then Loan Repayment schedule has 6 periods, with the following data for 
periods:
+      | Nr | Days | Date             | Paid date | Balance of loan | Principal 
due | Interest | Fees | Penalties | Due   | Paid | In advance | Late | 
Outstanding |
+      |    |      | 01 January 2024  |           | 100.0           |           
    |          | 0.0  |           | 0.0   | 0.0  |            |      |          
   |
+      | 1  | 31   | 01 February 2024 |           | 83.57           | 16.43     
    | 0.58     | 0.0  | 0.0       | 17.01 | 0.0  | 0.0        | 0.0  | 17.01    
   |
+      | 2  | 29   | 01 March 2024    |           | 67.05           | 16.52     
    | 0.49     | 0.0  | 0.0       | 17.01 | 0.0  | 0.0        | 0.0  | 17.01    
   |
+      | 3  | 31   | 01 April 2024    |           | 50.43           | 16.62     
    | 0.39     | 0.0  | 0.0       | 17.01 | 0.0  | 0.0        | 0.0  | 17.01    
   |
+      | 4  | 30   | 01 May 2024      |           | 33.71           | 16.72     
    | 0.29     | 0.0  | 0.0       | 17.01 | 0.0  | 0.0        | 0.0  | 17.01    
   |
+      | 5  | 31   | 01 June 2024     |           | 16.9            | 16.81     
    | 0.2      | 0.0  | 0.0       | 17.01 | 0.0  | 0.0        | 0.0  | 17.01    
   |
+      | 6  | 30   | 01 July 2024     |           | 0.0             | 16.9      
    | 0.1      | 0.0  | 0.0       | 17.0  | 0.0  | 0.0        | 0.0  | 17.0     
   |
+    When Admin sets the business date to "02 April 2024"
+    Then Loan reschedule with the following data results a 400 error and 
"LOAN_RESCHEDULE_FROM_DATE_INSTALLMENT_NOT_FOUND" error message
+      | rescheduleFromDate | submittedOnDate | adjustedDueDate | 
graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
+      | 01 August 2024     | 02 April 2024   |                 |               
   |                 | 2          |                 |
\ No newline at end of file
diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/data/ProgressiveLoanRescheduleRequestDataValidator.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/data/ProgressiveLoanRescheduleRequestDataValidator.java
index 33c5d216c0..20f14807e1 100644
--- 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/data/ProgressiveLoanRescheduleRequestDataValidator.java
+++ 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/data/ProgressiveLoanRescheduleRequestDataValidator.java
@@ -94,7 +94,7 @@ public class ProgressiveLoanRescheduleRequestDataValidator 
implements LoanResche
         }
 
         if (hasExtraTermsChange) {
-            validateExtraTerms(dataValidatorBuilder, loan);
+            validateExtraTerms(dataValidatorBuilder, loan, rescheduleFromDate);
         } else if (hasAdjustDueDateChange) {
             validateAdjustDueDateChange(dataValidatorBuilder, loan, 
rescheduleFromDate);
         } else if (hasInterestRateChange) {
@@ -124,8 +124,10 @@ public class ProgressiveLoanRescheduleRequestDataValidator 
implements LoanResche
         validateForOverdueCharges(dataValidatorBuilder, loan, installment);
     }
 
-    private void validateExtraTerms(DataValidatorBuilder dataValidatorBuilder, 
Loan loan) {
+    private void validateExtraTerms(DataValidatorBuilder dataValidatorBuilder, 
Loan loan, LocalDate rescheduleFromDate) {
         validateLoanIsActive(loan, dataValidatorBuilder);
+        final LoanRepaymentScheduleInstallment installment = 
loan.getRelatedRepaymentScheduleInstallment(rescheduleFromDate);
+        validateReschedulingInstallment(dataValidatorBuilder, installment);
     }
 
     private Integer validateExtraTermsParam(FromJsonHelper fromJsonHelper, 
JsonElement jsonElement,

Reply via email to