You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ad...@apache.org on 2025/04/01 08:01:18 UTC
(fineract) branch develop updated: FINERACT-2210: Incorrect accounting of reversed charge-off transaction.
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 957666df18 FINERACT-2210: Incorrect accounting of reversed charge-off transaction.
957666df18 is described below
commit 957666df1838f0918215223f5810d42fddb7d6f8
Author: mariiaKraievska <ri...@gmail.com>
AuthorDate: Wed Mar 26 10:30:30 2025 +0200
FINERACT-2210: Incorrect accounting of reversed charge-off transaction.
---
.../journalentry/domain/JournalEntry.java | 10 +-
.../test/data/loanproduct/DefaultLoanProduct.java | 1 +
.../test/factory/LoanProductsRequestFactory.java | 122 +++++++++
.../global/LoanProductGlobalInitializerStep.java | 28 ++
.../fineract/test/support/TestContextKey.java | 1 +
.../test/resources/features/LoanChargeOff.feature | 44 ++-
.../service/AccountingProcessorHelper.java | 248 ++++++-----------
.../AccrualBasedAccountingProcessorForLoan.java | 305 ++++++++++-----------
.../CashBasedAccountingProcessorForLoan.java | 267 ++++++++----------
.../service/JournalEntryWritePlatformService.java | 2 +
...EntryWritePlatformServiceJpaRepositoryImpl.java | 22 ++
.../CreateJournalEntriesForChargeOffLoanTest.java | 9 +-
12 files changed, 578 insertions(+), 481 deletions(-)
diff --git a/fineract-accounting/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntry.java b/fineract-accounting/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntry.java
index ec86e22b53..d190e9f18d 100644
--- a/fineract-accounting/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntry.java
+++ b/fineract-accounting/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntry.java
@@ -27,6 +27,7 @@ import jakarta.persistence.Table;
import java.math.BigDecimal;
import java.time.LocalDate;
import lombok.Getter;
+import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.accounting.glaccount.domain.GLAccount;
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
@@ -54,6 +55,7 @@ public class JournalEntry extends AbstractAuditableWithUTCDateTimeCustom<Long> {
@Column(name = "currency_code", length = 3, nullable = false)
private String currencyCode;
+ @Setter
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "reversal_id")
private JournalEntry reversalJournalEntry;
@@ -73,6 +75,7 @@ public class JournalEntry extends AbstractAuditableWithUTCDateTimeCustom<Long> {
@Column(name = "share_transaction_id")
private Long shareTransactionId;
+ @Setter
@Column(name = "reversed", nullable = false)
private boolean reversed = false;
@@ -151,11 +154,4 @@ public class JournalEntry extends AbstractAuditableWithUTCDateTimeCustom<Long> {
return JournalEntryType.CREDIT.getValue().equals(this.type);
}
- public void setReversalJournalEntry(final JournalEntry reversalJournalEntry) {
- this.reversalJournalEntry = reversalJournalEntry;
- }
-
- public void setReversed(final boolean reversed) {
- this.reversed = reversed;
- }
}
diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/DefaultLoanProduct.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/DefaultLoanProduct.java
index b8dde51b8d..d3a6309d8c 100644
--- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/DefaultLoanProduct.java
+++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/DefaultLoanProduct.java
@@ -105,6 +105,7 @@ public enum DefaultLoanProduct implements LoanProduct {
LP2_INTEREST_RECALCULATION_ACCELERATE_MATURITY_CHARGE_OFF_BEHAVIOUR_LAST_INSTALLMENT_STRATEGY, //
LP2_ACCELERATE_MATURITY_CHARGE_OFF_BEHAVIOUR_LAST_INSTALLMENT_STRATEGY, //
LP2_ADV_PYMNT_INTEREST_DAILY_INT_RECALCULATION_ZERO_INT_CHARGE_OFF_INT_RECOGNITION_FROM_DISB_DATE, //
+ LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_DELINQUENT_REASON, //
;
@Override
diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/LoanProductsRequestFactory.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/LoanProductsRequestFactory.java
index 801777b59f..d7df068073 100644
--- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/LoanProductsRequestFactory.java
+++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/LoanProductsRequestFactory.java
@@ -1250,4 +1250,126 @@ public class LoanProductsRequestFactory {
.chargeOffFraudExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT_FRAUD))//
.incomeFromChargeOffPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF));//
}
+
+ public PostLoanProductsRequest defaultLoanProductsRequestLP2ChargeOffReasonToExpenseAccountMappings() {
+ final String name = Utils.randomNameGenerator(NAME_PREFIX_LP2, 4);
+ final String shortName = Utils.randomNameGenerator(SHORT_NAME_PREFIX, 3);
+
+ final List<Integer> principalVariationsForBorrowerCycle = new ArrayList<>();
+ final List<Integer> numberOfRepaymentVariationsForBorrowerCycle = new ArrayList<>();
+ final List<Integer> interestRateVariationsForBorrowerCycle = new ArrayList<>();
+ final List<LoanProductChargeData> charges = new ArrayList<>();
+ final List<LoanProductChargeToGLAccountMapper> penaltyToIncomeAccountMappings = new ArrayList<>();
+ final List<LoanProductChargeToGLAccountMapper> feeToIncomeAccountMappings = new ArrayList<>();
+
+ final List<GetLoanPaymentChannelToFundSourceMappings> paymentChannelToFundSourceMappings = new ArrayList<>();
+ final GetLoanPaymentChannelToFundSourceMappings loanPaymentChannelToFundSourceMappings = new GetLoanPaymentChannelToFundSourceMappings();
+ loanPaymentChannelToFundSourceMappings.fundSourceAccountId(accountTypeResolver.resolve(DefaultAccountType.FUND_RECEIVABLES));
+ loanPaymentChannelToFundSourceMappings.paymentTypeId(paymentTypeResolver.resolve(DefaultPaymentType.MONEY_TRANSFER));
+ paymentChannelToFundSourceMappings.add(loanPaymentChannelToFundSourceMappings);
+
+ final Long chargeOffReasonId = codeHelper.retrieveCodeByName(CHARGE_OFF_REASONS).getId();
+
+ final List<PostChargeOffReasonToExpenseAccountMappings> chargeOffReasonToExpenseAccountMappings = new ArrayList<>();
+ final PostChargeOffReasonToExpenseAccountMappings chargeOffDelinquentReason = new PostChargeOffReasonToExpenseAccountMappings();
+ chargeOffDelinquentReason.chargeOffReasonCodeValueId(codeValueResolver.resolve(chargeOffReasonId, DefaultCodeValue.DELINQUENT));
+ chargeOffDelinquentReason.expenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT_FRAUD));
+ chargeOffReasonToExpenseAccountMappings.add(chargeOffDelinquentReason);
+
+ return new PostLoanProductsRequest()//
+ .name(name)//
+ .shortName(shortName)//
+ .description(DESCRIPTION_LP2)//
+ .enableDownPayment(true)//
+ .enableAutoRepaymentForDownPayment(true)//
+ .disbursedAmountPercentageForDownPayment(new BigDecimal(25))//
+ .fundId(FUND_ID)//
+ .startDate(null)//
+ .closeDate(null)//
+ .includeInBorrowerCycle(false)//
+ .currencyCode(CURRENCY_CODE)//
+ .digitsAfterDecimal(2)//
+ .inMultiplesOf(0)//
+ .installmentAmountInMultiplesOf(1)//
+ .useBorrowerCycle(false)//
+ .minPrincipal(100.0)//
+ .principal(1000.0)//
+ .maxPrincipal(10000.0)//
+ .minNumberOfRepayments(1)//
+ .numberOfRepayments(3)//
+ .maxNumberOfRepayments(30)//
+ .isLinkedToFloatingInterestRates(false)//
+ .minInterestRatePerPeriod((double) 0)//
+ .interestRatePerPeriod((double) 0)//
+ .maxInterestRatePerPeriod((double) 0)//
+ .interestRateFrequencyType(INTEREST_RATE_FREQUENCY_TYPE_MONTH)//
+ .repaymentEvery(15)//
+ .repaymentFrequencyType(REPAYMENT_FREQUENCY_TYPE_DAYS)//
+ .principalVariationsForBorrowerCycle(principalVariationsForBorrowerCycle)//
+ .numberOfRepaymentVariationsForBorrowerCycle(numberOfRepaymentVariationsForBorrowerCycle)//
+ .interestRateVariationsForBorrowerCycle(interestRateVariationsForBorrowerCycle)//
+ .amortizationType(AMORTIZATION_TYPE)//
+ .interestType(INTEREST_TYPE_DECLINING_BALANCE)//
+ .isEqualAmortization(false)//
+ .interestCalculationPeriodType(INTEREST_CALCULATION_PERIOD_TYPE_SAME_AS_REPAYMENT)//
+ .transactionProcessingStrategyCode(TRANSACTION_PROCESSING_STRATEGY_CODE)//
+ .daysInYearType(DAYS_IN_YEAR_TYPE)//
+ .daysInMonthType(DAYS_IN_MONTH_TYPE)//
+ .canDefineInstallmentAmount(true)//
+ .graceOnArrearsAgeing(3)//
+ .overdueDaysForNPA(179)//
+ .accountMovesOutOfNPAOnlyOnArrearsCompletion(false)//
+ .principalThresholdForLastInstallment(50)//
+ .allowVariableInstallments(false)//
+ .canUseForTopup(false)//
+ .isInterestRecalculationEnabled(false)//
+ .holdGuaranteeFunds(false)//
+ .multiDisburseLoan(true)//
+ .allowAttributeOverrides(new AllowAttributeOverrides()//
+ .amortizationType(true)//
+ .interestType(true)//
+ .transactionProcessingStrategyCode(true)//
+ .interestCalculationPeriodType(true)//
+ .inArrearsTolerance(true)//
+ .repaymentEvery(true)//
+ .graceOnPrincipalAndInterestPayment(true)//
+ .graceOnArrearsAgeing(true))//
+ .allowPartialPeriodInterestCalcualtion(true)//
+ .maxTrancheCount(10)//
+ .outstandingLoanBalance(10000.0)//
+ .charges(charges)//
+ .accountingRule(LOAN_ACCOUNTING_RULE)//
+ .fundSourceAccountId(accountTypeResolver.resolve(DefaultAccountType.SUSPENSE_CLEARING_ACCOUNT))//
+ .loanPortfolioAccountId(accountTypeResolver.resolve(DefaultAccountType.LOANS_RECEIVABLE))//
+ .transfersInSuspenseAccountId(accountTypeResolver.resolve(DefaultAccountType.TRANSFER_IN_SUSPENSE_ACCOUNT))//
+ .interestOnLoanAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME))//
+ .incomeFromFeeAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_INCOME))//
+ .incomeFromPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_INCOME))//
+ .incomeFromRecoveryAccountId(accountTypeResolver.resolve(DefaultAccountType.RECOVERIES))//
+ .writeOffAccountId(accountTypeResolver.resolve(DefaultAccountType.WRITTEN_OFF))//
+ .overpaymentLiabilityAccountId(accountTypeResolver.resolve(DefaultAccountType.OVERPAYMENT_ACCOUNT))//
+ .receivableInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))//
+ .receivableFeeAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))//
+ .receivablePenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))//
+ .dateFormat(DATE_FORMAT)//
+ .locale(LOCALE_EN)//
+ .disallowExpectedDisbursements(true)//
+ .allowApprovedDisbursedAmountsOverApplied(true)//
+ .overAppliedCalculationType(OVER_APPLIED_CALCULATION_TYPE)//
+ .overAppliedNumber(OVER_APPLIED_NUMBER)//
+ .delinquencyBucketId(DELINQUENCY_BUCKET_ID.longValue())//
+ .goodwillCreditAccountId(accountTypeResolver.resolve(DefaultAccountType.GOODWILL_EXPENSE_ACCOUNT))//
+ .incomeFromGoodwillCreditInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME_CHARGE_OFF))//
+ .incomeFromGoodwillCreditFeesAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))//
+ .incomeFromGoodwillCreditPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))//
+ .paymentChannelToFundSourceMappings(paymentChannelToFundSourceMappings)//
+ .penaltyToIncomeAccountMappings(penaltyToIncomeAccountMappings)//
+ .feeToIncomeAccountMappings(feeToIncomeAccountMappings)//
+ .incomeFromChargeOffInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME_CHARGE_OFF))//
+ .incomeFromChargeOffFeesAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))//
+ .chargeOffExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT))//
+ .chargeOffFraudExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT))//
+ .chargeOffReasonToExpenseAccountMappings(chargeOffReasonToExpenseAccountMappings)//
+ .incomeFromChargeOffPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF));//
+ }
}
diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
index c7f3c2a402..c995b79759 100644
--- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
+++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
@@ -1975,6 +1975,34 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
.createLoanProduct(loanProductsRequestInterest36030DecliningPeriodDailyIntRecalc).execute();
TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP1_INTEREST_360_30__DECLINING_PERIOD_DAILY_INT_RECALC,
responseInterest36030DecliningPeriodDailyIntRecalc);
+
+ // LP2 + zero-interest chargeOff behaviour + progressive loan schedule + horizontal + delinquent charge-off
+ // reason to GL account mapping
+ // (LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_DELINQUENT_REASON)
+ final String name83 = DefaultLoanProduct.LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_DELINQUENT_REASON.getName();
+
+ final PostLoanProductsRequest loanProductsRequestAdvZeroInterestChargeOffProgressiveDelinquentReason = loanProductsRequestFactory
+ .defaultLoanProductsRequestLP2ChargeOffReasonToExpenseAccountMappings()//
+ .name(name83)//
+ .enableDownPayment(false)//
+ .enableAutoRepaymentForDownPayment(null)//
+ .disbursedAmountPercentageForDownPayment(null)//
+ .transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION.getValue())//
+ .loanScheduleType("PROGRESSIVE") //
+ .loanScheduleProcessingType("HORIZONTAL")//
+ .interestRateFrequencyType(3)//
+ .maxInterestRatePerPeriod(10.0)//
+ .paymentAllocation(List.of(//
+ createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), //
+ createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
+ createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
+ createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")))//
+ .chargeOffBehaviour("ZERO_INTEREST");//
+ final Response<PostLoanProductsResponse> responseLoanProductsRequestAdvZeroInterestChargeOffProgressiveDelinquentReason = loanProductsApi
+ .createLoanProduct(loanProductsRequestAdvZeroInterestChargeOffProgressiveDelinquentReason).execute();
+ TestContext.INSTANCE.set(
+ TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_DELINQUENT_REASON,
+ responseLoanProductsRequestAdvZeroInterestChargeOffProgressiveDelinquentReason);
}
public static AdvancedPaymentData createPaymentAllocation(String transactionType, String futureInstallmentAllocationRule,
diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java
index 51b118d425..418d3be8d4 100644
--- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java
+++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java
@@ -116,6 +116,7 @@ public abstract class TestContextKey {
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyInterestRecalculationZeroInterestChargeOff";
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR = "loanProductCreateResponseLP2AdvancedPaymentZeroInterestChargeOffBehaviour";
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF = "loanProductCreateResponseLP2AdvancedPaymentZeroInterestChargeOff";
+ public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_DELINQUENT_REASON = "loanProductCreateResponseLP2AdvancedPaymentZeroInterestChargeOffDelinquentReason";
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_ALLOW_PARTIAL_PERIOD = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationDailyAllowPartialPeriod";
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_ACCRUAL_ACTIVITY_POSTING = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationDailyAccrualActivityPosting";
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_CHARGEBACK_INTEREST_FEE_PRINCIPAL = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030ChargebackInterestFeePrincipal";
diff --git a/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff.feature b/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff.feature
index 9de439ff74..bbe446cd2c 100644
--- a/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff.feature
+++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff.feature
@@ -7541,4 +7541,46 @@ Feature: Charge-off
| 20 January 2024 | Accrual Adjustment | 12.58 | 0.0 | 12.58 | 0.0 | 0.0 | 0.0 | false | false |
| 20 January 2024 | Charge-off | 790.71 | 757.67 | 33.04 | 0.0 | 0.0 | 0.0 | false | false |
Then Loan marked as charged-off on "20 January 2024"
- Then LoanAccrualAdjustmentTransactionBusinessEvent is raised on "20 January 2024"
\ No newline at end of file
+ Then LoanAccrualAdjustmentTransactionBusinessEvent is raised on "20 January 2024"
+
+ @TestRailId:C3567
+ Scenario: Charge-off reversal on a fraud loan respects GL mapping based on charge-off reason
+ When Admin sets the business date to "1 January 2024"
+ And Admin creates a client with random data
+ And Admin creates a fully customized loan with the following data:
+ | LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
+ | LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_DELINQUENT_REASON | 01 January 2024 | 100 | 7 | DECLINING_BALANCE | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
+ Then Loan Repayment schedule has 6 periods, with the following data for periods:
+ | Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
+ | | | 01 January 2024 | | 100.0 | | | 0.0 | | 0.0 | | | | 0.0 |
+ | 1 | 31 | 01 February 2024 | | 83.59 | 16.41 | 0.59 | 0.0 | 0.0 | 17.0 | 0.0 | 0.0 | 0.0 | 17.0 |
+ | 2 | 29 | 01 March 2024 | | 67.05 | 16.54 | 0.46 | 0.0 | 0.0 | 17.0 | 0.0 | 0.0 | 0.0 | 17.0 |
+ | 3 | 31 | 01 April 2024 | | 50.45 | 16.6 | 0.4 | 0.0 | 0.0 | 17.0 | 0.0 | 0.0 | 0.0 | 17.0 |
+ | 4 | 30 | 01 May 2024 | | 33.74 | 16.71 | 0.29 | 0.0 | 0.0 | 17.0 | 0.0 | 0.0 | 0.0 | 17.0 |
+ | 5 | 31 | 01 June 2024 | | 16.94 | 16.8 | 0.2 | 0.0 | 0.0 | 17.0 | 0.0 | 0.0 | 0.0 | 17.0 |
+ | 6 | 30 | 01 July 2024 | | 0.0 | 16.94 | 0.1 | 0.0 | 0.0 | 17.04 | 0.0 | 0.0 | 0.0 | 17.04 |
+ Then Loan Repayment schedule has the following data in Total row:
+ | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
+ | 100 | 2.04 | 0 | 0 | 102.04 | 0 | 0 | 0 | 102.04 |
+ And Admin successfully approves the loan on "1 January 2024" with "100" amount and expected disbursement date on "1 January 2024"
+ And Admin successfully disburse the loan on "1 January 2024" with "100" EUR transaction amount
+ Then Admin can successfully set Fraud flag to the loan
+ When Admin sets the business date to "03 February 2024"
+ And Admin does charge-off the loan with reason "DELINQUENT" on "03 February 2024"
+ Then Loan Transactions tab has a "CHARGE_OFF" transaction with date "03 February 2024" which has the following Journal entries:
+ | Type | Account code | Account name | Debit | Credit |
+ | ASSET | 112601 | Loans Receivable | | 100.0 |
+ | ASSET | 112603 | Interest/Fee Receivable | | 0.62 |
+ | EXPENSE | 744037 | Credit Loss/Bad Debt-Fraud | 100.0 | |
+ | INCOME | 404001 | Interest Income Charge Off | 0.62 | |
+ Then Admin does a charge-off undo the loan
+ Then Loan Transactions tab has a "CHARGE_OFF" transaction with date "03 February 2024" which has the following Journal entries:
+ | Type | Account code | Account name | Debit | Credit |
+ | ASSET | 112601 | Loans Receivable | | 100.0 |
+ | ASSET | 112601 | Loans Receivable | 100.0 | |
+ | ASSET | 112603 | Interest/Fee Receivable | | 0.62 |
+ | ASSET | 112603 | Interest/Fee Receivable | 0.62 | |
+ | EXPENSE | 744037 | Credit Loss/Bad Debt-Fraud | 100.0 | |
+ | EXPENSE | 744037 | Credit Loss/Bad Debt-Fraud | | 100.0 |
+ | INCOME | 404001 | Interest Income Charge Off | 0.62 | |
+ | INCOME | 404001 | Interest Income Charge Off | | 0.62 |
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 d9ee4a5fb7..c000482be5 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
@@ -68,14 +68,11 @@ import org.apache.fineract.portfolio.PortfolioProductType;
import org.apache.fineract.portfolio.account.PortfolioAccountType;
import org.apache.fineract.portfolio.account.service.AccountTransfersReadPlatformService;
import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
-import org.apache.fineract.portfolio.client.domain.ClientTransaction;
import org.apache.fineract.portfolio.client.domain.ClientTransactionRepository;
import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData;
import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionEnumData;
-import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionEnumData;
-import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction;
import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransactionRepository;
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountTransactionEnumData;
import org.springframework.dao.DataAccessException;
@@ -356,15 +353,12 @@ public class AccountingProcessorHelper {
* transactionDate
* @param totalAmount
* totalAmount
- * @param isReversal
- * isReversal
* @param chargePaymentDTOs
* chargePaymentDTOs
*/
- public void createJournalEntriesAndReversalsForLoanCharges(final Office office, final String currencyCode,
- final Integer accountTypeToBeDebited, final Integer accountTypeToBeCredited, final Long loanProductId, final Long loanId,
- final String transactionId, final LocalDate transactionDate, final BigDecimal totalAmount, final Boolean isReversal,
- final List<ChargePaymentDTO> chargePaymentDTOs) {
+ public void createJournalEntriesForLoanCharges(final Office office, final String currencyCode, final Integer accountTypeToBeDebited,
+ final Integer accountTypeToBeCredited, final Long loanProductId, final Long loanId, final String transactionId,
+ final LocalDate transactionDate, final BigDecimal totalAmount, final List<ChargePaymentDTO> chargePaymentDTOs) {
GLAccount receivableAccount = getLinkedGLAccountForLoanCharges(loanProductId, accountTypeToBeDebited, null);
final Map<GLAccount, BigDecimal> creditDetailsMap = new LinkedHashMap<>();
@@ -387,13 +381,8 @@ public class AccountingProcessorHelper {
final GLAccount account = entry.getKey();
final BigDecimal amount = entry.getValue();
totalCreditedAmount = totalCreditedAmount.add(amount);
- if (isReversal) {
- createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
- createCreditJournalEntryForLoan(office, currencyCode, receivableAccount, loanId, transactionId, transactionDate, amount);
- } else {
- createDebitJournalEntryForLoan(office, currencyCode, receivableAccount, loanId, transactionId, transactionDate, amount);
- createCreditJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
- }
+ createDebitJournalEntryForLoan(office, currencyCode, receivableAccount, loanId, transactionId, transactionDate, amount);
+ createCreditJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
}
if (totalAmount.compareTo(totalCreditedAmount) != 0) {
@@ -453,61 +442,43 @@ public class AccountingProcessorHelper {
* @param transactionId
* @param transactionDate
* @param amount
- * @param isReversal
*/
- public void createJournalEntriesAndReversalsForLoan(final Office office, final String currencyCode,
- final Integer accountTypeToBeDebited, final Integer accountTypeToBeCredited, final Long loanProductId, final Long paymentTypeId,
- final Long loanId, final String transactionId, final LocalDate transactionDate, final BigDecimal amount,
- final Boolean isReversal) {
+ public void createJournalEntriesForLoan(final Office office, final String currencyCode, final Integer accountTypeToBeDebited,
+ final Integer accountTypeToBeCredited, final Long loanProductId, final Long paymentTypeId, final Long loanId,
+ final String transactionId, final LocalDate transactionDate, final BigDecimal amount) {
int accountTypeToDebitId = accountTypeToBeDebited;
int accountTypeToCreditId = accountTypeToBeCredited;
- // reverse debits and credits for reversals
- if (isReversal) {
- accountTypeToDebitId = accountTypeToBeCredited;
- accountTypeToCreditId = accountTypeToBeDebited;
- }
createJournalEntriesForLoan(office, currencyCode, accountTypeToDebitId, accountTypeToCreditId, loanProductId, paymentTypeId, loanId,
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) {
+ public void createSplitJournalEntriesForLoan(Office office, String currencyCode, List<JournalAmountHolder> splitAccountsHolder,
+ JournalAmountHolder totalAccountHolder, Long loanProductId, Long paymentTypeId, Long loanId, String transactionId,
+ LocalDate transactionDate) {
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());
- }
-
+ 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());
- }
+ createCreditJournalEntryForLoan(office, currencyCode, totalAccount, loanId, transactionId, transactionDate,
+ totalAccountHolder.getAmount());
}
- public void createCreditJournalEntryOrReversalForLoan(final Office office, final String currencyCode,
+ public void createCreditJournalEntryForLoan(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) {
+ final String transactionId, final LocalDate transactionDate, final BigDecimal amount) {
final int accountMappingTypeId = accountMappingType.getValue();
- createCreditJournalEntryOrReversalForLoan(office, currencyCode, accountMappingTypeId, loanProductId, paymentTypeId, loanId,
- transactionId, transactionDate, amount, isReversal);
+ createCreditJournalEntryForLoan(office, currencyCode, accountMappingTypeId, loanProductId, paymentTypeId, loanId, transactionId,
+ transactionDate, amount);
}
- public void createCreditJournalEntryOrReversalForLoan(final Office office, final String currencyCode,
+ public void createCreditJournalEntryForLoan(final Office office, final String currencyCode,
final AccrualAccountsForLoan accountMappingType, final Long loanProductId, final Long paymentTypeId, final Long loanId,
- final String transactionId, final LocalDate transactionDate, final BigDecimal amount, final Boolean isReversal) {
+ final String transactionId, final LocalDate transactionDate, final BigDecimal amount) {
final int accountMappingTypeId = accountMappingType.getValue();
- createCreditJournalEntryOrReversalForLoan(office, currencyCode, accountMappingTypeId, loanProductId, paymentTypeId, loanId,
- transactionId, transactionDate, amount, isReversal);
+ createCreditJournalEntryForLoan(office, currencyCode, accountMappingTypeId, loanProductId, paymentTypeId, loanId, transactionId,
+ transactionDate, amount);
}
/**
@@ -635,18 +606,6 @@ public class AccountingProcessorHelper {
}
}
- public void createCashBasedDebitJournalEntriesAndReversalsForSavings(final Office office, final String currencyCode,
- final Long debitAccountId, final Long savingsId, final String transactionId, final LocalDate transactionDate,
- final BigDecimal amount, final Boolean isReversal) {
- // reverse debits and credits for reversals
- final GLAccount debitAccount = getGLAccountById(debitAccountId);
- if (isReversal) {
- createCreditJournalEntryForSavings(office, currencyCode, debitAccount, savingsId, transactionId, transactionDate, amount);
- } else {
- createDebitJournalEntryForSavings(office, currencyCode, debitAccount, savingsId, transactionId, transactionDate, amount);
- }
- }
-
public void createCashBasedCreditJournalEntriesAndReversalsForSavings(final Office office, final String currencyCode,
final Long creditAccountId, final Long savingsId, final String transactionId, final LocalDate transactionDate,
final BigDecimal amount, final Boolean isReversal) {
@@ -685,18 +644,6 @@ public class AccountingProcessorHelper {
}
}
- public void createAccrualBasedDebitJournalEntriesAndReversalsForSavings(final Office office, final String currencyCode,
- final Long debitAccountId, final Long savingsId, final String transactionId, final LocalDate transactionDate,
- final BigDecimal amount, final Boolean isReversal) {
- // reverse debits and credits for reversals
- final GLAccount debitAccount = getGLAccountById(debitAccountId);
- if (isReversal) {
- createCreditJournalEntryForSavings(office, currencyCode, debitAccount, savingsId, transactionId, transactionDate, amount);
- } else {
- createDebitJournalEntryForSavings(office, currencyCode, debitAccount, savingsId, transactionId, transactionDate, amount);
- }
- }
-
public void createAccrualBasedBasedCreditJournalEntriesAndReversalsForSavings(final Office office, final String currencyCode,
final Long creditAccountId, final Long savingsId, final String transactionId, final LocalDate transactionDate,
final BigDecimal amount, final Boolean isReversal) {
@@ -723,80 +670,37 @@ public class AccountingProcessorHelper {
createCreditJournalEntryForSavings(office, currencyCode, creditAccount, savingsId, transactionId, transactionDate, amount);
}
- public void createDebitJournalEntryOrReversalForLoan(final Office office, final String currencyCode, final int accountMappingTypeId,
+ public void createDebitJournalEntryForLoan(final Office office, final String currencyCode, final int accountMappingTypeId,
final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId,
- final LocalDate transactionDate, final BigDecimal amount, final Boolean isReversal) {
+ final LocalDate transactionDate, final BigDecimal amount) {
final GLAccount account = getLinkedGLAccountForLoanProduct(loanProductId, accountMappingTypeId, paymentTypeId);
- if (isReversal) {
- createCreditJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
- } else {
- createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
- }
+ createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
}
- public void createDebitJournalEntryOrReversalForLoan(final Office office, final String currencyCode, final Long loanId,
- final String transactionId, final LocalDate transactionDate, final BigDecimal amount, final Boolean isReversal,
- final GLAccount account) {
- if (isReversal) {
- createCreditJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
- } else {
- createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
- }
+ public void createDebitJournalEntryForLoan(final Office office, final String currencyCode, final Long loanId,
+ final String transactionId, final LocalDate transactionDate, final BigDecimal amount, final GLAccount account) {
+ createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
}
- public void createDebitJournalEntryOrReversalForLoanCharges(final Office office, final String currencyCode,
- final int accountMappingTypeId, final Long loanProductId, final Long chargeId, final Long loanId, final String transactionId,
- final LocalDate transactionDate, final BigDecimal amount, final Boolean isReversal) {
+ public void createDebitJournalEntryForLoanCharges(final Office office, final String currencyCode, final int accountMappingTypeId,
+ final Long loanProductId, final Long chargeId, final Long loanId, final String transactionId, final LocalDate transactionDate,
+ final BigDecimal amount) {
final GLAccount account = getLinkedGLAccountForLoanCharges(loanProductId, accountMappingTypeId, chargeId);
- if (isReversal) {
- createCreditJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
- } else {
- createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
- }
+ createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
}
- public void createCreditJournalEntryOrReversalForLoanCharges(final Office office, final String currencyCode,
- final int accountMappingTypeId, final Long loanProductId, final Long loanId, final String transactionId,
- final LocalDate transactionDate, final BigDecimal totalAmount, final Boolean isReversal,
- final List<ChargePaymentDTO> chargePaymentDTOs) {
- /***
- * Map to track each account and the net credit to be made for a particular account
- ***/
- final Map<GLAccount, BigDecimal> creditDetailsMap = new LinkedHashMap<>();
- for (final ChargePaymentDTO chargePaymentDTO : chargePaymentDTOs) {
- final Long chargeId = chargePaymentDTO.getChargeId();
- final GLAccount chargeSpecificAccount = getLinkedGLAccountForLoanCharges(loanProductId, accountMappingTypeId, chargeId);
- BigDecimal chargeSpecificAmount = chargePaymentDTO.getAmount();
-
- // adjust net credit amount if the account is already present in the
- // map
- if (creditDetailsMap.containsKey(chargeSpecificAccount)) {
- final BigDecimal existingAmount = creditDetailsMap.get(chargeSpecificAccount);
- chargeSpecificAmount = chargeSpecificAmount.add(existingAmount);
- }
- creditDetailsMap.put(chargeSpecificAccount, chargeSpecificAmount);
- }
-
- BigDecimal totalCreditedAmount = BigDecimal.ZERO;
- for (final Map.Entry<GLAccount, BigDecimal> entry : creditDetailsMap.entrySet()) {
- final GLAccount account = entry.getKey();
- final BigDecimal amount = entry.getValue();
- totalCreditedAmount = totalCreditedAmount.add(amount);
- if (isReversal) {
- createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
- } else {
- createCreditJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
- }
- }
+ public void createCreditJournalEntryForLoanCharges(final Office office, final String currencyCode, final int accountMappingTypeId,
+ final Long loanProductId, final Long loanId, final String transactionId, final LocalDate transactionDate,
+ final BigDecimal totalAmount, final List<ChargePaymentDTO> chargePaymentDTOs) {
+ createJournalEntriesForLoanChargesInternal(office, currencyCode, accountMappingTypeId, loanProductId, loanId, transactionId,
+ transactionDate, totalAmount, chargePaymentDTOs, true);
+ }
- // TODO: Vishwas Temporary validation to be removed before moving to
- // release branch
- if (totalAmount.compareTo(totalCreditedAmount) != 0) {
- throw new PlatformDataIntegrityException(
- "Meltdown in advanced accounting...sum of all charges is not equal to the fee charge for a transaction",
- "Meltdown in advanced accounting...sum of all charges is not equal to the fee charge for a transaction",
- totalCreditedAmount, totalAmount);
- }
+ public void createDebitJournalEntryForLoanCharges(final Office office, final String currencyCode, final int accountMappingTypeId,
+ final Long loanProductId, final Long loanId, final String transactionId, final LocalDate transactionDate,
+ final BigDecimal totalAmount, final List<ChargePaymentDTO> chargePaymentDTOs) {
+ createJournalEntriesForLoanChargesInternal(office, currencyCode, accountMappingTypeId, loanProductId, loanId, transactionId,
+ transactionDate, totalAmount, chargePaymentDTOs, false);
}
/**
@@ -899,38 +803,20 @@ public class AccountingProcessorHelper {
}
}
- public LoanTransaction getLoanTransactionById(final Long loanTransactionId) {
- return this.loanTransactionRepository.getReferenceById(loanTransactionId);
- }
-
- public SavingsAccountTransaction getSavingsTransactionById(final Long savingsTransactionId) {
- return this.savingsAccountTransactionRepository.getReferenceById(savingsTransactionId);
- }
-
- public ClientTransaction getClientTransactionById(final Long clientTransactionId) {
- return this.clientTransactionRepository.getReferenceById(clientTransactionId);
- }
-
public Office getOfficeById(final long officeId) {
return this.officeRepository.getReferenceById(officeId);
}
- public void createCreditJournalEntryOrReversalForLoan(final Office office, final String currencyCode, final int accountMappingTypeId,
+ public void createCreditJournalEntryForLoan(final Office office, final String currencyCode, final int accountMappingTypeId,
final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId,
- final LocalDate transactionDate, final BigDecimal amount, final Boolean isReversal) {
+ final LocalDate transactionDate, final BigDecimal amount) {
final GLAccount account = getLinkedGLAccountForLoanProduct(loanProductId, accountMappingTypeId, paymentTypeId);
- createCreditJournalEntryOrReversalForLoan(office, currencyCode, loanId, transactionId, transactionDate, amount, isReversal,
- account);
+ createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate, amount, account);
}
- public void createCreditJournalEntryOrReversalForLoan(final Office office, final String currencyCode, final Long loanId,
- final String transactionId, final LocalDate transactionDate, final BigDecimal amount, final Boolean isReversal,
- final GLAccount account) {
- if (isReversal) {
- createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
- } else {
- createCreditJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
- }
+ public void createCreditJournalEntryForLoan(final Office office, final String currencyCode, final Long loanId,
+ final String transactionId, final LocalDate transactionDate, final BigDecimal amount, final GLAccount account) {
+ createCreditJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
}
private void createCreditJournalEntryForClientPayments(final Office office, final String currencyCode, final GLAccount account,
@@ -1403,4 +1289,38 @@ public class AccountingProcessorHelper {
return savedJournalEntry;
}
+ private void createJournalEntriesForLoanChargesInternal(final Office office, final String currencyCode, final int accountMappingTypeId,
+ final Long loanProductId, final Long loanId, final String transactionId, final LocalDate transactionDate,
+ final BigDecimal totalAmount, final List<ChargePaymentDTO> chargePaymentDTOs, final boolean isCredit) {
+ final Map<GLAccount, BigDecimal> creditDetailsMap = new LinkedHashMap<>();
+
+ for (final ChargePaymentDTO chargePaymentDTO : chargePaymentDTOs) {
+ final Long chargeId = chargePaymentDTO.getChargeId();
+ final GLAccount account = getLinkedGLAccountForLoanCharges(loanProductId, accountMappingTypeId, chargeId);
+ BigDecimal amount = chargePaymentDTO.getAmount();
+
+ creditDetailsMap.merge(account, amount, BigDecimal::add);
+ }
+
+ BigDecimal totalCreditedAmount = BigDecimal.ZERO;
+
+ for (Map.Entry<GLAccount, BigDecimal> entry : creditDetailsMap.entrySet()) {
+ GLAccount account = entry.getKey();
+ BigDecimal amount = entry.getValue();
+ totalCreditedAmount = totalCreditedAmount.add(amount);
+
+ if (isCredit) {
+ createCreditJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
+ } else {
+ createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
+ }
+ }
+
+ if (totalAmount.compareTo(totalCreditedAmount) != 0) {
+ throw new PlatformDataIntegrityException(
+ "Meltdown in advanced accounting...sum of all charges is not equal to the fee charge for a transaction",
+ "Meltdown in advanced accounting...sum of all charges is not equal to the fee charge for a transaction",
+ totalCreditedAmount, totalAmount);
+ }
+ }
}
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 999df7c376..8525540016 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
@@ -46,16 +46,24 @@ import org.springframework.stereotype.Component;
public class AccrualBasedAccountingProcessorForLoan implements AccountingProcessorForLoan {
private final AccountingProcessorHelper helper;
+ private final JournalEntryWritePlatformService journalEntryWritePlatformService;
@Override
public void createJournalEntriesForLoan(final LoanDTO loanDTO) {
- final GLClosure latestGLClosure = this.helper.getLatestClosureByBranch(loanDTO.getOfficeId());
- final Office office = this.helper.getOfficeById(loanDTO.getOfficeId());
+ final Long officeId = loanDTO.getOfficeId();
+ final GLClosure latestGLClosure = this.helper.getLatestClosureByBranch(officeId);
+ final Office office = this.helper.getOfficeById(officeId);
for (final LoanTransactionDTO loanTransactionDTO : loanDTO.getNewLoanTransactions()) {
final LocalDate transactionDate = loanTransactionDTO.getTransactionDate();
this.helper.checkForBranchClosures(latestGLClosure, transactionDate);
final LoanTransactionEnumData transactionType = loanTransactionDTO.getTransactionType();
+ if (loanTransactionDTO.isReversed()) {
+ journalEntryWritePlatformService.createJournalEntryForReversedLoanTransaction(transactionDate,
+ loanTransactionDTO.getTransactionId(), officeId);
+ continue;
+ }
+
// Handle Disbursements
if (transactionType.isDisbursement()) {
createJournalEntriesForDisbursements(loanDTO, loanTransactionDTO, office);
@@ -67,8 +75,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
}
/*
- * Handle repayments, loan refunds, repayments at disbursement and reversal of Repayments and Repayments at
- * disbursement (except charge adjustment)
+ * Handle repayments, loan refunds, repayments at disbursement (except charge adjustment)
*/
else if ((transactionType.isRepaymentType() && !transactionType.isChargeAdjustment())
|| transactionType.isRepaymentAtDisbursement() || transactionType.isChargePayment()) {
@@ -91,7 +98,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
createJournalEntriesForCreditBalanceRefund(loanDTO, loanTransactionDTO, office);
}
- // Handle Write Offs, waivers and their reversals
+ // Handle Write Offs
else if ((transactionType.isWriteOff() || transactionType.isWaiveInterest() || transactionType.isWaiveCharges())) {
createJournalEntriesForRepaymentsAndWriteOffs(loanDTO, loanTransactionDTO, office, true, false);
}
@@ -135,7 +142,6 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
final BigDecimal penaltiesAmount = loanTransactionDTO.getPenalties();
final BigDecimal overPayment = loanTransactionDTO.getOverPayment();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
- final boolean isReversal = loanTransactionDTO.isReversed();
GLAccountBalanceHolder glAccountBalanceHolder = new GLAccountBalanceHolder();
if (isMarkedAsChargeOff) {
@@ -202,14 +208,14 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// create credit entries
for (Map.Entry<Long, BigDecimal> creditEntry : glAccountBalanceHolder.getCreditBalances().entrySet()) {
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(creditEntry.getKey());
- this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, loanId, transactionId, transactionDate,
- creditEntry.getValue(), isReversal, glAccount);
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate,
+ creditEntry.getValue(), glAccount);
}
// create debit entries
for (Map.Entry<Long, BigDecimal> debitEntry : glAccountBalanceHolder.getDebitBalances().entrySet()) {
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(debitEntry.getKey());
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, loanId, transactionId, transactionDate,
- debitEntry.getValue(), isReversal, glAccount);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate, debitEntry.getValue(),
+ glAccount);
}
}
@@ -227,7 +233,6 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
final BigDecimal feesAmount = loanTransactionDTO.getFees();
final BigDecimal penaltiesAmount = loanTransactionDTO.getPenalties();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
- final boolean isReversal = loanTransactionDTO.isReversed();
GLAccountBalanceHolder glAccountBalanceHolder = new GLAccountBalanceHolder();
// need to fetch if there are account mappings (always one)
@@ -272,14 +277,14 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// create credit entries
for (Map.Entry<Long, BigDecimal> creditEntry : glAccountBalanceHolder.getCreditBalances().entrySet()) {
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(creditEntry.getKey());
- this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, loanId, transactionId, transactionDate,
- creditEntry.getValue(), isReversal, glAccount);
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate,
+ creditEntry.getValue(), glAccount);
}
// create debit entries
for (Map.Entry<Long, BigDecimal> debitEntry : glAccountBalanceHolder.getDebitBalances().entrySet()) {
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(debitEntry.getKey());
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, loanId, transactionId, transactionDate,
- debitEntry.getValue(), isReversal, glAccount);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate, debitEntry.getValue(),
+ glAccount);
}
}
@@ -318,7 +323,6 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
final BigDecimal penaltiesAmount = loanTransactionDTO.getPenalties();
final BigDecimal overPaymentAmount = loanTransactionDTO.getOverPayment();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
- final boolean isReversal = loanTransactionDTO.isReversed();
BigDecimal totalDebitAmount = new BigDecimal(0);
@@ -386,8 +390,8 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
}
for (Map.Entry<GLAccount, BigDecimal> entry : accountMap.entrySet()) {
- this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, loanId, transactionId, transactionDate,
- entry.getValue(), isReversal, entry.getKey());
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate, entry.getValue(),
+ entry.getKey());
}
if (totalDebitAmount.compareTo(BigDecimal.ZERO) > 0) {
@@ -398,8 +402,8 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
} else {
accountMappingTypeId = AccrualAccountsForLoan.INCOME_FROM_FEES.getValue();
}
- this.helper.createDebitJournalEntryOrReversalForLoanCharges(office, currencyCode, accountMappingTypeId, loanProductId, chargeId,
- loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
+ this.helper.createDebitJournalEntryForLoanCharges(office, currencyCode, accountMappingTypeId, loanProductId, chargeId, loanId,
+ transactionId, transactionDate, totalDebitAmount);
}
}
@@ -418,13 +422,12 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
final BigDecimal penaltiesAmount = loanTransactionDTO.getPenalties();
final BigDecimal overPaymentAmount = loanTransactionDTO.getOverPayment();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
- final boolean isReversal = loanTransactionDTO.isReversed();
BigDecimal totalDebitAmount = new BigDecimal(0);
Map<GLAccount, BigDecimal> accountMap = new LinkedHashMap<>();
- // handle principal payment (and reversals)
+ // handle principal payment
if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(principalAmount);
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
@@ -432,7 +435,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
accountMap.put(account, principalAmount);
}
- // handle interest payment (and reversals)
+ // handle interest payment
if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(interestAmount);
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
@@ -445,7 +448,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
}
}
- // handle fees payment (and reversals)
+ // handle fees payment
if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(feesAmount);
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
@@ -458,7 +461,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
}
}
- // handle penalties payment (and reversals)
+ // handle penalties payment
if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
@@ -485,8 +488,8 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
}
for (Map.Entry<GLAccount, BigDecimal> entry : accountMap.entrySet()) {
- this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, loanId, transactionId, transactionDate,
- entry.getValue(), isReversal, entry.getKey());
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate, entry.getValue(),
+ entry.getKey());
}
if (totalDebitAmount.compareTo(BigDecimal.ZERO) > 0) {
@@ -497,8 +500,8 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
} else {
accountMappingTypeId = AccrualAccountsForLoan.INCOME_FROM_FEES.getValue();
}
- this.helper.createDebitJournalEntryOrReversalForLoanCharges(office, currencyCode, accountMappingTypeId, loanProductId, chargeId,
- loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
+ this.helper.createDebitJournalEntryForLoanCharges(office, currencyCode, accountMappingTypeId, loanProductId, chargeId, loanId,
+ transactionId, transactionDate, totalDebitAmount);
}
}
@@ -519,7 +522,6 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
final String transactionId = loanTransactionDTO.getTransactionId();
final LocalDate transactionDate = loanTransactionDTO.getTransactionDate();
final BigDecimal amount = loanTransactionDTO.getAmount();
- final boolean isReversal = loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
final BigDecimal overpaidAmount = Objects.isNull(loanTransactionDTO.getOverPayment()) ? BigDecimal.ZERO
: loanTransactionDTO.getOverPayment();
@@ -536,36 +538,36 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
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);
+ helper.createCreditJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.FUND_SOURCE, loanProductId, paymentTypeId,
+ loanId, transactionId, transactionDate, amount);
if (overpaidAmount.compareTo(BigDecimal.ZERO) > 0) {
- helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, overpaidAmount, isReversal);
+ helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, overpaidAmount);
}
if (principalCredited.compareTo(principalPaid) > 0) {
- helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, getPrincipalAccount(loanDTO), loanProductId,
- paymentTypeId, loanId, transactionId, transactionDate, principalCredited.subtract(principalPaid), isReversal);
+ helper.createDebitJournalEntryForLoan(office, currencyCode, getPrincipalAccount(loanDTO), loanProductId, paymentTypeId, loanId,
+ transactionId, transactionDate, principalCredited.subtract(principalPaid));
} else if (principalCredited.compareTo(principalPaid) < 0) {
- helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, getPrincipalAccount(loanDTO), loanProductId,
- paymentTypeId, loanId, transactionId, transactionDate, principalPaid.subtract(principalCredited), isReversal);
+ helper.createCreditJournalEntryForLoan(office, currencyCode, getPrincipalAccount(loanDTO), loanProductId, paymentTypeId, loanId,
+ transactionId, transactionDate, principalPaid.subtract(principalCredited));
}
if (feeCredited.compareTo(feePaid) > 0) {
- helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, getFeeAccount(loanDTO), loanProductId, paymentTypeId,
- loanId, transactionId, transactionDate, feeCredited.subtract(feePaid), isReversal);
+ helper.createDebitJournalEntryForLoan(office, currencyCode, getFeeAccount(loanDTO), loanProductId, paymentTypeId, loanId,
+ transactionId, transactionDate, feeCredited.subtract(feePaid));
} else if (feeCredited.compareTo(feePaid) < 0) {
- helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, getFeeAccount(loanDTO), loanProductId, paymentTypeId,
- loanId, transactionId, transactionDate, feePaid.subtract(feeCredited), isReversal);
+ helper.createCreditJournalEntryForLoan(office, currencyCode, getFeeAccount(loanDTO), loanProductId, paymentTypeId, loanId,
+ transactionId, transactionDate, feePaid.subtract(feeCredited));
}
if (penaltyCredited.compareTo(penaltyPaid) > 0) {
- helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, getPenaltyAccount(loanDTO), loanProductId, paymentTypeId,
- loanId, transactionId, transactionDate, penaltyCredited.subtract(penaltyPaid), isReversal);
+ helper.createDebitJournalEntryForLoan(office, currencyCode, getPenaltyAccount(loanDTO), loanProductId, paymentTypeId, loanId,
+ transactionId, transactionDate, penaltyCredited.subtract(penaltyPaid));
} else if (penaltyCredited.compareTo(penaltyPaid) < 0) {
- helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, getPenaltyAccount(loanDTO), loanProductId, paymentTypeId,
- loanId, transactionId, transactionDate, penaltyPaid.subtract(penaltyCredited), isReversal);
+ helper.createCreditJournalEntryForLoan(office, currencyCode, getPenaltyAccount(loanDTO), loanProductId, paymentTypeId, loanId,
+ transactionId, transactionDate, penaltyPaid.subtract(penaltyCredited));
}
}
@@ -616,29 +618,27 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
final BigDecimal overpaymentPortion = loanTransactionDTO.getOverPayment() != null ? loanTransactionDTO.getOverPayment()
: BigDecimal.ZERO;
final BigDecimal principalPortion = loanTransactionDTO.getAmount().subtract(overpaymentPortion);
- final boolean isReversed = loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
- // create journal entries for the disbursement (or disbursement
- // reversal)
+ // create journal entries for the disbursement
if (MathUtil.isGreaterThanZero(principalPortion)) {
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, principalPortion, isReversed);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, principalPortion);
}
if (MathUtil.isGreaterThanZero(overpaymentPortion)) {
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, overpaymentPortion, isReversed);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, overpaymentPortion);
}
if (loanTransactionDTO.isLoanToLoanTransfer()) {
- this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, FinancialActivity.ASSET_TRANSFER.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, loanTransactionDTO.getAmount(), isReversed);
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, FinancialActivity.ASSET_TRANSFER.getValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, loanTransactionDTO.getAmount());
} else if (loanTransactionDTO.isAccountTransfer()) {
- this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, FinancialActivity.LIABILITY_TRANSFER.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, loanTransactionDTO.getAmount(), isReversed);
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, FinancialActivity.LIABILITY_TRANSFER.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, loanTransactionDTO.getAmount());
} else {
- this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, AccrualAccountsForLoan.FUND_SOURCE.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, loanTransactionDTO.getAmount(), isReversed);
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.FUND_SOURCE.getValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, loanTransactionDTO.getAmount());
}
}
@@ -667,7 +667,6 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
* <b>Penalty Write off</b>: Debits "Losses Written off" and Credits "Receivable Penalties" <br/>
* <br/>
* <br/>
- * In case the loan transaction has been reversed, all debits are turned into credits and vice versa
*
* @param loanTransactionDTO
* @param loanDTO
@@ -701,7 +700,6 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
final BigDecimal penaltiesAmount = loanTransactionDTO.getPenalties();
final BigDecimal overPaymentAmount = loanTransactionDTO.getOverPayment();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
- final boolean isReversal = loanTransactionDTO.isReversed();
GLAccountBalanceHolder glAccountBalanceHolder = new GLAccountBalanceHolder();
BigDecimal totalDebitAmount = new BigDecimal(0);
@@ -801,9 +799,9 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
} else {
if (isIncomeFromFee) {
- this.helper.createCreditJournalEntryOrReversalForLoanCharges(office, currencyCode,
+ this.helper.createCreditJournalEntryForLoanCharges(office, currencyCode,
AccrualAccountsForLoan.INCOME_FROM_FEES.getValue(), loanProductId, loanId, transactionId, transactionDate,
- feesAmount, isReversal, loanTransactionDTO.getFeePayments());
+ feesAmount, loanTransactionDTO.getFeePayments());
GLAccount debitAccount = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
AccrualAccountsForLoan.FUND_SOURCE.getValue(), paymentTypeId);
glAccountBalanceHolder.addToDebit(debitAccount, feesAmount);
@@ -879,44 +877,41 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// create credit entries
for (Map.Entry<Long, BigDecimal> creditEntry : glAccountBalanceHolder.getCreditBalances().entrySet()) {
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(creditEntry.getKey());
- this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, loanId, transactionId, transactionDate,
- creditEntry.getValue(), isReversal, glAccount);
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate,
+ creditEntry.getValue(), glAccount);
}
if (totalDebitAmount.compareTo(BigDecimal.ZERO) > 0) {
if (writeOff) {
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode,
- AccrualAccountsForLoan.LOSSES_WRITTEN_OFF.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
- transactionDate, totalDebitAmount, isReversal);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.LOSSES_WRITTEN_OFF.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
} else {
if (loanTransactionDTO.isLoanToLoanTransfer()) {
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, FinancialActivity.ASSET_TRANSFER.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, FinancialActivity.ASSET_TRANSFER.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
} else if (loanTransactionDTO.isAccountTransfer()) {
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode,
- FinancialActivity.LIABILITY_TRANSFER.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
- transactionDate, totalDebitAmount, isReversal);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, FinancialActivity.LIABILITY_TRANSFER.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
} else {
// create debit entries
for (Map.Entry<Long, BigDecimal> debitEntry : glAccountBalanceHolder.getDebitBalances().entrySet()) {
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(debitEntry.getKey());
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, loanId, transactionId, transactionDate,
- debitEntry.getValue(), isReversal, glAccount);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate,
+ debitEntry.getValue(), glAccount);
}
}
}
}
/**
- * Charge Refunds (and their reversals) have an extra refund related pair of journal entries in addition to
- * those related to the repayment above
+ * Charge Refunds 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);
+ this.helper.createJournalEntriesForLoan(office, currencyCode, incomeAccount, AccrualAccountsForLoan.FUND_SOURCE.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
}
}
@@ -938,14 +933,13 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
final BigDecimal penaltiesAmount = loanTransactionDTO.getPenalties();
final BigDecimal overPaymentAmount = loanTransactionDTO.getOverPayment();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
- final boolean isReversal = loanTransactionDTO.isReversed();
BigDecimal totalDebitAmount = new BigDecimal(0);
Map<GLAccount, BigDecimal> accountMap = new LinkedHashMap<>();
Map<Integer, BigDecimal> debitAccountMapForGoodwillCredit = new LinkedHashMap<>();
- // handle principal payment or writeOff (and reversals)
+ // handle principal payment or writeOff
if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(principalAmount);
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
@@ -957,7 +951,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
}
}
- // handle interest payment of writeOff (and reversals)
+ // handle interest payment of writeOff
if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(interestAmount);
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
@@ -975,15 +969,14 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
}
}
- // handle fees payment of writeOff (and reversals)
+ // handle fees payment of writeOff
if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(feesAmount);
if (isIncomeFromFee) {
- this.helper.createCreditJournalEntryOrReversalForLoanCharges(office, currencyCode,
- AccrualAccountsForLoan.INCOME_FROM_FEES.getValue(), loanProductId, loanId, transactionId, transactionDate,
- feesAmount, isReversal, loanTransactionDTO.getFeePayments());
+ this.helper.createCreditJournalEntryForLoanCharges(office, currencyCode, AccrualAccountsForLoan.INCOME_FROM_FEES.getValue(),
+ loanProductId, loanId, transactionId, transactionDate, feesAmount, loanTransactionDTO.getFeePayments());
} else {
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
AccrualAccountsForLoan.FEES_RECEIVABLE.getValue(), paymentTypeId);
@@ -1000,7 +993,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
}
}
- // handle penalties payment of writeOff (and reversals)
+ // handle penalties payment of writeOff
if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
if (isIncomeFromFee) {
@@ -1047,53 +1040,48 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
}
for (Map.Entry<GLAccount, BigDecimal> entry : accountMap.entrySet()) {
- this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, loanId, transactionId, transactionDate,
- entry.getValue(), isReversal, entry.getKey());
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate, entry.getValue(),
+ entry.getKey());
}
/**
- * Single DEBIT transaction for write-offs or Repayments (and their reversals)
+ * Single DEBIT transaction for write-offs or Repayments
***/
if (totalDebitAmount.compareTo(BigDecimal.ZERO) > 0) {
if (writeOff) {
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode,
- AccrualAccountsForLoan.LOSSES_WRITTEN_OFF.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
- transactionDate, totalDebitAmount, isReversal);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.LOSSES_WRITTEN_OFF.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
} else {
if (loanTransactionDTO.isLoanToLoanTransfer()) {
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, FinancialActivity.ASSET_TRANSFER.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, FinancialActivity.ASSET_TRANSFER.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
} else if (loanTransactionDTO.isAccountTransfer()) {
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode,
- FinancialActivity.LIABILITY_TRANSFER.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
- transactionDate, totalDebitAmount, isReversal);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, FinancialActivity.LIABILITY_TRANSFER.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
} else {
if (loanTransactionDTO.getTransactionType().isGoodwillCredit()) {
// create debit entries
for (Map.Entry<Integer, BigDecimal> debitEntry : debitAccountMapForGoodwillCredit.entrySet()) {
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, debitEntry.getKey().intValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, debitEntry.getValue(),
- isReversal);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, debitEntry.getKey().intValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, debitEntry.getValue());
}
} else {
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode,
- AccrualAccountsForLoan.FUND_SOURCE.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
- transactionDate, totalDebitAmount, isReversal);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.FUND_SOURCE.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
}
}
}
}
/**
- * Charge Refunds (and their reversals) have an extra refund related pair of journal entries in addition to
- * those related to the repayment above
+ * Charge Refunds have an extra refund related pair of journal entries in addition to those related to the
+ * repayment above
***/
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);
+ this.helper.createJournalEntriesForLoan(office, currencyCode, incomeAccount, AccrualAccountsForLoan.FUND_SOURCE.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
}
}
@@ -1120,8 +1108,6 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
/**
* Create a single Debit to fund source and a single credit to "Income from Recovery"
- *
- * In case the loan transaction is a reversal, all debits are turned into credits and vice versa
*/
private void createJournalEntriesForRecoveryRepayments(final LoanDTO loanDTO, final LoanTransactionDTO loanTransactionDTO,
final Office office) {
@@ -1134,12 +1120,11 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
final String transactionId = loanTransactionDTO.getTransactionId();
final LocalDate transactionDate = loanTransactionDTO.getTransactionDate();
final BigDecimal amount = loanTransactionDTO.getAmount();
- final boolean isReversal = loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
- this.helper.createJournalEntriesAndReversalsForLoan(office, currencyCode, AccrualAccountsForLoan.FUND_SOURCE.getValue(),
+ this.helper.createJournalEntriesForLoan(office, currencyCode, AccrualAccountsForLoan.FUND_SOURCE.getValue(),
AccrualAccountsForLoan.INCOME_FROM_RECOVERY.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
- transactionDate, amount, isReversal);
+ transactionDate, amount);
}
@@ -1151,8 +1136,6 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
*
* <b>Penalties:</b> Debit <i>Penalties Receivable</i> and credit <i>Income from Penalties</i>
*
- * Also handles reversals for both fees and payment applications
- *
* @param loanDTO
* @param loanTransactionDTO
* @param office
@@ -1170,28 +1153,43 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
final BigDecimal interestAmount = loanTransactionDTO.getInterest();
final BigDecimal feesAmount = loanTransactionDTO.getFees();
final BigDecimal penaltiesAmount = loanTransactionDTO.getPenalties();
- final boolean isReversed = transactionType.isAccrualAdjustment() != loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
- // create journal entries for recognizing interest (or reversal)
+ // create journal entries for recognizing interest
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);
+ if (transactionType.isAccrualAdjustment()) {
+ this.helper.createJournalEntriesForLoan(office, currencyCode, AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(),
+ AccrualAccountsForLoan.INTEREST_RECEIVABLE.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
+ transactionDate, interestAmount);
+ } else {
+ this.helper.createJournalEntriesForLoan(office, currencyCode, AccrualAccountsForLoan.INTEREST_RECEIVABLE.getValue(),
+ AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
+ transactionDate, interestAmount);
+ }
}
- // create journal entries for the fees application (or reversal)
+ // create journal entries for the fees application
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());
+ if (transactionType.isAccrualAdjustment()) {
+ this.helper.createJournalEntriesForLoanCharges(office, currencyCode, AccrualAccountsForLoan.INCOME_FROM_FEES.getValue(),
+ AccrualAccountsForLoan.FEES_RECEIVABLE.getValue(), loanProductId, loanId, transactionId, transactionDate,
+ feesAmount, loanTransactionDTO.getFeePayments());
+ } else {
+ this.helper.createJournalEntriesForLoanCharges(office, currencyCode, AccrualAccountsForLoan.FEES_RECEIVABLE.getValue(),
+ AccrualAccountsForLoan.INCOME_FROM_FEES.getValue(), loanProductId, loanId, transactionId, transactionDate,
+ feesAmount, loanTransactionDTO.getFeePayments());
+ }
}
- // create journal entries for the penalties application (or reversal)
+ // create journal entries for the penalties application
if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
-
- this.helper.createJournalEntriesAndReversalsForLoanCharges(office, currencyCode,
- AccrualAccountsForLoan.PENALTIES_RECEIVABLE.getValue(), AccrualAccountsForLoan.INCOME_FROM_PENALTIES.getValue(),
- loanProductId, loanId, transactionId, transactionDate, penaltiesAmount, isReversed,
- loanTransactionDTO.getPenaltyPayments());
+ if (transactionType.isAccrualAdjustment()) {
+ this.helper.createJournalEntriesForLoanCharges(office, currencyCode,
+ AccrualAccountsForLoan.INCOME_FROM_PENALTIES.getValue(), AccrualAccountsForLoan.PENALTIES_RECEIVABLE.getValue(),
+ loanProductId, loanId, transactionId, transactionDate, penaltiesAmount, loanTransactionDTO.getPenaltyPayments());
+ } else {
+ this.helper.createJournalEntriesForLoanCharges(office, currencyCode, AccrualAccountsForLoan.PENALTIES_RECEIVABLE.getValue(),
+ AccrualAccountsForLoan.INCOME_FROM_PENALTIES.getValue(), loanProductId, loanId, transactionId, transactionDate,
+ penaltiesAmount, loanTransactionDTO.getPenaltyPayments());
+ }
}
}
@@ -1205,17 +1203,16 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
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();
if (loanTransactionDTO.isAccountTransfer()) {
- this.helper.createJournalEntriesAndReversalsForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
+ this.helper.createJournalEntriesForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
FinancialActivity.LIABILITY_TRANSFER.getValue(), loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
- refundAmount, isReversal);
+ refundAmount);
} else {
- this.helper.createJournalEntriesAndReversalsForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
+ this.helper.createJournalEntriesForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
AccrualAccountsForLoan.FUND_SOURCE.getValue(), loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
- refundAmount, isReversal);
+ refundAmount);
}
}
@@ -1236,7 +1233,6 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// transaction properties
final String transactionId = loanTransactionDTO.getTransactionId();
final LocalDate transactionDate = loanTransactionDTO.getTransactionDate();
- final boolean isReversal = loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
BigDecimal overpaymentAmount = loanTransactionDTO.getOverPayment();
@@ -1257,8 +1253,8 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
}
JournalAmountHolder totalAmountHolder = new JournalAmountHolder(AccrualAccountsForLoan.FUND_SOURCE.getValue(), totalAmount);
- helper.createSplitJournalEntriesAndReversalsForLoan(office, currencyCode, journalAmountHolders, totalAmountHolder, loanProductId,
- paymentTypeId, loanId, transactionId, transactionDate, isReversal);
+ helper.createSplitJournalEntriesForLoan(office, currencyCode, journalAmountHolders, totalAmountHolder, loanProductId, paymentTypeId,
+ loanId, transactionId, transactionDate);
}
@@ -1293,21 +1289,20 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
final BigDecimal feesAmount = loanTransactionDTO.getFees();
final BigDecimal penaltiesAmount = loanTransactionDTO.getPenalties();
final BigDecimal overPaymentAmount = loanTransactionDTO.getOverPayment();
- final boolean isReversal = loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
BigDecimal totalDebitAmount = new BigDecimal(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);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, principalAmount);
}
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);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, interestAmount);
}
if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
@@ -1321,9 +1316,8 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
: chargePaymentDTO.getAmount(),
chargePaymentDTO.getLoanChargeId()));
}
- this.helper.createCreditJournalEntryOrReversalForLoanCharges(office, currencyCode,
- AccrualAccountsForLoan.INCOME_FROM_FEES.getValue(), loanProductId, loanId, transactionId, transactionDate, feesAmount,
- !isReversal, chargePaymentDTOs);
+ this.helper.createDebitJournalEntryForLoanCharges(office, currencyCode, AccrualAccountsForLoan.INCOME_FROM_FEES.getValue(),
+ loanProductId, loanId, transactionId, transactionDate, feesAmount, chargePaymentDTOs);
}
if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
@@ -1336,21 +1330,18 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
: chargePaymentDTO.getAmount(),
chargePaymentDTO.getLoanChargeId()));
}
-
- this.helper.createCreditJournalEntryOrReversalForLoanCharges(office, currencyCode,
- AccrualAccountsForLoan.INCOME_FROM_PENALTIES.getValue(), loanProductId, loanId, transactionId, transactionDate,
- penaltiesAmount, !isReversal, chargePaymentDTOs);
+ this.helper.createDebitJournalEntryForLoanCharges(office, currencyCode, AccrualAccountsForLoan.INCOME_FROM_PENALTIES.getValue(),
+ loanProductId, loanId, transactionId, transactionDate, penaltiesAmount, chargePaymentDTOs);
}
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);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, overPaymentAmount);
}
/*** create a single debit entry (or reversal) for the entire amount **/
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, AccrualAccountsForLoan.FUND_SOURCE.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, !isReversal);
-
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.FUND_SOURCE.getValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
}
}
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 770194ef7a..6081ab9e03 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
@@ -35,6 +35,7 @@ import org.apache.fineract.accounting.journalentry.data.LoanDTO;
import org.apache.fineract.accounting.journalentry.data.LoanTransactionDTO;
import org.apache.fineract.infrastructure.core.service.MathUtil;
import org.apache.fineract.organisation.office.domain.Office;
+import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionEnumData;
import org.springframework.stereotype.Component;
@Component
@@ -42,48 +43,53 @@ import org.springframework.stereotype.Component;
public class CashBasedAccountingProcessorForLoan implements AccountingProcessorForLoan {
private final AccountingProcessorHelper helper;
+ private final JournalEntryWritePlatformService journalEntryWritePlatformService;
@Override
public void createJournalEntriesForLoan(final LoanDTO loanDTO) {
- final GLClosure latestGLClosure = this.helper.getLatestClosureByBranch(loanDTO.getOfficeId());
+ final Long officeId = loanDTO.getOfficeId();
+ final GLClosure latestGLClosure = this.helper.getLatestClosureByBranch(officeId);
final Long loanProductId = loanDTO.getLoanProductId();
final String currencyCode = loanDTO.getCurrencyCode();
+ final Office office = this.helper.getOfficeById(officeId);
for (final LoanTransactionDTO loanTransactionDTO : loanDTO.getNewLoanTransactions()) {
final LocalDate transactionDate = loanTransactionDTO.getTransactionDate();
final String transactionId = loanTransactionDTO.getTransactionId();
- final Office office = this.helper.getOfficeById(loanTransactionDTO.getOfficeId());
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
final Long loanId = loanDTO.getLoanId();
+ final LoanTransactionEnumData transactionType = loanTransactionDTO.getTransactionType();
this.helper.checkForBranchClosures(latestGLClosure, transactionDate);
- /** Handle Disbursements and reversals of disbursements **/
- if (loanTransactionDTO.getTransactionType().isDisbursement()) {
+ if (loanTransactionDTO.isReversed()) {
+ journalEntryWritePlatformService.createJournalEntryForReversedLoanTransaction(transactionDate, transactionId, officeId);
+ continue;
+ }
+
+ /** Handle Disbursements **/
+ if (transactionType.isDisbursement()) {
createJournalEntriesForDisbursements(loanDTO, loanTransactionDTO, office);
}
/***
- * Logic for repayments, repayments at disbursement and reversal of Repayments and Repayments at
- * disbursement (except charge adjustment)
+ * Logic for repayments, repayments at disbursement (except charge adjustment)
***/
- else if ((loanTransactionDTO.getTransactionType().isRepaymentType()
- && !loanTransactionDTO.getTransactionType().isChargeAdjustment())
- || loanTransactionDTO.getTransactionType().isRepaymentAtDisbursement()
- || loanTransactionDTO.getTransactionType().isChargePayment()) {
+ else if ((transactionType.isRepaymentType() && !transactionType.isChargeAdjustment())
+ || transactionType.isRepaymentAtDisbursement() || transactionType.isChargePayment()) {
createJournalEntriesForRepayments(loanDTO, loanTransactionDTO, office);
}
/** Logic for handling recovery payments **/
- else if (loanTransactionDTO.getTransactionType().isRecoveryRepayment()) {
+ else if (transactionType.isRecoveryRepayment()) {
createJournalEntriesForRecoveryRepayments(loanDTO, loanTransactionDTO, office);
}
/** Logic for Refunds of Overpayments **/
- else if (loanTransactionDTO.getTransactionType().isRefund()) {
+ else if (transactionType.isRefund()) {
createJournalEntriesForRefund(loanDTO, loanTransactionDTO, office);
}
/** Logic for Credit Balance Refunds **/
- else if (loanTransactionDTO.getTransactionType().isCreditBalanceRefund()) {
+ else if (transactionType.isCreditBalanceRefund()) {
createJournalEntriesForCreditBalanceRefund(loanDTO, loanTransactionDTO, office);
}
@@ -91,33 +97,32 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
* Only principal write off affects cash based accounting (interest and fee write off need not be
* considered). Debit losses written off and credit Loan Portfolio
**/
- else if (loanTransactionDTO.getTransactionType().isWriteOff()) {
+ else if (transactionType.isWriteOff()) {
final BigDecimal principalAmount = loanTransactionDTO.getPrincipal();
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());
+ this.helper.createJournalEntriesForLoan(office, currencyCode, CashAccountsForLoan.LOSSES_WRITTEN_OFF.getValue(),
+ CashAccountsForLoan.LOAN_PORTFOLIO.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
+ transactionDate, principalAmount);
}
- } else if (loanTransactionDTO.getTransactionType().isInitiateTransfer()
- || loanTransactionDTO.getTransactionType().isApproveTransfer()
- || loanTransactionDTO.getTransactionType().isWithdrawTransfer()) {
+ } else if (transactionType.isInitiateTransfer() || transactionType.isApproveTransfer()
+ || transactionType.isWithdrawTransfer()) {
createJournalEntriesForTransfers(loanDTO, loanTransactionDTO, office);
}
/** Logic for Refunds of Active Loans **/
- else if (loanTransactionDTO.getTransactionType().isRefundForActiveLoans()) {
+ else if (transactionType.isRefundForActiveLoans()) {
createJournalEntriesForRefundForActiveLoan(loanDTO, loanTransactionDTO, office);
}
// Logic for Chargebacks
- else if (loanTransactionDTO.getTransactionType().isChargeback()) {
+ else if (transactionType.isChargeback()) {
createJournalEntriesForChargeback(loanDTO, loanTransactionDTO, office);
}
// Logic for Charge Adjustment
- else if (loanTransactionDTO.getTransactionType().isChargeAdjustment()) {
+ else if (transactionType.isChargeAdjustment()) {
createJournalEntriesForChargeAdjustment(loanDTO, loanTransactionDTO, office);
}
// Logic for Charge-Off
- else if (loanTransactionDTO.getTransactionType().isChargeoff()) {
+ else if (transactionType.isChargeoff()) {
createJournalEntriesForChargeOff(loanDTO, loanTransactionDTO, office);
}
}
@@ -138,7 +143,6 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
final BigDecimal feesAmount = loanTransactionDTO.getFees();
final BigDecimal penaltiesAmount = loanTransactionDTO.getPenalties();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
- final boolean isReversal = loanTransactionDTO.isReversed();
GLAccountBalanceHolder glAccountBalanceHolder = new GLAccountBalanceHolder();
@@ -174,14 +178,14 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
// create credit entries
for (Map.Entry<Long, BigDecimal> creditEntry : glAccountBalanceHolder.getCreditBalances().entrySet()) {
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(creditEntry.getKey());
- this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, loanId, transactionId, transactionDate,
- creditEntry.getValue(), isReversal, glAccount);
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate,
+ creditEntry.getValue(), glAccount);
}
// create debit entries
for (Map.Entry<Long, BigDecimal> debitEntry : glAccountBalanceHolder.getDebitBalances().entrySet()) {
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(debitEntry.getKey());
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, loanId, transactionId, transactionDate,
- debitEntry.getValue(), isReversal, glAccount);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate, debitEntry.getValue(),
+ glAccount);
}
}
@@ -230,13 +234,12 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
final BigDecimal penaltiesAmount = loanTransactionDTO.getPenalties();
final BigDecimal overPaymentAmount = loanTransactionDTO.getOverPayment();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
- final boolean isReversal = loanTransactionDTO.isReversed();
BigDecimal totalDebitAmount = new BigDecimal(0);
Map<GLAccount, BigDecimal> accountMap = new LinkedHashMap<>();
- // handle principal payment (and reversals)
+ // handle principal payment
if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(principalAmount);
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
@@ -244,7 +247,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
accountMap.put(account, principalAmount);
}
- // handle interest payment (and reversals)
+ // handle interest payment
if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(interestAmount);
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
@@ -257,7 +260,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
}
}
- // handle fees payment (and reversals)
+ // handle fees payment
if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(feesAmount);
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
@@ -297,8 +300,8 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
}
for (Map.Entry<GLAccount, BigDecimal> entry : accountMap.entrySet()) {
- this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, loanId, transactionId, transactionDate,
- entry.getValue(), isReversal, entry.getKey());
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate, entry.getValue(),
+ entry.getKey());
}
if (totalDebitAmount.compareTo(BigDecimal.ZERO) > 0) {
@@ -309,8 +312,8 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
} else {
accountMappingTypeId = CashAccountsForLoan.INCOME_FROM_FEES.getValue();
}
- this.helper.createDebitJournalEntryOrReversalForLoanCharges(office, currencyCode, accountMappingTypeId, loanProductId, chargeId,
- loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
+ this.helper.createDebitJournalEntryForLoanCharges(office, currencyCode, accountMappingTypeId, loanProductId, chargeId, loanId,
+ transactionId, transactionDate, totalDebitAmount);
}
}
@@ -329,13 +332,12 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
final BigDecimal penaltiesAmount = loanTransactionDTO.getPenalties();
final BigDecimal overPaymentAmount = loanTransactionDTO.getOverPayment();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
- final boolean isReversal = loanTransactionDTO.isReversed();
BigDecimal totalDebitAmount = new BigDecimal(0);
Map<GLAccount, BigDecimal> accountMap = new LinkedHashMap<>();
- // handle principal payment (and reversals)
+ // handle principal payment
if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(principalAmount);
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId, CashAccountsForLoan.LOAN_PORTFOLIO.getValue(),
@@ -343,7 +345,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
accountMap.put(account, principalAmount);
}
- // handle interest payment (and reversals)
+ // handle interest payment
if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(interestAmount);
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
@@ -356,7 +358,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
}
}
- // handle fees payment (and reversals)
+ // handle fees payment
if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(feesAmount);
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId, CashAccountsForLoan.INCOME_FROM_FEES.getValue(),
@@ -369,7 +371,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
}
}
- // handle penalties payment (and reversals)
+ // handle penalties payment
if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
@@ -396,8 +398,8 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
}
for (Map.Entry<GLAccount, BigDecimal> entry : accountMap.entrySet()) {
- this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, loanId, transactionId, transactionDate,
- entry.getValue(), isReversal, entry.getKey());
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate, entry.getValue(),
+ entry.getKey());
}
if (totalDebitAmount.compareTo(BigDecimal.ZERO) > 0) {
@@ -408,8 +410,8 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
} else {
accountMappingTypeId = CashAccountsForLoan.INCOME_FROM_FEES.getValue();
}
- this.helper.createDebitJournalEntryOrReversalForLoanCharges(office, currencyCode, accountMappingTypeId, loanProductId, chargeId,
- loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
+ this.helper.createDebitJournalEntryForLoanCharges(office, currencyCode, accountMappingTypeId, loanProductId, chargeId, loanId,
+ transactionId, transactionDate, totalDebitAmount);
}
}
@@ -430,20 +432,15 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
final String transactionId = loanTransactionDTO.getTransactionId();
final LocalDate transactionDate = loanTransactionDTO.getTransactionDate();
final BigDecimal amount = loanTransactionDTO.getAmount();
- final boolean isReversal = loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
- this.helper.createJournalEntriesAndReversalsForLoan(office, currencyCode, CashAccountsForLoan.LOAN_PORTFOLIO.getValue(),
- CashAccountsForLoan.FUND_SOURCE.getValue(), loanProductId, paymentTypeId, loanId, transactionId, transactionDate, amount,
- isReversal);
+ this.helper.createJournalEntriesForLoan(office, currencyCode, CashAccountsForLoan.LOAN_PORTFOLIO.getValue(),
+ CashAccountsForLoan.FUND_SOURCE.getValue(), loanProductId, paymentTypeId, loanId, transactionId, transactionDate, amount);
}
/**
* Debit loan Portfolio and credit Fund source for a Disbursement <br/>
*
- * All debits are turned into credits and vice versa in case of disbursement reversals
- *
- *
* @param loanDTO
* @param loanTransactionDTO
* @param office
@@ -461,36 +458,32 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
final BigDecimal overpaymentPortion = loanTransactionDTO.getOverPayment() != null ? loanTransactionDTO.getOverPayment()
: BigDecimal.ZERO;
final BigDecimal principalPortion = loanTransactionDTO.getAmount().subtract(overpaymentPortion);
- final boolean isReversal = loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
if (MathUtil.isGreaterThanZero(principalPortion)) {
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, CashAccountsForLoan.LOAN_PORTFOLIO.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, principalPortion, isReversal);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, CashAccountsForLoan.LOAN_PORTFOLIO.getValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, principalPortion);
}
if (MathUtil.isGreaterThanZero(overpaymentPortion)) {
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, CashAccountsForLoan.OVERPAYMENT.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, overpaymentPortion, isReversal);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, CashAccountsForLoan.OVERPAYMENT.getValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, overpaymentPortion);
}
if (loanTransactionDTO.isLoanToLoanTransfer()) {
- this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, FinancialActivity.ASSET_TRANSFER.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, loanTransactionDTO.getAmount(), isReversal);
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, FinancialActivity.ASSET_TRANSFER.getValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, loanTransactionDTO.getAmount());
} else if (loanTransactionDTO.isAccountTransfer()) {
- this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, FinancialActivity.LIABILITY_TRANSFER.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, loanTransactionDTO.getAmount(), isReversal);
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, FinancialActivity.LIABILITY_TRANSFER.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, loanTransactionDTO.getAmount());
} else {
- this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, CashAccountsForLoan.FUND_SOURCE.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, loanTransactionDTO.getAmount(), isReversal);
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, CashAccountsForLoan.FUND_SOURCE.getValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, loanTransactionDTO.getAmount());
}
}
/**
* Debit loan Portfolio and credit Fund source for a Disbursement <br/>
*
- * All debits are turned into credits and vice versa in case of disbursement reversals
- *
- *
* @param loanDTO
* @param loanTransactionDTO
* @param office
@@ -505,17 +498,16 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
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();
if (loanTransactionDTO.isAccountTransfer()) {
- this.helper.createJournalEntriesAndReversalsForLoan(office, currencyCode, CashAccountsForLoan.OVERPAYMENT.getValue(),
+ this.helper.createJournalEntriesForLoan(office, currencyCode, CashAccountsForLoan.OVERPAYMENT.getValue(),
FinancialActivity.LIABILITY_TRANSFER.getValue(), loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
- refundAmount, isReversal);
+ refundAmount);
} else {
- this.helper.createJournalEntriesAndReversalsForLoan(office, currencyCode, CashAccountsForLoan.OVERPAYMENT.getValue(),
+ this.helper.createJournalEntriesForLoan(office, currencyCode, CashAccountsForLoan.OVERPAYMENT.getValue(),
CashAccountsForLoan.FUND_SOURCE.getValue(), loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
- refundAmount, isReversal);
+ refundAmount);
}
}
@@ -523,8 +515,6 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
* Create a single Debit to fund source and multiple credits if applicable (loan portfolio for principal repayments,
* Interest on loans for interest repayments, Income from fees for fees payment and Income from penalties for
* penalty payment)
- *
- * In case the loan transaction is a reversal, all debits are turned into credits and vice versa
*/
private void createJournalEntriesForRepayments(final LoanDTO loanDTO, final LoanTransactionDTO loanTransactionDTO,
final Office office) {
@@ -532,7 +522,6 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
final boolean isMarkedChargeOff = loanDTO.isMarkedAsChargeOff();
if (isMarkedChargeOff) {
createJournalEntriesForChargeOffLoanRepayments(loanDTO, loanTransactionDTO, office);
-
} else {
createJournalEntriesForLoanRepayments(loanDTO, loanTransactionDTO, office);
}
@@ -555,7 +544,6 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
final BigDecimal penaltiesAmount = loanTransactionDTO.getPenalties();
final BigDecimal overPaymentAmount = loanTransactionDTO.getOverPayment();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
- final boolean isReversal = loanTransactionDTO.isReversed();
GLAccountBalanceHolder glAccountBalanceHolder = new GLAccountBalanceHolder();
BigDecimal totalDebitAmount = new BigDecimal(0);
@@ -707,36 +695,35 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
// create credit entries
for (Map.Entry<Long, BigDecimal> creditEntry : glAccountBalanceHolder.getCreditBalances().entrySet()) {
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(creditEntry.getKey());
- this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, loanId, transactionId, transactionDate,
- creditEntry.getValue(), isReversal, glAccount);
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate,
+ creditEntry.getValue(), glAccount);
}
- /*** create a single debit entry (or reversal) for the entire amount **/
+ /*** create a single debit entry for the entire amount **/
if (loanTransactionDTO.isLoanToLoanTransfer()) {
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, FinancialActivity.ASSET_TRANSFER.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, FinancialActivity.ASSET_TRANSFER.getValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
} else if (loanTransactionDTO.isAccountTransfer()) {
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, FinancialActivity.LIABILITY_TRANSFER.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, FinancialActivity.LIABILITY_TRANSFER.getValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
} else {
// create debit entries
for (Map.Entry<Long, BigDecimal> debitEntry : glAccountBalanceHolder.getDebitBalances().entrySet()) {
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(debitEntry.getKey());
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, loanId, transactionId, transactionDate,
- debitEntry.getValue(), isReversal, glAccount);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate,
+ debitEntry.getValue(), glAccount);
}
}
/**
- * Charge Refunds (and their reversals) have an extra refund related pair of journal entries in addition to
- * those related to the repayment above
+ * Charge Refunds 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);
+ this.helper.createJournalEntriesForLoan(office, currencyCode, incomeAccount, CashAccountsForLoan.FUND_SOURCE.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
}
}
}
@@ -755,7 +742,6 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
final BigDecimal feesAmount = loanTransactionDTO.getFees();
final BigDecimal penaltiesAmount = loanTransactionDTO.getPenalties();
final BigDecimal overPaymentAmount = loanTransactionDTO.getOverPayment();
- final boolean isReversal = loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
BigDecimal totalDebitAmount = new BigDecimal(0);
@@ -763,8 +749,8 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
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);
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, CashAccountsForLoan.LOAN_PORTFOLIO, loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, principalAmount);
if (loanTransactionDTO.getTransactionType().isGoodwillCredit()) {
populateDebitAccountEntry(loanProductId, principalAmount, CashAccountsForLoan.GOODWILL_CREDIT.getValue(),
debitAccountMapForGoodwillCredit, paymentTypeId);
@@ -773,8 +759,8 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
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);
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, CashAccountsForLoan.INTEREST_ON_LOANS, loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, interestAmount);
if (loanTransactionDTO.getTransactionType().isGoodwillCredit()) {
populateDebitAccountEntry(loanProductId, interestAmount,
CashAccountsForLoan.INCOME_FROM_GOODWILL_CREDIT_INTEREST.getValue(), debitAccountMapForGoodwillCredit,
@@ -784,9 +770,8 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
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());
+ this.helper.createCreditJournalEntryForLoanCharges(office, currencyCode, CashAccountsForLoan.INCOME_FROM_FEES.getValue(),
+ loanProductId, loanId, transactionId, transactionDate, feesAmount, loanTransactionDTO.getFeePayments());
if (loanTransactionDTO.getTransactionType().isGoodwillCredit()) {
populateDebitAccountEntry(loanProductId, feesAmount, CashAccountsForLoan.INCOME_FROM_GOODWILL_CREDIT_FEES.getValue(),
debitAccountMapForGoodwillCredit, paymentTypeId);
@@ -795,9 +780,8 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
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());
+ this.helper.createCreditJournalEntryForLoanCharges(office, currencyCode, CashAccountsForLoan.INCOME_FROM_PENALTIES.getValue(),
+ loanProductId, loanId, transactionId, transactionDate, penaltiesAmount, loanTransactionDTO.getPenaltyPayments());
if (loanTransactionDTO.getTransactionType().isGoodwillCredit()) {
populateDebitAccountEntry(loanProductId, penaltiesAmount,
CashAccountsForLoan.INCOME_FROM_GOODWILL_CREDIT_PENALTY.getValue(), debitAccountMapForGoodwillCredit,
@@ -807,45 +791,44 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
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);
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, CashAccountsForLoan.OVERPAYMENT, loanProductId, paymentTypeId,
+ loanId, transactionId, transactionDate, overPaymentAmount);
if (loanTransactionDTO.getTransactionType().isGoodwillCredit()) {
populateDebitAccountEntry(loanProductId, overPaymentAmount, CashAccountsForLoan.GOODWILL_CREDIT.getValue(),
debitAccountMapForGoodwillCredit, paymentTypeId);
}
}
- /*** create a single debit entry (or reversal) for the entire amount **/
+ /*** create a single debit entry for the entire amount **/
if (loanTransactionDTO.isLoanToLoanTransfer()) {
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, FinancialActivity.ASSET_TRANSFER.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, FinancialActivity.ASSET_TRANSFER.getValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
} else if (loanTransactionDTO.isAccountTransfer()) {
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, FinancialActivity.LIABILITY_TRANSFER.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, FinancialActivity.LIABILITY_TRANSFER.getValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
} else {
if (loanTransactionDTO.getTransactionType().isGoodwillCredit()) {
// create debit entries
for (Map.Entry<Integer, BigDecimal> debitEntry : debitAccountMapForGoodwillCredit.entrySet()) {
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, debitEntry.getKey().intValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, debitEntry.getValue(), isReversal);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, debitEntry.getKey(), loanProductId, paymentTypeId,
+ loanId, transactionId, transactionDate, debitEntry.getValue());
}
} else {
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, CashAccountsForLoan.FUND_SOURCE.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, CashAccountsForLoan.FUND_SOURCE.getValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
}
}
/**
- * Charge Refunds (and their reversals) have an extra refund related pair of journal entries in addition to
- * those related to the repayment above
+ * Charge Refunds have an extra refund related pair of journal entries in addition to those related to the
+ * repayment above
***/
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);
+ this.helper.createJournalEntriesForLoan(office, currencyCode, incomeAccount, CashAccountsForLoan.FUND_SOURCE.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
}
}
@@ -863,8 +846,6 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
/**
* Create a single Debit to fund source and a single credit to "Income from Recovery"
- *
- * In case the loan transaction is a reversal, all debits are turned into credits and vice versa
*/
private void createJournalEntriesForRecoveryRepayments(final LoanDTO loanDTO, final LoanTransactionDTO loanTransactionDTO,
final Office office) {
@@ -877,12 +858,11 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
final String transactionId = loanTransactionDTO.getTransactionId();
final LocalDate transactionDate = loanTransactionDTO.getTransactionDate();
final BigDecimal amount = loanTransactionDTO.getAmount();
- final boolean isReversal = loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
- this.helper.createJournalEntriesAndReversalsForLoan(office, currencyCode, CashAccountsForLoan.FUND_SOURCE.getValue(),
+ this.helper.createJournalEntriesForLoan(office, currencyCode, CashAccountsForLoan.FUND_SOURCE.getValue(),
CashAccountsForLoan.INCOME_FROM_RECOVERY.getValue(), loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
- amount, isReversal);
+ amount);
}
@@ -907,18 +887,16 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
final String transactionId = loanTransactionDTO.getTransactionId();
final LocalDate transactionDate = loanTransactionDTO.getTransactionDate();
final BigDecimal principalAmount = loanTransactionDTO.getPrincipal();
- final boolean isReversal = loanTransactionDTO.isReversed();
- // final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
if (loanTransactionDTO.getTransactionType().isInitiateTransfer()) {
- this.helper.createJournalEntriesAndReversalsForLoan(office, currencyCode, CashAccountsForLoan.TRANSFERS_SUSPENSE.getValue(),
+ this.helper.createJournalEntriesForLoan(office, currencyCode, CashAccountsForLoan.TRANSFERS_SUSPENSE.getValue(),
CashAccountsForLoan.LOAN_PORTFOLIO.getValue(), loanProductId, null, loanId, transactionId, transactionDate,
- principalAmount, isReversal);
+ principalAmount);
} else if (loanTransactionDTO.getTransactionType().isApproveTransfer()
|| loanTransactionDTO.getTransactionType().isWithdrawTransfer()) {
- this.helper.createJournalEntriesAndReversalsForLoan(office, currencyCode, CashAccountsForLoan.LOAN_PORTFOLIO.getValue(),
+ this.helper.createJournalEntriesForLoan(office, currencyCode, CashAccountsForLoan.LOAN_PORTFOLIO.getValue(),
CashAccountsForLoan.TRANSFERS_SUSPENSE.getValue(), loanProductId, null, loanId, transactionId, transactionDate,
- principalAmount, isReversal);
+ principalAmount);
}
}
@@ -932,7 +910,6 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
// transaction properties
final String transactionId = loanTransactionDTO.getTransactionId();
final LocalDate transactionDate = loanTransactionDTO.getTransactionDate();
- final boolean isReversal = loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
BigDecimal overpaymentAmount = loanTransactionDTO.getOverPayment();
@@ -951,8 +928,8 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
}
JournalAmountHolder totalAmountHolder = new JournalAmountHolder(CashAccountsForLoan.FUND_SOURCE.getValue(), totalAmount);
- helper.createSplitJournalEntriesAndReversalsForLoan(office, currencyCode, journalAmountHolders, totalAmountHolder, loanProductId,
- paymentTypeId, loanId, transactionId, transactionDate, isReversal);
+ helper.createSplitJournalEntriesForLoan(office, currencyCode, journalAmountHolders, totalAmountHolder, loanProductId, paymentTypeId,
+ loanId, transactionId, transactionDate);
}
private void createJournalEntriesForRefundForActiveLoan(LoanDTO loanDTO, LoanTransactionDTO loanTransactionDTO, Office office) {
@@ -969,21 +946,20 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
final BigDecimal feesAmount = loanTransactionDTO.getFees();
final BigDecimal penaltiesAmount = loanTransactionDTO.getPenalties();
final BigDecimal overPaymentAmount = loanTransactionDTO.getOverPayment();
- final boolean isReversal = loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
BigDecimal totalDebitAmount = new BigDecimal(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);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, CashAccountsForLoan.LOAN_PORTFOLIO.getValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, principalAmount);
}
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);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, CashAccountsForLoan.INTEREST_ON_LOANS.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, interestAmount);
}
if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
@@ -997,9 +973,8 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
: chargePaymentDTO.getAmount(),
chargePaymentDTO.getLoanChargeId()));
}
- this.helper.createCreditJournalEntryOrReversalForLoanCharges(office, currencyCode,
- CashAccountsForLoan.INCOME_FROM_FEES.getValue(), loanProductId, loanId, transactionId, transactionDate, feesAmount,
- !isReversal, chargePaymentDTOs);
+ this.helper.createDebitJournalEntryForLoanCharges(office, currencyCode, CashAccountsForLoan.INCOME_FROM_FEES.getValue(),
+ loanProductId, loanId, transactionId, transactionDate, feesAmount, chargePaymentDTOs);
}
if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
@@ -1013,20 +988,18 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
chargePaymentDTO.getLoanChargeId()));
}
- this.helper.createCreditJournalEntryOrReversalForLoanCharges(office, currencyCode,
- CashAccountsForLoan.INCOME_FROM_PENALTIES.getValue(), loanProductId, loanId, transactionId, transactionDate,
- penaltiesAmount, !isReversal, chargePaymentDTOs);
+ this.helper.createDebitJournalEntryForLoanCharges(office, currencyCode, CashAccountsForLoan.INCOME_FROM_PENALTIES.getValue(),
+ loanProductId, loanId, transactionId, transactionDate, penaltiesAmount, chargePaymentDTOs);
}
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);
+ this.helper.createDebitJournalEntryForLoan(office, currencyCode, CashAccountsForLoan.OVERPAYMENT.getValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, overPaymentAmount);
}
/*** create a single debit entry (or reversal) for the entire amount **/
- this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, CashAccountsForLoan.FUND_SOURCE.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, !isReversal);
-
+ this.helper.createCreditJournalEntryForLoan(office, currencyCode, CashAccountsForLoan.FUND_SOURCE.getValue(), loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
}
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformService.java
index 0ea9eceb68..3671ffa8cc 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformService.java
@@ -39,6 +39,8 @@ public interface JournalEntryWritePlatformService {
CommandProcessingResult defineOpeningBalance(JsonCommand command);
+ void createJournalEntryForReversedLoanTransaction(LocalDate transactionDate, String loanTransactionId, Long officeId);
+
String revertProvisioningJournalEntries(LocalDate reversalTransactionDate, Long entityId, Integer entityType);
String createProvisioningJournalEntries(ProvisioningEntry entry);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformServiceJpaRepositoryImpl.java
index 460e89e455..a0c7d9e042 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformServiceJpaRepositoryImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformServiceJpaRepositoryImpl.java
@@ -298,6 +298,28 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
return new CommandProcessingResultBuilder().withTransactionId(reversalTransactionId).build();
}
+ @Override
+ public void createJournalEntryForReversedLoanTransaction(final LocalDate transactionDate, final String loanTransactionId,
+ final Long officeId) {
+ final GLClosure latestGLClosure = this.helper.getLatestClosureByBranch(officeId);
+ this.helper.checkForBranchClosures(latestGLClosure, transactionDate);
+ final String transactionId = AccountingProcessorHelper.LOAN_TRANSACTION_IDENTIFIER + loanTransactionId;
+ final List<JournalEntry> journalEntries = this.glJournalEntryRepository.findJournalEntries(transactionId,
+ PortfolioProductType.LOAN.getValue());
+ if (journalEntries == null || journalEntries.isEmpty()) {
+ return;
+ }
+ for (final JournalEntry journalEntry : journalEntries) {
+ final JournalEntry reversalJournalEntry = JournalEntry.createNew(journalEntry.getOffice(), journalEntry.getPaymentDetail(),
+ journalEntry.getGlAccount(), journalEntry.getCurrencyCode(), transactionId, Boolean.FALSE, transactionDate,
+ journalEntry.isDebitEntry() ? JournalEntryType.CREDIT : JournalEntryType.DEBIT, journalEntry.getAmount(),
+ journalEntry.getDescription(), journalEntry.getEntityType(), journalEntry.getEntityId(),
+ journalEntry.getReferenceNumber(), journalEntry.getLoanTransactionId(), journalEntry.getSavingsTransactionId(),
+ journalEntry.getClientTransactionId(), journalEntry.getShareTransactionId());
+ helper.persistJournalEntry(reversalJournalEntry);
+ }
+ }
+
public String revertJournalEntry(final List<JournalEntry> journalEntries, String reversalComment) {
final Long officeId = journalEntries.get(0).getOffice().getId();
final String reversalTransactionId = generateTransactionId(officeId);
diff --git a/fineract-provider/src/test/java/org/apache/fineract/accounting/journalentry/CreateJournalEntriesForChargeOffLoanTest.java b/fineract-provider/src/test/java/org/apache/fineract/accounting/journalentry/CreateJournalEntriesForChargeOffLoanTest.java
index 61960d64a5..7280364f78 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/accounting/journalentry/CreateJournalEntriesForChargeOffLoanTest.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/accounting/journalentry/CreateJournalEntriesForChargeOffLoanTest.java
@@ -99,12 +99,11 @@ class CreateJournalEntriesForChargeOffLoanTest {
verify(helper, times(1)).getChargeOffMappingByCodeValue(1L, PortfolioProductType.LOAN, chargeOffReasonId);
verify(helper, times(1)).getLinkedGLAccountForLoanProduct(1L, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(), 1L);
- verify(helper, times(1)).createCreditJournalEntryOrReversalForLoan(helper.getOfficeById(1L), "USD",
- AccrualAccountsForLoan.LOAN_PORTFOLIO, 1L, null, 1L, "txn-123", LocalDate.now(ZoneId.systemDefault()),
- new BigDecimal("500.00"), false);
- verify(helper, times(1)).createDebitJournalEntryOrReversalForLoan(helper.getOfficeById(1L), "USD",
+ verify(helper, times(1)).createCreditJournalEntryForLoan(helper.getOfficeById(1L), "USD", AccrualAccountsForLoan.LOAN_PORTFOLIO, 1L,
+ null, 1L, "txn-123", LocalDate.now(ZoneId.systemDefault()), new BigDecimal("500.00"));
+ verify(helper, times(1)).createDebitJournalEntryForLoan(helper.getOfficeById(1L), "USD",
AccrualAccountsForLoan.CHARGE_OFF_EXPENSE.getValue(), 1L, null, 1L, "txn-123", LocalDate.now(ZoneId.systemDefault()),
- new BigDecimal("500.00"), false);
+ new BigDecimal("500.00"));
}
@Test