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

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


The following commit(s) were added to refs/heads/develop by this push:
     new 697449e7e FINERACT-2042 Chargeback with credit allocation, accounting
697449e7e is described below

commit 697449e7e742a9fac350890ff201741bb8bcd93c
Author: Peter Bagrij <[email protected]>
AuthorDate: Fri Mar 1 19:12:27 2024 +0100

    FINERACT-2042 Chargeback with credit allocation, accounting
---
 .../loanaccount/domain/LoanTransaction.java        |  30 +-
 .../journalentry/data/LoanTransactionDTO.java      |   5 +
 .../service/AccountingProcessorHelper.java         |   8 +-
 .../AccrualBasedAccountingProcessorForLoan.java    |  59 ++-
 ...PaymentAllocationLoanRepaymentScheduleTest.java |  12 +-
 .../integrationtests/BaseLoanIntegrationTest.java  |  97 +++--
 ...ebackWithCreditAllocationsIntegrationTests.java | 463 ++++++++++++++++++++-
 .../LoanDownPaymentTransactionChargebackTest.java  |  27 +-
 .../LoanRepaymentScheduleWithDownPaymentTest.java  |  14 +-
 .../LoanRescheduleTestWithDownpayment.java         |   4 +-
 .../LoanTransactionChargebackTest.java             |  63 ++-
 ...oanDisbursalWithDownPaymentIntegrationTest.java | 344 +++++++--------
 .../common/accounting/AccountHelper.java           |  38 +-
 .../common/accounting/GLAccountBuilder.java        |   8 +
 .../common/loans/LoanProductTestBuilder.java       |  96 ++++-
 15 files changed, 960 insertions(+), 308 deletions(-)

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 960ef6138..1b737fe28 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
@@ -35,6 +35,7 @@ import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import 
org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
 import org.apache.fineract.infrastructure.core.domain.ExternalId;
@@ -763,7 +764,14 @@ public class LoanTransaction extends 
AbstractAuditableWithUTCDateTimeCustom {
         thisTransactionData.put("currencyCode", currencyCode);
         thisTransactionData.put("amount", this.amount);
         thisTransactionData.put("netDisbursalAmount", 
this.loan.getNetDisbursalAmount());
-        thisTransactionData.put("principalPortion", this.principalPortion);
+
+        if (transactionType.isChargeback()
+                && (getLoan().getCreditAllocationRules() == null || 
getLoan().getCreditAllocationRules().size() == 0)) {
+            thisTransactionData.put("principalPortion", this.amount);
+        } else {
+            thisTransactionData.put("principalPortion", this.principalPortion);
+        }
+
         thisTransactionData.put("interestPortion", this.interestPortion);
         thisTransactionData.put("feeChargesPortion", this.feeChargesPortion);
         thisTransactionData.put("penaltyChargesPortion", 
this.penaltyChargesPortion);
@@ -790,6 +798,26 @@ public class LoanTransaction extends 
AbstractAuditableWithUTCDateTimeCustom {
             thisTransactionData.put("loanChargesPaid", loanChargesPaidData);
         }
 
+        if (transactionType.isChargeback() && this.overPaymentPortion != null 
&& this.overPaymentPortion.compareTo(BigDecimal.ZERO) > 0) {
+            BigDecimal principalPaid = overPaymentPortion;
+            BigDecimal feePaid = BigDecimal.ZERO;
+            BigDecimal penaltyPaid = BigDecimal.ZERO;
+            if (getLoanTransactionToRepaymentScheduleMappings().size() > 0) {
+                principalPaid = 
getLoanTransactionToRepaymentScheduleMappings().stream()
+                        .map(mapping -> 
Optional.ofNullable(mapping.getPrincipalPortion()).orElse(BigDecimal.ZERO))
+                        .reduce(BigDecimal.ZERO, BigDecimal::add);
+                feePaid = 
getLoanTransactionToRepaymentScheduleMappings().stream()
+                        .map(mapping -> 
Optional.ofNullable(mapping.getFeeChargesPortion()).orElse(BigDecimal.ZERO))
+                        .reduce(BigDecimal.ZERO, BigDecimal::add);
+                penaltyPaid = 
getLoanTransactionToRepaymentScheduleMappings().stream()
+                        .map(mapping -> 
Optional.ofNullable(mapping.getPenaltyChargesPortion()).orElse(BigDecimal.ZERO))
+                        .reduce(BigDecimal.ZERO, BigDecimal::add);
+            }
+            thisTransactionData.put("principalPaid", principalPaid);
+            thisTransactionData.put("feePaid", feePaid);
+            thisTransactionData.put("penaltyPaid", penaltyPaid);
+        }
+
         LoanTransactionRelation loanTransactionRelation = 
loanTransactionRelations.stream()
                 .filter(e -> 
LoanTransactionRelationTypeEnum.CHARGE_ADJUSTMENT.equals(e.getRelationType())).findAny().orElse(null);
         if (loanTransactionRelation != null) {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/LoanTransactionDTO.java
 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/LoanTransactionDTO.java
index bd9ebf290..07defb666 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/LoanTransactionDTO.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/LoanTransactionDTO.java
@@ -60,4 +60,9 @@ public class LoanTransactionDTO {
 
     private final String chargeRefundChargeType;
     private final LoanChargeData loanChargeData;
+
+    /** In case chargeback and overpayment the below field contains the 
distribution payment **/
+    private final BigDecimal principalPaid;
+    private final BigDecimal feePaid;
+    private final BigDecimal penaltyPaid;
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
index 804184c3e..d3ca6da09 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
@@ -156,9 +156,15 @@ public class AccountingProcessorHelper {
                 isAccountTransfer = 
this.accountTransfersReadPlatformService.isAccountTransfer(Long.parseLong(transactionId),
                         PortfolioAccountType.LOAN);
             }
+
+            BigDecimal principalPaid = (BigDecimal) map.get("principalPaid");
+            BigDecimal feePaid = (BigDecimal) map.get("feePaid");
+            BigDecimal penaltyPaid = (BigDecimal) map.get("penaltyPaid");
+
             final LoanTransactionDTO transaction = new 
LoanTransactionDTO(transactionOfficeId, paymentTypeId, transactionId,
                     transactionDate, transactionType, amount, principal, 
interest, fees, penalties, overPayments, reversed,
-                    penaltyPaymentDetails, feePaymentDetails, 
isAccountTransfer, chargeRefundChargeType, loanChargeData);
+                    penaltyPaymentDetails, feePaymentDetails, 
isAccountTransfer, chargeRefundChargeType, loanChargeData, principalPaid,
+                    feePaid, penaltyPaid);
             Boolean isLoanToLoanTransfer = (Boolean) 
accountingBridgeData.get("isLoanToLoanTransfer");
             transaction.setLoanToLoanTransfer(isLoanToLoanTransfer != null && 
isLoanToLoanTransfer);
             newLoanTransactions.add(transaction);
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
index f0ed03edb..d92657b7b 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
@@ -430,25 +430,54 @@ public class AccrualBasedAccountingProcessorForLoan 
implements AccountingProcess
         final BigDecimal overpaidAmount = 
Objects.isNull(loanTransactionDTO.getOverPayment()) ? BigDecimal.ZERO
                 : loanTransactionDTO.getOverPayment();
 
-        if (BigDecimal.ZERO.compareTo(overpaidAmount) == 0) { // when no 
overpay
-            helper.createJournalEntriesAndReversalsForLoan(office, 
currencyCode, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
-                    AccrualAccountsForLoan.FUND_SOURCE.getValue(), 
loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
-                    amount, isReversal);
-        } else if (overpaidAmount.compareTo(amount) >= 0) { // when the 
overpay amount is matching with the normal
-                                                            // amount
-            helper.createJournalEntriesAndReversalsForLoan(office, 
currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
-                    AccrualAccountsForLoan.FUND_SOURCE.getValue(), 
loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
-                    amount, isReversal);
-        } else {
-            BigDecimal diff = amount.subtract(overpaidAmount);
-            helper.createDebitJournalEntryOrReversalForLoan(office, 
currencyCode, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
-                    loanProductId, paymentTypeId, loanId, transactionId, 
transactionDate, diff, isReversal);
-            helper.createCreditJournalEntryOrReversalForLoan(office, 
currencyCode, AccrualAccountsForLoan.FUND_SOURCE, loanProductId,
-                    paymentTypeId, loanId, transactionId, transactionDate, 
amount, isReversal);
+        final BigDecimal principalCredited = 
Objects.isNull(loanTransactionDTO.getPrincipal()) ? BigDecimal.ZERO
+                : loanTransactionDTO.getPrincipal();
+        final BigDecimal feeCredited = 
Objects.isNull(loanTransactionDTO.getFees()) ? BigDecimal.ZERO : 
loanTransactionDTO.getFees();
+        final BigDecimal penaltyCredited = 
Objects.isNull(loanTransactionDTO.getPenalties()) ? BigDecimal.ZERO
+                : loanTransactionDTO.getPenalties();
+
+        final BigDecimal principalPaid = 
Objects.isNull(loanTransactionDTO.getPrincipalPaid()) ? BigDecimal.ZERO
+                : loanTransactionDTO.getPrincipalPaid();
+        final BigDecimal feePaid = 
Objects.isNull(loanTransactionDTO.getFeePaid()) ? BigDecimal.ZERO : 
loanTransactionDTO.getFeePaid();
+        final BigDecimal penaltyPaid = 
Objects.isNull(loanTransactionDTO.getPenaltyPaid()) ? BigDecimal.ZERO
+                : loanTransactionDTO.getPenaltyPaid();
+
+        helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, 
AccrualAccountsForLoan.FUND_SOURCE, loanProductId,
+                paymentTypeId, loanId, transactionId, transactionDate, amount, 
isReversal);
+
+        if (overpaidAmount.compareTo(BigDecimal.ZERO) > 0) {
             helper.createDebitJournalEntryOrReversalForLoan(office, 
currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
                     loanProductId, paymentTypeId, loanId, transactionId, 
transactionDate, overpaidAmount, isReversal);
         }
 
+        if (principalCredited.compareTo(principalPaid) > 0) {
+            helper.createDebitJournalEntryOrReversalForLoan(office, 
currencyCode, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
+                    loanProductId, paymentTypeId, loanId, transactionId, 
transactionDate, principalCredited.subtract(principalPaid),
+                    isReversal);
+        } else if (principalCredited.compareTo(principalPaid) < 0) {
+            helper.createCreditJournalEntryOrReversalForLoan(office, 
currencyCode, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
+                    loanProductId, paymentTypeId, loanId, transactionId, 
transactionDate, principalPaid.subtract(principalCredited),
+                    isReversal);
+        }
+
+        if (feeCredited.compareTo(feePaid) > 0) {
+            helper.createDebitJournalEntryOrReversalForLoan(office, 
currencyCode, AccrualAccountsForLoan.FEES_RECEIVABLE.getValue(),
+                    loanProductId, paymentTypeId, loanId, transactionId, 
transactionDate, feeCredited.subtract(feePaid), isReversal);
+        } else if (feeCredited.compareTo(feePaid) < 0) {
+            helper.createCreditJournalEntryOrReversalForLoan(office, 
currencyCode, AccrualAccountsForLoan.FEES_RECEIVABLE.getValue(),
+                    loanProductId, paymentTypeId, loanId, transactionId, 
transactionDate, feePaid.subtract(feeCredited), isReversal);
+        }
+
+        if (penaltyCredited.compareTo(penaltyPaid) > 0) {
+            helper.createDebitJournalEntryOrReversalForLoan(office, 
currencyCode, AccrualAccountsForLoan.PENALTIES_RECEIVABLE.getValue(),
+                    loanProductId, paymentTypeId, loanId, transactionId, 
transactionDate, penaltyCredited.subtract(penaltyPaid),
+                    isReversal);
+        } else if (penaltyCredited.compareTo(penaltyPaid) < 0) {
+            helper.createCreditJournalEntryOrReversalForLoan(office, 
currencyCode, AccrualAccountsForLoan.PENALTIES_RECEIVABLE.getValue(),
+                    loanProductId, paymentTypeId, loanId, transactionId, 
transactionDate, penaltyPaid.subtract(penaltyCredited),
+                    isReversal);
+        }
+
     }
 
     /**
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
index d6cb8f4f5..aa1bd5e42 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
@@ -3194,13 +3194,13 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             );
             // verify journal entries
             verifyJournalEntries(loanResponse.getLoanId(), journalEntry(100.0, 
loansReceivableAccount, "DEBIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(100.0, fundSource, "CREDIT"), //
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
                     journalEntry(50.0, overpaymentAccount, "CREDIT"), //
-                    journalEntry(150.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(150.0, fundSource, "DEBIT"), //
                     journalEntry(50.0, loansReceivableAccount, "DEBIT"), //
                     journalEntry(50.0, overpaymentAccount, "DEBIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(100.0, fundSource, "CREDIT") //
             );
         });
     }
@@ -3273,12 +3273,12 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             );
             // verify journal entries
             verifyJournalEntries(loanResponse.getLoanId(), journalEntry(100.0, 
loansReceivableAccount, "DEBIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(100.0, fundSource, "CREDIT"), //
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
                     journalEntry(50.0, overpaymentAccount, "CREDIT"), //
-                    journalEntry(150.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(150.0, fundSource, "DEBIT"), //
                     journalEntry(28.0, overpaymentAccount, "DEBIT"), //
-                    journalEntry(28.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(28.0, fundSource, "CREDIT") //
             );
         });
     }
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
index fc4aaf202..bcd50f555 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
@@ -72,6 +72,7 @@ import 
org.apache.fineract.integrationtests.common.BatchHelper;
 import org.apache.fineract.integrationtests.common.BusinessDateHelper;
 import org.apache.fineract.integrationtests.common.ClientHelper;
 import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
+import org.apache.fineract.integrationtests.common.SchedulerJobHelper;
 import org.apache.fineract.integrationtests.common.Utils;
 import org.apache.fineract.integrationtests.common.accounting.Account;
 import org.apache.fineract.integrationtests.common.accounting.AccountHelper;
@@ -114,6 +115,7 @@ public abstract class BaseLoanIntegrationTest {
     protected final LoanProductHelper loanProductHelper = new 
LoanProductHelper();
     protected JournalEntryHelper journalEntryHelper = new 
JournalEntryHelper(requestSpec, responseSpec);
     protected ClientHelper clientHelper = new ClientHelper(requestSpec, 
responseSpec);
+    protected SchedulerJobHelper schedulerJobHelper = new 
SchedulerJobHelper(requestSpec);
     protected final InlineLoanCOBHelper inlineLoanCOBHelper = new 
InlineLoanCOBHelper(requestSpec, responseSpec);
 
     protected BusinessDateHelper businessDateHelper = new BusinessDateHelper();
@@ -123,18 +125,22 @@ public abstract class BaseLoanIntegrationTest {
     protected DateTimeFormatter dateTimeFormatter = 
DateTimeFormatter.ofPattern(DATETIME_PATTERN);
 
     // asset
-    protected final Account loansReceivableAccount = 
accountHelper.createAssetAccount();
-    protected final Account interestFeeReceivableAccount = 
accountHelper.createAssetAccount();
-    protected final Account suspenseAccount = 
accountHelper.createAssetAccount();
+    protected final Account loansReceivableAccount = 
accountHelper.createAssetAccount("loanPortfolio");
+
+    protected final Account interestReceivableAccount = 
accountHelper.createAssetAccount("interestReceivable");
+    protected final Account feeReceivableAccount = 
accountHelper.createAssetAccount("feeReceivable");
+    protected final Account penaltyReceivableAccount = 
accountHelper.createAssetAccount("penaltyReceivable");
+    protected final Account suspenseAccount = 
accountHelper.createAssetAccount("suspense");
     // liability
-    protected final Account suspenseClearingAccount = 
accountHelper.createLiabilityAccount();
-    protected final Account overpaymentAccount = 
accountHelper.createLiabilityAccount();
+    protected final Account fundSource = 
accountHelper.createLiabilityAccount("fundSource");
+    protected final Account overpaymentAccount = 
accountHelper.createLiabilityAccount("overpayment");
     // income
-    protected final Account interestIncomeAccount = 
accountHelper.createIncomeAccount();
-    protected final Account feeIncomeAccount = 
accountHelper.createIncomeAccount();
-    protected final Account feeChargeOffAccount = 
accountHelper.createIncomeAccount();
-    protected final Account recoveriesAccount = 
accountHelper.createIncomeAccount();
-    protected final Account interestIncomeChargeOffAccount = 
accountHelper.createIncomeAccount();
+    protected final Account interestIncomeAccount = 
accountHelper.createIncomeAccount("interestIncome");
+    protected final Account feeIncomeAccount = 
accountHelper.createIncomeAccount("feeIncome");
+    protected final Account penaltyIncomeAccount = 
accountHelper.createIncomeAccount("penaltyIncome");
+    protected final Account feeChargeOffAccount = 
accountHelper.createIncomeAccount("feeChargeOff");
+    protected final Account recoveriesAccount = 
accountHelper.createIncomeAccount("recoveries");
+    protected final Account interestIncomeChargeOffAccount = 
accountHelper.createIncomeAccount("interestIncomeChargeOff");
     // expense
     protected final Account creditLossBadDebtAccount = 
accountHelper.createExpenseAccount();
     protected final Account creditLossBadDebtFraudAccount = 
accountHelper.createExpenseAccount();
@@ -159,6 +165,7 @@ public abstract class BaseLoanIntegrationTest {
                 .includeInBorrowerCycle(false)//
                 .currencyCode("USD")//
                 .digitsAfterDecimal(2)//
+                .inMultiplesOf(0)//
                 .installmentAmountInMultiplesOf(1)//
                 .useBorrowerCycle(false)//
                 .minPrincipal(100.0)//
@@ -207,24 +214,18 @@ public abstract class BaseLoanIntegrationTest {
                 .outstandingLoanBalance(10000.0)//
                 .charges(Collections.emptyList())//
                 .accountingRule(3)//
-                
.fundSourceAccountId(suspenseClearingAccount.getAccountID().longValue())//
+                .fundSourceAccountId(fundSource.getAccountID().longValue())//
                 
.loanPortfolioAccountId(loansReceivableAccount.getAccountID().longValue())//
                 
.transfersInSuspenseAccountId(suspenseAccount.getAccountID().longValue())//
                 
.interestOnLoanAccountId(interestIncomeAccount.getAccountID().longValue())//
                 
.incomeFromFeeAccountId(feeIncomeAccount.getAccountID().longValue())//
-                
.incomeFromPenaltyAccountId(feeIncomeAccount.getAccountID().longValue())//
+                
.incomeFromPenaltyAccountId(penaltyIncomeAccount.getAccountID().longValue())//
                 
.incomeFromRecoveryAccountId(recoveriesAccount.getAccountID().longValue())//
                 
.writeOffAccountId(writtenOffAccount.getAccountID().longValue())//
                 
.overpaymentLiabilityAccountId(overpaymentAccount.getAccountID().longValue())//
-                
.receivableInterestAccountId(interestFeeReceivableAccount.getAccountID().longValue())//
-                
.receivableFeeAccountId(interestFeeReceivableAccount.getAccountID().longValue())//
-                
.receivablePenaltyAccountId(interestFeeReceivableAccount.getAccountID().longValue())//
-                .dateFormat(DATETIME_PATTERN)//
-                .locale("en_GB")//
-                .disallowExpectedDisbursements(true)//
-                .allowApprovedDisbursedAmountsOverApplied(true)//
-                .overAppliedCalculationType("percentage")//
-                .overAppliedNumber(50)//
+                
.receivableInterestAccountId(interestReceivableAccount.getAccountID().longValue())//
+                
.receivableFeeAccountId(feeReceivableAccount.getAccountID().longValue())//
+                
.receivablePenaltyAccountId(penaltyReceivableAccount.getAccountID().longValue())//
                 
.goodwillCreditAccountId(goodwillExpenseAccount.getAccountID().longValue())//
                 
.incomeFromGoodwillCreditInterestAccountId(interestIncomeChargeOffAccount.getAccountID().longValue())//
                 
.incomeFromGoodwillCreditFeesAccountId(feeChargeOffAccount.getAccountID().longValue())//
@@ -233,7 +234,12 @@ public abstract class BaseLoanIntegrationTest {
                 
.incomeFromChargeOffFeesAccountId(feeChargeOffAccount.getAccountID().longValue())//
                 
.chargeOffExpenseAccountId(creditLossBadDebtAccount.getAccountID().longValue())//
                 
.chargeOffFraudExpenseAccountId(creditLossBadDebtFraudAccount.getAccountID().longValue())//
-                
.incomeFromChargeOffPenaltyAccountId(feeChargeOffAccount.getAccountID().longValue());
+                
.incomeFromChargeOffPenaltyAccountId(feeChargeOffAccount.getAccountID().longValue()).dateFormat(DATETIME_PATTERN)//
+                .locale("en_GB")//
+                .disallowExpectedDisbursements(true)//
+                .allowApprovedDisbursedAmountsOverApplied(true)//
+                .overAppliedCalculationType("percentage")//
+                .overAppliedNumber(50);
     }
 
     protected PostLoanProductsRequest 
createOnePeriod30DaysLongNoInterestPeriodicAccrualProductWithAdvancedPaymentAllocation()
 {
@@ -344,7 +350,7 @@ public abstract class BaseLoanIntegrationTest {
                 boolean found = 
loanDetails.getTransactions().stream().anyMatch(item -> 
Objects.equals(item.getAmount(), tr.amount) //
                         && Objects.equals(item.getType().getValue(), tr.type) 
//
                         && Objects.equals(item.getDate(), 
LocalDate.parse(tr.date, dateTimeFormatter)) //
-                        && Objects.equals(item.getOutstandingLoanBalance(), 
tr.outstandingAmount) //
+                        && Objects.equals(item.getOutstandingLoanBalance(), 
tr.outstandingPrincipal) //
                         && Objects.equals(item.getPrincipalPortion(), 
tr.principalPortion) //
                         && Objects.equals(item.getInterestPortion(), 
tr.interestPortion) //
                         && Objects.equals(item.getFeeChargesPortion(), 
tr.feePortion) //
@@ -416,6 +422,18 @@ public abstract class BaseLoanIntegrationTest {
         });
     }
 
+    protected void verifyTRJournalEntries(Long transactionId, Journal... 
entries) {
+        GetJournalEntriesTransactionIdResponse journalEntriesForLoan = 
journalEntryHelper.getJournalEntries("L" + transactionId.toString());
+        Assertions.assertEquals(entries.length, 
journalEntriesForLoan.getPageItems().size());
+        Arrays.stream(entries).forEach(journalEntry -> {
+            boolean found = journalEntriesForLoan.getPageItems().stream()
+                    .anyMatch(item -> Objects.equals(item.getAmount(), 
journalEntry.amount)
+                            && Objects.equals(item.getGlAccountId(), 
journalEntry.account.getAccountID().longValue())
+                            && 
Objects.requireNonNull(item.getEntryType()).getValue().equals(journalEntry.type));
+            Assertions.assertTrue(found, "Required journal entry not found: " 
+ journalEntry);
+        });
+    }
+
     protected Long addCharge(Long loanId, boolean isPenalty, double amount, 
String dueDate) {
         Integer chargeId = ChargesHelper.createCharges(requestSpec, 
responseSpec,
                 
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT,
 String.valueOf(amount), isPenalty));
@@ -602,9 +620,10 @@ public abstract class BaseLoanIntegrationTest {
         return response.getResourceId();
     }
 
-    protected void addChargebackForLoan(Long loanId, Long transactionId, 
Double amount) {
-        loanTransactionHelper.chargebackLoanTransaction(loanId, transactionId,
+    protected Long addChargebackForLoan(Long loanId, Long transactionId, 
Double amount) {
+        PostLoansLoanIdTransactionsResponse response = 
loanTransactionHelper.chargebackLoanTransaction(loanId, transactionId,
                 new 
PostLoansLoanIdTransactionsTransactionIdRequest().locale("en").transactionAmount(amount).paymentTypeId(1L));
+        return response.getResourceId();
     }
 
     protected PostChargesResponse createCharge(Double amount) {
@@ -627,8 +646,22 @@ public abstract class BaseLoanIntegrationTest {
                 new 
BusinessDateRequest().type(BUSINESS_DATE.getName()).date(date).dateFormat(DATETIME_PATTERN).locale("en"));
     }
 
-    protected Journal journalEntry(double principalAmount, Account account, 
String type) {
-        return new Journal(principalAmount, account, type);
+    protected Long getTransactionId(Long loanId, String type, String date) {
+        GetLoansLoanIdResponse loan = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId.intValue());
+        return loan.getTransactions().stream().filter(tr -> 
Objects.equals(tr.getType().getValue(), type)
+                && Objects.equals(tr.getDate(), LocalDate.parse(date, 
dateTimeFormatter))).findAny().orElseThrow().getId();
+    }
+
+    protected Journal journalEntry(double amount, Account account, String 
type) {
+        return new Journal(amount, account, type);
+    }
+
+    protected Journal debit(Account account, double amount) {
+        return new Journal(amount, account, "DEBIT");
+    }
+
+    protected Journal credit(Account account, double amount) {
+        return new Journal(amount, account, "CREDIT");
     }
 
     protected Transaction transaction(double principalAmount, String type, 
String date) {
@@ -639,16 +672,16 @@ public abstract class BaseLoanIntegrationTest {
         return new Transaction(principalAmount, type, date, true);
     }
 
-    protected TransactionExt transaction(double amount, String type, String 
date, double outstandingAmount, double principalPortion,
+    protected TransactionExt transaction(double amount, String type, String 
date, double outstandingPrincipal, double principalPortion,
             double interestPortion, double feePortion, double penaltyPortion, 
double unrecognizedIncomePortion, double overpaymentPortion) {
-        return new TransactionExt(amount, type, date, outstandingAmount, 
principalPortion, interestPortion, feePortion, penaltyPortion,
+        return new TransactionExt(amount, type, date, outstandingPrincipal, 
principalPortion, interestPortion, feePortion, penaltyPortion,
                 unrecognizedIncomePortion, overpaymentPortion, false);
     }
 
-    protected TransactionExt transaction(double amount, String type, String 
date, double outstandingAmount, double principalPortion,
+    protected TransactionExt transaction(double amount, String type, String 
date, double outstandingPrincipal, double principalPortion,
             double interestPortion, double feePortion, double penaltyPortion, 
double unrecognizedIncomePortion, double overpaymentPortion,
             boolean reversed) {
-        return new TransactionExt(amount, type, date, outstandingAmount, 
principalPortion, interestPortion, feePortion, penaltyPortion,
+        return new TransactionExt(amount, type, date, outstandingPrincipal, 
principalPortion, interestPortion, feePortion, penaltyPortion,
                 unrecognizedIncomePortion, overpaymentPortion, reversed);
     }
 
@@ -765,7 +798,7 @@ public abstract class BaseLoanIntegrationTest {
         Double amount;
         String type;
         String date;
-        Double outstandingAmount;
+        Double outstandingPrincipal;
         Double principalPortion;
         Double interestPortion;
         Double feePortion;
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargebackWithCreditAllocationsIntegrationTests.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargebackWithCreditAllocationsIntegrationTests.java
index 63ae1b179..ccb3e1a2a 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargebackWithCreditAllocationsIntegrationTests.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargebackWithCreditAllocationsIntegrationTests.java
@@ -1011,6 +1011,455 @@ public class 
LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
         });
     }
 
+    @Test
+    public void testAccountingChargebackOnPrincipal() {
+        runAt("01 January 2023", () -> {
+            // Create Client
+            Long clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+            // Create Loan Product
+            Long loanProductId = createLoanProduct(//
+                    createDefaultPaymentAllocation(), //
+                    chargebackAllocation("PENALTY", "FEE", "INTEREST", 
"PRINCIPAL")//
+            );
+            // Apply and Approve Loan
+            Long loanId = applyAndApproveLoan(clientId, loanProductId, 3);
+
+            // Disburse Loan
+            disburseLoan(loanId, BigDecimal.valueOf(750), "01 January 2023");
+
+            verifyRepaymentSchedule(loanId, //
+                    installment(0, null, "01 January 2023"), //
+                    installment(250.0, 0, 0, 0, 250.0, false, "01 February 
2023"), //
+                    installment(250.0, 0, 0, 0, 250.0, false, "01 March 
2023"), //
+                    installment(250.0, 0, 0, 0, 250.0, false, "01 April 2023") 
//
+            );
+
+            // Repayment #1
+            updateBusinessDate("01 February 2023");
+            Long repaymentTransaction1 = addRepaymentForLoan(loanId, 250.0, 
"01 February 2023");
+
+            // Repayment #2
+            updateBusinessDate("01 March 2023");
+            Long repaymentTransaction2 = addRepaymentForLoan(loanId, 250.0, 
"01 March 2023");
+
+            // Repayment #3
+            updateBusinessDate("30 March 2023");
+            Long repaymentTransaction3 = addRepaymentForLoan(loanId, 250.0, 
"30 March 2023");
+
+            // Chargeback 250
+            Long chargeback = addChargebackForLoan(loanId, 
repaymentTransaction2, 250.0);
+
+            verifyTransactions(loanId, //
+                    transaction(750.0, "Disbursement", "01 January 2023", 
750.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(250.0, "Repayment", "01 February 2023", 500.0, 
250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(250.0, "Repayment", "01 March 2023", 250.0, 
250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(250.0, "Repayment", "30 March 2023", 0.0, 
250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(250.0, "Chargeback", "30 March 2023", 250, 
250.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
+            );
+
+            // Verify GL entries
+            verifyTRJournalEntries(repaymentTransaction1, //
+                    debit(fundSource, 250), //
+                    credit(loansReceivableAccount, 250)//
+            );
+
+            verifyTRJournalEntries(repaymentTransaction2, //
+                    debit(fundSource, 250), //
+                    credit(loansReceivableAccount, 250) //
+            );
+
+            verifyTRJournalEntries(repaymentTransaction3, //
+                    debit(fundSource, 250), //
+                    credit(loansReceivableAccount, 250)//
+            );
+
+            verifyTRJournalEntries(chargeback, //
+                    debit(loansReceivableAccount, 250), //
+                    credit(fundSource, 250) //
+            );
+
+        });
+    }
+
+    @Test
+    public void testAccountingChargebackOnPrincipalAndFees() {
+        runAt("01 January 2023", () -> {
+            // Create Client
+            Long clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+            // Create Loan Product
+            Long loanProductId = createLoanProduct(//
+                    createDefaultPaymentAllocation(), //
+                    chargebackAllocation("PENALTY", "FEE", "INTEREST", 
"PRINCIPAL")//
+            );
+            // Apply and Approve Loan
+            Long loanId = applyAndApproveLoan(clientId, loanProductId, 3);
+
+            // Disburse Loan
+            disburseLoan(loanId, BigDecimal.valueOf(750), "01 January 2023");
+
+            Long feeId = addCharge(loanId, false, 30, "15 February 2023");
+
+            verifyRepaymentSchedule(loanId, //
+                    installment(0, null, "01 January 2023"), //
+                    installment(250.0, 0, 0, 0, 250.0, false, "01 February 
2023"), //
+                    installment(250.0, 0, 30, 0, 280.0, false, "01 March 
2023"), //
+                    installment(250.0, 0, 0, 0, 250.0, false, "01 April 2023") 
//
+            );
+
+            // Repayment #1
+            updateBusinessDate("01 February 2023");
+            Long repaymentTransaction1 = addRepaymentForLoan(loanId, 250.0, 
"01 February 2023");
+
+            // Repayment #2
+            updateBusinessDate("01 March 2023");
+            Long repaymentTransaction2 = addRepaymentForLoan(loanId, 280.0, 
"01 March 2023");
+
+            // Run periodic accrual
+            schedulerJobHelper.executeAndAwaitJob("Add Accrual Transactions");
+
+            // Repayment #3
+            updateBusinessDate("30 March 2023");
+            Long repaymentTransaction3 = addRepaymentForLoan(loanId, 250.0, 
"30 March 2023");
+
+            // Chargeback 250
+            Long chargeback = addChargebackForLoan(loanId, 
repaymentTransaction2, 280.0);
+
+            verifyTransactions(loanId, //
+                    transaction(750.0, "Disbursement", "01 January 2023", 
750.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(250.0, "Repayment", "01 February 2023", 500.0, 
250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(280.0, "Repayment", "01 March 2023", 250.0, 
250.0, 0.0, 30.0, 0.0, 0.0, 0.0), //
+                    transaction(30.0, "Accrual", "01 March 2023", 0.0, 0.0, 
0.0, 30.0, 0.0, 0.0, 0.0), //
+                    transaction(250.0, "Repayment", "30 March 2023", 0.0, 
250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(280.0, "Chargeback", "30 March 2023", 250, 
250.0, 0.0, 30.0, 0.0, 0.0, 0.0) //
+            );
+
+            // Verify GL entries
+            verifyTRJournalEntries(repaymentTransaction1, //
+                    debit(fundSource, 250), //
+                    credit(loansReceivableAccount, 250) //
+            );
+
+            verifyTRJournalEntries(repaymentTransaction2, //
+                    debit(fundSource, 280), //
+                    credit(loansReceivableAccount, 250), //
+                    credit(feeReceivableAccount, 30)//
+            );
+
+            verifyTRJournalEntries(repaymentTransaction3, //
+                    debit(fundSource, 250), //
+                    credit(loansReceivableAccount, 250)//
+            );
+
+            verifyTRJournalEntries(chargeback, //
+                    debit(loansReceivableAccount, 250), //
+                    debit(feeReceivableAccount, 30), //
+                    credit(fundSource, 280) //
+            );
+
+        });
+    }
+
+    @Test
+    public void testAccountingChargebackOnPrincipalAndPenalties() {
+        runAt("01 January 2023", () -> {
+            // Create Client
+            Long clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+            // Create Loan Product
+            Long loanProductId = createLoanProduct(//
+                    createDefaultPaymentAllocation(), //
+                    chargebackAllocation("PENALTY", "FEE", "INTEREST", 
"PRINCIPAL")//
+            );
+            // Apply and Approve Loan
+            Long loanId = applyAndApproveLoan(clientId, loanProductId, 3);
+
+            // Disburse Loan
+            disburseLoan(loanId, BigDecimal.valueOf(750), "01 January 2023");
+
+            Long feeId = addCharge(loanId, true, 30, "15 February 2023");
+
+            verifyRepaymentSchedule(loanId, //
+                    installment(0, null, "01 January 2023"), //
+                    installment(250.0, 0, 0, 0, 250.0, false, "01 February 
2023"), //
+                    installment(250.0, 0, 0, 30.0, 280.0, false, "01 March 
2023"), //
+                    installment(250.0, 0, 0, 0, 250.0, false, "01 April 2023") 
//
+            );
+
+            // Repayment #1
+            updateBusinessDate("01 February 2023");
+            Long repaymentTransaction1 = addRepaymentForLoan(loanId, 250.0, 
"01 February 2023");
+
+            // Repayment #2
+            updateBusinessDate("01 March 2023");
+            Long repaymentTransaction2 = addRepaymentForLoan(loanId, 280.0, 
"01 March 2023");
+
+            // Run periodic accrual
+            schedulerJobHelper.executeAndAwaitJob("Add Accrual Transactions");
+
+            // Repayment #3
+            updateBusinessDate("30 March 2023");
+            Long repaymentTransaction3 = addRepaymentForLoan(loanId, 250.0, 
"30 March 2023");
+
+            // Chargeback 250
+            Long chargeback = addChargebackForLoan(loanId, 
repaymentTransaction2, 280.0);
+
+            verifyTransactions(loanId, //
+                    transaction(750.0, "Disbursement", "01 January 2023", 
750.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(250.0, "Repayment", "01 February 2023", 500.0, 
250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(280.0, "Repayment", "01 March 2023", 250.0, 
250.0, 0.0, 0.0, 30.0, 0.0, 0.0), //
+                    transaction(30.0, "Accrual", "01 March 2023", 0.0, 0.0, 
0.0, 0.0, 30.0, 0.0, 0.0), //
+                    transaction(250.0, "Repayment", "30 March 2023", 0.0, 
250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(280.0, "Chargeback", "30 March 2023", 250, 
250.0, 0.0, 0.0, 30.0, 0.0, 0.0) //
+            );
+
+            // Verify GL entries
+            verifyTRJournalEntries(repaymentTransaction1, //
+                    debit(fundSource, 250), //
+                    credit(loansReceivableAccount, 250) //
+            );
+
+            verifyTRJournalEntries(repaymentTransaction2, //
+                    debit(fundSource, 280), //
+                    credit(loansReceivableAccount, 250), //
+                    credit(penaltyReceivableAccount, 30)//
+            );
+
+            verifyTRJournalEntries(repaymentTransaction3, //
+                    debit(fundSource, 250), //
+                    credit(loansReceivableAccount, 250)//
+            );
+
+            verifyTRJournalEntries(chargeback, //
+                    debit(loansReceivableAccount, 250), //
+                    debit(penaltyReceivableAccount, 30), //
+                    credit(fundSource, 280) //
+            );
+
+        });
+    }
+
+    @Test
+    public void testAccountingOverpaymentAmountIsSmallerThanChargeback() {
+        runAt("01 January 2023", () -> {
+            // Create Client
+            Long clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+            // Create Loan Product
+            Long loanProductId = createLoanProduct(//
+                    createDefaultPaymentAllocation(), //
+                    chargebackAllocation("PENALTY", "FEE", "INTEREST", 
"PRINCIPAL")//
+            );
+            // Apply and Approve Loan
+            Long loanId = applyAndApproveLoan(clientId, loanProductId, 3);
+
+            // Disburse Loan
+            disburseLoan(loanId, BigDecimal.valueOf(750), "01 January 2023");
+
+            verifyRepaymentSchedule(loanId, //
+                    installment(0, null, "01 January 2023"), //
+                    installment(250.0, 0, 0, 0, 250.0, false, "01 February 
2023"), //
+                    installment(250.0, 0, 0, 0, 250.0, false, "01 March 
2023"), //
+                    installment(250.0, 0, 0, 0, 250.0, false, "01 April 2023") 
//
+            );
+
+            // Repayment #1
+            updateBusinessDate("01 February 2023");
+            Long repaymentTransaction1 = addRepaymentForLoan(loanId, 250.0, 
"01 February 2023");
+
+            // Repayment #2
+            updateBusinessDate("01 March 2023");
+            Long repaymentTransaction2 = addRepaymentForLoan(loanId, 250.0, 
"01 March 2023");
+
+            // Repayment #3
+            updateBusinessDate("30 March 2023");
+            Long repaymentTransaction3 = addRepaymentForLoan(loanId, 400.0, 
"30 March 2023");
+
+            // Chargeback 250
+            updateBusinessDate("31 March 2023");
+            Long chargeback = addChargebackForLoan(loanId, 
repaymentTransaction2, 250.0);
+
+            verifyTransactions(loanId, //
+                    transaction(750.0, "Disbursement", "01 January 2023", 
750.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(250.0, "Repayment", "01 February 2023", 500.0, 
250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(250.0, "Repayment", "01 March 2023", 250.0, 
250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(400.0, "Repayment", "30 March 2023", 0.0, 
250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(250.0, "Chargeback", "31 March 2023", 100, 
250.0, 0.0, 0.0, 0.0, 0.0, 150.0) //
+            );
+
+            // Verify GL entries
+            verifyTRJournalEntries(repaymentTransaction1, //
+                    debit(fundSource, 250), //
+                    credit(loansReceivableAccount, 250) //
+            );
+
+            verifyTRJournalEntries(repaymentTransaction2, //
+                    debit(fundSource, 250), //
+                    credit(loansReceivableAccount, 250) //
+            );
+
+            verifyTRJournalEntries(repaymentTransaction3, //
+                    debit(fundSource, 400), //
+                    credit(loansReceivableAccount, 250), //
+                    credit(overpaymentAccount, 150) //
+            );
+
+            verifyTRJournalEntries(chargeback, //
+                    debit(loansReceivableAccount, 100), //
+                    debit(overpaymentAccount, 150), //
+                    credit(fundSource, 250) //
+            );
+        });
+    }
+
+    @Test
+    public void testAccountingOverpaymentAmountIsBiggerThanChargeback() {
+        runAt("01 January 2023", () -> {
+            // Create Client
+            Long clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+            // Create Loan Product
+            Long loanProductId = createLoanProduct(//
+                    createDefaultPaymentAllocation(), //
+                    chargebackAllocation("PENALTY", "FEE", "INTEREST", 
"PRINCIPAL")//
+            );
+            // Apply and Approve Loan
+            Long loanId = applyAndApproveLoan(clientId, loanProductId, 3);
+
+            // Disburse Loan
+            disburseLoan(loanId, BigDecimal.valueOf(750), "01 January 2023");
+
+            verifyRepaymentSchedule(loanId, //
+                    installment(0, null, "01 January 2023"), //
+                    installment(250.0, 0, 0, 0, 250.0, false, "01 February 
2023"), //
+                    installment(250.0, 0, 0, 0, 250.0, false, "01 March 
2023"), //
+                    installment(250.0, 0, 0, 0, 250.0, false, "01 April 2023") 
//
+            );
+
+            // Repayment #1
+            updateBusinessDate("01 February 2023");
+            Long repaymentTransaction1 = addRepaymentForLoan(loanId, 250.0, 
"01 February 2023");
+
+            // Repayment #2
+            updateBusinessDate("01 March 2023");
+            Long repaymentTransaction2 = addRepaymentForLoan(loanId, 250.0, 
"01 March 2023");
+
+            // Repayment #3
+            updateBusinessDate("30 March 2023");
+            Long repaymentTransaction3 = addRepaymentForLoan(loanId, 400.0, 
"30 March 2023");
+
+            // Chargeback 250
+            updateBusinessDate("31 March 2023");
+            Long chargeback = addChargebackForLoan(loanId, 
repaymentTransaction2, 100.0);
+
+            verifyTransactions(loanId, //
+                    transaction(750.0, "Disbursement", "01 January 2023", 
750.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(250.0, "Repayment", "01 February 2023", 500.0, 
250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(250.0, "Repayment", "01 March 2023", 250.0, 
250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(400.0, "Repayment", "30 March 2023", 0.0, 
250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(100.0, "Chargeback", "31 March 2023", 0.0, 
100.0, 0.0, 0.0, 0.0, 0.0, -50.0) //
+            );
+
+            // Verify GL entries
+            verifyTRJournalEntries(repaymentTransaction1, //
+                    debit(fundSource, 250), //
+                    credit(loansReceivableAccount, 250) //
+            );
+
+            verifyTRJournalEntries(repaymentTransaction2, //
+                    debit(fundSource, 250), //
+                    credit(loansReceivableAccount, 250) //
+            );
+
+            verifyTRJournalEntries(repaymentTransaction3, //
+                    debit(fundSource, 400), //
+                    credit(loansReceivableAccount, 250), //
+                    credit(overpaymentAccount, 150) //
+            );
+
+            verifyTRJournalEntries(chargeback, //
+                    debit(overpaymentAccount, 100), //
+                    credit(fundSource, 100) //
+            );
+        });
+    }
+
+    @Test
+    public void 
testAccountingOverpaidLoansWithFeesWhenOverpaymentAmountIsBiggerThanChargeback()
 {
+        runAt("01 January 2023", () -> {
+            // Create Client
+            Long clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+            // Create Loan Product
+            Long loanProductId = createLoanProduct(//
+                    createDefaultPaymentAllocation(), //
+                    chargebackAllocation("PENALTY", "FEE", "INTEREST", 
"PRINCIPAL")//
+            );
+            // Apply and Approve Loan
+            Long loanId = applyAndApproveLoan(clientId, loanProductId, 3);
+
+            // Disburse Loan
+            disburseLoan(loanId, BigDecimal.valueOf(750), "01 January 2023");
+
+            verifyRepaymentSchedule(loanId, //
+                    installment(0, null, "01 January 2023"), //
+                    installment(250.0, 0, 0, 0, 250.0, false, "01 February 
2023"), //
+                    installment(250.0, 0, 0, 0, 250.0, false, "01 March 
2023"), //
+                    installment(250.0, 0, 0, 0, 250.0, false, "01 April 2023") 
//
+            );
+
+            // Repayment #1
+            updateBusinessDate("01 February 2023");
+            Long repaymentTransaction1 = addRepaymentForLoan(loanId, 250.0, 
"01 February 2023");
+
+            // Add fee & Repayment #2
+            updateBusinessDate("01 March 2023");
+            Long feeId = addCharge(loanId, false, 30, "01 March 2023");
+            Long repaymentTransaction2 = addRepaymentForLoan(loanId, 280.0, 
"01 March 2023");
+            schedulerJobHelper.executeAndAwaitJob("Add Accrual Transactions");
+
+            // Repayment #3
+            updateBusinessDate("30 March 2023");
+            Long repaymentTransaction3 = addRepaymentForLoan(loanId, 400.0, 
"30 March 2023");
+
+            // Chargeback 250
+            updateBusinessDate("31 March 2023");
+            Long chargeback = addChargebackForLoan(loanId, 
repaymentTransaction2, 100.0);
+
+            verifyTransactions(loanId, //
+                    transaction(750.0, "Disbursement", "01 January 2023", 
750.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(250.0, "Repayment", "01 February 2023", 500.0, 
250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(280.0, "Repayment", "01 March 2023", 250.0, 
250.0, 0.0, 30.0, 0.0, 0.0, 0.0), //
+                    transaction(30.0, "Accrual", "01 March 2023", 0.0, 0.0, 
0.0, 30.0, 0.0, 0.0, 0.0), //
+                    transaction(400.0, "Repayment", "30 March 2023", 0.0, 
250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+                    transaction(100.0, "Chargeback", "31 March 2023", 0.0, 
70.0, 0.0, 30.0, 0.0, 0.0, -50.0) //
+            );
+
+            // Verify GL entries
+            verifyTRJournalEntries(repaymentTransaction1, //
+                    debit(fundSource, 250), //
+                    credit(loansReceivableAccount, 250) //
+            );
+
+            verifyTRJournalEntries(repaymentTransaction2, //
+                    debit(fundSource, 280), //
+                    credit(loansReceivableAccount, 250), //
+                    credit(feeReceivableAccount, 30) //
+            );
+
+            verifyTRJournalEntries(getTransactionId(loanId, "Accrual", "01 
March 2023"), //
+                    debit(feeReceivableAccount, 30), //
+                    credit(feeIncomeAccount, 30) //
+            );
+
+            verifyTRJournalEntries(repaymentTransaction3, //
+                    debit(fundSource, 400), //
+                    credit(loansReceivableAccount, 250), //
+                    credit(overpaymentAccount, 150) //
+            );
+
+            verifyTRJournalEntries(chargeback, //
+                    debit(overpaymentAccount, 100), //
+                    credit(fundSource, 100) //
+            );
+        });
+    }
+
     private void verifyLoanSummaryAmounts(Long loanId, double 
creditedPrincipal, double creditedFee, double creditedPenalty,
             double totalOutstanding) {
         GetLoansLoanIdResponse loanResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId.intValue());
@@ -1023,10 +1472,10 @@ public class 
LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
     }
 
     @Nullable
-    private Long applyAndApproveLoan(Long clientId, Long loanProductId) {
-        PostLoansRequest applicationRequest = applyLoanRequest(clientId, 
loanProductId, "01 January 2023", 1250.0, 4)//
+    private Long applyAndApproveLoan(Long clientId, Long loanProductId, int 
numberOfRepayments) {
+        PostLoansRequest applicationRequest = applyLoanRequest(clientId, 
loanProductId, "01 January 2023", 1250.0, numberOfRepayments)//
                 .repaymentEvery(1)//
-                .loanTermFrequency(4)//
+                .loanTermFrequency(numberOfRepayments)//
                 .repaymentFrequencyType(RepaymentFrequencyType.MONTHS)//
                 .loanTermFrequencyType(RepaymentFrequencyType.MONTHS)//
                 
.transactionProcessingStrategyCode("advanced-payment-allocation-strategy");
@@ -1036,8 +1485,12 @@ public class 
LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
         PostLoansLoanIdResponse approvedLoanResult = 
loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
                 approveLoanRequest(1250.0, "01 January 2023"));
 
-        Long loanId = approvedLoanResult.getLoanId();
-        return loanId;
+        return approvedLoanResult.getLoanId();
+    }
+
+    @Nullable
+    private Long applyAndApproveLoan(Long clientId, Long loanProductId) {
+        return applyAndApproveLoan(clientId, loanProductId, 4);
     }
 
     public Long createLoanProduct(AdvancedPaymentData defaultAllocation, 
CreditAllocationData creditAllocationData) {
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDownPaymentTransactionChargebackTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDownPaymentTransactionChargebackTest.java
index 17e05c2de..2b8f7b015 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDownPaymentTransactionChargebackTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDownPaymentTransactionChargebackTest.java
@@ -23,7 +23,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
 import java.math.BigDecimal;
-import 
org.apache.fineract.client.models.GetJournalEntriesTransactionIdResponse;
 import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
 import 
org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse;
 import org.apache.fineract.client.models.PostLoanProductsRequest;
@@ -88,15 +87,10 @@ public class LoanDownPaymentTransactionChargebackTest 
extends BaseLoanIntegratio
             );
 
             // verify journal entries for chargeback transaction
-            GetJournalEntriesTransactionIdResponse journalEntries = 
journalEntryHelper
-                    .getJournalEntries("L" + 
chargebackTransactionId.toString());
-            assertEquals(2L, journalEntries.getTotalFilteredRecords());
-            assertEquals(50.0, 
journalEntries.getPageItems().get(0).getAmount());
-            assertEquals("CREDIT", 
journalEntries.getPageItems().get(0).getEntryType().getValue());
-
-            assertEquals(50.0, 
journalEntries.getPageItems().get(1).getAmount());
-            assertEquals("DEBIT", 
journalEntries.getPageItems().get(1).getEntryType().getValue());
-
+            verifyTRJournalEntries(chargebackTransactionId, //
+                    credit(fundSource, 50.0), //
+                    debit(loansReceivableAccount, 50.0) //
+            );
         });
     }
 
@@ -152,15 +146,10 @@ public class LoanDownPaymentTransactionChargebackTest 
extends BaseLoanIntegratio
             );
 
             // verify journal entries for chargeback transaction
-            GetJournalEntriesTransactionIdResponse journalEntries = 
journalEntryHelper
-                    .getJournalEntries("L" + 
chargebackTransactionId.toString());
-            assertEquals(2L, journalEntries.getTotalFilteredRecords());
-            assertEquals(50.0, 
journalEntries.getPageItems().get(0).getAmount());
-            assertEquals("CREDIT", 
journalEntries.getPageItems().get(0).getEntryType().getValue());
-
-            assertEquals(50.0, 
journalEntries.getPageItems().get(1).getAmount());
-            assertEquals("DEBIT", 
journalEntries.getPageItems().get(1).getEntryType().getValue());
-
+            verifyTRJournalEntries(chargebackTransactionId, //
+                    credit(fundSource, 50.0), //
+                    debit(loansReceivableAccount, 50.0) //
+            );
         });
     }
 
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentScheduleWithDownPaymentTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentScheduleWithDownPaymentTest.java
index d9cf82d3c..9ef2a6acb 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentScheduleWithDownPaymentTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentScheduleWithDownPaymentTest.java
@@ -1252,10 +1252,11 @@ public class LoanRepaymentScheduleWithDownPaymentTest 
extends BaseLoanIntegratio
                     transaction(1000.0, "Disbursement", "03 March 2023", 
1000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
                     transaction(250.0, "Down Payment", "03 March 2023", 750.0, 
250.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
             );
-            verifyJournalEntries(loanResponse.getResourceId(), 
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+            verifyJournalEntries(loanResponse.getResourceId(), //
+                    journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT") //
+                    journalEntry(250.0, fundSource, "DEBIT") //
             );
 
             
loanTransactionHelper.makeLoanRepayment(loanResponse.getResourceId(), new 
PostLoansLoanIdTransactionsRequest()
@@ -1464,10 +1465,11 @@ public class LoanRepaymentScheduleWithDownPaymentTest 
extends BaseLoanIntegratio
                     transaction(1000.0, "Disbursement", "03 March 2023", 
1000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
                     transaction(250.0, "Down Payment", "03 March 2023", 750.0, 
250.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
             );
-            verifyJournalEntries(loanResponse.getResourceId(), 
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+            verifyJournalEntries(loanResponse.getResourceId(), //
+                    journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT") //
+                    journalEntry(250.0, fundSource, "DEBIT") //
             );
 
             String externalId = UUID.randomUUID().toString();
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleTestWithDownpayment.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleTestWithDownpayment.java
index d54a60d20..450553ff8 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleTestWithDownpayment.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleTestWithDownpayment.java
@@ -74,9 +74,9 @@ public class LoanRescheduleTestWithDownpayment extends 
BaseLoanIntegrationTest {
 
             // verify journal entries
             verifyJournalEntries(loanId, journalEntry(250.0, 
loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionChargebackTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionChargebackTest.java
index 635a6c2c3..0fb211c96 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionChargebackTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionChargebackTest.java
@@ -18,6 +18,7 @@
  */
 package org.apache.fineract.integrationtests;
 
+import static 
org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder.ACCRUAL_PERIODIC;
 import static 
org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder.DEFAULT_STRATEGY;
 import static 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY;
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -39,7 +40,6 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.fineract.client.models.AdvancedPaymentData;
 import org.apache.fineract.client.models.GetDelinquencyBucketsResponse;
 import org.apache.fineract.client.models.GetDelinquencyRangesResponse;
-import 
org.apache.fineract.client.models.GetJournalEntriesTransactionIdResponse;
 import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
 import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
 import org.apache.fineract.client.models.GetLoansLoanIdRepaymentSchedule;
@@ -53,7 +53,6 @@ import 
org.apache.fineract.integrationtests.common.BusinessDateHelper;
 import org.apache.fineract.integrationtests.common.ClientHelper;
 import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
 import org.apache.fineract.integrationtests.common.Utils;
-import org.apache.fineract.integrationtests.common.accounting.Account;
 import org.apache.fineract.integrationtests.common.accounting.AccountHelper;
 import 
org.apache.fineract.integrationtests.common.accounting.JournalEntryHelper;
 import 
org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
@@ -72,7 +71,7 @@ import org.junit.jupiter.params.provider.MethodSource;
 
 @Slf4j
 @ExtendWith(LoanTestLifecycleExtension.class)
-public class LoanTransactionChargebackTest {
+public class LoanTransactionChargebackTest extends BaseLoanIntegrationTest {
 
     private ResponseSpecification responseSpec;
     private ResponseSpecification responseSpecErr400;
@@ -139,14 +138,10 @@ public class LoanTransactionChargebackTest {
 
         
loanTransactionHelper.validateLoanPrincipalOustandingBalance(getLoansLoanIdResponse,
 amount.doubleValue());
 
-        GetJournalEntriesTransactionIdResponse journalEntries = 
journalEntryHelper
-                .getJournalEntries("L" + chargebackTransactionId.toString());
-        assertEquals(2L, journalEntries.getTotalFilteredRecords());
-        assertEquals(1000.0, journalEntries.getPageItems().get(0).getAmount());
-        assertEquals("CREDIT", 
journalEntries.getPageItems().get(0).getEntryType().getValue());
-
-        assertEquals(1000.0, journalEntries.getPageItems().get(1).getAmount());
-        assertEquals("DEBIT", 
journalEntries.getPageItems().get(1).getEntryType().getValue());
+        verifyTRJournalEntries(chargebackTransactionId, //
+                credit(fundSource, 1000.0), //
+                debit(loansReceivableAccount, 1000.0) //
+        );
 
         // Try to reverse a Loan Transaction charge back
         PostLoansLoanIdTransactionsResponse reverseTransactionResponse = 
loanTransactionHelper.reverseLoanTransaction(loanId,
@@ -431,17 +426,11 @@ public class LoanTransactionChargebackTest {
         
assertEquals(getLoansLoanIdResponse.getTimeline().getExpectedMaturityDate(),
                 getLoansLoanIdResponse.getTimeline().getActualMaturityDate());
 
-        GetJournalEntriesTransactionIdResponse journalEntries = 
journalEntryHelper
-                .getJournalEntries("L" + chargebackTransactionId.toString());
-        assertEquals(3L, journalEntries.getTotalFilteredRecords());
-        assertEquals(100.0, journalEntries.getPageItems().get(0).getAmount());
-        assertEquals("DEBIT", 
journalEntries.getPageItems().get(0).getEntryType().getValue());
-
-        assertEquals(200.0, journalEntries.getPageItems().get(1).getAmount());
-        assertEquals("CREDIT", 
journalEntries.getPageItems().get(1).getEntryType().getValue());
-
-        assertEquals(100.0, journalEntries.getPageItems().get(2).getAmount());
-        assertEquals("DEBIT", 
journalEntries.getPageItems().get(2).getEntryType().getValue());
+        verifyTRJournalEntries(chargebackTransactionId, //
+                credit(fundSource, 200.0), //
+                debit(loansReceivableAccount, 100.0), //
+                debit(overpaymentAccount, 100.0) //
+        );
 
         final GetDelinquencyRangesResponse delinquencyRange = 
getLoansLoanIdResponse.getDelinquencyRange();
         assertNull(delinquencyRange);
@@ -525,14 +514,10 @@ public class LoanTransactionChargebackTest {
 
         
loanTransactionHelper.validateLoanPrincipalOustandingBalance(getLoansLoanIdResponse,
 Double.valueOf("0.00"));
 
-        GetJournalEntriesTransactionIdResponse journalEntries = 
journalEntryHelper
-                .getJournalEntries("L" + chargebackTransactionId.toString());
-        assertEquals(2L, journalEntries.getTotalFilteredRecords());
-        assertEquals(50.0, journalEntries.getPageItems().get(0).getAmount());
-        assertEquals("CREDIT", 
journalEntries.getPageItems().get(0).getEntryType().getValue());
-
-        assertEquals(50.0, journalEntries.getPageItems().get(1).getAmount());
-        assertEquals("DEBIT", 
journalEntries.getPageItems().get(1).getEntryType().getValue());
+        verifyTRJournalEntries(chargebackTransactionId, //
+                credit(fundSource, 50.0), //
+                debit(overpaymentAccount, 50.0) //
+        );
     }
 
     @ParameterizedTest
@@ -632,12 +617,20 @@ public class LoanTransactionChargebackTest {
             final Integer delinquencyBucketId, final boolean 
withJournalEntries, LoanProductTestBuilder loanProductTestBuilder) {
         final HashMap<String, Object> loanProductMap;
         if (withJournalEntries) {
-            final Account assetAccount = accountHelper.createAssetAccount();
-            final Account expenseAccount = 
accountHelper.createExpenseAccount();
-            final Account incomeAccount = accountHelper.createIncomeAccount();
-            final Account overpaymentAccount = 
accountHelper.createLiabilityAccount();
             loanProductMap = loanProductTestBuilder
-                    .withAccountingRulePeriodicAccrual(new Account[] { 
assetAccount, expenseAccount, incomeAccount, overpaymentAccount })
+                    .withFullAccountingConfig(ACCRUAL_PERIODIC,
+                            
LoanProductTestBuilder.FullAccountingConfig.builder().fundSourceAccountId(fundSource.getAccountID().longValue())//
+                                    
.loanPortfolioAccountId(loansReceivableAccount.getAccountID().longValue())//
+                                    
.transfersInSuspenseAccountId(suspenseAccount.getAccountID().longValue())//
+                                    
.interestOnLoanAccountId(interestIncomeAccount.getAccountID().longValue())//
+                                    
.incomeFromFeeAccountId(feeIncomeAccount.getAccountID().longValue())//
+                                    
.incomeFromPenaltyAccountId(penaltyIncomeAccount.getAccountID().longValue())//
+                                    
.incomeFromRecoveryAccountId(recoveriesAccount.getAccountID().longValue())//
+                                    
.writeOffAccountId(writtenOffAccount.getAccountID().longValue())//
+                                    
.overpaymentLiabilityAccountId(overpaymentAccount.getAccountID().longValue())//
+                                    
.receivableInterestAccountId(interestReceivableAccount.getAccountID().longValue())//
+                                    
.receivableFeeAccountId(interestReceivableAccount.getAccountID().longValue())//
+                                    
.receivablePenaltyAccountId(interestReceivableAccount.getAccountID().longValue()).build())
                     .build(null, delinquencyBucketId);
         } else {
             loanProductMap = loanProductTestBuilder.build(null, 
delinquencyBucketId);
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/UndoLoanDisbursalWithDownPaymentIntegrationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/UndoLoanDisbursalWithDownPaymentIntegrationTest.java
index 6ecb979ac..20f4837ac 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/UndoLoanDisbursalWithDownPaymentIntegrationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/UndoLoanDisbursalWithDownPaymentIntegrationTest.java
@@ -69,9 +69,9 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest 
extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -91,14 +91,14 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             verifyJournalEntries(loanId,
                     // original entries
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
                     // original entries reverted
                     journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(250.0, fundSource, "CREDIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "DEBIT")); //
+                    journalEntry(1000.0, fundSource, "DEBIT")); //
 
             verifyRepaymentSchedule(loanId, //
                     installment(1000.0, null, "01 January 2023"), //
@@ -139,9 +139,9 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // make a repayment
@@ -164,23 +164,23 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             verifyJournalEntries(loanId, //
                     // original entries down-payment
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
 
                     // repayment entries
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
 
                     // original entries compensated
                     journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(250.0, fundSource, "CREDIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(1000.0, fundSource, "DEBIT"), //
 
                     // repayment entries compensated
                     journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(250.0, fundSource, "CREDIT") //
             );
 
             verifyRepaymentSchedule(loanId, //
@@ -225,9 +225,9 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // undoDisbursal
@@ -240,15 +240,15 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             verifyJournalEntries(loanId, //
                     // original entries
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
 
                     // original entries are compensated
                     journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(250.0, fundSource, "CREDIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "DEBIT") //
+                    journalEntry(1000.0, fundSource, "DEBIT") //
             );
 
             // verify repayment entries are reverted
@@ -298,11 +298,11 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -322,23 +322,23 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             verifyJournalEntries(loanId, //
                     // original entries
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
 
                     // original entries compensated
                     journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(250.0, fundSource, "CREDIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(1000.0, fundSource, "DEBIT"), //
 
                     // manual partial repayment of the first installment
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
 
                     // manual partial repayment of the first installment 
compensation after undoDisburse
                     journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(100.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -381,9 +381,9 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -429,9 +429,9 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -476,9 +476,9 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -498,14 +498,14 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             verifyJournalEntries(loanId, //
                     // original entries
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
                     // original entries reverted
                     journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(250.0, fundSource, "CREDIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "DEBIT") //
+                    journalEntry(1000.0, fundSource, "DEBIT") //
             );
 
             // Verify Repayment Schedule
@@ -548,9 +548,9 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // make a repayment
@@ -573,23 +573,23 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             verifyJournalEntries(loanId,
                     // original entries down-payment
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
 
                     // repayment entries
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
 
                     // original entries compensated
                     journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(250.0, fundSource, "CREDIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(1000.0, fundSource, "DEBIT"), //
 
                     // repayment entries compensated
                     journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(250.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -635,9 +635,9 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // undoDisbursal
@@ -650,15 +650,15 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             verifyJournalEntries(loanId,
                     // original entries
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
 
                     // original entries are compensated
                     journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(250.0, fundSource, "CREDIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "DEBIT") //
+                    journalEntry(1000.0, fundSource, "DEBIT") //
             );
 
             // Verify Repayment Schedule
@@ -707,11 +707,11 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -731,23 +731,23 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             verifyJournalEntries(loanId,
                     // original entries
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
 
                     // original entries compensated
                     journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(250.0, fundSource, "CREDIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(1000.0, fundSource, "DEBIT"), //
 
                     // manual partial repayment of the first installment
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
 
                     // manual partial repayment of the first installment 
compensation after undoDisburse
                     journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(100.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -787,9 +787,9 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
 
             // verify journal entries
             verifyJournalEntries(loanId, journalEntry(250.0, 
loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -815,13 +815,13 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
                     journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(400.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -846,21 +846,21 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             verifyJournalEntries(loanId,
                     // first disbursement + down-payment
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
 
                     // second disbursement + down-payment
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
                     journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(400.0, fundSource, "CREDIT"), //
 
                     // compensation of second disbursement + down-payment
                     journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(100.0, fundSource, "CREDIT"), //
                     journalEntry(400.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "DEBIT") //
+                    journalEntry(400.0, fundSource, "DEBIT") //
             );
 
             verifyRepaymentSchedule(loanId, //
@@ -901,9 +901,9 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
 
             // verify journal entries
             verifyJournalEntries(loanId, journalEntry(250.0, 
loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -941,15 +941,15 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
                     journalEntry(300.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(300.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(300.0, fundSource, "DEBIT"), //
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
                     journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(400.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -975,25 +975,25 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             verifyJournalEntries(loanId,
                     // first disbursement + down-payment
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
 
                     // repayment
                     journalEntry(300.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(300.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(300.0, fundSource, "DEBIT"), //
 
                     // second disbursement + down-payment
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
                     journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(400.0, fundSource, "CREDIT"), //
 
                     // compensation of second disbursement + down-payment
                     journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(100.0, fundSource, "CREDIT"), //
                     journalEntry(400.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "DEBIT") //
+                    journalEntry(400.0, fundSource, "DEBIT") //
             );
 
             verifyRepaymentSchedule(loanId, //
@@ -1038,9 +1038,9 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -1070,13 +1070,13 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
                     journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(400.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -1101,21 +1101,21 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             verifyJournalEntries(loanId,
                     // first disbursement + down-payment
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
 
                     // second disbursement + down-payment
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
                     journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(400.0, fundSource, "CREDIT"), //
 
                     // compensation of second disbursement + down-payment
                     journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(100.0, fundSource, "CREDIT"), //
                     journalEntry(400.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "DEBIT") //
+                    journalEntry(400.0, fundSource, "DEBIT") //
             );
 
             verifyRepaymentSchedule(loanId, //
@@ -1157,9 +1157,9 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -1186,13 +1186,13 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
                     journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(400.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -1249,9 +1249,9 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -1281,13 +1281,13 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
                     journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(400.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -1341,9 +1341,9 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -1370,13 +1370,13 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
                     journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(400.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -1404,27 +1404,27 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             verifyJournalEntries(loanId,
                     // 1st disbursal + down-payment
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
 
                     // 2nd disbursal + down-payment
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
                     journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(400.0, fundSource, "CREDIT"), //
 
                     // compensation of the 1st disbursal + down-payment
                     journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(250.0, fundSource, "CREDIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(1000.0, fundSource, "DEBIT"), //
 
                     // compensation of the 2nd disbursal + down-payment
                     journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(100.0, fundSource, "CREDIT"), //
                     journalEntry(400.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "DEBIT") //
+                    journalEntry(400.0, fundSource, "DEBIT") //
             );
         });
     }
@@ -1463,9 +1463,9 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -1495,13 +1495,13 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
                     journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(400.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -1529,27 +1529,27 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             verifyJournalEntries(loanId,
                     // 1st disbursal + down-payment
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
 
                     // 2nd disbursal + down-payment
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
                     journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(400.0, fundSource, "CREDIT"), //
 
                     // compensation of the 1st disbursal + down-payment
                     journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(250.0, fundSource, "CREDIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(1000.0, fundSource, "DEBIT"), //
 
                     // compensation of the 2nd disbursal + down-payment
                     journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(100.0, fundSource, "CREDIT"), //
                     journalEntry(400.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "DEBIT") //
+                    journalEntry(400.0, fundSource, "DEBIT") //
             );
         });
     }
@@ -1585,9 +1585,9 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -1614,13 +1614,13 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
                     journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(400.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -1654,35 +1654,35 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             verifyJournalEntries(loanId,
                     // 1st disbursal + down-payment
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
 
                     // 2nd disbursal + down-payment
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
                     journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(400.0, fundSource, "CREDIT"), //
 
                     // manual repayment
                     journalEntry(50.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(50.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(50.0, fundSource, "DEBIT"), //
 
                     // compensation of the 1st disbursal + down-payment
                     journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(250.0, fundSource, "CREDIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(1000.0, fundSource, "DEBIT"), //
 
                     // compensation of the 2nd disbursal + down-payment
                     journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(100.0, fundSource, "CREDIT"), //
                     journalEntry(400.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(400.0, fundSource, "DEBIT"), //
 
                     // compensation of repayment
                     journalEntry(50.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(50.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(50.0, fundSource, "CREDIT") //
             );
         });
     }
@@ -1721,9 +1721,9 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             // verify journal entries
             verifyJournalEntries(loanId, //
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(1000.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -1752,13 +1752,13 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
 
             // verify journal entries
             verifyJournalEntries(loanId, journalEntry(250.0, 
loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
                     journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(400.0, fundSource, "CREDIT") //
             );
 
             // Verify Repayment Schedule
@@ -1792,35 +1792,35 @@ public class 
UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
             verifyJournalEntries(loanId,
                     // 1st disbursal + down-payment
                     journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(250.0, fundSource, "DEBIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(1000.0, fundSource, "CREDIT"), //
 
                     // 2nd disbursal + down-payment
                     journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(100.0, fundSource, "DEBIT"), //
                     journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(400.0, fundSource, "CREDIT"), //
 
                     // manual repayment
                     journalEntry(50.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(50.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(50.0, fundSource, "DEBIT"), //
 
                     // compensation of the 1st disbursal + down-payment
                     journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(250.0, fundSource, "CREDIT"), //
                     journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(1000.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(1000.0, fundSource, "DEBIT"), //
 
                     // compensation of the 2nd disbursal + down-payment
                     journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(100.0, suspenseClearingAccount, "CREDIT"), //
+                    journalEntry(100.0, fundSource, "CREDIT"), //
                     journalEntry(400.0, loansReceivableAccount, "CREDIT"), //
-                    journalEntry(400.0, suspenseClearingAccount, "DEBIT"), //
+                    journalEntry(400.0, fundSource, "DEBIT"), //
 
                     // compensation of repayment
                     journalEntry(50.0, loansReceivableAccount, "DEBIT"), //
-                    journalEntry(50.0, suspenseClearingAccount, "CREDIT") //
+                    journalEntry(50.0, fundSource, "CREDIT") //
             );
         });
     }
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/AccountHelper.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/AccountHelper.java
index 0d2a50392..100447372 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/AccountHelper.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/AccountHelper.java
@@ -42,35 +42,55 @@ public class AccountHelper extends IntegrationTest {
     }
 
     public Account createAssetAccount() {
-        final String assetAccountJSON = new 
GLAccountBuilder().withAccountTypeAsAsset().build();
+        return this.createAssetAccount(null);
+    }
+
+    public Account createIncomeAccount() {
+        return this.createIncomeAccount(null);
+    }
+
+    public Account createExpenseAccount() {
+        return this.createExpenseAccount(null);
+    }
+
+    public Account createLiabilityAccount() {
+        return this.createLiabilityAccount(null);
+    }
+
+    public Account createEquityAccount() {
+        return this.createEquityAccount(null);
+    }
+
+    public Account createAssetAccount(String accountName) {
+        final String assetAccountJSON = new 
GLAccountBuilder().withName(accountName).withAccountTypeAsAsset().build();
         final Integer accountID = Utils.performServerPost(this.requestSpec, 
this.responseSpec, CREATE_GL_ACCOUNT_URL, assetAccountJSON,
                 GL_ACCOUNT_ID_RESPONSE);
         return new Account(accountID, Account.AccountType.ASSET);
     }
 
-    public Account createIncomeAccount() {
-        final String assetAccountJSON = new 
GLAccountBuilder().withAccountTypeAsIncome().build();
+    public Account createIncomeAccount(String accountName) {
+        final String assetAccountJSON = new 
GLAccountBuilder().withName(accountName).withAccountTypeAsIncome().build();
         final Integer accountID = Utils.performServerPost(this.requestSpec, 
this.responseSpec, CREATE_GL_ACCOUNT_URL, assetAccountJSON,
                 GL_ACCOUNT_ID_RESPONSE);
         return new Account(accountID, Account.AccountType.INCOME);
     }
 
-    public Account createExpenseAccount() {
-        final String assetAccountJSON = new 
GLAccountBuilder().withAccountTypeAsExpense().build();
+    public Account createExpenseAccount(String accountName) {
+        final String assetAccountJSON = new 
GLAccountBuilder().withName(accountName).withAccountTypeAsExpense().build();
         final Integer accountID = Utils.performServerPost(this.requestSpec, 
this.responseSpec, CREATE_GL_ACCOUNT_URL, assetAccountJSON,
                 GL_ACCOUNT_ID_RESPONSE);
         return new Account(accountID, Account.AccountType.EXPENSE);
     }
 
-    public Account createLiabilityAccount() {
-        final String liabilityAccountJSON = new 
GLAccountBuilder().withAccountTypeAsLiability().build();
+    public Account createLiabilityAccount(String accountName) {
+        final String liabilityAccountJSON = new 
GLAccountBuilder().withName(accountName).withAccountTypeAsLiability().build();
         final Integer accountID = Utils.performServerPost(this.requestSpec, 
this.responseSpec, CREATE_GL_ACCOUNT_URL, liabilityAccountJSON,
                 GL_ACCOUNT_ID_RESPONSE);
         return new Account(accountID, Account.AccountType.LIABILITY);
     }
 
-    public Account createEquityAccount() {
-        final String equityAccountJSON = new 
GLAccountBuilder().withAccountTypeAsAsEquity().build();
+    public Account createEquityAccount(String accountName) {
+        final String equityAccountJSON = new 
GLAccountBuilder().withName(accountName).withAccountTypeAsAsEquity().build();
         final Integer accountID = Utils.performServerPost(this.requestSpec, 
this.responseSpec, CREATE_GL_ACCOUNT_URL, equityAccountJSON,
                 GL_ACCOUNT_ID_RESPONSE);
         return new Account(accountID, Account.AccountType.EQUITY);
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/GLAccountBuilder.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/GLAccountBuilder.java
index 9edec639f..9a675d159 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/GLAccountBuilder.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/GLAccountBuilder.java
@@ -21,6 +21,7 @@ package 
org.apache.fineract.integrationtests.common.accounting;
 import com.google.gson.Gson;
 import java.util.Calendar;
 import java.util.HashMap;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.fineract.integrationtests.common.Utils;
 
 public class GLAccountBuilder {
@@ -86,6 +87,13 @@ public class GLAccountBuilder {
         return this;
     }
 
+    public GLAccountBuilder withName(String name) {
+        if (StringUtils.isNotBlank(name)) {
+            this.name = Utils.uniqueRandomStringGenerator(name + "_", 5);
+        }
+        return this;
+    }
+
     public GLAccountBuilder withAccountUsageAsHeader() {
         accountUsage = ACCOUNT_USAGE_HEADER;
         return this;
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
index a5973d554..7fd2529f4 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
@@ -25,6 +25,8 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
+import lombok.Builder;
 import org.apache.fineract.client.models.AdvancedPaymentData;
 import org.apache.fineract.client.models.CreditAllocationData;
 import org.apache.fineract.integrationtests.common.Utils;
@@ -69,10 +71,10 @@ public class LoanProductTestBuilder {
     public static final String RECALCULATION_COMPOUNDING_METHOD_FEE = "2";
     public static final String 
RECALCULATION_COMPOUNDING_METHOD_INTEREST_AND_FEE = "3";
 
-    private static final String NONE = "1";
-    private static final String CASH_BASED = "2";
-    private static final String ACCRUAL_PERIODIC = "3";
-    private static final String ACCRUAL_UPFRONT = "4";
+    public static final String NONE = "1";
+    public static final String CASH_BASED = "2";
+    public static final String ACCRUAL_PERIODIC = "3";
+    public static final String ACCRUAL_UPFRONT = "4";
 
     public static final String INTEREST_APPLICABLE_STRATEGY_REST_DATE = "2";
     public static final String INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE 
= "1";
@@ -157,6 +159,7 @@ public class LoanProductTestBuilder {
     private Integer repaymentStartDateType = null;
     private String loanScheduleType = LoanScheduleType.CUMULATIVE.name();
     private String loanScheduleProcessingType = 
LoanScheduleProcessingType.HORIZONTAL.name();
+    private FullAccountingConfig fullAccountingConfig;
 
     public String build() {
         final HashMap<String, Object> map = build(null, null);
@@ -231,7 +234,9 @@ public class LoanProductTestBuilder {
             map.put("outstandingLoanBalance", this.outstandingLoanBalance);
         }
 
-        if (this.accountingRule.equals(ACCRUAL_UPFRONT) || 
this.accountingRule.equals(ACCRUAL_PERIODIC)) {
+        if (this.fullAccountingConfig != null) {
+            map.putAll(this.fullAccountingConfig.toMap());
+        } else if (this.accountingRule.equals(ACCRUAL_UPFRONT) || 
this.accountingRule.equals(ACCRUAL_PERIODIC)) {
             
map.putAll(getAccountMappingForAccrualBased(this.feeAndPenaltyAssetAccount));
         } else if (this.accountingRule.equals(CASH_BASED)) {
             map.putAll(getAccountMappingForCashBased());
@@ -487,6 +492,13 @@ public class LoanProductTestBuilder {
         return this;
     }
 
+    public LoanProductTestBuilder withFullAccountingConfig(String 
accountingRule, FullAccountingConfig fullAccountingConfig) {
+        this.accountingRule = accountingRule;
+        this.fullAccountingConfig = fullAccountingConfig;
+        this.accountList = null;
+        return this;
+    }
+
     private Map<String, String> getAccountMappingForCashBased() {
         final Map<String, String> map = new HashMap<>();
         for (int i = 0; i < this.accountList.length; i++) {
@@ -768,4 +780,78 @@ public class LoanProductTestBuilder {
         return transactionProcessingStrategyCode;
     }
 
+    @Builder
+    public static class FullAccountingConfig {
+
+        private final Long fundSourceAccountId;
+        private final Long loanPortfolioAccountId;
+        private final Long transfersInSuspenseAccountId;
+        private final Long interestOnLoanAccountId;
+        private final Long incomeFromFeeAccountId;
+        private final Long incomeFromPenaltyAccountId;
+        private final Long incomeFromRecoveryAccountId;
+        private final Long writeOffAccountId;
+        private final Long overpaymentLiabilityAccountId;
+        private final Long receivableInterestAccountId;
+        private final Long receivableFeeAccountId;
+        private final Long receivablePenaltyAccountId;
+        private final Long goodwillCreditAccountId;
+        private final Long incomeFromGoodwillCreditInterestAccountId;
+        private final Long incomeFromGoodwillCreditFeesAccountId;
+        private final Long incomeFromGoodwillCreditPenaltyAccountId;
+        private final Long incomeFromChargeOffInterestAccountId;
+        private final Long incomeFromChargeOffFeesAccountId;
+        private final Long chargeOffExpenseAccountId;
+        private final Long chargeOffFraudExpenseAccountId;
+        private final Long incomeFromChargeOffPenaltyAccountId;
+        private final Long accountingRule;
+
+        public Map<String, String> toMap() {
+            Map<String, String> map = new HashMap<>();
+            Optional.ofNullable(fundSourceAccountId)
+                    .ifPresent(fundSourceAccountId -> 
map.put("fundSourceAccountId", Long.toString(fundSourceAccountId)));
+            Optional.ofNullable(loanPortfolioAccountId)
+                    .ifPresent(loanPortfolioAccountId -> 
map.put("loanPortfolioAccountId", Long.toString(loanPortfolioAccountId)));
+            Optional.ofNullable(transfersInSuspenseAccountId).ifPresent(
+                    transfersInSuspenseAccountId -> 
map.put("transfersInSuspenseAccountId", 
Long.toString(transfersInSuspenseAccountId)));
+            Optional.ofNullable(interestOnLoanAccountId)
+                    .ifPresent(interestOnLoanAccountId -> 
map.put("interestOnLoanAccountId", Long.toString(interestOnLoanAccountId)));
+            Optional.ofNullable(incomeFromFeeAccountId)
+                    .ifPresent(incomeFromFeeAccountId -> 
map.put("incomeFromFeeAccountId", Long.toString(incomeFromFeeAccountId)));
+            Optional.ofNullable(incomeFromPenaltyAccountId).ifPresent(
+                    incomeFromPenaltyAccountId -> 
map.put("incomeFromPenaltyAccountId", 
Long.toString(incomeFromPenaltyAccountId)));
+            Optional.ofNullable(incomeFromRecoveryAccountId).ifPresent(
+                    incomeFromRecoveryAccountId -> 
map.put("incomeFromRecoveryAccountId", 
Long.toString(incomeFromRecoveryAccountId)));
+            Optional.ofNullable(writeOffAccountId)
+                    .ifPresent(writeOffAccountId -> 
map.put("writeOffAccountId", Long.toString(writeOffAccountId)));
+            
Optional.ofNullable(overpaymentLiabilityAccountId).ifPresent(overpaymentLiabilityAccountId
 -> map
+                    .put("overpaymentLiabilityAccountId", 
Long.toString(overpaymentLiabilityAccountId)));
+            Optional.ofNullable(receivableInterestAccountId).ifPresent(
+                    receivableInterestAccountId -> 
map.put("receivableInterestAccountId", 
Long.toString(receivableInterestAccountId)));
+            Optional.ofNullable(receivableFeeAccountId)
+                    .ifPresent(receivableFeeAccountId -> 
map.put("receivableFeeAccountId", Long.toString(receivableFeeAccountId)));
+            Optional.ofNullable(receivablePenaltyAccountId).ifPresent(
+                    receivablePenaltyAccountId -> 
map.put("receivablePenaltyAccountId", 
Long.toString(receivablePenaltyAccountId)));
+            Optional.ofNullable(goodwillCreditAccountId)
+                    .ifPresent(goodwillCreditAccountId -> 
map.put("goodwillCreditAccountId", Long.toString(goodwillCreditAccountId)));
+            
Optional.ofNullable(incomeFromGoodwillCreditInterestAccountId).ifPresent(incomeFromGoodwillCreditInterestAccountId
 -> map
+                    .put("incomeFromGoodwillCreditInterestAccountId", 
Long.toString(incomeFromGoodwillCreditInterestAccountId)));
+            
Optional.ofNullable(incomeFromGoodwillCreditFeesAccountId).ifPresent(incomeFromGoodwillCreditFeesAccountId
 -> map
+                    .put("incomeFromGoodwillCreditFeesAccountId", 
Long.toString(incomeFromGoodwillCreditFeesAccountId)));
+            
Optional.ofNullable(incomeFromGoodwillCreditPenaltyAccountId).ifPresent(incomeFromGoodwillCreditPenaltyAccountId
 -> map
+                    .put("incomeFromGoodwillCreditPenaltyAccountId", 
Long.toString(incomeFromGoodwillCreditPenaltyAccountId)));
+            
Optional.ofNullable(incomeFromChargeOffInterestAccountId).ifPresent(incomeFromChargeOffInterestAccountId
 -> map
+                    .put("incomeFromChargeOffInterestAccountId", 
Long.toString(incomeFromChargeOffInterestAccountId)));
+            
Optional.ofNullable(incomeFromChargeOffFeesAccountId).ifPresent(incomeFromChargeOffFeesAccountId
 -> map
+                    .put("incomeFromChargeOffFeesAccountId", 
Long.toString(incomeFromChargeOffFeesAccountId)));
+            Optional.ofNullable(chargeOffExpenseAccountId)
+                    .ifPresent(chargeOffExpenseAccountId -> 
map.put("chargeOffExpenseAccountId", Long.toString(chargeOffExpenseAccountId)));
+            
Optional.ofNullable(chargeOffFraudExpenseAccountId).ifPresent(chargeOffFraudExpenseAccountId
 -> map
+                    .put("chargeOffFraudExpenseAccountId", 
Long.toString(chargeOffFraudExpenseAccountId)));
+            
Optional.ofNullable(incomeFromChargeOffPenaltyAccountId).ifPresent(incomeFromChargeOffPenaltyAccountId
 -> map
+                    .put("incomeFromChargeOffPenaltyAccountId", 
Long.toString(incomeFromChargeOffPenaltyAccountId)));
+            return map;
+        }
+    }
+
 }

Reply via email to