FINERACT-2114: Interest rate modification, adjust reschedule validation
This commit is contained in:
committed by
Adam Saghy
parent
2a445a5862
commit
3e923bf483
+4
@@ -262,6 +262,10 @@ public final class JsonCommand {
|
|||||||
return parameterExists(parameterName);
|
return parameterExists(parameterName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasParameterValue(final String parameterName) {
|
||||||
|
return this.fromApiJsonHelper.parameterHasValue(parameterName, this.parsedCommand);
|
||||||
|
}
|
||||||
|
|
||||||
public String dateFormat() {
|
public String dateFormat() {
|
||||||
return stringValueOfParameterNamed("dateFormat");
|
return stringValueOfParameterNamed("dateFormat");
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -157,6 +157,13 @@ public class FromJsonHelper {
|
|||||||
return this.helperDelegator.parameterExists(parameterName, element);
|
return this.helperDelegator.parameterExists(parameterName, element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check Parameter has a non-blank value
|
||||||
|
*/
|
||||||
|
public boolean parameterHasValue(final String parameterName, final JsonElement element) {
|
||||||
|
return this.helperDelegator.parameterHasValue(parameterName, element);
|
||||||
|
}
|
||||||
|
|
||||||
public String extractStringNamed(final String parameterName, final JsonElement element) {
|
public String extractStringNamed(final String parameterName, final JsonElement element) {
|
||||||
return this.helperDelegator.extractStringNamed(parameterName, element, new HashSet<String>());
|
return this.helperDelegator.extractStringNamed(parameterName, element, new HashSet<String>());
|
||||||
}
|
}
|
||||||
|
|||||||
+21
@@ -61,6 +61,27 @@ public class JsonParserHelper {
|
|||||||
return element.getAsJsonObject().has(parameterName);
|
return element.getAsJsonObject().has(parameterName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check Parameter has a non-blank value
|
||||||
|
*/
|
||||||
|
public boolean parameterHasValue(final String parameterName, final JsonElement element) {
|
||||||
|
if (element == null || !element.isJsonObject()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var valueObject = element.getAsJsonObject().get(parameterName);
|
||||||
|
if (valueObject == null || valueObject.isJsonNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (valueObject instanceof JsonArray) {
|
||||||
|
return !valueObject.getAsJsonArray().isEmpty();
|
||||||
|
}
|
||||||
|
if (valueObject instanceof JsonObject) {
|
||||||
|
return !valueObject.getAsJsonObject().isEmpty();
|
||||||
|
}
|
||||||
|
return valueObject.isJsonPrimitive() && !valueObject.getAsJsonPrimitive().getAsString().isBlank();
|
||||||
|
}
|
||||||
|
|
||||||
public Boolean extractBooleanNamed(final String parameterName, final JsonElement element, final Set<String> requestParamatersDetected) {
|
public Boolean extractBooleanNamed(final String parameterName, final JsonElement element, final Set<String> requestParamatersDetected) {
|
||||||
Boolean value = null;
|
Boolean value = null;
|
||||||
if (element.isJsonObject()) {
|
if (element.isJsonObject()) {
|
||||||
|
|||||||
+95
@@ -0,0 +1,95 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.infrastructure.core.serialization;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class JsonParserHelperTest {
|
||||||
|
|
||||||
|
static final JsonParserHelper onTestUnit = new JsonParserHelper();
|
||||||
|
|
||||||
|
static final String testDataHasValues = "{\n" + " \"integerNumber\": 10,\n" + " \"doubleNumber\": 3.14,\n"
|
||||||
|
+ " \"string\": \"example\",\n" + " \"arrayList\": [1, \"two\", 3.0],\n" + " \"localDate\": \"2024-08-10\",\n"
|
||||||
|
+ " \"keyValue\": {\n" + " \"key\": \"sampleKey\",\n" + " \"value\": \"sampleValue\"\n" + " }\n" + "}";
|
||||||
|
|
||||||
|
static final String testDataValuesEmpty = "{\n" + " \"integerNumber\": null,\n" + " \"doubleNumber\": 0.0,\n"
|
||||||
|
+ " \"string\": \"\",\n" + " \"arrayList\": [],\n" + " \"localDate\": null,\n" + " \"keyValue\": {\n"
|
||||||
|
+ " \"key\": \"\",\n" + " \"value\": null\n" + " }\n" + "}";
|
||||||
|
|
||||||
|
static final String testDataValuesMissing = "{}";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parameterExists() {
|
||||||
|
JsonElement jsonHasValues = JsonParser.parseString(testDataHasValues);
|
||||||
|
JsonElement jsonValuesEmpty = JsonParser.parseString(testDataValuesEmpty);
|
||||||
|
JsonElement jsonValuesMissing = JsonParser.parseString(testDataValuesMissing);
|
||||||
|
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterExists("integerNumber", jsonHasValues));
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterExists("doubleNumber", jsonHasValues));
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterExists("string", jsonHasValues));
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterExists("arrayList", jsonHasValues));
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterExists("localDate", jsonHasValues));
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterExists("keyValue", jsonHasValues));
|
||||||
|
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterExists("integerNumber", jsonValuesEmpty));
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterExists("doubleNumber", jsonValuesEmpty));
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterExists("string", jsonValuesEmpty));
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterExists("arrayList", jsonValuesEmpty));
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterExists("localDate", jsonValuesEmpty));
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterExists("keyValue", jsonValuesEmpty));
|
||||||
|
|
||||||
|
Assertions.assertFalse(onTestUnit.parameterExists("integerNumber", jsonValuesMissing));
|
||||||
|
Assertions.assertFalse(onTestUnit.parameterExists("doubleNumber", jsonValuesMissing));
|
||||||
|
Assertions.assertFalse(onTestUnit.parameterExists("string", jsonValuesMissing));
|
||||||
|
Assertions.assertFalse(onTestUnit.parameterExists("arrayList", jsonValuesMissing));
|
||||||
|
Assertions.assertFalse(onTestUnit.parameterExists("localDate", jsonValuesMissing));
|
||||||
|
Assertions.assertFalse(onTestUnit.parameterExists("keyValue", jsonValuesMissing));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parameterHasValue() {
|
||||||
|
JsonElement jsonHasValues = JsonParser.parseString(testDataHasValues);
|
||||||
|
JsonElement jsonValuesEmpty = JsonParser.parseString(testDataValuesEmpty);
|
||||||
|
JsonElement jsonValuesMissing = JsonParser.parseString(testDataValuesMissing);
|
||||||
|
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterHasValue("integerNumber", jsonHasValues));
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterHasValue("doubleNumber", jsonHasValues));
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterHasValue("string", jsonHasValues));
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterHasValue("arrayList", jsonHasValues));
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterHasValue("localDate", jsonHasValues));
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterHasValue("keyValue", jsonHasValues));
|
||||||
|
|
||||||
|
Assertions.assertFalse(onTestUnit.parameterHasValue("integerNumber", jsonValuesEmpty));
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterHasValue("doubleNumber", jsonValuesEmpty));
|
||||||
|
Assertions.assertFalse(onTestUnit.parameterHasValue("string", jsonValuesEmpty));
|
||||||
|
Assertions.assertFalse(onTestUnit.parameterHasValue("arrayList", jsonValuesEmpty));
|
||||||
|
Assertions.assertFalse(onTestUnit.parameterHasValue("localDate", jsonValuesEmpty));
|
||||||
|
Assertions.assertTrue(onTestUnit.parameterHasValue("keyValue", jsonValuesEmpty));
|
||||||
|
|
||||||
|
Assertions.assertFalse(onTestUnit.parameterHasValue("integerNumber", jsonValuesMissing));
|
||||||
|
Assertions.assertFalse(onTestUnit.parameterHasValue("doubleNumber", jsonValuesMissing));
|
||||||
|
Assertions.assertFalse(onTestUnit.parameterHasValue("string", jsonValuesMissing));
|
||||||
|
Assertions.assertFalse(onTestUnit.parameterHasValue("arrayList", jsonValuesMissing));
|
||||||
|
Assertions.assertFalse(onTestUnit.parameterHasValue("localDate", jsonValuesMissing));
|
||||||
|
Assertions.assertFalse(onTestUnit.parameterHasValue("keyValue", jsonValuesMissing));
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
@@ -4566,6 +4566,21 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
return installment;
|
return installment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param date
|
||||||
|
* @return a schedule installment is related to the provided date
|
||||||
|
**/
|
||||||
|
public LoanRepaymentScheduleInstallment getRelatedRepaymentScheduleInstallment(LocalDate date) {
|
||||||
|
if (date == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return getRepaymentScheduleInstallments()//
|
||||||
|
.stream()//
|
||||||
|
.filter(installment -> date.isAfter(installment.getFromDate()) && !date.isAfter(installment.getDueDate()))//
|
||||||
|
.findAny()//
|
||||||
|
.orElse(null);//
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return loan disbursement data
|
* @return loan disbursement data
|
||||||
**/
|
**/
|
||||||
|
|||||||
+3
-2
@@ -50,8 +50,9 @@ public final class RescheduleLoansApiConstants {
|
|||||||
public static final String rescheduleReasonCommentParamName = "rescheduleReasonComment";
|
public static final String rescheduleReasonCommentParamName = "rescheduleReasonComment";
|
||||||
public static final String submittedOnDateParamName = "submittedOnDate";
|
public static final String submittedOnDateParamName = "submittedOnDate";
|
||||||
public static final String adjustedDueDateParamName = "adjustedDueDate";
|
public static final String adjustedDueDateParamName = "adjustedDueDate";
|
||||||
public static final String resheduleForMultiDisbursementNotSupportedErrorCode = "loan.reschedule.tranche.multidisbursement.error.code";
|
public static final String rescheduleForMultiDisbursementNotSupportedErrorCode = "loan.reschedule.tranche.multidisbursement.error.code";
|
||||||
public static final String resheduleWithInterestRecalculationNotSupportedErrorCode = "loan.reschedule.interestrecalculation.error.code";
|
public static final String rescheduleMultipleOperationsNotSupportedErrorCode = "loan.reschedule.multioperations.error.code";
|
||||||
|
public static final String rescheduleSelectedOperationNotSupportedErrorCode = "loan.reschedule.selectedoperationnotsupported.error.code";
|
||||||
public static final String allCommandParamName = "all";
|
public static final String allCommandParamName = "all";
|
||||||
public static final String approveCommandParamName = "approve";
|
public static final String approveCommandParamName = "approve";
|
||||||
public static final String pendingCommandParamName = "pending";
|
public static final String pendingCommandParamName = "pending";
|
||||||
|
|||||||
+87
-28
@@ -42,6 +42,7 @@ import org.apache.fineract.infrastructure.core.service.DateUtils;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
|
||||||
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.RescheduleLoansApiConstants;
|
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.RescheduleLoansApiConstants;
|
||||||
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequest;
|
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequest;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -140,11 +141,77 @@ public class LoanRescheduleRequestDataValidator {
|
|||||||
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rescheduleReasonCommentParamName).value(rescheduleReasonComment)
|
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rescheduleReasonCommentParamName).value(rescheduleReasonComment)
|
||||||
.ignoreIfNull().notExceedingLengthOf(500);
|
.ignoreIfNull().notExceedingLengthOf(500);
|
||||||
|
|
||||||
if (this.fromJsonHelper.parameterExists(RescheduleLoansApiConstants.emiParamName, jsonElement)
|
final LocalDate adjustedDueDate = this.fromJsonHelper.extractLocalDateNamed(RescheduleLoansApiConstants.adjustedDueDateParamName,
|
||||||
|| this.fromJsonHelper.parameterExists(RescheduleLoansApiConstants.endDateParamName, jsonElement)) {
|
jsonElement);
|
||||||
|
|
||||||
|
if (adjustedDueDate != null && DateUtils.isBefore(adjustedDueDate, rescheduleFromDate)) {
|
||||||
|
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rescheduleFromDateParamName).failWithCode(
|
||||||
|
"adjustedDueDate.before.rescheduleFromDate", "Adjusted due date cannot be before the reschedule from date");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loan.getLoanProduct().getLoanProductRelatedDetail().getLoanScheduleType() == LoanScheduleType.CUMULATIVE) {
|
||||||
final LocalDate endDate = jsonCommand.localDateValueOfParameterNamed(RescheduleLoansApiConstants.endDateParamName);
|
final LocalDate endDate = jsonCommand.localDateValueOfParameterNamed(RescheduleLoansApiConstants.endDateParamName);
|
||||||
final BigDecimal emi = jsonCommand.bigDecimalValueOfParameterNamed(RescheduleLoansApiConstants.emiParamName);
|
final BigDecimal emi = jsonCommand.bigDecimalValueOfParameterNamed(RescheduleLoansApiConstants.emiParamName);
|
||||||
|
validateForCumulativeLoan(dataValidatorBuilder, loan, jsonElement, rescheduleFromDate, endDate, emi);
|
||||||
|
} else {
|
||||||
|
validateForProgressiveLoan(dataValidatorBuilder, loan, jsonElement, rescheduleFromDate, adjustedDueDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dataValidationErrors.isEmpty()) {
|
||||||
|
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateForProgressiveLoan(final DataValidatorBuilder dataValidatorBuilder, final Loan loan, final JsonElement jsonElement,
|
||||||
|
final LocalDate rescheduleFromDate, final LocalDate adjustedDueDate) {
|
||||||
|
final var unsupportedFields = List.of(RescheduleLoansApiConstants.graceOnPrincipalParamName, //
|
||||||
|
RescheduleLoansApiConstants.graceOnInterestParamName, //
|
||||||
|
RescheduleLoansApiConstants.extraTermsParamName, //
|
||||||
|
RescheduleLoansApiConstants.emiParamName//
|
||||||
|
);
|
||||||
|
|
||||||
|
for (var unsupportedField : unsupportedFields) {
|
||||||
|
if (this.fromJsonHelper.parameterHasValue(unsupportedField, jsonElement)) {
|
||||||
|
dataValidatorBuilder.reset().parameter(unsupportedField).failWithCode(
|
||||||
|
RescheduleLoansApiConstants.rescheduleSelectedOperationNotSupportedErrorCode,
|
||||||
|
"Selected operation is not supported by Progressive Loan at a time during Loan Rescheduling");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final LocalDate businessDate = DateUtils.getBusinessLocalDate();
|
||||||
|
LoanRepaymentScheduleInstallment installment = null;
|
||||||
|
if (rescheduleFromDate != null) {
|
||||||
|
boolean hasInterestRateChange = this.fromJsonHelper.parameterHasValue(RescheduleLoansApiConstants.newInterestRateParamName,
|
||||||
|
jsonElement);
|
||||||
|
if (hasInterestRateChange && adjustedDueDate != null) {
|
||||||
|
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.adjustedDueDateParamName).failWithCode(
|
||||||
|
RescheduleLoansApiConstants.rescheduleMultipleOperationsNotSupportedErrorCode,
|
||||||
|
"Only one operation is supported at a time during Loan Rescheduling");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasInterestRateChange && !rescheduleFromDate.isAfter(businessDate)) {
|
||||||
|
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rescheduleFromDateParamName).failWithCode(
|
||||||
|
"loan.reschedule.interestratechange.reschedulefrom.shouldbefuture",
|
||||||
|
"Loan Reschedule From date should be in the future.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (adjustedDueDate != null) {
|
||||||
|
installment = loan.getRepaymentScheduleInstallment(rescheduleFromDate);
|
||||||
|
} else if (hasInterestRateChange) {
|
||||||
|
installment = loan.getRelatedRepaymentScheduleInstallment(rescheduleFromDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
validateReschedulingInstallment(dataValidatorBuilder, installment);
|
||||||
|
}
|
||||||
|
|
||||||
|
validateForOverdueCharges(dataValidatorBuilder, loan, installment);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateForCumulativeLoan(final DataValidatorBuilder dataValidatorBuilder, final Loan loan, final JsonElement jsonElement,
|
||||||
|
final LocalDate rescheduleFromDate, final LocalDate endDate, final BigDecimal emi) {
|
||||||
|
if (emi != null || endDate != null) {
|
||||||
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.endDateParamName).value(endDate).notNull();
|
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.endDateParamName).value(endDate).notNull();
|
||||||
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.emiParamName).value(emi).notNull().positiveAmount();
|
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.emiParamName).value(emi).notNull().positiveAmount();
|
||||||
|
|
||||||
@@ -156,15 +223,6 @@ public class LoanRescheduleRequestDataValidator {
|
|||||||
.failWithCode("repayment.schedule.installment.does.not.exist", "Repayment schedule installment does not exist");
|
.failWithCode("repayment.schedule.installment.does.not.exist", "Repayment schedule installment does not exist");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
final LocalDate adjustedDueDate = this.fromJsonHelper.extractLocalDateNamed(RescheduleLoansApiConstants.adjustedDueDateParamName,
|
|
||||||
jsonElement);
|
|
||||||
|
|
||||||
if (adjustedDueDate != null && DateUtils.isBefore(adjustedDueDate, rescheduleFromDate)) {
|
|
||||||
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rescheduleFromDateParamName).failWithCode(
|
|
||||||
"adjustedDueDate.before.rescheduleFromDate", "Adjusted due date cannot be before the reschedule from date");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// at least one of the following must be provided => graceOnPrincipal,
|
// at least one of the following must be provided => graceOnPrincipal,
|
||||||
@@ -177,37 +235,38 @@ public class LoanRescheduleRequestDataValidator {
|
|||||||
&& !this.fromJsonHelper.parameterExists(RescheduleLoansApiConstants.emiParamName, jsonElement)) {
|
&& !this.fromJsonHelper.parameterExists(RescheduleLoansApiConstants.emiParamName, jsonElement)) {
|
||||||
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.graceOnPrincipalParamName).notNull();
|
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.graceOnPrincipalParamName).notNull();
|
||||||
}
|
}
|
||||||
LoanRepaymentScheduleInstallment installment = null;
|
|
||||||
|
final LoanRepaymentScheduleInstallment installment = loan.getRepaymentScheduleInstallment(rescheduleFromDate);
|
||||||
|
|
||||||
if (rescheduleFromDate != null) {
|
if (rescheduleFromDate != null) {
|
||||||
installment = loan.getRepaymentScheduleInstallment(rescheduleFromDate);
|
validateReschedulingInstallment(dataValidatorBuilder, installment);
|
||||||
|
|
||||||
if (installment == null) {
|
|
||||||
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rescheduleFromDateParamName)
|
|
||||||
.failWithCode("repayment.schedule.installment.does.not.exist", "Repayment schedule installment does not exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (installment != null && installment.isObligationsMet()) {
|
|
||||||
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rescheduleFromDateParamName)
|
|
||||||
.failWithCode("repayment.schedule.installment.obligation.met", "Repayment schedule installment obligation met");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loan.isMultiDisburmentLoan()) {
|
if (loan.isMultiDisburmentLoan()) {
|
||||||
if (!loan.loanProduct().isDisallowExpectedDisbursements()) {
|
if (!loan.loanProduct().isDisallowExpectedDisbursements()) {
|
||||||
dataValidatorBuilder.reset().failWithCodeNoParameterAddedToErrorCode(
|
dataValidatorBuilder.reset().failWithCodeNoParameterAddedToErrorCode(
|
||||||
RescheduleLoansApiConstants.resheduleForMultiDisbursementNotSupportedErrorCode,
|
RescheduleLoansApiConstants.rescheduleForMultiDisbursementNotSupportedErrorCode,
|
||||||
"Loan rescheduling is not supported for multidisbursement tranche loans");
|
"Loan rescheduling is not supported for multidisbursement tranche loans");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
validateForOverdueCharges(dataValidatorBuilder, loan, installment);
|
validateForOverdueCharges(dataValidatorBuilder, loan, installment);
|
||||||
if (!dataValidationErrors.isEmpty()) {
|
}
|
||||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
|
||||||
|
private static void validateReschedulingInstallment(DataValidatorBuilder dataValidatorBuilder,
|
||||||
|
LoanRepaymentScheduleInstallment installment) {
|
||||||
|
if (installment == null) {
|
||||||
|
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rescheduleFromDateParamName)
|
||||||
|
.failWithCode("repayment.schedule.installment.does.not.exist", "Repayment schedule installment does not exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (installment != null && installment.isObligationsMet()) {
|
||||||
|
dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rescheduleFromDateParamName)
|
||||||
|
.failWithCode("repayment.schedule.installment.obligation.met", "Repayment schedule installment obligation met");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateForOverdueCharges(DataValidatorBuilder dataValidatorBuilder, final Loan loan,
|
private void validateForOverdueCharges(final DataValidatorBuilder dataValidatorBuilder, final Loan loan,
|
||||||
final LoanRepaymentScheduleInstallment installment) {
|
final LoanRepaymentScheduleInstallment installment) {
|
||||||
if (installment != null) {
|
if (installment != null) {
|
||||||
LocalDate rescheduleFromDate = installment.getFromDate();
|
LocalDate rescheduleFromDate = installment.getFromDate();
|
||||||
|
|||||||
+5
-16
@@ -195,29 +195,18 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
|
|||||||
submittedOnDate = jsonCommand.localDateValueOfParameterNamed(RescheduleLoansApiConstants.submittedOnDateParamName);
|
submittedOnDate = jsonCommand.localDateValueOfParameterNamed(RescheduleLoansApiConstants.submittedOnDateParamName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// initially set the value to null
|
|
||||||
LocalDate rescheduleFromDate = null;
|
|
||||||
|
|
||||||
// start point of the rescheduling exercise
|
// start point of the rescheduling exercise
|
||||||
Integer rescheduleFromInstallment = null;
|
Integer rescheduleFromInstallment = null;
|
||||||
|
|
||||||
// initially set the value to null
|
// initially set the value to null
|
||||||
LocalDate adjustedDueDate = null;
|
LocalDate adjustedDueDate = null;
|
||||||
|
|
||||||
|
LocalDate rescheduleFromDate = jsonCommand
|
||||||
|
.localDateValueOfParameterNamed(RescheduleLoansApiConstants.rescheduleFromDateParamName);
|
||||||
// check if the parameter is in the JsonCommand object
|
// check if the parameter is in the JsonCommand object
|
||||||
if (jsonCommand.hasParameter(RescheduleLoansApiConstants.rescheduleFromDateParamName)) {
|
if (rescheduleFromDate != null) {
|
||||||
// create a LocalDate object from the "rescheduleFromDate" Date
|
// get installment by due date
|
||||||
// string
|
rescheduleFromInstallment = loan.getRelatedRepaymentScheduleInstallment(rescheduleFromDate).getInstallmentNumber();
|
||||||
LocalDate localDate = jsonCommand.localDateValueOfParameterNamed(RescheduleLoansApiConstants.rescheduleFromDateParamName);
|
|
||||||
|
|
||||||
if (localDate != null) {
|
|
||||||
// get installment by due date
|
|
||||||
LoanRepaymentScheduleInstallment installment = loan.getRepaymentScheduleInstallment(localDate);
|
|
||||||
rescheduleFromInstallment = installment.getInstallmentNumber();
|
|
||||||
|
|
||||||
// update the value of the "rescheduleFromDate" variable
|
|
||||||
rescheduleFromDate = localDate;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jsonCommand.hasParameter(RescheduleLoansApiConstants.adjustedDueDateParamName)) {
|
if (jsonCommand.hasParameter(RescheduleLoansApiConstants.adjustedDueDateParamName)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user