FINERACT-1958-Configuration-down-payment

This commit is contained in:
Ruchi Dhamankar
2023-08-07 15:27:00 +02:00
committed by Adam Saghy
parent 7559e90ce2
commit 315f62d8dc
19 changed files with 573 additions and 27 deletions
@@ -207,6 +207,8 @@ public final class LoanApplicationTerms {
private final BigDecimal fixedPrincipalPercentagePerInstallment;
private LocalDate newScheduledDueDateStart;
private boolean isDownPaymentEnabled;
private BigDecimal disbursedAmountPercentageForDownPayment;
public static LoanApplicationTerms assembleFrom(final ApplicationCurrency currency, final Integer loanTermFrequency,
final PeriodFrequencyType loanTermPeriodFrequencyType, final Integer numberOfRepayments, final Integer repaymentEvery,
@@ -230,7 +232,8 @@ public final class LoanApplicationTerms {
Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled, final Integer numberOfDays,
boolean isSkipRepaymentOnFirstDayOfMonth, final HolidayDetailDTO holidayDetailDTO, final boolean allowCompoundingOnEod,
final boolean isEqualAmortization, final boolean isInterestToBeRecoveredFirstWhenGreaterThanEMI,
final BigDecimal fixedPrincipalPercentagePerInstallment, final boolean isPrincipalCompoundingDisabledForOverdueLoans) {
final BigDecimal fixedPrincipalPercentagePerInstallment, final boolean isPrincipalCompoundingDisabledForOverdueLoans,
final Boolean enableDownPayment, final BigDecimal disbursedAmountPercentageForDownPayment) {
final LoanRescheduleStrategyMethod rescheduleStrategyMethod = null;
final CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
@@ -247,7 +250,7 @@ public final class LoanApplicationTerms {
calendarHistoryDataWrapper, isInterestChargedFromDateSameAsDisbursalDateEnabled, numberOfDays,
isSkipRepaymentOnFirstDayOfMonth, holidayDetailDTO, allowCompoundingOnEod, isEqualAmortization, false,
isInterestToBeRecoveredFirstWhenGreaterThanEMI, fixedPrincipalPercentagePerInstallment,
isPrincipalCompoundingDisabledForOverdueLoans);
isPrincipalCompoundingDisabledForOverdueLoans, enableDownPayment, disbursedAmountPercentageForDownPayment);
}
@@ -293,6 +296,11 @@ public final class LoanApplicationTerms {
final boolean isInterestRecalculationEnabled = loanProductRelatedDetail.isInterestRecalculationEnabled();
final boolean isInterestChargedFromDateSameAsDisbursalDateEnabled = false;
final boolean isEqualAmortization = loanProductRelatedDetail.isEqualAmortization();
final boolean isDownPaymentEnabled = loanProductRelatedDetail.isEnableDownPayment();
BigDecimal disbursedAmountPercentageForDownPayment = null;
if (isDownPaymentEnabled) {
disbursedAmountPercentageForDownPayment = loanProductRelatedDetail.getDisbursedAmountPercentageForDownPayment();
}
return new LoanApplicationTerms(applicationCurrency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments,
repaymentEvery, repaymentPeriodFrequencyType, ((nthDay != null) ? nthDay.getValue() : null), dayOfWeek, amortizationMethod,
interestMethod, interestRatePerPeriod, interestRatePeriodFrequencyType, annualNominalInterestRate,
@@ -307,7 +315,7 @@ public final class LoanApplicationTerms {
isInterestChargedFromDateSameAsDisbursalDateEnabled, numberOfDays, isSkipRepaymentOnFirstDayOfMonth, holidayDetailDTO,
allowCompoundingOnEod, isEqualAmortization, isFirstRepaymentDateAllowedOnHoliday,
isInterestToBeRecoveredFirstWhenGreaterThanEMI, fixedPrincipalPercentagePerInstallment,
isPrincipalCompoundingDisabledForOverdueLoans);
isPrincipalCompoundingDisabledForOverdueLoans, isDownPaymentEnabled, disbursedAmountPercentageForDownPayment);
}
private LoanApplicationTerms(final ApplicationCurrency currency, final Integer loanTermFrequency,
@@ -333,7 +341,8 @@ public final class LoanApplicationTerms {
final Integer numberOfDays, final boolean isSkipRepaymentOnFirstDayOfMonth, final HolidayDetailDTO holidayDetailDTO,
final boolean allowCompoundingOnEod, final boolean isEqualAmortization, final boolean isFirstRepaymentDateAllowedOnHoliday,
final boolean isInterestToBeRecoveredFirstWhenGreaterThanEMI, final BigDecimal fixedPrincipalPercentagePerInstallment,
final boolean isPrincipalCompoundingDisabledForOverdueLoans) {
final boolean isPrincipalCompoundingDisabledForOverdueLoans, final boolean isDownPaymentEnabled,
final BigDecimal disbursedAmountPercentageForDownPayment) {
this.currency = currency;
this.loanTermFrequency = loanTermFrequency;
@@ -410,6 +419,8 @@ public final class LoanApplicationTerms {
this.isInterestToBeRecoveredFirstWhenGreaterThanEMI = isInterestToBeRecoveredFirstWhenGreaterThanEMI;
this.fixedPrincipalPercentagePerInstallment = fixedPrincipalPercentagePerInstallment;
this.isPrincipalCompoundingDisabledForOverdueLoans = isPrincipalCompoundingDisabledForOverdueLoans;
this.isDownPaymentEnabled = isDownPaymentEnabled;
this.disbursedAmountPercentageForDownPayment = disbursedAmountPercentageForDownPayment;
}
public Money adjustPrincipalIfLastRepaymentPeriod(final Money principalForPeriod, final Money totalCumulativePrincipalToDate,
@@ -1253,7 +1264,8 @@ public final class LoanApplicationTerms {
this.repaymentPeriodFrequencyType, this.numberOfRepayments, this.principalGrace, this.recurringMoratoriumOnPrincipalPeriods,
this.interestPaymentGrace, this.interestChargingGrace, this.amortizationMethod, this.inArrearsTolerance.getAmount(),
this.graceOnArrearsAgeing, this.daysInMonthType.getValue(), this.daysInYearType.getValue(),
this.interestRecalculationEnabled, this.isEqualAmortization);
this.interestRecalculationEnabled, this.isEqualAmortization, this.isDownPaymentEnabled,
this.disbursedAmountPercentageForDownPayment);
}
public Integer getLoanTermFrequency() {
@@ -147,4 +147,8 @@ public interface LoanProductConstants {
String DUE_DAYS_FOR_REPAYMENT_EVENT = "dueDaysForRepaymentEvent";
String OVER_DUE_DAYS_FOR_REPAYMENT_EVENT = "overDueDaysForRepaymentEvent";
// down-payment related
String ENABLE_DOWN_PAYMENT = "enableDownPayment";
String DISBURSED_AMOUNT_PERCENTAGE_DOWN_PAYMENT = "disbursedAmountPercentageForDownPayment";
}
@@ -385,6 +385,10 @@ public class LoanProduct extends AbstractPersistableCustom {
final Integer overDueDaysForRepaymentEvent = command
.integerValueOfParameterNamed(LoanProductConstants.OVER_DUE_DAYS_FOR_REPAYMENT_EVENT);
final boolean enableDownPayment = command.booleanPrimitiveValueOfParameterNamed(LoanProductConstants.ENABLE_DOWN_PAYMENT);
final BigDecimal disbursedAmountPercentageDownPayment = command
.bigDecimalValueOfParameterNamed(LoanProductConstants.DISBURSED_AMOUNT_PERCENTAGE_DOWN_PAYMENT);
return new LoanProduct(fund, loanTransactionProcessingStrategy, name, shortName, description, currency, principal, minPrincipal,
maxPrincipal, interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod, interestFrequencyType,
annualInterestRate, interestMethod, interestCalculationPeriodMethod, allowPartialPeriodInterestCalcualtion, repaymentEvery,
@@ -401,7 +405,7 @@ public class LoanProduct extends AbstractPersistableCustom {
minimumGapBetweenInstallments, maximumGapBetweenInstallments, syncExpectedWithDisbursementDate, canUseForTopup,
isEqualAmortization, productRates, fixedPrincipalPercentagePerInstallment, disallowExpectedDisbursements,
allowApprovedDisbursedAmountsOverApplied, overAppliedCalculationType, overAppliedNumber, dueDaysForRepaymentEvent,
overDueDaysForRepaymentEvent);
overDueDaysForRepaymentEvent, enableDownPayment, disbursedAmountPercentageDownPayment);
}
@@ -612,7 +616,8 @@ public class LoanProduct extends AbstractPersistableCustom {
final boolean syncExpectedWithDisbursementDate, final boolean canUseForTopup, final boolean isEqualAmortization,
final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment, final boolean disallowExpectedDisbursements,
final boolean allowApprovedDisbursedAmountsOverApplied, final String overAppliedCalculationType,
final Integer overAppliedNumber, final Integer dueDaysForRepaymentEvent, final Integer overDueDaysForRepaymentEvent) {
final Integer overAppliedNumber, final Integer dueDaysForRepaymentEvent, final Integer overDueDaysForRepaymentEvent,
final boolean enableDownPayment, final BigDecimal disbursedAmountPercentageForDownPayment) {
this.fund = fund;
this.transactionProcessingStrategyCode = transactionProcessingStrategyCode;
this.name = name.trim();
@@ -645,7 +650,7 @@ public class LoanProduct extends AbstractPersistableCustom {
considerPartialPeriodInterest, repayEvery, repaymentFrequencyType, defaultNumberOfInstallments, graceOnPrincipalPayment,
recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, graceOnInterestCharged, amortizationMethod,
inArrearsTolerance, graceOnArrearsAgeing, daysInMonthType.getValue(), daysInYearType.getValue(),
isInterestRecalculationEnabled, isEqualAmortization);
isInterestRecalculationEnabled, isEqualAmortization, enableDownPayment, disbursedAmountPercentageForDownPayment);
this.loanProductRelatedDetail.validateRepaymentPeriodWithGraceSettings();
@@ -1216,6 +1221,20 @@ public class LoanProduct extends AbstractPersistableCustom {
this.overDueDaysForRepaymentEvent = newValue;
}
if (command.isChangeInBooleanParameterNamed(LoanProductConstants.ENABLE_DOWN_PAYMENT,
this.loanProductRelatedDetail.isEnableDownPayment())) {
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(LoanProductConstants.ENABLE_DOWN_PAYMENT);
actualChanges.put(LoanProductConstants.ENABLE_DOWN_PAYMENT, newValue);
this.loanProductRelatedDetail.updateEnableDownPayment(newValue);
}
if (command.isChangeInBigDecimalParameterNamed(LoanProductConstants.DISBURSED_AMOUNT_PERCENTAGE_DOWN_PAYMENT,
this.loanProductRelatedDetail.getDisbursedAmountPercentageForDownPayment())) {
BigDecimal newValue = command.bigDecimalValueOfParameterNamed(LoanProductConstants.DISBURSED_AMOUNT_PERCENTAGE_DOWN_PAYMENT);
actualChanges.put(LoanProductConstants.DISBURSED_AMOUNT_PERCENTAGE_DOWN_PAYMENT, newValue);
this.loanProductRelatedDetail.updateDisbursedAmountPercentageForDownPayment(newValue);
}
return actualChanges;
}
@@ -129,6 +129,12 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
@Column(name = "is_equal_amortization", nullable = false)
private boolean isEqualAmortization = false;
@Column(name = "enable_down_payment", nullable = false)
private boolean enableDownPayment;
@Column(name = "disbursed_amount_percentage_for_down_payment", scale = 6, precision = 9)
private BigDecimal disbursedAmountPercentageForDownPayment;
public static LoanProductRelatedDetail createFrom(final MonetaryCurrency currency, final BigDecimal principal,
final BigDecimal nominalInterestRatePerPeriod, final PeriodFrequencyType interestRatePeriodFrequencyType,
final BigDecimal nominalAnnualInterestRate, final InterestMethod interestMethod,
@@ -137,14 +143,15 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
final Integer graceOnPrincipalPayment, final Integer recurringMoratoriumOnPrincipalPeriods,
final Integer graceOnInterestPayment, final Integer graceOnInterestCharged, final AmortizationMethod amortizationMethod,
final BigDecimal inArrearsTolerance, final Integer graceOnArrearsAgeing, final Integer daysInMonthType,
final Integer daysInYearType, final boolean isInterestRecalculationEnabled, final boolean isEqualAmortization) {
final Integer daysInYearType, final boolean isInterestRecalculationEnabled, final boolean isEqualAmortization,
final boolean enableDownPayment, final BigDecimal disbursedAmountPercentageForDownPayment) {
return new LoanProductRelatedDetail(currency, principal, nominalInterestRatePerPeriod, interestRatePeriodFrequencyType,
nominalAnnualInterestRate, interestMethod, interestCalculationPeriodMethod, allowPartialPeriodInterestCalcualtion,
repaymentEvery, repaymentPeriodFrequencyType, numberOfRepayments, graceOnPrincipalPayment,
recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, graceOnInterestCharged, amortizationMethod,
inArrearsTolerance, graceOnArrearsAgeing, daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
isEqualAmortization);
isEqualAmortization, enableDownPayment, disbursedAmountPercentageForDownPayment);
}
protected LoanProductRelatedDetail() {
@@ -159,7 +166,8 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
final Integer graceOnPrincipalPayment, final Integer recurringMoratoriumOnPrincipalPeriods,
final Integer graceOnInterestPayment, final Integer graceOnInterestCharged, final AmortizationMethod amortizationMethod,
final BigDecimal inArrearsTolerance, final Integer graceOnArrearsAgeing, final Integer daysInMonthType,
final Integer daysInYearType, final boolean isInterestRecalculationEnabled, final boolean isEqualAmortization) {
final Integer daysInYearType, final boolean isInterestRecalculationEnabled, final boolean isEqualAmortization,
final boolean enableDownPayment, final BigDecimal disbursedAmountPercentageForDownPayment) {
this.currency = currency;
this.principal = defaultPrincipal;
this.nominalInterestRatePerPeriod = defaultNominalInterestRatePerPeriod;
@@ -186,6 +194,8 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
this.daysInYearType = daysInYearType;
this.isInterestRecalculationEnabled = isInterestRecalculationEnabled;
this.isEqualAmortization = isEqualAmortization;
this.enableDownPayment = enableDownPayment;
this.disbursedAmountPercentageForDownPayment = disbursedAmountPercentageForDownPayment;
}
private Integer defaultToNullIfZero(final Integer value) {
@@ -675,4 +685,20 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
public void setNominalInterestRatePerPeriod(BigDecimal nominalInterestRatePerPeriod) {
this.nominalInterestRatePerPeriod = nominalInterestRatePerPeriod;
}
public boolean isEnableDownPayment() {
return enableDownPayment;
}
public BigDecimal getDisbursedAmountPercentageForDownPayment() {
return disbursedAmountPercentageForDownPayment;
}
public void updateEnableDownPayment(boolean enableDownPayment) {
this.enableDownPayment = enableDownPayment;
}
public void updateDisbursedAmountPercentageForDownPayment(BigDecimal disbursedAmountPercentageForDownPayment) {
this.disbursedAmountPercentageForDownPayment = disbursedAmountPercentageForDownPayment;
}
}