You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ad...@apache.org on 2025/07/15 08:47:01 UTC

(fineract) branch develop updated (35c51278f9 -> 42ff9743dd)

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

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


    from 35c51278f9 FINERACT-2181: Change execution order in 1029_add_installment_amount_in_multiples_of_to_loan.xml
     new 880580f736 FINERACT-2311: Buy down fee - final amortization
     new 42ff9743dd FINERACT-2311: added e2e auto test scenarios for add buy down fee final amortization with pay off and charge-off

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../test/data/loanproduct/DefaultLoanProduct.java  |   1 +
 .../test/factory/LoanProductsRequestFactory.java   |  22 +
 .../global/LoanProductGlobalInitializerStep.java   |  29 +-
 .../test/stepdef/common/JournalEntriesStepDef.java |  98 ++--
 .../fineract/test/support/TestContextKey.java      |   1 +
 .../features/AssetExternalization.feature          |  14 +-
 .../resources/features/LoanBuyDownFees.feature     | 500 +++++++++++++++++++--
 .../features/LoanCapitalizedIncome.feature         |  19 +-
 .../portfolio/loanaccount/domain/Loan.java         |   5 +-
 .../loanaccount/domain/LoanTransaction.java        |  16 +
 ...oanBuyDownFeeAmortizationProcessingService.java |   7 +
 ...=> LoanBuyDownFeeAmortizationEventService.java} |  37 +-
 ...uyDownFeeAmortizationProcessingServiceImpl.java | 128 ++++++
 ...nCapitalizedIncomeAmortizationEventService.java |   2 +-
 .../starter/LoanAccountConfiguration.java          |   9 +
 15 files changed, 798 insertions(+), 90 deletions(-)
 copy fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/{LoanCapitalizedIncomeAmortizationEventService.java => LoanBuyDownFeeAmortizationEventService.java} (71%)


(fineract) 01/02: FINERACT-2311: Buy down fee - final amortization

Posted by ad...@apache.org.
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

commit 880580f73693c89bb3bb24e44cceb57c63c36e85
Author: adam.magyari <ma...@gmail.com>
AuthorDate: Thu Jul 10 11:42:57 2025 +0200

    FINERACT-2311: Buy down fee - final amortization
    
    - early repayment
    - write off
    - charge-off
---
 .../resources/features/LoanBuyDownFees.feature     |  46 ++++++--
 .../portfolio/loanaccount/domain/Loan.java         |   5 +-
 .../loanaccount/domain/LoanTransaction.java        |  16 +++
 ...oanBuyDownFeeAmortizationProcessingService.java |   7 ++
 ...=> LoanBuyDownFeeAmortizationEventService.java} |  37 +++---
 ...uyDownFeeAmortizationProcessingServiceImpl.java | 128 +++++++++++++++++++++
 ...nCapitalizedIncomeAmortizationEventService.java |   2 +-
 .../starter/LoanAccountConfiguration.java          |   9 ++
 8 files changed, 216 insertions(+), 34 deletions(-)

diff --git a/fineract-e2e-tests-runner/src/test/resources/features/LoanBuyDownFees.feature b/fineract-e2e-tests-runner/src/test/resources/features/LoanBuyDownFees.feature
index ac6ef6ccd9..cd538a2d47 100644
--- a/fineract-e2e-tests-runner/src/test/resources/features/LoanBuyDownFees.feature
+++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanBuyDownFees.feature
@@ -327,12 +327,17 @@ Feature:Feature: Buy Down Fees
     When Loan Pay-off is made on "1 March 2024"
     Then Loan's all installments have obligations met
     Then Loan Transactions tab has the following data:
-      | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
-      | 01 January 2024  | Disbursement     | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
-      | 01 January 2024  | Buy Down Fee     | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
-      | 01 February 2024 | Repayment        | 33.72  | 33.14     | 0.58     | 0.0  | 0.0       | 66.86        | false    |
-      | 01 March 2024    | Repayment        | 67.25  | 66.86     | 0.39     | 0.0  | 0.0       | 0.0          | false    |
-      | 01 March 2024    | Accrual          | 0.97   | 0.0       | 0.97     | 0.0  | 0.0       | 0.0          | false    |
+      | Transaction date | Transaction Type          | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
+      | 01 January 2024  | Disbursement              | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 January 2024  | Buy Down Fee              | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 February 2024 | Repayment                 | 33.72  | 33.14     | 0.58     | 0.0  | 0.0       | 66.86        | false    |
+      | 01 March 2024    | Repayment                 | 67.25  | 66.86     | 0.39     | 0.0  | 0.0       | 0.0          | false    |
+      | 01 March 2024    | Accrual                   | 0.97   | 0.0       | 0.97     | 0.0  | 0.0       | 0.0          | false    |
+      | 01 March 2024    | Buy Down Fee Amortization | 50.0   | 0.0       | 50.0     | 0.0  | 0.0       | 0.0          | false    |
+    And Loan Transactions tab has a "BUY_DOWN_FEE_AMORTIZATION" transaction with date "01 March 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | INCOME    | 450281       | Income From Buy Down        |       | 50.0   |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 50.0  |        |
 
   @TestRailId:C3828
   Scenario: Verify loan with Buy Down fees and early payoff and daily amortization - UC2.2
@@ -508,6 +513,11 @@ Feature:Feature: Buy Down Fees
 
       | 01 March 2024    | Repayment                 | 67.25  | 66.86     | 0.39     | 0.0  | 0.0       | 0.0          | false    |
       | 01 March 2024    | Accrual                   | 0.01   | 0.0       | 0.01     | 0.0  | 0.0       | 0.0          | false    |
+      | 01 March 2024    | Buy Down Fee Amortization | 17.03  | 0.0       | 17.03    | 0.0  | 0.0       | 0.0          | false    |
+    And Loan Transactions tab has a "BUY_DOWN_FEE_AMORTIZATION" transaction with date "01 March 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | INCOME    | 450281       | Income From Buy Down        |       | 17.03  |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 17.03 |        |
 
   @TestRailId:C3772
   Scenario: Verify loan with Buy Down fees and charge-off - UC3.1
@@ -556,12 +566,18 @@ Feature:Feature: Buy Down Fees
       | EXPENSE   | 744007       | Credit Loss/Bad Debt       |  66.86 |        |
       | INCOME    | 404001       | Interest Income Charge Off |   0.59 |        |
     Then Loan Transactions tab has the following data:
-      | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
-      | 01 January 2024  | Disbursement     | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
-      | 01 January 2024  | Buy Down Fee     | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
-      | 01 February 2024 | Repayment        | 33.72  | 33.14     | 0.58     | 0.0  | 0.0       | 66.86        | false    |
-      | 01 March 2024    | Accrual          | 0.97   | 0.0       | 0.97     | 0.0  | 0.0       | 0.0          | false    |
-      | 01 March 2024    | Charge-off       | 67.45  | 66.86     | 0.59     | 0.0  | 0.0       | 0.0          | false    |
+      | Transaction date | Transaction Type          | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
+      | 01 January 2024  | Disbursement              | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 January 2024  | Buy Down Fee              | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 February 2024 | Repayment                 | 33.72  | 33.14     | 0.58     | 0.0  | 0.0       | 66.86        | false    |
+      | 01 March 2024    | Buy Down Fee Amortization | 33.52  | 0.0       | 33.52    | 0.0  | 0.0       | 0.0          | false    |
+      | 01 March 2024    | Accrual                   | 0.97   | 0.0       | 0.97     | 0.0  | 0.0       | 0.0          | false    |
+      | 01 March 2024    | Charge-off                | 67.45  | 66.86     | 0.59     | 0.0  | 0.0       | 0.0          | false    |
+      | 01 March 2024    | Buy Down Fee Amortization | 16.48  | 0.0       | 16.48    | 0.0  | 0.0       | 0.0          | false    |
+    And Loan Transactions tab has a "BUY_DOWN_FEE_AMORTIZATION" transaction with date "01 March 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | EXPENSE   | 744007       | Credit Loss/Bad Debt        |       | 16.48  |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 16.48 |        |
 
     When Loan Pay-off is made on "1 March 2024"
     Then Loan's all installments have obligations met
@@ -745,8 +761,14 @@ Feature:Feature: Buy Down Fees
       | 29 February 2024 | Accrual                   | 0.02   | 0.0       | 0.02     | 0.0  | 0.0       | 0.0          | false    |
       | 29 February 2024 | Buy Down Fee Amortization | 0.55   | 0.0       | 0.55     | 0.0  | 0.0       | 0.0          | false    |
 
+      | 01 March 2024    | Buy Down Fee Amortization | 0.55   | 0.0       | 0.55     | 0.0  | 0.0       | 0.0          | false    |
       | 01 March 2024    | Accrual                   | 0.01   | 0.0       | 0.01     | 0.0  | 0.0       | 0.0          | false    |
       | 01 March 2024    | Charge-off                | 67.45  | 66.86     | 0.59     | 0.0  | 0.0       | 0.0          | false    |
+      | 01 March 2024    | Buy Down Fee Amortization | 16.48  | 0.0       | 16.48    | 0.0  | 0.0       | 0.0          | false    |
+    And Loan Transactions tab has a "BUY_DOWN_FEE_AMORTIZATION" transaction with date "01 March 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | EXPENSE   | 744007       | Credit Loss/Bad Debt        |       | 16.48  |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 16.48 |        |
 
     When Loan Pay-off is made on "1 March 2024"
     Then Loan's all installments have obligations met
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 337b3fd472..07cc2744c0 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
@@ -1755,8 +1755,9 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
 
     public LoanTransaction getLastUserTransaction() {
         return getLoanTransactions().stream() //
-                .filter(t -> t.isNotReversed()
-                        && !(t.isAccrual() || t.isAccrualAdjustment() || t.isIncomePosting() || t.isCapitalizedIncomeAmortization())) //
+                .filter(t -> t.isNotReversed() && !(t.isAccrual() || t.isAccrualAdjustment() || t.isIncomePosting()
+                        || t.isCapitalizedIncomeAmortization() || t.isCapitalizedIncomeAmortizationAdjustment()
+                        || t.isBuyDownFeeAmortization() || t.isBuyDownFeeAmortizationAdjustment())) //
                 .reduce((first, second) -> second) //
                 .orElse(null);
     }
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
index 62c49d807b..d8dc5940b3 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
@@ -706,6 +706,10 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
         return LoanTransactionType.CAPITALIZED_INCOME_AMORTIZATION.equals(getTypeOf()) && isNotReversed();
     }
 
+    public boolean isCapitalizedIncomeAmortizationAdjustment() {
+        return LoanTransactionType.CAPITALIZED_INCOME_AMORTIZATION_ADJUSTMENT.equals(getTypeOf()) && isNotReversed();
+    }
+
     public boolean isCapitalizedIncomeAdjustment() {
         return LoanTransactionType.CAPITALIZED_INCOME_ADJUSTMENT.equals(getTypeOf()) && isNotReversed();
     }
@@ -998,4 +1002,16 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
     public boolean isBuyDownFee() {
         return LoanTransactionType.BUY_DOWN_FEE.equals(this.typeOf);
     }
+
+    public boolean isBuyDownFeeAdjustment() {
+        return LoanTransactionType.BUY_DOWN_FEE_ADJUSTMENT.equals(this.typeOf);
+    }
+
+    public boolean isBuyDownFeeAmortization() {
+        return LoanTransactionType.BUY_DOWN_FEE_AMORTIZATION.equals(this.typeOf);
+    }
+
+    public boolean isBuyDownFeeAmortizationAdjustment() {
+        return LoanTransactionType.BUY_DOWN_FEE_AMORTIZATION_ADJUSTMENT.equals(this.typeOf);
+    }
 }
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanBuyDownFeeAmortizationProcessingService.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanBuyDownFeeAmortizationProcessingService.java
index 8c1cc6a043..9caee39923 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanBuyDownFeeAmortizationProcessingService.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanBuyDownFeeAmortizationProcessingService.java
@@ -20,9 +20,16 @@ package org.apache.fineract.portfolio.loanaccount.service;
 
 import java.time.LocalDate;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
 import org.springframework.lang.NonNull;
 
 public interface LoanBuyDownFeeAmortizationProcessingService {
 
     void processBuyDownFeeAmortizationTillDate(@NonNull Loan loan, @NonNull LocalDate tillDate, boolean addJournal);
+
+    void processBuyDownFeeAmortizationOnLoanClosure(@NonNull Loan loan, boolean addJournal);
+
+    void processBuyDownFeeAmortizationOnLoanChargeOff(@NonNull Loan loan, @NonNull LoanTransaction chargeOffTransaction);
+
+    void processBuyDownFeeAmortizationOnLoanUndoChargeOff(@NonNull LoanTransaction loanTransaction);
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanCapitalizedIncomeAmortizationEventService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanBuyDownFeeAmortizationEventService.java
similarity index 71%
copy from fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanCapitalizedIncomeAmortizationEventService.java
copy to fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanBuyDownFeeAmortizationEventService.java
index 0036e1ba83..b300a51d84 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanCapitalizedIncomeAmortizationEventService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanBuyDownFeeAmortizationEventService.java
@@ -35,10 +35,10 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
 
 @Slf4j
 @RequiredArgsConstructor
-public class LoanCapitalizedIncomeAmortizationEventService {
+public class LoanBuyDownFeeAmortizationEventService {
 
     private final BusinessEventNotifierService businessEventNotifierService;
-    private final LoanCapitalizedIncomeAmortizationProcessingService loanCapitalizedIncomeAmortizationProcessingService;
+    private final LoanBuyDownFeeAmortizationProcessingService loanBuyDownFeeAmortizationProcessingService;
 
     @PostConstruct
     public void addListeners() {
@@ -56,10 +56,10 @@ public class LoanCapitalizedIncomeAmortizationEventService {
         public void onBusinessEvent(final LoanCloseBusinessEvent event) {
             final Loan loan = event.get();
             final LoanStatus status = loan.getStatus();
-            if (loan.getLoanProductRelatedDetail().isEnableIncomeCapitalization()
+            if (loan.getLoanProductRelatedDetail().isEnableBuyDownFee()
                     && (status.isClosedObligationsMet() || status.isClosedWrittenOff() || status.isOverpaid())) {
-                log.debug("Loan closure on capitalized income amortization for loan {}", loan.getId());
-                loanCapitalizedIncomeAmortizationProcessingService.processCapitalizedIncomeAmortizationOnLoanClosure(loan, false);
+                log.debug("Loan closure on buy down fee amortization for loan {}", loan.getId());
+                loanBuyDownFeeAmortizationProcessingService.processBuyDownFeeAmortizationOnLoanClosure(loan, false);
             }
         }
     }
@@ -70,10 +70,10 @@ public class LoanCapitalizedIncomeAmortizationEventService {
         public void onBusinessEvent(final LoanBalanceChangedBusinessEvent event) {
             final Loan loan = event.get();
             final LoanStatus status = loan.getStatus();
-            if (loan.getLoanProductRelatedDetail().isEnableIncomeCapitalization()
+            if (loan.getLoanProductRelatedDetail().isEnableBuyDownFee()
                     && (status.isClosedObligationsMet() || status.isClosedWrittenOff() || status.isOverpaid())) {
-                log.debug("Loan balance change on capitalized income amortization for loan {}", loan.getId());
-                loanCapitalizedIncomeAmortizationProcessingService.processCapitalizedIncomeAmortizationOnLoanClosure(loan, true);
+                log.debug("Loan balance change on buy down fee amortization for loan {}", loan.getId());
+                loanBuyDownFeeAmortizationProcessingService.processBuyDownFeeAmortizationOnLoanClosure(loan, true);
             }
         }
     }
@@ -84,10 +84,9 @@ public class LoanCapitalizedIncomeAmortizationEventService {
         public void onBusinessEvent(final LoanChargeOffPostBusinessEvent event) {
             final LoanTransaction loanTransaction = event.get();
             final Loan loan = loanTransaction.getLoan();
-            if (loan.getLoanProductRelatedDetail().isEnableIncomeCapitalization() && loan.isChargedOff() && loanTransaction.isChargeOff()) {
-                log.debug("Loan charge-off on capitalized income amortization for loan {}", loan.getId());
-                loanCapitalizedIncomeAmortizationProcessingService.processCapitalizedIncomeAmortizationOnLoanChargeOff(loan,
-                        loanTransaction);
+            if (loan.getLoanProductRelatedDetail().isEnableBuyDownFee() && loan.isChargedOff() && loanTransaction.isChargeOff()) {
+                log.debug("Loan charge-off on buy down fee amortization for loan {}", loan.getId());
+                loanBuyDownFeeAmortizationProcessingService.processBuyDownFeeAmortizationOnLoanChargeOff(loan, loanTransaction);
             }
         }
     }
@@ -97,10 +96,10 @@ public class LoanCapitalizedIncomeAmortizationEventService {
         @Override
         public void onBusinessEvent(final LoanChargeOffPreBusinessEvent event) {
             final Loan loan = event.get();
-            if (loan.getLoanProductRelatedDetail().isEnableIncomeCapitalization()) {
-                log.debug("Loan pre charge-off capitalized income amortization for loan {}", loan.getId());
-                loanCapitalizedIncomeAmortizationProcessingService.processCapitalizedIncomeAmortizationTillDate(loan,
-                        DateUtils.getBusinessLocalDate(), false);
+            if (loan.getLoanProductRelatedDetail().isEnableBuyDownFee()) {
+                log.debug("Loan pre charge-off buy down fee amortization for loan {}", loan.getId());
+                loanBuyDownFeeAmortizationProcessingService.processBuyDownFeeAmortizationTillDate(loan, DateUtils.getBusinessLocalDate(),
+                        true);
             }
         }
     }
@@ -112,10 +111,10 @@ public class LoanCapitalizedIncomeAmortizationEventService {
             final LoanTransaction loanTransaction = event.get();
             final Loan loan = loanTransaction.getLoan();
             final LoanStatus status = loan.getStatus();
-            if (loan.getLoanProductRelatedDetail().isEnableIncomeCapitalization() && loanTransaction.getTypeOf().isChargeOff()
+            if (loan.getLoanProductRelatedDetail().isEnableBuyDownFee() && loanTransaction.getTypeOf().isChargeOff()
                     && !(loan.isChargedOff() || status.isClosedObligationsMet() || status.isClosedWrittenOff() || status.isOverpaid())) {
-                log.debug("Loan undo charge-off on capitalized income amortization for loan {}", loan.getId());
-                loanCapitalizedIncomeAmortizationProcessingService.processCapitalizedIncomeAmortizationOnLoanUndoChargeOff(loanTransaction);
+                log.debug("Loan undo charge-off on buy down fee amortization for loan {}", loan.getId());
+                loanBuyDownFeeAmortizationProcessingService.processBuyDownFeeAmortizationOnLoanUndoChargeOff(loanTransaction);
             }
         }
     }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanBuyDownFeeAmortizationProcessingServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanBuyDownFeeAmortizationProcessingServiceImpl.java
index c186d42812..4e3f6d0a78 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanBuyDownFeeAmortizationProcessingServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanBuyDownFeeAmortizationProcessingServiceImpl.java
@@ -20,11 +20,16 @@ package org.apache.fineract.portfolio.loanaccount.service;
 
 import java.math.BigDecimal;
 import java.time.LocalDate;
+import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 import lombok.RequiredArgsConstructor;
+import org.apache.fineract.infrastructure.core.domain.ExternalId;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
 import org.apache.fineract.infrastructure.core.service.MathUtil;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
+import org.apache.fineract.infrastructure.event.business.domain.loan.LoanAdjustTransactionBusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanBuyDownFeeAmortizationAdjustmentTransactionCreatedBusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanBuyDownFeeAmortizationTransactionCreatedBusinessEvent;
 import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
@@ -32,6 +37,8 @@ import org.apache.fineract.organisation.monetary.domain.Money;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanBuyDownFeeBalance;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelation;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelationTypeEnum;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
 import org.apache.fineract.portfolio.loanaccount.repository.LoanBuyDownFeeBalanceRepository;
 import org.apache.fineract.portfolio.loanaccount.util.BuyDownFeeAmortizationUtil;
@@ -102,6 +109,127 @@ public class LoanBuyDownFeeAmortizationProcessingServiceImpl implements LoanBuyD
         }
     }
 
+    @Override
+    @Transactional
+    public void processBuyDownFeeAmortizationOnLoanClosure(@NonNull final Loan loan, final boolean addJournal) {
+        List<Long> existingTransactionIds = Collections.emptyList();
+        List<Long> existingReversedTransactionIds = Collections.emptyList();
+        if (addJournal) {
+            existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
+            existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
+        }
+
+        final LocalDate transactionDate = getFinalBuyDownFeeAmortizationTransactionDate(loan);
+        final Optional<LoanTransaction> amortizationTransaction = createBuyDownFeeAmortizationTransaction(loan, transactionDate, false,
+                null);
+        amortizationTransaction.ifPresent(loanTransaction -> {
+            if (loanTransaction.isBuyDownFeeAmortization()) {
+                businessEventNotifierService
+                        .notifyPostBusinessEvent(new LoanBuyDownFeeAmortizationTransactionCreatedBusinessEvent(loanTransaction));
+            } else {
+                businessEventNotifierService
+                        .notifyPostBusinessEvent(new LoanBuyDownFeeAmortizationAdjustmentTransactionCreatedBusinessEvent(loanTransaction));
+            }
+        });
+
+        if (addJournal) {
+            journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
+        }
+    }
+
+    @Override
+    @Transactional
+    public void processBuyDownFeeAmortizationOnLoanChargeOff(@NonNull final Loan loan,
+            @NonNull final LoanTransaction chargeOffTransaction) {
+        final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
+        final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
+
+        LocalDate transactionDate = loan.getChargedOffOnDate();
+        if (transactionDate == null) {
+            transactionDate = DateUtils.getBusinessLocalDate();
+        }
+
+        final Optional<LoanTransaction> amortizationTransaction = createBuyDownFeeAmortizationTransaction(loan, transactionDate, true,
+                chargeOffTransaction);
+        if (amortizationTransaction.isPresent()) {
+            journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
+            if (amortizationTransaction.get().isBuyDownFeeAmortization()) {
+                businessEventNotifierService.notifyPostBusinessEvent(
+                        new LoanBuyDownFeeAmortizationTransactionCreatedBusinessEvent(amortizationTransaction.get()));
+            } else {
+                businessEventNotifierService.notifyPostBusinessEvent(
+                        new LoanBuyDownFeeAmortizationAdjustmentTransactionCreatedBusinessEvent(amortizationTransaction.get()));
+            }
+        }
+    }
+
+    @Override
+    @Transactional
+    public void processBuyDownFeeAmortizationOnLoanUndoChargeOff(@NonNull final LoanTransaction loanTransaction) {
+        final Loan loan = loanTransaction.getLoan();
+        final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
+        final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
+
+        loan.getLoanTransactions().stream().filter(LoanTransaction::isBuyDownFeeAmortization)
+                .filter(transaction -> transaction.getTransactionDate().equals(loanTransaction.getTransactionDate())
+                        && transaction.getLoanTransactionRelations().stream()
+                                .anyMatch(rel -> LoanTransactionRelationTypeEnum.RELATED.equals(rel.getRelationType())
+                                        && rel.getToTransaction().equals(loanTransaction)))
+                .forEach(transaction -> {
+                    transaction.reverse();
+                    final LoanAdjustTransactionBusinessEvent.Data data = new LoanAdjustTransactionBusinessEvent.Data(transaction);
+                    businessEventNotifierService.notifyPostBusinessEvent(new LoanAdjustTransactionBusinessEvent(data));
+
+                });
+
+        for (LoanBuyDownFeeBalance balance : loanBuyDownFeeBalanceRepository.findAllByLoanId(loan.getId())) {
+            balance.setUnrecognizedAmount(balance.getChargedOffAmount());
+            balance.setChargedOffAmount(BigDecimal.ZERO);
+        }
+
+        journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
+    }
+
+    private Optional<LoanTransaction> createBuyDownFeeAmortizationTransaction(final Loan loan, final LocalDate transactionDate,
+            final boolean isChargeOff, final LoanTransaction chargeOffTransaction) {
+        ExternalId externalId = externalIdFactory.create();
+
+        final List<LoanBuyDownFeeBalance> balances = loanBuyDownFeeBalanceRepository.findAllByLoanId(loan.getId());
+
+        BigDecimal totalAmortizationAmount = BigDecimal.ZERO;
+        for (LoanBuyDownFeeBalance balance : balances) {
+            List<LoanTransaction> adjustments = loanTransactionRepository.findAdjustments(balance.getLoanTransaction());
+            LocalDate maturityDate = loan.getMaturityDate() != null ? loan.getMaturityDate() : transactionDate;
+            final Money amortizationTillDate = BuyDownFeeAmortizationUtil.calculateTotalAmortizationTillDate(balance, adjustments,
+                    maturityDate, loan.getLoanProductRelatedDetail().getBuyDownFeeStrategy(), maturityDate, loan.getCurrency());
+            totalAmortizationAmount = totalAmortizationAmount.add(amortizationTillDate.getAmount());
+            if (isChargeOff) {
+                balance.setChargedOffAmount(balance.getUnrecognizedAmount());
+            }
+            balance.setUnrecognizedAmount(BigDecimal.ZERO);
+        }
+
+        BigDecimal amortizedAmount = loanTransactionRepository.getAmortizedAmountBuyDownFee(loan);
+        BigDecimal totalUnrecognizedAmount = totalAmortizationAmount.subtract(amortizedAmount);
+        if (MathUtil.isZero(totalUnrecognizedAmount)) {
+            return Optional.empty();
+        }
+
+        final LoanTransaction amortizationTransaction = MathUtil.isGreaterThanZero(totalUnrecognizedAmount)
+                ? LoanTransaction.buyDownFeeAmortization(loan, loan.getOffice(), transactionDate, totalUnrecognizedAmount, externalId)
+                : LoanTransaction.buyDownFeeAmortizationAdjustment(loan,
+                        Money.of(loan.getCurrency(), MathUtil.negate(totalUnrecognizedAmount)), transactionDate, externalId);
+        if (isChargeOff) {
+            amortizationTransaction.getLoanTransactionRelations().add(LoanTransactionRelation.linkToTransaction(amortizationTransaction,
+                    chargeOffTransaction, LoanTransactionRelationTypeEnum.RELATED));
+        }
+
+        loan.addLoanTransaction(amortizationTransaction);
+        loanTransactionRepository.saveAndFlush(amortizationTransaction);
+
+        return Optional.of(amortizationTransaction);
+    }
+
     private LocalDate getFinalBuyDownFeeAmortizationTransactionDate(final Loan loan) {
         return switch (loan.getStatus()) {
             case CLOSED_OBLIGATIONS_MET -> loan.getClosedOnDate();
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanCapitalizedIncomeAmortizationEventService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanCapitalizedIncomeAmortizationEventService.java
index 0036e1ba83..dcdbebcf6f 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanCapitalizedIncomeAmortizationEventService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanCapitalizedIncomeAmortizationEventService.java
@@ -100,7 +100,7 @@ public class LoanCapitalizedIncomeAmortizationEventService {
             if (loan.getLoanProductRelatedDetail().isEnableIncomeCapitalization()) {
                 log.debug("Loan pre charge-off capitalized income amortization for loan {}", loan.getId());
                 loanCapitalizedIncomeAmortizationProcessingService.processCapitalizedIncomeAmortizationTillDate(loan,
-                        DateUtils.getBusinessLocalDate(), false);
+                        DateUtils.getBusinessLocalDate(), true);
             }
         }
     }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java
index 60358ea5f7..23731b0b61 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java
@@ -123,6 +123,7 @@ import org.apache.fineract.portfolio.loanaccount.service.LoanArrearsAgingService
 import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
 import org.apache.fineract.portfolio.loanaccount.service.LoanAssemblerImpl;
 import org.apache.fineract.portfolio.loanaccount.service.LoanBalanceService;
+import org.apache.fineract.portfolio.loanaccount.service.LoanBuyDownFeeAmortizationEventService;
 import org.apache.fineract.portfolio.loanaccount.service.LoanBuyDownFeeAmortizationProcessingService;
 import org.apache.fineract.portfolio.loanaccount.service.LoanBuyDownFeeAmortizationProcessingServiceImpl;
 import org.apache.fineract.portfolio.loanaccount.service.LoanCalculateRepaymentPastDueService;
@@ -573,4 +574,12 @@ public class LoanAccountConfiguration {
         return new LoanBuyDownFeeAmortizationProcessingServiceImpl(loanTransactionRepository, loanBuyDownFeeBalanceRepository,
                 businessEventNotifierService, journalEntryPoster, externalIdFactory);
     }
+
+    @Bean
+    @ConditionalOnMissingBean(LoanBuyDownFeeAmortizationEventService.class)
+    public LoanBuyDownFeeAmortizationEventService loanBuyDownFeeAmortizationEventService(
+            BusinessEventNotifierService businessEventNotifierService,
+            LoanBuyDownFeeAmortizationProcessingService loanBuyDownFeeAmortizationProcessingService) {
+        return new LoanBuyDownFeeAmortizationEventService(businessEventNotifierService, loanBuyDownFeeAmortizationProcessingService);
+    }
 }


(fineract) 02/02: FINERACT-2311: added e2e auto test scenarios for add buy down fee final amortization with pay off and charge-off

Posted by ad...@apache.org.
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

commit 42ff9743dd8b9c28af878d43a67d77a36c7900f2
Author: MarianaDmytrivBinariks <md...@binariks.com>
AuthorDate: Mon Jul 14 18:28:18 2025 +0300

    FINERACT-2311: added e2e auto test scenarios for add buy down fee final amortization with pay off and charge-off
---
 .../test/data/loanproduct/DefaultLoanProduct.java  |   1 +
 .../test/factory/LoanProductsRequestFactory.java   |  22 +
 .../global/LoanProductGlobalInitializerStep.java   |  29 +-
 .../test/stepdef/common/JournalEntriesStepDef.java |  98 +++--
 .../fineract/test/support/TestContextKey.java      |   1 +
 .../features/AssetExternalization.feature          |  14 +-
 .../resources/features/LoanBuyDownFees.feature     | 458 ++++++++++++++++++++-
 .../features/LoanCapitalizedIncome.feature         |  19 +-
 8 files changed, 584 insertions(+), 58 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 5cd25a4e87..c302c5f083 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
@@ -131,6 +131,7 @@ public enum DefaultLoanProduct implements LoanProduct {
     LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_IR_DAILY_TILL_REST_FREQUENCY_DATE_LAST_INSTALLMENT, //
     LP2_PROGRESSIVE_ADVANCED_PAYMENT_ALLOCATION_CAPITALIZED_INCOME, //
     LP2_PROGRESSIVE_ADVANCED_PAYMENT_ALLOCATION_BUYDOWN_FEES, //
+    LP2_PROGRESSIVE_ADVANCED_PAYMENT_ALLOCATION_BUYDOWN_FEES_CHARGE_OFF_REASON, //
     LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALC_DAILY_CAPITALIZED_INCOME_ADJ_CUSTOM_ALLOC, //
     LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALC_DAILY_CAPITALIZED_INCOME, //
     LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALC_DAILY_CAPITALIZED_INCOME_FEE, //
diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/LoanProductsRequestFactory.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/LoanProductsRequestFactory.java
index b742b8655e..3ef70564cf 100644
--- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/LoanProductsRequestFactory.java
+++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/LoanProductsRequestFactory.java
@@ -1754,4 +1754,26 @@ public class LoanProductsRequestFactory {
                 .buyDownExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.BUY_DOWN_EXPENSE))//
                 .incomeFromBuyDownAccountId(accountTypeResolver.resolve(DefaultAccountType.INCOME_FROM_BUY_DOWN));//
     }
+
+    public PostLoanProductsRequest defaultLoanProductsRequestLP2ChargeOffReasonToExpenseAccountMappingsWithBuyDownFee() {
+
+        Long chargeOffReasonId = codeHelper.retrieveCodeByName(CHARGE_OFF_REASONS).getId();
+
+        List<PostChargeOffReasonToExpenseAccountMappings> chargeOffReasonToExpenseAccountMappings = new ArrayList<>();
+        PostChargeOffReasonToExpenseAccountMappings chargeOffFraudReason = new PostChargeOffReasonToExpenseAccountMappings();
+        PostChargeOffReasonToExpenseAccountMappings chargeOffDelinquentReason = new PostChargeOffReasonToExpenseAccountMappings();
+        PostChargeOffReasonToExpenseAccountMappings chargeOffOtherReason = new PostChargeOffReasonToExpenseAccountMappings();
+        chargeOffFraudReason.chargeOffReasonCodeValueId(codeValueResolver.resolve(chargeOffReasonId, DefaultCodeValue.FRAUD));
+        chargeOffFraudReason.expenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT_FRAUD));
+        chargeOffDelinquentReason.chargeOffReasonCodeValueId(codeValueResolver.resolve(chargeOffReasonId, DefaultCodeValue.DELINQUENT));
+        chargeOffDelinquentReason.expenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT));
+        chargeOffOtherReason.chargeOffReasonCodeValueId(codeValueResolver.resolve(chargeOffReasonId, DefaultCodeValue.OTHER));
+        chargeOffOtherReason.expenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT));
+        chargeOffReasonToExpenseAccountMappings.add(chargeOffFraudReason);
+        chargeOffReasonToExpenseAccountMappings.add(chargeOffDelinquentReason);
+        chargeOffReasonToExpenseAccountMappings.add(chargeOffOtherReason);
+
+        return defaultLoanProductsRequestLP2BuyDownFees()//
+                .chargeOffReasonToExpenseAccountMappings(chargeOffReasonToExpenseAccountMappings);//
+    }
 }
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 74e603d62c..a19f9fabbb 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
@@ -2945,7 +2945,7 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
                 responseLoanProductsRequestLP2ProgressiveAdvPymnt36030InterestRecalcApprovedOverAppliedFlatCapitalizedIncome);
 
         // LP2 with progressive loan schedule + horizontal + interest EMI + 360/30
-        // + interest recalculation=false, buy down fees enabled
+        // + interest recalculation, buy down fees enabled
         final String name114 = DefaultLoanProduct.LP2_PROGRESSIVE_ADVANCED_PAYMENT_ALLOCATION_BUYDOWN_FEES.getName();
         final PostLoanProductsRequest loanProductsRequestLP2ProgressiveAdvPaymentBuyDownFees = loanProductsRequestFactory
                 .defaultLoanProductsRequestLP2BuyDownFees()//
@@ -3334,6 +3334,33 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
                 .createLoanProduct(loanProductsRequestNoInterestRecalculationAllocationPenaltyFirst).execute();
         TestContext.INSTANCE.set(TestContextKey.LP2_NO_INTEREST_RECALCULATION_ALLOCATION_PENALTY_FIRST_RESPONSE,
                 responseLoanProductsRequestNoInterestRecalculationAllocationPenaltyFirst);
+
+        // LP2 with progressive loan schedule + horizontal + interest EMI + 360/30
+        // charge-off reasons to GL account mapping
+        // + interest recalculation, buy down fees enabled
+        final String name128 = DefaultLoanProduct.LP2_PROGRESSIVE_ADVANCED_PAYMENT_ALLOCATION_BUYDOWN_FEES_CHARGE_OFF_REASON.getName();
+        final PostLoanProductsRequest loanProductsRequestLP2ProgressiveAdvPaymentBuyDownFeesWithChargeOffReason = loanProductsRequestFactory
+                .defaultLoanProductsRequestLP2ChargeOffReasonToExpenseAccountMappingsWithBuyDownFee()//
+                .name(name128)//
+                .transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION.getValue())//
+                .loanScheduleType("PROGRESSIVE") //
+                .isInterestRecalculationEnabled(true)//
+                .preClosureInterestCalculationStrategy(1)//
+                .rescheduleStrategyMethod(4)//
+                .interestRecalculationCompoundingMethod(0)//
+                .recalculationRestFrequencyType(2)//
+                .recalculationRestFrequencyInterval(1)//
+                .paymentAllocation(List.of(//
+                        createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), //
+                        createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
+                        createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
+                        createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));//
+        final Response<PostLoanProductsResponse> responseLoanProductsRequestLP2ProgressiveAdvPaymentBuyDownFeesWithChargeOffReason = loanProductsApi
+                .createLoanProduct(loanProductsRequestLP2ProgressiveAdvPaymentBuyDownFeesWithChargeOffReason).execute();
+        TestContext.INSTANCE.set(
+                TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_PROGRESSIVE_ADV_PYMNT_BUYDOWN_FEES_CHARGE_OFF_REASON,
+                responseLoanProductsRequestLP2ProgressiveAdvPaymentBuyDownFeesWithChargeOffReason);
+
     }
 
     public static AdvancedPaymentData createPaymentAllocation(String transactionType, String futureInstallmentAllocationRule,
diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/JournalEntriesStepDef.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/JournalEntriesStepDef.java
index 3aeca48bb8..8ec36b0923 100644
--- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/JournalEntriesStepDef.java
+++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/JournalEntriesStepDef.java
@@ -69,7 +69,6 @@ public class JournalEntriesStepDef extends AbstractStepDef {
         DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
         Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
         long loanId = loanResponse.body().getLoanId();
-        String resourceId = String.valueOf(loanId);
 
         Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
         ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
@@ -83,6 +82,50 @@ public class JournalEntriesStepDef extends AbstractStepDef {
                         && transactionTypeExpected.equals(t.getType().getCode().substring(20)))
                 .collect(Collectors.toList());
 
+        List<List<JournalEntryTransactionItem>> journalLinesActualList = getJournalLinesActualList(transactionsMatch);
+        checkJournalEntryData(journalLinesActualList, loanId, table);
+    }
+
+    public void checkJournalEntryData(List<List<JournalEntryTransactionItem>> journalLinesActualList, long loanId, DataTable table) {
+        String resourceId = String.valueOf(loanId);
+
+        List<List<String>> data = table.asLists();
+        final int expectedCount = data.size() - 1;
+        final int actualCount = journalLinesActualList.stream().mapToInt(List::size).sum();
+        assertThat(actualCount).as("The number of journal entries for the transaction does not match the expected count! Expected: "
+                + expectedCount + ", Actual: " + actualCount).isEqualTo(expectedCount);
+        for (int i = 1; i < data.size(); i++) {
+            List<List<List<String>>> possibleActualValuesList = new ArrayList<>();
+            List<String> expectedValues = data.get(i);
+            boolean containsAnyExpected = false;
+
+            for (int j = 0; j < journalLinesActualList.size(); j++) {
+                List<JournalEntryTransactionItem> journalLinesActual = journalLinesActualList.get(j);
+
+                List<List<String>> actualValuesList = journalLinesActual.stream().map(t -> {
+                    List<String> actualValues = new ArrayList<>();
+                    actualValues.add(t.getGlAccountType().getValue() == null ? null : t.getGlAccountType().getValue());
+                    actualValues.add(t.getGlAccountCode() == null ? null : t.getGlAccountCode());
+                    actualValues.add(t.getGlAccountName() == null ? null : t.getGlAccountName());
+                    actualValues.add("DEBIT".equals(t.getEntryType().getValue()) ? String.valueOf(t.getAmount()) : null);
+                    actualValues.add("CREDIT".equals(t.getEntryType().getValue()) ? String.valueOf(t.getAmount()) : null);
+
+                    return actualValues;
+                }).collect(Collectors.toList());
+                possibleActualValuesList.add(actualValuesList);
+
+                boolean containsExpectedValues = actualValuesList.stream().anyMatch(actualValues -> actualValues.equals(expectedValues));
+                if (containsExpectedValues) {
+                    containsAnyExpected = true;
+                }
+            }
+            assertThat(containsAnyExpected)
+                    .as(ErrorMessageHelper.wrongValueInLineInJournalEntries(resourceId, i, possibleActualValuesList, expectedValues))
+                    .isTrue();
+        }
+    }
+
+    public List<List<JournalEntryTransactionItem>> getJournalLinesActualList(List<GetLoansLoanIdTransactions> transactionsMatch) {
         List<List<JournalEntryTransactionItem>> journalLinesActualList = transactionsMatch.stream().map(t -> {
             String transactionId = "L" + t.getId();
             Response<GetJournalEntriesTransactionIdResponse> journalEntryDataResponse = null;
@@ -116,40 +159,33 @@ public class JournalEntriesStepDef extends AbstractStepDef {
             return journalEntryDataResponse.body().getPageItems();
         }).collect(Collectors.toList());
 
-        List<List<String>> data = table.asLists();
-        final int expectedCount = data.size() - 1;
-        final int actualCount = journalLinesActualList.stream().mapToInt(List::size).sum();
-        assertThat(actualCount).as("The number of journal entries for the transaction does not match the expected count! Expected: "
-                + expectedCount + ", Actual: " + actualCount).isEqualTo(expectedCount);
-        for (int i = 1; i < data.size(); i++) {
-            List<List<List<String>>> possibleActualValuesList = new ArrayList<>();
-            List<String> expectedValues = data.get(i);
-            boolean containsAnyExpected = false;
+        return journalLinesActualList;
+    }
 
-            for (int j = 0; j < journalLinesActualList.size(); j++) {
-                List<JournalEntryTransactionItem> journalLinesActual = journalLinesActualList.get(j);
+    @Then("Loan Transactions tab has {int} a {string} transactions with date {string} which has the following Journal entries:")
+    public void journalEntryDataCheck(int numberTrns, String transactionType, String transactionDate, DataTable table) throws IOException {
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
+        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
+        long loanId = loanResponse.body().getLoanId();
 
-                List<List<String>> actualValuesList = journalLinesActual.stream().map(t -> {
-                    List<String> actualValues = new ArrayList<>();
-                    actualValues.add(t.getGlAccountType().getValue() == null ? null : t.getGlAccountType().getValue());
-                    actualValues.add(t.getGlAccountCode() == null ? null : t.getGlAccountCode());
-                    actualValues.add(t.getGlAccountName() == null ? null : t.getGlAccountName());
-                    actualValues.add("DEBIT".equals(t.getEntryType().getValue()) ? String.valueOf(t.getAmount()) : null);
-                    actualValues.add("CREDIT".equals(t.getEntryType().getValue()) ? String.valueOf(t.getAmount()) : null);
+        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
+        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
 
-                    return actualValues;
-                }).collect(Collectors.toList());
-                possibleActualValuesList.add(actualValuesList);
+        TransactionType transactionType1 = TransactionType.valueOf(transactionType);
+        String transactionTypeExpected = transactionType1.getValue();
 
-                boolean containsExpectedValues = actualValuesList.stream().anyMatch(actualValues -> actualValues.equals(expectedValues));
-                if (containsExpectedValues) {
-                    containsAnyExpected = true;
-                }
-            }
-            assertThat(containsAnyExpected)
-                    .as(ErrorMessageHelper.wrongValueInLineInJournalEntries(resourceId, i, possibleActualValuesList, expectedValues))
-                    .isTrue();
-        }
+        List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
+        List<GetLoansLoanIdTransactions> transactionsMatch = transactions.stream()
+                .filter(t -> transactionDate.equals(formatter.format(t.getDate()))
+                        && transactionTypeExpected.equals(t.getType().getCode().substring(20)))
+                .collect(Collectors.toList());
+        assertThat(transactionsMatch.size())
+                .as("The number of journal entries for the transaction does not match the expected count! Expected: " + numberTrns
+                        + ", Actual: " + transactionsMatch.size())
+                .isEqualTo(numberTrns);
+
+        List<List<JournalEntryTransactionItem>> journalLinesActualList = getJournalLinesActualList(transactionsMatch);
+        checkJournalEntryData(journalLinesActualList, loanId, table);
     }
 
     @Then("Reversed loan capitalized income amortization transaction has the following Journal entries:")
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 9eefa43c57..789b9a5556 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
@@ -156,6 +156,7 @@ public abstract class TestContextKey {
     public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALC_DAILY_CASH_ACCOUNTING_DISBURSEMENT_CHARGES = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationDailyCashBasedDisbursementCharge";
     public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_PROGRESSIVE_ADV_PYMNT_CAPITALIZED_INCOME = "loanProductCreateResponseLP2ProgressiveAdvancedPaymentCapitalizedIncome";
     public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_PROGRESSIVE_ADV_PYMNT_BUYDOWN_FEES = "loanProductCreateResponseLP2ProgressiveAdvancedPaymentBuyDownFees";
+    public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_PROGRESSIVE_ADV_PYMNT_BUYDOWN_FEES_CHARGE_OFF_REASON = "loanProductCreateResponseLP2ProgressiveAdvancedPaymentBuyDownFeesWithChargeOffReason";
     public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALC_DAILY_CAPITALIZED_INCOME_ADJ_CUSTOM_ALLOC = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationDailyCapitalizedIncomeAdjCustomAlloc";
     public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_RECALC_EMI_360_30_MULTIDISB_OVER_APPLIED_PERCENTAGE_CAPITALIZED_INCOME = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationDailyMultidisbursalApprovedOVerAppliedPercentageCapitalizedIncome";
     public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_RECALC_EMI_360_30_MULTIDISB_OVER_APPLIED_FLAT_CAPITALIZED_INCOME = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationDailyMultidisbursalApprovedOVerAppliedFlatCapitalizedIncome";
diff --git a/fineract-e2e-tests-runner/src/test/resources/features/AssetExternalization.feature b/fineract-e2e-tests-runner/src/test/resources/features/AssetExternalization.feature
index 468b4fd59c..c9a18bdfac 100644
--- a/fineract-e2e-tests-runner/src/test/resources/features/AssetExternalization.feature
+++ b/fineract-e2e-tests-runner/src/test/resources/features/AssetExternalization.feature
@@ -1809,15 +1809,15 @@ Feature: Asset Externalization
   @TestRailId:C3800 @AssetExternalizationJournalEntry
   Scenario: Verify manual journal entry with External Asset Owner empty value if asset-externalization is enabled - UC2
     Given Global configuration "asset-externalization-of-non-active-loans" is enabled
-    When Admin sets the business date to "25 June 2025"
-    Then Admin creates manual Journal entry with "88" amount and "20 June 2025" date and without External Asset Owner
+    When Admin sets the business date to "10 June 2025"
+    Then Admin creates manual Journal entry with "88" amount and "10 June 2025" date and without External Asset Owner
     Then Verify manual Journal entry with External Asset Owner "true" and with the following Journal entries:
       | Type      | Account code | Account name              | Debit | Credit | Manual Entry |
       | ASSET     | 112601       | Loans Receivable          | 88.0  |        | true         |
       | LIABILITY | 145023       | Suspense/Clearing account |       | 88.0   | true         |
     Given Global configuration "asset-externalization-of-non-active-loans" is enabled
 
-  @TestRailId:C38001 @AssetExternalizationJournalEntry
+  @TestRailId:C3801 @AssetExternalizationJournalEntry
   Scenario: Verify manual journal entry with External Asset Owner empty value if asset-externalization is enabled for existing loan - UC3
     Given Global configuration "asset-externalization-of-non-active-loans" is enabled
 
@@ -1835,18 +1835,18 @@ Feature: Asset Externalization
       | settlementDate | purchasePriceRatio | status  | effectiveFrom | effectiveTo | Transaction type |
       | 2025-06-01     | 1                  | PENDING | 2025-06-01    | 9999-12-31  | SALE             |
 
-    When Admin sets the business date to "25 June 2025"
-    Then Admin creates manual Journal entry with "99" amount and "20 June 2025" date and without External Asset Owner
+    When Admin sets the business date to "27 June 2025"
+    Then Admin creates manual Journal entry with "99" amount and "27 June 2025" date and unique External Asset Owner
     Then Verify manual Journal entry with External Asset Owner "true" and with the following Journal entries:
       | Type      | Account code | Account name              | Debit | Credit | Manual Entry |
       | ASSET     | 112601       | Loans Receivable          | 99.0  |        | true         |
       | LIABILITY | 145023       | Suspense/Clearing account |       | 99.0   | true         |
     Given Global configuration "asset-externalization-of-non-active-loans" is enabled
 
-    When Loan Pay-off is made on "25 June 2025"
+    When Loan Pay-off is made on "26 June 2025"
     Then Loan's all installments have obligations met
 
-  @TestRailId:C3802 @AssetExternalizationJournalEntry
+  @TestRailId:C3821 @AssetExternalizationJournalEntry
   Scenario: Verify manual journal entry with no External Asset Owner value if asset-externalization is disabled - UC4
     Given Global configuration "asset-externalization-of-non-active-loans" is disabled
     When Admin sets the business date to "25 June 2025"
diff --git a/fineract-e2e-tests-runner/src/test/resources/features/LoanBuyDownFees.feature b/fineract-e2e-tests-runner/src/test/resources/features/LoanBuyDownFees.feature
index cd538a2d47..acc006ea65 100644
--- a/fineract-e2e-tests-runner/src/test/resources/features/LoanBuyDownFees.feature
+++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanBuyDownFees.feature
@@ -520,7 +520,7 @@ Feature:Feature: Buy Down Fees
       | LIABILITY | 145024       | Deferred Capitalized Income | 17.03 |        |
 
   @TestRailId:C3772
-  Scenario: Verify loan with Buy Down fees and charge-off - UC3.1
+  Scenario: Verify loan with Buy Down fees and charge-off transaction - amortization in case of loan charge-off event - UC3.1
     When Admin sets the business date to "1 January 2024"
     And Admin creates a client with random data
     And Admin creates a fully customized loan with the following data:
@@ -574,8 +574,11 @@ Feature:Feature: Buy Down Fees
       | 01 March 2024    | Accrual                   | 0.97   | 0.0       | 0.97     | 0.0  | 0.0       | 0.0          | false    |
       | 01 March 2024    | Charge-off                | 67.45  | 66.86     | 0.59     | 0.0  | 0.0       | 0.0          | false    |
       | 01 March 2024    | Buy Down Fee Amortization | 16.48  | 0.0       | 16.48    | 0.0  | 0.0       | 0.0          | false    |
-    And Loan Transactions tab has a "BUY_DOWN_FEE_AMORTIZATION" transaction with date "01 March 2024" which has the following Journal entries:
+# --- check BDF journal entries for before and after charge-off trn processed --- #
+    And Loan Transactions tab has 2 a "BUY_DOWN_FEE_AMORTIZATION" transactions with date "01 March 2024" which has the following Journal entries:
       | Type      | Account code | Account name                | Debit | Credit |
+      | INCOME    | 450281       | Income From Buy Down        |       | 33.52  |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 33.52 |        |
       | EXPENSE   | 744007       | Credit Loss/Bad Debt        |       | 16.48  |
       | LIABILITY | 145024       | Deferred Capitalized Income | 16.48 |        |
 
@@ -583,7 +586,7 @@ Feature:Feature: Buy Down Fees
     Then Loan's all installments have obligations met
 
   @TestRailId:C3829
-  Scenario: Verify loan with Buy Down fees and charge-off and daily amortization - UC3.2
+  Scenario: Verify loan with Buy Down fees and charge-off transaction - daily amortization and amortization in case of loan charge-off event - UC3.2
     When Admin sets the business date to "1 January 2024"
     And Admin creates a client with random data
     And Admin creates a fully customized loan with the following data:
@@ -765,16 +768,389 @@ Feature:Feature: Buy Down Fees
       | 01 March 2024    | Accrual                   | 0.01   | 0.0       | 0.01     | 0.0  | 0.0       | 0.0          | false    |
       | 01 March 2024    | Charge-off                | 67.45  | 66.86     | 0.59     | 0.0  | 0.0       | 0.0          | false    |
       | 01 March 2024    | Buy Down Fee Amortization | 16.48  | 0.0       | 16.48    | 0.0  | 0.0       | 0.0          | false    |
-    And Loan Transactions tab has a "BUY_DOWN_FEE_AMORTIZATION" transaction with date "01 March 2024" which has the following Journal entries:
+# --- check BDFA journal entries for before and after charge-off trn processed --- #
+    And Loan Transactions tab has 2 a "BUY_DOWN_FEE_AMORTIZATION" transactions with date "01 March 2024" which has the following Journal entries:
       | Type      | Account code | Account name                | Debit | Credit |
+      | INCOME    | 450281       | Income From Buy Down        |       | 0.55   |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 0.55  |        |
       | EXPENSE   | 744007       | Credit Loss/Bad Debt        |       | 16.48  |
       | LIABILITY | 145024       | Deferred Capitalized Income | 16.48 |        |
 
     When Loan Pay-off is made on "1 March 2024"
     Then Loan's all installments have obligations met
 
+  @TestRailId:C3848
+  Scenario: Verify loan with Buy Down fees and undo the charge-off transaction - amortization in case of loan charge-off event should also be reversed  - UC3.3
+    When Admin sets the business date to "1 January 2024"
+    And Admin creates a client with random data
+    And 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_PROGRESSIVE_ADVANCED_PAYMENT_ALLOCATION_BUYDOWN_FEES | 1 January 2024    | 100            | 7                      | DECLINING_BALANCE | DAILY                       | EQUAL_INSTALLMENTS | 3                 | MONTHS                | 1              | MONTHS                 | 3                  | 0                       | 0                      | 0                    | ADVANCED_PAYMENT_ALLOCATION |
+    And Admin successfully approves the loan on "1 January 2024" with "100" amount and expected disbursement date on "1 January 2024"
+    And Admin successfully disburse the loan on "1 January 2024" with "100" EUR transaction amount
+    Then Loan status will be "ACTIVE"
+    When Admin adds buy down fee with "AUTOPAY" payment type to the loan on "1 January 2024" with "50" EUR transaction amount
+    Then Loan Repayment schedule has 3 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 |           | 66.86           | 33.14         | 0.58     | 0.0  | 0.0       | 33.72 | 0.0  | 0.0        | 0.0  | 33.72       |
+      | 2  | 29   | 01 March 2024    |           | 33.53           | 33.33         | 0.39     | 0.0  | 0.0       | 33.72 | 0.0  | 0.0        | 0.0  | 33.72       |
+      | 3  | 31   | 01 April 2024    |           | 0.0             | 33.53         | 0.2     | 0.0  | 0.0       | 33.73 | 0.0  | 0.0        | 0.0  | 33.73       |
+    And Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due    | Paid | In advance | Late | Outstanding |
+      | 100.0         | 1.17     | 0.0  | 0.0       | 101.17 | 0.0  | 0.0        | 0.0  | 101.17      |
+    And Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
+      | 01 January 2024  | Disbursement     | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 January 2024  | Buy Down Fee     | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 0.0          | false    |
+    And Loan Transactions tab has a "BUY_DOWN_FEE" transaction with date "01 January 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | EXPENSE   | 450280       | Buy Down Expense            | 50.0  |        |
+      | LIABILITY | 145024       | Deferred Capitalized Income |       | 50.0   |
+# --- charge-off ---#
+    When Admin sets the business date to "1 February 2024"
+    And Admin does charge-off the loan on "1 February 2024"
+    Then Loan status will be "ACTIVE"
+    And Loan marked as charged-off on "01 February 2024"
+    Then Loan Repayment schedule has 3 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 |           | 66.86           | 33.14         | 0.58     | 0.0  | 0.0       | 33.72 | 0.0  | 0.0        | 0.0  | 33.72       |
+      | 2  | 29   | 01 March 2024    |           | 33.53           | 33.33         | 0.39     | 0.0  | 0.0       | 33.72 | 0.0  | 0.0        | 0.0  | 33.72       |
+      | 3  | 31   | 01 April 2024    |           | 0.0             | 33.53         | 0.2     | 0.0  | 0.0       | 33.73 | 0.0  | 0.0        | 0.0  | 33.73       |
+    And Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due    | Paid | In advance | Late | Outstanding |
+      | 100.0         | 1.17     | 0.0  | 0.0       | 101.17 | 0.0  | 0.0        | 0.0  | 101.17      |
+    And Loan Transactions tab has a "CHARGE_OFF" transaction with date "01 February 2024" which has the following Journal entries:
+      | Type      | Account code | Account name               | Debit  | Credit |
+      | ASSET     | 112601       | Loans Receivable           |        | 100.0  |
+      | ASSET     | 112603       | Interest/Fee Receivable    |        |  1.17  |
+      | EXPENSE   | 744007       | Credit Loss/Bad Debt       | 100.0  |        |
+      | INCOME    | 404001       | Interest Income Charge Off |  1.17  |        |
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type          | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
+      | 01 January 2024  | Disbursement              | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 January 2024  | Buy Down Fee              | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 February 2024 | Buy Down Fee Amortization | 17.58  | 0.0       | 17.58    | 0.0  | 0.0       | 0.0          | false    |
+      | 01 February 2024 | Accrual                   | 0.58   | 0.0       | 0.58     | 0.0  | 0.0       | 0.0          | false    |
+      | 01 February 2024 | Charge-off                | 101.17 | 100.0     | 1.17     | 0.0  | 0.0       | 0.0          | false    |
+      | 01 February 2024 | Buy Down Fee Amortization | 32.42  | 0.0       | 32.42    | 0.0  | 0.0       | 0.0          | false    |
+# --- check BDFA journal entries for before and after charge-off trn processed --- #
+    And Loan Transactions tab has 2 a "BUY_DOWN_FEE_AMORTIZATION" transactions with date "01 February 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | INCOME    | 450281       | Income From Buy Down        |       | 17.58  |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 17.58 |        |
+      | EXPENSE   | 744007       | Credit Loss/Bad Debt        |       | 32.42  |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 32.42 |        |
+# --- charge-off undo ---#
+    Then Admin does a charge-off undo the loan
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type          | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
+      | 01 January 2024  | Disbursement              | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 January 2024  | Buy Down Fee              | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 February 2024 | Buy Down Fee Amortization | 17.58  | 0.0       | 17.58    | 0.0  | 0.0       | 0.0          | false    |
+      | 01 February 2024 | Accrual                   | 0.58   | 0.0       | 0.58     | 0.0  | 0.0       | 0.0          | false    |
+      | 01 February 2024 | Charge-off                | 101.17 | 100.0     | 1.17     | 0.0  | 0.0       | 0.0          | true     |
+    And Loan Transactions tab has a "CHARGE_OFF" transaction with date "01 February 2024" which has the following Journal entries:
+      | Type      | Account code | Account name               | Debit  | Credit |
+      | ASSET     | 112601       | Loans Receivable           |        | 100.0  |
+      | ASSET     | 112603       | Interest/Fee Receivable    |        |  1.17  |
+      | EXPENSE   | 744007       | Credit Loss/Bad Debt       | 100.0  |        |
+      | INCOME    | 404001       | Interest Income Charge Off |  1.17  |        |
+      | ASSET     | 112601       | Loans Receivable           | 100.0  |        |
+      | ASSET     | 112603       | Interest/Fee Receivable    |  1.17  |        |
+      | EXPENSE   | 744007       | Credit Loss/Bad Debt       |        | 100.0  |
+      | INCOME    | 404001       | Interest Income Charge Off |        | 1.17   |
+    And Loan Transactions tab has 1 a "BUY_DOWN_FEE_AMORTIZATION" transactions with date "01 February 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | INCOME    | 450281       | Income From Buy Down        |       | 17.58  |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 17.58 |        |
+
+    When Loan Pay-off is made on "1 February 2024"
+    Then Loan's all installments have obligations met
+
+  @TestRailId:C3849
+  Scenario: Verify loan with Buy Down fees and undo the charge-off a fraud loan - amortization in case of loan charge-off event should also be reversed  - UC3.4
+    When Admin sets the business date to "1 January 2024"
+    And Admin creates a client with random data
+    And 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_PROGRESSIVE_ADVANCED_PAYMENT_ALLOCATION_BUYDOWN_FEES | 1 January 2024    | 100            | 7                      | DECLINING_BALANCE | DAILY                       | EQUAL_INSTALLMENTS | 3                 | MONTHS                | 1              | MONTHS                 | 3                  | 0                       | 0                      | 0                    | ADVANCED_PAYMENT_ALLOCATION |
+    And Admin successfully approves the loan on "1 January 2024" with "100" amount and expected disbursement date on "1 January 2024"
+    And Admin successfully disburse the loan on "1 January 2024" with "100" EUR transaction amount
+    Then Loan status will be "ACTIVE"
+    When Admin adds buy down fee with "AUTOPAY" payment type to the loan on "1 January 2024" with "50" EUR transaction amount
+    Then Loan Repayment schedule has 3 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 |           | 66.86           | 33.14         | 0.58     | 0.0  | 0.0       | 33.72 | 0.0  | 0.0        | 0.0  | 33.72       |
+      | 2  | 29   | 01 March 2024    |           | 33.53           | 33.33         | 0.39     | 0.0  | 0.0       | 33.72 | 0.0  | 0.0        | 0.0  | 33.72       |
+      | 3  | 31   | 01 April 2024    |           | 0.0             | 33.53         | 0.2     | 0.0  | 0.0       | 33.73 | 0.0  | 0.0        | 0.0  | 33.73       |
+    And Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due    | Paid | In advance | Late | Outstanding |
+      | 100.0         | 1.17     | 0.0  | 0.0       | 101.17 | 0.0  | 0.0        | 0.0  | 101.17      |
+    And Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
+      | 01 January 2024  | Disbursement     | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 January 2024  | Buy Down Fee     | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 0.0          | false    |
+    And Loan Transactions tab has a "BUY_DOWN_FEE" transaction with date "01 January 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | EXPENSE   | 450280       | Buy Down Expense            | 50.0  |        |
+      | LIABILITY | 145024       | Deferred Capitalized Income |       | 50.0   |
+
+    Then Admin can successfully set Fraud flag to the loan
+# --- charge-off ---#
+    When Admin sets the business date to "1 February 2024"
+    And Admin does charge-off the loan on "1 February 2024"
+    Then Loan status will be "ACTIVE"
+    And Loan marked as charged-off on "01 February 2024"
+    Then Loan Repayment schedule has 3 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 |           | 66.86           | 33.14         | 0.58     | 0.0  | 0.0       | 33.72 | 0.0  | 0.0        | 0.0  | 33.72       |
+      | 2  | 29   | 01 March 2024    |           | 33.53           | 33.33         | 0.39     | 0.0  | 0.0       | 33.72 | 0.0  | 0.0        | 0.0  | 33.72       |
+      | 3  | 31   | 01 April 2024    |           | 0.0             | 33.53         | 0.2     | 0.0  | 0.0       | 33.73 | 0.0  | 0.0        | 0.0  | 33.73       |
+    And Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due    | Paid | In advance | Late | Outstanding |
+      | 100.0         | 1.17     | 0.0  | 0.0       | 101.17 | 0.0  | 0.0        | 0.0  | 101.17      |
+    And Loan Transactions tab has a "CHARGE_OFF" transaction with date "01 February 2024" which has the following Journal entries:
+      | Type      | Account code | Account name               | Debit  | Credit |
+      | ASSET     | 112601       | Loans Receivable           |        | 100.0  |
+      | ASSET     | 112603       | Interest/Fee Receivable    |        |  1.17  |
+      | EXPENSE   | 744037       | Credit Loss/Bad Debt-Fraud | 100.0  |        |
+      | INCOME    | 404001       | Interest Income Charge Off |  1.17  |        |
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type          | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
+      | 01 January 2024  | Disbursement              | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 January 2024  | Buy Down Fee              | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 February 2024 | Buy Down Fee Amortization | 17.58  | 0.0       | 17.58    | 0.0  | 0.0       | 0.0          | false    |
+      | 01 February 2024 | Accrual                   | 0.58   | 0.0       | 0.58     | 0.0  | 0.0       | 0.0          | false    |
+      | 01 February 2024 | Charge-off                | 101.17 | 100.0     | 1.17     | 0.0  | 0.0       | 0.0          | false    |
+      | 01 February 2024 | Buy Down Fee Amortization | 32.42  | 0.0       | 32.42    | 0.0  | 0.0       | 0.0          | false    |
+# --- check BDFA journal entries for before and after charge-off trn processed --- #
+    And Loan Transactions tab has 2 a "BUY_DOWN_FEE_AMORTIZATION" transactions with date "01 February 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | INCOME    | 450281       | Income From Buy Down        |       | 17.58  |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 17.58 |        |
+      | EXPENSE   | 744037       | Credit Loss/Bad Debt-Fraud  |       | 32.42  |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 32.42 |        |
+# --- charge-off undo ---#
+    Then Admin does a charge-off undo the loan
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type          | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
+      | 01 January 2024  | Disbursement              | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 January 2024  | Buy Down Fee              | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 February 2024 | Buy Down Fee Amortization | 17.58  | 0.0       | 17.58    | 0.0  | 0.0       | 0.0          | false    |
+      | 01 February 2024 | Accrual                   | 0.58   | 0.0       | 0.58     | 0.0  | 0.0       | 0.0          | false    |
+      | 01 February 2024 | Charge-off                | 101.17 | 100.0     | 1.17     | 0.0  | 0.0       | 0.0          | true     |
+    And Loan Transactions tab has a "CHARGE_OFF" transaction with date "01 February 2024" which has the following Journal entries:
+      | Type      | Account code | Account name               | Debit  | Credit |
+      | ASSET     | 112601       | Loans Receivable           |        | 100.0  |
+      | ASSET     | 112603       | Interest/Fee Receivable    |        |  1.17  |
+      | EXPENSE   | 744037       | Credit Loss/Bad Debt-Fraud | 100.0  |        |
+      | INCOME    | 404001       | Interest Income Charge Off |  1.17  |        |
+      | ASSET     | 112601       | Loans Receivable           | 100.0  |        |
+      | ASSET     | 112603       | Interest/Fee Receivable    |  1.17  |        |
+      | EXPENSE   | 744037       | Credit Loss/Bad Debt-Fraud |        | 100.0  |
+      | INCOME    | 404001       | Interest Income Charge Off |        | 1.17   |
+    And Loan Transactions tab has 1 a "BUY_DOWN_FEE_AMORTIZATION" transactions with date "01 February 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | INCOME    | 450281       | Income From Buy Down        |       | 17.58  |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 17.58 |        |
+    When Loan Pay-off is made on "1 February 2024"
+    Then Loan's all installments have obligations met
+
+  @TestRailId:C3850
+  Scenario: Verify loan with Buy Down fees and charge-off with "delinquent" reason - amortization in case of loan charge-off event - UC3.5
+    When Admin sets the business date to "1 January 2024"
+    And Admin creates a client with random data
+    And 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_PROGRESSIVE_ADVANCED_PAYMENT_ALLOCATION_BUYDOWN_FEES_CHARGE_OFF_REASON | 1 January 2024    | 100            | 7                      | DECLINING_BALANCE | DAILY                       | EQUAL_INSTALLMENTS | 3                 | MONTHS                | 1              | MONTHS                 | 3                  | 0                       | 0                      | 0                    | ADVANCED_PAYMENT_ALLOCATION |
+    And Admin successfully approves the loan on "1 January 2024" with "100" amount and expected disbursement date on "1 January 2024"
+    And Admin successfully disburse the loan on "1 January 2024" with "100" EUR transaction amount
+    Then Loan status will be "ACTIVE"
+    When Admin adds buy down fee with "AUTOPAY" payment type to the loan on "1 January 2024" with "50" EUR transaction amount
+    Then Loan Repayment schedule has 3 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 |           | 66.86           | 33.14         | 0.58     | 0.0  | 0.0       | 33.72 | 0.0  | 0.0        | 0.0  | 33.72       |
+      | 2  | 29   | 01 March 2024    |           | 33.53           | 33.33         | 0.39     | 0.0  | 0.0       | 33.72 | 0.0  | 0.0        | 0.0  | 33.72       |
+      | 3  | 31   | 01 April 2024    |           | 0.0             | 33.53         | 0.2     | 0.0  | 0.0       | 33.73 | 0.0  | 0.0        | 0.0  | 33.73       |
+    And Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due    | Paid | In advance | Late | Outstanding |
+      | 100.0         | 1.17     | 0.0  | 0.0       | 101.17 | 0.0  | 0.0        | 0.0  | 101.17      |
+    And Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
+      | 01 January 2024  | Disbursement     | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 January 2024  | Buy Down Fee     | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 0.0          | false    |
+    And Loan Transactions tab has a "BUY_DOWN_FEE" transaction with date "01 January 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | EXPENSE   | 450280       | Buy Down Expense            | 50.0  |        |
+      | LIABILITY | 145024       | Deferred Capitalized Income |       | 50.0   |
+    Then Admin can successfully set Fraud flag to the loan
+    When Admin sets the business date to "25 January 2024"
+    And Admin does charge-off the loan with reason "DELINQUENT" on "25 January 2024"
+    And Loan Transactions tab has a "CHARGE_OFF" transaction with date "25 January 2024" which has the following Journal entries:
+      | Type      | Account code | Account name               | Debit  | Credit |
+      | ASSET     | 112601       | Loans Receivable           |        | 100.0  |
+      | ASSET     | 112603       | Interest/Fee Receivable    |        |  1.17  |
+      | EXPENSE   | 744007       | Credit Loss/Bad Debt       | 100.0  |        |
+      | INCOME    | 404001       | Interest Income Charge Off |  1.17  |        |
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type          | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
+      | 01 January 2024  | Disbursement              | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 January 2024  | Buy Down Fee              | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 25 January 2024  | Buy Down Fee Amortization | 13.74  | 0.0       | 13.74    | 0.0  | 0.0       | 0.0          | false    |
+      | 25 January 2024  | Accrual                   | 0.45   | 0.0       | 0.45     | 0.0  | 0.0       | 0.0          | false    |
+      | 25 January 2024  | Charge-off                | 101.17 | 100.0     | 1.17     | 0.0  | 0.0       | 0.0          | false    |
+      | 25 January 2024  | Buy Down Fee Amortization | 36.26  | 0.0       | 36.26    | 0.0  | 0.0       | 0.0          | false    |
+# --- check BDFA journal entries for before and after charge-off trn processed --- #
+    And Loan Transactions tab has 2 a "BUY_DOWN_FEE_AMORTIZATION" transactions with date "25 January 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | INCOME    | 450281       | Income From Buy Down        |       | 13.74  |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 13.74 |        |
+      | EXPENSE   | 744007       | Credit Loss/Bad Debt        |       | 36.26  |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 36.26 |        |
+
+    When Loan Pay-off is made on "25 January 2024"
+    Then Loan's all installments have obligations met
+
+  @TestRailId:C3851
+  Scenario: Verify loan with Buy Down fees and charge-off a fraud loan - amortization in case of loan charge-off event - UC3.6
+    When Admin sets the business date to "1 January 2024"
+    And Admin creates a client with random data
+    And 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_PROGRESSIVE_ADVANCED_PAYMENT_ALLOCATION_BUYDOWN_FEES_CHARGE_OFF_REASON | 1 January 2024    | 100            | 7                      | DECLINING_BALANCE | DAILY                       | EQUAL_INSTALLMENTS | 3                 | MONTHS                | 1              | MONTHS                 | 3                  | 0                       | 0                      | 0                    | ADVANCED_PAYMENT_ALLOCATION |
+    And Admin successfully approves the loan on "1 January 2024" with "100" amount and expected disbursement date on "1 January 2024"
+    And Admin successfully disburse the loan on "1 January 2024" with "100" EUR transaction amount
+    Then Loan status will be "ACTIVE"
+    When Admin adds buy down fee with "AUTOPAY" payment type to the loan on "1 January 2024" with "50" EUR transaction amount
+    Then Loan Repayment schedule has 3 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 |           | 66.86           | 33.14         | 0.58     | 0.0  | 0.0       | 33.72 | 0.0  | 0.0        | 0.0  | 33.72       |
+      | 2  | 29   | 01 March 2024    |           | 33.53           | 33.33         | 0.39     | 0.0  | 0.0       | 33.72 | 0.0  | 0.0        | 0.0  | 33.72       |
+      | 3  | 31   | 01 April 2024    |           | 0.0             | 33.53         | 0.2     | 0.0  | 0.0       | 33.73 | 0.0  | 0.0        | 0.0  | 33.73       |
+    And Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due    | Paid | In advance | Late | Outstanding |
+      | 100.0         | 1.17     | 0.0  | 0.0       | 101.17 | 0.0  | 0.0        | 0.0  | 101.17      |
+    And Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
+      | 01 January 2024  | Disbursement     | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 January 2024  | Buy Down Fee     | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 0.0          | false    |
+    And Loan Transactions tab has a "BUY_DOWN_FEE" transaction with date "01 January 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | EXPENSE   | 450280       | Buy Down Expense            | 50.0  |        |
+      | LIABILITY | 145024       | Deferred Capitalized Income |       | 50.0   |
+    Then Admin can successfully set Fraud flag to the loan
+    When Admin sets the business date to "25 January 2024"
+    And Admin does charge-off the loan on "25 January 2024"
+    And Loan Transactions tab has a "CHARGE_OFF" transaction with date "25 January 2024" which has the following Journal entries:
+      | Type      | Account code | Account name               | Debit  | Credit |
+      | ASSET     | 112601       | Loans Receivable           |        | 100.0  |
+      | ASSET     | 112603       | Interest/Fee Receivable    |        |  1.17  |
+      | EXPENSE   | 744037       | Credit Loss/Bad Debt-Fraud | 100.0  |        |
+      | INCOME    | 404001       | Interest Income Charge Off |  1.17  |        |
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type          | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
+      | 01 January 2024  | Disbursement              | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 January 2024  | Buy Down Fee              | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 25 January 2024  | Buy Down Fee Amortization | 13.74  | 0.0       | 13.74    | 0.0  | 0.0       | 0.0          | false    |
+      | 25 January 2024  | Accrual                   | 0.45   | 0.0       | 0.45     | 0.0  | 0.0       | 0.0          | false    |
+      | 25 January 2024  | Charge-off                | 101.17 | 100.0     | 1.17     | 0.0  | 0.0       | 0.0          | false    |
+      | 25 January 2024  | Buy Down Fee Amortization | 36.26  | 0.0       | 36.26    | 0.0  | 0.0       | 0.0          | false    |
+    And Loan Transactions tab has 2 a "BUY_DOWN_FEE_AMORTIZATION" transactions with date "25 January 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | INCOME    | 450281       | Income From Buy Down        |       | 13.74  |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 13.74 |        |
+      | EXPENSE   | 744037       | Credit Loss/Bad Debt-Fraud  |       | 36.26  |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 36.26 |        |
+
+    When Loan Pay-off is made on "25 January 2024"
+    Then Loan's all installments have obligations met
+
+  @TestRailId:C3852
+  Scenario: Verify loan with Buy Down fees and undo the charge-off transaction with "delinquent" reason - amortization in case of loan charge-off event should also be reversed - UC3.7
+    When Admin sets the business date to "1 January 2024"
+    And Admin creates a client with random data
+    And 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_PROGRESSIVE_ADVANCED_PAYMENT_ALLOCATION_BUYDOWN_FEES_CHARGE_OFF_REASON | 1 January 2024    | 100            | 7                      | DECLINING_BALANCE | DAILY                       | EQUAL_INSTALLMENTS | 3                 | MONTHS                | 1              | MONTHS                 | 3                  | 0                       | 0                      | 0                    | ADVANCED_PAYMENT_ALLOCATION |
+    And Admin successfully approves the loan on "1 January 2024" with "100" amount and expected disbursement date on "1 January 2024"
+    And Admin successfully disburse the loan on "1 January 2024" with "100" EUR transaction amount
+    Then Loan status will be "ACTIVE"
+    When Admin adds buy down fee with "AUTOPAY" payment type to the loan on "1 January 2024" with "50" EUR transaction amount
+    Then Loan Repayment schedule has 3 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 |           | 66.86           | 33.14         | 0.58     | 0.0  | 0.0       | 33.72 | 0.0  | 0.0        | 0.0  | 33.72       |
+      | 2  | 29   | 01 March 2024    |           | 33.53           | 33.33         | 0.39     | 0.0  | 0.0       | 33.72 | 0.0  | 0.0        | 0.0  | 33.72       |
+      | 3  | 31   | 01 April 2024    |           | 0.0             | 33.53         | 0.2     | 0.0  | 0.0       | 33.73 | 0.0  | 0.0        | 0.0  | 33.73       |
+    And Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due    | Paid | In advance | Late | Outstanding |
+      | 100.0         | 1.17     | 0.0  | 0.0       | 101.17 | 0.0  | 0.0        | 0.0  | 101.17      |
+    And Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
+      | 01 January 2024  | Disbursement     | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 January 2024  | Buy Down Fee     | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 0.0          | false    |
+    And Loan Transactions tab has a "BUY_DOWN_FEE" transaction with date "01 January 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | EXPENSE   | 450280       | Buy Down Expense            | 50.0  |        |
+      | LIABILITY | 145024       | Deferred Capitalized Income |       | 50.0   |
+    Then Admin can successfully set Fraud flag to the loan
+    When Admin sets the business date to "25 January 2024"
+    And Admin does charge-off the loan with reason "DELINQUENT" on "25 January 2024"
+    And Loan Transactions tab has a "CHARGE_OFF" transaction with date "25 January 2024" which has the following Journal entries:
+      | Type      | Account code | Account name               | Debit  | Credit |
+      | ASSET     | 112601       | Loans Receivable           |        | 100.0  |
+      | ASSET     | 112603       | Interest/Fee Receivable    |        |  1.17  |
+      | EXPENSE   | 744007       | Credit Loss/Bad Debt       | 100.0  |        |
+      | INCOME    | 404001       | Interest Income Charge Off |  1.17  |        |
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type          | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
+      | 01 January 2024  | Disbursement              | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 January 2024  | Buy Down Fee              | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 25 January 2024  | Buy Down Fee Amortization | 13.74  | 0.0       | 13.74    | 0.0  | 0.0       | 0.0          | false    |
+      | 25 January 2024  | Accrual                   | 0.45   | 0.0       | 0.45     | 0.0  | 0.0       | 0.0          | false    |
+      | 25 January 2024  | Charge-off                | 101.17 | 100.0     | 1.17     | 0.0  | 0.0       | 0.0          | false    |
+      | 25 January 2024  | Buy Down Fee Amortization | 36.26  | 0.0       | 36.26    | 0.0  | 0.0       | 0.0          | false    |
+    And Loan Transactions tab has 2 a "BUY_DOWN_FEE_AMORTIZATION" transactions with date "25 January 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | INCOME    | 450281       | Income From Buy Down        |       | 13.74  |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 13.74 |        |
+      | EXPENSE   | 744007       | Credit Loss/Bad Debt        |       | 36.26  |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 36.26 |        |
+
+    Then Admin does a charge-off undo the loan
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type          | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
+      | 01 January 2024  | Disbursement              | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 January 2024  | Buy Down Fee              | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 25 January 2024  | Buy Down Fee Amortization | 13.74  | 0.0       | 13.74    | 0.0  | 0.0       | 0.0          | false    |
+      | 25 January 2024  | Accrual                   | 0.45   | 0.0       | 0.45     | 0.0  | 0.0       | 0.0          | false    |
+      | 25 January 2024  | Charge-off                | 101.17 | 100.0     | 1.17     | 0.0  | 0.0       | 0.0          | true     |
+    And Loan Transactions tab has a "CHARGE_OFF" transaction with date "25 January 2024" which has the following Journal entries:
+      | Type      | Account code | Account name               | Debit  | Credit |
+      | ASSET     | 112601       | Loans Receivable           |        | 100.0  |
+      | ASSET     | 112603       | Interest/Fee Receivable    |        |  1.17  |
+      | EXPENSE   | 744007       | Credit Loss/Bad Debt       | 100.0  |        |
+      | INCOME    | 404001       | Interest Income Charge Off |  1.17  |        |
+      | ASSET     | 112601       | Loans Receivable           | 100.0  |        |
+      | ASSET     | 112603       | Interest/Fee Receivable    |  1.17  |        |
+      | EXPENSE   | 744007       | Credit Loss/Bad Debt       |        | 100.0  |
+      | INCOME    | 404001       | Interest Income Charge Off |        | 1.17   |
+    And Loan Transactions tab has 1 a "BUY_DOWN_FEE_AMORTIZATION" transactions with date "25 January 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | INCOME    | 450281       | Income From Buy Down        |       | 13.74  |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 13.74 |        |
+
+    When Loan Pay-off is made on "25 January 2024"
+    Then Loan's all installments have obligations met
+
   @TestRailId:С3825
-  Scenario: Verify loan with Buy Down Fee adjustment trn with daily amortization and repayment trns - UC4
+  Scenario: Verify loan with Buy Down Fee adjustment trn and repayment trns - UC4
     When Admin sets the business date to "1 January 2024"
     And Admin creates a client with random data
     And Admin creates a fully customized loan with the following data:
@@ -858,19 +1234,19 @@ Feature:Feature: Buy Down Fees
     When Loan Pay-off is made on "1 April 2024"
     Then Loan's all installments have obligations met
     Then Loan Transactions tab has the following data:
-      | Transaction date | Transaction Type        | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
-      | 01 January 2024  | Disbursement            | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
-      | 01 January 2024  | Buy Down Fee            | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
-      | 01 February 2024 | Repayment               | 33.72  | 33.14     | 0.58     | 0.0  | 0.0       | 66.86        | false    |
-      | 01 March 2024    | Buy Down Fee Adjustment | 10.0   | 10.0      | 0.0      | 0.0  | 0.0       | 56.86        | false    |
-      | 31 March 2024    | Accrual                 | 1.35   | 0.0       | 1.35     | 0.0  | 0.0       | 0.0          | false    |
+      | Transaction date | Transaction Type          | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
+      | 01 January 2024  | Disbursement              | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 January 2024  | Buy Down Fee              | 50.0   | 0.0       | 0.0      | 0.0  | 0.0       | 100.0        | false    |
+      | 01 February 2024 | Repayment                 | 33.72  | 33.14     | 0.58     | 0.0  | 0.0       | 66.86        | false    |
+      | 01 March 2024    | Buy Down Fee Adjustment   | 10.0   | 10.0      | 0.0      | 0.0  | 0.0       | 56.86        | false    |
+      | 31 March 2024    | Accrual                   | 1.35   | 0.0       | 1.35     | 0.0  | 0.0       | 0.0          | false    |
       | 31 March 2024    | Buy Down Fee Amortization | 40.0   | 0.0       | 40.0     | 0.0  | 0.0       | 0.0          | false    |
-      | 01 April 2024    | Repayment               | 33.73  | 33.34     | 0.39     | 0.0  | 0.0       | 23.52        | false    |
-      | 01 April 2024    | Repayment               | 33.91  | 33.52     | 0.39     | 0.0  | 0.0       | 0.0          | false    |
-      | 01 April 2024    | Accrual                 | 0.01   | 0.0       | 0.01     | 0.0  | 0.0       | 0.0          | false    |
+      | 01 April 2024    | Repayment                 | 33.73  | 33.34     | 0.39     | 0.0  | 0.0       | 23.52        | false    |
+      | 01 April 2024    | Repayment                 | 33.91  | 33.52     | 0.39     | 0.0  | 0.0       | 0.0          | false    |
+      | 01 April 2024    | Accrual                   | 0.01   | 0.0       | 0.01     | 0.0  | 0.0       | 0.0          | false    |
 
   @TestRailId:С3826
-  Scenario: Verify loan with a few Buy Down Fee adjustment trns with daily amortization and repayment trns - UC5
+  Scenario: Verify loan with a few Buy Down Fee adjustment trns and repayment trns - UC5
     When Admin sets the business date to "1 January 2024"
     And Admin creates a client with random data
     And Admin creates a fully customized loan with the following data:
@@ -971,3 +1347,55 @@ Feature:Feature: Buy Down Fees
       | 01 April 2024    | Repayment                 | 33.73  | 33.34     | 0.39     | 0.0  | 0.0       | 18.52        | false    |
       | 01 April 2024    | Repayment                 | 33.91  | 33.52     | 0.39     | 0.0  | 0.0       | 0.0          | false    |
       | 01 April 2024    | Accrual                   | 0.01   | 0.0       | 0.01     | 0.0  | 0.0       | 0.0          | false    |
+
+  @TestRailId:C3853
+  Scenario: Verify add buy down fee to a progressive loan after disbursement and then write off loan - amortization in case of loan close event
+    When Admin sets the business date to "1 January 2024"
+    And Admin creates a client with random data
+    And 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_PROGRESSIVE_ADVANCED_PAYMENT_ALLOCATION_BUYDOWN_FEES | 1 January 2024    | 1000           | 7                      | DECLINING_BALANCE | DAILY                       | EQUAL_INSTALLMENTS | 3                 | MONTHS                | 1              | MONTHS                 | 3                  | 0                       | 0                      | 0                    | ADVANCED_PAYMENT_ALLOCATION |
+    And Admin successfully approves the loan on "1 January 2024" with "1000" amount and expected disbursement date on "1 January 2024"
+    And Admin successfully disburse the loan on "1 January 2024" with "900" EUR transaction amount
+    Then Loan status will be "ACTIVE"
+    When Admin sets the business date to "2 January 2024"
+    When Admin adds buy down fee with "AUTOPAY" payment type to the loan on "2 January 2024" with "100" EUR transaction amount
+    Then Loan Repayment schedule has 3 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  |           | 900.0           |               |          | 0.0  |           | 0.0    | 0.0  |            |      |             |
+      | 1  | 31   | 01 February 2024 |           | 601.74          | 298.26        | 5.25     | 0.0  | 0.0       | 303.51 | 0.0  | 0.0        | 0.0  | 303.51      |
+      | 2  | 29   | 01 March 2024    |           | 301.74          | 300.0         | 3.51     | 0.0  | 0.0       | 303.51 | 0.0  | 0.0        | 0.0  | 303.51      |
+      | 3  | 31   | 01 April 2024    |           | 0.0             | 301.74        | 1.76     | 0.0  | 0.0       | 303.5  | 0.0  | 0.0        | 0.0  | 303.5       |
+    And Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due    | Paid | In advance | Late | Outstanding |
+      | 900.0         | 10.52    | 0.0  | 0.0       | 910.52 | 0.0  | 0.0        | 0.0  | 910.52      |
+    And Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
+      | 01 January 2024  | Disbursement     | 900.0  | 0.0       | 0.0      | 0.0  | 0.0       | 900.0        | false    |
+      | 02 January 2024  | Buy Down Fee     | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 0.0          | false    |
+    And Loan Transactions tab has a "BUY_DOWN_FEE" transaction with date "02 January 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | EXPENSE   | 450280       | Buy Down Expense            | 100.0 |        |
+      | LIABILITY | 145024       | Deferred Capitalized Income |       | 100.0  |
+# --- make write-off --- #
+    And Admin does write-off the loan on "02 January 2024"
+    Then Loan status will be "CLOSED_WRITTEN_OFF"
+    Then Loan Repayment schedule has 3 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  |                 | 900.0           |               |          | 0.0  |           | 0.0    | 0.0  |            |      |             |
+      | 1  | 31   | 01 February 2024 | 02 January 2024 | 601.74          | 298.26        | 5.25     | 0.0  | 0.0       | 303.51 | 0.0  | 0.0        | 0.0  | 0.0         |
+      | 2  | 29   | 01 March 2024    | 02 January 2024 | 301.74          | 300.0         | 3.51     | 0.0  | 0.0       | 303.51 | 0.0  | 0.0        | 0.0  | 0.0         |
+      | 3  | 31   | 01 April 2024    | 02 January 2024 | 0.0             | 301.74        | 1.76     | 0.0  | 0.0       | 303.5  | 0.0  | 0.0        | 0.0  | 0.0         |
+    And Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due    | Paid | In advance | Late | Outstanding |
+      | 900.0         | 10.52    | 0.0  | 0.0       | 910.52 | 0.0  | 0.0        | 0.0  | 0.0         |
+    And Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type          | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
+      | 01 January 2024  | Disbursement              | 900.0  | 0.0       | 0.0      | 0.0  | 0.0       | 900.0        | false    |
+      | 02 January 2024  | Buy Down Fee              | 100.0  | 0.0       | 0.0      | 0.0  | 0.0       | 900.0        | false    |
+      | 02 January 2024  | Close (as written-off)    | 910.52 | 900.0     | 10.52    | 0.0  | 0.0       | 0.0          | false    |
+      | 02 January 2024  | Buy Down Fee Amortization | 100.0  | 0.0       | 100.0    | 0.0  | 0.0       | 0.0          | false    |
+    And Loan Transactions tab has a "BUY_DOWN_FEE_AMORTIZATION" transaction with date "02 January 2024" which has the following Journal entries:
+      | Type      | Account code | Account name                | Debit | Credit |
+      | EXPENSE   | e4           | Written off                 |       | 100.0  |
+      | LIABILITY | 145024       | Deferred Capitalized Income | 100.0 |        |
diff --git a/fineract-e2e-tests-runner/src/test/resources/features/LoanCapitalizedIncome.feature b/fineract-e2e-tests-runner/src/test/resources/features/LoanCapitalizedIncome.feature
index d52aaecf1a..363d7e1036 100644
--- a/fineract-e2e-tests-runner/src/test/resources/features/LoanCapitalizedIncome.feature
+++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanCapitalizedIncome.feature
@@ -1464,8 +1464,11 @@ Feature: Capitalized Income
       | 26 January 2024  | Accrual                         | 3.69   | 0.0       | 3.69     | 0.0  | 0.0       | 0.0          | false    |
       | 26 January 2024  | Charge-off                      | 1004.58| 1000.0    | 4.58     | 0.0  | 0.0       | 0.0          | false    |
       | 26 January 2024  | Capitalized Income Amortization | 16.67  | 0.0       | 16.67    | 0.0  | 0.0       | 0.0          | false    |
-    Then Loan Transactions tab has a "CAPITALIZED_INCOME_AMORTIZATION" transaction with date "26 January 2024" which has the following Journal entries:
+# --- check CIA journal entries for before and after charge-off trn processed --- #
+    Then Loan Transactions tab has 2 a "CAPITALIZED_INCOME_AMORTIZATION" transactions with date "26 January 2024" which has the following Journal entries:
       | Type      | Account code | Account name                 | Debit  | Credit |
+      | INCOME    | 404000       | Interest Income              |        | 83.33  |
+      | LIABILITY | 145024       | Deferred Capitalized Income  | 83.33  |        |
       | EXPENSE   | 744007       | Credit Loss/Bad Debt         |        | 16.67  |
       | LIABILITY | 145024       | Deferred Capitalized Income  | 16.67  |        |
     Then LoanCapitalizedIncomeAmortizationTransactionCreatedBusinessEvent is raised on "26 January 2024"
@@ -1507,8 +1510,11 @@ Feature: Capitalized Income
       | 26 January 2024  | Accrual                         | 3.69   | 0.0       | 3.69     | 0.0  | 0.0       | 0.0          | false    |
       | 26 January 2024  | Charge-off                      | 1004.58| 1000.0    | 4.58     | 0.0  | 0.0       | 0.0          | false    |
       | 26 January 2024  | Capitalized Income Amortization | 16.67  | 0.0       | 16.67    | 0.0  | 0.0       | 0.0          | false    |
-    Then Loan Transactions tab has a "CAPITALIZED_INCOME_AMORTIZATION" transaction with date "26 January 2024" which has the following Journal entries:
+# --- check CIA journal entries for before and after charge-off trn processed --- #
+    Then Loan Transactions tab has 2 a "CAPITALIZED_INCOME_AMORTIZATION" transactions with date "26 January 2024" which has the following Journal entries:
       | Type      | Account code | Account name                 | Debit  | Credit |
+      | INCOME    | 404000       | Interest Income              |        | 83.33  |
+      | LIABILITY | 145024       | Deferred Capitalized Income  | 83.33  |        |
       | EXPENSE   | 744037       | Credit Loss/Bad Debt-Fraud   |        | 16.67  |
       | LIABILITY | 145024       | Deferred Capitalized Income  | 16.67  |        |
     Then LoanCapitalizedIncomeAmortizationTransactionCreatedBusinessEvent is raised on "26 January 2024"
@@ -1550,8 +1556,11 @@ Feature: Capitalized Income
       | 26 January 2024  | Accrual                         | 3.69   | 0.0       | 3.69     | 0.0  | 0.0       | 0.0          | false    |
       | 26 January 2024  | Charge-off                      | 1004.58| 1000.0    | 4.58     | 0.0  | 0.0       | 0.0          | false    |
       | 26 January 2024  | Capitalized Income Amortization | 16.67  | 0.0       | 16.67    | 0.0  | 0.0       | 0.0          | false    |
-    Then Loan Transactions tab has a "CAPITALIZED_INCOME_AMORTIZATION" transaction with date "26 January 2024" which has the following Journal entries:
+# --- check CIA journal entries for before and after charge-off trn processed --- #
+    Then Loan Transactions tab has 2 a "CAPITALIZED_INCOME_AMORTIZATION" transactions with date "26 January 2024" which has the following Journal entries:
       | Type      | Account code | Account name                 | Debit  | Credit |
+      | INCOME    | 404000       | Interest Income              |        | 83.33  |
+      | LIABILITY | 145024       | Deferred Capitalized Income  | 83.33  |        |
       | EXPENSE   | 744007       | Credit Loss/Bad Debt         |        | 16.67  |
       | LIABILITY | 145024       | Deferred Capitalized Income  | 16.67  |        |
     Then LoanCapitalizedIncomeAmortizationTransactionCreatedBusinessEvent is raised on "26 January 2024"
@@ -1593,8 +1602,10 @@ Feature: Capitalized Income
       | 26 January 2024  | Accrual                         | 3.69   | 0.0       | 3.69     | 0.0  | 0.0       | 0.0          | false    |
       | 26 January 2024  | Charge-off                      | 1004.58| 1000.0    | 4.58     | 0.0  | 0.0       | 0.0          | false    |
       | 26 January 2024  | Capitalized Income Amortization | 16.67  | 0.0       | 16.67    | 0.0  | 0.0       | 0.0          | false    |
-    Then Loan Transactions tab has a "CAPITALIZED_INCOME_AMORTIZATION" transaction with date "26 January 2024" which has the following Journal entries:
+    Then Loan Transactions tab has 2 a "CAPITALIZED_INCOME_AMORTIZATION" transactions with date "26 January 2024" which has the following Journal entries:
       | Type      | Account code | Account name                 | Debit  | Credit |
+      | INCOME    | 404000       | Interest Income              |        | 83.33  |
+      | LIABILITY | 145024       | Deferred Capitalized Income  | 83.33  |        |
       | EXPENSE   | 744007       | Credit Loss/Bad Debt         |        | 16.67  |
       | LIABILITY | 145024       | Deferred Capitalized Income  | 16.67  |        |
     Then LoanCapitalizedIncomeAmortizationTransactionCreatedBusinessEvent is raised on "26 January 2024"