FINERACT-2181: Installment amount in multiples of should be inherited from loan product to loan level

This commit is contained in:
Jose Alberto Hernandez
2025-06-06 10:54:29 +02:00
committed by Adam Saghy
parent 95a8231b18
commit 39a8d5c63e
16 changed files with 94 additions and 36 deletions
@@ -432,8 +432,6 @@ public class LoanScheduleAssembler {
final BigDecimal principalThresholdForLastInstalment = loanProduct.getPrincipalThresholdForLastInstallment();
final Integer installmentAmountInMultiplesOf = loanProduct.getInstallmentAmountInMultiplesOf();
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
if (loanProduct.isLinkedToFloatingInterestRate()) {
final BigDecimal interestRateDiff = this.fromApiJsonHelper
@@ -538,8 +536,9 @@ public class LoanScheduleAssembler {
loanProduct.isMultiDisburseLoan(), emiAmount, disbursementDatas, maxOutstandingBalance, graceOnArrearsAgeing,
daysInMonthType, daysInYearType, isInterestRecalculationEnabled, recalculationFrequencyType, restCalendarInstance,
compoundingMethod, compoundingCalendarInstance, compoundingFrequencyType, principalThresholdForLastInstalment,
installmentAmountInMultiplesOf, loanProduct.preCloseInterestCalculationStrategy(), calendar, BigDecimal.ZERO,
loanTermVariations, isInterestChargedFromDateSameAsDisbursalDateEnabled, numberOfDays, isSkipMeetingOnFirstDay, detailDTO,
loanProduct.getLoanProductRelatedDetail().getInstallmentAmountInMultiplesOf(),
loanProduct.preCloseInterestCalculationStrategy(), calendar, BigDecimal.ZERO, loanTermVariations,
isInterestChargedFromDateSameAsDisbursalDateEnabled, numberOfDays, isSkipMeetingOnFirstDay, detailDTO,
allowCompoundingOnEod, isEqualAmortization, isInterestToBeRecoveredFirstWhenGreaterThanEMI,
fixedPrincipalPercentagePerInstallment, isPrincipalCompoundingDisabledForOverdueLoans, isDownPaymentEnabled,
disbursedAmountPercentageForDownPayment, isAutoRepaymentForDownPaymentEnabled, repaymentStartDateType, submittedOnDate,
@@ -673,8 +672,8 @@ public class LoanScheduleAssembler {
}
}
public LoanProductRelatedDetail assembleLoanProductRelatedDetail(final JsonElement element, final LoanProduct loanProduct) {
final LoanApplicationTerms loanApplicationTerms = assembleLoanApplicationTermsFrom(element, loanProduct);
public LoanProductRelatedDetail assembleLoanProductRelatedDetail(final LoanApplicationTerms loanApplicationTerms,
final JsonElement element) {
LoanProductRelatedDetail loanProductRelatedDetail = loanApplicationTerms.toLoanProductRelatedDetail();
final String interestRateFrequencyTypeParamName = "interestRateFrequencyType";
if (this.fromApiJsonHelper.parameterExists(interestRateFrequencyTypeParamName, element)) {
@@ -684,6 +683,10 @@ public class LoanScheduleAssembler {
return loanProductRelatedDetail;
}
public LoanProductRelatedDetail assembleLoanProductRelatedDetail(final JsonElement element, final LoanProduct loanProduct) {
return assembleLoanProductRelatedDetail(assembleLoanApplicationTermsFrom(element, loanProduct), element);
}
public LoanScheduleModel assembleLoanScheduleFrom(final JsonElement element) {
// This method is getting called from calculate loan schedule.
final LoanApplicationTerms loanApplicationTerms = assembleLoanTerms(element);
@@ -221,8 +221,9 @@ public class LoanAssemblerImpl implements LoanAssembler {
// Here we add Rates to LoanApplication
final List<Rate> rates = this.rateAssembler.fromParsedJson(element);
final LoanProductRelatedDetail loanProductRelatedDetail = this.loanScheduleAssembler.assembleLoanProductRelatedDetail(element,
loanProduct);
final LoanApplicationTerms loanApplicationTerms = this.loanScheduleAssembler.assembleLoanTerms(element);
final LoanProductRelatedDetail loanProductRelatedDetail = this.loanScheduleAssembler
.assembleLoanProductRelatedDetail(loanApplicationTerms, element);
final BigDecimal interestRateDifferential = this.fromApiJsonHelper
.extractBigDecimalWithLocaleNamed(LoanApiConstants.interestRateDifferentialParameterName, element);
@@ -247,7 +248,6 @@ public class LoanAssemblerImpl implements LoanAssembler {
isEnableInstallmentLevelDelinquency = loanProduct.isEnableInstallmentLevelDelinquency();
}
final LoanApplicationTerms loanApplicationTerms = this.loanScheduleAssembler.assembleLoanTerms(element);
final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled();
Long officeId = client != null ? client.getOffice().getId() : group.getOffice().getId();
final List<Holiday> holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(officeId,
@@ -410,11 +410,11 @@ public class LoanProductUpdateUtil {
}
if (command.isChangeInIntegerParameterNamedWithNullCheck(LoanProductConstants.installmentAmountInMultiplesOfParamName,
loanProduct.getInstallmentAmountInMultiplesOf())) {
loanProduct.getLoanProductRelatedDetail().getInstallmentAmountInMultiplesOf())) {
final Integer newValue = command.integerValueOfParameterNamed(LoanProductConstants.installmentAmountInMultiplesOfParamName);
actualChanges.put(LoanProductConstants.installmentAmountInMultiplesOfParamName, newValue);
actualChanges.put("locale", localeAsInput);
loanProduct.setInstallmentAmountInMultiplesOf(newValue);
loanProduct.getLoanProductRelatedDetail().setInstallmentAmountInMultiplesOf(newValue);
}
if (command.isChangeInBooleanParameterNamed(LoanProductConstants.CAN_USE_FOR_TOPUP, loanProduct.isCanUseForTopup())) {
@@ -444,9 +444,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
.getDisbursedAmountPercentageForDownPayment();
Money downPaymentMoney = Money.of(loan.getCurrency(),
MathUtil.percentageOf(amountToDisburse.getAmount(), disbursedAmountPercentageForDownPayment, 19));
if (loan.getLoanProduct().getInstallmentAmountInMultiplesOf() != null) {
if (loan.getLoanProductRelatedDetail().getInstallmentAmountInMultiplesOf() != null) {
downPaymentMoney = Money.roundToMultiplesOf(downPaymentMoney,
loan.getLoanProduct().getInstallmentAmountInMultiplesOf());
loan.getLoanProductRelatedDetail().getInstallmentAmountInMultiplesOf());
}
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(actualDisbursementDate,
downPaymentMoney.getAmount(), PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN,
@@ -254,7 +254,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
+ "lp.allow_multiple_disbursals as multiDisburseLoan, lp.max_disbursals as maxTrancheCount, lp.max_outstanding_loan_balance as outstandingLoanBalance, "
+ "lp.disallow_expected_disbursements as disallowExpectedDisbursements, lp.allow_approved_disbursed_amounts_over_applied as allowApprovedDisbursedAmountsOverApplied, lp.over_applied_calculation_type as overAppliedCalculationType, over_applied_number as overAppliedNumber, "
+ "lp.days_in_month_enum as daysInMonth, lp.days_in_year_enum as daysInYear, lp.interest_recalculation_enabled as isInterestRecalculationEnabled, "
+ "lp.can_define_fixed_emi_amount as canDefineInstallmentAmount, lp.instalment_amount_in_multiples_of as installmentAmountInMultiplesOf, "
+ "lp.can_define_fixed_emi_amount as canDefineInstallmentAmount, lp.installment_amount_in_multiples_of as installmentAmountInMultiplesOf, "
+ "lp.due_days_for_repayment_event as dueDaysForRepaymentEvent, lp.overdue_days_for_repayment_event as overDueDaysForRepaymentEvent, lp.enable_down_payment as enableDownPayment, lp.disbursed_amount_percentage_for_down_payment as disbursedAmountPercentageForDownPayment, lp.enable_auto_repayment_for_down_payment as enableAutoRepaymentForDownPayment, lp.repayment_start_date_type_enum as repaymentStartDateType, "
+ "lp.enable_installment_level_delinquency as enableInstallmentLevelDelinquency, "
+ "lpr.pre_close_interest_calculation_strategy as preCloseInterestCalculationStrategy, "
@@ -160,6 +160,7 @@ public class LoanDownPaymentHandlerServiceImplTest {
when(downPaymentMoney.getCurrencyCode()).thenReturn(loanCurrency.getCode());
when(overPaymentPortionMoney.getCurrencyCode()).thenReturn(loanCurrency.getCode());
when(loanRepaymentRelatedDetail.getInstallmentAmountInMultiplesOf()).thenReturn(10);
when(loanForProcessing.getLoanRepaymentScheduleDetail()).thenReturn(loanRepaymentRelatedDetail);
when(loanForProcessing.repaymentScheduleDetail()).thenReturn(loanRepaymentRelatedDetail);
when(loanRepaymentRelatedDetail.isInterestRecalculationEnabled()).thenReturn(true);
@@ -168,7 +169,6 @@ public class LoanDownPaymentHandlerServiceImplTest {
when(loanForProcessing.getCurrency()).thenReturn(loanCurrency);
when(loanForProcessing.loanCurrency()).thenReturn(loanCurrency);
when(loanForProcessing.getLoanProduct()).thenReturn(loanProduct);
when(loanProduct.getInstallmentAmountInMultiplesOf()).thenReturn(10);
when(loanForProcessing.getLoanProductRelatedDetail()).thenReturn(loanProductRelatedDetail);
when(loanTransactionProcessingService.reprocessLoanTransactions(any(), any(), any(), any(), any(), any()))
.thenReturn(changedTransactionDetail);