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 f3606bb2d1 FINERACT-2225: Save journal entries for accrual transaction
created by charge adjustment
f3606bb2d1 is described below
commit f3606bb2d1e08b52e56ceafe0e50f22d2742b7d7
Author: Oleksii Novikov <[email protected]>
AuthorDate: Thu Mar 27 12:04:20 2025 +0200
FINERACT-2225: Save journal entries for accrual transaction created by
charge adjustment
---
.../src/test/resources/features/LoanCharge.feature | 25 ++++++++++++++++++++++
.../service/LoanAccrualsProcessingService.java | 3 ++-
.../service/LoanAccrualEventService.java | 16 ++++++++++++--
.../service/LoanAccrualsProcessingServiceImpl.java | 5 +++--
4 files changed, 44 insertions(+), 5 deletions(-)
diff --git
a/fineract-e2e-tests-runner/src/test/resources/features/LoanCharge.feature
b/fineract-e2e-tests-runner/src/test/resources/features/LoanCharge.feature
index a7a0ddf2c4..dc53816649 100644
--- a/fineract-e2e-tests-runner/src/test/resources/features/LoanCharge.feature
+++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanCharge.feature
@@ -2722,3 +2722,28 @@ Feature: LoanCharge
| 01 March 2024 | Accrual | 1.16 | 0.0 | 1.16 |
0.0 | 0.0 | 0.0 | false | false |
| 01 March 2024 | Charge-off | 107.14 | 100.0 | 2.14 |
5.0 | 0.0 | 0.0 | false | false |
| 01 March 2024 | Charge Adjustment | 5.0 | 5.0 | 0.0 |
0.0 | 0.0 | 95.0 | false | false |
+
+ @TestRailId:C3571
+ Scenario: Charge adjustment on account with zero principal balance should
not create accrual transactions without journal entries
+ When Admin sets the business date to "25 March 2025"
+ When Admin creates a client with random data
+ And Admin successfully creates a new customised Loan submitted on date:
"25 March 2025", with Principal: "800", a loanTermFrequency: 1 months, and
numberOfRepayments: 1
+ And Admin successfully approves the loan on "25 March 2025" with "800"
amount and expected disbursement date on "25 March 2025"
+ When Admin successfully disburse the loan on "25 March 2025" with "800"
EUR transaction amount
+ And Customer makes "AUTOPAY" repayment on "25 March 2025" with 800 EUR
transaction amount
+ And Admin adds an NSF fee because of payment bounce with "25 March 2025"
transaction date
+ When Admin makes a charge adjustment for the last "LOAN_NSF_FEE" type
charge which is due on "25 March 2025" with 10 EUR transaction amount and
externalId ""
+ Then Loan Transactions tab has a "CHARGE_ADJUSTMENT" transaction with date
"25 March 2025" which has the following Journal entries:
+ | Type | Account code | Account name | Debit | Credit |
+ | ASSET | 112601 | Loans Receivable | | 10.0 |
+ | INCOME | 404007 | Fee Income | 10.0 | |
+ Then Loan Transactions tab has the following data:
+ | Transaction date | Transaction Type | Amount | Principal | Interest |
Fees | Penalties | Loan Balance |
+ | 25 March 2025 | Disbursement | 800.0 | 0.0 | 0.0 |
0.0 | 0.0 | 800.0 |
+ | 25 March 2025 | Repayment | 800.0 | 790.0 | 0.0 |
0.0 | 10.0 | 10.0 |
+ | 25 March 2025 | Charge Adjustment | 10.0 | 10.0 | 0.0 |
0.0 | 0.0 | 0.0 |
+ | 25 March 2025 | Accrual | 10.0 | 0.0 | 0.0 |
0.0 | 10.0 | 0.0 |
+ Then Loan Transactions tab has a "ACCRUAL" transaction with date "25 March
2025" which has the following Journal entries:
+ | Type | Account code | Account name | Debit | Credit |
+ | ASSET | 112603 | Interest/Fee Receivable | 10.0 | |
+ | INCOME | 404007 | Fee Income | | 10.0 |
\ No newline at end of file
diff --git
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingService.java
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingService.java
index 297774a04f..ef944e9fe7 100644
---
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingService.java
+++
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingService.java
@@ -24,6 +24,7 @@ import java.util.List;
import org.apache.fineract.infrastructure.core.exception.MultiException;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
+import org.springframework.lang.NonNull;
public interface LoanAccrualsProcessingService {
@@ -41,7 +42,7 @@ public interface LoanAccrualsProcessingService {
void processIncomePostingAndAccruals(@NotNull Loan loan);
- void processAccrualsOnLoanClosure(@NotNull Loan loan);
+ void processAccrualsOnLoanClosure(@NonNull Loan loan, boolean addJournal);
void processAccrualsOnLoanForeClosure(@NotNull Loan loan, @NotNull
LocalDate foreClosureDate,
@NotNull List<LoanTransaction> newAccrualTransactions);
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualEventService.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualEventService.java
index 9697a56d08..c48dd9f089 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualEventService.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualEventService.java
@@ -19,6 +19,7 @@
package org.apache.fineract.portfolio.loanaccount.service;
import jakarta.annotation.PostConstruct;
+import java.util.Objects;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.event.business.BusinessEventListener;
@@ -27,6 +28,7 @@ import
org.apache.fineract.infrastructure.event.business.domain.loan.LoanCloseBu
import
org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
+import
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelationTypeEnum;
@Slf4j
@RequiredArgsConstructor
@@ -50,7 +52,7 @@ public class LoanAccrualEventService {
LoanStatus status = loan.getStatus();
if (status.isClosedObligationsMet() || status.isOverpaid()) {
log.debug("Loan closure on accrual for loan {}", loan.getId());
-
loanAccrualsProcessingService.processAccrualsOnLoanClosure(loan);
+
loanAccrualsProcessingService.processAccrualsOnLoanClosure(loan, false);
loanAccrualActivityProcessingService.processAccrualActivityForLoanClosure(loan);
}
}
@@ -64,9 +66,19 @@ public class LoanAccrualEventService {
LoanStatus status = loan.getStatus();
if (status.isClosedObligationsMet() || status.isOverpaid()) {
log.debug("Loan balance change on accrual for loan {}",
loan.getId());
-
loanAccrualsProcessingService.processAccrualsOnLoanClosure(loan);
+ final boolean hasChargeAdjustment = hasChargeAdjustment(loan);
+
loanAccrualsProcessingService.processAccrualsOnLoanClosure(loan,
hasChargeAdjustment);
loanAccrualActivityProcessingService.processAccrualActivityForLoanClosure(loan);
}
}
+
+ private boolean hasChargeAdjustment(final Loan loan) {
+ return loan.getLoanTransactions().stream()
+ .filter(transaction -> transaction.isChargeAdjustment() &&
transaction.isNotReversed())
+ .anyMatch(chargeAdjustment ->
chargeAdjustment.getLoanTransactionRelations().stream()
+ .anyMatch(relation -> relation.getRelationType()
== LoanTransactionRelationTypeEnum.CHARGE_ADJUSTMENT
+ && relation.getFromTransaction() != null
+ &&
Objects.equals(relation.getFromTransaction().getId(),
chargeAdjustment.getId())));
+ }
}
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java
index 2e566a4b57..13d3259637 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java
@@ -83,6 +83,7 @@ import
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanSchedul
import
org.apache.fineract.portfolio.loanproduct.domain.InterestRecalculationCompoundingMethod;
import
org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.lang.NonNull;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@@ -284,9 +285,9 @@ public class LoanAccrualsProcessingServiceImpl implements
LoanAccrualsProcessing
* method calculates accruals for loan on loan closure
*/
@Override
- public void processAccrualsOnLoanClosure(@NotNull Loan loan) {
+ public void processAccrualsOnLoanClosure(@NonNull final Loan loan, final
boolean addJournal) {
// check and process accruals for loan WITHOUT interest recalculation
details and compounding posted as income
- addAccruals(loan,
loan.getLastLoanRepaymentScheduleInstallment().getDueDate(), false, true,
false);
+ addAccruals(loan,
loan.getLastLoanRepaymentScheduleInstallment().getDueDate(), false, true,
addJournal);
if (isProgressiveAccrual(loan)) {
return;
}