FINERACT-2042: Fix chargeback on overpaid loan
diff --git a/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeback.feature b/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeback.feature
index 8448fa1..140dc06 100644
--- a/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeback.feature
+++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeback.feature
@@ -2160,8 +2160,8 @@
| | | 01 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 0 | 01 January 2024 | 04 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 125.0 | 0.0 |
| 2 | 15 | 16 January 2024 | 16 January 2024 | 250.0 | 125.0 | 0.0 | 0.0 | 3.0 | 128.0 | 128.0 | 0.0 | 0.0 | 0.0 |
- | 3 | 15 | 31 January 2024 | 31 January 2024 | 128.0 | 250.0 | 0.0 | 0.0 | 3.0 | 253.0 | 253.0 | 0.0 | 0.0 | 0.0 |
- | 4 | 15 | 15 February 2024 | 15 February 2024 | 3.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
+ | 3 | 15 | 31 January 2024 | 31 January 2024 | 125.0 | 250.0 | 0.0 | 0.0 | 3.0 | 253.0 | 253.0 | 0.0 | 0.0 | 0.0 |
+ | 4 | 15 | 15 February 2024 | 15 February 2024 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 625.0 | 0.0 | 0.0 | 6.0 | 631.0 | 631.0 | 0.0 | 125.0 | 0.0 |
@@ -2200,8 +2200,8 @@
| | | 01 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 0 | 01 January 2024 | 04 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 125.0 | 0.0 |
| 2 | 15 | 16 January 2024 | 16 January 2024 | 250.0 | 125.0 | 0.0 | 0.0 | 3.0 | 128.0 | 128.0 | 0.0 | 0.0 | 0.0 |
- | 3 | 15 | 31 January 2024 | 15 February 2024 | 128.0 | 175.0 | 0.0 | 0.0 | 3.0 | 178.0 | 178.0 | 0.0 | 3.0 | 0.0 |
- | 4 | 15 | 15 February 2024 | 15 February 2024 | 3.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
+ | 3 | 15 | 31 January 2024 | 15 February 2024 | 125.0 | 175.0 | 0.0 | 0.0 | 3.0 | 178.0 | 178.0 | 0.0 | 3.0 | 0.0 |
+ | 4 | 15 | 15 February 2024 | 15 February 2024 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 550.0 | 0.0 | 0.0 | 6.0 | 556.0 | 556.0 | 0.0 | 128.0 | 0.0 |
@@ -2242,8 +2242,8 @@
| | | 01 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 0 | 01 January 2024 | 04 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 125.0 | 0.0 |
| 2 | 15 | 16 January 2024 | 31 January 2024 | 250.0 | 125.0 | 0.0 | 4.0 | 3.0 | 132.0 | 132.0 | 0.0 | 7.0 | 0.0 |
- | 3 | 15 | 31 January 2024 | 15 February 2024 | 132.0 | 168.0 | 0.0 | 4.0 | 3.0 | 175.0 | 175.0 | 0.0 | 57.0 | 0.0 |
- | 4 | 15 | 15 February 2024 | 15 February 2024 | 7.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
+ | 3 | 15 | 31 January 2024 | 15 February 2024 | 125.0 | 168.0 | 0.0 | 4.0 | 3.0 | 175.0 | 175.0 | 0.0 | 57.0 | 0.0 |
+ | 4 | 15 | 15 February 2024 | 15 February 2024 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 543.0 | 0.0 | 8.0 | 6.0 | 557.0 | 557.0 | 0.0 | 189.0 | 0.0 |
@@ -2844,3 +2844,131 @@
| LIABILITY | 145023 | Suspense/Clearing account | | 280.0 |
| EXPENSE | 744007 | Credit Loss/Bad Debt | 250.0 | |
| INCOME | 404008 | Fee Charge Off | 30.0 | |
+
+ @TestRailId:C3111 @creditAllocation @AdvancedPaymentAllocationChargeback @AdvancedPaymentAllocation
+ Scenario: Verify chargeback function for advanced payment allocation - credit allocation accounting entries UC10: chargeback on overpaid loan
+ When Admin sets the business date to "01 January 2024"
+ When Admin creates a client with random data
+ When 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 |
+ | PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROG_SCHEDULE_HOR_INST_LVL_DELINQUENCY_CREDIT_ALLOCATION | 01 January 2024 | 100 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
+ And Admin successfully approves the loan on "01 January 2024" with "100" amount and expected disbursement date on "01 January 2024"
+ When Admin successfully disburse the loan on "01 January 2024" with "100" EUR transaction amount
+ Then Loan Repayment schedule has 4 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 | 0 | 01 January 2024 | | 75.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 |
+ | 2 | 31 | 01 February 2024 | | 50.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 |
+ | 3 | 29 | 01 March 2024 | | 25.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 |
+ | 4 | 31 | 01 April 2024 | | 0.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 |
+ Then Loan Transactions tab has the following data:
+ | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
+ | 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 |
+ When Admin adds "LOAN_NSF_FEE" due date charge with "05 January 2024" due date and 5 EUR transaction amount
+ Then Loan Repayment schedule has 4 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 | 0 | 01 January 2024 | | 75.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 |
+ | 2 | 31 | 01 February 2024 | | 50.0 | 25.0 | 0.0 | 0.0 | 5.0 | 30.0 | 0.0 | 0.0 | 0.0 | 30.0 |
+ | 3 | 29 | 01 March 2024 | | 25.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 |
+ | 4 | 31 | 01 April 2024 | | 0.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 |
+ Then Loan Transactions tab has the following data:
+ | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
+ | 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 |
+ When Admin sets the business date to "01 February 2024"
+ And Customer makes "AUTOPAY" repayment on "01 February 2024" with 105 EUR transaction amount
+ Then Loan Repayment schedule has 4 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 | 0 | 01 January 2024 | 01 February 2024 | 75.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 25.0 | 0.0 | 25.0 | 0.0 |
+ | 2 | 31 | 01 February 2024 | 01 February 2024 | 50.0 | 25.0 | 0.0 | 0.0 | 5.0 | 30.0 | 30.0 | 0.0 | 0.0 | 0.0 |
+ | 3 | 29 | 01 March 2024 | 01 February 2024 | 25.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 25.0 | 25.0 | 0.0 | 0.0 |
+ | 4 | 31 | 01 April 2024 | 01 February 2024 | 0.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 25.0 | 25.0 | 0.0 | 0.0 |
+ Then Loan Transactions tab has the following data:
+ | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
+ | 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 |
+ | 01 February 2024 | Repayment | 105.0 | 100.0 | 0.0 | 0.0 | 5.0 | 0.0 |
+ | 01 February 2024 | Accrual | 5.0 | 0.0 | 0.0 | 0.0 | 5.0 | 0.0 |
+ Then Loan has 0 outstanding amount
+ Then Loan status will be "CLOSED_OBLIGATIONS_MET"
+ When Admin sets the business date to "01 March 2024"
+ When Admin makes "MERCHANT_ISSUED_REFUND" transaction with "AUTOPAY" payment type on "19 January 2024" with 10 EUR transaction amount
+ Then Loan Repayment schedule has 4 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 | 0 | 01 January 2024 | 01 February 2024 | 75.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 25.0 | 0.0 | 25.0 | 0.0 |
+ | 2 | 31 | 01 February 2024 | 01 February 2024 | 50.0 | 25.0 | 0.0 | 0.0 | 5.0 | 30.0 | 30.0 | 0.0 | 0.0 | 0.0 |
+ | 3 | 29 | 01 March 2024 | 01 February 2024 | 25.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 25.0 | 25.0 | 0.0 | 0.0 |
+ | 4 | 31 | 01 April 2024 | 01 February 2024 | 0.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 25.0 | 25.0 | 0.0 | 0.0 |
+ Then Loan Transactions tab has the following data:
+ | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Overpayment |
+ | 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | 0.0 |
+ | 19 January 2024 | Merchant Issued Refund | 10.0 | 10.0 | 0.0 | 0.0 | 0.0 | 90.0 | 0.0 |
+ | 01 February 2024 | Repayment | 105.0 | 90.0 | 0.0 | 0.0 | 5.0 | 0.0 | 10.0 |
+ | 01 February 2024 | Accrual | 5.0 | 0.0 | 0.0 | 0.0 | 5.0 | 0.0 | 0.0 |
+ Then Loan has 0 outstanding amount
+ Then Loan has 10 overpaid amount
+ Then Loan status will be "OVERPAID"
+ When Admin sets the business date to "15 April 2024"
+ And Admin makes "REPAYMENT_ADJUSTMENT_CHARGEBACK" chargeback with 7 EUR transaction amount for Payment nr. 1
+ Then Loan Transactions tab has a "DISBURSEMENT" transaction with date "01 January 2024" which has the following Journal entries:
+ | Type | Account code | Account name | Debit | Credit |
+ | ASSET | 112601 | Loans Receivable | 100.0 | |
+ | LIABILITY | 145023 | Suspense/Clearing account | | 100.0 |
+ Then Loan Transactions tab has a "MERCHANT_ISSUED_REFUND" transaction with date "19 January 2024" which has the following Journal entries:
+ | Type | Account code | Account name | Debit | Credit |
+ | ASSET | 112601 | Loans Receivable | | 10.0 |
+ | LIABILITY | 145023 | Suspense/Clearing account | 10.0 | |
+ Then Loan Transactions tab has a "REPAYMENT" transaction with date "01 February 2024" which has the following Journal entries:
+ | Type | Account code | Account name | Debit | Credit |
+ | ASSET | 112601 | Loans Receivable | | 90.0 |
+ | ASSET | 112603 | Interest/Fee Receivable | | 5.0 |
+ | LIABILITY | l1 | Overpayment account | | 10.0 |
+ | LIABILITY | 145023 | Suspense/Clearing account | 105.0 | |
+ Then Loan Repayment schedule has 5 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 | 0 | 01 January 2024 | 01 February 2024 | 75.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 25.0 | 0.0 | 25.0 | 0.0 |
+ | 2 | 31 | 01 February 2024 | 01 February 2024 | 50.0 | 25.0 | 0.0 | 0.0 | 5.0 | 30.0 | 30.0 | 0.0 | 0.0 | 0.0 |
+ | 3 | 29 | 01 March 2024 | 01 February 2024 | 25.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 25.0 | 25.0 | 0.0 | 0.0 |
+ | 4 | 31 | 01 April 2024 | 01 February 2024 | 0.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 25.0 | 25.0 | 0.0 | 0.0 |
+ | 5 | 14 | 15 April 2024 | 15 April 2024 | 0.0 | 2.0 | 0.0 | 0.0 | 5.0 | 7.0 | 7.0 | 0.0 | 0.0 | 0.0 |
+ Then Loan Transactions tab has the following data:
+ | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Overpayment |
+ | 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | 0.0 |
+ | 19 January 2024 | Merchant Issued Refund | 10.0 | 10.0 | 0.0 | 0.0 | 0.0 | 90.0 | 0.0 |
+ | 01 February 2024 | Repayment | 105.0 | 90.0 | 0.0 | 0.0 | 5.0 | 0.0 | 10.0 |
+ | 01 February 2024 | Accrual | 5.0 | 0.0 | 0.0 | 0.0 | 5.0 | 0.0 | 0.0 |
+ | 15 April 2024 | Chargeback | 7.0 | 2.0 | 0.0 | 0.0 | 5.0 | 0.0 | 7.0 |
+ Then Loan Transactions tab has a "CHARGEBACK" transaction with date "15 April 2024" which has the following Journal entries:
+ | Type | Account code | Account name | Debit | Credit |
+ | LIABILITY | l1 | Overpayment account | 7.0 | |
+ | LIABILITY | 145023 | Suspense/Clearing account | | 7.0 |
+ Then Loan has 0 outstanding amount
+ Then Loan has 3 overpaid amount
+ Then Loan status will be "OVERPAID"
+ When Admin sets the business date to "16 April 2024"
+ When Admin makes "REPAYMENT_ADJUSTMENT_REFUND" chargeback with 7 EUR transaction amount for Payment nr. 1
+ Then Loan Repayment schedule has 5 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 | 0 | 01 January 2024 | 01 February 2024 | 75.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 25.0 | 0.0 | 25.0 | 0.0 |
+ | 2 | 31 | 01 February 2024 | 01 February 2024 | 50.0 | 25.0 | 0.0 | 0.0 | 5.0 | 30.0 | 30.0 | 0.0 | 0.0 | 0.0 |
+ | 3 | 29 | 01 March 2024 | 01 February 2024 | 25.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 25.0 | 25.0 | 0.0 | 0.0 |
+ | 4 | 31 | 01 April 2024 | 01 February 2024 | 0.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 25.0 | 25.0 | 0.0 | 0.0 |
+ | 5 | 15 | 16 April 2024 | | 0.0 | 9.0 | 0.0 | 0.0 | 5.0 | 14.0 | 10.0 | 0.0 | 0.0 | 4.0 |
+ Then Loan Transactions tab has the following data:
+ | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Overpayment |
+ | 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | 0.0 |
+ | 19 January 2024 | Merchant Issued Refund | 10.0 | 10.0 | 0.0 | 0.0 | 0.0 | 90.0 | 0.0 |
+ | 01 February 2024 | Repayment | 105.0 | 90.0 | 0.0 | 0.0 | 5.0 | 0.0 | 10.0 |
+ | 01 February 2024 | Accrual | 5.0 | 0.0 | 0.0 | 0.0 | 5.0 | 0.0 | 0.0 |
+ | 15 April 2024 | Chargeback | 7.0 | 2.0 | 0.0 | 0.0 | 5.0 | 0.0 | 7.0 |
+ | 16 April 2024 | Chargeback | 7.0 | 7.0 | 0.0 | 0.0 | 0.0 | 4.0 | 3.0 |
+ Then Loan Transactions tab has a "CHARGEBACK" transaction with date "16 April 2024" which has the following Journal entries:
+ | Type | Account code | Account name | Debit | Credit |
+ | LIABILITY | l1 | Overpayment account | 3.0 | |
+ | ASSET | 112601 | Loans Receivable | 4.0 | |
+ | LIABILITY | 145023 | Suspense/Clearing account | | 7.0 |
+ Then Loan has 4 outstanding amount
+ Then Loan status will be "ACTIVE"
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index e5266b1..6c07e94 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -134,6 +134,7 @@
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelPeriod;
import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod;
+import org.apache.fineract.portfolio.loanproduct.domain.CreditAllocationTransactionType;
import org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod;
import org.apache.fineract.portfolio.loanproduct.domain.InterestRecalculationCompoundingMethod;
@@ -712,7 +713,7 @@
ChangedTransactionDetail changedTransactionDetail = null;
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
.determineProcessor(this.transactionProcessingStrategyCode);
- final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
+ final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(getDisbursementDate(),
allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(), getActiveCharges());
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
@@ -875,7 +876,7 @@
* Consider removing this block of code or logically completing it for the future by getting the list of
* affected Transactions
***/
- final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
+ final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(getDisbursementDate(),
allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(), getActiveCharges());
}
@@ -943,7 +944,7 @@
* Consider removing this block of code or logically completing it for the future by getting the list of
* affected Transactions
***/
- final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
+ final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(getDisbursementDate(),
allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(), getActiveCharges());
} else {
@@ -1137,7 +1138,7 @@
* Consider removing this block of code or logically completing it for the future by getting the list of
* affected Transactions
*/
- final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
+ final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(getDisbursementDate(),
allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(), getActiveCharges());
} else {
@@ -2696,7 +2697,7 @@
private ChangedTransactionDetail reprocessTransactionForDisbursement() {
ChangedTransactionDetail changedTransactionDetail = null;
if (this.loanProduct.isMultiDisburseLoan()) {
- final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
+ final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
if (!allNonContraTransactionsPostDisbursement.isEmpty()) {
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
.determineProcessor(this.transactionProcessingStrategyCode);
@@ -3369,7 +3370,7 @@
if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
}
- final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
+ final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(getDisbursementDate(),
allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(), getActiveCharges());
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
@@ -3429,12 +3430,12 @@
return incomePostTransactions;
}
- private List<LoanTransaction> retrieveListOfTransactionsPostDisbursement() {
+ public List<LoanTransaction> retrieveListOfTransactionsForReprocessing() {
final List<LoanTransaction> repaymentsOrWaivers = new ArrayList<>();
List<LoanTransaction> trans = getLoanTransactions();
for (final LoanTransaction transaction : trans) {
- if (transaction.isNotReversed() && (transaction.isChargeOff() || transaction.isReAge() || transaction.isReAmortize()
- || !transaction.isNonMonetaryTransaction())) {
+ if (transaction.isNotReversed() && !transaction.isAccrual() && (transaction.isChargeOff() || transaction.isReAge()
+ || transaction.isReAmortize() || !transaction.isNonMonetaryTransaction())) {
repaymentsOrWaivers.add(transaction);
}
}
@@ -3818,7 +3819,7 @@
loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING_UNDO, this);
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
.determineProcessor(this.transactionProcessingStrategyCode);
- final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
+ final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
}
@@ -3868,10 +3869,15 @@
}
if (loanTransaction.isRefund() || loanTransaction.isRefundForActiveLoan()) {
totalPaidInRepayments = totalPaidInRepayments.minus(loanTransaction.getAmount(currency));
- } else if (loanTransaction.isCreditBalanceRefund() || loanTransaction.isChargeback()) {
+ } else if (loanTransaction.isCreditBalanceRefund()) {
if (loanTransaction.getPrincipalPortion(currency).isZero()) {
totalPaidInRepayments = totalPaidInRepayments.minus(loanTransaction.getOverPaymentPortion(currency));
}
+ } else if (loanTransaction.isChargeback()) {
+ if (loanTransaction.getPrincipalPortion(currency).isZero() && getCreditAllocationRules().stream()
+ .filter(car -> car.getTransactionType().equals(CreditAllocationTransactionType.CHARGEBACK)).findAny().isEmpty()) {
+ totalPaidInRepayments = totalPaidInRepayments.minus(loanTransaction.getOverPaymentPortion(currency));
+ }
}
}
@@ -3972,7 +3978,7 @@
if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
}
- final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
+ final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(getDisbursementDate(),
allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(), getActiveCharges());
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
@@ -5420,7 +5426,7 @@
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
.determineProcessor(this.transactionProcessingStrategyCode);
- final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
+ final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
ChangedTransactionDetail changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(
getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(),
getActiveCharges());
@@ -5574,7 +5580,7 @@
public ChangedTransactionDetail processTransactions() {
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
.determineProcessor(this.transactionProcessingStrategyCode);
- final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
+ final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
ChangedTransactionDetail changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(
getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(),
getActiveCharges());
@@ -5818,7 +5824,7 @@
public void processPostDisbursementTransactions() {
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
.determineProcessor(this.transactionProcessingStrategyCode);
- final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
+ final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
final List<LoanTransaction> copyTransactions = new ArrayList<>();
if (!allNonContraTransactionsPostDisbursement.isEmpty()) {
for (LoanTransaction loanTransaction : allNonContraTransactionsPostDisbursement) {
@@ -6428,7 +6434,7 @@
loanRepaymentScheduleTransactionProcessor.processLatestTransaction(loanTransaction, new TransactionCtx(getCurrency(),
getRepaymentScheduleInstallments(), getActiveCharges(), new MoneyHolder(getTotalOverpaidAsMoney())));
} else {
- final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
+ final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(getDisbursementDate(),
allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(), getActiveCharges());
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
index e1f12c3..2e08300 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
@@ -356,6 +356,7 @@
(ctx.getInstallments().size() + 1), pastDueDate, transactionDate, zeroMoney.getAmount(),
zeroMoney.getAmount(), zeroMoney.getAmount(), zeroMoney.getAmount(), false, null);
recognizeAmountsAfterChargeback(ctx.getCurrency(), transactionDate, installment, chargebackAllocation);
+ installment.markAsAdditional();
loan.addLoanRepaymentScheduleInstallment(installment);
}
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
index ef43af8..02f6cd7 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
@@ -1159,7 +1159,7 @@
+ " ls.fee_charges_amount as feeChargesDue, ls.fee_charges_completed_derived as feeChargesPaid, ls.fee_charges_waived_derived as feeChargesWaived, ls.fee_charges_writtenoff_derived as feeChargesWrittenOff, "
+ " ls.penalty_charges_amount as penaltyChargesDue, ls.penalty_charges_completed_derived as penaltyChargesPaid, ls.penalty_charges_waived_derived as penaltyChargesWaived, "
+ " ls.penalty_charges_writtenoff_derived as penaltyChargesWrittenOff, ls.total_paid_in_advance_derived as totalPaidInAdvanceForPeriod, "
- + " ls.total_paid_late_derived as totalPaidLateForPeriod, (coalesce(ls.credits_amount,0) + coalesce(ls.credited_fee,0) + coalesce(ls.credited_penalty,0)) as totalCredits, ls.is_down_payment isDownPayment "
+ + " ls.total_paid_late_derived as totalPaidLateForPeriod, ls.credits_amount as principalCredits, ls.credited_fee as feeCredits, ls.credited_penalty as penaltyCredits, ls.is_down_payment isDownPayment "
+ " from m_loan_repayment_schedule ls ";
}
@@ -1230,9 +1230,11 @@
disbursementChargeAmount, waivedChargeAmount, periods);
// Add the Charge back or Credits to the initial amount to avoid negative balance
- final BigDecimal credits = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "totalCredits");
-
- this.outstandingLoanPrincipalBalance = this.outstandingLoanPrincipalBalance.add(credits);
+ final BigDecimal principalCredits = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalCredits");
+ final BigDecimal feeCredits = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeCredits");
+ final BigDecimal penaltyCredits = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyCredits");
+ final BigDecimal credits = principalCredits.add(feeCredits).add(penaltyCredits);
+ this.outstandingLoanPrincipalBalance = this.outstandingLoanPrincipalBalance.add(principalCredits);
totalPrincipalDisbursed = totalPrincipalDisbursed.add(disbursedAmount);
@@ -1305,6 +1307,7 @@
totalPaidInAdvance = totalPaidInAdvance.plus(totalPaidInAdvanceForPeriod);
totalPaidLate = totalPaidLate.plus(totalPaidLateForPeriod);
totalOutstanding = totalOutstanding.plus(totalOutstandingForPeriod);
+ totalCredits = totalCredits.add(credits);
if (fromDate == null) {
fromDate = this.lastDueDate;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reaging/LoanReAgingServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reaging/LoanReAgingServiceImpl.java
index 4db6b7e..33909fa 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reaging/LoanReAgingServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reaging/LoanReAgingServiceImpl.java
@@ -44,7 +44,6 @@
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
-import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionComparator;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
import org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeParameter;
@@ -181,8 +180,7 @@
}
private void reProcessLoanTransactions(Loan loan) {
- final List<LoanTransaction> filteredTransactions = loan.getLoanTransactions().stream().filter(LoanTransaction::isNotReversed)
- .filter(t -> t.isChargeOff() || !t.isNonMonetaryTransaction()).sorted(LoanTransactionComparator.INSTANCE).toList();
+ final List<LoanTransaction> filteredTransactions = loan.retrieveListOfTransactionsForReprocessing();
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loanRepaymentScheduleTransactionProcessorFactory
.determineProcessor(loan.transactionProcessingStrategy());
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationServiceImpl.java
index b12af75..880b856 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationServiceImpl.java
@@ -22,7 +22,6 @@
import java.math.BigDecimal;
import java.time.LocalDate;
-import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
@@ -44,7 +43,6 @@
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
-import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionComparator;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
@@ -135,18 +133,11 @@
}
private void reProcessLoanTransactions(Loan loan) {
- final List<LoanTransaction> repaymentsOrWaivers = new ArrayList<>();
- List<LoanTransaction> trans = loan.getLoanTransactions();
- for (final LoanTransaction transaction : trans) {
- if (transaction.isNotReversed() && (transaction.isChargeOff() || !transaction.isNonMonetaryTransaction())) {
- repaymentsOrWaivers.add(transaction);
- }
- }
- repaymentsOrWaivers.sort(LoanTransactionComparator.INSTANCE);
+ final List<LoanTransaction> filteredTransactions = loan.retrieveListOfTransactionsForReprocessing();
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loanRepaymentScheduleTransactionProcessorFactory
.determineProcessor(loan.transactionProcessingStrategy());
- loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(loan.getDisbursementDate(), repaymentsOrWaivers,
+ loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(loan.getDisbursementDate(), filteredTransactions,
loan.getCurrency(), loan.getRepaymentScheduleInstallments(), loan.getActiveCharges());
}