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

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


The following commit(s) were added to refs/heads/develop by this push:
     new fc93db16b5 FINERACT-2319: Add penalty-first payment allocation 
strategy for progressive loans with backdated repayment charge handling
fc93db16b5 is described below

commit fc93db16b59ebb84a1844266a94b99f61bf87088
Author: Oleksii Novikov <[email protected]>
AuthorDate: Mon Jun 30 14:13:43 2025 +0300

    FINERACT-2319: Add penalty-first payment allocation strategy for 
progressive loans with backdated repayment charge handling
---
 .../test/data/loanproduct/DefaultLoanProduct.java  |  1 +
 .../global/LoanProductGlobalInitializerStep.java   | 32 +++++++++
 .../fineract/test/support/TestContextKey.java      |  1 +
 .../test/resources/features/LoanRepayment.feature  | 83 ++++++++++++++++++++++
 .../portfolio/loanaccount/domain/Loan.java         | 19 +++++
 .../service/LoanDownPaymentHandlerServiceImpl.java |  1 +
 .../domain/LoanAccountDomainServiceJpa.java        |  1 +
 .../LoanTransactionProcessingServiceImpl.java      |  3 +
 .../integrationtests/BaseLoanIntegrationTest.java  | 61 ++++++++++++----
 .../LoanTransactionAccrualActivityPostingTest.java | 46 ++++++------
 ...nReprocessForAdvancedPaymentAllocationTest.java |  2 +-
 ...tiveLoansWithAdvancedPaymentAllocationTest.java | 18 ++---
 12 files changed, 219 insertions(+), 49 deletions(-)

diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/DefaultLoanProduct.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/DefaultLoanProduct.java
index de24fdd195..5cd25a4e87 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/DefaultLoanProduct.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/DefaultLoanProduct.java
@@ -109,6 +109,7 @@ public enum DefaultLoanProduct implements LoanProduct {
     LP2_ADV_PYMNT_ACCELERATE_MATURITY_CHARGE_OFF_BEHAVIOUR, //
     LP2_NO_INTEREST_RECALCULATION_CHARGEBACK_ALLOCATION_INTEREST_FIRST, //
     LP2_NO_INTEREST_RECALCULATION_CHARGEBACK_ALLOCATION_PRINCIPAL_FIRST, //
+    LP2_NO_INTEREST_RECALCULATION_ALLOCATION_PENALTY_FIRST, //
     
LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALC_EMI_360_30_CHARGEBACK_INTEREST_PENALTY_FEE_PRINCIPAL,
 //
     
LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALC_EMI_360_30_CHARGEBACK_INTEREST_FEE_PRINCIPAL,
 //
     
LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALC_EMI_360_30_CHARGEBACK_PRINCIPAL_INTEREST_FEE,
 //
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
index 6ef4a74c30..74e603d62c 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
@@ -3302,6 +3302,38 @@ public class LoanProductGlobalInitializerStep implements 
FineractGlobalInitializ
         TestContext.INSTANCE.set(
                 
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_INTEREST_FLAT_ADV_PMT_ALLOC_MULTIDISBURSE_PART_PERIOD_CALC_DISABLED,
                 
responseLoanProductsRequestDownPaymentAdvInterestFlatMultiDisbPartPeriodIntCalcDisabled);
+
+        // LP2 without Down-payment + interest recalculation disabled + 
advanced payment allocation + progressive loan
+        // schedule + horizontal + allocation penalty first
+        // (LP2_NO_INTEREST_RECALCULATION_ALLOCATION_PENALTY_FIRST)
+        String name127 = 
DefaultLoanProduct.LP2_NO_INTEREST_RECALCULATION_ALLOCATION_PENALTY_FIRST.getName();
+        PostLoanProductsRequest 
loanProductsRequestNoInterestRecalculationAllocationPenaltyFirst = 
loanProductsRequestFactory
+                .defaultLoanProductsRequestLP2()//
+                .name(name127)//
+                
.transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION.getValue())//
+                .loanScheduleType("PROGRESSIVE") //
+                .loanScheduleProcessingType("HORIZONTAL")//
+                .enableDownPayment(false)//
+                .enableAutoRepaymentForDownPayment(null)//
+                .disbursedAmountPercentageForDownPayment(null)//
+                .paymentAllocation(List.of(//
+                        createPaymentAllocation("DEFAULT", "LAST_INSTALLMENT",
+                                
LoanProductPaymentAllocationRule.AllocationTypesEnum.PAST_DUE_PENALTY, //
+                                
LoanProductPaymentAllocationRule.AllocationTypesEnum.PAST_DUE_INTEREST, //
+                                
LoanProductPaymentAllocationRule.AllocationTypesEnum.PAST_DUE_PRINCIPAL, //
+                                
LoanProductPaymentAllocationRule.AllocationTypesEnum.PAST_DUE_FEE, //
+                                
LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_PENALTY, //
+                                
LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_INTEREST, //
+                                
LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_PRINCIPAL, //
+                                
LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_FEE, //
+                                
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_PENALTY, //
+                                
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_INTEREST, //
+                                
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_PRINCIPAL, //
+                                
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_FEE)));//
+        Response<PostLoanProductsResponse> 
responseLoanProductsRequestNoInterestRecalculationAllocationPenaltyFirst = 
loanProductsApi
+                
.createLoanProduct(loanProductsRequestNoInterestRecalculationAllocationPenaltyFirst).execute();
+        
TestContext.INSTANCE.set(TestContextKey.LP2_NO_INTEREST_RECALCULATION_ALLOCATION_PENALTY_FIRST_RESPONSE,
+                
responseLoanProductsRequestNoInterestRecalculationAllocationPenaltyFirst);
     }
 
     public static AdvancedPaymentData createPaymentAllocation(String 
transactionType, String futureInstallmentAllocationRule,
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java
index 54fe29e5e7..9eefa43c57 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java
@@ -169,6 +169,7 @@ public abstract class TestContextKey {
     public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_360_30_INTEREST_RECALC_AUTO_DOWNPAYMENT_ZERO_INTEREST_CHARGE_OFF_ACCRUAL_ACTIVITY
 = 
"loanProductCreateResponseLP2AdvancedPaymentInterestDailyInterestRecalculationAutoDownpaymentZeroInterestChargeOffBehaviourAccrualActivity";
     public static final String 
LP2_NO_INTEREST_RECALCULATION_CHARGEBACK_ALLOCATION_INTEREST_FIRST_RESPONSE = 
"loanProductCreateResponseLP2NoInterestRecalculationChargebackAllocationInterestFirst";
     public static final String 
LP2_NO_INTEREST_RECALCULATION_CHARGEBACK_ALLOCATION_PRINCIPAL_FIRST_RESPONSE = 
"loanProductCreateResponseLP2NoInterestRecalculationChargebackAllocationPrincipalFirst";
+    public static final String 
LP2_NO_INTEREST_RECALCULATION_ALLOCATION_PENALTY_FIRST_RESPONSE = 
"loanProductCreateResponseLP2NoInterestRecalculationAllocationPenaltyFirst";
     public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ACCELERATE_MATURITY_CHARGE_OFF_BEHAVIOUR_LAST_INSTALLMENT_STRATEGY
 = 
"loanProductCreateResponseLP2AdvancedPaymentInterestDailyInterestRecalculationAccelerateMaturityChargeOffBehaviourLastInstallmentStrategy";
     public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_ACCELERATE_MATURITY_CHARGE_OFF_BEHAVIOUR_LAST_INSTALLMENT_STRATEGY
 = 
"loanProductCreateResponseLP2AdvancedPaymentAccelerateMaturityChargeOffBehaviourLastInstallmentStrategy";
     public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_IR_DAILY_TILL_REST_FREQUENCY_DATE_LAST_INSTALLMENT
 = 
"loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationDailyTillRestFrequencyDateLastInstallment";
diff --git 
a/fineract-e2e-tests-runner/src/test/resources/features/LoanRepayment.feature 
b/fineract-e2e-tests-runner/src/test/resources/features/LoanRepayment.feature
index 7f32493ce1..d9ad3fe40d 100644
--- 
a/fineract-e2e-tests-runner/src/test/resources/features/LoanRepayment.feature
+++ 
b/fineract-e2e-tests-runner/src/test/resources/features/LoanRepayment.feature
@@ -5406,3 +5406,86 @@ Feature: LoanRepayment
       | 01 January 2024  | Disbursement     | 100.0  | 0.0       | 0.0      | 
0.0  | 0.0       | 100.0        | false    | false    |
       | 01 February 2024 | Repayment        | 40.0   | 39.42     | 0.58     | 
0.0  | 0.0       | 60.58        | false    | false    |
     When Admin set 
"LP2_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL" loan product 
"DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation 
rule
+
+  Scenario: Verify progressive loan repayment reversals with penalty charge 
and backdated repayment
+    When Admin sets the business date to "20 October 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_NO_INTEREST_RECALCULATION_ALLOCATION_PENALTY_FIRST | 20 October 
2024   | 100            | 0                      | FLAT          | 
SAME_AS_REPAYMENT_PERIOD    | EQUAL_INSTALLMENTS | 30                | DAYS     
             | 30             | DAYS                   | 1                  | 0 
                      | 0                      | 0                    | 
ADVANCED_PAYMENT_ALLOCATION |
+    And Admin successfully approves the loan on "20 October 2024" with "100" 
amount and expected disbursement date on "20 October 2024"
+    And Admin successfully disburse the loan on "20 October 2024" with "100" 
EUR transaction amount
+    Then Loan Repayment schedule has 1 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 |
+      |    |      | 20 October 2024  |           | 100.0           |           
    |          | 0.0  |           | 0.0   | 0.0  |            |      |          
   |
+      | 1  | 30   | 19 November 2024 |           | 0.0             | 100.0     
    | 0.0      | 0.0  | 0.0       | 100.0 | 0.0  | 0.0        | 0.0  | 100.0    
   |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due   | Paid | In 
advance | Late | Outstanding |
+      | 100.0         | 0.0      | 0.0  | 0.0       | 100.0 | 0.0  | 0.0       
 | 0.0  | 100.0       |
+    When Admin sets the business date to "22 October 2024"
+    And Customer makes "AUTOPAY" repayment on "22 October 2024" with 100 EUR 
transaction amount
+    Then Loan status will be "CLOSED_OBLIGATIONS_MET"
+    Then Loan Repayment schedule has 1 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 |
+      |    |      | 20 October 2024  |                 | 100.0           |     
          |          | 0.0  |           | 0.0   | 0.0   |            |      |   
          |
+      | 1  | 30   | 19 November 2024 | 22 October 2024 | 0.0             | 
100.0         | 0.0      | 0.0  | 0.0       | 100.0 | 100.0 | 100.0      | 0.0  
| 0.0         |
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount | Principal | Interest | 
Fees | Penalties | Loan Balance |
+      | 20 October 2024  | Disbursement     | 100.0  | 0.0       | 0.0      | 
0.0  | 0.0       | 100.0        |
+      | 22 October 2024  | Repayment        | 100.0  | 100.0     | 0.0      | 
0.0  | 0.0       | 0.0          |
+    When Admin sets the business date to "24 October 2024"
+    And Customer makes a repayment undo on "22 October 2024"
+    Then Loan status will be "ACTIVE"
+    And Loan has 100 outstanding amount
+    Then Loan Repayment schedule has 1 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 |
+      |    |      | 20 October 2024  |           | 100.0           |           
    |          | 0.0  |           | 0.0   | 0.0  |            |      |          
   |
+      | 1  | 30   | 19 November 2024 |           | 0.0             | 100.0     
    | 0.0      | 0.0  | 0.0       | 100.0 | 0.0  | 0.0        | 0.0  | 100.0    
   |
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount | Principal | Interest | 
Fees | Penalties | Loan Balance | Reverted | Replayed |
+      | 20 October 2024  | Disbursement     | 100.0  | 0.0       | 0.0      | 
0.0  | 0.0       | 100.0        | false    | false    |
+      | 22 October 2024  | Repayment        | 100.0  | 100.0     | 0.0      | 
0.0  | 0.0       | 0.0          | true     | false     |
+    When Admin sets the business date to "26 October 2024"
+    And Customer makes "AUTOPAY" repayment on "26 October 2024" with 100 EUR 
transaction amount
+    Then Loan status will be "CLOSED_OBLIGATIONS_MET"
+    Then Loan Repayment schedule has 1 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 |
+      |    |      | 20 October 2024  |                 | 100.0           |     
          |          | 0.0  |           | 0.0   | 0.0   |            |      |   
          |
+      | 1  | 30   | 19 November 2024 | 26 October 2024 | 0.0             | 
100.0         | 0.0      | 0.0  | 0.0       | 100.0 | 100.0 | 100.0      | 0.0  
| 0.0         |
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount | Principal | Interest | 
Fees | Penalties | Loan Balance | Reverted | Replayed |
+      | 20 October 2024  | Disbursement     | 100.0  | 0.0       | 0.0      | 
0.0  | 0.0       | 100.0        | false    | false    |
+      | 22 October 2024  | Repayment        | 100.0  | 100.0     | 0.0      | 
0.0  | 0.0       | 0.0          | true     | false    |
+      | 26 October 2024  | Repayment        | 100.0  | 100.0     | 0.0      | 
0.0  | 0.0       | 0.0          | false    | false    |
+    When Admin sets the business date to "28 October 2024"
+    And Customer makes a repayment undo on "26 October 2024"
+    Then Loan status will be "ACTIVE"
+    And Loan has 100 outstanding amount
+    Then Loan Repayment schedule has 1 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 |
+      |    |      | 20 October 2024  |           | 100.0           |           
    |          | 0.0  |           | 0.0   | 0.0  |            |      |          
   |
+      | 1  | 30   | 19 November 2024 |           | 0.0             | 100.0     
    | 0.0      | 0.0  | 0.0       | 100.0 | 0.0  | 0.0        | 0.0  | 100.0    
   |
+    When Admin adds "LOAN_NSF_FEE" due date charge with "28 October 2024" due 
date and 10 EUR transaction amount
+    Then Loan Repayment schedule has 1 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 |
+      |    |      | 20 October 2024  |           | 100.0           |           
    |          | 0.0  |           | 0.0   | 0.0  |            |      |          
   |
+      | 1  | 30   | 19 November 2024 |           | 0.0             | 100.0     
    | 0.0      | 0.0  | 10.0      | 110.0 | 0.0  | 0.0        | 0.0  | 110.0    
   |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due   | Paid | In 
advance | Late | Outstanding |
+      | 100.0         | 0.0      | 0.0  | 10.0      | 110.0 | 0.0  | 0.0       
 | 0.0  | 110.0       |
+    And Customer makes "AUTOPAY" repayment on "26 October 2024" with 101 EUR 
transaction amount
+    Then Loan Repayment schedule has 1 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 |
+      |    |      | 20 October 2024  |           | 100.0           |           
    |          | 0.0  |           | 0.0   | 0.0   |            |      |         
    |
+      | 1  | 30   | 19 November 2024 |           | 0.0             | 100.0     
    | 0.0      | 0.0  | 10.0      | 110.0 | 101.0 | 101.0      | 0.0  | 9.0     
    |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due   | Paid  | In 
advance | Late | Outstanding |
+      | 100.0         | 0.0      | 0.0  | 10.0      | 110.0 | 101.0 | 101.0    
  | 0.0  | 9.0         |
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount | Principal | Interest | 
Fees | Penalties | Loan Balance | Reverted | Replayed |
+      | 20 October 2024  | Disbursement     | 100.0  | 0.0       | 0.0      | 
0.0  | 0.0       | 100.0        | false    | false    |
+      | 22 October 2024  | Repayment        | 100.0  | 100.0     | 0.0      | 
0.0  | 0.0       | 0.0          | true     | false    |
+      | 26 October 2024  | Repayment        | 100.0  | 100.0     | 0.0      | 
0.0  | 0.0       | 0.0          | true     | false    |
+      | 26 October 2024  | Repayment        | 101.0  | 100.0     | 0.0      | 
0.0  | 1.0       | 0.0          | false    | false    |
+    When Customer makes "AUTOPAY" repayment on "27 October 2024" with 9 EUR 
transaction amount
+    Then Loan status will be "CLOSED_OBLIGATIONS_MET"
\ No newline at end of file
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index 64458b8649..337b3fd472 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -49,11 +49,13 @@ import java.util.ListIterator;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
+import java.util.function.BiFunction;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import lombok.AccessLevel;
 import lombok.Getter;
 import lombok.Setter;
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.fineract.infrastructure.codes.domain.CodeValue;
 import 
org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
@@ -79,6 +81,7 @@ import 
org.apache.fineract.portfolio.loanproduct.domain.LoanSupportedInterestRef
 import org.apache.fineract.portfolio.rate.domain.Rate;
 import 
org.apache.fineract.portfolio.repaymentwithpostdatedchecks.domain.PostDatedChecks;
 import org.apache.fineract.useradministration.domain.AppUser;
+import org.springframework.lang.NonNull;
 
 @Entity
 @Table(name = "m_loan", uniqueConstraints = { @UniqueConstraint(columnNames = 
{ "account_no" }, name = "loan_account_no_UNIQUE"),
@@ -1242,6 +1245,22 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom<Long> {
         return this.charges == null ? new HashSet<>() : 
this.charges.stream().filter(LoanCharge::isActive).collect(Collectors.toSet());
     }
 
+    public boolean 
hasChargesAffectedByBackdatedRepaymentLikeTransaction(@NonNull final 
LoanTransaction transaction) {
+        if (!transaction.isRepaymentLikeType() || 
CollectionUtils.isEmpty(this.charges) || !isProgressiveSchedule()
+                || 
!DateUtils.isBeforeBusinessDate(transaction.getTransactionDate())) {
+            return false;
+        }
+
+        final BiFunction<LocalDate, LocalDate, LocalDate> earlierDate = 
(date1, date2) -> DateUtils.isBefore(date1, date2) ? date1 : date2;
+
+        return this.charges.stream().filter(LoanCharge::isActive)
+                .filter(loanCharge -> loanCharge.isSpecifiedDueDate() || 
loanCharge.isOverdueInstallmentCharge())
+                .filter(loanCharge -> loanCharge.getDueLocalDate() != 
null).anyMatch(loanCharge -> {
+                    final LocalDate comparisonDate = 
earlierDate.apply(loanCharge.getDueLocalDate(), 
loanCharge.getSubmittedOnDate());
+                    return comparisonDate != null && 
comparisonDate.isAfter(transaction.getTransactionDate());
+                });
+    }
+
     public LoanCharge fetchLoanChargesById(final Long id) {
         LoanCharge charge = null;
         for (LoanCharge loanCharge : this.charges) {
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanDownPaymentHandlerServiceImpl.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanDownPaymentHandlerServiceImpl.java
index dfc76a4557..467b8dbaf6 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanDownPaymentHandlerServiceImpl.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanDownPaymentHandlerServiceImpl.java
@@ -133,6 +133,7 @@ public class LoanDownPaymentHandlerServiceImpl implements 
LoanDownPaymentHandler
         boolean processLatest = isTransactionChronologicallyLatest //
                 && adjustedTransaction == null // covers reversals
                 && !loan.isForeclosure() //
+                && 
!loan.hasChargesAffectedByBackdatedRepaymentLikeTransaction(loanTransaction)
                 && 
loanTransactionProcessingService.canProcessLatestTransactionOnly(loan, 
loanTransaction, currentInstallment); //
         if (processLatest) {
             
loanTransactionProcessingService.processLatestTransaction(loan.getTransactionProcessingStrategyCode(),
 loanTransaction,
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
index b36039fdb1..3ba2f187c1 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
@@ -904,6 +904,7 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
 
         boolean processLatest = isTransactionChronologicallyLatest //
                 && !loan.isForeclosure() //
+                && 
!loan.hasChargesAffectedByBackdatedRepaymentLikeTransaction(refundTransaction) 
//
                 && 
loanTransactionProcessingService.canProcessLatestTransactionOnly(loan, 
refundTransaction, currentInstallment); //
         if (processLatest) {
             
loanTransactionProcessingService.processLatestTransaction(loan.getTransactionProcessingStrategyCode(),
 refundTransaction,
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanTransactionProcessingServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanTransactionProcessingServiceImpl.java
index f5592c81be..e7aa89385b 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanTransactionProcessingServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanTransactionProcessingServiceImpl.java
@@ -74,6 +74,9 @@ public class LoanTransactionProcessingServiceImpl implements 
LoanTransactionProc
         if 
(!DateUtils.isEqualBusinessDate(loanTransaction.getTransactionDate())) {
             return false;
         }
+        if 
(loan.hasChargesAffectedByBackdatedRepaymentLikeTransaction(loanTransaction)) {
+            return false;
+        }
         LoanInterestRecalculationDetails interestRecalculationDetails = 
loan.getLoanInterestRecalculationDetails();
         if (interestRecalculationDetails != null && 
((interestRecalculationDetails.getRestFrequencyType().isSameAsRepayment()
                 && 
interestRecalculationDetails.getPreCloseInterestCalculationStrategy().calculateTillPreClosureDateEnabled())
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
index 6bb511131e..46ce4b44b0 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
@@ -645,26 +645,57 @@ public abstract class BaseLoanIntegrationTest extends 
IntegrationTest {
         }
     }
 
-    protected void verifyTransactions(Long loanId, TransactionExt... 
transactions) {
-        GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId.intValue());
+    protected void verifyTransactions(final Long loanId, final 
TransactionExt... transactions) {
+        final GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId.intValue());
         if (transactions == null || transactions.length == 0) {
             assertNull(loanDetails.getTransactions(), "No transaction is 
expected on loan " + loanId);
         } else {
+            Assertions.assertNotNull(loanDetails.getTransactions());
             Assertions.assertEquals(transactions.length, 
loanDetails.getTransactions().size(), "Number of transactions on loan " + 
loanId);
+
             Arrays.stream(transactions).forEach(tr -> {
-                boolean found = loanDetails.getTransactions().stream()
-                        .anyMatch(item -> 
Objects.equals(Utils.getDoubleValue(item.getAmount()), tr.amount) //
-                                && Objects.equals(item.getType().getValue(), 
tr.type) //
-                                && Objects.equals(item.getDate(), 
LocalDate.parse(tr.date, dateTimeFormatter)) //
-                                && 
Objects.equals(Utils.getDoubleValue(item.getOutstandingLoanBalance()), 
tr.outstandingPrincipal) //
-                                && 
Objects.equals(Utils.getDoubleValue(item.getPrincipalPortion()), 
tr.principalPortion) //
-                                && 
Objects.equals(Utils.getDoubleValue(item.getInterestPortion()), 
tr.interestPortion) //
-                                && 
Objects.equals(Utils.getDoubleValue(item.getFeeChargesPortion()), 
tr.feePortion) //
-                                && 
Objects.equals(Utils.getDoubleValue(item.getPenaltyChargesPortion()), 
tr.penaltyPortion) //
-                                && 
Objects.equals(Utils.getDoubleValue(item.getOverpaymentPortion()), 
tr.overpaymentPortion) //
-                                && 
Objects.equals(Utils.getDoubleValue(item.getUnrecognizedIncomePortion()), 
tr.unrecognizedPortion) //
-                );
-                Assertions.assertTrue(found, "Required transaction not found: 
" + tr + " on loan " + loanId);
+                final List<GetLoansLoanIdTransactions> transactionsByDate = 
loanDetails.getTransactions().stream()
+                        .filter(item -> Objects.equals(item.getDate(), 
LocalDate.parse(tr.date, dateTimeFormatter))).toList();
+
+                if (transactionsByDate.isEmpty()) {
+                    Assertions.fail("No transactions found for date " + 
tr.date + " on loan " + loanId);
+                    return;
+                }
+
+                final boolean found = transactionsByDate.stream()
+                        .anyMatch(item -> 
Objects.equals(Utils.getDoubleValue(item.getAmount()), tr.amount)
+                                && Objects.equals(item.getType().getValue(), 
tr.type)
+                                && 
Objects.equals(Utils.getDoubleValue(item.getOutstandingLoanBalance()), 
tr.outstandingPrincipal)
+                                && 
Objects.equals(Utils.getDoubleValue(item.getPrincipalPortion()), 
tr.principalPortion)
+                                && 
Objects.equals(Utils.getDoubleValue(item.getInterestPortion()), 
tr.interestPortion)
+                                && 
Objects.equals(Utils.getDoubleValue(item.getFeeChargesPortion()), tr.feePortion)
+                                && 
Objects.equals(Utils.getDoubleValue(item.getPenaltyChargesPortion()), 
tr.penaltyPortion)
+                                && 
Objects.equals(Utils.getDoubleValue(item.getOverpaymentPortion()), 
tr.overpaymentPortion)
+                                && 
Objects.equals(Utils.getDoubleValue(item.getUnrecognizedIncomePortion()), 
tr.unrecognizedPortion));
+
+                if (!found) {
+                    final StringBuilder errorMessage = new StringBuilder();
+                    errorMessage.append("Required transaction not found: 
").append(tr).append(" on loan ").append(loanId);
+                    errorMessage.append("\nTransactions found for date 
").append(tr.date).append(":");
+
+                    for (int i = 0; i < transactionsByDate.size(); i++) {
+                        GetLoansLoanIdTransactions item = 
transactionsByDate.get(i);
+                        errorMessage.append("\n  Transaction ").append(i + 
1).append(": ");
+                        
errorMessage.append("amount=").append(Utils.getDoubleValue(item.getAmount()));
+                        errorMessage.append(", 
type=").append(item.getType().getValue());
+                        errorMessage.append(", 
date=").append(item.getDate().format(dateTimeFormatter));
+                        errorMessage.append(", 
outstandingPrincipal=").append(Utils.getDoubleValue(item.getOutstandingLoanBalance()));
+                        errorMessage.append(", 
principalPortion=").append(Utils.getDoubleValue(item.getPrincipalPortion()));
+                        errorMessage.append(", 
interestPortion=").append(Utils.getDoubleValue(item.getInterestPortion()));
+                        errorMessage.append(", 
feePortion=").append(Utils.getDoubleValue(item.getFeeChargesPortion()));
+                        errorMessage.append(", 
penaltyPortion=").append(Utils.getDoubleValue(item.getPenaltyChargesPortion()));
+                        errorMessage.append(", 
unrecognizedPortion=").append(Utils.getDoubleValue(item.getUnrecognizedIncomePortion()));
+                        errorMessage.append(", 
overpaymentPortion=").append(Utils.getDoubleValue(item.getOverpaymentPortion()));
+                        errorMessage.append(", 
reversed=").append(item.getManuallyReversed() != null ? 
item.getManuallyReversed() : false);
+                    }
+
+                    Assertions.fail(errorMessage.toString());
+                }
             });
         }
     }
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionAccrualActivityPostingTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionAccrualActivityPostingTest.java
index 7b0a7a584c..5de5032340 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionAccrualActivityPostingTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionAccrualActivityPostingTest.java
@@ -714,7 +714,6 @@ public class LoanTransactionAccrualActivityPostingTest 
extends BaseLoanIntegrati
         final String creationBusinessDay = "15 January 2023";
         AtomicReference<Long> loanId = new AtomicReference<>();
         runAt(creationBusinessDay, () -> {
-
             Long localLoanProductId = 
createLoanProductAccountingAccrualPeriodicAdvancedPaymentAllocation();
             
loanId.set(applyForLoanApplicationAdvancedPaymentAllocation(client.getClientId(),
 localLoanProductId, BigDecimal.valueOf(40000),
                     disbursementDay, BigDecimal.ZERO));
@@ -723,53 +722,52 @@ public class LoanTransactionAccrualActivityPostingTest 
extends BaseLoanIntegrati
                     
.dateFormat(DATETIME_PATTERN).approvedOnDate(disbursementDay).locale("en"));
 
             loanTransactionHelper.disburseLoan(loanId.get(), new 
PostLoansLoanIdRequest().actualDisbursementDate(disbursementDay)
-                    
.dateFormat(DATETIME_PATTERN).transactionAmount(BigDecimal.valueOf(1000.0)).locale("en"));
+                    
.dateFormat(DATETIME_PATTERN).transactionAmount(BigDecimal.valueOf(1000)).locale("en"));
 
             chargePenalty(loanId.get(), 20.0, chargeDueDate1st);
 
             addRepaymentForLoan(loanId.get(), 50.0, "10 January 2023");
             verifyTransactions(loanId.get(), //
-                    transaction(1000.0, "Disbursement", disbursementDay, 
1000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
-                    transaction(50.0, "Repayment", "10 January 2023", 970, 30, 
0, 0, 20, 0.0, 0.0));
+                    transaction(1000, "Disbursement", disbursementDay, 1000, 
0, 0, 0, 0, 0, 0),
+                    transaction(50, "Repayment", "10 January 2023", 950, 50, 
0, 0, 0, 0, 0));
 
         });
         runAt(repaymentPeriod1CloseDate, () -> {
             inlineLoanCOBHelper.executeInlineCOB(List.of(loanId.get()));
             verifyTransactions(loanId.get(), //
-                    transaction(1000.0, "Disbursement", disbursementDay, 
1000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
-                    transaction(20.0, "Accrual", "01 February 2023", 0, 0, 0, 
0, 20, 0.0, 0.0),
-                    transaction(50.0, "Repayment", "10 January 2023", 970, 30, 
0, 0, 20, 0.0, 0.0),
-                    transaction(20.0, "Accrual Activity", "01 February 2023", 
0, 0, 0.0, 0.0, 20.0, 0.0, 0.0));
+                    transaction(1000, "Disbursement", disbursementDay, 1000, 
0, 0, 0, 0, 0, 0),
+                    transaction(20, "Accrual", "01 February 2023", 0, 0, 0, 0, 
20, 0, 0),
+                    transaction(50, "Repayment", "10 January 2023", 950, 50, 
0, 0, 0, 0, 0),
+                    transaction(20, "Accrual Activity", "01 February 2023", 0, 
0, 0, 0, 20, 0, 0));
 
         });
         runAt(repaymentPeriod1OneDayAfterCloseDate, () -> {
-
             addRepaymentForLoan(loanId.get(), 220.0, "8 January 2023");
 
             verifyTransactions(loanId.get(), //
-                    transaction(1000.0, "Disbursement", disbursementDay, 
1000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
-                    transaction(20.0, "Accrual", "01 February 2023", 0, 0, 0, 
0, 20, 0.0, 0.0),
-                    transaction(50.0, "Repayment", "10 January 2023", 730, 50, 
0, 0, 0, 0.0, 0.0),
-                    transaction(220.0, "Repayment", "08 January 2023", 780, 
220, 0, 0, 0, 0.0, 0.0),
-                    transaction(20.0, "Accrual Activity", "01 February 2023", 
0, 0, 0.0, 0.0, 20.0, 0.0, 0.0));
+                    transaction(1000, "Disbursement", disbursementDay, 1000, 
0, 0, 0, 0, 0, 0),
+                    transaction(20, "Accrual", "01 February 2023", 0, 0, 0, 0, 
20, 0, 0),
+                    transaction(50, "Repayment", "10 January 2023", 730, 50, 
0, 0, 0, 0, 0),
+                    transaction(220, "Repayment", "08 January 2023", 780, 220, 
0, 0, 0, 0, 0),
+                    transaction(20, "Accrual Activity", "01 February 2023", 0, 
0, 0, 0, 20, 0, 0));
 
             chargePenalty(loanId.get(), 33.0, chargeDueDate2st);
 
             verifyTransactions(loanId.get(), //
-                    transaction(1000.0, "Disbursement", disbursementDay, 
1000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
-                    transaction(20.0, "Accrual", "01 February 2023", 0, 0, 0, 
0, 20, 0.0, 0.0),
-                    transaction(50.0, "Repayment", "10 January 2023", 730, 50, 
0, 0, 0, 0.0, 0.0),
-                    transaction(220.0, "Repayment", "08 January 2023", 780, 
220, 0, 0, 0, 0.0, 0.0),
-                    transaction(53.0, "Accrual Activity", "01 February 2023", 
0, 0, 0.0, 0.0, 53.0, 0.0, 0.0));
+                    transaction(1000, "Disbursement", disbursementDay, 1000, 
0, 0, 0, 0, 0, 0),
+                    transaction(20, "Accrual", "01 February 2023", 0, 0, 0, 0, 
20, 0, 0),
+                    transaction(50, "Repayment", "10 January 2023", 730, 50, 
0, 0, 0, 0, 0),
+                    transaction(220, "Repayment", "08 January 2023", 780, 220, 
0, 0, 0, 0, 0),
+                    transaction(53, "Accrual Activity", "01 February 2023", 0, 
0, 0, 0, 53, 0, 0));
 
             chargeFee(loanId.get(), 12.0, chargeDueDate3st);
 
             verifyTransactions(loanId.get(), //
-                    transaction(1000.0, "Disbursement", disbursementDay, 
1000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
-                    transaction(20.0, "Accrual", "01 February 2023", 0, 0, 0, 
0, 20, 0.0, 0.0),
-                    transaction(50.0, "Repayment", "10 January 2023", 730, 50, 
0, 0, 0, 0.0, 0.0),
-                    transaction(220.0, "Repayment", "08 January 2023", 780, 
220, 0, 0, 0, 0.0, 0.0),
-                    transaction(65.0, "Accrual Activity", "01 February 2023", 
0, 0, 0.0, 12.0, 53.0, 0.0, 0.0));
+                    transaction(1000, "Disbursement", disbursementDay, 1000, 
0, 0, 0, 0, 0, 0),
+                    transaction(20, "Accrual", "01 February 2023", 0, 0, 0, 0, 
20, 0, 0),
+                    transaction(50, "Repayment", "10 January 2023", 730, 50, 
0, 0, 0, 0, 0),
+                    transaction(220, "Repayment", "08 January 2023", 780, 220, 
0, 0, 0, 0, 0),
+                    transaction(65, "Accrual Activity", "01 February 2023", 0, 
0, 0, 12, 53, 0, 0));
 
         });
     }
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionReprocessForAdvancedPaymentAllocationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionReprocessForAdvancedPaymentAllocationTest.java
index 92774f3b53..158e7a2639 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionReprocessForAdvancedPaymentAllocationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionReprocessForAdvancedPaymentAllocationTest.java
@@ -120,7 +120,7 @@ public class 
LoanTransactionReprocessForAdvancedPaymentAllocationTest extends Ba
                             
.transactionAmount(50.0).externalId(loanTransactionExternalIdStr));
 
             // verify transaction amounts
-            verifyTransaction(LocalDate.of(2023, 2, 20), 50.0f, 0.0f, 0.0f, 
50.0f, 0.0f, loanId, "repayment");
+            verifyTransaction(LocalDate.of(2023, 2, 20), 50.0f, 50.0f, 0.0f, 
0.0f, 0.0f, loanId, "repayment");
 
             // add loan charge for a date later than repayment date
             // apply penalty
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/RefundForActiveLoansWithAdvancedPaymentAllocationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/RefundForActiveLoansWithAdvancedPaymentAllocationTest.java
index 35a2b1daac..6499611820 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/RefundForActiveLoansWithAdvancedPaymentAllocationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/RefundForActiveLoansWithAdvancedPaymentAllocationTest.java
@@ -389,11 +389,11 @@ public class 
RefundForActiveLoansWithAdvancedPaymentAllocationTest extends BaseL
             assertEquals(LocalDate.of(2023, 1, 31), 
firstRepaymentInstallment.getDueDate());
 
             assertEquals(feePortion, 
Utils.getDoubleValue(secondRepaymentInstallment.getFeeChargesDue()));
-            assertEquals(0.00, 
Utils.getDoubleValue(secondRepaymentInstallment.getFeeChargesOutstanding()));
+            assertEquals(50.00, 
Utils.getDoubleValue(secondRepaymentInstallment.getFeeChargesOutstanding()));
             assertEquals(penaltyPortion, 
Utils.getDoubleValue(secondRepaymentInstallment.getPenaltyChargesDue()));
-            assertEquals(0.00, 
Utils.getDoubleValue(secondRepaymentInstallment.getPenaltyChargesOutstanding()));
+            assertEquals(100.00, 
Utils.getDoubleValue(secondRepaymentInstallment.getPenaltyChargesOutstanding()));
             assertEquals(400.00, 
Utils.getDoubleValue(secondRepaymentInstallment.getTotalDueForPeriod()));
-            assertEquals(0.00, 
Utils.getDoubleValue(secondRepaymentInstallment.getTotalOutstandingForPeriod()));
+            assertEquals(150.00, 
Utils.getDoubleValue(secondRepaymentInstallment.getTotalOutstandingForPeriod()));
             assertEquals(LocalDate.of(2023, 3, 2), 
secondRepaymentInstallment.getDueDate());
 
             assertEquals(0.00, 
Utils.getDoubleValue(thirdRepaymentInstallment.getFeeChargesDue()));
@@ -401,7 +401,7 @@ public class 
RefundForActiveLoansWithAdvancedPaymentAllocationTest extends BaseL
             assertEquals(0.00, 
Utils.getDoubleValue(thirdRepaymentInstallment.getPenaltyChargesDue()));
             assertEquals(0.00, 
Utils.getDoubleValue(thirdRepaymentInstallment.getPenaltyChargesOutstanding()));
             assertEquals(250.00, 
Utils.getDoubleValue(thirdRepaymentInstallment.getTotalDueForPeriod()));
-            assertEquals(240.00, 
Utils.getDoubleValue(thirdRepaymentInstallment.getTotalOutstandingForPeriod()));
+            assertEquals(90.00, 
Utils.getDoubleValue(thirdRepaymentInstallment.getTotalOutstandingForPeriod()));
             assertEquals(LocalDate.of(2023, 4, 1), 
thirdRepaymentInstallment.getDueDate());
 
             loanTransactionHelper.makeRefundByCash("28 January 2023", 15.0f, 
loanId);
@@ -424,13 +424,13 @@ public class 
RefundForActiveLoansWithAdvancedPaymentAllocationTest extends BaseL
             assertEquals(LocalDate.of(2023, 1, 31), 
firstRepaymentInstallment.getDueDate());
 
             assertEquals(feePortion, 
Utils.getDoubleValue(secondRepaymentInstallment.getFeeChargesDue()));
-            assertEquals(0.00, 
Utils.getDoubleValue(secondRepaymentInstallment.getFeeChargesOutstanding()));
+            assertEquals(50.00, 
Utils.getDoubleValue(secondRepaymentInstallment.getFeeChargesOutstanding()));
             assertEquals(penaltyPortion, 
Utils.getDoubleValue(secondRepaymentInstallment.getPenaltyChargesDue()));
-            assertEquals(0.00, 
Utils.getDoubleValue(secondRepaymentInstallment.getPenaltyChargesOutstanding()));
+            assertEquals(100.00, 
Utils.getDoubleValue(secondRepaymentInstallment.getPenaltyChargesOutstanding()));
             assertEquals(250.00, 
Utils.getDoubleValue(secondRepaymentInstallment.getPrincipalDue()));
-            assertEquals(5.00, 
Utils.getDoubleValue(secondRepaymentInstallment.getPrincipalOutstanding()));
+            assertEquals(0.00, 
Utils.getDoubleValue(secondRepaymentInstallment.getPrincipalOutstanding()));
             assertEquals(400.00, 
Utils.getDoubleValue(secondRepaymentInstallment.getTotalDueForPeriod()));
-            assertEquals(5.00, 
Utils.getDoubleValue(secondRepaymentInstallment.getTotalOutstandingForPeriod()));
+            assertEquals(150.00, 
Utils.getDoubleValue(secondRepaymentInstallment.getTotalOutstandingForPeriod()));
             assertEquals(LocalDate.of(2023, 3, 2), 
secondRepaymentInstallment.getDueDate());
 
             assertEquals(0.00, 
Utils.getDoubleValue(thirdRepaymentInstallment.getFeeChargesDue()));
@@ -438,7 +438,7 @@ public class 
RefundForActiveLoansWithAdvancedPaymentAllocationTest extends BaseL
             assertEquals(0.00, 
Utils.getDoubleValue(thirdRepaymentInstallment.getPenaltyChargesDue()));
             assertEquals(0.00, 
Utils.getDoubleValue(thirdRepaymentInstallment.getPenaltyChargesOutstanding()));
             assertEquals(250.00, 
Utils.getDoubleValue(thirdRepaymentInstallment.getTotalDueForPeriod()));
-            assertEquals(250.00, 
Utils.getDoubleValue(thirdRepaymentInstallment.getTotalOutstandingForPeriod()));
+            assertEquals(105.0, 
Utils.getDoubleValue(thirdRepaymentInstallment.getTotalOutstandingForPeriod()));
             assertEquals(LocalDate.of(2023, 4, 1), 
thirdRepaymentInstallment.getDueDate());
 
             // fully unpaying the second installment


Reply via email to