From 1d1876edfd453213c3c4b217575a4c6f5299d5ec Mon Sep 17 00:00:00 2001 From: Jose Alberto Hernandez Date: Fri, 30 Jan 2026 21:58:44 -0500 Subject: [PATCH] FINERACT-2421: Disbursement charge amount incorrect calculation --- .../charge/domain/ChargeTimeType.java | 5 + .../resources/features/LoanCharge.feature | 105 ++++++++---------- .../DelinquencyReadPlatformServiceImpl.java | 2 +- .../loanaccount/data/DisbursementData.java | 5 + .../portfolio/loanaccount/domain/Loan.java | 8 +- .../domain/LoanDisbursementDetails.java | 6 +- ...oanRepaymentScheduleProcessingWrapper.java | 2 +- ...rgeRepaymentScheduleProcessingWrapper.java | 2 +- .../loanaccount/mapper/LoanMapper.java | 2 +- ...pprovedAmountWritePlatformServiceImpl.java | 2 +- .../service/LoanBalanceService.java | 2 +- .../service/LoanChargeService.java | 36 ++++-- .../domain/LoanAccountDomainServiceJpa.java | 2 +- ...cheduleCalculationPlatformServiceImpl.java | 4 +- .../LoanApprovedAmountValidatorImpl.java | 4 +- .../service/LoanChargeAssembler.java | 8 +- .../LoanChargeWritePlatformServiceImpl.java | 4 +- .../service/LoanDisbursementService.java | 13 ++- .../service/LoanReadPlatformServiceImpl.java | 15 ++- .../service/LoanRepaymentScheduleService.java | 7 +- ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- .../starter/LoanAccountConfiguration.java | 16 ++- 22 files changed, 136 insertions(+), 116 deletions(-) diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/charge/domain/ChargeTimeType.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/charge/domain/ChargeTimeType.java index d9cc7efa7..f713062c5 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/charge/domain/ChargeTimeType.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/charge/domain/ChargeTimeType.java @@ -221,4 +221,9 @@ public enum ChargeTimeType { public boolean isSharesRedeem() { return this.equals(ChargeTimeType.SHARE_REDEEM); } + + public boolean isDisbursementOrTrancheDisbursementCharge() { + return isTimeOfDisbursement() || isTrancheDisbursement(); + } + } 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 48856d17c..db82c41d2 100644 --- a/fineract-e2e-tests-runner/src/test/resources/features/LoanCharge.feature +++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanCharge.feature @@ -3590,7 +3590,6 @@ Feature: LoanCharge | Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding | | Disbursement Charge | false | Disbursement | | % Amount | 2.0 | 2.0 | 0.0 | 0.0 | - @Skip @TestRailId:C3582 Scenario: Verify amount+interest disbursement charge for tranche interest bearing progressive loan that doesn't expect tranches with full disbursement - UC8.1.5 When Admin sets the business date to "01 January 2024" @@ -3713,7 +3712,6 @@ Feature: LoanCharge | Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding | | Disbursement Charge | false | Disbursement | | % Interest | 0.04 | 0.04 | 0.0 | 0.0 | - @Skip @TestRailId:C3554 Scenario: Verify amount disbursement charge for tranche interest bearing progressive loan that expects one tranche - UC8.2.1 When Admin sets the business date to "01 January 2024" @@ -3738,7 +3736,7 @@ Feature: LoanCharge | 6 | 30 | 01 July 2024 | | 0.0 | 11.82 | 0.07 | 0.0 | 0.0 | 11.89 | 0.0 | 0.0 | 0.0 | 11.89 | Then Loan Repayment schedule has the following data in Total row: | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | - | 70.0 | 1.44 | 1.4 | 0.0 | 72.87 | 1.4 | 0.0 | 0.0 | 71.44 | + | 70.0 | 1.44 | 1.4 | 0.0 | 72.84 | 1.4 | 0.0 | 0.0 | 71.44 | Then Loan Transactions tab has the following data: | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | | 01 January 2024 | Disbursement | 70.0 | 0.0 | 0.0 | 0.0 | 0.0 | 70.0 | false | false | @@ -3756,23 +3754,22 @@ Feature: LoanCharge And Customer makes "AUTOPAY" repayment on "01 February 2024" with 11.91 EUR transaction amount 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 | | 70.0 | | | 1.43 | | 1.4 | 1.4 | | | | + | | | 01 January 2024 | | 70.0 | | | 1.4 | | 1.4 | 1.4 | | | | | 1 | 31 | 01 February 2024 | 01 February 2024 | 58.5 | 11.5 | 0.41 | 0.0 | 0.0 | 11.91 | 11.91 | 0.0 | 0.0 | 0.0 | | 2 | 29 | 01 March 2024 | | 46.93 | 11.57 | 0.34 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | - | 3 | 31 | 01 April 2024 | | 35.29 | 11.67 | 0.27 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | + | 3 | 31 | 01 April 2024 | | 35.29 | 11.64 | 0.27 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | | 4 | 30 | 01 May 2024 | | 23.59 | 11.7 | 0.21 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | | 5 | 31 | 01 June 2024 | | 11.82 | 11.77 | 0.14 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | | 6 | 30 | 01 July 2024 | | 0.0 | 11.82 | 0.07 | 0.0 | 0.0 | 11.89 | 0.0 | 0.0 | 0.0 | 11.89 | Then Loan Repayment schedule has the following data in Total row: | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | - | 100.0 | 1.44 | 1.4 | 0.0 | 72.84 | 13.31 | 0.0 | 0.0 | 59.53 | + | 70.0 | 1.44 | 1.4 | 0.0 | 72.84 | 13.31 | 0.0 | 0.0 | 59.53 | Then Loan Transactions tab has the following data: | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | | 01 January 2024 | Disbursement | 70.0 | 0.0 | 0.0 | 0.0 | 0.0 | 70.0 | false | false | | 01 January 2024 | Repayment (at time of disbursement) | 1.4 | 0.0 | 0.0 | 1.4 | 0.0 | 70.0 | false | false | | 01 February 2024 | Repayment | 11.91 | 11.5 | 0.41 | 0.0 | 0.0 | 58.5 | false | false | - @Skip @TestRailId:C3555 Scenario: Verify amount disbursement charge for tranche interest bearing progressive loan that expects two tranches with undo last disbursement - UC8.2.2 When Admin sets the business date to "01 January 2024" @@ -3783,60 +3780,60 @@ Feature: LoanCharge | LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALC_DAILY_MULTIDISBURSE_EXPECT_TRANCHE | 01 January 2024 | 100 | 7 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION | LOAN_DISBURSEMENT_CHARGE | 2 | 01 January 2024 | 70.0 | 01 February 2024 | 30.0 | Then Loan Charges tab has the following data: | Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding | - | Disbursement Charge | false | Disbursement | | % Amount | 2.0 | 0.0 | 0.0 | 2.0 | + | Disbursement Charge | false | Disbursement | | % Amount | 1.4 | 0.0 | 0.0 | 1.4 | 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 "70" EUR transaction amount 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 | | 70.0 | | | 2.0 | | 2.0 | 2.0 | | | | + | | | 01 January 2024 | | 70.0 | | | 1.4 | | 1.4 | 1.4 | | | | | 1 | 31 | 01 February 2024 | | 58.5 | 11.5 | 0.41 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | - | | | 01 February 2024 | | 30.0 | | | 0.0 | | 0.0 | 0.0 | | | | - | 2 | 29 | 01 March 2024 | | 46.93 | 11.57 | 0.34 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | - | 3 | 31 | 01 April 2024 | | 35.29 | 11.64 | 0.27 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | - | 4 | 30 | 01 May 2024 | | 23.59 | 11.7 | 0.21 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | - | 5 | 31 | 01 June 2024 | | 11.82 | 11.77 | 0.14 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | - | 6 | 30 | 01 July 2024 | | 0.0 | 11.82 | 0.07 | 0.0 | 0.0 | 11.89 | 0.0 | 0.0 | 0.0 | 11.89 | + | | | 01 February 2024 | | 30.0 | | | 0.0 | | 0.0 | | | | 0.0 | + | 2 | 29 | 01 March 2024 | | 76.93 | 11.57 | 0.34 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | + | 3 | 31 | 01 April 2024 | | 65.29 | 11.64 | 0.27 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | + | 4 | 30 | 01 May 2024 | | 53.59 | 11.7 | 0.21 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | + | 5 | 31 | 01 June 2024 | | 41.82 | 11.77 | 0.14 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | + | 6 | 30 | 01 July 2024 | | 30.0 | 11.82 | 0.07 | 0.0 | 0.0 | 11.89 | 0.0 | 0.0 | 0.0 | 11.89 | Then Loan Repayment schedule has the following data in Total row: | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | - | 70.0 | 1.44 | 2.0 | 0.0 | 73.44 | 2.0 | 0.0 | 0.0 | 71.44 | + | 70.0 | 1.44 | 1.4 | 0.0 | 72.84 | 1.4 | 0.0 | 0.0 | 71.44 | Then Loan Transactions tab has the following data: | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | | 01 January 2024 | Disbursement | 70.0 | 0.0 | 0.0 | 0.0 | 0.0 | 70.0 | false | false | - | 01 January 2024 | Repayment (at time of disbursement) | 2.0 | 0.0 | 0.0 | 2.0 | 0.0 | 70.0 | false | false | + | 01 January 2024 | Repayment (at time of disbursement) | 1.4 | 0.0 | 0.0 | 1.4 | 0.0 | 70.0 | false | false | Then Loan Charges tab has the following data: - | Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding | - | Disbursement Charge | false | Disbursement | | % Loan Amount + Interest | 2.0 | 2.0 | 0.0 | 0.0 | + | Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding | + | Disbursement Charge | false | Disbursement | | % Amount | 1.4 | 1.4 | 0.0 | 0.0 | # -- REPAYMENT_AT_DISBURSEMENT journal entries ---- Then Loan Transactions tab has a "REPAYMENT_AT_DISBURSEMENT" transaction with date "01 January 2024" which has the following Journal entries: | Type | Account code | Account name | Debit | Credit | - | INCOME | 404007 | Fee Income | | 2.0 | - | LIABILITY | 145023 | Suspense/Clearing account | 2.0 | | + | INCOME | 404007 | Fee Income | | 1.4 | + | LIABILITY | 145023 | Suspense/Clearing account | 1.4 | | # --- 1st repayment - 1 February, 2024 --- When Admin sets the business date to "01 February 2024" And Customer makes "AUTOPAY" repayment on "01 February 2024" with 11.91 EUR transaction amount 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 | | 70.0 | | | 2.0 | | 2.0 | 2.0 | | | | + | | | 01 January 2024 | | 70.0 | | | 1.4 | | 1.4 | 1.4 | | | | | 1 | 31 | 01 February 2024 | 01 February 2024 | 58.5 | 11.5 | 0.41 | 0.0 | 0.0 | 11.91 | 11.91 | 0.0 | 0.0 | 0.0 | - | | | 01 February 2024 | | 30.0 | | | 0.0 | | 0.0 | 0.0 | | | | + | | | 01 February 2024 | | 30.0 | | | 0.0 | | 0.0 | | | | 0.0 | | 2 | 29 | 01 March 2024 | | 76.93 | 11.57 | 0.34 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | - | 3 | 31 | 01 April 2024 | | 65.29 | 11.67 | 0.27 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | + | 3 | 31 | 01 April 2024 | | 65.29 | 11.64 | 0.27 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | | 4 | 30 | 01 May 2024 | | 53.59 | 11.7 | 0.21 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | | 5 | 31 | 01 June 2024 | | 41.82 | 11.77 | 0.14 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | | 6 | 30 | 01 July 2024 | | 30.0 | 11.82 | 0.07 | 0.0 | 0.0 | 11.89 | 0.0 | 0.0 | 0.0 | 11.89 | Then Loan Repayment schedule has the following data in Total row: | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | - | 70.0 | 1.44 | 2.0 | 0.0 | 72.84 | 13.91 | 0.0 | 0.0 | 59.53 | + | 70.0 | 1.44 | 1.4 | 0.0 | 72.84 | 13.31 | 0.0 | 0.0 | 59.53 | Then Loan Transactions tab has the following data: | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | | 01 January 2024 | Disbursement | 70.0 | 0.0 | 0.0 | 0.0 | 0.0 | 70.0 | false | false | - | 01 January 2024 | Repayment (at time of disbursement) | 2.0 | 0.0 | 0.0 | 2.0 | 0.0 | 70.0 | false | false | + | 01 January 2024 | Repayment (at time of disbursement) | 1.4 | 0.0 | 0.0 | 1.4 | 0.0 | 70.0 | false | false | | 01 February 2024 | Repayment | 11.91 | 11.5 | 0.41 | 0.0 | 0.0 | 58.5 | false | false | # --- 2nd disbursement - 1 February, 2024 --- When Admin successfully disburse the loan on "01 February 2024" with "30" EUR transaction amount 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 | | 70.0 | | | 2.0 | | 2.0 | 2.0 | | | | + | | | 01 January 2024 | | 70.0 | | | 1.4 | | 1.4 | 1.4 | | | | | 1 | 31 | 01 February 2024 | 01 February 2024 | 58.5 | 11.5 | 0.41 | 0.0 | 0.0 | 11.91 | 11.91 | 0.0 | 0.0 | 0.0 | | | | 01 February 2024 | | 30.0 | | | 0.0 | | 0.0 | 0.0 | | | | | 2 | 29 | 01 March 2024 | | 71.01 | 17.49 | 0.52 | 0.0 | 0.0 | 18.01 | 0.0 | 0.0 | 0.0 | 18.01 | @@ -3846,32 +3843,31 @@ Feature: LoanCharge | 6 | 30 | 01 July 2024 | | 0.0 | 17.91 | 0.1 | 0.0 | 0.0 | 18.01 | 0.0 | 0.0 | 0.0 | 18.01 | Then Loan Repayment schedule has the following data in Total row: | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | - | 100.0 | 1.96 | 2.0 | 0.0 | 103.96 | 13.91 | 0.0 | 0.0 | 90.05 | + | 100.0 | 1.96 | 1.4 | 0.0 | 103.36 | 13.31 | 0.0 | 0.0 | 90.05 | Then Loan Transactions tab has the following data: | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | | 01 January 2024 | Disbursement | 70.0 | 0.0 | 0.0 | 0.0 | 0.0 | 70.0 | false | false | - | 01 January 2024 | Repayment (at time of disbursement) | 2.0 | 0.0 | 0.0 | 2.0 | 0.0 | 70.0 | false | false | + | 01 January 2024 | Repayment (at time of disbursement) | 1.4 | 0.0 | 0.0 | 1.4 | 0.0 | 70.0 | false | false | | 01 February 2024 | Repayment | 11.91 | 11.5 | 0.41 | 0.0 | 0.0 | 58.5 | false | false | - | 15 February 2024 | Disbursement | 30.0 | 0.0 | 0.0 | 0.0 | 0.0 | 88.5 | false | false | + | 01 February 2024 | Disbursement | 30.0 | 0.0 | 0.0 | 0.0 | 0.0 | 88.5 | false | false | # -- undo last disbursement ---- When Admin successfully undo last disbursal - Then Loan status has changed to "Active" 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 | | 70.0 | | | 2.0 | | 2.0 | 2.0 | | | | + | | | 01 January 2024 | | 70.0 | | | 1.4 | | 1.4 | 1.4 | | | | | 1 | 31 | 01 February 2024 | 01 February 2024 | 58.5 | 11.5 | 0.41 | 0.0 | 0.0 | 11.91 | 11.91 | 0.0 | 0.0 | 0.0 | | 2 | 29 | 01 March 2024 | | 46.93 | 11.57 | 0.34 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | - | 3 | 31 | 01 April 2024 | | 35.29 | 11.67 | 0.27 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | + | 3 | 31 | 01 April 2024 | | 35.29 | 11.64 | 0.27 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | | 4 | 30 | 01 May 2024 | | 23.59 | 11.7 | 0.21 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | | 5 | 31 | 01 June 2024 | | 11.82 | 11.77 | 0.14 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | | 6 | 30 | 01 July 2024 | | 0.0 | 11.82 | 0.07 | 0.0 | 0.0 | 11.89 | 0.0 | 0.0 | 0.0 | 11.89 | Then Loan Repayment schedule has the following data in Total row: | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | - | 100.0 | 1.44 | 2.0 | 0.0 | 73.44 | 13.91 | 0.0 | 0.0 | 59.53 | + | 70.0 | 1.44 | 1.4 | 0.0 | 72.84 | 13.31 | 0.0 | 0.0 | 59.53 | Then Loan Transactions tab has the following data: | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | | 01 January 2024 | Disbursement | 70.0 | 0.0 | 0.0 | 0.0 | 0.0 | 70.0 | false | false | - | 01 January 2024 | Repayment (at time of disbursement) | 2.0 | 0.0 | 0.0 | 2.0 | 0.0 | 70.0 | false | false | + | 01 January 2024 | Repayment (at time of disbursement) | 1.4 | 0.0 | 0.0 | 1.4 | 0.0 | 70.0 | false | false | | 01 February 2024 | Repayment | 11.91 | 11.5 | 0.41 | 0.0 | 0.0 | 58.5 | false | false | @Skip @@ -4034,7 +4030,6 @@ Feature: LoanCharge | 01 January 2024 | Repayment (at time of disbursement) | 1.43 | 0.0 | 0.0 | 1.43 | 0.0 | 70.0 | false | false | | 01 February 2024 | Repayment | 11.91 | 11.5 | 0.41 | 0.0 | 0.0 | 58.5 | false | false | - @Skip @TestRailId:C3558 Scenario: Verify interest disbursement charge for tranche interest bearing progressive loan that expects one tranche with undo disbursement - UC8.2.5 When Admin sets the business date to "01 January 2024" @@ -4097,22 +4092,21 @@ Feature: LoanCharge Then Loan status has changed to "Approved" 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.04 | | 0.04 | | | | 0.02 | - | 1 | 31 | 01 February 2024 | | 83.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 2 | 29 | 01 March 2024 | | 67.05 | 16.52 | 0.49 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 3 | 31 | 01 April 2024 | | 50.43 | 16.62 | 0.39 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 4 | 30 | 01 May 2024 | | 33.71 | 16.72 | 0.29 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 5 | 31 | 01 June 2024 | | 16.9 | 16.81 | 0.2 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 6 | 30 | 01 July 2024 | | 0.0 | 16.9 | 0.1 | 0.0 | 0.0 | 17.0 | 0.0 | 0.0 | 0.0 | 17.0 | + | | | 01 January 2024 | | 70.0 | | | 0.03 | | 0.03 | | | | 0.03 | + | 1 | 31 | 01 February 2024 | | 58.5 | 11.5 | 0.41 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | + | 2 | 29 | 01 March 2024 | | 46.93 | 11.57 | 0.34 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | + | 3 | 31 | 01 April 2024 | | 35.29 | 11.64 | 0.27 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | + | 4 | 30 | 01 May 2024 | | 23.59 | 11.7 | 0.21 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | + | 5 | 31 | 01 June 2024 | | 11.82 | 11.77 | 0.14 | 0.0 | 0.0 | 11.91 | 0.0 | 0.0 | 0.0 | 11.91 | + | 6 | 30 | 01 July 2024 | | 0.0 | 11.82 | 0.07 | 0.0 | 0.0 | 11.89 | 0.0 | 0.0 | 0.0 | 11.89 | Then Loan Repayment schedule has the following data in Total row: | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | - | 100.0 | 2.05 | 0.04 | 0.0 | 102.09 | 0.0 | 0.0 | 0.0 | 102.09 | + | 70.0 | 1.44 | 0.03 | 0.0 | 71.47 | 0.00 | 0.0 | 0.0 | 71.47 | Then Loan Transactions tab has none transaction Then Loan Charges tab has the following data: | Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding | - | Disbursement Charge | false | Disbursement | | % Interest | 0.04 | 0.04 | 0.0 | 0.0 | + | Disbursement Charge | false | Disbursement | | % Interest | 0.03 | 0.0 | 0.0 | 0.03 | - @Skip @TestRailId:C3560 Scenario: Verify amount disbursement charge for tranche interest bearing progressive loan that doesn't expect tranches with undo disbursements - UC8.2.6 When Admin sets the business date to "01 January 2024" @@ -4137,7 +4131,7 @@ Feature: LoanCharge | 6 | 30 | 01 July 2024 | | 0.0 | 11.82 | 0.07 | 0.0 | 0.0 | 11.89 | 0.0 | 0.0 | 0.0 | 11.89 | Then Loan Repayment schedule has the following data in Total row: | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | - | 70.0 | 1.44 | 1.4 | 0.0 | 72.87 | 1.4 | 0.0 | 0.0 | 71.44 | + | 70.0 | 1.44 | 1.4 | 0.0 | 72.84 | 1.4 | 0.0 | 0.0 | 71.44 | Then Loan Transactions tab has the following data: | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | | 01 January 2024 | Disbursement | 70.0 | 0.0 | 0.0 | 0.0 | 0.0 | 70.0 | false | false | @@ -4164,7 +4158,7 @@ Feature: LoanCharge | 6 | 30 | 01 July 2024 | | 0.0 | 11.82 | 0.07 | 0.0 | 0.0 | 11.89 | 0.0 | 0.0 | 0.0 | 11.89 | Then Loan Repayment schedule has the following data in Total row: | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | - | 100.0 | 1.44 | 1.4 | 0.0 | 72.84 | 13.31 | 0.0 | 0.0 | 59.53 | + | 70.0 | 1.44 | 1.4 | 0.0 | 72.84 | 13.31 | 0.0 | 0.0 | 59.53 | Then Loan Transactions tab has the following data: | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | | 01 January 2024 | Disbursement | 70.0 | 0.0 | 0.0 | 0.0 | 0.0 | 70.0 | false | false | @@ -4188,15 +4182,15 @@ Feature: LoanCharge Then Loan Transactions tab has the following data: | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | | 01 January 2024 | Disbursement | 70.0 | 0.0 | 0.0 | 0.0 | 0.0 | 70.0 | false | false | - | 01 January 2024 | Repayment (at time of disbursement) | 2.0 | 0.0 | 0.0 | 2.0 | 0.0 | 70.0 | false | false | + | 01 January 2024 | Repayment (at time of disbursement) | 1.4 | 0.0 | 0.0 | 1.4 | 0.0 | 70.0 | false | false | | 01 February 2024 | Repayment | 11.91 | 11.5 | 0.41 | 0.0 | 0.0 | 58.5 | false | false | - | 15 February 2024 | Disbursement | 30.0 | 0.0 | 0.0 | 0.0 | 0.0 | 88.5 | false | false | + | 01 February 2024 | Disbursement | 30.0 | 0.0 | 0.0 | 0.0 | 0.0 | 88.5 | false | false | # -- undo disbursement ---- When Admin successfully undo disbursal Then Loan status has changed to "Approved" 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 | | | 2.0 | | 2.0 | | | | 2.0 | + | | | 01 January 2024 | | 100.0 | | | 1.4 | | 1.4 | | | | 1.4 | | 1 | 31 | 01 February 2024 | | 83.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | | 2 | 29 | 01 March 2024 | | 67.05 | 16.52 | 0.49 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | | 3 | 31 | 01 April 2024 | | 50.43 | 16.62 | 0.39 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | @@ -4205,13 +4199,12 @@ Feature: LoanCharge | 6 | 30 | 01 July 2024 | | 0.0 | 16.9 | 0.1 | 0.0 | 0.0 | 17.0 | 0.0 | 0.0 | 0.0 | 17.0 | Then Loan Repayment schedule has the following data in Total row: | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | - | 100.0 | 2.05 | 2.0 | 0.0 | 104.05 | 0.0 | 0.0 | 0.0 | 104.05 | + | 100.0 | 2.05 | 1.4 | 0.0 | 103.45 | 0.0 | 0.0 | 0.0 | 103.45 | Then Loan Transactions tab has none transaction Then Loan Charges tab has the following data: | Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding | - | Disbursement Charge | false | Disbursement | | % Interest | 2.0 | 0.0 | 0.0 | 2.0 | + | Disbursement Charge | false | Disbursement | | % Amount | 2.0 | 0.0 | 0.0 | 2.0 | - @Skip @TestRailId:C3561 Scenario: Verify amount+interest disbursement charge for tranche interest bearing progressive loan that doesn't expect tranches with undo disbursement - UC8.2.7 When Admin sets the business date to "01 January 2024" @@ -4274,7 +4267,7 @@ Feature: LoanCharge Then Loan status has changed to "Approved" 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.02 | | 0.02 | | | | 0.02 | + | | | 01 January 2024 | | 100.0 | | | 2.04 | | 2.04 | | | | 2.04 | | 1 | 31 | 01 February 2024 | | 83.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | | 2 | 29 | 01 March 2024 | | 67.05 | 16.52 | 0.49 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | | 3 | 31 | 01 April 2024 | | 50.43 | 16.62 | 0.39 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | @@ -4283,7 +4276,7 @@ Feature: LoanCharge | 6 | 30 | 01 July 2024 | | 0.0 | 16.9 | 0.1 | 0.0 | 0.0 | 17.0 | 0.0 | 0.0 | 0.0 | 17.0 | Then Loan Repayment schedule has the following data in Total row: | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | - | 100.0 | 2.05 | 0.02 | 0.0 | 102.07 | 0.0 | 0.0 | 0.0 | 102.07 | + | 100.0 | 2.05 | 2.04 | 0.0 | 104.09 | 0.0 | 0.0 | 0.0 | 104.09 | Then Loan Transactions tab has none transaction Then Loan Charges tab has the following data: | Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding | diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyReadPlatformServiceImpl.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyReadPlatformServiceImpl.java index d0f36ff2d..9f29937e7 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyReadPlatformServiceImpl.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyReadPlatformServiceImpl.java @@ -216,7 +216,7 @@ public class DelinquencyReadPlatformServiceImpl implements DelinquencyReadPlatfo // Calculate available amount: (approved + over applied) - expected tranches - disbursed - capitalized income if (loan.isMultiDisburmentLoan() && loan.getDisbursementDetails() != null) { final BigDecimal expectedDisbursementAmount = loan.getDisbursementDetails().stream() - .filter(detail -> detail.actualDisbursementDate() == null).map(LoanDisbursementDetails::principal) + .filter(detail -> detail.actualDisbursementDate() == null).map(LoanDisbursementDetails::getPrincipal) .reduce(BigDecimal.ZERO, BigDecimal::add); approvedWithOverApplied = approvedWithOverApplied.subtract(expectedDisbursementAmount); } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/DisbursementData.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/DisbursementData.java index 608799270..3e75012c1 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/DisbursementData.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/DisbursementData.java @@ -22,6 +22,8 @@ import java.math.BigDecimal; import java.time.LocalDate; import lombok.Getter; import lombok.RequiredArgsConstructor; +import lombok.Setter; +import lombok.experimental.Accessors; import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType; @@ -30,6 +32,7 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanSchedul */ @RequiredArgsConstructor @Getter +@Accessors(chain = true) public final class DisbursementData implements LoanPrincipalRelatedDataHolder, Comparable { private final Long id; @@ -41,6 +44,8 @@ public final class DisbursementData implements LoanPrincipalRelatedDataHolder, C private final String loanChargeId; private final BigDecimal chargeAmount; private final BigDecimal waivedChargeAmount; + @Setter + private BigDecimal disburseChargeAmount; // import fields private transient Integer rowIndex; 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 f179d71c4..ee155ca67 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 @@ -814,7 +814,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { if (isMultiDisburmentLoan()) { for (LoanDisbursementDetails disbursementDetail : getDisbursementDetails()) { if (disbursementDetail.actualDisbursementDate() != null) { - principal = principal.add(disbursementDetail.principal()); + principal = principal.add(disbursementDetail.getPrincipal()); } } return principal; @@ -999,7 +999,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { if (!details.isEmpty()) { principal = BigDecimal.ZERO; for (LoanDisbursementDetails disbursementDetails : details) { - principal = principal.add(disbursementDetails.principal()); + principal = principal.add(disbursementDetails.getPrincipal()); } } return principal; @@ -1303,7 +1303,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { public LoanDisbursementDetails getDisbursementDetails(final LocalDate transactionDate, final BigDecimal transactionAmount) { for (LoanDisbursementDetails disbursementDetail : this.disbursementDetails) { if (!disbursementDetail.isReversed() && disbursementDetail.getDisbursementDate().equals(transactionDate) - && (disbursementDetail.principal().compareTo(transactionAmount) == 0)) { + && (disbursementDetail.getPrincipal().compareTo(transactionAmount) == 0)) { return disbursementDetail; } } @@ -1317,7 +1317,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { Collection loanDisburseDetails = this.getDisbursementDetails(); for (LoanDisbursementDetails details : loanDisburseDetails) { if (details.actualDisbursementDate() != null) { - principalAmount = principalAmount.add(details.principal()); + principalAmount = principalAmount.add(details.getPrincipal()); } } } else if (isApproved()) { diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanDisbursementDetails.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanDisbursementDetails.java index 31b065ba6..ef31e7dec 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanDisbursementDetails.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanDisbursementDetails.java @@ -26,10 +26,12 @@ import jakarta.persistence.Table; import java.math.BigDecimal; import java.time.LocalDate; import java.util.Objects; +import lombok.Getter; import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.loanaccount.data.DisbursementData; +@Getter @Entity @Table(name = "m_loan_disbursement_detail") public class LoanDisbursementDetails extends AbstractPersistableCustom { @@ -107,10 +109,6 @@ public class LoanDisbursementDetails extends AbstractPersistableCustom { return this.actualDisbursementDate; } - public BigDecimal principal() { - return this.principal; - } - public void updatePrincipal(BigDecimal principal) { this.principal = principal; } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleProcessingWrapper.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleProcessingWrapper.java index ba233d726..a3972d846 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleProcessingWrapper.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleProcessingWrapper.java @@ -108,7 +108,7 @@ public class LoanRepaymentScheduleProcessingWrapper { && loanCharge.getLoan().isMultiDisburmentLoan()) { for (final LoanDisbursementDetails loanDisbursementDetails : loanCharge.getLoan().getDisbursementDetails()) { if (!DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDate(), loanCharge.getDueDate())) { - amount = amount.add(loanDisbursementDetails.principal()); + amount = amount.add(loanDisbursementDetails.getPrincipal()); } } } else { diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/SingleLoanChargeRepaymentScheduleProcessingWrapper.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/SingleLoanChargeRepaymentScheduleProcessingWrapper.java index f73ed71b6..bd2522435 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/SingleLoanChargeRepaymentScheduleProcessingWrapper.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/SingleLoanChargeRepaymentScheduleProcessingWrapper.java @@ -132,7 +132,7 @@ public class SingleLoanChargeRepaymentScheduleProcessingWrapper { // Then we need to get as of this loan charge due date how much amount disbursed. for (final LoanDisbursementDetails loanDisbursementDetails : loan.getDisbursementDetails()) { if (!DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDate(), loanCharge.getDueDate())) { - baseAmount = MathUtil.add(baseAmount, loanDisbursementDetails.principal()); + baseAmount = MathUtil.add(baseAmount, loanDisbursementDetails.getPrincipal()); } } } else { diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/mapper/LoanMapper.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/mapper/LoanMapper.java index 3f00fea29..d6bc7ae52 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/mapper/LoanMapper.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/mapper/LoanMapper.java @@ -94,7 +94,7 @@ public class LoanMapper { BigDecimal waivedChargeAmount = null; disbursementData.add( new DisbursementData(loanDisbursementDetails.getId(), loan.getId(), expectedDisbursementDate, actualDisbursementDate, - loanDisbursementDetails.principal(), loan.getNetDisbursalAmount(), null, null, waivedChargeAmount)); + loanDisbursementDetails.getPrincipal(), loan.getNetDisbursalAmount(), null, null, waivedChargeAmount)); } return disbursementData; diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApprovedAmountWritePlatformServiceImpl.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApprovedAmountWritePlatformServiceImpl.java index f8fe4cb32..13a096cb5 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApprovedAmountWritePlatformServiceImpl.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApprovedAmountWritePlatformServiceImpl.java @@ -88,7 +88,7 @@ public class LoanApprovedAmountWritePlatformServiceImpl implements LoanApprovedA changes.put("oldApprovedAmount", loan.getApprovedPrincipal()); BigDecimal expectedDisbursementAmount = loan.getDisbursementDetails().stream().filter(t -> t.actualDisbursementDate() == null) - .map(LoanDisbursementDetails::principal).reduce(BigDecimal.ZERO, BigDecimal::add); + .map(LoanDisbursementDetails::getPrincipal).reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal oldAvailableDisbursement = loan.getApprovedPrincipal().subtract(loan.getSummary().getTotalPrincipal()) .subtract(expectedDisbursementAmount); diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanBalanceService.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanBalanceService.java index 9396ab1ee..c15689549 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanBalanceService.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanBalanceService.java @@ -187,7 +187,7 @@ public class LoanBalanceService { charge.resetToOriginal(loan.getCurrency()); } } - loan.getLoanRepaymentScheduleDetail().setPrincipal(loan.getDisbursedAmount().subtract(disbursementDetail.principal())); + loan.getLoanRepaymentScheduleDetail().setPrincipal(loan.getDisbursedAmount().subtract(disbursementDetail.getPrincipal())); disbursementDetail.updateActualDisbursementDate(null); disbursementDetail.reverse(); updateLoanSummaryDerivedFields(loan); diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeService.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeService.java index d725279e1..569ba3379 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeService.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeService.java @@ -251,7 +251,9 @@ public class LoanChargeService { case PERCENT_OF_AMOUNT_AND_INTEREST -> { final BigDecimal totalInterestCharged = loan.getTotalInterest(); if (loan.isMultiDisburmentLoan() && loanCharge.isDisbursementCharge()) { - yield getTotalAllTrancheDisbursementAmount(loan).getAmount().add(totalInterestCharged); + yield sumMultiDisbursementAmounts(loan, false).getAmount().add(totalInterestCharged); + } else if (loan.isMultiDisburmentLoan() && loanCharge.isTrancheDisbursementCharge()) { + yield sumMultiDisbursementAmounts(loan, true).getAmount().add(totalInterestCharged); } else { yield loan.getPrincipal().getAmount().add(totalInterestCharged); } @@ -259,7 +261,7 @@ public class LoanChargeService { case PERCENT_OF_INTEREST -> loan.getTotalInterest(); case PERCENT_OF_DISBURSEMENT_AMOUNT -> { if (loanCharge.getTrancheDisbursementCharge() != null) { - yield loanCharge.getTrancheDisbursementCharge().getloanDisbursementDetails().principal(); + yield loanCharge.getTrancheDisbursementCharge().getloanDisbursementDetails().getPrincipal(); } else { yield loan.getPrincipal().getAmount(); } @@ -449,7 +451,7 @@ public class LoanChargeService { if (loanCharge.getLoan().isMultiDisburmentLoan() && loanCharge.isSpecifiedDueDate()) { for (final LoanDisbursementDetails loanDisbursementDetails : loanCharge.getLoan().getDisbursementDetails()) { if (!DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDate(), loanCharge.getDueDate())) { - amountPercentageAppliedTo = amountPercentageAppliedTo.add(loanDisbursementDetails.principal()); + amountPercentageAppliedTo = amountPercentageAppliedTo.add(loanDisbursementDetails.getPrincipal()); } } } else { @@ -465,7 +467,7 @@ public class LoanChargeService { break; case PERCENT_OF_DISBURSEMENT_AMOUNT: LoanTrancheDisbursementCharge loanTrancheDisbursementCharge = loanCharge.getLoanTrancheDisbursementCharge(); - amountPercentageAppliedTo = loanTrancheDisbursementCharge.getloanDisbursementDetails().principal(); + amountPercentageAppliedTo = loanTrancheDisbursementCharge.getloanDisbursementDetails().getPrincipal(); break; default: break; @@ -850,14 +852,23 @@ public class LoanChargeService { } } - private Money getTotalAllTrancheDisbursementAmount(final Loan loan) { - Money amount = Money.zero(loan.getCurrency()); + private Money sumMultiDisbursementAmounts(final Loan loan, final boolean isTrancheDisbursement) { if (loan.isMultiDisburmentLoan()) { - for (final LoanDisbursementDetails loanDisbursementDetail : loan.getDisbursementDetails()) { - amount = amount.plus(loanDisbursementDetail.principal()); + final List loanDisbursementDetails = loan.getDisbursementDetails(); + if (loan.isOpen() || !loanDisbursementDetails.isEmpty()) { + if (isTrancheDisbursement) { + return Money.of(loan.getCurrency(), loanDisbursementDetails.stream() // + .map(LoanDisbursementDetails::getPrincipal) // + .reduce(BigDecimal.ZERO, BigDecimal::add)); + } + return Money.of(loan.getCurrency(), loanDisbursementDetails.get(0).getPrincipal()); + } else if (loan.isSubmittedAndPendingApproval()) { + return Money.of(loan.getCurrency(), loan.getProposedPrincipal()); + } else if (loan.isApproved()) { + return Money.of(loan.getCurrency(), loan.getApprovedPrincipal()); } } - return amount; + return Money.zero(loan.getCurrency()); } private List fetchAllLoanChargeIds(final Loan loan) { @@ -884,15 +895,16 @@ public class LoanChargeService { private BigDecimal getDerivedAmountForCharge(final Loan loan, final LoanCharge loanCharge) { BigDecimal amount = BigDecimal.ZERO; - if (loan.isMultiDisburmentLoan() && loanCharge.getCharge().getChargeTimeType().equals(ChargeTimeType.DISBURSEMENT.getValue())) { - amount = loan.getApprovedPrincipal(); + final ChargeTimeType chargeTimeType = ChargeTimeType.fromInt(loanCharge.getCharge().getChargeTimeType()); + if (loan.isMultiDisburmentLoan() && chargeTimeType.isDisbursementOrTrancheDisbursementCharge()) { + return sumMultiDisbursementAmounts(loan, chargeTimeType.isTrancheDisbursement()).getAmount(); } else { // If charge type is specified due date and loan is multi disburment loan. // Then we need to get as of this loan charge due date how much amount disbursed. if (loanCharge.isSpecifiedDueDate() && loan.isMultiDisburmentLoan()) { for (final LoanDisbursementDetails loanDisbursementDetails : loan.getDisbursementDetails()) { if (!DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDate(), loanCharge.getDueDate())) { - amount = amount.add(loanDisbursementDetails.principal()); + amount = amount.add(loanDisbursementDetails.getPrincipal()); } } } else { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java index f07b2dafe..7b8a8100e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java @@ -962,7 +962,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { for (LoanDisbursementDetails loanDisbursementDetails : loan.getDisbursementDetails()) { if (loanDisbursementDetails.actualDisbursementDate() == null) { - totalPrincipal = Money.of(currency, totalPrincipal.getAmount().subtract(loanDisbursementDetails.principal())); + totalPrincipal = Money.of(currency, totalPrincipal.getAmount().subtract(loanDisbursementDetails.getPrincipal())); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java index 8bfc0b235..1c4f21f69 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java @@ -175,8 +175,8 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC for (LoanRepaymentScheduleInstallment installment : installments) { if (loanDisbursementDetails != null && !DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDateAsLocalDate(), installment.getDueDate())) { - outstanding = outstanding.plus(loanDisbursementDetails.principal()); - principal = principal.plus(loanDisbursementDetails.principal()); + outstanding = outstanding.plus(loanDisbursementDetails.getPrincipal()); + principal = principal.plus(loanDisbursementDetails.getPrincipal()); if (disbursementItr.hasNext()) { loanDisbursementDetails = disbursementItr.next(); } else { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApprovedAmountValidatorImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApprovedAmountValidatorImpl.java index b2a5baf30..02dbb7a6f 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApprovedAmountValidatorImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApprovedAmountValidatorImpl.java @@ -97,7 +97,7 @@ public final class LoanApprovedAmountValidatorImpl implements LoanApprovedAmount BigDecimal totalPrincipalOnLoan = loan.getSummary().getTotalPrincipal(); BigDecimal totalExpectedPrincipal = loan.getDisbursementDetails().stream().filter(t -> t.actualDisbursementDate() == null) - .map(LoanDisbursementDetails::principal).reduce(BigDecimal.ZERO, BigDecimal::add); + .map(LoanDisbursementDetails::getPrincipal).reduce(BigDecimal.ZERO, BigDecimal::add); if (MathUtil.isLessThan(newApprovedAmount, totalPrincipalOnLoan.add(totalExpectedPrincipal))) { baseDataValidator.reset().parameter(LoanApiConstants.amountParameterName) .failWithCode("less.than.disbursed.principal.and.capitalized.income"); @@ -145,7 +145,7 @@ public final class LoanApprovedAmountValidatorImpl implements LoanApprovedAmount } BigDecimal expectedDisbursementAmount = loan.getDisbursementDetails().stream().filter(t -> t.actualDisbursementDate() == null) - .map(LoanDisbursementDetails::principal).reduce(BigDecimal.ZERO, BigDecimal::add); + .map(LoanDisbursementDetails::getPrincipal).reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal maximumAvailableDisbursementThreshold = maximumThresholdForApprovedAmount .subtract(loan.getSummary().getTotalPrincipal()).subtract(expectedDisbursementAmount); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeAssembler.java index 9ad6a79aa..303128285 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeAssembler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeAssembler.java @@ -174,7 +174,7 @@ public class LoanChargeAssembler { } else { if (disbursementDetail.expectedDisbursementDateAsLocalDate().equals(expectedDisbursementDate)) { final LoanCharge loanCharge = createNewWithoutLoan(chargeDefinition, - disbursementDetail.principal(), amount, chargeTime, chargeCalculation, + disbursementDetail.getPrincipal(), amount, chargeTime, chargeCalculation, disbursementDetail.expectedDisbursementDateAsLocalDate(), chargePaymentModeEnum, numberOfRepayments, externalId); loanCharges.add(loanCharge); @@ -191,8 +191,8 @@ public class LoanChargeAssembler { LoanTrancheDisbursementCharge loanTrancheDisbursementCharge = null; for (LoanDisbursementDetails disbursementDetail : disbursementDetails) { if (ChargeTimeType.TRANCHE_DISBURSEMENT.getValue().equals(chargeDefinition.getChargeTimeType())) { - final LoanCharge loanCharge = createNewWithoutLoan(chargeDefinition, disbursementDetail.principal(), - amount, chargeTime, chargeCalculation, + final LoanCharge loanCharge = createNewWithoutLoan(chargeDefinition, + disbursementDetail.getPrincipal(), amount, chargeTime, chargeCalculation, disbursementDetail.expectedDisbursementDateAsLocalDate(), chargePaymentModeEnum, numberOfRepayments, externalId); loanCharges.add(loanCharge); @@ -309,7 +309,7 @@ public class LoanChargeAssembler { amountPercentageAppliedTo = BigDecimal.ZERO; for (final LoanDisbursementDetails loanDisbursementDetails : loan.getDisbursementDetails()) { if (!DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDate(), dueDate)) { - amountPercentageAppliedTo = amountPercentageAppliedTo.add(loanDisbursementDetails.principal()); + amountPercentageAppliedTo = amountPercentageAppliedTo.add(loanDisbursementDetails.getPrincipal()); } } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeWritePlatformServiceImpl.java index f0198b360..47304853e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeWritePlatformServiceImpl.java @@ -105,7 +105,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachin import org.apache.fineract.portfolio.loanaccount.domain.LoanOverdueInstallmentCharge; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleProcessingWrapper; -import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper; import org.apache.fineract.portfolio.loanaccount.domain.LoanTrancheDisbursementCharge; import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction; @@ -159,7 +158,6 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo private final AccountAssociationsReadPlatformService accountAssociationsReadPlatformService; private final FromJsonHelper fromApiJsonHelper; private final ConfigurationDomainService configurationDomainService; - private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory; private final ExternalIdFactory externalIdFactory; private final AccountTransferDetailRepository accountTransferDetailRepository; private final LoanChargeAssembler loanChargeAssembler; @@ -216,7 +214,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo externalId = externalIdFactory.create(); } LocalDate dueDate = disbursementDetail.expectedDisbursementDateAsLocalDate(); - loanCharge = loanChargeAssembler.createNewWithoutLoan(chargeDefinition, disbursementDetail.principal(), null, null, + loanCharge = loanChargeAssembler.createNewWithoutLoan(chargeDefinition, disbursementDetail.getPrincipal(), null, null, null, dueDate, null, null, externalId); loanTrancheDisbursementCharge = new LoanTrancheDisbursementCharge(loanCharge, disbursementDetail); loanCharge.updateLoanTrancheDisbursementCharge(loanTrancheDisbursementCharge); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanDisbursementService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanDisbursementService.java index aa6cd0451..b8fe98fa5 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanDisbursementService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanDisbursementService.java @@ -138,7 +138,7 @@ public class LoanDisbursementService { disburseAmount = disburseAmount.zero(); for (LoanDisbursementDetails disbursementDetails : details) { disbursementDetails.updateActualDisbursementDate(actualDisbursementDate); - disburseAmount = disburseAmount.plus(disbursementDetails.principal()); + disburseAmount = disburseAmount.plus(disbursementDetails.getPrincipal()); } } } else { @@ -162,7 +162,7 @@ public class LoanDisbursementService { // First try to find a tranche that exactly matches the requested disbursement amount for (LoanDisbursementDetails disbursementDetails : details) { if (disbursementDetails.actualDisbursementDate() == null - && disbursementDetails.principal().compareTo(principalDisbursed) == 0) { + && disbursementDetails.getPrincipal().compareTo(principalDisbursed) == 0) { selectedTranche = disbursementDetails; break; } @@ -198,9 +198,9 @@ public class LoanDisbursementService { BigDecimal setPrincipalAmount = BigDecimal.ZERO; for (LoanDisbursementDetails disbursementDetails : loanDisburseDetails) { if (disbursementDetails.actualDisbursementDate() != null) { - setPrincipalAmount = setPrincipalAmount.add(disbursementDetails.principal()); + setPrincipalAmount = setPrincipalAmount.add(disbursementDetails.getPrincipal()); } - totalAmount = totalAmount.add(disbursementDetails.principal()); + totalAmount = totalAmount.add(disbursementDetails.getPrincipal()); } loan.getLoanRepaymentScheduleDetail().setPrincipal(setPrincipalAmount); } else { @@ -435,7 +435,7 @@ public class LoanDisbursementService { LoanDisbursementDetails singleDetail = undisbursedDetails.iterator().next(); BigDecimal loanPrincipal = loan.getLoanRepaymentScheduleDetail().getPrincipal().getAmount(); - if (singleDetail.principal().compareTo(loanPrincipal) == 0) { + if (singleDetail.getPrincipal().compareTo(loanPrincipal) == 0) { return false; } } @@ -452,7 +452,8 @@ public class LoanDisbursementService { return disbursementDetails.stream() .sorted(Comparator.comparing(LoanDisbursementDetails::expectedDisbursementDate) - .thenComparing((LoanDisbursementDetails d1, LoanDisbursementDetails d2) -> d2.principal().compareTo(d1.principal())) + .thenComparing( + (LoanDisbursementDetails d1, LoanDisbursementDetails d2) -> d2.getPrincipal().compareTo(d1.getPrincipal())) .thenComparing(LoanDisbursementDetails::getId)) .collect(Collectors.toList()); } 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 711f1a878..7da1e2df9 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 @@ -1666,10 +1666,14 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa } public String schema() { - return "dd.id as id, dd.loan_id as loanId, dd.expected_disburse_date as expectedDisbursementdate, dd.disbursedon_date as actualDisbursementdate,dd.principal as principal,dd.net_disbursal_amount as netDisbursalAmount,sum(lc.amount) chargeAmount, lc.amount_waived_derived waivedAmount, " - + sqlGenerator.groupConcat("lc.id") + " loanChargeId " - + "from m_loan l inner join m_loan_disbursement_detail dd on dd.loan_id = l.id left join m_loan_tranche_disbursement_charge tdc on tdc.disbursement_detail_id=dd.id " - + "left join m_loan_charge lc on lc.id=tdc.loan_charge_id and lc.is_active=true"; + return "dd.id as id, dd.loan_id as loanId, dd.expected_disburse_date as expectedDisbursementdate, dd.disbursedon_date as actualDisbursementdate, " + + "dd.principal as principal,dd.net_disbursal_amount as netDisbursalAmount, sum(lc.amount) as chargeAmount, coalesce(sum(cad.amount), 0) as disburseChargeAmount, " + + "lc.amount_waived_derived waivedAmount, coalesce(" + sqlGenerator.groupConcat("lc.id") + ", " + + sqlGenerator.groupConcat("cad.id") + ") loanChargeId " + + "from m_loan l inner join m_loan_disbursement_detail dd on dd.loan_id = l.id " + + "left join m_loan_tranche_disbursement_charge tdc on tdc.disbursement_detail_id = dd.id " + + "left join m_loan_charge lc on lc.id = tdc.loan_charge_id and lc.is_active = true " + + "left join (select lch.id, lch.loan_id, lch.amount from m_loan_charge lch inner join m_charge ch on ch.id = lch.charge_id and ch.charge_time_enum = 1) cad on cad.loan_id = l.id"; } @Override @@ -1686,8 +1690,9 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa if (chargeAmount != null && waivedAmount != null) { chargeAmount = chargeAmount.subtract(waivedAmount); } + BigDecimal disburseChargeAmount = rs.getBigDecimal("disburseChargeAmount"); return new DisbursementData(id, loanId, expectedDisbursementdate, actualDisbursementdate, principal, netDisbursalAmount, - loanChargeId, chargeAmount, waivedAmount); + loanChargeId, chargeAmount, waivedAmount).setDisburseChargeAmount(disburseChargeAmount); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanRepaymentScheduleService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanRepaymentScheduleService.java index 7844b54e9..f5cfd2284 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanRepaymentScheduleService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanRepaymentScheduleService.java @@ -365,7 +365,12 @@ public class LoanRepaymentScheduleService { if (dataItem.isDisbursement()) { // Process disbursement data DisbursementData data = (DisbursementData) dataItem.getData(); - periodData = createLoanSchedulePeriodData(data, disbursementChargeAmount, waivedChargeAmount); + if (periods.isEmpty()) { + periodData = createLoanSchedulePeriodData(data, disbursementChargeAmount, waivedChargeAmount); + } else { + periodData = createLoanSchedulePeriodData(data, disbursementChargeAmount.subtract(data.getDisburseChargeAmount()), + waivedChargeAmount); + } } else { // Process capitalized income data LoanTransactionRepaymentPeriodData data = (LoanTransactionRepaymentPeriodData) dataItem.getData(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 6a9c0667d..af7644c7b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -2209,7 +2209,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf Collection loanDisburseDetails = loan.getDisbursementDetails(); for (LoanDisbursementDetails disbursementDetails : loanDisburseDetails) { if (disbursementDetails.actualDisbursementDate() != null) { - totalDisbursedAmount = totalDisbursedAmount.add(disbursementDetails.principal()); + totalDisbursedAmount = totalDisbursedAmount.add(disbursementDetails.getPrincipal()); } } if (totalDisbursedAmount.compareTo(loan.getApprovedPrincipal()) == 0) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java index 1abb051df..0afb7b400 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java @@ -314,11 +314,10 @@ public class LoanAccountConfiguration { LoanWritePlatformService loanWritePlatformService, LoanUtilService loanUtilService, LoanChargeReadPlatformService loanChargeReadPlatformService, LoanLifecycleStateMachine loanLifecycleStateMachine, AccountAssociationsReadPlatformService accountAssociationsReadPlatformService, FromJsonHelper fromApiJsonHelper, - ConfigurationDomainService configurationDomainService, - LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory, - ExternalIdFactory externalIdFactory, AccountTransferDetailRepository accountTransferDetailRepository, - LoanChargeAssembler loanChargeAssembler, PaymentDetailWritePlatformService paymentDetailWritePlatformService, - NoteRepository noteRepository, LoanAccrualsProcessingService loanAccrualsProcessingService, + ConfigurationDomainService configurationDomainService, ExternalIdFactory externalIdFactory, + AccountTransferDetailRepository accountTransferDetailRepository, LoanChargeAssembler loanChargeAssembler, + PaymentDetailWritePlatformService paymentDetailWritePlatformService, NoteRepository noteRepository, + LoanAccrualsProcessingService loanAccrualsProcessingService, LoanDownPaymentTransactionValidator loanDownPaymentTransactionValidator, LoanChargeValidator loanChargeValidator, LoanScheduleService loanScheduleService, ReprocessLoanTransactionsService reprocessLoanTransactionsService, LoanAccountService loanAccountService, LoanAdjustmentService loanAdjustmentService, LoanChargeService loanChargeService, @@ -327,10 +326,9 @@ public class LoanAccountConfiguration { businessEventNotifierService, loanTransactionRepository, accountTransfersWritePlatformService, loanRepositoryWrapper, loanAccountDomainService, loanChargeRepository, loanWritePlatformService, loanUtilService, loanChargeReadPlatformService, loanLifecycleStateMachine, accountAssociationsReadPlatformService, fromApiJsonHelper, configurationDomainService, - loanRepaymentScheduleTransactionProcessorFactory, externalIdFactory, accountTransferDetailRepository, loanChargeAssembler, - paymentDetailWritePlatformService, noteRepository, loanAccrualsProcessingService, loanDownPaymentTransactionValidator, - loanChargeValidator, loanScheduleService, reprocessLoanTransactionsService, loanAccountService, loanAdjustmentService, - loanChargeService, loanJournalEntryPoster); + externalIdFactory, accountTransferDetailRepository, loanChargeAssembler, paymentDetailWritePlatformService, noteRepository, + loanAccrualsProcessingService, loanDownPaymentTransactionValidator, loanChargeValidator, loanScheduleService, + reprocessLoanTransactionsService, loanAccountService, loanAdjustmentService, loanChargeService, loanJournalEntryPoster); } @Bean