You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ad...@apache.org on 2023/02/07 09:21:58 UTC

[fineract] branch develop updated: FINERACT-1839 Accounting for CBR Reversal - [x] Accrual and Cash Processor support - [x] Integration test - [x] Sonarlint code smell fix

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

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


The following commit(s) were added to refs/heads/develop by this push:
     new 3d885495e FINERACT-1839 Accounting for CBR Reversal - [x] Accrual and Cash Processor support - [x] Integration test - [x] Sonarlint code smell fix
3d885495e is described below

commit 3d885495e21308b922bab852aedea274c791ef83
Author: Janos Haber <ja...@finesolution.hu>
AuthorDate: Mon Feb 6 16:53:30 2023 +0100

    FINERACT-1839 Accounting for CBR Reversal
    - [x] Accrual and Cash Processor support
    - [x] Integration test
    - [x] Sonarlint code smell fix
---
 .../service/AccountingProcessorHelper.java         | 24 +++++++
 .../AccrualBasedAccountingProcessorForLoan.java    | 75 +++++++++++++---------
 .../CashBasedAccountingProcessorForLoan.java       | 68 ++++++++++++--------
 .../journalentry/service/JournalAmountHolder.java  | 33 ++++++++++
 .../ClientLoanIntegrationTest.java                 | 33 ++++++++++
 5 files changed, 174 insertions(+), 59 deletions(-)

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 4d8e854de..1f7e8b656 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
@@ -453,6 +453,30 @@ public class AccountingProcessorHelper {
                 transactionId, transactionDate, amount);
     }
 
+    public void createSplitJournalEntriesAndReversalsForLoan(Office office, String currencyCode,
+            List<JournalAmountHolder> splitAccountsHolder, JournalAmountHolder totalAccountHolder, Long loanProductId, Long paymentTypeId,
+            Long loanId, String transactionId, LocalDate transactionDate, Boolean isReversal) {
+        splitAccountsHolder.forEach(journalItemHolder -> {
+            final GLAccount account = getLinkedGLAccountForLoanProduct(loanProductId, journalItemHolder.getAccountType(), paymentTypeId);
+            if (isReversal) {
+                createCreditJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate,
+                        journalItemHolder.getAmount());
+            } else {
+                createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate,
+                        journalItemHolder.getAmount());
+            }
+
+        });
+        final GLAccount totalAccount = getLinkedGLAccountForLoanProduct(loanProductId, totalAccountHolder.getAccountType(), paymentTypeId);
+        if (isReversal) {
+            createDebitJournalEntryForLoan(office, currencyCode, totalAccount, loanId, transactionId, transactionDate,
+                    totalAccountHolder.getAmount());
+        } else {
+            createCreditJournalEntryForLoan(office, currencyCode, totalAccount, loanId, transactionId, transactionDate,
+                    totalAccountHolder.getAmount());
+        }
+    }
+
     public void createCreditJournalEntryOrReversalForLoan(final Office office, final String currencyCode,
             final CashAccountsForLoan accountMappingType, final Long loanProductId, final Long paymentTypeId, final Long loanId,
             final String transactionId, final LocalDate transactionDate, final BigDecimal amount, final Boolean isReversal) {
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 e75944f68..f99ed0df5 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
@@ -129,7 +129,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
         Map<GLAccount, BigDecimal> accountMap = new HashMap<>();
 
         // handle principal payment (and reversals)
-        if (principalAmount != null && !(principalAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(principalAmount);
             GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
                     AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(), paymentTypeId);
@@ -137,7 +137,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
         }
 
         // handle interest payment (and reversals)
-        if (interestAmount != null && !(interestAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(interestAmount);
             GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
                     AccrualAccountsForLoan.INTEREST_RECEIVABLE.getValue(), paymentTypeId);
@@ -150,7 +150,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
         }
 
         // handle fees payment (and reversals)
-        if (feesAmount != null && !(feesAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(feesAmount);
             GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
                     AccrualAccountsForLoan.FEES_RECEIVABLE.getValue(), paymentTypeId);
@@ -163,7 +163,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
         }
 
         // handle penalties payment (and reversals)
-        if (penaltiesAmount != null && !(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
             GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
                     AccrualAccountsForLoan.PENALTIES_RECEIVABLE.getValue(), paymentTypeId);
@@ -176,7 +176,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
         }
 
         // handle overpayment
-        if (overPaymentAmount != null && !(overPaymentAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (overPaymentAmount != null && overPaymentAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(overPaymentAmount);
             GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
                     paymentTypeId);
@@ -193,7 +193,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
                     entry.getValue(), isReversal, entry.getKey());
         }
 
-        if (!(totalDebitAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (totalDebitAmount.compareTo(BigDecimal.ZERO) > 0) {
             Long chargeId = loanTransactionDTO.getLoanChargeData().getChargeId();
             Integer accountMappingTypeId;
             if (loanTransactionDTO.getLoanChargeData().isPenalty()) {
@@ -327,7 +327,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
         Map<GLAccount, BigDecimal> accountMap = new HashMap<>();
 
         // handle principal payment or writeOff (and reversals)
-        if (principalAmount != null && !(principalAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(principalAmount);
             GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
                     AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(), paymentTypeId);
@@ -335,7 +335,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
         }
 
         // handle interest payment of writeOff (and reversals)
-        if (interestAmount != null && !(interestAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(interestAmount);
             GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
                     AccrualAccountsForLoan.INTEREST_RECEIVABLE.getValue(), paymentTypeId);
@@ -348,7 +348,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
         }
 
         // handle fees payment of writeOff (and reversals)
-        if (feesAmount != null && !(feesAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
 
             totalDebitAmount = totalDebitAmount.add(feesAmount);
 
@@ -369,7 +369,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
         }
 
         // handle penalties payment of writeOff (and reversals)
-        if (penaltiesAmount != null && !(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
             if (isIncomeFromFee) {
                 GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
@@ -392,7 +392,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
             }
         }
 
-        if (overPaymentAmount != null && !(overPaymentAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (overPaymentAmount != null && overPaymentAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(overPaymentAmount);
             GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
                     paymentTypeId);
@@ -412,7 +412,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
         /**
          * Single DEBIT transaction for write-offs or Repayments (and their reversals)
          ***/
-        if (!(totalDebitAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (totalDebitAmount.compareTo(BigDecimal.ZERO) > 0) {
             if (writeOff) {
                 this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode,
                         AccrualAccountsForLoan.LOSSES_WRITTEN_OFF.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
@@ -444,13 +444,11 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
          * Charge Refunds (and their reversals) have an extra refund related pair of journal entries in addition to
          * those related to the repayment above
          ***/
-        if (!(totalDebitAmount.compareTo(BigDecimal.ZERO) == 0)) {
-            if (loanTransactionDTO.getTransactionType().isChargeRefund()) {
-                Integer incomeAccount = this.helper.getValueForFeeOrPenaltyIncomeAccount(loanTransactionDTO.getChargeRefundChargeType());
-                this.helper.createJournalEntriesAndReversalsForLoan(office, currencyCode, incomeAccount,
-                        AccrualAccountsForLoan.FUND_SOURCE.getValue(), loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
-                        totalDebitAmount, isReversal);
-            }
+        if (totalDebitAmount.compareTo(BigDecimal.ZERO) > 0 && loanTransactionDTO.getTransactionType().isChargeRefund()) {
+            Integer incomeAccount = this.helper.getValueForFeeOrPenaltyIncomeAccount(loanTransactionDTO.getChargeRefundChargeType());
+            this.helper.createJournalEntriesAndReversalsForLoan(office, currencyCode, incomeAccount,
+                    AccrualAccountsForLoan.FUND_SOURCE.getValue(), loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
+                    totalDebitAmount, isReversal);
         }
     }
 
@@ -510,19 +508,19 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
         final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
 
         // create journal entries for recognizing interest (or reversal)
-        if (interestAmount != null && !(interestAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
             this.helper.createJournalEntriesAndReversalsForLoan(office, currencyCode, AccrualAccountsForLoan.INTEREST_RECEIVABLE.getValue(),
                     AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
                     transactionDate, interestAmount, isReversed);
         }
         // create journal entries for the fees application (or reversal)
-        if (feesAmount != null && !(feesAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
             this.helper.createJournalEntriesAndReversalsForLoanCharges(office, currencyCode,
                     AccrualAccountsForLoan.FEES_RECEIVABLE.getValue(), AccrualAccountsForLoan.INCOME_FROM_FEES.getValue(), loanProductId,
                     loanId, transactionId, transactionDate, feesAmount, isReversed, loanTransactionDTO.getFeePayments());
         }
         // create journal entries for the penalties application (or reversal)
-        if (penaltiesAmount != null && !(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
 
             this.helper.createJournalEntriesAndReversalsForLoanCharges(office, currencyCode,
                     AccrualAccountsForLoan.PENALTIES_RECEIVABLE.getValue(), AccrualAccountsForLoan.INCOME_FROM_PENALTIES.getValue(),
@@ -565,13 +563,28 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
         // transaction properties
         final String transactionId = loanTransactionDTO.getTransactionId();
         final LocalDate transactionDate = loanTransactionDTO.getTransactionDate();
-        final BigDecimal refundAmount = loanTransactionDTO.getAmount();
         final boolean isReversal = loanTransactionDTO.isReversed();
         final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
 
-        this.helper.createJournalEntriesAndReversalsForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
-                AccrualAccountsForLoan.FUND_SOURCE.getValue(), loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
-                refundAmount, isReversal);
+        BigDecimal overpaymentAmount = loanTransactionDTO.getOverPayment();
+        BigDecimal principalAmount = loanTransactionDTO.getPrincipal();
+
+        BigDecimal totalAmount = BigDecimal.ZERO;
+        List<JournalAmountHolder> journalAmountHolders = new ArrayList<>();
+
+        if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
+            totalAmount = totalAmount.add(principalAmount);
+            journalAmountHolders.add(new JournalAmountHolder(AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(), principalAmount));
+        }
+        if (overpaymentAmount != null && overpaymentAmount.compareTo(BigDecimal.ZERO) > 0) {
+            totalAmount = totalAmount.add(overpaymentAmount);
+            journalAmountHolders.add(new JournalAmountHolder(AccrualAccountsForLoan.OVERPAYMENT.getValue(), overpaymentAmount));
+        }
+
+        JournalAmountHolder totalAmountHolder = new JournalAmountHolder(AccrualAccountsForLoan.FUND_SOURCE.getValue(), totalAmount);
+        helper.createSplitJournalEntriesAndReversalsForLoan(office, currencyCode, journalAmountHolders, totalAmountHolder, loanProductId,
+                paymentTypeId, loanId, transactionId, transactionDate, isReversal);
+
     }
 
     private void createJournalEntriesForRefundForActiveLoan(LoanDTO loanDTO, LoanTransactionDTO loanTransactionDTO, Office office) {
@@ -594,19 +607,19 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
 
         BigDecimal totalDebitAmount = new BigDecimal(0);
 
-        if (principalAmount != null && !(principalAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(principalAmount);
             this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, AccrualAccountsForLoan.LOAN_PORTFOLIO,
                     loanProductId, paymentTypeId, loanId, transactionId, transactionDate, principalAmount, !isReversal);
         }
 
-        if (interestAmount != null && !(interestAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(interestAmount);
             this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, AccrualAccountsForLoan.INTEREST_ON_LOANS,
                     loanProductId, paymentTypeId, loanId, transactionId, transactionDate, interestAmount, !isReversal);
         }
 
-        if (feesAmount != null && !(feesAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(feesAmount);
 
             List<ChargePaymentDTO> chargePaymentDTOs = new ArrayList<>();
@@ -622,7 +635,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
                     !isReversal, chargePaymentDTOs);
         }
 
-        if (penaltiesAmount != null && !(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
             List<ChargePaymentDTO> chargePaymentDTOs = new ArrayList<>();
 
@@ -638,7 +651,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
                     penaltiesAmount, !isReversal, chargePaymentDTOs);
         }
 
-        if (overPaymentAmount != null && !(overPaymentAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (overPaymentAmount != null && overPaymentAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(overPaymentAmount);
             this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT, loanProductId,
                     paymentTypeId, loanId, transactionId, transactionDate, overPaymentAmount, !isReversal);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForLoan.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForLoan.java
index 2e9589496..e4f1aa592 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForLoan.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForLoan.java
@@ -92,7 +92,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
              **/
             else if (loanTransactionDTO.getTransactionType().isWriteOff()) {
                 final BigDecimal principalAmount = loanTransactionDTO.getPrincipal();
-                if (principalAmount != null && !(principalAmount.compareTo(BigDecimal.ZERO) == 0)) {
+                if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
                     this.helper.createJournalEntriesAndReversalsForLoan(office, currencyCode,
                             CashAccountsForLoan.LOSSES_WRITTEN_OFF.getValue(), CashAccountsForLoan.LOAN_PORTFOLIO.getValue(), loanProductId,
                             paymentTypeId, loanId, transactionId, transactionDate, principalAmount, loanTransactionDTO.isReversed());
@@ -140,7 +140,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
         Map<GLAccount, BigDecimal> accountMap = new HashMap<>();
 
         // handle principal payment (and reversals)
-        if (principalAmount != null && !(principalAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(principalAmount);
             GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
                     AccountingConstants.CashAccountsForLoan.LOAN_PORTFOLIO.getValue(), paymentTypeId);
@@ -148,7 +148,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
         }
 
         // handle interest payment (and reversals)
-        if (interestAmount != null && !(interestAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(interestAmount);
             GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
                     AccountingConstants.CashAccountsForLoan.INTEREST_ON_LOANS.getValue(), paymentTypeId);
@@ -161,7 +161,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
         }
 
         // handle fees payment (and reversals)
-        if (feesAmount != null && !(feesAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(feesAmount);
             GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
                     AccountingConstants.CashAccountsForLoan.INCOME_FROM_FEES.getValue(), paymentTypeId);
@@ -174,7 +174,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
         }
 
         // handle penalties payment (and reversals)
-        if (penaltiesAmount != null && !(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
             GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
                     CashAccountsForLoan.INCOME_FROM_PENALTIES.getValue(), paymentTypeId);
@@ -187,7 +187,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
         }
 
         // handle overpayment
-        if (overPaymentAmount != null && !(overPaymentAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (overPaymentAmount != null && overPaymentAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(overPaymentAmount);
             GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
                     AccountingConstants.CashAccountsForLoan.OVERPAYMENT.getValue(), paymentTypeId);
@@ -204,7 +204,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
                     entry.getValue(), isReversal, entry.getKey());
         }
 
-        if (!(totalDebitAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (totalDebitAmount.compareTo(BigDecimal.ZERO) > 0) {
             Long chargeId = loanTransactionDTO.getLoanChargeData().getChargeId();
             Integer accountMappingTypeId;
             if (loanTransactionDTO.getLoanChargeData().isPenalty()) {
@@ -342,33 +342,33 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
 
         BigDecimal totalDebitAmount = new BigDecimal(0);
 
-        if (principalAmount != null && !(principalAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(principalAmount);
             this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, CashAccountsForLoan.LOAN_PORTFOLIO, loanProductId,
                     paymentTypeId, loanId, transactionId, transactionDate, principalAmount, isReversal);
         }
 
-        if (interestAmount != null && !(interestAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(interestAmount);
             this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, CashAccountsForLoan.INTEREST_ON_LOANS,
                     loanProductId, paymentTypeId, loanId, transactionId, transactionDate, interestAmount, isReversal);
         }
 
-        if (feesAmount != null && !(feesAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(feesAmount);
             this.helper.createCreditJournalEntryOrReversalForLoanCharges(office, currencyCode,
                     CashAccountsForLoan.INCOME_FROM_FEES.getValue(), loanProductId, loanId, transactionId, transactionDate, feesAmount,
                     isReversal, loanTransactionDTO.getFeePayments());
         }
 
-        if (penaltiesAmount != null && !(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
             this.helper.createCreditJournalEntryOrReversalForLoanCharges(office, currencyCode,
                     CashAccountsForLoan.INCOME_FROM_PENALTIES.getValue(), loanProductId, loanId, transactionId, transactionDate,
                     penaltiesAmount, isReversal, loanTransactionDTO.getPenaltyPayments());
         }
 
-        if (overPaymentAmount != null && !(overPaymentAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (overPaymentAmount != null && overPaymentAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(overPaymentAmount);
             this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, CashAccountsForLoan.OVERPAYMENT, loanProductId,
                     paymentTypeId, loanId, transactionId, transactionDate, overPaymentAmount, isReversal);
@@ -396,13 +396,11 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
          * Charge Refunds (and their reversals) have an extra refund related pair of journal entries in addition to
          * those related to the repayment above
          ***/
-        if (!(totalDebitAmount.compareTo(BigDecimal.ZERO) == 0)) {
-            if (loanTransactionDTO.getTransactionType().isChargeRefund()) {
-                Integer incomeAccount = this.helper.getValueForFeeOrPenaltyIncomeAccount(loanTransactionDTO.getChargeRefundChargeType());
-                this.helper.createJournalEntriesAndReversalsForLoan(office, currencyCode, incomeAccount,
-                        CashAccountsForLoan.FUND_SOURCE.getValue(), loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
-                        totalDebitAmount, isReversal);
-            }
+        if (totalDebitAmount.compareTo(BigDecimal.ZERO) > 0 && loanTransactionDTO.getTransactionType().isChargeRefund()) {
+            Integer incomeAccount = this.helper.getValueForFeeOrPenaltyIncomeAccount(loanTransactionDTO.getChargeRefundChargeType());
+            this.helper.createJournalEntriesAndReversalsForLoan(office, currencyCode, incomeAccount,
+                    CashAccountsForLoan.FUND_SOURCE.getValue(), loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
+                    totalDebitAmount, isReversal);
         }
     }
 
@@ -477,13 +475,27 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
         // transaction properties
         final String transactionId = loanTransactionDTO.getTransactionId();
         final LocalDate transactionDate = loanTransactionDTO.getTransactionDate();
-        final BigDecimal refundAmount = loanTransactionDTO.getAmount();
         final boolean isReversal = loanTransactionDTO.isReversed();
         final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
 
-        this.helper.createJournalEntriesAndReversalsForLoan(office, currencyCode, CashAccountsForLoan.OVERPAYMENT.getValue(),
-                CashAccountsForLoan.FUND_SOURCE.getValue(), loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
-                refundAmount, isReversal);
+        BigDecimal overpaymentAmount = loanTransactionDTO.getOverPayment();
+        BigDecimal principalAmount = loanTransactionDTO.getPrincipal();
+
+        BigDecimal totalAmount = BigDecimal.ZERO;
+        List<JournalAmountHolder> journalAmountHolders = new ArrayList<>();
+
+        if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
+            totalAmount = totalAmount.add(principalAmount);
+            journalAmountHolders.add(new JournalAmountHolder(CashAccountsForLoan.LOAN_PORTFOLIO.getValue(), principalAmount));
+        }
+        if (overpaymentAmount != null && overpaymentAmount.compareTo(BigDecimal.ZERO) > 0) {
+            totalAmount = totalAmount.add(overpaymentAmount);
+            journalAmountHolders.add(new JournalAmountHolder(CashAccountsForLoan.OVERPAYMENT.getValue(), overpaymentAmount));
+        }
+
+        JournalAmountHolder totalAmountHolder = new JournalAmountHolder(CashAccountsForLoan.FUND_SOURCE.getValue(), totalAmount);
+        helper.createSplitJournalEntriesAndReversalsForLoan(office, currencyCode, journalAmountHolders, totalAmountHolder, loanProductId,
+                paymentTypeId, loanId, transactionId, transactionDate, isReversal);
     }
 
     private void createJournalEntriesForRefundForActiveLoan(LoanDTO loanDTO, LoanTransactionDTO loanTransactionDTO, Office office) {
@@ -505,19 +517,19 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
 
         BigDecimal totalDebitAmount = new BigDecimal(0);
 
-        if (principalAmount != null && !(principalAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(principalAmount);
             this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, CashAccountsForLoan.LOAN_PORTFOLIO, loanProductId,
                     paymentTypeId, loanId, transactionId, transactionDate, principalAmount, !isReversal);
         }
 
-        if (interestAmount != null && !(interestAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(interestAmount);
             this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, CashAccountsForLoan.INTEREST_ON_LOANS,
                     loanProductId, paymentTypeId, loanId, transactionId, transactionDate, interestAmount, !isReversal);
         }
 
-        if (feesAmount != null && !(feesAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(feesAmount);
 
             List<ChargePaymentDTO> chargePaymentDTOs = new ArrayList<>();
@@ -533,7 +545,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
                     !isReversal, chargePaymentDTOs);
         }
 
-        if (penaltiesAmount != null && !(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
             List<ChargePaymentDTO> chargePaymentDTOs = new ArrayList<>();
 
@@ -549,7 +561,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
                     penaltiesAmount, !isReversal, chargePaymentDTOs);
         }
 
-        if (overPaymentAmount != null && !(overPaymentAmount.compareTo(BigDecimal.ZERO) == 0)) {
+        if (overPaymentAmount != null && overPaymentAmount.compareTo(BigDecimal.ZERO) > 0) {
             totalDebitAmount = totalDebitAmount.add(overPaymentAmount);
             this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, CashAccountsForLoan.OVERPAYMENT, loanProductId,
                     paymentTypeId, loanId, transactionId, transactionDate, overPaymentAmount, !isReversal);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalAmountHolder.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalAmountHolder.java
new file mode 100644
index 000000000..2ec625bbe
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalAmountHolder.java
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.accounting.journalentry.service;
+
+import java.math.BigDecimal;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class JournalAmountHolder {
+
+    private Integer accountType;
+    private BigDecimal amount;
+}
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
index 79adfb007..3aa41f676 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
@@ -53,6 +53,7 @@ import java.util.Set;
 import java.util.UUID;
 import org.apache.fineract.accounting.glaccount.domain.GLAccountType;
 import org.apache.fineract.client.models.BusinessDateRequest;
+import org.apache.fineract.client.models.GetJournalEntriesTransactionIdResponse;
 import org.apache.fineract.client.models.GetLoanTransactionRelation;
 import org.apache.fineract.client.models.GetLoansLoanIdLoanTransactionRelation;
 import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
@@ -60,6 +61,7 @@ import org.apache.fineract.client.models.GetLoansLoanIdResponse;
 import org.apache.fineract.client.models.GetLoansLoanIdSummary;
 import org.apache.fineract.client.models.GetLoansLoanIdTransactions;
 import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse;
+import org.apache.fineract.client.models.JournalEntryTransactionItem;
 import org.apache.fineract.client.models.PostChargesRequest;
 import org.apache.fineract.client.models.PostChargesResponse;
 import org.apache.fineract.client.models.PostClientsResponse;
@@ -7197,6 +7199,18 @@ public class ClientLoanIntegrationTest {
             assertEquals(LocalDate.of(2022, 10, 10), loanDetails.getTransactions().get(3).getDate());
             assertEquals(0.0, loanDetails.getTransactions().get(3).getOutstandingLoanBalance());
 
+            GetJournalEntriesTransactionIdResponse journalEntriesForTransaction = journalEntryHelper
+                    .getJournalEntries("L" + loanDetails.getTransactions().get(3).getId());
+            List<JournalEntryTransactionItem> journalItems = journalEntriesForTransaction.getPageItems();
+            assertEquals(2, journalItems.size());
+            assertEquals(200.0,
+                    journalItems.stream()
+                            .filter(j -> "DEBIT".equalsIgnoreCase(j.getEntryType().getValue())
+                                    && j.getGlAccountId().equals(overpaymentAccount.getAccountID().longValue()))
+                            .findFirst().get().getAmount());
+            assertEquals(200.0, journalItems.stream().filter(j -> "CREDIT".equalsIgnoreCase(j.getEntryType().getValue())
+                    && j.getGlAccountId().equals(assetAccount.getAccountID().longValue())).findFirst().get().getAmount());
+
             this.loanTransactionHelper.reverseLoanTransaction(loanDetails.getId(), loanDetails.getTransactions().get(1).getId(),
                     new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat("dd MMMM yyyy").transactionAmount(0.0)
                             .transactionDate("10 October 2022").locale("en"));
@@ -7232,6 +7246,25 @@ public class ClientLoanIntegrationTest {
             assertEquals(100.0, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPrincipalPaid());
             assertEquals(100.0, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPrincipalOutstanding());
 
+            journalEntriesForTransaction = journalEntryHelper.getJournalEntries("L" + loanDetails.getTransactions().get(3).getId());
+            journalItems = journalEntriesForTransaction.getPageItems();
+            assertEquals(3, journalItems.size());
+            assertEquals(1,
+                    journalItems.stream().filter(item -> item.getAmount() == 200.0d)
+                            .filter(j -> "CREDIT".equalsIgnoreCase(j.getEntryType().getValue())
+                                    && j.getGlAccountId().equals(assetAccount.getAccountID().longValue()))
+                            .count());
+            assertEquals(1,
+                    journalItems.stream().filter(item -> item.getAmount() == 100.0d)
+                            .filter(j -> "DEBIT".equalsIgnoreCase(j.getEntryType().getValue())
+                                    && j.getGlAccountId().equals(overpaymentAccount.getAccountID().longValue()))
+                            .count());
+            assertEquals(1,
+                    journalItems.stream().filter(item -> item.getAmount() == 100.0d)
+                            .filter(j -> "DEBIT".equalsIgnoreCase(j.getEntryType().getValue())
+                                    && j.getGlAccountId().equals(assetAccount.getAccountID().longValue()))
+                            .count());
+
         } finally {
             GlobalConfigurationHelper.updateIsAutomaticExternalIdGenerationEnabled(this.requestSpec, this.responseSpec, false);
             GlobalConfigurationHelper.updateIsBusinessDateEnabled(this.requestSpec, this.responseSpec, false);