FINERACT-1724: Fee's are not included in total balance amount, when we have multiple disbursements on first day
This commit is contained in:
+17
-13
@@ -655,7 +655,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
getId(), loanCharge.name());
|
getId(), loanCharge.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate(false));
|
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate());
|
||||||
|
|
||||||
loanCharge.update(this);
|
loanCharge.update(this);
|
||||||
|
|
||||||
@@ -770,18 +770,18 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||||
final List<LoanRepaymentScheduleInstallment> chargePaymentInstallments = new ArrayList<>();
|
final List<LoanRepaymentScheduleInstallment> chargePaymentInstallments = new ArrayList<>();
|
||||||
LocalDate startDate = getDisbursementDate();
|
|
||||||
List<LoanRepaymentScheduleInstallment> installments = getRepaymentScheduleInstallments();
|
List<LoanRepaymentScheduleInstallment> installments = getRepaymentScheduleInstallments();
|
||||||
for (final LoanRepaymentScheduleInstallment installment : installments) {
|
for (final LoanRepaymentScheduleInstallment installment : installments) {
|
||||||
if (installmentNumber == null && charge.isDueForCollectionFromAndUpToAndIncluding(startDate, installment.getDueDate())) {
|
boolean isDue = installment.isFirstPeriod()
|
||||||
|
? charge.isDueForCollectionFromIncludingAndUpToAndIncluding(installment.getFromDate(), installment.getDueDate())
|
||||||
|
: charge.isDueForCollectionFromAndUpToAndIncluding(installment.getFromDate(), installment.getDueDate());
|
||||||
|
if (installmentNumber == null && isDue) {
|
||||||
chargePaymentInstallments.add(installment);
|
chargePaymentInstallments.add(installment);
|
||||||
break;
|
break;
|
||||||
} else if (installmentNumber != null && installment.getInstallmentNumber().equals(installmentNumber)) {
|
} else if (installmentNumber != null && installment.getInstallmentNumber().equals(installmentNumber)) {
|
||||||
chargePaymentInstallments.add(installment);
|
chargePaymentInstallments.add(installment);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
startDate = installment.getDueDate();
|
|
||||||
}
|
}
|
||||||
final Set<LoanCharge> loanCharges = new HashSet<>(1);
|
final Set<LoanCharge> loanCharges = new HashSet<>(1);
|
||||||
loanCharges.add(charge);
|
loanCharges.add(charge);
|
||||||
@@ -808,13 +808,11 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateChargeHasValidSpecifiedDateIfApplicable(final LoanCharge loanCharge, final LocalDate disbursementDate,
|
private void validateChargeHasValidSpecifiedDateIfApplicable(final LoanCharge loanCharge, final LocalDate disbursementDate) {
|
||||||
final LocalDate lastRepaymentPeriodDueDate) {
|
if (loanCharge.isSpecifiedDueDate() && loanCharge.getDueLocalDate().isBefore(disbursementDate)) {
|
||||||
if (isInterestBearing() && loanCharge.isSpecifiedDueDate()
|
|
||||||
&& !loanCharge.isDueForCollectionFromAndUpToAndIncluding(disbursementDate, lastRepaymentPeriodDueDate)) {
|
|
||||||
final String defaultUserMessage = "This charge with specified due date cannot be added as the it is not in schedule range.";
|
final String defaultUserMessage = "This charge with specified due date cannot be added as the it is not in schedule range.";
|
||||||
throw new LoanChargeCannotBeAddedException("loanCharge", "specified.due.date.outside.range", defaultUserMessage,
|
throw new LoanChargeCannotBeAddedException("loanCharge", "specified.due.date.outside.range", defaultUserMessage,
|
||||||
getDisbursementDate(), lastRepaymentPeriodDueDate, loanCharge.name());
|
getDisbursementDate(), loanCharge.name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1745,7 +1743,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
if (loanCharge.isActive()) {
|
if (loanCharge.isActive()) {
|
||||||
clearLoanInstallmentChargesBeforeRegeneration(loanCharge);
|
clearLoanInstallmentChargesBeforeRegeneration(loanCharge);
|
||||||
loanCharge.update(chargeAmt, loanCharge.getDueLocalDate(), amount, fetchNumberOfInstallmensAfterExceptions(), totalChargeAmt);
|
loanCharge.update(chargeAmt, loanCharge.getDueLocalDate(), amount, fetchNumberOfInstallmensAfterExceptions(), totalChargeAmt);
|
||||||
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate(false));
|
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -5560,7 +5558,10 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
List<LoanCharge> loanCharges = new ArrayList<>();
|
List<LoanCharge> loanCharges = new ArrayList<>();
|
||||||
List<LoanInstallmentCharge> loanInstallmentCharges = new ArrayList<>();
|
List<LoanInstallmentCharge> loanInstallmentCharges = new ArrayList<>();
|
||||||
for (LoanCharge loanCharge : this.getActiveCharges()) {
|
for (LoanCharge loanCharge : this.getActiveCharges()) {
|
||||||
if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(fromDate, toDate)) {
|
boolean isDue = fromDate.isEqual(this.getDisbursementDate())
|
||||||
|
? loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(fromDate, toDate)
|
||||||
|
: loanCharge.isDueForCollectionFromAndUpToAndIncluding(fromDate, toDate);
|
||||||
|
if (isDue) {
|
||||||
if (loanCharge.isPenaltyCharge() && !loanCharge.isInstalmentFee()) {
|
if (loanCharge.isPenaltyCharge() && !loanCharge.isInstalmentFee()) {
|
||||||
penalties = penalties.add(loanCharge.amount());
|
penalties = penalties.add(loanCharge.amount());
|
||||||
loanCharges.add(loanCharge);
|
loanCharges.add(loanCharge);
|
||||||
@@ -6569,7 +6570,10 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
interestAccountedForCurrentPeriod = installment.getInterestWaived(getCurrency()).plus(installment.getInterestPaid(getCurrency()));
|
interestAccountedForCurrentPeriod = installment.getInterestWaived(getCurrency()).plus(installment.getInterestPaid(getCurrency()));
|
||||||
for (LoanCharge loanCharge : this.charges) {
|
for (LoanCharge loanCharge : this.charges) {
|
||||||
if (loanCharge.isActive() && !loanCharge.isDueAtDisbursement()) {
|
if (loanCharge.isActive() && !loanCharge.isDueAtDisbursement()) {
|
||||||
if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(installment.getFromDate(), paymentDate)) {
|
boolean isDue = installment.isFirstPeriod()
|
||||||
|
? loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(installment.getFromDate(), paymentDate)
|
||||||
|
: loanCharge.isDueForCollectionFromAndUpToAndIncluding(installment.getFromDate(), paymentDate);
|
||||||
|
if (isDue) {
|
||||||
if (loanCharge.isPenaltyCharge()) {
|
if (loanCharge.isPenaltyCharge()) {
|
||||||
penaltyForCurrentPeriod = penaltyForCurrentPeriod.plus(loanCharge.getAmount(getCurrency()));
|
penaltyForCurrentPeriod = penaltyForCurrentPeriod.plus(loanCharge.getAmount(getCurrency()));
|
||||||
penaltyAccoutedForCurrentPeriod = penaltyAccoutedForCurrentPeriod
|
penaltyAccoutedForCurrentPeriod = penaltyAccoutedForCurrentPeriod
|
||||||
|
|||||||
+8
-4
@@ -641,7 +641,10 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final LoanCharge loanCharge : loanCharges) {
|
for (final LoanCharge loanCharge : loanCharges) {
|
||||||
if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(installment.getFromDate(), chargesTillDate)) {
|
boolean isDue = installment.isFirstPeriod()
|
||||||
|
? loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(installment.getFromDate(), chargesTillDate)
|
||||||
|
: loanCharge.isDueForCollectionFromAndUpToAndIncluding(installment.getFromDate(), chargesTillDate);
|
||||||
|
if (isDue) {
|
||||||
if (loanCharge.isFeeCharge()) {
|
if (loanCharge.isFeeCharge()) {
|
||||||
dueDateFeeIncome = dueDateFeeIncome.add(loanCharge.amount());
|
dueDateFeeIncome = dueDateFeeIncome.add(loanCharge.amount());
|
||||||
} else if (loanCharge.isPenaltyCharge()) {
|
} else if (loanCharge.isPenaltyCharge()) {
|
||||||
@@ -792,9 +795,10 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
loan.addLoanTransaction(accrualTransaction);
|
loan.addLoanTransaction(accrualTransaction);
|
||||||
Set<LoanChargePaidBy> accrualCharges = accrualTransaction.getLoanChargesPaid();
|
Set<LoanChargePaidBy> accrualCharges = accrualTransaction.getLoanChargesPaid();
|
||||||
for (LoanCharge loanCharge : loan.getActiveCharges()) {
|
for (LoanCharge loanCharge : loan.getActiveCharges()) {
|
||||||
if (loanCharge.isActive() && !loanCharge.isPaid()
|
boolean isDue = fromDate.isEqual(loan.getDisbursementDate())
|
||||||
&& (loanCharge.isDueForCollectionFromAndUpToAndIncluding(fromDate, foreClosureDate)
|
? loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(fromDate, foreClosureDate)
|
||||||
|| loanCharge.isInstalmentFee())) {
|
: loanCharge.isDueForCollectionFromAndUpToAndIncluding(fromDate, foreClosureDate);
|
||||||
|
if (loanCharge.isActive() && !loanCharge.isPaid() && (isDue || loanCharge.isInstalmentFee())) {
|
||||||
final LoanChargePaidBy loanChargePaidBy = new LoanChargePaidBy(accrualTransaction, loanCharge,
|
final LoanChargePaidBy loanChargePaidBy = new LoanChargePaidBy(accrualTransaction, loanCharge,
|
||||||
loanCharge.getAmountOutstanding(currency).getAmount(), null);
|
loanCharge.getAmountOutstanding(currency).getAmount(), null);
|
||||||
accrualCharges.add(loanChargePaidBy);
|
accrualCharges.add(loanChargePaidBy);
|
||||||
|
|||||||
+13
-2
@@ -625,14 +625,25 @@ public class LoanCharge extends AbstractPersistableCustom {
|
|||||||
|
|
||||||
public boolean isDueForCollectionFromAndUpToAndIncluding(final LocalDate fromNotInclusive, final LocalDate upToAndInclusive) {
|
public boolean isDueForCollectionFromAndUpToAndIncluding(final LocalDate fromNotInclusive, final LocalDate upToAndInclusive) {
|
||||||
final LocalDate dueDate = getDueLocalDate();
|
final LocalDate dueDate = getDueLocalDate();
|
||||||
return occursOnDayFromAndUpToAndIncluding(fromNotInclusive, upToAndInclusive, dueDate);
|
return occursOnDayFromExclusiveAndUpToAndIncluding(fromNotInclusive, upToAndInclusive, dueDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean occursOnDayFromAndUpToAndIncluding(final LocalDate fromNotInclusive, final LocalDate upToAndInclusive,
|
public boolean isDueForCollectionFromIncludingAndUpToAndIncluding(final LocalDate fromAndInclusive, final LocalDate upToAndInclusive) {
|
||||||
|
final LocalDate dueDate = getDueLocalDate();
|
||||||
|
return occursOnDayFromAndUpToAndIncluding(fromAndInclusive, upToAndInclusive, dueDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean occursOnDayFromExclusiveAndUpToAndIncluding(final LocalDate fromNotInclusive, final LocalDate upToAndInclusive,
|
||||||
final LocalDate target) {
|
final LocalDate target) {
|
||||||
return target != null && target.isAfter(fromNotInclusive) && !target.isAfter(upToAndInclusive);
|
return target != null && target.isAfter(fromNotInclusive) && !target.isAfter(upToAndInclusive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean occursOnDayFromAndUpToAndIncluding(final LocalDate fromAndInclusive, final LocalDate upToAndInclusive,
|
||||||
|
final LocalDate target) {
|
||||||
|
return target != null && (target.isEqual(fromAndInclusive) || target.isAfter(fromAndInclusive))
|
||||||
|
&& !target.isAfter(upToAndInclusive);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isFeeCharge() {
|
public boolean isFeeCharge() {
|
||||||
return !this.penaltyCharge;
|
return !this.penaltyCharge;
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-32
@@ -47,14 +47,14 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
|||||||
final Money feeChargesWaivedForRepaymentPeriod = cumulativeFeeChargesWaivedWithin(startDate, period.getDueDate(), loanCharges,
|
final Money feeChargesWaivedForRepaymentPeriod = cumulativeFeeChargesWaivedWithin(startDate, period.getDueDate(), loanCharges,
|
||||||
currency, !period.isRecalculatedInterestComponent(), period.isFirstPeriod());
|
currency, !period.isRecalculatedInterestComponent(), period.isFirstPeriod());
|
||||||
final Money feeChargesWrittenOffForRepaymentPeriod = cumulativeFeeChargesWrittenOffWithin(startDate, period.getDueDate(),
|
final Money feeChargesWrittenOffForRepaymentPeriod = cumulativeFeeChargesWrittenOffWithin(startDate, period.getDueDate(),
|
||||||
loanCharges, currency, !period.isRecalculatedInterestComponent());
|
loanCharges, currency, !period.isRecalculatedInterestComponent(), period.isFirstPeriod());
|
||||||
|
|
||||||
final Money penaltyChargesDueForRepaymentPeriod = cumulativePenaltyChargesDueWithin(startDate, period.getDueDate(), loanCharges,
|
final Money penaltyChargesDueForRepaymentPeriod = cumulativePenaltyChargesDueWithin(startDate, period.getDueDate(), loanCharges,
|
||||||
currency, period, totalPrincipal, totalInterest, !period.isRecalculatedInterestComponent());
|
currency, period, totalPrincipal, totalInterest, !period.isRecalculatedInterestComponent());
|
||||||
final Money penaltyChargesWaivedForRepaymentPeriod = cumulativePenaltyChargesWaivedWithin(startDate, period.getDueDate(),
|
final Money penaltyChargesWaivedForRepaymentPeriod = cumulativePenaltyChargesWaivedWithin(startDate, period.getDueDate(),
|
||||||
loanCharges, currency, !period.isRecalculatedInterestComponent(), period.isFirstPeriod());
|
loanCharges, currency, !period.isRecalculatedInterestComponent(), period.isFirstPeriod());
|
||||||
final Money penaltyChargesWrittenOffForRepaymentPeriod = cumulativePenaltyChargesWrittenOffWithin(startDate,
|
final Money penaltyChargesWrittenOffForRepaymentPeriod = cumulativePenaltyChargesWrittenOffWithin(startDate,
|
||||||
period.getDueDate(), loanCharges, currency, !period.isRecalculatedInterestComponent());
|
period.getDueDate(), loanCharges, currency, !period.isRecalculatedInterestComponent(), period.isFirstPeriod());
|
||||||
|
|
||||||
period.updateChargePortion(feeChargesDueForRepaymentPeriod, feeChargesWaivedForRepaymentPeriod,
|
period.updateChargePortion(feeChargesDueForRepaymentPeriod, feeChargesWaivedForRepaymentPeriod,
|
||||||
feeChargesWrittenOffForRepaymentPeriod, penaltyChargesDueForRepaymentPeriod, penaltyChargesWaivedForRepaymentPeriod,
|
feeChargesWrittenOffForRepaymentPeriod, penaltyChargesDueForRepaymentPeriod, penaltyChargesWaivedForRepaymentPeriod,
|
||||||
@@ -71,6 +71,9 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
|||||||
Money cumulative = Money.zero(monetaryCurrency);
|
Money cumulative = Money.zero(monetaryCurrency);
|
||||||
for (final LoanCharge loanCharge : loanCharges) {
|
for (final LoanCharge loanCharge : loanCharges) {
|
||||||
if (loanCharge.isFeeCharge() && !loanCharge.isDueAtDisbursement()) {
|
if (loanCharge.isFeeCharge() && !loanCharge.isDueAtDisbursement()) {
|
||||||
|
boolean isDue = period.isFirstPeriod()
|
||||||
|
? loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(periodStart, periodEnd)
|
||||||
|
: loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd);
|
||||||
if (loanCharge.isInstalmentFee() && isInstallmentChargeApplicable) {
|
if (loanCharge.isInstalmentFee() && isInstallmentChargeApplicable) {
|
||||||
if (loanCharge.getChargeCalculation().isPercentageBased()) {
|
if (loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
BigDecimal amount = BigDecimal.ZERO;
|
BigDecimal amount = BigDecimal.ZERO;
|
||||||
@@ -87,12 +90,9 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
|||||||
} else {
|
} else {
|
||||||
cumulative = cumulative.plus(loanCharge.amountOrPercentage());
|
cumulative = cumulative.plus(loanCharge.amountOrPercentage());
|
||||||
}
|
}
|
||||||
} else if (loanCharge.isOverdueInstallmentCharge()
|
} else if (loanCharge.isOverdueInstallmentCharge() && isDue && loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
&& loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)
|
|
||||||
&& loanCharge.getChargeCalculation().isPercentageBased()) {
|
|
||||||
cumulative = cumulative.plus(loanCharge.chargeAmount());
|
cumulative = cumulative.plus(loanCharge.chargeAmount());
|
||||||
} else if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)
|
} else if (isDue && loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
&& loanCharge.getChargeCalculation().isPercentageBased()) {
|
|
||||||
BigDecimal amount = BigDecimal.ZERO;
|
BigDecimal amount = BigDecimal.ZERO;
|
||||||
if (loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
|
if (loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
|
||||||
amount = amount.add(totalPrincipal.getAmount()).add(totalInterest.getAmount());
|
amount = amount.add(totalPrincipal.getAmount()).add(totalInterest.getAmount());
|
||||||
@@ -116,10 +116,7 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
|||||||
}
|
}
|
||||||
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
|
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
|
||||||
cumulative = cumulative.plus(loanChargeAmt);
|
cumulative = cumulative.plus(loanChargeAmt);
|
||||||
} else if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
|
} else if (isDue) {
|
||||||
cumulative = cumulative.plus(loanCharge.amount());
|
|
||||||
// Special case for Loan Charges (Due Date) added the same disbursement date
|
|
||||||
} else if (period.isFirstPeriod() && periodStart.equals(loanCharge.getDueDate())) {
|
|
||||||
cumulative = cumulative.plus(loanCharge.amount());
|
cumulative = cumulative.plus(loanCharge.amount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,15 +133,14 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
|||||||
|
|
||||||
for (final LoanCharge loanCharge : loanCharges) {
|
for (final LoanCharge loanCharge : loanCharges) {
|
||||||
if (loanCharge.isFeeCharge() && !loanCharge.isDueAtDisbursement()) {
|
if (loanCharge.isFeeCharge() && !loanCharge.isDueAtDisbursement()) {
|
||||||
|
boolean isDue = isFirstPeriod ? loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(periodStart, periodEnd)
|
||||||
|
: loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd);
|
||||||
if (loanCharge.isInstalmentFee() && isInstallmentChargeApplicable) {
|
if (loanCharge.isInstalmentFee() && isInstallmentChargeApplicable) {
|
||||||
LoanInstallmentCharge loanChargePerInstallment = loanCharge.getInstallmentLoanCharge(periodEnd);
|
LoanInstallmentCharge loanChargePerInstallment = loanCharge.getInstallmentLoanCharge(periodEnd);
|
||||||
if (loanChargePerInstallment != null) {
|
if (loanChargePerInstallment != null) {
|
||||||
cumulative = cumulative.plus(loanChargePerInstallment.getAmountWaived(currency));
|
cumulative = cumulative.plus(loanChargePerInstallment.getAmountWaived(currency));
|
||||||
}
|
}
|
||||||
} else if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
|
} else if (isDue) {
|
||||||
cumulative = cumulative.plus(loanCharge.getAmountWaived(currency));
|
|
||||||
// Special case for Loan Charges (Due Date) added the same disbursement date
|
|
||||||
} else if (isFirstPeriod && periodStart.equals(loanCharge.getDueDate())) {
|
|
||||||
cumulative = cumulative.plus(loanCharge.getAmountWaived(currency));
|
cumulative = cumulative.plus(loanCharge.getAmountWaived(currency));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,18 +150,21 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Money cumulativeFeeChargesWrittenOffWithin(final LocalDate periodStart, final LocalDate periodEnd,
|
private Money cumulativeFeeChargesWrittenOffWithin(final LocalDate periodStart, final LocalDate periodEnd,
|
||||||
final Set<LoanCharge> loanCharges, final MonetaryCurrency currency, boolean isInstallmentChargeApplicable) {
|
final Set<LoanCharge> loanCharges, final MonetaryCurrency currency, boolean isInstallmentChargeApplicable,
|
||||||
|
boolean isFirstPeriod) {
|
||||||
|
|
||||||
Money cumulative = Money.zero(currency);
|
Money cumulative = Money.zero(currency);
|
||||||
|
|
||||||
for (final LoanCharge loanCharge : loanCharges) {
|
for (final LoanCharge loanCharge : loanCharges) {
|
||||||
if (loanCharge.isFeeCharge() && !loanCharge.isDueAtDisbursement()) {
|
if (loanCharge.isFeeCharge() && !loanCharge.isDueAtDisbursement()) {
|
||||||
|
boolean isDue = isFirstPeriod ? loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(periodStart, periodEnd)
|
||||||
|
: loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd);
|
||||||
if (loanCharge.isInstalmentFee() && isInstallmentChargeApplicable) {
|
if (loanCharge.isInstalmentFee() && isInstallmentChargeApplicable) {
|
||||||
LoanInstallmentCharge loanChargePerInstallment = loanCharge.getInstallmentLoanCharge(periodEnd);
|
LoanInstallmentCharge loanChargePerInstallment = loanCharge.getInstallmentLoanCharge(periodEnd);
|
||||||
if (loanChargePerInstallment != null) {
|
if (loanChargePerInstallment != null) {
|
||||||
cumulative = cumulative.plus(loanChargePerInstallment.getAmountWrittenOff(currency));
|
cumulative = cumulative.plus(loanChargePerInstallment.getAmountWrittenOff(currency));
|
||||||
}
|
}
|
||||||
} else if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
|
} else if (isDue) {
|
||||||
cumulative = cumulative.plus(loanCharge.getAmountWrittenOff(currency));
|
cumulative = cumulative.plus(loanCharge.getAmountWrittenOff(currency));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -182,6 +181,9 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
|||||||
|
|
||||||
for (final LoanCharge loanCharge : loanCharges) {
|
for (final LoanCharge loanCharge : loanCharges) {
|
||||||
if (loanCharge.isPenaltyCharge()) {
|
if (loanCharge.isPenaltyCharge()) {
|
||||||
|
boolean isDue = period.isFirstPeriod()
|
||||||
|
? loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(periodStart, periodEnd)
|
||||||
|
: loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd);
|
||||||
if (loanCharge.isInstalmentFee() && isInstallmentChargeApplicable) {
|
if (loanCharge.isInstalmentFee() && isInstallmentChargeApplicable) {
|
||||||
if (loanCharge.getChargeCalculation().isPercentageBased()) {
|
if (loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
BigDecimal amount = BigDecimal.ZERO;
|
BigDecimal amount = BigDecimal.ZERO;
|
||||||
@@ -198,12 +200,9 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
|||||||
} else {
|
} else {
|
||||||
cumulative = cumulative.plus(loanCharge.amountOrPercentage());
|
cumulative = cumulative.plus(loanCharge.amountOrPercentage());
|
||||||
}
|
}
|
||||||
} else if (loanCharge.isOverdueInstallmentCharge()
|
} else if (loanCharge.isOverdueInstallmentCharge() && isDue && loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
&& loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)
|
|
||||||
&& loanCharge.getChargeCalculation().isPercentageBased()) {
|
|
||||||
cumulative = cumulative.plus(loanCharge.chargeAmount());
|
cumulative = cumulative.plus(loanCharge.chargeAmount());
|
||||||
} else if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)
|
} else if (isDue && loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
&& loanCharge.getChargeCalculation().isPercentageBased()) {
|
|
||||||
BigDecimal amount = BigDecimal.ZERO;
|
BigDecimal amount = BigDecimal.ZERO;
|
||||||
if (loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
|
if (loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
|
||||||
amount = amount.add(totalPrincipal.getAmount()).add(totalInterest.getAmount());
|
amount = amount.add(totalPrincipal.getAmount()).add(totalInterest.getAmount());
|
||||||
@@ -214,10 +213,7 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
|||||||
}
|
}
|
||||||
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
|
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
|
||||||
cumulative = cumulative.plus(loanChargeAmt);
|
cumulative = cumulative.plus(loanChargeAmt);
|
||||||
} else if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
|
} else if (isDue) {
|
||||||
cumulative = cumulative.plus(loanCharge.amount());
|
|
||||||
// Special case for Loan Charges (Due Date) added the same disbursement date
|
|
||||||
} else if (period.isFirstPeriod() && periodStart.equals(loanCharge.getDueDate())) {
|
|
||||||
cumulative = cumulative.plus(loanCharge.amount());
|
cumulative = cumulative.plus(loanCharge.amount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,15 +230,14 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
|||||||
|
|
||||||
for (final LoanCharge loanCharge : loanCharges) {
|
for (final LoanCharge loanCharge : loanCharges) {
|
||||||
if (loanCharge.isPenaltyCharge()) {
|
if (loanCharge.isPenaltyCharge()) {
|
||||||
|
boolean isDue = isFirstPeriod ? loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(periodStart, periodEnd)
|
||||||
|
: loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd);
|
||||||
if (loanCharge.isInstalmentFee() && isInstallmentChargeApplicable) {
|
if (loanCharge.isInstalmentFee() && isInstallmentChargeApplicable) {
|
||||||
LoanInstallmentCharge loanChargePerInstallment = loanCharge.getInstallmentLoanCharge(periodEnd);
|
LoanInstallmentCharge loanChargePerInstallment = loanCharge.getInstallmentLoanCharge(periodEnd);
|
||||||
if (loanChargePerInstallment != null) {
|
if (loanChargePerInstallment != null) {
|
||||||
cumulative = cumulative.plus(loanChargePerInstallment.getAmountWaived(currency));
|
cumulative = cumulative.plus(loanChargePerInstallment.getAmountWaived(currency));
|
||||||
}
|
}
|
||||||
} else if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
|
} else if (isDue) {
|
||||||
cumulative = cumulative.plus(loanCharge.getAmountWaived(currency));
|
|
||||||
// Special case for Loan Charges (Due Date) added the same disbursement date
|
|
||||||
} else if (isFirstPeriod && periodStart.equals(loanCharge.getDueDate())) {
|
|
||||||
cumulative = cumulative.plus(loanCharge.getAmountWaived(currency));
|
cumulative = cumulative.plus(loanCharge.getAmountWaived(currency));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -252,18 +247,21 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Money cumulativePenaltyChargesWrittenOffWithin(final LocalDate periodStart, final LocalDate periodEnd,
|
private Money cumulativePenaltyChargesWrittenOffWithin(final LocalDate periodStart, final LocalDate periodEnd,
|
||||||
final Set<LoanCharge> loanCharges, final MonetaryCurrency currency, boolean isInstallmentChargeApplicable) {
|
final Set<LoanCharge> loanCharges, final MonetaryCurrency currency, boolean isInstallmentChargeApplicable,
|
||||||
|
final boolean isFirstPeriod) {
|
||||||
|
|
||||||
Money cumulative = Money.zero(currency);
|
Money cumulative = Money.zero(currency);
|
||||||
|
|
||||||
for (final LoanCharge loanCharge : loanCharges) {
|
for (final LoanCharge loanCharge : loanCharges) {
|
||||||
if (loanCharge.isPenaltyCharge()) {
|
if (loanCharge.isPenaltyCharge()) {
|
||||||
|
boolean isDue = isFirstPeriod ? loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(periodStart, periodEnd)
|
||||||
|
: loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd);
|
||||||
if (loanCharge.isInstalmentFee() && isInstallmentChargeApplicable) {
|
if (loanCharge.isInstalmentFee() && isInstallmentChargeApplicable) {
|
||||||
LoanInstallmentCharge loanChargePerInstallment = loanCharge.getInstallmentLoanCharge(periodEnd);
|
LoanInstallmentCharge loanChargePerInstallment = loanCharge.getInstallmentLoanCharge(periodEnd);
|
||||||
if (loanChargePerInstallment != null) {
|
if (loanChargePerInstallment != null) {
|
||||||
cumulative = cumulative.plus(loanChargePerInstallment.getAmountWrittenOff(currency));
|
cumulative = cumulative.plus(loanChargePerInstallment.getAmountWrittenOff(currency));
|
||||||
}
|
}
|
||||||
} else if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
|
} else if (isDue) {
|
||||||
cumulative = cumulative.plus(loanCharge.getAmountWrittenOff(currency));
|
cumulative = cumulative.plus(loanCharge.getAmountWrittenOff(currency));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -110,10 +110,10 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
LocalDate startDate = disbursementDate;
|
LocalDate startDate = disbursementDate;
|
||||||
for (final LoanRepaymentScheduleInstallment installment : installments) {
|
for (final LoanRepaymentScheduleInstallment installment : installments) {
|
||||||
for (final LoanCharge loanCharge : transferCharges) {
|
for (final LoanCharge loanCharge : transferCharges) {
|
||||||
if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(startDate, installment.getDueDate())
|
boolean isDue = installment.isFirstPeriod()
|
||||||
// Special case for Loan Charges (Due Date) added the same disbursement date
|
? loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(startDate, installment.getDueDate())
|
||||||
|| (startDate.equals(disbursementDate) && loanCharge.getDueDate() != null
|
: loanCharge.isDueForCollectionFromAndUpToAndIncluding(startDate, installment.getDueDate());
|
||||||
&& loanCharge.getDueDate().equals(disbursementDate))) {
|
if (isDue) {
|
||||||
Money amountForProcess = loanCharge.getAmount(currency);
|
Money amountForProcess = loanCharge.getAmount(currency);
|
||||||
if (amountForProcess.isGreaterThan(loanTransaction.getAmount(currency))) {
|
if (amountForProcess.isGreaterThan(loanTransaction.getAmount(currency))) {
|
||||||
amountForProcess = loanTransaction.getAmount(currency);
|
amountForProcess = loanTransaction.getAmount(currency);
|
||||||
|
|||||||
+4
@@ -477,4 +477,8 @@ public final class LoanScheduleParams {
|
|||||||
public void setUnCompoundedAmount(Money unCompoundedAmount) {
|
public void setUnCompoundedAmount(Money unCompoundedAmount) {
|
||||||
this.unCompoundedAmount = unCompoundedAmount;
|
this.unCompoundedAmount = unCompoundedAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isFirstPeriod() {
|
||||||
|
return 1 == instalmentNumber;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-29
@@ -437,12 +437,12 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
LoanScheduleParams scheduleParams, LocalDate scheduledDueDate, ScheduleCurrentPeriodParams currentPeriodParams) {
|
LoanScheduleParams scheduleParams, LocalDate scheduledDueDate, ScheduleCurrentPeriodParams currentPeriodParams) {
|
||||||
PrincipalInterest principalInterest = new PrincipalInterest(currentPeriodParams.getPrincipalForThisPeriod(),
|
PrincipalInterest principalInterest = new PrincipalInterest(currentPeriodParams.getPrincipalForThisPeriod(),
|
||||||
currentPeriodParams.getInterestForThisPeriod(), null);
|
currentPeriodParams.getInterestForThisPeriod(), null);
|
||||||
currentPeriodParams.setFeeChargesForInstallment(
|
currentPeriodParams.setFeeChargesForInstallment(cumulativeFeeChargesDueWithin(scheduleParams.getPeriodStartDate(), scheduledDueDate,
|
||||||
cumulativeFeeChargesDueWithin(scheduleParams.getPeriodStartDate(), scheduledDueDate, loanCharges, currency,
|
loanCharges, currency, principalInterest, scheduleParams.getPrincipalToBeScheduled(),
|
||||||
principalInterest, scheduleParams.getPrincipalToBeScheduled(), scheduleParams.getTotalCumulativeInterest(), true));
|
scheduleParams.getTotalCumulativeInterest(), true, scheduleParams.isFirstPeriod()));
|
||||||
currentPeriodParams.setPenaltyChargesForInstallment(
|
currentPeriodParams.setPenaltyChargesForInstallment(cumulativePenaltyChargesDueWithin(scheduleParams.getPeriodStartDate(),
|
||||||
cumulativePenaltyChargesDueWithin(scheduleParams.getPeriodStartDate(), scheduledDueDate, loanCharges, currency,
|
scheduledDueDate, loanCharges, currency, principalInterest, scheduleParams.getPrincipalToBeScheduled(),
|
||||||
principalInterest, scheduleParams.getPrincipalToBeScheduled(), scheduleParams.getTotalCumulativeInterest(), true));
|
scheduleParams.getTotalCumulativeInterest(), true, scheduleParams.isFirstPeriod()));
|
||||||
scheduleParams.addTotalFeeChargesCharged(currentPeriodParams.getFeeChargesForInstallment());
|
scheduleParams.addTotalFeeChargesCharged(currentPeriodParams.getFeeChargesForInstallment());
|
||||||
scheduleParams.addTotalPenaltyChargesCharged(currentPeriodParams.getPenaltyChargesForInstallment());
|
scheduleParams.addTotalPenaltyChargesCharged(currentPeriodParams.getPenaltyChargesForInstallment());
|
||||||
}
|
}
|
||||||
@@ -456,11 +456,11 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(loanScheduleModelPeriod.periodFromDate(),
|
Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(loanScheduleModelPeriod.periodFromDate(),
|
||||||
loanScheduleModelPeriod.periodDueDate(), nonCompoundingCharges, currency, principalInterest,
|
loanScheduleModelPeriod.periodDueDate(), nonCompoundingCharges, currency, principalInterest,
|
||||||
scheduleParams.getPrincipalToBeScheduled(), scheduleParams.getTotalCumulativeInterest(),
|
scheduleParams.getPrincipalToBeScheduled(), scheduleParams.getTotalCumulativeInterest(),
|
||||||
!loanScheduleModelPeriod.isRecalculatedInterestComponent());
|
!loanScheduleModelPeriod.isRecalculatedInterestComponent(), scheduleParams.isFirstPeriod());
|
||||||
Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(loanScheduleModelPeriod.periodFromDate(),
|
Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(loanScheduleModelPeriod.periodFromDate(),
|
||||||
loanScheduleModelPeriod.periodDueDate(), nonCompoundingCharges, currency, principalInterest,
|
loanScheduleModelPeriod.periodDueDate(), nonCompoundingCharges, currency, principalInterest,
|
||||||
scheduleParams.getPrincipalToBeScheduled(), scheduleParams.getTotalCumulativeInterest(),
|
scheduleParams.getPrincipalToBeScheduled(), scheduleParams.getTotalCumulativeInterest(),
|
||||||
!loanScheduleModelPeriod.isRecalculatedInterestComponent());
|
!loanScheduleModelPeriod.isRecalculatedInterestComponent(), scheduleParams.isFirstPeriod());
|
||||||
scheduleParams.addTotalFeeChargesCharged(feeChargesForInstallment);
|
scheduleParams.addTotalFeeChargesCharged(feeChargesForInstallment);
|
||||||
scheduleParams.addTotalPenaltyChargesCharged(penaltyChargesForInstallment);
|
scheduleParams.addTotalPenaltyChargesCharged(penaltyChargesForInstallment);
|
||||||
scheduleParams.addTotalRepaymentExpected(feeChargesForInstallment.plus(penaltyChargesForInstallment));
|
scheduleParams.addTotalRepaymentExpected(feeChargesForInstallment.plus(penaltyChargesForInstallment));
|
||||||
@@ -561,10 +561,10 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
currentPeriodParams.getInterestForThisPeriod(), null);
|
currentPeriodParams.getInterestForThisPeriod(), null);
|
||||||
oustanding = oustanding.minus(cumulativeFeeChargesDueWithin(transactionDate, scheduledDueDate, loanCharges,
|
oustanding = oustanding.minus(cumulativeFeeChargesDueWithin(transactionDate, scheduledDueDate, loanCharges,
|
||||||
totalInterestChargedForFullLoanTerm.getCurrency(), tempPrincipalInterest, scheduleParams.getPrincipalToBeScheduled(),
|
totalInterestChargedForFullLoanTerm.getCurrency(), tempPrincipalInterest, scheduleParams.getPrincipalToBeScheduled(),
|
||||||
scheduleParams.getTotalCumulativeInterest(), true));
|
scheduleParams.getTotalCumulativeInterest(), true, scheduleParams.isFirstPeriod()));
|
||||||
oustanding = oustanding.minus(cumulativePenaltyChargesDueWithin(transactionDate, scheduledDueDate, loanCharges,
|
oustanding = oustanding.minus(cumulativePenaltyChargesDueWithin(transactionDate, scheduledDueDate, loanCharges,
|
||||||
totalInterestChargedForFullLoanTerm.getCurrency(), tempPrincipalInterest, scheduleParams.getPrincipalToBeScheduled(),
|
totalInterestChargedForFullLoanTerm.getCurrency(), tempPrincipalInterest, scheduleParams.getPrincipalToBeScheduled(),
|
||||||
scheduleParams.getTotalCumulativeInterest(), true));
|
scheduleParams.getTotalCumulativeInterest(), true, scheduleParams.isFirstPeriod()));
|
||||||
|
|
||||||
if (!oustanding.isGreaterThan(currentPeriodParams.getInterestForThisPeriod()) && !scheduledDueDate.equals(transactionDate)) {
|
if (!oustanding.isGreaterThan(currentPeriodParams.getInterestForThisPeriod()) && !scheduledDueDate.equals(transactionDate)) {
|
||||||
final Collection<LoanTermVariationsData> interestRates = loanApplicationTerms.getLoanTermVariations().getInterestRateChanges();
|
final Collection<LoanTermVariationsData> interestRates = loanApplicationTerms.getLoanTermVariations().getInterestRateChanges();
|
||||||
@@ -717,7 +717,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
processTransactions.clear();
|
processTransactions.clear();
|
||||||
currentTransactions.addAll(createCurrentTransactionList(detail));
|
currentTransactions.addAll(createCurrentTransactionList(detail));
|
||||||
|
|
||||||
if (!transactionDate.isEqual(scheduleParams.getPeriodStartDate()) || scheduleParams.getInstalmentNumber() == 1) {
|
if (!transactionDate.isEqual(scheduleParams.getPeriodStartDate()) || scheduleParams.isFirstPeriod()) {
|
||||||
|
|
||||||
int periodDays = Math.toIntExact(ChronoUnit.DAYS.between(scheduleParams.getPeriodStartDate(), transactionDate));
|
int periodDays = Math.toIntExact(ChronoUnit.DAYS.between(scheduleParams.getPeriodStartDate(), transactionDate));
|
||||||
// calculates period start date for interest
|
// calculates period start date for interest
|
||||||
@@ -758,10 +758,10 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
null);
|
null);
|
||||||
Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(scheduleParams.getPeriodStartDate(),
|
Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(scheduleParams.getPeriodStartDate(),
|
||||||
transactionDate, loanCharges, currency, principalInterest, scheduleParams.getPrincipalToBeScheduled(),
|
transactionDate, loanCharges, currency, principalInterest, scheduleParams.getPrincipalToBeScheduled(),
|
||||||
scheduleParams.getTotalCumulativeInterest(), false);
|
scheduleParams.getTotalCumulativeInterest(), false, scheduleParams.isFirstPeriod());
|
||||||
Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(scheduleParams.getPeriodStartDate(),
|
Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(scheduleParams.getPeriodStartDate(),
|
||||||
transactionDate, loanCharges, currency, principalInterest, scheduleParams.getPrincipalToBeScheduled(),
|
transactionDate, loanCharges, currency, principalInterest, scheduleParams.getPrincipalToBeScheduled(),
|
||||||
scheduleParams.getTotalCumulativeInterest(), false);
|
scheduleParams.getTotalCumulativeInterest(), false, scheduleParams.isFirstPeriod());
|
||||||
|
|
||||||
// sum up real totalInstallmentDue from
|
// sum up real totalInstallmentDue from
|
||||||
// components
|
// components
|
||||||
@@ -1788,9 +1788,9 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
|
|
||||||
if (compoundingDate.isBefore(endDate)) {
|
if (compoundingDate.isBefore(endDate)) {
|
||||||
Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(lastCompoundingDate, compoundingDate, charges, currency,
|
Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(lastCompoundingDate, compoundingDate, charges, currency,
|
||||||
null, loanApplicationTerms.getPrincipal(), null, false);
|
null, loanApplicationTerms.getPrincipal(), null, false, lastCompoundingDate.isEqual(startDate));
|
||||||
Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(lastCompoundingDate, compoundingDate, charges,
|
Money penaltyChargesForInstallment = cumulativePenaltyChargesDueWithin(lastCompoundingDate, compoundingDate, charges,
|
||||||
currency, null, loanApplicationTerms.getPrincipal(), null, false);
|
currency, null, loanApplicationTerms.getPrincipal(), null, false, lastCompoundingDate.isEqual(startDate));
|
||||||
Money compoundAmount = feeChargesForInstallment.plus(penaltyChargesForInstallment);
|
Money compoundAmount = feeChargesForInstallment.plus(penaltyChargesForInstallment);
|
||||||
if (addUncompounded) {
|
if (addUncompounded) {
|
||||||
compoundAmount = compoundAmount.plus(scheduleParams.getUnCompoundedAmount());
|
compoundAmount = compoundAmount.plus(scheduleParams.getUnCompoundedAmount());
|
||||||
@@ -1987,23 +1987,22 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
|
|
||||||
private Money cumulativeFeeChargesDueWithin(final LocalDate periodStart, final LocalDate periodEnd, final Set<LoanCharge> loanCharges,
|
private Money cumulativeFeeChargesDueWithin(final LocalDate periodStart, final LocalDate periodEnd, final Set<LoanCharge> loanCharges,
|
||||||
final MonetaryCurrency monetaryCurrency, final PrincipalInterest principalInterestForThisPeriod, final Money principalDisbursed,
|
final MonetaryCurrency monetaryCurrency, final PrincipalInterest principalInterestForThisPeriod, final Money principalDisbursed,
|
||||||
final Money totalInterestChargedForFullLoanTerm, boolean isInstallmentChargeApplicable) {
|
final Money totalInterestChargedForFullLoanTerm, boolean isInstallmentChargeApplicable, final boolean isFirstPeriod) {
|
||||||
|
|
||||||
Money cumulative = Money.zero(monetaryCurrency);
|
Money cumulative = Money.zero(monetaryCurrency);
|
||||||
|
|
||||||
for (final LoanCharge loanCharge : loanCharges) {
|
for (final LoanCharge loanCharge : loanCharges) {
|
||||||
if (!loanCharge.isDueAtDisbursement() && loanCharge.isFeeCharge()) {
|
if (!loanCharge.isDueAtDisbursement() && loanCharge.isFeeCharge()) {
|
||||||
|
boolean isDue = isFirstPeriod ? loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(periodStart, periodEnd)
|
||||||
|
: loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd);
|
||||||
if (loanCharge.isInstalmentFee() && isInstallmentChargeApplicable) {
|
if (loanCharge.isInstalmentFee() && isInstallmentChargeApplicable) {
|
||||||
cumulative = calculateInstallmentCharge(principalInterestForThisPeriod, cumulative, loanCharge);
|
cumulative = calculateInstallmentCharge(principalInterestForThisPeriod, cumulative, loanCharge);
|
||||||
} else if (loanCharge.isOverdueInstallmentCharge()
|
} else if (loanCharge.isOverdueInstallmentCharge() && isDue && loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
&& loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)
|
|
||||||
&& loanCharge.getChargeCalculation().isPercentageBased()) {
|
|
||||||
cumulative = cumulative.plus(loanCharge.chargeAmount());
|
cumulative = cumulative.plus(loanCharge.chargeAmount());
|
||||||
} else if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)
|
} else if (isDue && loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
&& loanCharge.getChargeCalculation().isPercentageBased()) {
|
|
||||||
cumulative = calculateSpecificDueDateChargeWithPercentage(principalDisbursed, totalInterestChargedForFullLoanTerm,
|
cumulative = calculateSpecificDueDateChargeWithPercentage(principalDisbursed, totalInterestChargedForFullLoanTerm,
|
||||||
cumulative, loanCharge);
|
cumulative, loanCharge);
|
||||||
} else if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
|
} else if (isDue) {
|
||||||
cumulative = cumulative.plus(loanCharge.amount());
|
cumulative = cumulative.plus(loanCharge.amount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2050,23 +2049,22 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
|||||||
private Money cumulativePenaltyChargesDueWithin(final LocalDate periodStart, final LocalDate periodEnd,
|
private Money cumulativePenaltyChargesDueWithin(final LocalDate periodStart, final LocalDate periodEnd,
|
||||||
final Set<LoanCharge> loanCharges, final MonetaryCurrency monetaryCurrency,
|
final Set<LoanCharge> loanCharges, final MonetaryCurrency monetaryCurrency,
|
||||||
final PrincipalInterest principalInterestForThisPeriod, final Money principalDisbursed,
|
final PrincipalInterest principalInterestForThisPeriod, final Money principalDisbursed,
|
||||||
final Money totalInterestChargedForFullLoanTerm, boolean isInstallmentChargeApplicable) {
|
final Money totalInterestChargedForFullLoanTerm, boolean isInstallmentChargeApplicable, final boolean isFirstPeriod) {
|
||||||
|
|
||||||
Money cumulative = Money.zero(monetaryCurrency);
|
Money cumulative = Money.zero(monetaryCurrency);
|
||||||
|
|
||||||
for (final LoanCharge loanCharge : loanCharges) {
|
for (final LoanCharge loanCharge : loanCharges) {
|
||||||
if (loanCharge.isPenaltyCharge()) {
|
if (loanCharge.isPenaltyCharge()) {
|
||||||
|
boolean isDue = isFirstPeriod ? loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(periodStart, periodEnd)
|
||||||
|
: loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd);
|
||||||
if (loanCharge.isInstalmentFee() && isInstallmentChargeApplicable) {
|
if (loanCharge.isInstalmentFee() && isInstallmentChargeApplicable) {
|
||||||
cumulative = calculateInstallmentCharge(principalInterestForThisPeriod, cumulative, loanCharge);
|
cumulative = calculateInstallmentCharge(principalInterestForThisPeriod, cumulative, loanCharge);
|
||||||
} else if (loanCharge.isOverdueInstallmentCharge()
|
} else if (loanCharge.isOverdueInstallmentCharge() && isDue && loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
&& loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)
|
|
||||||
&& loanCharge.getChargeCalculation().isPercentageBased()) {
|
|
||||||
cumulative = cumulative.plus(loanCharge.chargeAmount());
|
cumulative = cumulative.plus(loanCharge.chargeAmount());
|
||||||
} else if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)
|
} else if (isDue && loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||||
&& loanCharge.getChargeCalculation().isPercentageBased()) {
|
|
||||||
cumulative = calculateSpecificDueDateChargeWithPercentage(principalDisbursed, totalInterestChargedForFullLoanTerm,
|
cumulative = calculateSpecificDueDateChargeWithPercentage(principalDisbursed, totalInterestChargedForFullLoanTerm,
|
||||||
cumulative, loanCharge);
|
cumulative, loanCharge);
|
||||||
} else if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
|
} else if (isDue) {
|
||||||
cumulative = cumulative.plus(loanCharge.amount());
|
cumulative = cumulative.plus(loanCharge.amount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+64
-3
@@ -26,6 +26,7 @@ import io.restassured.builder.ResponseSpecBuilder;
|
|||||||
import io.restassured.http.ContentType;
|
import io.restassured.http.ContentType;
|
||||||
import io.restassured.specification.RequestSpecification;
|
import io.restassured.specification.RequestSpecification;
|
||||||
import io.restassured.specification.ResponseSpecification;
|
import io.restassured.specification.ResponseSpecification;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -37,6 +38,7 @@ import org.apache.fineract.client.models.JournalEntryTransactionItem;
|
|||||||
import org.apache.fineract.client.models.PostChargesResponse;
|
import org.apache.fineract.client.models.PostChargesResponse;
|
||||||
import org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdResponse;
|
import org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdResponse;
|
||||||
import org.apache.fineract.client.models.PostLoansLoanIdChargesResponse;
|
import org.apache.fineract.client.models.PostLoansLoanIdChargesResponse;
|
||||||
|
import org.apache.fineract.client.models.PostLoansLoanIdRequest;
|
||||||
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
|
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
|
||||||
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
|
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
|
||||||
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
|
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
|
||||||
@@ -505,6 +507,64 @@ public class LoanChargeSpecificDueDateTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplyLoanSpecificDueDatePenaltyWithDisbursementDateWithMultipleDisbursement() {
|
||||||
|
|
||||||
|
final LocalDate todaysDate = Utils.getLocalDateOfTenant();
|
||||||
|
|
||||||
|
// Client and Loan account creation
|
||||||
|
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2012");
|
||||||
|
final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProductWithPeriodicAccrual(loanTransactionHelper,
|
||||||
|
null);
|
||||||
|
assertNotNull(getLoanProductsProductResponse);
|
||||||
|
|
||||||
|
// Older date to have more than one overdue installment
|
||||||
|
LocalDate transactionDate = todaysDate;
|
||||||
|
String operationDate = Utils.dateFormatter.format(transactionDate);
|
||||||
|
log.info("Operation date {}", transactionDate);
|
||||||
|
|
||||||
|
// Create Loan Account
|
||||||
|
final Integer loanId = createLoanAccount(loanTransactionHelper, clientId.toString(),
|
||||||
|
getLoanProductsProductResponse.getId().toString(), operationDate, "12", "0");
|
||||||
|
|
||||||
|
// Get loan details
|
||||||
|
GetLoansLoanIdResponse getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
|
||||||
|
validateLoanAccount(getLoansLoanIdResponse, Double.valueOf(principalAmount), Double.valueOf("0.00"), true);
|
||||||
|
|
||||||
|
// Apply Loan Charge with specific due date
|
||||||
|
|
||||||
|
final String feeAmount = "10.00";
|
||||||
|
String payloadJSON = ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, feeAmount, true);
|
||||||
|
final PostChargesResponse postChargesResponse = ChargesHelper.createLoanCharge(requestSpec, responseSpec, payloadJSON);
|
||||||
|
assertNotNull(postChargesResponse);
|
||||||
|
final Long loanChargeId = postChargesResponse.getResourceId();
|
||||||
|
assertNotNull(loanChargeId);
|
||||||
|
|
||||||
|
payloadJSON = LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(loanChargeId.toString(), operationDate, feeAmount);
|
||||||
|
PostLoansLoanIdChargesResponse postLoansLoanIdChargesResponse = loanTransactionHelper.addChargeForLoan(loanId, payloadJSON,
|
||||||
|
responseSpec);
|
||||||
|
assertNotNull(postLoansLoanIdChargesResponse);
|
||||||
|
|
||||||
|
// Get loan details expecting to have a delinquency classification
|
||||||
|
getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
|
||||||
|
validateLoanAccount(getLoansLoanIdResponse, Double.valueOf(principalAmount), Double.valueOf("10.00"), true);
|
||||||
|
|
||||||
|
loanTransactionHelper.disburseLoan((long) loanId, new PostLoansLoanIdRequest().actualDisbursementDate(operationDate)
|
||||||
|
.transactionAmount(new BigDecimal("1000")).locale("en").dateFormat("dd MMMM yyyy"));
|
||||||
|
|
||||||
|
// Get loan details expecting to have a delinquency classification
|
||||||
|
getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
|
||||||
|
validateLoanAccount(getLoansLoanIdResponse, Double.parseDouble(principalAmount) * 2, Double.valueOf("10.00"), true);
|
||||||
|
|
||||||
|
operationDate = Utils.dateFormatter.format(transactionDate.plusMonths(1));
|
||||||
|
payloadJSON = LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(loanChargeId.toString(), operationDate, feeAmount);
|
||||||
|
postLoansLoanIdChargesResponse = loanTransactionHelper.addChargeForLoan(loanId, payloadJSON, responseSpec);
|
||||||
|
|
||||||
|
// Get loan details expecting to have a delinquency classification
|
||||||
|
getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
|
||||||
|
validateLoanAccount(getLoansLoanIdResponse, Double.parseDouble(principalAmount) * 2, Double.valueOf("20.00"), true);
|
||||||
|
}
|
||||||
|
|
||||||
private GetLoanProductsProductIdResponse createLoanProduct(final LoanTransactionHelper loanTransactionHelper,
|
private GetLoanProductsProductIdResponse createLoanProduct(final LoanTransactionHelper loanTransactionHelper,
|
||||||
final Integer delinquencyBucketId) {
|
final Integer delinquencyBucketId) {
|
||||||
final HashMap<String, Object> loanProductMap = new LoanProductTestBuilder().build(null, delinquencyBucketId);
|
final HashMap<String, Object> loanProductMap = new LoanProductTestBuilder().build(null, delinquencyBucketId);
|
||||||
@@ -515,13 +575,14 @@ public class LoanChargeSpecificDueDateTest {
|
|||||||
private GetLoanProductsProductIdResponse createLoanProductWithPeriodicAccrual(final LoanTransactionHelper loanTransactionHelper,
|
private GetLoanProductsProductIdResponse createLoanProductWithPeriodicAccrual(final LoanTransactionHelper loanTransactionHelper,
|
||||||
final Integer delinquencyBucketId) {
|
final Integer delinquencyBucketId) {
|
||||||
final Account assetAccount = this.accountHelper.createAssetAccount();
|
final Account assetAccount = this.accountHelper.createAssetAccount();
|
||||||
final Account assetFeeAndPenaltyAccount = this.accountHelper.createAssetAccount();
|
|
||||||
final Account incomeAccount = this.accountHelper.createIncomeAccount();
|
final Account incomeAccount = this.accountHelper.createIncomeAccount();
|
||||||
final Account expenseAccount = this.accountHelper.createExpenseAccount();
|
final Account expenseAccount = this.accountHelper.createExpenseAccount();
|
||||||
final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
|
final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
|
||||||
|
|
||||||
final HashMap<String, Object> loanProductMap = new LoanProductTestBuilder()
|
final HashMap<String, Object> loanProductMap = new LoanProductTestBuilder().withMultiDisburse()
|
||||||
|
.withInterestCalculationPeriodTypeAsRepaymentPeriod(true).withInterestTypeAsDecliningBalance()
|
||||||
.withAccountingRulePeriodicAccrual(new Account[] { assetAccount, incomeAccount, expenseAccount, overpaymentAccount })
|
.withAccountingRulePeriodicAccrual(new Account[] { assetAccount, incomeAccount, expenseAccount, overpaymentAccount })
|
||||||
|
.withDisallowExpectedDisbursements(true) //
|
||||||
.build(null, delinquencyBucketId);
|
.build(null, delinquencyBucketId);
|
||||||
final Integer loanProductId = loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
|
final Integer loanProductId = loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
|
||||||
return loanTransactionHelper.getLoanProduct(loanProductId);
|
return loanTransactionHelper.getLoanProduct(loanProductId);
|
||||||
@@ -539,7 +600,7 @@ public class LoanChargeSpecificDueDateTest {
|
|||||||
.build(clientId, loanProductId, null);
|
.build(clientId, loanProductId, null);
|
||||||
final Integer loanId = loanTransactionHelper.getLoanId(loanApplicationJSON);
|
final Integer loanId = loanTransactionHelper.getLoanId(loanApplicationJSON);
|
||||||
loanTransactionHelper.approveLoan(operationDate, principalAmount, loanId, null);
|
loanTransactionHelper.approveLoan(operationDate, principalAmount, loanId, null);
|
||||||
loanTransactionHelper.disburseLoanWithNetDisbursalAmount(operationDate, loanId, principalAmount);
|
loanTransactionHelper.disburseLoanWithTransactionAmount(operationDate, loanId, principalAmount);
|
||||||
return loanId;
|
return loanId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-61
@@ -95,53 +95,6 @@ public class LoanSpecificDueDateChargeAfterMaturityTest {
|
|||||||
this.periodicAccrualAccountingHelper = new PeriodicAccrualAccountingHelper(requestSpec, responseSpec);
|
this.periodicAccrualAccountingHelper = new PeriodicAccrualAccountingHelper(requestSpec, responseSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void onlyNonInterestBearingLoanCanAcceptChargeAfterMaturity() {
|
|
||||||
final Account assetAccount = this.accountHelper.createAssetAccount();
|
|
||||||
final Account incomeAccount = this.accountHelper.createIncomeAccount();
|
|
||||||
final Account expenseAccount = this.accountHelper.createExpenseAccount();
|
|
||||||
final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
|
|
||||||
|
|
||||||
final Integer loanProductID = createLoanProductWithPeriodicAccrualAccountingWithInterestRecalculationEnabled(assetAccount,
|
|
||||||
incomeAccount, expenseAccount, overpaymentAccount);
|
|
||||||
|
|
||||||
final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec, DATE_OF_JOINING);
|
|
||||||
|
|
||||||
final Integer loanID = applyForLoanApplication(clientID, loanProductID, "1");
|
|
||||||
|
|
||||||
final float PENALTY_PORTION = 100.0f;
|
|
||||||
|
|
||||||
Integer flatSpecifiedDueDate = ChargesHelper.createCharges(requestSpec, responseSpec, ChargesHelper
|
|
||||||
.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, String.valueOf(PENALTY_PORTION), true));
|
|
||||||
|
|
||||||
HashMap<String, Object> loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
|
|
||||||
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
|
|
||||||
|
|
||||||
loanStatusHashMap = this.loanTransactionHelper.approveLoan(EXPECTED_DISBURSAL_DATE, loanID);
|
|
||||||
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
|
|
||||||
LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
|
|
||||||
|
|
||||||
LocalDate targetDate = LocalDate.of(2011, 3, 4);
|
|
||||||
final String loanDisbursementDate = dateFormatter.format(targetDate);
|
|
||||||
|
|
||||||
String loanDetails = this.loanTransactionHelper.getLoanDetails(requestSpec, responseSpec, loanID);
|
|
||||||
loanStatusHashMap = this.loanTransactionHelper.disburseLoanWithNetDisbursalAmount(loanDisbursementDate, loanID,
|
|
||||||
JsonPath.from(loanDetails).get("netDisbursalAmount").toString());
|
|
||||||
LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
|
|
||||||
|
|
||||||
targetDate = LocalDate.of(2011, 4, 5);
|
|
||||||
final String penaltyCharge1AddedDate = dateFormatter.format(targetDate);
|
|
||||||
|
|
||||||
final String ADD_CHARGES_URL = "/fineract-provider/api/v1/loans/" + loanID + "/charges?" + Utils.TENANT_IDENTIFIER;
|
|
||||||
ResponseSpecification response403Spec = new ResponseSpecBuilder().expectStatusCode(403).build();
|
|
||||||
final HashMap response = Utils.performServerPost(requestSpec, response403Spec, ADD_CHARGES_URL,
|
|
||||||
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(flatSpecifiedDueDate), penaltyCharge1AddedDate,
|
|
||||||
String.valueOf(PENALTY_PORTION)),
|
|
||||||
"");
|
|
||||||
assertEquals("validation.msg.domain.rule.violation", response.get("userMessageGlobalisationCode"));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void checkPeriodicAccrualAccountingAPIFlow() {
|
public void checkPeriodicAccrualAccountingAPIFlow() {
|
||||||
final Account assetAccount = this.accountHelper.createAssetAccount();
|
final Account assetAccount = this.accountHelper.createAssetAccount();
|
||||||
@@ -458,20 +411,6 @@ public class LoanSpecificDueDateChargeAfterMaturityTest {
|
|||||||
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
|
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Integer createLoanProductWithPeriodicAccrualAccountingWithInterestRecalculationEnabled(final Account... accounts) {
|
|
||||||
LOG.info("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------");
|
|
||||||
final String loanProductJSON = new LoanProductTestBuilder().withPrincipal("10000.0").withNumberOfRepayments("1")
|
|
||||||
.withinterestRatePerPeriod("1").withInterestRateFrequencyTypeAsYear().withInterestTypeAsDecliningBalance()
|
|
||||||
.withInterestCalculationPeriodTypeAsDays()
|
|
||||||
.withInterestRecalculationDetails(LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE,
|
|
||||||
LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS,
|
|
||||||
LoanProductTestBuilder.INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE)
|
|
||||||
.withInterestRecalculationRestFrequencyDetails(LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_DAILY, "0", null, null)
|
|
||||||
.withInterestRecalculationCompoundingFrequencyDetails(null, null, null, null).withMoratorium("0", "0")
|
|
||||||
.withInterestCalculationPeriodTypeAsRepaymentPeriod(true).withAccountingRulePeriodicAccrual(accounts).build(null);
|
|
||||||
return this.loanTransactionHelper.getLoanProductId(loanProductJSON);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Integer createLoanProductWithPeriodicAccrualAccountingNoInterest(final Account... accounts) {
|
private Integer createLoanProductWithPeriodicAccrualAccountingNoInterest(final Account... accounts) {
|
||||||
LOG.info("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------");
|
LOG.info("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------");
|
||||||
final String loanProductJSON = new LoanProductTestBuilder().withPrincipal(LP_PRINCIPAL.toString()).withRepaymentTypeAsMonth()
|
final String loanProductJSON = new LoanProductTestBuilder().withPrincipal(LP_PRINCIPAL.toString()).withRepaymentTypeAsMonth()
|
||||||
|
|||||||
Reference in New Issue
Block a user