FINERACT-2382: Repayment schedule for Flat-Cumulative-Multi Disbursement
This commit is contained in:
committed by
Adam Saghy
parent
567b12170b
commit
2269d616dc
+1
-1
@@ -494,7 +494,7 @@ public class DataValidatorBuilder {
|
||||
final Integer intValue = Integer.valueOf(this.value.toString());
|
||||
if (!intValue.equals(number)) {
|
||||
String validationErrorCode = "validation.msg." + this.resource + "." + this.parameter + ".not.equal.to.specified.number";
|
||||
String defaultEnglishMessage = "The parameter `" + this.parameter + "` must be same as" + number;
|
||||
String defaultEnglishMessage = "The parameter `" + this.parameter + "` must be same as " + number;
|
||||
final ApiParameterError error = ApiParameterError.parameterError(validationErrorCode, defaultEnglishMessage, this.parameter,
|
||||
intValue, number);
|
||||
this.dataValidationErrors.add(error);
|
||||
|
||||
+2
-2
@@ -1085,7 +1085,7 @@ public final class LoanApplicationTerms {
|
||||
final BigDecimal loanTermFrequencyBigDecimal = calculatePeriodsInLoanTerm();
|
||||
|
||||
return this.annualNominalInterestRate.divide(loanTermPeriodsInYearBigDecimal, mc).divide(divisor, mc)
|
||||
.multiply(loanTermFrequencyBigDecimal);
|
||||
.multiply(loanTermFrequencyBigDecimal, mc);
|
||||
}
|
||||
|
||||
private BigDecimal calculatePeriodsInLoanTerm() {
|
||||
@@ -1237,7 +1237,7 @@ public final class LoanApplicationTerms {
|
||||
}
|
||||
|
||||
if (this.installmentAmountInMultiplesOf != null) {
|
||||
Money roundedPrincipalPerPeriod = Money.roundToMultiplesOf(principalPerPeriod, this.installmentAmountInMultiplesOf);
|
||||
Money roundedPrincipalPerPeriod = Money.roundToMultiplesOf(principalPerPeriod, this.installmentAmountInMultiplesOf, mc);
|
||||
if (interestForThisInstallment != null) {
|
||||
Money roundedInterestForThisInstallment = Money.roundToMultiplesOf(interestForThisInstallment,
|
||||
this.installmentAmountInMultiplesOf);
|
||||
|
||||
+2
-27
@@ -214,8 +214,6 @@ public final class LoanApplicationValidator {
|
||||
expectedFirstRepaymentOnDate);
|
||||
}
|
||||
|
||||
validateCumulativeMultiDisburse(loan);
|
||||
|
||||
validateLoanTermAndRepaidEveryValues(loan.getTermFrequency(), loan.getTermPeriodFrequencyType().getValue(),
|
||||
loan.getLoanProductRelatedDetail().getNumberOfRepayments(), loan.getLoanProductRelatedDetail().getRepayEvery(),
|
||||
loan.getLoanProductRelatedDetail().getRepaymentPeriodFrequencyType().getValue(), loan);
|
||||
@@ -230,8 +228,6 @@ public final class LoanApplicationValidator {
|
||||
expectedFirstRepaymentOnDate);
|
||||
}
|
||||
|
||||
validateCumulativeMultiDisburse(loan);
|
||||
|
||||
validateLoanTermAndRepaidEveryValues(loan.getTermFrequency(), loan.getTermPeriodFrequencyType().getValue(),
|
||||
loan.getLoanProductRelatedDetail().getNumberOfRepayments(), loan.getLoanProductRelatedDetail().getRepayEvery(),
|
||||
loan.getLoanProductRelatedDetail().getRepaymentPeriodFrequencyType().getValue(), loan);
|
||||
@@ -1742,16 +1738,8 @@ public final class LoanApplicationValidator {
|
||||
if (transactionProcessingStrategyCode != null) {
|
||||
final Integer interestType = this.fromApiJsonHelper.extractIntegerNamed(LoanApiConstants.interestTypeParameterName,
|
||||
element, Locale.getDefault());
|
||||
String processorCode = loanRepaymentScheduleTransactionProcessorFactory
|
||||
.determineProcessor(transactionProcessingStrategyCode).getCode();
|
||||
boolean isProgressive = "advanced-payment-allocation-strategy".equals(processorCode);
|
||||
if (isProgressive) {
|
||||
baseDataValidator.reset().parameter(LoanApiConstants.interestTypeParameterName).value(interestType)
|
||||
.ignoreIfNull().inMinMaxRange(0, 1);
|
||||
} else {
|
||||
baseDataValidator.reset().parameter(LoanApiConstants.interestTypeParameterName).value(interestType)
|
||||
.ignoreIfNull().integerSameAsNumber(InterestMethod.DECLINING_BALANCE.getValue());
|
||||
}
|
||||
baseDataValidator.reset().parameter(LoanApiConstants.interestTypeParameterName).value(interestType).ignoreIfNull()
|
||||
.inMinMaxRange(0, 1);
|
||||
}
|
||||
} else {
|
||||
if (loan.isCumulativeSchedule()) {
|
||||
@@ -2208,19 +2196,6 @@ public final class LoanApplicationValidator {
|
||||
}
|
||||
}
|
||||
|
||||
private static void validateCumulativeMultiDisburse(Loan loan) {
|
||||
if (loan.isCumulativeSchedule() && loan.isMultiDisburmentLoan()
|
||||
&& loan.getLoanProductRelatedDetail().getInterestMethod().isFlat()) {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final ApiParameterError error = ApiParameterError.generalError(
|
||||
"validation.msg.loan.cumulative.multidisburse.does.not.support.flat.interest.mode",
|
||||
"Cumulative multidisburse loan does NOT support FLAT interest mode.");
|
||||
dataValidationErrors.add(error);
|
||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||
dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
private Calendar getCalendarInstance(Loan loan) {
|
||||
CalendarInstance calendarInstance = calendarInstanceRepository.findCalendarInstanceByEntityId(loan.getId(),
|
||||
CalendarEntityType.LOANS.getValue());
|
||||
|
||||
+1
-7
@@ -1059,13 +1059,7 @@ public final class LoanProductDataValidator {
|
||||
|
||||
final Integer interestType = this.fromApiJsonHelper.extractIntegerNamed(INTEREST_TYPE, element, Locale.getDefault());
|
||||
|
||||
boolean isProgressive = isProgressive(element, loanProduct);
|
||||
if (isProgressive) {
|
||||
baseDataValidator.reset().parameter(INTEREST_TYPE).value(interestType).ignoreIfNull().inMinMaxRange(0, 1);
|
||||
} else {
|
||||
baseDataValidator.reset().parameter(INTEREST_TYPE).value(interestType).ignoreIfNull()
|
||||
.integerSameAsNumber(InterestMethod.DECLINING_BALANCE.getValue());
|
||||
}
|
||||
baseDataValidator.reset().parameter(INTEREST_TYPE).value(interestType).ignoreIfNull().inMinMaxRange(0, 1);
|
||||
}
|
||||
|
||||
final String overAppliedCalculationType = this.fromApiJsonHelper.extractStringNamed(OVER_APPLIED_CALCULATION_TYPE, element);
|
||||
|
||||
+69
@@ -6251,6 +6251,75 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
|
||||
});
|
||||
}
|
||||
|
||||
// UC158: Repayment schedule handling for flat cumulative multi-disbursement
|
||||
@Test
|
||||
public void uc158() {
|
||||
AtomicLong loanIdRef = new AtomicLong();
|
||||
Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
|
||||
final BigDecimal principalAmount = BigDecimal.valueOf(2000.0);
|
||||
|
||||
runAt("1 January 2024", () -> {
|
||||
// Create a Cumulative Multidisbursal and Flat Interest Type
|
||||
PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(
|
||||
createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct().interestType(InterestType.FLAT).daysInMonthType(30)//
|
||||
.transactionProcessingStrategyCode(LoanProductTestBuilder.DEFAULT_STRATEGY).interestRateFrequencyType(YEARS)
|
||||
.daysInYearType(365).loanScheduleType(LoanScheduleType.CUMULATIVE.toString()).repaymentEvery(1)
|
||||
.installmentAmountInMultiplesOf(null)//
|
||||
.repaymentFrequencyType(2L)//
|
||||
);
|
||||
assertNotNull(loanProductResponse.getResourceId());
|
||||
|
||||
PostLoansRequest applicationRequest = applyLoanRequest(clientId, loanProductResponse.getResourceId(), "1 January 2024",
|
||||
principalAmount.doubleValue(), 3).interestCalculationPeriodType(1).interestType(InterestType.FLAT)//
|
||||
.transactionProcessingStrategyCode(LoanProductTestBuilder.DEFAULT_STRATEGY).interestRateFrequencyType(YEARS)//
|
||||
.interestRatePerPeriod(BigDecimal.valueOf(7.0))//
|
||||
.repaymentEvery(1)//
|
||||
.repaymentFrequencyType(MONTHS)//
|
||||
.loanTermFrequency(3)//
|
||||
.loanTermFrequencyType(MONTHS);
|
||||
PostLoansResponse loanResponse = loanTransactionHelper.applyLoan(applicationRequest);
|
||||
|
||||
loanTransactionHelper.approveLoan(loanResponse.getLoanId(), new PostLoansLoanIdRequest().approvedLoanAmount(principalAmount)
|
||||
.dateFormat(DATETIME_PATTERN).approvedOnDate("1 January 2024").locale("en"));
|
||||
|
||||
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
|
||||
new PostLoansLoanIdRequest().actualDisbursementDate("1 January 2024").dateFormat(DATETIME_PATTERN).locale("en")
|
||||
.transactionAmount(BigDecimal.valueOf(1000.00)));
|
||||
|
||||
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
|
||||
validateLoanSummaryBalances(loanDetails, 1017.50, 0.00, 1000.00, 0.00, null);
|
||||
validatePeriod(loanDetails, 0, LocalDate.of(2024, 1, 1), null, 1000.0, null, null, null, 0.0, 0.0, null, null, null, null, null,
|
||||
null, null, null, null);
|
||||
validatePeriod(loanDetails, 1, LocalDate.of(2024, 2, 1), null, 666.67, 333.33, 0.00, 333.33, 0.0, 0.0, 0.0, 0.00, 0.00, 0.00,
|
||||
5.83, 0.00, 5.83, 0.00, 0.00);
|
||||
validatePeriod(loanDetails, 2, LocalDate.of(2024, 3, 1), null, 333.34, 333.33, 0.00, 333.33, 0.0, 0.0, 0.0, 0.00, 0.00, 0.00,
|
||||
5.83, 0.00, 5.83, 0.00, 0.00);
|
||||
validatePeriod(loanDetails, 3, LocalDate.of(2024, 4, 1), null, 0.00, 333.34, 0.00, 333.34, 0.0, 0.0, 0.00, 0.00, 0.00, 0.00,
|
||||
5.84, 0.00, 5.84, 0.00, 0.00);
|
||||
loanIdRef.set(loanResponse.getLoanId());
|
||||
});
|
||||
|
||||
runAt("15 January 2024", () -> {
|
||||
final Long loanId = loanIdRef.get();
|
||||
|
||||
loanTransactionHelper.disburseLoan(loanId, new PostLoansLoanIdRequest().actualDisbursementDate("15 January 2024")
|
||||
.dateFormat(DATETIME_PATTERN).locale("en").transactionAmount(BigDecimal.valueOf(500.0)));
|
||||
|
||||
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId);
|
||||
validateLoanSummaryBalances(loanDetails, 1526.25, 0.00, 1500.00, 0.00, null);
|
||||
validatePeriod(loanDetails, 0, LocalDate.of(2024, 1, 1), null, 1000.0, null, null, null, 0.0, 0.0, null, null, null, null, null,
|
||||
null, null, null, null);
|
||||
validatePeriod(loanDetails, 1, LocalDate.of(2024, 1, 15), null, 500.0, null, null, null, 0.0, 0.0, null, null, null, null, null,
|
||||
null, null, null, null);
|
||||
validatePeriod(loanDetails, 2, LocalDate.of(2024, 2, 1), null, 1000.00, 500.00, 0.00, 500.00, 0.0, 0.0, 0.0, 0.00, 0.00, 0.00,
|
||||
8.75, 0.00, 8.75, 0.00, 0.00);
|
||||
validatePeriod(loanDetails, 3, LocalDate.of(2024, 3, 1), null, 500.00, 500.00, 0.00, 500.00, 0.0, 0.0, 0.0, 0.00, 0.00, 0.00,
|
||||
8.75, 0.00, 8.75, 0.00, 0.00);
|
||||
validatePeriod(loanDetails, 4, LocalDate.of(2024, 4, 1), null, 0.00, 500.00, 0.00, 500.00, 0.0, 0.0, 0.00, 0.00, 0.00, 0.00,
|
||||
8.75, 0.00, 8.75, 0.00, 0.00);
|
||||
});
|
||||
}
|
||||
|
||||
private Long applyAndApproveLoanProgressiveAdvancedPaymentAllocationStrategyMonthlyRepayments(Long clientId, Long loanProductId,
|
||||
Integer numberOfRepayments, String loanDisbursementDate, double amount) {
|
||||
LOG.info("------------------------------APPLY AND APPROVE LOAN ---------------------------------------");
|
||||
|
||||
Reference in New Issue
Block a user