Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ public static final class PostCreateRescheduleLoansRequest {
public Long rescheduleReasonId;
@Schema(example = "20 September 2011")
public String submittedOnDate;
@Schema(example = "20 September 2011")
public String endDate;
@Schema(example = "100.00")
public BigDecimal emi;
}

@Schema(description = "PostUpdateRescheduleLoansRequest")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,24 @@ public static void validateEMIAndEndDate(FromJsonHelper fromJsonHelper, Loan loa
DataValidatorBuilder dataValidatorBuilder) {
final LocalDate endDate = fromJsonHelper.extractLocalDateNamed(RescheduleLoansApiConstants.endDateParamName, jsonElement);
final BigDecimal emi = fromJsonHelper.extractBigDecimalWithLocaleNamed(RescheduleLoansApiConstants.emiParamName, jsonElement);
final Integer extraTerms = fromJsonHelper.extractIntegerWithLocaleNamed(RescheduleLoansApiConstants.extraTermsParamName,
jsonElement);
if (emi != null || endDate != null) {
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.endDateParamName).value(endDate).notNull();
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.emiParamName).value(emi).notNull().positiveAmount();

if (endDate != null) {
LoanRepaymentScheduleInstallment endInstallment = loan.fetchLoanRepaymentScheduleInstallmentByDueDate(endDate);

if (endInstallment == null) {
if (endInstallment == null && (extraTerms == null || extraTerms == 0)) {
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.endDateParamName)
.failWithCode("repayment.schedule.installment.does.not.exist", "Repayment schedule installment does not exist");
} else if (endInstallment == null && extraTerms != null && extraTerms > 0) {
LocalDate lastDueDate = loan.getLastLoanRepaymentScheduleInstallment().getDueDate();
if (!DateUtils.isAfter(endDate, lastDueDate)) {
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.endDateParamName).failWithCode(
"repayment.schedule.installment.does.not.exist", "Repayment schedule installment does not exist");
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,17 +249,19 @@ private void createLoanTermVariationsForRegularLoans(final Loan loan, final Inte
final boolean isSpecificToInstallment, BigDecimal decimalValue, LocalDate dueDate, LocalDate endDate, BigDecimal emi) {

if (rescheduleFromDate != null && endDate != null && emi != null) {
LoanTermVariations parent = null;
final Integer termType = LoanTermVariationType.EMI_AMOUNT.getValue();
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
for (LoanRepaymentScheduleInstallment installment : installments) {
if (!DateUtils.isBefore(installment.getDueDate(), rescheduleFromDate)
&& !DateUtils.isAfter(installment.getDueDate(), endDate)) {
createLoanTermVariations(loanRescheduleRequest, termType, loan, installment.getDueDate(), installment.getDueDate(),
loanRescheduleRequestToTermVariationMappings, isActive, true, emi, parent);
}
if (DateUtils.isAfter(installment.getDueDate(), endDate)) {
break;

LoanTermVariations parent = createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate,
rescheduleFromDate, loanRescheduleRequestToTermVariationMappings, isActive, false, emi, null);

LoanRepaymentScheduleInstallment revertInstallment = loan.getRepaymentScheduleInstallments().stream()
.filter(i -> DateUtils.isAfter(i.getDueDate(), endDate)).findFirst().orElse(null);
if (revertInstallment != null) {
BigDecimal originalEmi = loan.retriveLastEmiAmount();
if (originalEmi != null) {
createLoanTermVariations(loanRescheduleRequest, termType, loan, revertInstallment.getDueDate(),
revertInstallment.getDueDate(), loanRescheduleRequestToTermVariationMappings, isActive, false, originalEmi,
parent);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,33 @@ public void testLoanTermVariationDeserializesProperly() {
});
}

@Test
public void testCreateLoanRescheduleChangeEMIWithExtraTerms() {
PostClientsResponse client = clientHelper.createClient(ClientHelper.defaultClientCreationRequest());
Long commonLoanProductId = createLoanProductPeriodicWithInterest();

AtomicReference<Long> loanIdRef = new AtomicReference<>();
runAt("01 March 2024", () -> {
Long loanId = applyForLoanApplicationWithInterest(client.getClientId(), commonLoanProductId, BigDecimal.valueOf(4000),
"1 March 2023", "1 March 2024");
loanIdRef.set(loanId);
loanTransactionHelper.approveLoan("1 March 2024", loanId.intValue());

loanTransactionHelper.disburseLoan("1 March 2024", loanId.intValue(), "4000", null);

PostCreateRescheduleLoansResponse rescheduleLoansResponse = loanRescheduleRequestHelper
.createLoanRescheduleRequest(new PostCreateRescheduleLoansRequest().loanId(loanIdRef.get()).dateFormat(DATETIME_PATTERN)
.locale("en").submittedOnDate("1 March 2024").rescheduleReasonId(1L).rescheduleFromDate("1 April 2024")
.emi(BigDecimal.valueOf(500)).endDate("1 May 2024").extraTerms(2));

GetLoanRescheduleRequestResponse getLoanRescheduleRequestResponse = Assertions.assertDoesNotThrow(
() -> loanRescheduleRequestHelper.readLoanRescheduleRequest(rescheduleLoansResponse.getResourceId(), null));
Assertions.assertNotNull(getLoanRescheduleRequestResponse);

approveLoanReschedule(rescheduleLoansResponse.getResourceId(), "1 March 2024");
});
}

private Integer createProgressiveLoanProduct() {
AdvancedPaymentData defaultAllocation = createDefaultPaymentAllocation("NEXT_INSTALLMENT");
final String loanProductJSON = new LoanProductTestBuilder().withNumberOfRepayments(numberOfRepayments)
Expand Down