FINERACT-2148: Fix and add tests when interestRecalculation = false and zero interest charge-off behaviour
This commit is contained in:
committed by
Adam Saghy
parent
faaf44d91a
commit
dfc1d3ebad
+1
@@ -74,6 +74,7 @@ public enum DefaultLoanProduct implements LoanProduct {
|
|||||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_IR_DAILY_TILL_PRECLOSE_LAST_INSTALLMENT_STRATEGY, //
|
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_IR_DAILY_TILL_PRECLOSE_LAST_INSTALLMENT_STRATEGY, //
|
||||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION, //
|
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION, //
|
||||||
LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR, //
|
LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR, //
|
||||||
|
LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR, //
|
||||||
;
|
;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+43
-4
@@ -1094,17 +1094,56 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
|
|||||||
final String name51 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR
|
final String name51 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR
|
||||||
.getName();
|
.getName();
|
||||||
|
|
||||||
final PostLoanProductsRequest loanProductsRequestAdvCustomZeroInterestChargeOffBehaviourProgressiveLoanSchedule = loanProductsRequestFactory
|
final PostLoanProductsRequest loanProductsRequestAdvInterestRecalculationZeroInterestChargeOffBehaviourProgressiveLoanSchedule = loanProductsRequestFactory
|
||||||
.defaultLoanProductsRequestLP2InterestDailyRecalculation()//
|
.defaultLoanProductsRequestLP2InterestDailyRecalculation()//
|
||||||
.name(name51)//
|
.name(name51)//
|
||||||
.paymentAllocation(List.of(//
|
.paymentAllocation(List.of(//
|
||||||
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT")))
|
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT")))
|
||||||
.chargeOffBehaviour("ZERO_INTEREST");//
|
.chargeOffBehaviour("ZERO_INTEREST");//
|
||||||
final Response<PostLoanProductsResponse> responseLoanProductsRequestAdvCustomZeroInterestChargeOffBehaviourProgressiveLoanSchedule = loanProductsApi
|
final Response<PostLoanProductsResponse> responseLoanProductsRequestAdvInterestRecalculationZeroInterestChargeOffBehaviourProgressiveLoanSchedule = loanProductsApi
|
||||||
.createLoanProduct(loanProductsRequestAdvCustomZeroInterestChargeOffBehaviourProgressiveLoanSchedule).execute();
|
.createLoanProduct(loanProductsRequestAdvInterestRecalculationZeroInterestChargeOffBehaviourProgressiveLoanSchedule)
|
||||||
|
.execute();
|
||||||
TestContext.INSTANCE.set(
|
TestContext.INSTANCE.set(
|
||||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR,
|
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR,
|
||||||
responseLoanProductsRequestAdvCustomZeroInterestChargeOffBehaviourProgressiveLoanSchedule);
|
responseLoanProductsRequestAdvInterestRecalculationZeroInterestChargeOffBehaviourProgressiveLoanSchedule);
|
||||||
|
|
||||||
|
// LP2 + zero-interest chargeOff behaviour + progressive loan schedule + horizontal
|
||||||
|
// (LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR)
|
||||||
|
final String name52 = DefaultLoanProduct.LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR.getName();
|
||||||
|
|
||||||
|
final PostLoanProductsRequest loanProductsRequestAdvZeroInterestChargeOffBehaviourProgressiveLoanSchedule = loanProductsRequestFactory
|
||||||
|
.defaultLoanProductsRequestLP2()//
|
||||||
|
.name(name52)//
|
||||||
|
.enableDownPayment(false)//
|
||||||
|
.enableAutoRepaymentForDownPayment(null)//
|
||||||
|
.disbursedAmountPercentageForDownPayment(null)//
|
||||||
|
.transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION.getValue())//
|
||||||
|
.loanScheduleType("PROGRESSIVE") //
|
||||||
|
.loanScheduleProcessingType("HORIZONTAL")//
|
||||||
|
.interestRateFrequencyType(3)//
|
||||||
|
.maxInterestRatePerPeriod(10.0)//
|
||||||
|
.paymentAllocation(List.of(//
|
||||||
|
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT",
|
||||||
|
LoanProductPaymentAllocationRule.AllocationTypesEnum.PAST_DUE_PENALTY, //
|
||||||
|
LoanProductPaymentAllocationRule.AllocationTypesEnum.PAST_DUE_FEE, //
|
||||||
|
LoanProductPaymentAllocationRule.AllocationTypesEnum.PAST_DUE_PRINCIPAL, //
|
||||||
|
LoanProductPaymentAllocationRule.AllocationTypesEnum.PAST_DUE_INTEREST, //
|
||||||
|
LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_PENALTY, //
|
||||||
|
LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_FEE, //
|
||||||
|
LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_PRINCIPAL, //
|
||||||
|
LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_INTEREST, //
|
||||||
|
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_PENALTY, //
|
||||||
|
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_FEE,
|
||||||
|
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_INTEREST, //
|
||||||
|
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_PRINCIPAL), //
|
||||||
|
createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
|
||||||
|
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
|
||||||
|
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")))//
|
||||||
|
.chargeOffBehaviour("ZERO_INTEREST");//
|
||||||
|
final Response<PostLoanProductsResponse> responseLoanProductsRequestAdvZeroInterestChargeOffBehaviourProgressiveLoanSchedule = loanProductsApi
|
||||||
|
.createLoanProduct(loanProductsRequestAdvZeroInterestChargeOffBehaviourProgressiveLoanSchedule).execute();
|
||||||
|
TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR,
|
||||||
|
responseLoanProductsRequestAdvZeroInterestChargeOffBehaviourProgressiveLoanSchedule);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AdvancedPaymentData createPaymentAllocation(String transactionType, String futureInstallmentAllocationRule,
|
public static AdvancedPaymentData createPaymentAllocation(String transactionType, String futureInstallmentAllocationRule,
|
||||||
|
|||||||
+18
-4
@@ -20,6 +20,7 @@ package org.apache.fineract.test.stepdef.loan;
|
|||||||
|
|
||||||
import static org.apache.fineract.test.data.TransactionProcessingStrategyCode.ADVANCED_PAYMENT_ALLOCATION;
|
import static org.apache.fineract.test.data.TransactionProcessingStrategyCode.ADVANCED_PAYMENT_ALLOCATION;
|
||||||
import static org.apache.fineract.test.data.loanproduct.DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR;
|
import static org.apache.fineract.test.data.loanproduct.DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR;
|
||||||
|
import static org.apache.fineract.test.data.loanproduct.DefaultLoanProduct.LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.awaitility.Awaitility.await;
|
import static org.awaitility.Awaitility.await;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
@@ -2767,13 +2768,25 @@ public class LoanStepDef extends AbstractStepDef {
|
|||||||
eventCheckHelper.createLoanEventCheck(response);
|
eventCheckHelper.createLoanEventCheck(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@When("Admin creates a new zero charge-off Loan with date: {string}")
|
@When("Admin creates a new zero charge-off Loan with interest recalculation and date: {string}")
|
||||||
public void createLoanWithInterestRecalculationAndZeroChargeOffBehaviour(final String date) throws IOException {
|
public void createLoanWithInterestRecalculationAndZeroChargeOffBehaviour(final String date) throws IOException {
|
||||||
|
createLoanWithZeroChargeOffBehaviour(date, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin creates a new zero charge-off Loan without interest recalculation and with date: {string}")
|
||||||
|
public void createLoanWithoutInterestRecalculationAndZeroChargeOffBehaviour(final String date) throws IOException {
|
||||||
|
createLoanWithZeroChargeOffBehaviour(date, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createLoanWithZeroChargeOffBehaviour(final String date, final boolean isInterestRecalculation) throws IOException {
|
||||||
final Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
|
final Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
|
||||||
final Long clientId = clientResponse.body().getClientId();
|
final Long clientId = clientResponse.body().getClientId();
|
||||||
|
|
||||||
final DefaultLoanProduct product = DefaultLoanProduct
|
final DefaultLoanProduct product = isInterestRecalculation
|
||||||
.valueOf(LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR.getName());
|
? DefaultLoanProduct
|
||||||
|
.valueOf(LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR.getName())
|
||||||
|
: DefaultLoanProduct.valueOf(LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR.getName());
|
||||||
|
|
||||||
final Long loanProductId = loanProductResolver.resolve(product);
|
final Long loanProductId = loanProductResolver.resolve(product);
|
||||||
|
|
||||||
final PostLoansRequest loansRequest = loanRequestFactory.defaultLoansRequest(clientId).productId(loanProductId)
|
final PostLoansRequest loansRequest = loanRequestFactory.defaultLoansRequest(clientId).productId(loanProductId)
|
||||||
@@ -2785,7 +2798,8 @@ public class LoanStepDef extends AbstractStepDef {
|
|||||||
.interestRateFrequencyType(3)//
|
.interestRateFrequencyType(3)//
|
||||||
.interestRatePerPeriod(new BigDecimal(7))//
|
.interestRatePerPeriod(new BigDecimal(7))//
|
||||||
.interestType(InterestType.DECLINING_BALANCE.value)//
|
.interestType(InterestType.DECLINING_BALANCE.value)//
|
||||||
.interestCalculationPeriodType(InterestCalculationPeriodTime.DAILY.value)//
|
.interestCalculationPeriodType(isInterestRecalculation ? InterestCalculationPeriodTime.DAILY.value
|
||||||
|
: InterestCalculationPeriodTime.SAME_AS_REPAYMENT_PERIOD.value)//
|
||||||
.transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION.value);
|
.transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION.value);
|
||||||
|
|
||||||
final Response<PostLoansResponse> response = loansApi.calculateLoanScheduleOrSubmitLoanApplication(loansRequest, "").execute();
|
final Response<PostLoansResponse> response = loansApi.calculateLoanScheduleOrSubmitLoanApplication(loansRequest, "").execute();
|
||||||
|
|||||||
+1
@@ -105,6 +105,7 @@ public abstract class TestContextKey {
|
|||||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_WHOLE_TERM = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationSameAsRepTillPreCloseWholeTerm";
|
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_WHOLE_TERM = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationSameAsRepTillPreCloseWholeTerm";
|
||||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmiActualActualInterestRefundFInterestRecalculation";
|
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmiActualActualInterestRefundFInterestRecalculation";
|
||||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyInterestRecalculationZeroInterestChargeOffBehaviour";
|
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyInterestRecalculationZeroInterestChargeOffBehaviour";
|
||||||
|
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR = "loanProductCreateResponseLP2AdvancedPaymentZeroInterestChargeOffBehaviour";
|
||||||
public static final String CHARGE_FOR_LOAN_PERCENT_LATE_CREATE_RESPONSE = "ChargeForLoanPercentLateCreateResponse";
|
public static final String CHARGE_FOR_LOAN_PERCENT_LATE_CREATE_RESPONSE = "ChargeForLoanPercentLateCreateResponse";
|
||||||
public static final String CHARGE_FOR_LOAN_PERCENT_LATE_AMOUNT_PLUS_INTEREST_CREATE_RESPONSE = "ChargeForLoanPercentLateAmountPlusInterestCreateResponse";
|
public static final String CHARGE_FOR_LOAN_PERCENT_LATE_AMOUNT_PLUS_INTEREST_CREATE_RESPONSE = "ChargeForLoanPercentLateAmountPlusInterestCreateResponse";
|
||||||
public static final String CHARGE_FOR_LOAN_PERCENT_PROCESSING_CREATE_RESPONSE = "ChargeForLoanPercentProcessingCreateResponse";
|
public static final String CHARGE_FOR_LOAN_PERCENT_PROCESSING_CREATE_RESPONSE = "ChargeForLoanPercentProcessingCreateResponse";
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+39
-27
@@ -1171,11 +1171,10 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleChargeOff(final LoanTransaction loanTransaction, final TransactionCtx transactionCtx) {
|
private void handleChargeOff(final LoanTransaction loanTransaction, final TransactionCtx transactionCtx) {
|
||||||
if (transactionCtx instanceof ProgressiveTransactionCtx progressiveTransactionCtx) {
|
if (loanTransaction.getLoan().isProgressiveSchedule()) {
|
||||||
if (LoanChargeOffBehaviour.ZERO_INTEREST.equals(loanTransaction.getLoan().getLoanProductRelatedDetail().getChargeOffBehaviour())
|
if (LoanChargeOffBehaviour.ZERO_INTEREST.equals(loanTransaction.getLoan().getLoanProductRelatedDetail().getChargeOffBehaviour())
|
||||||
&& !loanTransaction.isReversed()) {
|
&& !loanTransaction.isReversed()) {
|
||||||
handleZeroInterestChargeOff(loanTransaction, progressiveTransactionCtx);
|
handleZeroInterestChargeOff(loanTransaction, transactionCtx);
|
||||||
progressiveTransactionCtx.setChargedOff(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1198,13 +1197,13 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
loanTransaction.updateComponentsAndTotal(principalPortion, interestPortion, feeChargesPortion, penaltychargesPortion);
|
loanTransaction.updateComponentsAndTotal(principalPortion, interestPortion, feeChargesPortion, penaltychargesPortion);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleZeroInterestChargeOff(final LoanTransaction loanTransaction,
|
private void handleZeroInterestChargeOff(final LoanTransaction loanTransaction, final TransactionCtx transactionCtx) {
|
||||||
final ProgressiveTransactionCtx progressiveTransactionCtx) {
|
|
||||||
final LocalDate transactionDate = loanTransaction.getTransactionDate();
|
final LocalDate transactionDate = loanTransaction.getTransactionDate();
|
||||||
final List<LoanRepaymentScheduleInstallment> installments = progressiveTransactionCtx.getInstallments();
|
final List<LoanRepaymentScheduleInstallment> installments = transactionCtx.getInstallments();
|
||||||
|
|
||||||
if (!installments.isEmpty()) {
|
if (!installments.isEmpty()) {
|
||||||
if (loanTransaction.getLoan().isInterestRecalculationEnabled()) {
|
if (transactionCtx instanceof ProgressiveTransactionCtx progressiveTransactionCtx
|
||||||
|
&& loanTransaction.getLoan().isInterestRecalculationEnabled()) {
|
||||||
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 newInterest = emiCalculator.getPeriodInterestTillDate(progressiveTransactionCtx.getModel(),
|
final BigDecimal newInterest = emiCalculator.getPeriodInterestTillDate(progressiveTransactionCtx.getModel(),
|
||||||
@@ -1213,40 +1212,53 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
installment.updatePrincipal(MathUtil.nullToZero(installment.getPrincipal()).add(interestRemoved));
|
installment.updatePrincipal(MathUtil.nullToZero(installment.getPrincipal()).add(interestRemoved));
|
||||||
installment.updateInterestCharged(newInterest);
|
installment.updateInterestCharged(newInterest);
|
||||||
});
|
});
|
||||||
|
progressiveTransactionCtx.setChargedOff(true);
|
||||||
} else {
|
} else {
|
||||||
calculatePartialPeriodInterest(progressiveTransactionCtx, transactionDate);
|
calculatePartialPeriodInterest(transactionCtx, transactionDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
installments.stream().filter(installment -> installment.getFromDate().isAfter(transactionDate)).forEach(installment -> {
|
final MonetaryCurrency currency = loanTransaction.getLoan().getCurrency();
|
||||||
installment.updatePrincipal(MathUtil.nullToZero(installment.getPrincipal()).add(installment.getInterestCharged()));
|
|
||||||
installment.updateInterestCharged(BigDecimal.ZERO);
|
|
||||||
});
|
|
||||||
|
|
||||||
final BigDecimal totalInstallmentsPrincipal = installments.stream().map(LoanRepaymentScheduleInstallment::getPrincipal)
|
installments.stream()
|
||||||
.reduce(ZERO, BigDecimal::add);
|
.filter(installment -> installment.getFromDate().isAfter(transactionDate) && !installment.isObligationsMet())
|
||||||
final Money amountToEditLastInstallment = loanTransaction.getLoan().getPrincipal().minus(totalInstallmentsPrincipal);
|
.forEach(installment -> {
|
||||||
final int lastInstallmentIndex = installments.size() - 1;
|
final BigDecimal interestOutstanding = installment.getInterestOutstanding(currency).getAmount();
|
||||||
installments.get(lastInstallmentIndex)
|
final BigDecimal updatedInterestCharged = installment.getInterestCharged(currency).getAmount()
|
||||||
.updatePrincipal(installments.get(lastInstallmentIndex).getPrincipal().add(amountToEditLastInstallment.getAmount()));
|
.subtract(interestOutstanding);
|
||||||
|
|
||||||
|
if (interestOutstanding.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
final BigDecimal newPrincipal = installment.getPrincipal(currency).getAmount().add(interestOutstanding);
|
||||||
|
|
||||||
|
installment.updatePrincipal(newPrincipal);
|
||||||
|
installment.updateInterestCharged(updatedInterestCharged);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final Money amountToEditLastInstallment = loanTransaction.getLoan().getPrincipal().minus(installments.stream()
|
||||||
|
.filter(i -> !i.isAdditional()).map(LoanRepaymentScheduleInstallment::getPrincipal).reduce(ZERO, BigDecimal::add));
|
||||||
|
|
||||||
|
if (amountToEditLastInstallment.getAmount().signum() != 0) {
|
||||||
|
installments.stream().filter(i -> !i.isAdditional() && !i.isObligationsMet()).reduce((first, second) -> second)
|
||||||
|
.ifPresent(last -> last.updatePrincipal(last.getPrincipal().add(amountToEditLastInstallment.getAmount())));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calculatePartialPeriodInterest(final ProgressiveTransactionCtx progressiveTransactionCtx, final LocalDate chargeOffDate) {
|
private void calculatePartialPeriodInterest(final TransactionCtx transactionCtx, final LocalDate chargeOffDate) {
|
||||||
progressiveTransactionCtx.getInstallments().stream()
|
transactionCtx.getInstallments().stream()
|
||||||
.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(progressiveTransactionCtx.getCurrency())
|
final BigDecimal totalInterest = installment.getInterestOutstanding(transactionCtx.getCurrency()).getAmount();
|
||||||
.getAmount();
|
|
||||||
final long totalDaysInPeriod = ChronoUnit.DAYS.between(installment.getFromDate(), installment.getDueDate());
|
final long totalDaysInPeriod = ChronoUnit.DAYS.between(installment.getFromDate(), installment.getDueDate());
|
||||||
final long daysTillChargeOff = ChronoUnit.DAYS.between(installment.getFromDate(), chargeOffDate);
|
final long daysTillChargeOff = ChronoUnit.DAYS.between(installment.getFromDate(), chargeOffDate);
|
||||||
|
|
||||||
final BigDecimal interestTillChargeOff = totalInterest
|
final MathContext mc = MoneyHelper.getMathContext();
|
||||||
.divide(BigDecimal.valueOf(totalDaysInPeriod), MoneyHelper.getMathContext())
|
final Money interestTillChargeOff = Money.of(transactionCtx.getCurrency(), totalInterest
|
||||||
.multiply(BigDecimal.valueOf(daysTillChargeOff));
|
.divide(BigDecimal.valueOf(totalDaysInPeriod), mc).multiply(BigDecimal.valueOf(daysTillChargeOff), mc), mc);
|
||||||
|
|
||||||
final BigDecimal interestRemoved = totalInterest.subtract(interestTillChargeOff);
|
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);
|
installment.updateInterestCharged(interestTillChargeOff.getAmount());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user