Merge pull request #1346 from fynmanoj/FINERACT-1151-fix
FINERACT-1151-fix
This commit is contained in:
+48
@@ -359,4 +359,52 @@ public class LoanRescheduleOnDecliningBalanceLoanTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateLoanRescheduleRequestWithMultpleInterestAppropriation() {
|
||||
// create all required entities
|
||||
this.createRequiredEntities();
|
||||
this.createAndApproveLoanRescheduleRequestForInterestAppropriation();
|
||||
|
||||
this.createAndApproveLoanRescheduleRequestForSecondInterestAppropriation();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* create new loan reschedule request
|
||||
**/
|
||||
private void createAndApproveLoanRescheduleRequestForSecondInterestAppropriation() {
|
||||
LOG.info(
|
||||
"---------------------------------CREATING LOAN RESCHEDULE REQUEST FOR INTEREST APPROPRIATTION-------------------------------------");
|
||||
|
||||
final String requestJSON = new LoanRescheduleRequestTestBuilder().updateGraceOnPrincipal(null).updateGraceOnInterest(null)
|
||||
.updateExtraTerms(null).updateRescheduleFromDate("04 December 2015").updateAdjustedDueDate("04 June 2016")
|
||||
.updateRecalculateInterest(true).build(this.loanId.toString());
|
||||
|
||||
this.loanRescheduleRequestId = this.loanRescheduleRequestHelper.createLoanRescheduleRequest(requestJSON);
|
||||
this.loanRescheduleRequestHelper.verifyCreationOfLoanRescheduleRequest(this.loanRescheduleRequestId);
|
||||
|
||||
LOG.info("Successfully created loan reschedule request (ID: {} )", this.loanRescheduleRequestId);
|
||||
|
||||
final String aproveRequestJSON = new LoanRescheduleRequestTestBuilder().getApproveLoanRescheduleRequestJSON();
|
||||
this.loanRescheduleRequestHelper.approveLoanRescheduleRequest(this.loanRescheduleRequestId, aproveRequestJSON);
|
||||
final HashMap response = (HashMap) this.loanRescheduleRequestHelper.getLoanRescheduleRequest(loanRescheduleRequestId, "statusEnum");
|
||||
assertTrue((Boolean) response.get("approved"));
|
||||
|
||||
LOG.info("Successfully approved loan reschedule request (ID: {})", this.loanRescheduleRequestId);
|
||||
|
||||
final Map repaymentSchedule = (Map) this.loanTransactionHelper.getLoanDetail(requestSpec, generalResponseSpec, loanId,
|
||||
"repaymentSchedule");
|
||||
final ArrayList periods = (ArrayList) repaymentSchedule.get("periods");
|
||||
|
||||
HashMap period = (HashMap) periods.get(7);
|
||||
Float totalDueForPeriod = (Float) period.get("totalDueForPeriod");
|
||||
|
||||
final HashMap loanSummary = this.loanTransactionHelper.getLoanSummary(requestSpec, generalResponseSpec, loanId);
|
||||
final Float totalExpectedRepayment = (Float) loanSummary.get("totalExpectedRepayment");
|
||||
|
||||
assertEquals(12187, totalDueForPeriod.intValue(), "EXPECTED REPAYMENT in Second Reschedule is NOK");
|
||||
assertEquals(130750, totalExpectedRepayment.intValue(), "TOTAL EXPECTED in Second Reschedule REPAYMENT is NOK");
|
||||
|
||||
LOG.info("Successfully approved loan reschedule request (ID: {})", this.loanRescheduleRequestId);
|
||||
}
|
||||
}
|
||||
|
||||
+30
@@ -82,6 +82,9 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus
|
||||
@Column(name = "accrual_interest_derived", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal interestAccrued;
|
||||
|
||||
@Column(name = "reschedule_interest_portion", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal rescheduleInterestPortion;
|
||||
|
||||
@Column(name = "fee_charges_amount", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal feeChargesCharged;
|
||||
|
||||
@@ -139,6 +142,24 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus
|
||||
this.obligationsMet = false;
|
||||
}
|
||||
|
||||
public LoanRepaymentScheduleInstallment(final Loan loan, final Integer installmentNumber, final LocalDate fromDate,
|
||||
final LocalDate dueDate, final BigDecimal principal, final BigDecimal interest, final BigDecimal feeCharges,
|
||||
final BigDecimal penaltyCharges, final boolean recalculatedInterestComponent,
|
||||
final Set<LoanInterestRecalcualtionAdditionalDetails> compoundingDetails, final BigDecimal rescheduleInterestPortion) {
|
||||
this.loan = loan;
|
||||
this.installmentNumber = installmentNumber;
|
||||
this.fromDate = fromDate.toDateTimeAtStartOfDay().toDate();
|
||||
this.dueDate = dueDate.toDateTimeAtStartOfDay().toDate();
|
||||
this.principal = defaultToNullIfZero(principal);
|
||||
this.interestCharged = defaultToNullIfZero(interest);
|
||||
this.feeChargesCharged = defaultToNullIfZero(feeCharges);
|
||||
this.penaltyCharges = defaultToNullIfZero(penaltyCharges);
|
||||
this.obligationsMet = false;
|
||||
this.recalculatedInterestComponent = recalculatedInterestComponent;
|
||||
this.loanCompoundingDetails = compoundingDetails;
|
||||
this.rescheduleInterestPortion = rescheduleInterestPortion;
|
||||
}
|
||||
|
||||
public LoanRepaymentScheduleInstallment(final Loan loan, final Integer installmentNumber, final LocalDate fromDate,
|
||||
final LocalDate dueDate, final BigDecimal principal, final BigDecimal interest, final BigDecimal feeCharges,
|
||||
final BigDecimal penaltyCharges, final boolean recalculatedInterestComponent,
|
||||
@@ -807,4 +828,13 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus
|
||||
return getPenaltyChargesPaid(currency).plus(getFeeChargesPaid(currency)).plus(getInterestPaid(currency))
|
||||
.plus(getPrincipalCompleted(currency));
|
||||
}
|
||||
|
||||
public BigDecimal getRescheduleInterestPortion() {
|
||||
return rescheduleInterestPortion;
|
||||
}
|
||||
|
||||
public void setRescheduleInterestPortion(BigDecimal rescheduleInterestPortion) {
|
||||
this.rescheduleInterestPortion = rescheduleInterestPortion;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+26
-1
@@ -397,6 +397,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
for (LoanScheduleModelPeriod installment : (List<LoanScheduleModelPeriod>) periods) {
|
||||
if (!installment.isEMIFixedSpecificToInstallment()) {
|
||||
installment.addInterestAmount(interestFraction);
|
||||
installment.setRescheduleInterestPortion(interestFraction.getAmount());
|
||||
interestTobeApproppriated = interestTobeApproppriated.minus(interestFraction);
|
||||
}
|
||||
}
|
||||
@@ -404,6 +405,11 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
|
||||
if (interestTobeApproppriated.isGreaterThanZero()) {
|
||||
lastInstallment.addInterestAmount(interestTobeApproppriated);
|
||||
BigDecimal rescheduleInterestPortion = BigDecimal.ZERO;
|
||||
if (lastInstallment.rescheduleInterestPortion() != null) {
|
||||
rescheduleInterestPortion = lastInstallment.rescheduleInterestPortion();
|
||||
}
|
||||
lastInstallment.setRescheduleInterestPortion(rescheduleInterestPortion.add(interestTobeApproppriated.getAmount()));
|
||||
}
|
||||
scheduleParams.addTotalRepaymentExpected(loanApplicationTerms.getInterestTobeApproppriated());
|
||||
scheduleParams.addTotalCumulativeInterest(loanApplicationTerms.getInterestTobeApproppriated());
|
||||
@@ -2385,6 +2391,24 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
loanRepaymentScheduleTransactionProcessor, scheduleTillDate, applyInterestRecalculation);
|
||||
periods.clear();
|
||||
}
|
||||
|
||||
BigDecimal rescheuleInterestPortionTobeRetained = BigDecimal.ZERO;
|
||||
for (LoanRepaymentScheduleInstallment retainedInstallment : retainedInstallments) {
|
||||
if (retainedInstallment.getRescheduleInterestPortion() != null) {
|
||||
rescheuleInterestPortionTobeRetained = rescheuleInterestPortionTobeRetained
|
||||
.add(retainedInstallment.getRescheduleInterestPortion());
|
||||
}
|
||||
}
|
||||
|
||||
BigDecimal rescheuleInterestPortionTotal = BigDecimal.ZERO;
|
||||
for (LoanRepaymentScheduleInstallment inst : loan.getRepaymentScheduleInstallments()) {
|
||||
if (inst.getRescheduleInterestPortion() != null) {
|
||||
rescheuleInterestPortionTotal = rescheuleInterestPortionTotal.add(inst.getRescheduleInterestPortion());
|
||||
}
|
||||
}
|
||||
|
||||
BigDecimal rescheuleInterestPortionTobeAppropriated = rescheuleInterestPortionTotal.subtract(rescheuleInterestPortionTobeRetained);
|
||||
loanApplicationTerms.setInterestTobeApproppriated(Money.of(loan.getCurrency(), rescheuleInterestPortionTobeAppropriated));
|
||||
LoanScheduleModel loanScheduleModel = generate(mc, loanApplicationTerms, loan.charges(), holidayDetailDTO, loanScheduleParams);
|
||||
|
||||
for (LoanScheduleModelPeriod loanScheduleModelPeriod : loanScheduleModel.getPeriods()) {
|
||||
@@ -2589,7 +2613,8 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
scheduledLoanInstallment.periodFromDate(), scheduledLoanInstallment.periodDueDate(),
|
||||
scheduledLoanInstallment.principalDue(), scheduledLoanInstallment.interestDue(),
|
||||
scheduledLoanInstallment.feeChargesDue(), scheduledLoanInstallment.penaltyChargesDue(),
|
||||
scheduledLoanInstallment.isRecalculatedInterestComponent(), scheduledLoanInstallment.getLoanCompoundingDetails());
|
||||
scheduledLoanInstallment.isRecalculatedInterestComponent(), scheduledLoanInstallment.getLoanCompoundingDetails(),
|
||||
scheduledLoanInstallment.rescheduleInterestPortion());
|
||||
installments.add(installment);
|
||||
}
|
||||
return installment;
|
||||
|
||||
+10
@@ -138,4 +138,14 @@ public final class LoanScheduleModelDisbursementPeriod implements LoanScheduleMo
|
||||
public boolean isEMIFixedSpecificToInstallment() {
|
||||
return isEMIFixedSpecificToInstallment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal rescheduleInterestPortion() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRescheduleInterestPortion(BigDecimal rescheduleInterestPortion) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -58,4 +58,8 @@ public interface LoanScheduleModelPeriod {
|
||||
void setEMIFixedSpecificToInstallmentTrue();
|
||||
|
||||
boolean isEMIFixedSpecificToInstallment();
|
||||
|
||||
BigDecimal rescheduleInterestPortion();
|
||||
|
||||
void setRescheduleInterestPortion(BigDecimal rescheduleInterestPortion);
|
||||
}
|
||||
|
||||
+11
@@ -43,6 +43,7 @@ public final class LoanScheduleModelRepaymentPeriod implements LoanScheduleModel
|
||||
private final boolean recalculatedInterestComponent;
|
||||
private final Set<LoanInterestRecalcualtionAdditionalDetails> loanCompoundingDetails = new HashSet<>();
|
||||
private boolean isEMIFixedSpecificToInstallment = false;
|
||||
BigDecimal rescheduleInterestPortion;
|
||||
|
||||
public static LoanScheduleModelRepaymentPeriod repayment(final int periodNumber, final LocalDate startDate,
|
||||
final LocalDate scheduledDueDate, final Money principalDue, final Money outstandingLoanBalance, final Money interestDue,
|
||||
@@ -172,4 +173,14 @@ public final class LoanScheduleModelRepaymentPeriod implements LoanScheduleModel
|
||||
public void setEMIFixedSpecificToInstallmentTrue() {
|
||||
this.isEMIFixedSpecificToInstallment = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRescheduleInterestPortion(BigDecimal rescheduleInterestPortion) {
|
||||
this.rescheduleInterestPortion = rescheduleInterestPortion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal rescheduleInterestPortion() {
|
||||
return this.rescheduleInterestPortion;
|
||||
}
|
||||
}
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
--
|
||||
-- Licensed to the Apache Software Foundation (ASF) under one
|
||||
-- or more contributor license agreements. See the NOTICE file
|
||||
-- distributed with this work for additional information
|
||||
-- regarding copyright ownership. The ASF licenses this file
|
||||
-- to you under the Apache License, Version 2.0 (the
|
||||
-- "License"); you may not use this file except in compliance
|
||||
-- with the License. You may obtain a copy of the License at
|
||||
--
|
||||
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||
--
|
||||
-- Unless required by applicable law or agreed to in writing,
|
||||
-- software distributed under the License is distributed on an
|
||||
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
-- KIND, either express or implied. See the License for the
|
||||
-- specific language governing permissions and limitations
|
||||
-- under the License.
|
||||
--
|
||||
|
||||
|
||||
alter table m_loan_repayment_schedule
|
||||
add column `reschedule_interest_portion` decimal(19,6) DEFAULT NULL after `accrual_interest_derived`;
|
||||
Reference in New Issue
Block a user