FINERACT-2210: Fix journal entries creation issue when amount is null
This commit is contained in:
committed by
Adam Saghy
parent
a1d51e1e34
commit
a11c567413
+1
@@ -106,6 +106,7 @@ public enum DefaultLoanProduct implements LoanProduct {
|
|||||||
LP2_ACCELERATE_MATURITY_CHARGE_OFF_BEHAVIOUR_LAST_INSTALLMENT_STRATEGY, //
|
LP2_ACCELERATE_MATURITY_CHARGE_OFF_BEHAVIOUR_LAST_INSTALLMENT_STRATEGY, //
|
||||||
LP2_ADV_PYMNT_INTEREST_DAILY_INT_RECALCULATION_ZERO_INT_CHARGE_OFF_INT_RECOGNITION_FROM_DISB_DATE, //
|
LP2_ADV_PYMNT_INTEREST_DAILY_INT_RECALCULATION_ZERO_INT_CHARGE_OFF_INT_RECOGNITION_FROM_DISB_DATE, //
|
||||||
LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_DELINQUENT_REASON, //
|
LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_DELINQUENT_REASON, //
|
||||||
|
LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_DELINQUENT_REASON_INTEREST_RECALC, //
|
||||||
LP2_ADV_DP_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL, //
|
LP2_ADV_DP_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL, //
|
||||||
LP2_ADV_DP_IR_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL, //
|
LP2_ADV_DP_IR_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL, //
|
||||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALC_DAILY_DISBURSEMENT_CHARGES, //
|
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALC_DAILY_DISBURSEMENT_CHARGES, //
|
||||||
|
|||||||
+34
@@ -2227,6 +2227,40 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
|
|||||||
TestContext.INSTANCE.set(
|
TestContext.INSTANCE.set(
|
||||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALC_DAILY_CASH_ACCOUNTING_DISBURSEMENT_CHARGES,
|
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALC_DAILY_CASH_ACCOUNTING_DISBURSEMENT_CHARGES,
|
||||||
responseLoanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcDailyCashAccountingDisbursementCharge);
|
responseLoanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcDailyCashAccountingDisbursementCharge);
|
||||||
|
|
||||||
|
// LP2 + zero-interest chargeOff behaviour + progressive loan schedule + horizontal + delinquent charge-off
|
||||||
|
// reason to GL account mapping + interest recalculation
|
||||||
|
// (LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_DELINQUENT_REASON_INTEREST_RECALC)
|
||||||
|
final String name90 = DefaultLoanProduct.LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_DELINQUENT_REASON_INTEREST_RECALC.getName();
|
||||||
|
|
||||||
|
final PostLoanProductsRequest loanProductsRequestAdvZeroInterestChargeOffProgressiveDelinquentReasonIntRecalc = loanProductsRequestFactory
|
||||||
|
.defaultLoanProductsRequestLP2ChargeOffReasonToExpenseAccountMappings()//
|
||||||
|
.name(name90)//
|
||||||
|
.enableDownPayment(false)//
|
||||||
|
.isInterestRecalculationEnabled(true)//
|
||||||
|
.preClosureInterestCalculationStrategy(1)//
|
||||||
|
.rescheduleStrategyMethod(4)//
|
||||||
|
.interestRecalculationCompoundingMethod(0)//
|
||||||
|
.recalculationRestFrequencyType(2)//
|
||||||
|
.recalculationRestFrequencyInterval(1)//
|
||||||
|
.enableAutoRepaymentForDownPayment(null)//
|
||||||
|
.disbursedAmountPercentageForDownPayment(null)//
|
||||||
|
.transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION.getValue())//
|
||||||
|
.loanScheduleType("PROGRESSIVE") //
|
||||||
|
.loanScheduleProcessingType("HORIZONTAL")//
|
||||||
|
.interestRateFrequencyType(3)//
|
||||||
|
.maxInterestRatePerPeriod(10.0)//
|
||||||
|
.paymentAllocation(List.of(//
|
||||||
|
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), //
|
||||||
|
createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
|
||||||
|
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
|
||||||
|
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")))//
|
||||||
|
.chargeOffBehaviour("ZERO_INTEREST");//
|
||||||
|
final Response<PostLoanProductsResponse> responseLoanProductsRequestAdvZeroInterestChargeOffProgressiveDelinquentReasonIntRecalc = loanProductsApi
|
||||||
|
.createLoanProduct(loanProductsRequestAdvZeroInterestChargeOffProgressiveDelinquentReasonIntRecalc).execute();
|
||||||
|
TestContext.INSTANCE.set(
|
||||||
|
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_DELINQUENT_REASON_INTEREST_RECALC,
|
||||||
|
responseLoanProductsRequestAdvZeroInterestChargeOffProgressiveDelinquentReasonIntRecalc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AdvancedPaymentData createPaymentAllocation(String transactionType, String futureInstallmentAllocationRule,
|
public static AdvancedPaymentData createPaymentAllocation(String transactionType, String futureInstallmentAllocationRule,
|
||||||
|
|||||||
+1
@@ -117,6 +117,7 @@ public abstract class TestContextKey {
|
|||||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR = "loanProductCreateResponseLP2AdvancedPaymentZeroInterestChargeOffBehaviour";
|
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR = "loanProductCreateResponseLP2AdvancedPaymentZeroInterestChargeOffBehaviour";
|
||||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF = "loanProductCreateResponseLP2AdvancedPaymentZeroInterestChargeOff";
|
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF = "loanProductCreateResponseLP2AdvancedPaymentZeroInterestChargeOff";
|
||||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_DELINQUENT_REASON = "loanProductCreateResponseLP2AdvancedPaymentZeroInterestChargeOffDelinquentReason";
|
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_DELINQUENT_REASON = "loanProductCreateResponseLP2AdvancedPaymentZeroInterestChargeOffDelinquentReason";
|
||||||
|
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_DELINQUENT_REASON_INTEREST_RECALC = "loanProductCreateResponseLP2AdvancedPaymentZeroInterestChargeOffDelinquentReasonInterestRecalculation";
|
||||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADVANCED_DP_CUSTOM_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE = "loanProductCreateResponseLP2ProgressiveLoanScheduleDPCustomPaymentAllocation";
|
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADVANCED_DP_CUSTOM_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE = "loanProductCreateResponseLP2ProgressiveLoanScheduleDPCustomPaymentAllocation";
|
||||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADVANCED_DP_IR_CUSTOM_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE = "loanProductCreateResponseLP2ProgressiveLoanScheduleDPIRCustomPaymentAllocation";
|
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADVANCED_DP_IR_CUSTOM_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE = "loanProductCreateResponseLP2ProgressiveLoanScheduleDPIRCustomPaymentAllocation";
|
||||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_ALLOW_PARTIAL_PERIOD = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationDailyAllowPartialPeriod";
|
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_ALLOW_PARTIAL_PERIOD = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationDailyAllowPartialPeriod";
|
||||||
|
|||||||
@@ -8123,3 +8123,225 @@ Feature: Charge-off
|
|||||||
And Loan Charges tab has the following data:
|
And Loan Charges tab has the following data:
|
||||||
| Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding |
|
| Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding |
|
||||||
| Snooze fee | false | Specified due date | 23 January 2024 | Flat | 5.0 | 0.0 | 5.0 | 0.0 |
|
| Snooze fee | false | Specified due date | 23 January 2024 | Flat | 5.0 | 0.0 | 5.0 | 0.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3611
|
||||||
|
Scenario: As a user I want to verify that backdated transactions are allowed after charge-off and backdated full repayment, interestRecalculation = false
|
||||||
|
When Admin sets the business date to "11 March 2025"
|
||||||
|
And Admin creates a client with random data
|
||||||
|
And Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_DELINQUENT_REASON | 11 March 2025 | 500 | 7 | DECLINING_BALANCE | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "11 March 2025" with "500" amount and expected disbursement date on "11 March 2025"
|
||||||
|
And Admin successfully disburse the loan on "11 March 2025" with "500" 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 | Waived | Outstanding |
|
||||||
|
| | | 11 March 2025 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | | |
|
||||||
|
| 1 | 31 | 11 April 2025 | | 417.97 | 82.03 | 2.97 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 2 | 30 | 11 May 2025 | | 335.37 | 82.6 | 2.4 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 3 | 31 | 11 June 2025 | | 252.36 | 83.01 | 1.99 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 4 | 30 | 11 July 2025 | | 168.81 | 83.55 | 1.45 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 5 | 31 | 11 August 2025 | | 84.81 | 84.0 | 1.0 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 6 | 31 | 11 September 2025| | 0.0 | 84.81 | 0.5 | 0.0 | 0.0 | 85.31 | 0.0 | 0.0 | 0.0 | 0.0 | 85.31 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Waived | Outstanding |
|
||||||
|
| 500.0 | 10.31 | 0.0 | 0 | 510.31 | 0.0 | 0 | 0 | 0.0 | 510.31 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||||
|
| 11 March 2025 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 | false | false |
|
||||||
|
Then Admin can successfully set Fraud flag to the loan
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "14 April 2025"
|
||||||
|
And Admin does charge-off the loan with reason "DELINQUENT" on "14 April 2025"
|
||||||
|
Then Loan marked as charged-off on "14 April 2025"
|
||||||
|
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 | Waived | Outstanding |
|
||||||
|
| | | 11 March 2025 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | | |
|
||||||
|
| 1 | 31 | 11 April 2025 | | 417.97 | 82.03 | 2.97 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 2 | 30 | 11 May 2025 | | 333.21 | 84.76 | 0.24 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 3 | 31 | 11 June 2025 | | 248.21 | 85.0 | 0.0 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 4 | 30 | 11 July 2025 | | 163.21 | 85.0 | 0.0 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 5 | 31 | 11 August 2025 | | 78.21 | 85.0 | 0.0 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 6 | 31 | 11 September 2025 | | 0.0 | 78.21 | 0.0 | 0.0 | 0.0 | 78.21 | 0.0 | 0.0 | 0.0 | 0.0 | 78.21 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Waived | Outstanding |
|
||||||
|
| 500.0 | 3.21 | 0.0 | 0 | 503.21 | 0 | 0 | 0 | 0.0 | 503.21 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||||
|
| 11 March 2025 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 | false | false |
|
||||||
|
| 14 April 2025 | Accrual | 3.21 | 0.0 | 3.21 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 14 April 2025 | Charge-off | 503.21 | 500.0 | 3.21 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Customer makes "REPAYMENT" transaction with "AUTOPAY" payment type on "13 April 2025" with 500 EUR transaction amount and system-generated Idempotency key
|
||||||
|
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 | Waived | Outstanding |
|
||||||
|
| | | 11 March 2025 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | | |
|
||||||
|
| 1 | 31 | 11 April 2025 | 13 April 2025 | 417.97 | 82.03 | 2.97 | 0.0 | 0.0 | 85.0 | 85.0 | 0.0 | 85.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 30 | 11 May 2025 | 13 April 2025 | 335.37 | 82.6 | 2.4 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 31 | 11 June 2025 | 13 April 2025 | 252.36 | 83.01 | 1.99 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 30 | 11 July 2025 | 13 April 2025 | 168.81 | 83.55 | 1.45 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 5 | 31 | 11 August 2025 | 13 April 2025 | 84.81 | 84.0 | 1.0 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 6 | 31 | 11 September 2025 | | 0.0 | 84.81 | 0.0 | 0.0 | 0.0 | 84.81 | 75.0 | 75.0 | 0.0 | 0.0 | 9.81 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Waived | Outstanding |
|
||||||
|
| 500.0 | 9.81 | 0.0 | 0 | 509.81 | 500.0 | 415.0 | 85.0 | 0.0 | 9.81 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||||
|
| 11 March 2025 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 | false | false |
|
||||||
|
| 13 April 2025 | Repayment | 500.0 | 490.19 | 9.81 | 0.0 | 0.0 | 9.81 | false | false |
|
||||||
|
| 14 April 2025 | Accrual | 3.21 | 0.0 | 3.21 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 14 April 2025 | Accrual Adjustment | 0.24 | 0.0 | 0.24 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 14 April 2025 | Charge-off | 9.81 | 9.81 | 0.0 | 0.0 | 0.0 | 0.0 | false | true |
|
||||||
|
When Customer makes "MERCHANT_ISSUED_REFUND" transaction with "AUTOPAY" payment type on "13 April 2025" with 500 EUR transaction amount and system-generated Idempotency key
|
||||||
|
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 | Waived | Outstanding |
|
||||||
|
| | | 11 March 2025 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | | |
|
||||||
|
| 1 | 31 | 11 April 2025 | 13 April 2025 | 417.97 | 82.03 | 2.97 | 0.0 | 0.0 | 85.0 | 85.0 | 0.0 | 85.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 30 | 11 May 2025 | 13 April 2025 | 335.37 | 82.6 | 2.4 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 31 | 11 June 2025 | 13 April 2025 | 252.36 | 83.01 | 1.99 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 30 | 11 July 2025 | 13 April 2025 | 168.81 | 83.55 | 1.45 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 5 | 31 | 11 August 2025 | 13 April 2025 | 84.81 | 84.0 | 1.0 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 6 | 31 | 11 September 2025 | 13 April 2025 | 0.0 | 84.81 | 0.5 | 0.0 | 0.0 | 85.31 | 85.31 | 85.31 | 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 | Waived | Outstanding |
|
||||||
|
| 500.0 | 10.31 | 0.0 | 0 | 510.31 | 510.31 | 425.31 | 85.0 | 0.0 | 0.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||||
|
| 11 March 2025 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 | false | false |
|
||||||
|
| 13 April 2025 | Repayment | 500.0 | 490.19 | 9.81 | 0.0 | 0.0 | 9.81 | false | false |
|
||||||
|
| 13 April 2025 | Merchant Issued Refund | 500.0 | 9.81 | 0.5 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 14 April 2025 | Accrual | 3.21 | 0.0 | 3.21 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 14 April 2025 | Accrual Adjustment | 0.24 | 0.0 | 0.24 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 14 April 2025 | Charge-off | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | false | true |
|
||||||
|
When Customer makes "GOODWILL_CREDIT" transaction with "AUTOPAY" payment type on "13 April 2025" with 500 EUR transaction amount and system-generated Idempotency key
|
||||||
|
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 | Waived | Outstanding |
|
||||||
|
| | | 11 March 2025 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | | |
|
||||||
|
| 1 | 31 | 11 April 2025 | 13 April 2025 | 417.97 | 82.03 | 2.97 | 0.0 | 0.0 | 85.0 | 85.0 | 0.0 | 85.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 30 | 11 May 2025 | 13 April 2025 | 335.37 | 82.6 | 2.4 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 31 | 11 June 2025 | 13 April 2025 | 252.36 | 83.01 | 1.99 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 30 | 11 July 2025 | 13 April 2025 | 168.81 | 83.55 | 1.45 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 5 | 31 | 11 August 2025 | 13 April 2025 | 84.81 | 84.0 | 1.0 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 6 | 31 | 11 September 2025 | 13 April 2025 | 0.0 | 84.81 | 0.5 | 0.0 | 0.0 | 85.31 | 85.31 | 85.31 | 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 | Waived | Outstanding |
|
||||||
|
| 500.0 | 10.31 | 0.0 | 0 | 510.31 | 510.31 | 425.31 | 85.0 | 0.0 | 0.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||||
|
| 11 March 2025 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 | false | false |
|
||||||
|
| 13 April 2025 | Repayment | 500.0 | 490.19 | 9.81 | 0.0 | 0.0 | 9.81 | false | false |
|
||||||
|
| 13 April 2025 | Merchant Issued Refund | 500.0 | 9.81 | 0.5 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 13 April 2025 | Goodwill Credit | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 14 April 2025 | Accrual | 3.21 | 0.0 | 3.21 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 14 April 2025 | Accrual Adjustment | 0.24 | 0.0 | 0.24 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 14 April 2025 | Charge-off | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | false | true |
|
||||||
|
|
||||||
|
@TestRailId:C3612
|
||||||
|
Scenario: As a user I want to verify that backdated transactions are allowed after charge-off and backdated full repayment, interestRecalculation = true
|
||||||
|
When Admin sets the business date to "11 March 2025"
|
||||||
|
And Admin creates a client with random data
|
||||||
|
And Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_DELINQUENT_REASON_INTEREST_RECALC | 11 March 2025 | 500 | 7 | DECLINING_BALANCE | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "11 March 2025" with "500" amount and expected disbursement date on "11 March 2025"
|
||||||
|
And Admin successfully disburse the loan on "11 March 2025" with "500" 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 | Waived | Outstanding |
|
||||||
|
| | | 11 March 2025 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | | |
|
||||||
|
| 1 | 31 | 11 April 2025 | | 417.97 | 82.03 | 2.97 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 2 | 30 | 11 May 2025 | | 335.37 | 82.6 | 2.4 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 3 | 31 | 11 June 2025 | | 252.36 | 83.01 | 1.99 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 4 | 30 | 11 July 2025 | | 168.81 | 83.55 | 1.45 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 5 | 31 | 11 August 2025 | | 84.81 | 84.0 | 1.0 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 6 | 31 | 11 September 2025| | 0.0 | 84.81 | 0.5 | 0.0 | 0.0 | 85.31 | 0.0 | 0.0 | 0.0 | 0.0 | 85.31 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Waived | Outstanding |
|
||||||
|
| 500.0 | 10.31 | 0.0 | 0 | 510.31 | 0.0 | 0 | 0 | 0.0 | 510.31 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||||
|
| 11 March 2025 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 | false | false |
|
||||||
|
Then Admin can successfully set Fraud flag to the loan
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "14 April 2025"
|
||||||
|
And Admin does charge-off the loan with reason "DELINQUENT" on "14 April 2025"
|
||||||
|
Then Loan marked as charged-off on "14 April 2025"
|
||||||
|
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 | Waived | Outstanding |
|
||||||
|
| | | 11 March 2025 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | | |
|
||||||
|
| 1 | 31 | 11 April 2025 | | 417.97 | 82.03 | 2.97 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 2 | 30 | 11 May 2025 | | 333.26 | 84.71 | 0.29 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 3 | 31 | 11 June 2025 | | 248.26 | 85.0 | 0.0 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 4 | 30 | 11 July 2025 | | 163.26 | 85.0 | 0.0 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 5 | 31 | 11 August 2025 | | 78.26 | 85.0 | 0.0 | 0.0 | 0.0 | 85.0 | 0.0 | 0.0 | 0.0 | 0.0 | 85.0 |
|
||||||
|
| 6 | 31 | 11 September 2025 | | 0.0 | 78.26 | 0.0 | 0.0 | 0.0 | 78.26 | 0.0 | 0.0 | 0.0 | 0.0 | 78.26 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Waived | Outstanding |
|
||||||
|
| 500.0 | 3.26 | 0.0 | 0 | 503.26 | 0.0 | 0 | 0 | 0.0 | 503.26 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||||
|
| 11 March 2025 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 | false | false |
|
||||||
|
| 14 April 2025 | Accrual | 3.26 | 0.0 | 3.26 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 14 April 2025 | Charge-off | 503.26 | 500.0 | 3.26 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Customer makes "REPAYMENT" transaction with "AUTOPAY" payment type on "13 April 2025" with 500 EUR transaction amount and system-generated Idempotency key
|
||||||
|
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 | Waived | Outstanding |
|
||||||
|
| | | 11 March 2025 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | | |
|
||||||
|
| 1 | 31 | 11 April 2025 | 13 April 2025 | 417.97 | 82.03 | 2.97 | 0.0 | 0.0 | 85.0 | 85.0 | 0.0 | 85.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 30 | 11 May 2025 | 13 April 2025 | 333.16 | 84.81 | 0.19 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 31 | 11 June 2025 | 13 April 2025 | 248.16 | 85.0 | 0.0 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 30 | 11 July 2025 | 13 April 2025 | 163.16 | 85.0 | 0.0 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 5 | 31 | 11 August 2025 | 13 April 2025 | 78.16 | 85.0 | 0.0 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 6 | 31 | 11 September 2025 | | 0.0 | 78.16 | 0.0 | 0.0 | 0.0 | 78.16 | 75.0 | 75.0 | 0.0 | 0.0 | 3.16 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Waived | Outstanding |
|
||||||
|
| 500.0 | 3.16 | 0.0 | 0 | 503.16 | 500.0 | 415.0 | 85.0 | 0.0 | 3.16 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||||
|
| 11 March 2025 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 | false | false |
|
||||||
|
| 13 April 2025 | Repayment | 500.0 | 496.84 | 3.16 | 0.0 | 0.0 | 3.16 | false | false |
|
||||||
|
| 14 April 2025 | Accrual | 3.26 | 0.0 | 3.26 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 14 April 2025 | Accrual Adjustment | 0.1 | 0.0 | 0.1 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 14 April 2025 | Charge-off | 3.16 | 3.16 | 0.0 | 0.0 | 0.0 | 0.0 | false | true |
|
||||||
|
When Customer makes "MERCHANT_ISSUED_REFUND" transaction with "AUTOPAY" payment type on "13 April 2025" with 500 EUR transaction amount and system-generated Idempotency key
|
||||||
|
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 | Waived | Outstanding |
|
||||||
|
| | | 11 March 2025 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | | |
|
||||||
|
| 1 | 31 | 11 April 2025 | 13 April 2025 | 417.97 | 82.03 | 2.97 | 0.0 | 0.0 | 85.0 | 85.0 | 0.0 | 85.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 30 | 11 May 2025 | 13 April 2025 | 333.16 | 84.81 | 0.19 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 31 | 11 June 2025 | 13 April 2025 | 248.16 | 85.0 | 0.0 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 30 | 11 July 2025 | 13 April 2025 | 163.16 | 85.0 | 0.0 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 5 | 31 | 11 August 2025 | 13 April 2025 | 78.16 | 85.0 | 0.0 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 6 | 31 | 11 September 2025 | 13 April 2025 | 0.0 | 78.16 | 0.0 | 0.0 | 0.0 | 78.16 | 78.16 | 78.16 | 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 | Waived | Outstanding |
|
||||||
|
| 500.0 | 3.16 | 0.0 | 0 | 503.16 | 503.16 | 418.16 | 85.0 | 0.0 | 0.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||||
|
| 11 March 2025 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 | false | false |
|
||||||
|
| 13 April 2025 | Repayment | 500.0 | 496.84 | 3.16 | 0.0 | 0.0 | 3.16 | false | false |
|
||||||
|
| 13 April 2025 | Merchant Issued Refund | 500.0 | 3.16 | 0.0 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 14 April 2025 | Accrual | 3.26 | 0.0 | 3.26 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 14 April 2025 | Accrual Adjustment | 0.1 | 0.0 | 0.1 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 14 April 2025 | Charge-off | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | false | true |
|
||||||
|
When Customer makes "GOODWILL_CREDIT" transaction with "AUTOPAY" payment type on "13 April 2025" with 500 EUR transaction amount and system-generated Idempotency key
|
||||||
|
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 | Waived | Outstanding |
|
||||||
|
| | | 11 March 2025 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | | |
|
||||||
|
| 1 | 31 | 11 April 2025 | 13 April 2025 | 417.97 | 82.03 | 2.97 | 0.0 | 0.0 | 85.0 | 85.0 | 0.0 | 85.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 30 | 11 May 2025 | 13 April 2025 | 333.16 | 84.81 | 0.19 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 31 | 11 June 2025 | 13 April 2025 | 248.16 | 85.0 | 0.0 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 30 | 11 July 2025 | 13 April 2025 | 163.16 | 85.0 | 0.0 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 5 | 31 | 11 August 2025 | 13 April 2025 | 78.16 | 85.0 | 0.0 | 0.0 | 0.0 | 85.0 | 85.0 | 85.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 6 | 31 | 11 September 2025 | 13 April 2025 | 0.0 | 78.16 | 0.0 | 0.0 | 0.0 | 78.16 | 78.16 | 78.16 | 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 | Waived | Outstanding |
|
||||||
|
| 500.0 | 3.16 | 0.0 | 0 | 503.16 | 503.16 | 418.16 | 85.0 | 0.0 | 0.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||||
|
| 11 March 2025 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 | false | false |
|
||||||
|
| 13 April 2025 | Repayment | 500.0 | 496.84 | 3.16 | 0.0 | 0.0 | 3.16 | false | false |
|
||||||
|
| 13 April 2025 | Merchant Issued Refund | 500.0 | 3.16 | 0.0 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 13 April 2025 | Goodwill Credit | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 14 April 2025 | Accrual | 3.26 | 0.0 | 3.26 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 14 April 2025 | Accrual Adjustment | 0.1 | 0.0 | 0.1 | 0.0 | 0.0 | 0.0 | false | false |
|
||||||
|
| 14 April 2025 | Charge-off | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | false | true |
|
||||||
|
|||||||
+30
-21
@@ -1400,20 +1400,25 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
if (!installments.isEmpty() && transactionDate.isBefore(loan.getMaturityDate())) {
|
if (!installments.isEmpty() && transactionDate.isBefore(loan.getMaturityDate())) {
|
||||||
if (transactionCtx instanceof ProgressiveTransactionCtx progressiveTransactionCtx
|
if (transactionCtx instanceof ProgressiveTransactionCtx progressiveTransactionCtx
|
||||||
&& loanTransaction.getLoan().isInterestBearingAndInterestRecalculationEnabled()) {
|
&& loanTransaction.getLoan().isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
|
final BigDecimal interestOutstanding = currentInstallment.getInterestOutstanding(loan.getCurrency()).getAmount();
|
||||||
final BigDecimal newInterest = emiCalculator.getPeriodInterestTillDate(progressiveTransactionCtx.getModel(),
|
final BigDecimal newInterest = emiCalculator.getPeriodInterestTillDate(progressiveTransactionCtx.getModel(),
|
||||||
currentInstallment.getDueDate(), transactionDate, true).getAmount();
|
currentInstallment.getDueDate(), transactionDate, true).getAmount();
|
||||||
currentInstallment.updateInterestCharged(newInterest);
|
if (interestOutstanding.compareTo(BigDecimal.ZERO) > 0 || newInterest.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
currentInstallment.updateInterestCharged(newInterest);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
final BigDecimal totalInterest = currentInstallment.getInterestOutstanding(transactionCtx.getCurrency()).getAmount();
|
final BigDecimal totalInterest = currentInstallment.getInterestOutstanding(transactionCtx.getCurrency()).getAmount();
|
||||||
final long totalDaysInPeriod = ChronoUnit.DAYS.between(currentInstallment.getFromDate(), currentInstallment.getDueDate());
|
if (totalInterest.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
final long daysTillChargeOff = ChronoUnit.DAYS.between(currentInstallment.getFromDate(), transactionDate);
|
final long totalDaysInPeriod = ChronoUnit.DAYS.between(currentInstallment.getFromDate(),
|
||||||
|
currentInstallment.getDueDate());
|
||||||
|
final long daysTillChargeOff = ChronoUnit.DAYS.between(currentInstallment.getFromDate(), transactionDate);
|
||||||
|
|
||||||
final MathContext mc = MoneyHelper.getMathContext();
|
final MathContext mc = MoneyHelper.getMathContext();
|
||||||
final Money interestTillChargeOff = Money.of(transactionCtx.getCurrency(),
|
final Money interestTillChargeOff = Money.of(transactionCtx.getCurrency(), totalInterest
|
||||||
totalInterest.divide(BigDecimal.valueOf(totalDaysInPeriod), mc).multiply(BigDecimal.valueOf(daysTillChargeOff), mc),
|
.divide(BigDecimal.valueOf(totalDaysInPeriod), mc).multiply(BigDecimal.valueOf(daysTillChargeOff), mc), mc);
|
||||||
mc);
|
|
||||||
|
|
||||||
currentInstallment.updateInterestCharged(interestTillChargeOff.getAmount());
|
currentInstallment.updateInterestCharged(interestTillChargeOff.getAmount());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
currentInstallment.updateDueDate(transactionDate);
|
currentInstallment.updateDueDate(transactionDate);
|
||||||
@@ -1478,25 +1483,27 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
private void handleZeroInterestChargeOff(final LoanTransaction loanTransaction, final TransactionCtx transactionCtx) {
|
private void handleZeroInterestChargeOff(final LoanTransaction loanTransaction, final TransactionCtx transactionCtx) {
|
||||||
final LocalDate transactionDate = loanTransaction.getTransactionDate();
|
final LocalDate transactionDate = loanTransaction.getTransactionDate();
|
||||||
final List<LoanRepaymentScheduleInstallment> installments = transactionCtx.getInstallments();
|
final List<LoanRepaymentScheduleInstallment> installments = transactionCtx.getInstallments();
|
||||||
|
final MonetaryCurrency currency = loanTransaction.getLoan().getCurrency();
|
||||||
|
|
||||||
if (!installments.isEmpty()) {
|
if (!installments.isEmpty()) {
|
||||||
if (transactionCtx instanceof ProgressiveTransactionCtx progressiveTransactionCtx
|
if (transactionCtx instanceof ProgressiveTransactionCtx progressiveTransactionCtx
|
||||||
&& loanTransaction.getLoan().isInterestBearingAndInterestRecalculationEnabled()) {
|
&& loanTransaction.getLoan().isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
installments.stream().filter(installment -> !installment.getFromDate().isAfter(transactionDate)
|
installments.stream().filter(installment -> !installment.getFromDate().isAfter(transactionDate)
|
||||||
&& installment.getDueDate().isAfter(transactionDate)).forEach(installment -> {
|
&& installment.getDueDate().isAfter(transactionDate)).forEach(installment -> {
|
||||||
|
final BigDecimal interestOutstanding = installment.getInterestOutstanding(currency).getAmount();
|
||||||
final BigDecimal newInterest = emiCalculator.getPeriodInterestTillDate(progressiveTransactionCtx.getModel(),
|
final BigDecimal newInterest = emiCalculator.getPeriodInterestTillDate(progressiveTransactionCtx.getModel(),
|
||||||
installment.getDueDate(), transactionDate, true).getAmount();
|
installment.getDueDate(), transactionDate, true).getAmount();
|
||||||
final BigDecimal interestRemoved = installment.getInterestCharged().subtract(newInterest);
|
if (interestOutstanding.compareTo(BigDecimal.ZERO) > 0 || newInterest.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
installment.updatePrincipal(MathUtil.nullToZero(installment.getPrincipal()).add(interestRemoved));
|
final BigDecimal interestRemoved = installment.getInterestCharged().subtract(newInterest);
|
||||||
installment.updateInterestCharged(newInterest);
|
installment.updatePrincipal(MathUtil.nullToZero(installment.getPrincipal()).add(interestRemoved));
|
||||||
|
installment.updateInterestCharged(newInterest);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
progressiveTransactionCtx.setChargedOff(true);
|
progressiveTransactionCtx.setChargedOff(true);
|
||||||
} else {
|
} else {
|
||||||
calculatePartialPeriodInterest(transactionCtx, transactionDate);
|
calculatePartialPeriodInterest(transactionCtx, transactionDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
final MonetaryCurrency currency = loanTransaction.getLoan().getCurrency();
|
|
||||||
|
|
||||||
installments.stream()
|
installments.stream()
|
||||||
.filter(installment -> installment.getFromDate().isAfter(transactionDate) && !installment.isObligationsMet())
|
.filter(installment -> installment.getFromDate().isAfter(transactionDate) && !installment.isObligationsMet())
|
||||||
.forEach(installment -> {
|
.forEach(installment -> {
|
||||||
@@ -1538,16 +1545,18 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
.filter(installment -> !installment.getFromDate().isAfter(chargeOffDate) && installment.getDueDate().isAfter(chargeOffDate))
|
.filter(installment -> !installment.getFromDate().isAfter(chargeOffDate) && installment.getDueDate().isAfter(chargeOffDate))
|
||||||
.forEach(installment -> {
|
.forEach(installment -> {
|
||||||
final BigDecimal totalInterest = installment.getInterestOutstanding(transactionCtx.getCurrency()).getAmount();
|
final BigDecimal totalInterest = installment.getInterestOutstanding(transactionCtx.getCurrency()).getAmount();
|
||||||
final long totalDaysInPeriod = ChronoUnit.DAYS.between(installment.getFromDate(), installment.getDueDate());
|
if (totalInterest.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
final long daysTillChargeOff = ChronoUnit.DAYS.between(installment.getFromDate(), chargeOffDate);
|
final long totalDaysInPeriod = ChronoUnit.DAYS.between(installment.getFromDate(), installment.getDueDate());
|
||||||
|
final long daysTillChargeOff = ChronoUnit.DAYS.between(installment.getFromDate(), chargeOffDate);
|
||||||
|
|
||||||
final MathContext mc = MoneyHelper.getMathContext();
|
final MathContext mc = MoneyHelper.getMathContext();
|
||||||
final Money interestTillChargeOff = Money.of(transactionCtx.getCurrency(), totalInterest
|
final Money interestTillChargeOff = Money.of(transactionCtx.getCurrency(), totalInterest
|
||||||
.divide(BigDecimal.valueOf(totalDaysInPeriod), mc).multiply(BigDecimal.valueOf(daysTillChargeOff), mc), mc);
|
.divide(BigDecimal.valueOf(totalDaysInPeriod), mc).multiply(BigDecimal.valueOf(daysTillChargeOff), mc), mc);
|
||||||
|
|
||||||
final BigDecimal interestRemoved = totalInterest.subtract(interestTillChargeOff.getAmount());
|
final BigDecimal interestRemoved = totalInterest.subtract(interestTillChargeOff.getAmount());
|
||||||
installment.updatePrincipal(MathUtil.nullToZero(installment.getPrincipal()).add(interestRemoved));
|
installment.updatePrincipal(MathUtil.nullToZero(installment.getPrincipal()).add(interestRemoved));
|
||||||
installment.updateInterestCharged(interestTillChargeOff.getAmount());
|
installment.updateInterestCharged(interestTillChargeOff.getAmount());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-6
@@ -60,6 +60,7 @@ import org.apache.fineract.accounting.producttoaccountmapping.exception.ProductT
|
|||||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.journalentry.LoanJournalEntryCreatedBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.journalentry.LoanJournalEntryCreatedBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
||||||
import org.apache.fineract.organisation.office.domain.Office;
|
import org.apache.fineract.organisation.office.domain.Office;
|
||||||
@@ -453,13 +454,19 @@ public class AccountingProcessorHelper {
|
|||||||
JournalAmountHolder totalAccountHolder, Long loanProductId, Long paymentTypeId, Long loanId, String transactionId,
|
JournalAmountHolder totalAccountHolder, Long loanProductId, Long paymentTypeId, Long loanId, String transactionId,
|
||||||
LocalDate transactionDate) {
|
LocalDate transactionDate) {
|
||||||
splitAccountsHolder.forEach(journalItemHolder -> {
|
splitAccountsHolder.forEach(journalItemHolder -> {
|
||||||
final GLAccount account = getLinkedGLAccountForLoanProduct(loanProductId, journalItemHolder.getAccountType(), paymentTypeId);
|
if (MathUtil.isGreaterThanZero(journalItemHolder.getAmount())) {
|
||||||
createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate,
|
final GLAccount account = getLinkedGLAccountForLoanProduct(loanProductId, journalItemHolder.getAccountType(),
|
||||||
journalItemHolder.getAmount());
|
paymentTypeId);
|
||||||
|
createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate,
|
||||||
|
journalItemHolder.getAmount());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
final GLAccount totalAccount = getLinkedGLAccountForLoanProduct(loanProductId, totalAccountHolder.getAccountType(), paymentTypeId);
|
if (MathUtil.isGreaterThanZero(totalAccountHolder.getAmount())) {
|
||||||
createCreditJournalEntryForLoan(office, currencyCode, totalAccount, loanId, transactionId, transactionDate,
|
final GLAccount totalAccount = getLinkedGLAccountForLoanProduct(loanProductId, totalAccountHolder.getAccountType(),
|
||||||
totalAccountHolder.getAmount());
|
paymentTypeId);
|
||||||
|
createCreditJournalEntryForLoan(office, currencyCode, totalAccount, loanId, transactionId, transactionDate,
|
||||||
|
totalAccountHolder.getAmount());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createCreditJournalEntryForLoan(final Office office, final String currencyCode,
|
public void createCreditJournalEntryForLoan(final Office office, final String currencyCode,
|
||||||
|
|||||||
+141
-115
@@ -147,75 +147,79 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
if (isMarkedAsChargeOff) {
|
if (isMarkedAsChargeOff) {
|
||||||
// ChargeOFF
|
// ChargeOFF
|
||||||
// principal payment
|
// principal payment
|
||||||
if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(principalAmount)) {
|
||||||
populateCreditDebitMaps(loanProductId, principalAmount, paymentTypeId,
|
populateCreditDebitMaps(loanProductId, principalAmount, paymentTypeId,
|
||||||
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_INTEREST.getValue(),
|
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_INTEREST.getValue(),
|
||||||
AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), glAccountBalanceHolder);
|
AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), glAccountBalanceHolder);
|
||||||
}
|
}
|
||||||
// interest payment
|
// interest payment
|
||||||
if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(interestAmount)) {
|
||||||
populateCreditDebitMaps(loanProductId, interestAmount, paymentTypeId,
|
populateCreditDebitMaps(loanProductId, interestAmount, paymentTypeId,
|
||||||
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_INTEREST.getValue(),
|
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_INTEREST.getValue(),
|
||||||
AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), glAccountBalanceHolder);
|
AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), glAccountBalanceHolder);
|
||||||
}
|
}
|
||||||
// handle fees payment
|
// handle fees payment
|
||||||
if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(feesAmount)) {
|
||||||
populateCreditDebitMaps(loanProductId, feesAmount, paymentTypeId,
|
populateCreditDebitMaps(loanProductId, feesAmount, paymentTypeId,
|
||||||
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_INTEREST.getValue(),
|
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_INTEREST.getValue(),
|
||||||
AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), glAccountBalanceHolder);
|
AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), glAccountBalanceHolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle penalty payment
|
// handle penalty payment
|
||||||
if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(penaltiesAmount)) {
|
||||||
populateCreditDebitMaps(loanProductId, penaltiesAmount, paymentTypeId,
|
populateCreditDebitMaps(loanProductId, penaltiesAmount, paymentTypeId,
|
||||||
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_INTEREST.getValue(),
|
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_INTEREST.getValue(),
|
||||||
AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), glAccountBalanceHolder);
|
AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), glAccountBalanceHolder);
|
||||||
}
|
}
|
||||||
// handle overpayment
|
// handle overpayment
|
||||||
if (overPayment != null && overPayment.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(overPayment)) {
|
||||||
populateCreditDebitMaps(loanProductId, overPayment, paymentTypeId, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
|
populateCreditDebitMaps(loanProductId, overPayment, paymentTypeId, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
|
||||||
AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), glAccountBalanceHolder);
|
AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), glAccountBalanceHolder);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// principal payment
|
// principal payment
|
||||||
if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(principalAmount)) {
|
||||||
populateCreditDebitMaps(loanProductId, principalAmount, paymentTypeId, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
|
populateCreditDebitMaps(loanProductId, principalAmount, paymentTypeId, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
|
||||||
AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), glAccountBalanceHolder);
|
AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), glAccountBalanceHolder);
|
||||||
}
|
}
|
||||||
// interest payment
|
// interest payment
|
||||||
if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(interestAmount)) {
|
||||||
populateCreditDebitMaps(loanProductId, interestAmount, paymentTypeId, AccrualAccountsForLoan.INTEREST_RECEIVABLE.getValue(),
|
populateCreditDebitMaps(loanProductId, interestAmount, paymentTypeId, AccrualAccountsForLoan.INTEREST_RECEIVABLE.getValue(),
|
||||||
AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), glAccountBalanceHolder);
|
AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), glAccountBalanceHolder);
|
||||||
}
|
}
|
||||||
// handle fees payment
|
// handle fees payment
|
||||||
if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(feesAmount)) {
|
||||||
populateCreditDebitMaps(loanProductId, feesAmount, paymentTypeId, AccrualAccountsForLoan.FEES_RECEIVABLE.getValue(),
|
populateCreditDebitMaps(loanProductId, feesAmount, paymentTypeId, AccrualAccountsForLoan.FEES_RECEIVABLE.getValue(),
|
||||||
AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), glAccountBalanceHolder);
|
AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), glAccountBalanceHolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle penalty payment
|
// handle penalty payment
|
||||||
if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(penaltiesAmount)) {
|
||||||
populateCreditDebitMaps(loanProductId, penaltiesAmount, paymentTypeId,
|
populateCreditDebitMaps(loanProductId, penaltiesAmount, paymentTypeId,
|
||||||
AccrualAccountsForLoan.PENALTIES_RECEIVABLE.getValue(), AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(),
|
AccrualAccountsForLoan.PENALTIES_RECEIVABLE.getValue(), AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(),
|
||||||
glAccountBalanceHolder);
|
glAccountBalanceHolder);
|
||||||
}
|
}
|
||||||
// handle overpayment
|
// handle overpayment
|
||||||
if (overPayment != null && overPayment.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(overPayment)) {
|
||||||
populateCreditDebitMaps(loanProductId, overPayment, paymentTypeId, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
|
populateCreditDebitMaps(loanProductId, overPayment, paymentTypeId, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
|
||||||
AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), glAccountBalanceHolder);
|
AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(), glAccountBalanceHolder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// create credit entries
|
// create credit entries
|
||||||
for (Map.Entry<Long, BigDecimal> creditEntry : glAccountBalanceHolder.getCreditBalances().entrySet()) {
|
for (Map.Entry<Long, BigDecimal> creditEntry : glAccountBalanceHolder.getCreditBalances().entrySet()) {
|
||||||
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(creditEntry.getKey());
|
if (MathUtil.isGreaterThanZero(creditEntry.getValue())) {
|
||||||
this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate,
|
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(creditEntry.getKey());
|
||||||
creditEntry.getValue(), glAccount);
|
this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate,
|
||||||
|
creditEntry.getValue(), glAccount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// create debit entries
|
// create debit entries
|
||||||
for (Map.Entry<Long, BigDecimal> debitEntry : glAccountBalanceHolder.getDebitBalances().entrySet()) {
|
for (Map.Entry<Long, BigDecimal> debitEntry : glAccountBalanceHolder.getDebitBalances().entrySet()) {
|
||||||
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(debitEntry.getKey());
|
if (MathUtil.isGreaterThanZero(debitEntry.getValue())) {
|
||||||
this.helper.createDebitJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate, debitEntry.getValue(),
|
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(debitEntry.getKey());
|
||||||
glAccount);
|
this.helper.createDebitJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate,
|
||||||
|
debitEntry.getValue(), glAccount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,14 +245,15 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
ProductToGLAccountMapping mapping = chargeOffReasonCodeValue != null
|
ProductToGLAccountMapping mapping = chargeOffReasonCodeValue != null
|
||||||
? helper.getChargeOffMappingByCodeValue(loanProductId, PortfolioProductType.LOAN, chargeOffReasonCodeValue)
|
? helper.getChargeOffMappingByCodeValue(loanProductId, PortfolioProductType.LOAN, chargeOffReasonCodeValue)
|
||||||
: null;
|
: null;
|
||||||
if (mapping != null) {
|
|
||||||
GLAccount accountCredit = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
if (MathUtil.isGreaterThanZero(principalAmount)) {
|
||||||
AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(), paymentTypeId);
|
if (mapping != null) {
|
||||||
glAccountBalanceHolder.addToCredit(accountCredit, principalAmount);
|
GLAccount accountCredit = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
||||||
glAccountBalanceHolder.addToDebit(mapping.getGlAccount(), principalAmount);
|
AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(), paymentTypeId);
|
||||||
} else {
|
glAccountBalanceHolder.addToCredit(accountCredit, principalAmount);
|
||||||
// principal payment
|
glAccountBalanceHolder.addToDebit(mapping.getGlAccount(), principalAmount);
|
||||||
if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
|
} else {
|
||||||
|
// principal payment
|
||||||
if (isMarkedFraud) {
|
if (isMarkedFraud) {
|
||||||
populateCreditDebitMaps(loanProductId, principalAmount, paymentTypeId, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
|
populateCreditDebitMaps(loanProductId, principalAmount, paymentTypeId, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
|
||||||
AccrualAccountsForLoan.CHARGE_OFF_FRAUD_EXPENSE.getValue(), glAccountBalanceHolder);
|
AccrualAccountsForLoan.CHARGE_OFF_FRAUD_EXPENSE.getValue(), glAccountBalanceHolder);
|
||||||
@@ -259,43 +264,48 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// interest payment
|
// interest payment
|
||||||
if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(interestAmount)) {
|
||||||
|
|
||||||
populateCreditDebitMaps(loanProductId, interestAmount, paymentTypeId, AccrualAccountsForLoan.INTEREST_RECEIVABLE.getValue(),
|
populateCreditDebitMaps(loanProductId, interestAmount, paymentTypeId, AccrualAccountsForLoan.INTEREST_RECEIVABLE.getValue(),
|
||||||
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_INTEREST.getValue(), glAccountBalanceHolder);
|
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_INTEREST.getValue(), glAccountBalanceHolder);
|
||||||
}
|
}
|
||||||
// handle fees payment
|
// handle fees payment
|
||||||
if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(feesAmount)) {
|
||||||
populateCreditDebitMaps(loanProductId, feesAmount, paymentTypeId, AccrualAccountsForLoan.FEES_RECEIVABLE.getValue(),
|
populateCreditDebitMaps(loanProductId, feesAmount, paymentTypeId, AccrualAccountsForLoan.FEES_RECEIVABLE.getValue(),
|
||||||
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_FEES.getValue(), glAccountBalanceHolder);
|
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_FEES.getValue(), glAccountBalanceHolder);
|
||||||
}
|
}
|
||||||
// handle penalty payment
|
// handle penalty payment
|
||||||
if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(penaltiesAmount)) {
|
||||||
populateCreditDebitMaps(loanProductId, penaltiesAmount, paymentTypeId, AccrualAccountsForLoan.PENALTIES_RECEIVABLE.getValue(),
|
populateCreditDebitMaps(loanProductId, penaltiesAmount, paymentTypeId, AccrualAccountsForLoan.PENALTIES_RECEIVABLE.getValue(),
|
||||||
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_PENALTY.getValue(), glAccountBalanceHolder);
|
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_PENALTY.getValue(), glAccountBalanceHolder);
|
||||||
}
|
}
|
||||||
// create credit entries
|
// create credit entries
|
||||||
for (Map.Entry<Long, BigDecimal> creditEntry : glAccountBalanceHolder.getCreditBalances().entrySet()) {
|
for (Map.Entry<Long, BigDecimal> creditEntry : glAccountBalanceHolder.getCreditBalances().entrySet()) {
|
||||||
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(creditEntry.getKey());
|
if (MathUtil.isGreaterThanZero(creditEntry.getValue())) {
|
||||||
this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate,
|
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(creditEntry.getKey());
|
||||||
creditEntry.getValue(), glAccount);
|
this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate,
|
||||||
|
creditEntry.getValue(), glAccount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// create debit entries
|
// create debit entries
|
||||||
for (Map.Entry<Long, BigDecimal> debitEntry : glAccountBalanceHolder.getDebitBalances().entrySet()) {
|
for (Map.Entry<Long, BigDecimal> debitEntry : glAccountBalanceHolder.getDebitBalances().entrySet()) {
|
||||||
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(debitEntry.getKey());
|
if (MathUtil.isGreaterThanZero(debitEntry.getValue())) {
|
||||||
this.helper.createDebitJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate, debitEntry.getValue(),
|
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(debitEntry.getKey());
|
||||||
glAccount);
|
this.helper.createDebitJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate,
|
||||||
|
debitEntry.getValue(), glAccount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void populateCreditDebitMaps(Long loanProductId, BigDecimal transactionPartAmount, Long paymentTypeId,
|
private void populateCreditDebitMaps(Long loanProductId, BigDecimal transactionPartAmount, Long paymentTypeId,
|
||||||
Integer creditAccountType, Integer debitAccountType, GLAccountBalanceHolder glAccountBalanceHolder) {
|
Integer creditAccountType, Integer debitAccountType, GLAccountBalanceHolder glAccountBalanceHolder) {
|
||||||
// Resolve Credit
|
if (MathUtil.isGreaterThanZero(transactionPartAmount)) {
|
||||||
GLAccount accountCredit = this.helper.getLinkedGLAccountForLoanProduct(loanProductId, creditAccountType, paymentTypeId);
|
// Resolve Credit
|
||||||
glAccountBalanceHolder.addToCredit(accountCredit, transactionPartAmount);
|
GLAccount accountCredit = this.helper.getLinkedGLAccountForLoanProduct(loanProductId, creditAccountType, paymentTypeId);
|
||||||
// Resolve Debit
|
glAccountBalanceHolder.addToCredit(accountCredit, transactionPartAmount);
|
||||||
GLAccount accountDebit = this.helper.getLinkedGLAccountForLoanProduct(loanProductId, debitAccountType, paymentTypeId);
|
// Resolve Debit
|
||||||
glAccountBalanceHolder.addToDebit(accountDebit, transactionPartAmount);
|
GLAccount accountDebit = this.helper.getLinkedGLAccountForLoanProduct(loanProductId, debitAccountType, paymentTypeId);
|
||||||
|
glAccountBalanceHolder.addToDebit(accountDebit, transactionPartAmount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createJournalEntriesForChargeAdjustment(LoanDTO loanDTO, LoanTransactionDTO loanTransactionDTO, Office office) {
|
private void createJournalEntriesForChargeAdjustment(LoanDTO loanDTO, LoanTransactionDTO loanTransactionDTO, Office office) {
|
||||||
@@ -329,7 +339,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
Map<GLAccount, BigDecimal> accountMap = new LinkedHashMap<>();
|
Map<GLAccount, BigDecimal> accountMap = new LinkedHashMap<>();
|
||||||
|
|
||||||
// handle principal payment
|
// handle principal payment
|
||||||
if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(principalAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(principalAmount);
|
totalDebitAmount = totalDebitAmount.add(principalAmount);
|
||||||
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
||||||
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_FEES.getValue(), paymentTypeId);
|
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_FEES.getValue(), paymentTypeId);
|
||||||
@@ -337,7 +347,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle interest payment
|
// handle interest payment
|
||||||
if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(interestAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(interestAmount);
|
totalDebitAmount = totalDebitAmount.add(interestAmount);
|
||||||
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
||||||
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_FEES.getValue(), paymentTypeId);
|
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_FEES.getValue(), paymentTypeId);
|
||||||
@@ -351,7 +361,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle fees payment
|
// handle fees payment
|
||||||
if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(feesAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(feesAmount);
|
totalDebitAmount = totalDebitAmount.add(feesAmount);
|
||||||
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
||||||
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_FEES.getValue(), paymentTypeId);
|
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_FEES.getValue(), paymentTypeId);
|
||||||
@@ -364,7 +374,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle penalty payment
|
// handle penalty payment
|
||||||
if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(penaltiesAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
|
totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
|
||||||
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
||||||
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_PENALTY.getValue(), paymentTypeId);
|
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_PENALTY.getValue(), paymentTypeId);
|
||||||
@@ -377,7 +387,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle overpayment
|
// handle overpayment
|
||||||
if (overPaymentAmount != null && overPaymentAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(overPaymentAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(overPaymentAmount);
|
totalDebitAmount = totalDebitAmount.add(overPaymentAmount);
|
||||||
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
|
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
|
||||||
paymentTypeId);
|
paymentTypeId);
|
||||||
@@ -390,11 +400,13 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (Map.Entry<GLAccount, BigDecimal> entry : accountMap.entrySet()) {
|
for (Map.Entry<GLAccount, BigDecimal> entry : accountMap.entrySet()) {
|
||||||
this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate, entry.getValue(),
|
if (MathUtil.isGreaterThanZero(entry.getValue())) {
|
||||||
entry.getKey());
|
this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate, entry.getValue(),
|
||||||
|
entry.getKey());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalDebitAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(totalDebitAmount)) {
|
||||||
Long chargeId = loanTransactionDTO.getLoanChargeData().getChargeId();
|
Long chargeId = loanTransactionDTO.getLoanChargeData().getChargeId();
|
||||||
Integer accountMappingTypeId;
|
Integer accountMappingTypeId;
|
||||||
if (loanTransactionDTO.getLoanChargeData().isPenalty()) {
|
if (loanTransactionDTO.getLoanChargeData().isPenalty()) {
|
||||||
@@ -428,7 +440,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
Map<GLAccount, BigDecimal> accountMap = new LinkedHashMap<>();
|
Map<GLAccount, BigDecimal> accountMap = new LinkedHashMap<>();
|
||||||
|
|
||||||
// handle principal payment
|
// handle principal payment
|
||||||
if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(principalAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(principalAmount);
|
totalDebitAmount = totalDebitAmount.add(principalAmount);
|
||||||
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
||||||
AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(), paymentTypeId);
|
AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(), paymentTypeId);
|
||||||
@@ -436,7 +448,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle interest payment
|
// handle interest payment
|
||||||
if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(interestAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(interestAmount);
|
totalDebitAmount = totalDebitAmount.add(interestAmount);
|
||||||
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
||||||
AccrualAccountsForLoan.INTEREST_RECEIVABLE.getValue(), paymentTypeId);
|
AccrualAccountsForLoan.INTEREST_RECEIVABLE.getValue(), paymentTypeId);
|
||||||
@@ -449,7 +461,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle fees payment
|
// handle fees payment
|
||||||
if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(feesAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(feesAmount);
|
totalDebitAmount = totalDebitAmount.add(feesAmount);
|
||||||
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
||||||
AccrualAccountsForLoan.FEES_RECEIVABLE.getValue(), paymentTypeId);
|
AccrualAccountsForLoan.FEES_RECEIVABLE.getValue(), paymentTypeId);
|
||||||
@@ -462,7 +474,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle penalties payment
|
// handle penalties payment
|
||||||
if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(penaltiesAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
|
totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
|
||||||
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
||||||
AccrualAccountsForLoan.PENALTIES_RECEIVABLE.getValue(), paymentTypeId);
|
AccrualAccountsForLoan.PENALTIES_RECEIVABLE.getValue(), paymentTypeId);
|
||||||
@@ -475,7 +487,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle overpayment
|
// handle overpayment
|
||||||
if (overPaymentAmount != null && overPaymentAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(overPaymentAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(overPaymentAmount);
|
totalDebitAmount = totalDebitAmount.add(overPaymentAmount);
|
||||||
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
|
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
|
||||||
paymentTypeId);
|
paymentTypeId);
|
||||||
@@ -488,11 +500,13 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (Map.Entry<GLAccount, BigDecimal> entry : accountMap.entrySet()) {
|
for (Map.Entry<GLAccount, BigDecimal> entry : accountMap.entrySet()) {
|
||||||
this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate, entry.getValue(),
|
if (MathUtil.isGreaterThanZero(entry.getValue())) {
|
||||||
entry.getKey());
|
this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate, entry.getValue(),
|
||||||
|
entry.getKey());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalDebitAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(totalDebitAmount)) {
|
||||||
Long chargeId = loanTransactionDTO.getLoanChargeData().getChargeId();
|
Long chargeId = loanTransactionDTO.getLoanChargeData().getChargeId();
|
||||||
Integer accountMappingTypeId;
|
Integer accountMappingTypeId;
|
||||||
if (loanTransactionDTO.getLoanChargeData().isPenalty()) {
|
if (loanTransactionDTO.getLoanChargeData().isPenalty()) {
|
||||||
@@ -538,10 +552,12 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
final BigDecimal penaltyPaid = Objects.isNull(loanTransactionDTO.getPenaltyPaid()) ? BigDecimal.ZERO
|
final BigDecimal penaltyPaid = Objects.isNull(loanTransactionDTO.getPenaltyPaid()) ? BigDecimal.ZERO
|
||||||
: loanTransactionDTO.getPenaltyPaid();
|
: loanTransactionDTO.getPenaltyPaid();
|
||||||
|
|
||||||
helper.createCreditJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.FUND_SOURCE, loanProductId, paymentTypeId,
|
if (MathUtil.isGreaterThanZero(amount)) {
|
||||||
loanId, transactionId, transactionDate, amount);
|
helper.createCreditJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.FUND_SOURCE, loanProductId, paymentTypeId,
|
||||||
|
loanId, transactionId, transactionDate, amount);
|
||||||
|
}
|
||||||
|
|
||||||
if (overpaidAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(overpaidAmount)) {
|
||||||
helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(), loanProductId,
|
helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(), loanProductId,
|
||||||
paymentTypeId, loanId, transactionId, transactionDate, overpaidAmount);
|
paymentTypeId, loanId, transactionId, transactionDate, overpaidAmount);
|
||||||
}
|
}
|
||||||
@@ -617,7 +633,8 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
final LocalDate transactionDate = loanTransactionDTO.getTransactionDate();
|
final LocalDate transactionDate = loanTransactionDTO.getTransactionDate();
|
||||||
final BigDecimal overpaymentPortion = loanTransactionDTO.getOverPayment() != null ? loanTransactionDTO.getOverPayment()
|
final BigDecimal overpaymentPortion = loanTransactionDTO.getOverPayment() != null ? loanTransactionDTO.getOverPayment()
|
||||||
: BigDecimal.ZERO;
|
: BigDecimal.ZERO;
|
||||||
final BigDecimal principalPortion = loanTransactionDTO.getAmount().subtract(overpaymentPortion);
|
final BigDecimal loanTransactionDTOAmount = loanTransactionDTO.getAmount();
|
||||||
|
final BigDecimal principalPortion = loanTransactionDTOAmount.subtract(overpaymentPortion);
|
||||||
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
|
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
|
||||||
|
|
||||||
// create journal entries for the disbursement
|
// create journal entries for the disbursement
|
||||||
@@ -630,15 +647,17 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(), loanProductId,
|
this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(), loanProductId,
|
||||||
paymentTypeId, loanId, transactionId, transactionDate, overpaymentPortion);
|
paymentTypeId, loanId, transactionId, transactionDate, overpaymentPortion);
|
||||||
}
|
}
|
||||||
if (loanTransactionDTO.isLoanToLoanTransfer()) {
|
if (MathUtil.isGreaterThanZero(loanTransactionDTOAmount)) {
|
||||||
this.helper.createCreditJournalEntryForLoan(office, currencyCode, FinancialActivity.ASSET_TRANSFER.getValue(), loanProductId,
|
if (loanTransactionDTO.isLoanToLoanTransfer()) {
|
||||||
paymentTypeId, loanId, transactionId, transactionDate, loanTransactionDTO.getAmount());
|
this.helper.createCreditJournalEntryForLoan(office, currencyCode, FinancialActivity.ASSET_TRANSFER.getValue(),
|
||||||
} else if (loanTransactionDTO.isAccountTransfer()) {
|
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, loanTransactionDTOAmount);
|
||||||
this.helper.createCreditJournalEntryForLoan(office, currencyCode, FinancialActivity.LIABILITY_TRANSFER.getValue(),
|
} else if (loanTransactionDTO.isAccountTransfer()) {
|
||||||
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, loanTransactionDTO.getAmount());
|
this.helper.createCreditJournalEntryForLoan(office, currencyCode, FinancialActivity.LIABILITY_TRANSFER.getValue(),
|
||||||
} else {
|
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, loanTransactionDTOAmount);
|
||||||
this.helper.createCreditJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.FUND_SOURCE.getValue(), loanProductId,
|
} else {
|
||||||
paymentTypeId, loanId, transactionId, transactionDate, loanTransactionDTO.getAmount());
|
this.helper.createCreditJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.FUND_SOURCE.getValue(),
|
||||||
|
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, loanTransactionDTOAmount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -705,7 +724,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
BigDecimal totalDebitAmount = new BigDecimal(0);
|
BigDecimal totalDebitAmount = new BigDecimal(0);
|
||||||
|
|
||||||
// principal payment
|
// principal payment
|
||||||
if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(principalAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(principalAmount);
|
totalDebitAmount = totalDebitAmount.add(principalAmount);
|
||||||
if (loanTransactionDTO.getTransactionType().isMerchantIssuedRefund()) {
|
if (loanTransactionDTO.getTransactionType().isMerchantIssuedRefund()) {
|
||||||
if (isMarkedFraud) {
|
if (isMarkedFraud) {
|
||||||
@@ -747,7 +766,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
// interest payment
|
// interest payment
|
||||||
if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(interestAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(interestAmount);
|
totalDebitAmount = totalDebitAmount.add(interestAmount);
|
||||||
if (loanTransactionDTO.getTransactionType().isMerchantIssuedRefund()) {
|
if (loanTransactionDTO.getTransactionType().isMerchantIssuedRefund()) {
|
||||||
populateCreditDebitMaps(loanProductId, interestAmount, paymentTypeId,
|
populateCreditDebitMaps(loanProductId, interestAmount, paymentTypeId,
|
||||||
@@ -777,7 +796,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle fees payment
|
// handle fees payment
|
||||||
if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(feesAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(feesAmount);
|
totalDebitAmount = totalDebitAmount.add(feesAmount);
|
||||||
if (loanTransactionDTO.getTransactionType().isMerchantIssuedRefund()) {
|
if (loanTransactionDTO.getTransactionType().isMerchantIssuedRefund()) {
|
||||||
populateCreditDebitMaps(loanProductId, feesAmount, paymentTypeId,
|
populateCreditDebitMaps(loanProductId, feesAmount, paymentTypeId,
|
||||||
@@ -816,7 +835,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle penalties
|
// handle penalties
|
||||||
if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(penaltiesAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
|
totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
|
||||||
if (loanTransactionDTO.getTransactionType().isMerchantIssuedRefund()) {
|
if (loanTransactionDTO.getTransactionType().isMerchantIssuedRefund()) {
|
||||||
populateCreditDebitMaps(loanProductId, penaltiesAmount, paymentTypeId,
|
populateCreditDebitMaps(loanProductId, penaltiesAmount, paymentTypeId,
|
||||||
@@ -853,7 +872,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
// overpayment
|
// overpayment
|
||||||
if (overPaymentAmount != null && overPaymentAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(overPaymentAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(overPaymentAmount);
|
totalDebitAmount = totalDebitAmount.add(overPaymentAmount);
|
||||||
if (loanTransactionDTO.getTransactionType().isMerchantIssuedRefund()) {
|
if (loanTransactionDTO.getTransactionType().isMerchantIssuedRefund()) {
|
||||||
populateCreditDebitMaps(loanProductId, overPaymentAmount, paymentTypeId, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
|
populateCreditDebitMaps(loanProductId, overPaymentAmount, paymentTypeId, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
|
||||||
@@ -876,12 +895,14 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
|
|
||||||
// create credit entries
|
// create credit entries
|
||||||
for (Map.Entry<Long, BigDecimal> creditEntry : glAccountBalanceHolder.getCreditBalances().entrySet()) {
|
for (Map.Entry<Long, BigDecimal> creditEntry : glAccountBalanceHolder.getCreditBalances().entrySet()) {
|
||||||
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(creditEntry.getKey());
|
if (MathUtil.isGreaterThanZero(creditEntry.getValue())) {
|
||||||
this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate,
|
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(creditEntry.getKey());
|
||||||
creditEntry.getValue(), glAccount);
|
this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate,
|
||||||
|
creditEntry.getValue(), glAccount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalDebitAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(totalDebitAmount)) {
|
||||||
if (writeOff) {
|
if (writeOff) {
|
||||||
this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.LOSSES_WRITTEN_OFF.getValue(),
|
this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.LOSSES_WRITTEN_OFF.getValue(),
|
||||||
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
|
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
|
||||||
@@ -907,7 +928,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
* Charge Refunds have an extra refund related pair of journal entries in addition to those related to the
|
* Charge Refunds have an extra refund related pair of journal entries in addition to those related to the
|
||||||
* repayment above
|
* repayment above
|
||||||
***/
|
***/
|
||||||
if (totalDebitAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(totalDebitAmount)) {
|
||||||
if (loanTransactionDTO.getTransactionType().isChargeRefund()) {
|
if (loanTransactionDTO.getTransactionType().isChargeRefund()) {
|
||||||
Integer incomeAccount = this.helper.getValueForFeeOrPenaltyIncomeAccount(loanTransactionDTO.getChargeRefundChargeType());
|
Integer incomeAccount = this.helper.getValueForFeeOrPenaltyIncomeAccount(loanTransactionDTO.getChargeRefundChargeType());
|
||||||
this.helper.createJournalEntriesForLoan(office, currencyCode, incomeAccount, AccrualAccountsForLoan.FUND_SOURCE.getValue(),
|
this.helper.createJournalEntriesForLoan(office, currencyCode, incomeAccount, AccrualAccountsForLoan.FUND_SOURCE.getValue(),
|
||||||
@@ -940,7 +961,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
Map<Integer, BigDecimal> debitAccountMapForGoodwillCredit = new LinkedHashMap<>();
|
Map<Integer, BigDecimal> debitAccountMapForGoodwillCredit = new LinkedHashMap<>();
|
||||||
|
|
||||||
// handle principal payment or writeOff
|
// handle principal payment or writeOff
|
||||||
if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(principalAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(principalAmount);
|
totalDebitAmount = totalDebitAmount.add(principalAmount);
|
||||||
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
||||||
AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(), paymentTypeId);
|
AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(), paymentTypeId);
|
||||||
@@ -952,7 +973,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle interest payment of writeOff
|
// handle interest payment of writeOff
|
||||||
if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(interestAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(interestAmount);
|
totalDebitAmount = totalDebitAmount.add(interestAmount);
|
||||||
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
||||||
AccrualAccountsForLoan.INTEREST_RECEIVABLE.getValue(), paymentTypeId);
|
AccrualAccountsForLoan.INTEREST_RECEIVABLE.getValue(), paymentTypeId);
|
||||||
@@ -970,10 +991,8 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle fees payment of writeOff
|
// handle fees payment of writeOff
|
||||||
if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(feesAmount)) {
|
||||||
|
|
||||||
totalDebitAmount = totalDebitAmount.add(feesAmount);
|
totalDebitAmount = totalDebitAmount.add(feesAmount);
|
||||||
|
|
||||||
if (isIncomeFromFee) {
|
if (isIncomeFromFee) {
|
||||||
this.helper.createCreditJournalEntryForLoanCharges(office, currencyCode, AccrualAccountsForLoan.INCOME_FROM_FEES.getValue(),
|
this.helper.createCreditJournalEntryForLoanCharges(office, currencyCode, AccrualAccountsForLoan.INCOME_FROM_FEES.getValue(),
|
||||||
loanProductId, loanId, transactionId, transactionDate, feesAmount, loanTransactionDTO.getFeePayments());
|
loanProductId, loanId, transactionId, transactionDate, feesAmount, loanTransactionDTO.getFeePayments());
|
||||||
@@ -994,7 +1013,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle penalties payment of writeOff
|
// handle penalties payment of writeOff
|
||||||
if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(penaltiesAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
|
totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
|
||||||
if (isIncomeFromFee) {
|
if (isIncomeFromFee) {
|
||||||
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
|
||||||
@@ -1023,7 +1042,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overPaymentAmount != null && overPaymentAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(overPaymentAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(overPaymentAmount);
|
totalDebitAmount = totalDebitAmount.add(overPaymentAmount);
|
||||||
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
|
GLAccount account = this.helper.getLinkedGLAccountForLoanProduct(loanProductId, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
|
||||||
paymentTypeId);
|
paymentTypeId);
|
||||||
@@ -1040,14 +1059,16 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (Map.Entry<GLAccount, BigDecimal> entry : accountMap.entrySet()) {
|
for (Map.Entry<GLAccount, BigDecimal> entry : accountMap.entrySet()) {
|
||||||
this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate, entry.getValue(),
|
if (MathUtil.isGreaterThanZero(entry.getValue())) {
|
||||||
entry.getKey());
|
this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate, entry.getValue(),
|
||||||
|
entry.getKey());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Single DEBIT transaction for write-offs or Repayments
|
* Single DEBIT transaction for write-offs or Repayments
|
||||||
***/
|
***/
|
||||||
if (totalDebitAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(totalDebitAmount)) {
|
||||||
if (writeOff) {
|
if (writeOff) {
|
||||||
this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.LOSSES_WRITTEN_OFF.getValue(),
|
this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.LOSSES_WRITTEN_OFF.getValue(),
|
||||||
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
|
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
|
||||||
@@ -1078,7 +1099,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
* Charge Refunds have an extra refund related pair of journal entries in addition to those related to the
|
* Charge Refunds have an extra refund related pair of journal entries in addition to those related to the
|
||||||
* repayment above
|
* repayment above
|
||||||
***/
|
***/
|
||||||
if (totalDebitAmount.compareTo(BigDecimal.ZERO) > 0 && loanTransactionDTO.getTransactionType().isChargeRefund()) {
|
if (MathUtil.isGreaterThanZero(totalDebitAmount) && loanTransactionDTO.getTransactionType().isChargeRefund()) {
|
||||||
Integer incomeAccount = this.helper.getValueForFeeOrPenaltyIncomeAccount(loanTransactionDTO.getChargeRefundChargeType());
|
Integer incomeAccount = this.helper.getValueForFeeOrPenaltyIncomeAccount(loanTransactionDTO.getChargeRefundChargeType());
|
||||||
this.helper.createJournalEntriesForLoan(office, currencyCode, incomeAccount, AccrualAccountsForLoan.FUND_SOURCE.getValue(),
|
this.helper.createJournalEntriesForLoan(office, currencyCode, incomeAccount, AccrualAccountsForLoan.FUND_SOURCE.getValue(),
|
||||||
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
|
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
|
||||||
@@ -1122,10 +1143,11 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
final BigDecimal amount = loanTransactionDTO.getAmount();
|
final BigDecimal amount = loanTransactionDTO.getAmount();
|
||||||
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
|
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
|
||||||
|
|
||||||
this.helper.createJournalEntriesForLoan(office, currencyCode, AccrualAccountsForLoan.FUND_SOURCE.getValue(),
|
if (MathUtil.isGreaterThanZero(amount)) {
|
||||||
AccrualAccountsForLoan.INCOME_FROM_RECOVERY.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
|
this.helper.createJournalEntriesForLoan(office, currencyCode, AccrualAccountsForLoan.FUND_SOURCE.getValue(),
|
||||||
transactionDate, amount);
|
AccrualAccountsForLoan.INCOME_FROM_RECOVERY.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
|
||||||
|
transactionDate, amount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1156,7 +1178,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
|
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
|
||||||
|
|
||||||
// create journal entries for recognizing interest
|
// create journal entries for recognizing interest
|
||||||
if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(interestAmount)) {
|
||||||
if (transactionType.isAccrualAdjustment()) {
|
if (transactionType.isAccrualAdjustment()) {
|
||||||
this.helper.createJournalEntriesForLoan(office, currencyCode, AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(),
|
this.helper.createJournalEntriesForLoan(office, currencyCode, AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(),
|
||||||
AccrualAccountsForLoan.INTEREST_RECEIVABLE.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
|
AccrualAccountsForLoan.INTEREST_RECEIVABLE.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
|
||||||
@@ -1168,7 +1190,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// create journal entries for the fees application
|
// create journal entries for the fees application
|
||||||
if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(feesAmount)) {
|
||||||
if (transactionType.isAccrualAdjustment()) {
|
if (transactionType.isAccrualAdjustment()) {
|
||||||
this.helper.createJournalEntriesForLoanCharges(office, currencyCode, AccrualAccountsForLoan.INCOME_FROM_FEES.getValue(),
|
this.helper.createJournalEntriesForLoanCharges(office, currencyCode, AccrualAccountsForLoan.INCOME_FROM_FEES.getValue(),
|
||||||
AccrualAccountsForLoan.FEES_RECEIVABLE.getValue(), loanProductId, loanId, transactionId, transactionDate,
|
AccrualAccountsForLoan.FEES_RECEIVABLE.getValue(), loanProductId, loanId, transactionId, transactionDate,
|
||||||
@@ -1180,7 +1202,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// create journal entries for the penalties application
|
// create journal entries for the penalties application
|
||||||
if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(penaltiesAmount)) {
|
||||||
if (transactionType.isAccrualAdjustment()) {
|
if (transactionType.isAccrualAdjustment()) {
|
||||||
this.helper.createJournalEntriesForLoanCharges(office, currencyCode,
|
this.helper.createJournalEntriesForLoanCharges(office, currencyCode,
|
||||||
AccrualAccountsForLoan.INCOME_FROM_PENALTIES.getValue(), AccrualAccountsForLoan.PENALTIES_RECEIVABLE.getValue(),
|
AccrualAccountsForLoan.INCOME_FROM_PENALTIES.getValue(), AccrualAccountsForLoan.PENALTIES_RECEIVABLE.getValue(),
|
||||||
@@ -1205,14 +1227,16 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
final BigDecimal refundAmount = loanTransactionDTO.getAmount();
|
final BigDecimal refundAmount = loanTransactionDTO.getAmount();
|
||||||
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
|
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
|
||||||
|
|
||||||
if (loanTransactionDTO.isAccountTransfer()) {
|
if (MathUtil.isGreaterThanZero(refundAmount)) {
|
||||||
this.helper.createJournalEntriesForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
|
if (loanTransactionDTO.isAccountTransfer()) {
|
||||||
FinancialActivity.LIABILITY_TRANSFER.getValue(), loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
|
this.helper.createJournalEntriesForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
|
||||||
refundAmount);
|
FinancialActivity.LIABILITY_TRANSFER.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
|
||||||
} else {
|
transactionDate, refundAmount);
|
||||||
this.helper.createJournalEntriesForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
|
} else {
|
||||||
AccrualAccountsForLoan.FUND_SOURCE.getValue(), loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
|
this.helper.createJournalEntriesForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
|
||||||
refundAmount);
|
AccrualAccountsForLoan.FUND_SOURCE.getValue(), loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
|
||||||
|
refundAmount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1241,12 +1265,12 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
BigDecimal totalAmount = BigDecimal.ZERO;
|
BigDecimal totalAmount = BigDecimal.ZERO;
|
||||||
List<JournalAmountHolder> journalAmountHolders = new ArrayList<>();
|
List<JournalAmountHolder> journalAmountHolders = new ArrayList<>();
|
||||||
|
|
||||||
if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(principalAmount)) {
|
||||||
totalAmount = totalAmount.add(principalAmount);
|
totalAmount = totalAmount.add(principalAmount);
|
||||||
journalAmountHolders
|
journalAmountHolders
|
||||||
.add(new JournalAmountHolder(determineAccrualAccountForCBR(isMarkedChargeOff, isMarkedFraud, false), principalAmount));
|
.add(new JournalAmountHolder(determineAccrualAccountForCBR(isMarkedChargeOff, isMarkedFraud, false), principalAmount));
|
||||||
}
|
}
|
||||||
if (overpaymentAmount != null && overpaymentAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(overpaymentAmount)) {
|
||||||
totalAmount = totalAmount.add(overpaymentAmount);
|
totalAmount = totalAmount.add(overpaymentAmount);
|
||||||
journalAmountHolders
|
journalAmountHolders
|
||||||
.add(new JournalAmountHolder(determineAccrualAccountForCBR(isMarkedChargeOff, isMarkedFraud, true), overpaymentAmount));
|
.add(new JournalAmountHolder(determineAccrualAccountForCBR(isMarkedChargeOff, isMarkedFraud, true), overpaymentAmount));
|
||||||
@@ -1293,19 +1317,19 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
|
|
||||||
BigDecimal totalDebitAmount = new BigDecimal(0);
|
BigDecimal totalDebitAmount = new BigDecimal(0);
|
||||||
|
|
||||||
if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(principalAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(principalAmount);
|
totalDebitAmount = totalDebitAmount.add(principalAmount);
|
||||||
this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
|
this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
|
||||||
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, principalAmount);
|
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, principalAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(interestAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(interestAmount);
|
totalDebitAmount = totalDebitAmount.add(interestAmount);
|
||||||
this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(),
|
this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.INTEREST_ON_LOANS.getValue(),
|
||||||
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, interestAmount);
|
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, interestAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(feesAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(feesAmount);
|
totalDebitAmount = totalDebitAmount.add(feesAmount);
|
||||||
|
|
||||||
List<ChargePaymentDTO> chargePaymentDTOs = new ArrayList<>();
|
List<ChargePaymentDTO> chargePaymentDTOs = new ArrayList<>();
|
||||||
@@ -1320,7 +1344,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
loanProductId, loanId, transactionId, transactionDate, feesAmount, chargePaymentDTOs);
|
loanProductId, loanId, transactionId, transactionDate, feesAmount, chargePaymentDTOs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(penaltiesAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
|
totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
|
||||||
List<ChargePaymentDTO> chargePaymentDTOs = new ArrayList<>();
|
List<ChargePaymentDTO> chargePaymentDTOs = new ArrayList<>();
|
||||||
|
|
||||||
@@ -1334,14 +1358,16 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
|||||||
loanProductId, loanId, transactionId, transactionDate, penaltiesAmount, chargePaymentDTOs);
|
loanProductId, loanId, transactionId, transactionDate, penaltiesAmount, chargePaymentDTOs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overPaymentAmount != null && overPaymentAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (MathUtil.isGreaterThanZero(overPaymentAmount)) {
|
||||||
totalDebitAmount = totalDebitAmount.add(overPaymentAmount);
|
totalDebitAmount = totalDebitAmount.add(overPaymentAmount);
|
||||||
this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(), loanProductId,
|
this.helper.createDebitJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(), loanProductId,
|
||||||
paymentTypeId, loanId, transactionId, transactionDate, overPaymentAmount);
|
paymentTypeId, loanId, transactionId, transactionDate, overPaymentAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** create a single debit entry (or reversal) for the entire amount **/
|
if (MathUtil.isGreaterThanZero(totalDebitAmount)) {
|
||||||
this.helper.createCreditJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.FUND_SOURCE.getValue(), loanProductId,
|
/*** create a single debit entry (or reversal) for the entire amount **/
|
||||||
paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
|
this.helper.createCreditJournalEntryForLoan(office, currencyCode, AccrualAccountsForLoan.FUND_SOURCE.getValue(), loanProductId,
|
||||||
|
paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user