FINERACT-2090: refactor and cleanup Loan entity
This commit is contained in:
committed by
Adam Saghy
parent
369b809700
commit
c9f0799a06
+370
-1007
File diff suppressed because it is too large
Load Diff
+37
-116
@@ -140,103 +140,39 @@ public class LoanSummary {
|
|||||||
this.totalFeeChargesDueAtDisbursement = totalFeeChargesDueAtDisbursement;
|
this.totalFeeChargesDueAtDisbursement = totalFeeChargesDueAtDisbursement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateTotalFeeChargesDueAtDisbursement(final BigDecimal totalFeeChargesDueAtDisbursement) {
|
|
||||||
this.totalFeeChargesDueAtDisbursement = totalFeeChargesDueAtDisbursement;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Money getTotalFeeChargesDueAtDisbursement(final MonetaryCurrency currency) {
|
|
||||||
return Money.of(currency, this.totalFeeChargesDueAtDisbursement);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Money getTotalOutstanding(final MonetaryCurrency currency) {
|
|
||||||
return Money.of(currency, this.totalOutstanding);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateFeeChargeOutstanding(final BigDecimal totalFeeChargesOutstanding) {
|
|
||||||
this.totalFeeChargesOutstanding = totalFeeChargesOutstanding;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updatePenaltyChargeOutstanding(final BigDecimal totalPenaltyChargesOutstanding) {
|
|
||||||
this.totalPenaltyChargesOutstanding = totalPenaltyChargesOutstanding;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateFeeChargesWaived(final BigDecimal totalFeeChargesWaived) {
|
|
||||||
this.totalFeeChargesWaived = totalFeeChargesWaived;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updatePenaltyChargesWaived(final BigDecimal totalPenaltyChargesWaived) {
|
|
||||||
this.totalPenaltyChargesWaived = totalPenaltyChargesWaived;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRepaidInFull(final MonetaryCurrency currency) {
|
|
||||||
return getTotalOutstanding(currency).isZero();
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getTotalInterestCharged() {
|
|
||||||
return this.totalInterestCharged;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getTotalPrincipalOutstanding() {
|
|
||||||
return this.totalPrincipalOutstanding;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getTotalInterestOutstanding() {
|
|
||||||
return this.totalInterestOutstanding;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getTotalFeeChargesOutstanding() {
|
|
||||||
return this.totalFeeChargesOutstanding;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getTotalPenaltyChargesOutstanding() {
|
|
||||||
return this.totalPenaltyChargesOutstanding;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getTotalOutstanding() {
|
|
||||||
return this.totalOutstanding;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateTotalOutstanding(final BigDecimal newTotalOutstanding) {
|
|
||||||
this.totalOutstanding = newTotalOutstanding;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateTotalWaived(final BigDecimal totalWaived) {
|
|
||||||
this.totalWaived = totalWaived;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All fields but <code>totalFeeChargesDueAtDisbursement</code> should be reset.
|
* All fields but <code>totalFeeChargesDueAtDisbursement</code> should be reset.
|
||||||
*/
|
*/
|
||||||
public void zeroFields() {
|
public void zeroFields() {
|
||||||
this.totalPrincipalDisbursed = BigDecimal.ZERO;
|
this.totalCostOfLoan = BigDecimal.ZERO;
|
||||||
this.totalPrincipalAdjustments = BigDecimal.ZERO;
|
this.totalExpectedCostOfLoan = BigDecimal.ZERO;
|
||||||
|
this.totalExpectedRepayment = BigDecimal.ZERO;
|
||||||
this.totalFeeAdjustments = BigDecimal.ZERO;
|
this.totalFeeAdjustments = BigDecimal.ZERO;
|
||||||
this.totalPenaltyAdjustments = BigDecimal.ZERO;
|
|
||||||
this.totalPrincipalRepaid = BigDecimal.ZERO;
|
|
||||||
this.totalPrincipalWrittenOff = BigDecimal.ZERO;
|
|
||||||
this.totalPrincipalOutstanding = BigDecimal.ZERO;
|
|
||||||
this.totalInterestCharged = BigDecimal.ZERO;
|
|
||||||
this.totalInterestRepaid = BigDecimal.ZERO;
|
|
||||||
this.totalInterestWaived = BigDecimal.ZERO;
|
|
||||||
this.totalInterestWrittenOff = BigDecimal.ZERO;
|
|
||||||
this.totalInterestOutstanding = BigDecimal.ZERO;
|
|
||||||
this.totalFeeChargesCharged = BigDecimal.ZERO;
|
this.totalFeeChargesCharged = BigDecimal.ZERO;
|
||||||
|
this.totalFeeChargesOutstanding = BigDecimal.ZERO;
|
||||||
this.totalFeeChargesRepaid = BigDecimal.ZERO;
|
this.totalFeeChargesRepaid = BigDecimal.ZERO;
|
||||||
this.totalFeeChargesWaived = BigDecimal.ZERO;
|
this.totalFeeChargesWaived = BigDecimal.ZERO;
|
||||||
this.totalFeeChargesWrittenOff = BigDecimal.ZERO;
|
this.totalFeeChargesWrittenOff = BigDecimal.ZERO;
|
||||||
this.totalFeeChargesOutstanding = BigDecimal.ZERO;
|
this.totalInterestCharged = BigDecimal.ZERO;
|
||||||
|
this.totalInterestOutstanding = BigDecimal.ZERO;
|
||||||
|
this.totalInterestRepaid = BigDecimal.ZERO;
|
||||||
|
this.totalInterestWaived = BigDecimal.ZERO;
|
||||||
|
this.totalInterestWrittenOff = BigDecimal.ZERO;
|
||||||
|
this.totalOutstanding = BigDecimal.ZERO;
|
||||||
|
this.totalPenaltyAdjustments = BigDecimal.ZERO;
|
||||||
this.totalPenaltyChargesCharged = BigDecimal.ZERO;
|
this.totalPenaltyChargesCharged = BigDecimal.ZERO;
|
||||||
|
this.totalPenaltyChargesOutstanding = BigDecimal.ZERO;
|
||||||
this.totalPenaltyChargesRepaid = BigDecimal.ZERO;
|
this.totalPenaltyChargesRepaid = BigDecimal.ZERO;
|
||||||
this.totalPenaltyChargesWaived = BigDecimal.ZERO;
|
this.totalPenaltyChargesWaived = BigDecimal.ZERO;
|
||||||
this.totalPenaltyChargesWrittenOff = BigDecimal.ZERO;
|
this.totalPenaltyChargesWrittenOff = BigDecimal.ZERO;
|
||||||
this.totalPenaltyChargesOutstanding = BigDecimal.ZERO;
|
this.totalPrincipalAdjustments = BigDecimal.ZERO;
|
||||||
this.totalExpectedRepayment = BigDecimal.ZERO;
|
this.totalPrincipalDisbursed = BigDecimal.ZERO;
|
||||||
|
this.totalPrincipalOutstanding = BigDecimal.ZERO;
|
||||||
|
this.totalPrincipalRepaid = BigDecimal.ZERO;
|
||||||
|
this.totalPrincipalWrittenOff = BigDecimal.ZERO;
|
||||||
this.totalRepayment = BigDecimal.ZERO;
|
this.totalRepayment = BigDecimal.ZERO;
|
||||||
this.totalExpectedCostOfLoan = BigDecimal.ZERO;
|
|
||||||
this.totalCostOfLoan = BigDecimal.ZERO;
|
|
||||||
this.totalWaived = BigDecimal.ZERO;
|
this.totalWaived = BigDecimal.ZERO;
|
||||||
this.totalWrittenOff = BigDecimal.ZERO;
|
this.totalWrittenOff = BigDecimal.ZERO;
|
||||||
this.totalOutstanding = BigDecimal.ZERO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateSummary(final MonetaryCurrency currency, final Money principal,
|
public void updateSummary(final MonetaryCurrency currency, final Money principal,
|
||||||
@@ -327,58 +263,43 @@ public class LoanSummary {
|
|||||||
this.totalOutstanding = totalOutstanding.getAmount();
|
this.totalOutstanding = totalOutstanding.getAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getTotalPrincipalDisbursed() {
|
public void updateTotalFeeChargesDueAtDisbursement(final BigDecimal totalFeeChargesDueAtDisbursement) {
|
||||||
return this.totalPrincipalDisbursed;
|
this.totalFeeChargesDueAtDisbursement = totalFeeChargesDueAtDisbursement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getTotalPrincipalRepaid() {
|
public Money getTotalFeeChargesDueAtDisbursement(final MonetaryCurrency currency) {
|
||||||
return this.totalPrincipalRepaid;
|
return Money.of(currency, this.totalFeeChargesDueAtDisbursement);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getTotalWrittenOff() {
|
public Money getTotalOutstanding(final MonetaryCurrency currency) {
|
||||||
return this.totalWrittenOff;
|
return Money.of(currency, this.totalOutstanding);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void updateFeeChargeOutstanding(final BigDecimal totalFeeChargesOutstanding) {
|
||||||
* @return total interest repaid
|
this.totalFeeChargesOutstanding = totalFeeChargesOutstanding;
|
||||||
**/
|
|
||||||
public BigDecimal getTotalInterestRepaid() {
|
|
||||||
return this.totalInterestRepaid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getTotalFeeChargesCharged() {
|
public void updatePenaltyChargeOutstanding(final BigDecimal totalPenaltyChargesOutstanding) {
|
||||||
return this.totalFeeChargesCharged;
|
this.totalPenaltyChargesOutstanding = totalPenaltyChargesOutstanding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getTotalPenaltyChargesCharged() {
|
public void updateFeeChargesWaived(final BigDecimal totalFeeChargesWaived) {
|
||||||
return this.totalPenaltyChargesCharged;
|
this.totalFeeChargesWaived = totalFeeChargesWaived;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getTotalPrincipalWrittenOff() {
|
public void updatePenaltyChargesWaived(final BigDecimal totalPenaltyChargesWaived) {
|
||||||
return this.totalPrincipalWrittenOff;
|
this.totalPenaltyChargesWaived = totalPenaltyChargesWaived;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getTotalInterestWaived() {
|
public boolean isRepaidInFull(final MonetaryCurrency currency) {
|
||||||
return this.totalInterestWaived;
|
return getTotalOutstanding(currency).isZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getTotalFeeChargesRepaid() {
|
public void updateTotalOutstanding(final BigDecimal newTotalOutstanding) {
|
||||||
return this.totalFeeChargesRepaid;
|
this.totalOutstanding = newTotalOutstanding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getTotalFeeChargesWaived() {
|
public void updateTotalWaived(final BigDecimal totalWaived) {
|
||||||
return this.totalFeeChargesWaived;
|
this.totalWaived = totalWaived;
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getTotalPenaltyChargesRepaid() {
|
|
||||||
return this.totalPenaltyChargesRepaid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getTotalPenaltyChargesWaived() {
|
|
||||||
return this.totalPenaltyChargesWaived;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getTotalExpectedRepayment() {
|
|
||||||
return this.totalExpectedRepayment;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+142
-107
@@ -33,6 +33,7 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -235,19 +236,11 @@ public final class LoanApplicationValidator {
|
|||||||
|
|
||||||
final Long clientId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.clientIdParameterName, element);
|
final Long clientId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.clientIdParameterName, element);
|
||||||
final Long groupId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.groupIdParameterName, element);
|
final Long groupId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.groupIdParameterName, element);
|
||||||
Client client = null;
|
final Client client = clientId != null ? this.clientRepository.findOneWithNotFoundDetection(clientId) : null;
|
||||||
if (clientId != null) {
|
final Group group = groupId != null ? this.groupRepository.findOneWithNotFoundDetection(groupId) : null;
|
||||||
client = this.clientRepository.findOneWithNotFoundDetection(clientId);
|
|
||||||
}
|
|
||||||
Group group = null;
|
|
||||||
if (groupId != null) {
|
|
||||||
group = this.groupRepository.findOneWithNotFoundDetection(groupId);
|
|
||||||
}
|
|
||||||
validateClientOrGroup(client, group, productId);
|
validateClientOrGroup(client, group, productId);
|
||||||
|
|
||||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
validateOrThrow("loan", baseDataValidator -> {
|
||||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan");
|
|
||||||
|
|
||||||
final String loanTypeStr = this.fromApiJsonHelper.extractStringNamed(LoanApiConstants.loanTypeParameterName, element);
|
final String loanTypeStr = this.fromApiJsonHelper.extractStringNamed(LoanApiConstants.loanTypeParameterName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.loanTypeParameterName).value(loanTypeStr).notNull();
|
baseDataValidator.reset().parameter(LoanApiConstants.loanTypeParameterName).value(loanTypeStr).notNull();
|
||||||
|
|
||||||
@@ -256,13 +249,15 @@ public final class LoanApplicationValidator {
|
|||||||
baseDataValidator.reset().parameter(LoanApiConstants.loanTypeParameterName).value(loanType.getValue()).inMinMaxRange(1, 4);
|
baseDataValidator.reset().parameter(LoanApiConstants.loanTypeParameterName).value(loanType.getValue()).inMinMaxRange(1, 4);
|
||||||
|
|
||||||
if (loanType.isIndividualAccount()) {
|
if (loanType.isIndividualAccount()) {
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.clientIdParameterName).value(clientId).notNull().longGreaterThanZero();
|
baseDataValidator.reset().parameter(LoanApiConstants.clientIdParameterName).value(clientId).notNull()
|
||||||
|
.longGreaterThanZero();
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.groupIdParameterName).value(groupId)
|
baseDataValidator.reset().parameter(LoanApiConstants.groupIdParameterName).value(groupId)
|
||||||
.mustBeBlankWhenParameterProvided(LoanApiConstants.clientIdParameterName, clientId);
|
.mustBeBlankWhenParameterProvided(LoanApiConstants.clientIdParameterName, clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loanType.isGroupAccount()) {
|
if (loanType.isGroupAccount()) {
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.groupIdParameterName).value(groupId).notNull().longGreaterThanZero();
|
baseDataValidator.reset().parameter(LoanApiConstants.groupIdParameterName).value(groupId).notNull()
|
||||||
|
.longGreaterThanZero();
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.clientIdParameterName).value(clientId)
|
baseDataValidator.reset().parameter(LoanApiConstants.clientIdParameterName).value(clientId)
|
||||||
.mustBeBlankWhenParameterProvided(LoanApiConstants.groupIdParameterName, groupId);
|
.mustBeBlankWhenParameterProvided(LoanApiConstants.groupIdParameterName, groupId);
|
||||||
}
|
}
|
||||||
@@ -270,7 +265,8 @@ public final class LoanApplicationValidator {
|
|||||||
if (loanType.isJLGAccount()) {
|
if (loanType.isJLGAccount()) {
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.clientIdParameterName).value(clientId).notNull()
|
baseDataValidator.reset().parameter(LoanApiConstants.clientIdParameterName).value(clientId).notNull()
|
||||||
.integerGreaterThanZero();
|
.integerGreaterThanZero();
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.groupIdParameterName).value(groupId).notNull().longGreaterThanZero();
|
baseDataValidator.reset().parameter(LoanApiConstants.groupIdParameterName).value(groupId).notNull()
|
||||||
|
.longGreaterThanZero();
|
||||||
|
|
||||||
// if it is JLG loan that must have meeting details
|
// if it is JLG loan that must have meeting details
|
||||||
if (isMeetingMandatoryForJLGLoans) {
|
if (isMeetingMandatoryForJLGLoans) {
|
||||||
@@ -291,7 +287,6 @@ public final class LoanApplicationValidator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isEqualAmortization = false;
|
boolean isEqualAmortization = false;
|
||||||
@@ -307,9 +302,11 @@ public final class LoanApplicationValidator {
|
|||||||
BigDecimal fixedPrincipalPercentagePerInstallment = this.fromApiJsonHelper
|
BigDecimal fixedPrincipalPercentagePerInstallment = this.fromApiJsonHelper
|
||||||
.extractBigDecimalWithLocaleNamed(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName, element);
|
.extractBigDecimalWithLocaleNamed(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName)
|
baseDataValidator.reset().parameter(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName)
|
||||||
.value(fixedPrincipalPercentagePerInstallment).notLessThanMin(BigDecimal.ONE).notGreaterThanMax(BigDecimal.valueOf(100));
|
.value(fixedPrincipalPercentagePerInstallment).notLessThanMin(BigDecimal.ONE)
|
||||||
|
.notGreaterThanMax(BigDecimal.valueOf(100));
|
||||||
|
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.productIdParameterName).value(productId).notNull().integerGreaterThanZero();
|
baseDataValidator.reset().parameter(LoanApiConstants.productIdParameterName).value(productId).notNull()
|
||||||
|
.integerGreaterThanZero();
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.accountNoParameterName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.accountNoParameterName, element)) {
|
||||||
final String accountNo = this.fromApiJsonHelper.extractStringNamed(LoanApiConstants.accountNoParameterName, element);
|
final String accountNo = this.fromApiJsonHelper.extractStringNamed(LoanApiConstants.accountNoParameterName, element);
|
||||||
@@ -325,7 +322,8 @@ public final class LoanApplicationValidator {
|
|||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.fundIdParameterName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.fundIdParameterName, element)) {
|
||||||
final Long fundId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.fundIdParameterName, element);
|
final Long fundId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.fundIdParameterName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.fundIdParameterName).value(fundId).ignoreIfNull().integerGreaterThanZero();
|
baseDataValidator.reset().parameter(LoanApiConstants.fundIdParameterName).value(fundId).ignoreIfNull()
|
||||||
|
.integerGreaterThanZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.loanOfficerIdParameterName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.loanOfficerIdParameterName, element)) {
|
||||||
@@ -340,7 +338,8 @@ public final class LoanApplicationValidator {
|
|||||||
.integerGreaterThanZero();
|
.integerGreaterThanZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
final BigDecimal principal = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(LoanApiConstants.principalParamName, element);
|
final BigDecimal principal = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(LoanApiConstants.principalParamName,
|
||||||
|
element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.principalParamName).value(principal).notNull().positiveAmount();
|
baseDataValidator.reset().parameter(LoanApiConstants.principalParamName).value(principal).notNull().positiveAmount();
|
||||||
|
|
||||||
final Integer loanTermFrequency = this.fromApiJsonHelper
|
final Integer loanTermFrequency = this.fromApiJsonHelper
|
||||||
@@ -358,8 +357,8 @@ public final class LoanApplicationValidator {
|
|||||||
baseDataValidator.reset().parameter(LoanApiConstants.numberOfRepaymentsParameterName).value(numberOfRepayments).notNull()
|
baseDataValidator.reset().parameter(LoanApiConstants.numberOfRepaymentsParameterName).value(numberOfRepayments).notNull()
|
||||||
.integerGreaterThanZero();
|
.integerGreaterThanZero();
|
||||||
|
|
||||||
final Integer repaymentEvery = this.fromApiJsonHelper.extractIntegerWithLocaleNamed(LoanApiConstants.repaymentEveryParameterName,
|
final Integer repaymentEvery = this.fromApiJsonHelper
|
||||||
element);
|
.extractIntegerWithLocaleNamed(LoanApiConstants.repaymentEveryParameterName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.repaymentEveryParameterName).value(repaymentEvery).notNull()
|
baseDataValidator.reset().parameter(LoanApiConstants.repaymentEveryParameterName).value(repaymentEvery).notNull()
|
||||||
.integerGreaterThanZero();
|
.integerGreaterThanZero();
|
||||||
|
|
||||||
@@ -373,7 +372,8 @@ public final class LoanApplicationValidator {
|
|||||||
|
|
||||||
final Integer interestType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(LoanApiConstants.interestTypeParameterName,
|
final Integer interestType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(LoanApiConstants.interestTypeParameterName,
|
||||||
element);
|
element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.interestTypeParameterName).value(interestType).notNull().inMinMaxRange(0, 1);
|
baseDataValidator.reset().parameter(LoanApiConstants.interestTypeParameterName).value(interestType).notNull().inMinMaxRange(0,
|
||||||
|
1);
|
||||||
|
|
||||||
final Integer interestCalculationPeriodType = this.fromApiJsonHelper
|
final Integer interestCalculationPeriodType = this.fromApiJsonHelper
|
||||||
.extractIntegerSansLocaleNamed(LoanApiConstants.interestCalculationPeriodTypeParameterName, element);
|
.extractIntegerSansLocaleNamed(LoanApiConstants.interestCalculationPeriodTypeParameterName, element);
|
||||||
@@ -392,8 +392,8 @@ public final class LoanApplicationValidator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.isFloatingInterestRate, element)) {
|
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.isFloatingInterestRate, element)) {
|
||||||
final Boolean isFloatingInterestRate = this.fromApiJsonHelper.extractBooleanNamed(LoanApiConstants.isFloatingInterestRate,
|
final Boolean isFloatingInterestRate = this.fromApiJsonHelper
|
||||||
element);
|
.extractBooleanNamed(LoanApiConstants.isFloatingInterestRate, element);
|
||||||
if (isFloatingInterestRate != null && isFloatingInterestRate
|
if (isFloatingInterestRate != null && isFloatingInterestRate
|
||||||
&& !loanProduct.getFloatingRates().isFloatingInterestRateCalculationAllowed()) {
|
&& !loanProduct.getFloatingRates().isFloatingInterestRateCalculationAllowed()) {
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.isFloatingInterestRate).failWithCode(
|
baseDataValidator.reset().parameter(LoanApiConstants.isFloatingInterestRate).failWithCode(
|
||||||
@@ -432,8 +432,8 @@ public final class LoanApplicationValidator {
|
|||||||
|
|
||||||
final BigDecimal interestRatePerPeriod = this.fromApiJsonHelper
|
final BigDecimal interestRatePerPeriod = this.fromApiJsonHelper
|
||||||
.extractBigDecimalWithLocaleNamed(LoanApiConstants.interestRatePerPeriodParameterName, element);
|
.extractBigDecimalWithLocaleNamed(LoanApiConstants.interestRatePerPeriodParameterName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.interestRatePerPeriodParameterName).value(interestRatePerPeriod).notNull()
|
baseDataValidator.reset().parameter(LoanApiConstants.interestRatePerPeriodParameterName).value(interestRatePerPeriod)
|
||||||
.zeroOrPositiveAmount();
|
.notNull().zeroOrPositiveAmount();
|
||||||
isInterestBearing = interestRatePerPeriod.compareTo(BigDecimal.ZERO) > 0;
|
isInterestBearing = interestRatePerPeriod.compareTo(BigDecimal.ZERO) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,15 +484,15 @@ public final class LoanApplicationValidator {
|
|||||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.repaymentsStartingFromDateParameterName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.repaymentsStartingFromDateParameterName, element)) {
|
||||||
final LocalDate repaymentsStartingFromDate = this.fromApiJsonHelper
|
final LocalDate repaymentsStartingFromDate = this.fromApiJsonHelper
|
||||||
.extractLocalDateNamed(LoanApiConstants.repaymentsStartingFromDateParameterName, element);
|
.extractLocalDateNamed(LoanApiConstants.repaymentsStartingFromDateParameterName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.repaymentsStartingFromDateParameterName).value(repaymentsStartingFromDate)
|
baseDataValidator.reset().parameter(LoanApiConstants.repaymentsStartingFromDateParameterName)
|
||||||
.ignoreIfNull().notNull();
|
.value(repaymentsStartingFromDate).ignoreIfNull().notNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.inArrearsToleranceParameterName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.inArrearsToleranceParameterName, element)) {
|
||||||
final BigDecimal inArrearsTolerance = this.fromApiJsonHelper
|
final BigDecimal inArrearsTolerance = this.fromApiJsonHelper
|
||||||
.extractBigDecimalWithLocaleNamed(LoanApiConstants.inArrearsToleranceParameterName, element);
|
.extractBigDecimalWithLocaleNamed(LoanApiConstants.inArrearsToleranceParameterName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.inArrearsToleranceParameterName).value(inArrearsTolerance).ignoreIfNull()
|
baseDataValidator.reset().parameter(LoanApiConstants.inArrearsToleranceParameterName).value(inArrearsTolerance)
|
||||||
.zeroOrPositiveAmount();
|
.ignoreIfNull().zeroOrPositiveAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
final LocalDate submittedOnDate = this.fromApiJsonHelper.extractLocalDateNamed(LoanApiConstants.submittedOnDateParameterName,
|
final LocalDate submittedOnDate = this.fromApiJsonHelper.extractLocalDateNamed(LoanApiConstants.submittedOnDateParameterName,
|
||||||
@@ -562,8 +562,8 @@ public final class LoanApplicationValidator {
|
|||||||
.parameterAtIndexArray(LoanApiConstants.clientCollateralIdParameterName, i).value(clientCollateralId)
|
.parameterAtIndexArray(LoanApiConstants.clientCollateralIdParameterName, i).value(clientCollateralId)
|
||||||
.notNull().integerGreaterThanZero();
|
.notNull().integerGreaterThanZero();
|
||||||
|
|
||||||
final BigDecimal quantity = this.fromApiJsonHelper.extractBigDecimalNamed(LoanApiConstants.quantityParameterName,
|
final BigDecimal quantity = this.fromApiJsonHelper
|
||||||
collateralItemElement, locale);
|
.extractBigDecimalNamed(LoanApiConstants.quantityParameterName, collateralItemElement, locale);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.collateralParameterName)
|
baseDataValidator.reset().parameter(LoanApiConstants.collateralParameterName)
|
||||||
.parameterAtIndexArray(LoanApiConstants.quantityParameterName, i).value(quantity).notNull()
|
.parameterAtIndexArray(LoanApiConstants.quantityParameterName, i).value(quantity).notNull()
|
||||||
.positiveAmount();
|
.positiveAmount();
|
||||||
@@ -571,7 +571,8 @@ public final class LoanApplicationValidator {
|
|||||||
final ClientCollateralManagement clientCollateralManagement = this.clientCollateralManagementRepositoryWrapper
|
final ClientCollateralManagement clientCollateralManagement = this.clientCollateralManagementRepositoryWrapper
|
||||||
.getCollateral(clientCollateralId);
|
.getCollateral(clientCollateralId);
|
||||||
|
|
||||||
if (clientCollateralId != null && BigDecimal.valueOf(0).compareTo(clientCollateralManagement.getQuantity()) >= 0) {
|
if (clientCollateralId != null
|
||||||
|
&& BigDecimal.valueOf(0).compareTo(clientCollateralManagement.getQuantity()) >= 0) {
|
||||||
throw new InvalidAmountOfCollateralQuantity(clientCollateralManagement.getQuantity());
|
throw new InvalidAmountOfCollateralQuantity(clientCollateralManagement.getQuantity());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -659,8 +660,8 @@ public final class LoanApplicationValidator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.daysInYearTypeParameterName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.daysInYearTypeParameterName, element)) {
|
||||||
final Integer daysInYearType = this.fromApiJsonHelper.extractIntegerNamed(LoanApiConstants.daysInYearTypeParameterName, element,
|
final Integer daysInYearType = this.fromApiJsonHelper.extractIntegerNamed(LoanApiConstants.daysInYearTypeParameterName,
|
||||||
Locale.getDefault());
|
element, Locale.getDefault());
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.daysInYearTypeParameterName).value(daysInYearType).notNull()
|
baseDataValidator.reset().parameter(LoanApiConstants.daysInYearTypeParameterName).value(daysInYearType).notNull()
|
||||||
.isOneOfTheseValues(1, 360, 364, 365);
|
.isOneOfTheseValues(1, 360, 364, 365);
|
||||||
}
|
}
|
||||||
@@ -685,7 +686,8 @@ public final class LoanApplicationValidator {
|
|||||||
List<LoanProductPaymentAllocationRule> allocationRules = loanProduct.getPaymentAllocationRules();
|
List<LoanProductPaymentAllocationRule> allocationRules = loanProduct.getPaymentAllocationRules();
|
||||||
|
|
||||||
if (LoanScheduleProcessingType.HORIZONTAL.name().equals(loanScheduleProcessingType)
|
if (LoanScheduleProcessingType.HORIZONTAL.name().equals(loanScheduleProcessingType)
|
||||||
&& AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY.equals(transactionProcessingStrategy)) {
|
&& AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY
|
||||||
|
.equals(transactionProcessingStrategy)) {
|
||||||
advancedPaymentAllocationsValidator.checkGroupingOfAllocationRules(allocationRules);
|
advancedPaymentAllocationsValidator.checkGroupingOfAllocationRules(allocationRules);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -734,10 +736,7 @@ public final class LoanApplicationValidator {
|
|||||||
.extractIntegerWithLocaleNamed("recurringMoratoriumOnPrincipalPeriods", element);
|
.extractIntegerWithLocaleNamed("recurringMoratoriumOnPrincipalPeriods", element);
|
||||||
loanProductDataValidator.validateRepaymentPeriodWithGraceSettings(numberOfRepayments, graceOnPrincipalPayment,
|
loanProductDataValidator.validateRepaymentPeriodWithGraceSettings(numberOfRepayments, graceOnPrincipalPayment,
|
||||||
graceOnInterestPayment, graceOnInterestCharged, recurringMoratoriumOnPrincipalPeriods, baseDataValidator);
|
graceOnInterestPayment, graceOnInterestCharged, recurringMoratoriumOnPrincipalPeriods, baseDataValidator);
|
||||||
|
});
|
||||||
if (!dataValidationErrors.isEmpty()) {
|
|
||||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateBorrowerCycle(JsonElement element, LoanProduct loanProduct, Long clientId, Long groupId,
|
private void validateBorrowerCycle(JsonElement element, LoanProduct loanProduct, Long clientId, Long groupId,
|
||||||
@@ -821,8 +820,7 @@ public final class LoanApplicationValidator {
|
|||||||
loanProduct = this.loanProductRepository.findById(productId).orElseThrow(() -> new LoanProductNotFoundException(productId));
|
loanProduct = this.loanProductRepository.findById(productId).orElseThrow(() -> new LoanProductNotFoundException(productId));
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
validateOrThrow("loan", baseDataValidator -> {
|
||||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan");
|
|
||||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||||
boolean atLeastOneParameterPassedForUpdate = false;
|
boolean atLeastOneParameterPassedForUpdate = false;
|
||||||
|
|
||||||
@@ -830,7 +828,8 @@ public final class LoanApplicationValidator {
|
|||||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.clientIdParameterName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.clientIdParameterName, element)) {
|
||||||
atLeastOneParameterPassedForUpdate = true;
|
atLeastOneParameterPassedForUpdate = true;
|
||||||
clientId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.clientIdParameterName, element);
|
clientId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.clientIdParameterName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.clientIdParameterName).value(clientId).notNull().integerGreaterThanZero();
|
baseDataValidator.reset().parameter(LoanApiConstants.clientIdParameterName).value(clientId).notNull()
|
||||||
|
.integerGreaterThanZero();
|
||||||
}
|
}
|
||||||
Client client = null;
|
Client client = null;
|
||||||
if (clientId != null) {
|
if (clientId != null) {
|
||||||
@@ -840,7 +839,8 @@ public final class LoanApplicationValidator {
|
|||||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.groupIdParameterName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.groupIdParameterName, element)) {
|
||||||
atLeastOneParameterPassedForUpdate = true;
|
atLeastOneParameterPassedForUpdate = true;
|
||||||
groupId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.groupIdParameterName, element);
|
groupId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.groupIdParameterName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.groupIdParameterName).value(groupId).notNull().integerGreaterThanZero();
|
baseDataValidator.reset().parameter(LoanApiConstants.groupIdParameterName).value(groupId).notNull()
|
||||||
|
.integerGreaterThanZero();
|
||||||
}
|
}
|
||||||
Group group = null;
|
Group group = null;
|
||||||
if (groupId != null) {
|
if (groupId != null) {
|
||||||
@@ -863,8 +863,8 @@ public final class LoanApplicationValidator {
|
|||||||
boolean isEqualAmortization = loan.getLoanProductRelatedDetail().isEqualAmortization();
|
boolean isEqualAmortization = loan.getLoanProductRelatedDetail().isEqualAmortization();
|
||||||
if (this.fromApiJsonHelper.parameterExists(LoanProductConstants.IS_EQUAL_AMORTIZATION_PARAM, element)) {
|
if (this.fromApiJsonHelper.parameterExists(LoanProductConstants.IS_EQUAL_AMORTIZATION_PARAM, element)) {
|
||||||
isEqualAmortization = this.fromApiJsonHelper.extractBooleanNamed(LoanProductConstants.IS_EQUAL_AMORTIZATION_PARAM, element);
|
isEqualAmortization = this.fromApiJsonHelper.extractBooleanNamed(LoanProductConstants.IS_EQUAL_AMORTIZATION_PARAM, element);
|
||||||
baseDataValidator.reset().parameter(LoanProductConstants.IS_EQUAL_AMORTIZATION_PARAM).value(isEqualAmortization).ignoreIfNull()
|
baseDataValidator.reset().parameter(LoanProductConstants.IS_EQUAL_AMORTIZATION_PARAM).value(isEqualAmortization)
|
||||||
.validateForBooleanValue();
|
.ignoreIfNull().validateForBooleanValue();
|
||||||
if (isEqualAmortization && loanProduct.isInterestRecalculationEnabled()) {
|
if (isEqualAmortization && loanProduct.isInterestRecalculationEnabled()) {
|
||||||
throw new EqualAmortizationUnsupportedFeatureException("interest.recalculation", "interest recalculation");
|
throw new EqualAmortizationUnsupportedFeatureException("interest.recalculation", "interest recalculation");
|
||||||
}
|
}
|
||||||
@@ -873,7 +873,8 @@ public final class LoanApplicationValidator {
|
|||||||
BigDecimal fixedPrincipalPercentagePerInstallment = this.fromApiJsonHelper
|
BigDecimal fixedPrincipalPercentagePerInstallment = this.fromApiJsonHelper
|
||||||
.extractBigDecimalWithLocaleNamed(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName, element);
|
.extractBigDecimalWithLocaleNamed(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName)
|
baseDataValidator.reset().parameter(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName)
|
||||||
.value(fixedPrincipalPercentagePerInstallment).notLessThanMin(BigDecimal.ONE).notGreaterThanMax(BigDecimal.valueOf(100));
|
.value(fixedPrincipalPercentagePerInstallment).notLessThanMin(BigDecimal.ONE)
|
||||||
|
.notGreaterThanMax(BigDecimal.valueOf(100));
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.externalIdParameterName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.externalIdParameterName, element)) {
|
||||||
atLeastOneParameterPassedForUpdate = true;
|
atLeastOneParameterPassedForUpdate = true;
|
||||||
@@ -885,7 +886,8 @@ public final class LoanApplicationValidator {
|
|||||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.fundIdParameterName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.fundIdParameterName, element)) {
|
||||||
atLeastOneParameterPassedForUpdate = true;
|
atLeastOneParameterPassedForUpdate = true;
|
||||||
final Long fundId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.fundIdParameterName, element);
|
final Long fundId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.fundIdParameterName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.fundIdParameterName).value(fundId).ignoreIfNull().integerGreaterThanZero();
|
baseDataValidator.reset().parameter(LoanApiConstants.fundIdParameterName).value(fundId).ignoreIfNull()
|
||||||
|
.integerGreaterThanZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.loanOfficerIdParameterName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.loanOfficerIdParameterName, element)) {
|
||||||
@@ -908,7 +910,8 @@ public final class LoanApplicationValidator {
|
|||||||
|
|
||||||
if (!AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY
|
if (!AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY
|
||||||
.equals(loanProduct.getTransactionProcessingStrategyCode())
|
.equals(loanProduct.getTransactionProcessingStrategyCode())
|
||||||
&& AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY.equals(transactionProcessingStrategy)) {
|
&& AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY
|
||||||
|
.equals(transactionProcessingStrategy)) {
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.transactionProcessingStrategyCodeParameterName).failWithCode(
|
baseDataValidator.reset().parameter(LoanApiConstants.transactionProcessingStrategyCodeParameterName).failWithCode(
|
||||||
"strategy.cannot.be.advanced.payment.allocation.if.not.configured",
|
"strategy.cannot.be.advanced.payment.allocation.if.not.configured",
|
||||||
"Loan transaction processing strategy cannot be Advanced Payment Allocation Strategy if it's not configured on loan product");
|
"Loan transaction processing strategy cannot be Advanced Payment Allocation Strategy if it's not configured on loan product");
|
||||||
@@ -925,8 +928,8 @@ public final class LoanApplicationValidator {
|
|||||||
atLeastOneParameterPassedForUpdate = true;
|
atLeastOneParameterPassedForUpdate = true;
|
||||||
final BigDecimal inArrearsTolerance = this.fromApiJsonHelper
|
final BigDecimal inArrearsTolerance = this.fromApiJsonHelper
|
||||||
.extractBigDecimalWithLocaleNamed(LoanApiConstants.inArrearsToleranceParameterName, element);
|
.extractBigDecimalWithLocaleNamed(LoanApiConstants.inArrearsToleranceParameterName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.inArrearsToleranceParameterName).value(inArrearsTolerance).ignoreIfNull()
|
baseDataValidator.reset().parameter(LoanApiConstants.inArrearsToleranceParameterName).value(inArrearsTolerance)
|
||||||
.zeroOrPositiveAmount();
|
.ignoreIfNull().zeroOrPositiveAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.loanTermFrequencyParameterName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.loanTermFrequencyParameterName, element)) {
|
||||||
@@ -941,8 +944,8 @@ public final class LoanApplicationValidator {
|
|||||||
atLeastOneParameterPassedForUpdate = true;
|
atLeastOneParameterPassedForUpdate = true;
|
||||||
final Integer loanTermFrequencyType = this.fromApiJsonHelper
|
final Integer loanTermFrequencyType = this.fromApiJsonHelper
|
||||||
.extractIntegerWithLocaleNamed(LoanApiConstants.loanTermFrequencyTypeParameterName, element);
|
.extractIntegerWithLocaleNamed(LoanApiConstants.loanTermFrequencyTypeParameterName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.loanTermFrequencyTypeParameterName).value(loanTermFrequencyType).notNull()
|
baseDataValidator.reset().parameter(LoanApiConstants.loanTermFrequencyTypeParameterName).value(loanTermFrequencyType)
|
||||||
.inMinMaxRange(0, 3);
|
.notNull().inMinMaxRange(0, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer numberOfRepayments = loan.getNumberOfRepayments();
|
Integer numberOfRepayments = loan.getNumberOfRepayments();
|
||||||
@@ -966,8 +969,8 @@ public final class LoanApplicationValidator {
|
|||||||
atLeastOneParameterPassedForUpdate = true;
|
atLeastOneParameterPassedForUpdate = true;
|
||||||
final Integer repaymentEveryType = this.fromApiJsonHelper
|
final Integer repaymentEveryType = this.fromApiJsonHelper
|
||||||
.extractIntegerWithLocaleNamed(LoanApiConstants.repaymentFrequencyTypeParameterName, element);
|
.extractIntegerWithLocaleNamed(LoanApiConstants.repaymentFrequencyTypeParameterName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.repaymentFrequencyTypeParameterName).value(repaymentEveryType).notNull()
|
baseDataValidator.reset().parameter(LoanApiConstants.repaymentFrequencyTypeParameterName).value(repaymentEveryType)
|
||||||
.inMinMaxRange(0, 3);
|
.notNull().inMinMaxRange(0, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
CalendarUtils.validateNthDayOfMonthFrequency(baseDataValidator, LoanApiConstants.repaymentFrequencyNthDayTypeParameterName,
|
CalendarUtils.validateNthDayOfMonthFrequency(baseDataValidator, LoanApiConstants.repaymentFrequencyNthDayTypeParameterName,
|
||||||
@@ -977,8 +980,8 @@ public final class LoanApplicationValidator {
|
|||||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.interestTypeParameterName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.interestTypeParameterName, element)) {
|
||||||
atLeastOneParameterPassedForUpdate = true;
|
atLeastOneParameterPassedForUpdate = true;
|
||||||
interestType = this.fromApiJsonHelper.extractIntegerWithLocaleNamed(LoanApiConstants.interestTypeParameterName, element);
|
interestType = this.fromApiJsonHelper.extractIntegerWithLocaleNamed(LoanApiConstants.interestTypeParameterName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.interestTypeParameterName).value(interestType).notNull().inMinMaxRange(0,
|
baseDataValidator.reset().parameter(LoanApiConstants.interestTypeParameterName).value(interestType).notNull()
|
||||||
1);
|
.inMinMaxRange(0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loanProduct.isLinkedToFloatingInterestRate()) {
|
if (loanProduct.isLinkedToFloatingInterestRate()) {
|
||||||
@@ -1022,7 +1025,8 @@ public final class LoanApplicationValidator {
|
|||||||
atLeastOneParameterPassedForUpdate = true;
|
atLeastOneParameterPassedForUpdate = true;
|
||||||
}
|
}
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.interestRateDifferentialParameterName).value(interestRateDifferential)
|
baseDataValidator.reset().parameter(LoanApiConstants.interestRateDifferentialParameterName).value(interestRateDifferential)
|
||||||
.notNull().zeroOrPositiveAmount().inMinAndMaxAmountRange(loanProduct.getFloatingRates().getMinDifferentialLendingRate(),
|
.notNull().zeroOrPositiveAmount()
|
||||||
|
.inMinAndMaxAmountRange(loanProduct.getFloatingRates().getMinDifferentialLendingRate(),
|
||||||
loanProduct.getFloatingRates().getMaxDifferentialLendingRate());
|
loanProduct.getFloatingRates().getMaxDifferentialLendingRate());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -1043,12 +1047,13 @@ public final class LoanApplicationValidator {
|
|||||||
this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(LoanApiConstants.interestRatePerPeriodParameterName, element);
|
this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(LoanApiConstants.interestRatePerPeriodParameterName, element);
|
||||||
atLeastOneParameterPassedForUpdate = true;
|
atLeastOneParameterPassedForUpdate = true;
|
||||||
}
|
}
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.interestRatePerPeriodParameterName).value(interestRatePerPeriod).notNull()
|
baseDataValidator.reset().parameter(LoanApiConstants.interestRatePerPeriodParameterName).value(interestRatePerPeriod)
|
||||||
.zeroOrPositiveAmount();
|
.notNull().zeroOrPositiveAmount();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer interestCalculationPeriodType = loanProduct.getLoanProductRelatedDetail().getInterestCalculationPeriodMethod().getValue();
|
Integer interestCalculationPeriodType = loanProduct.getLoanProductRelatedDetail().getInterestCalculationPeriodMethod()
|
||||||
|
.getValue();
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.interestCalculationPeriodTypeParameterName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.interestCalculationPeriodTypeParameterName, element)) {
|
||||||
atLeastOneParameterPassedForUpdate = true;
|
atLeastOneParameterPassedForUpdate = true;
|
||||||
@@ -1079,11 +1084,11 @@ public final class LoanApplicationValidator {
|
|||||||
|
|
||||||
final String expectedDisbursementDateStr = this.fromApiJsonHelper
|
final String expectedDisbursementDateStr = this.fromApiJsonHelper
|
||||||
.extractStringNamed(LoanApiConstants.expectedDisbursementDateParameterName, element);
|
.extractStringNamed(LoanApiConstants.expectedDisbursementDateParameterName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.expectedDisbursementDateParameterName).value(expectedDisbursementDateStr)
|
baseDataValidator.reset().parameter(LoanApiConstants.expectedDisbursementDateParameterName)
|
||||||
.notBlank();
|
.value(expectedDisbursementDateStr).notBlank();
|
||||||
|
|
||||||
expectedDisbursementDate = this.fromApiJsonHelper.extractLocalDateNamed(LoanApiConstants.expectedDisbursementDateParameterName,
|
expectedDisbursementDate = this.fromApiJsonHelper
|
||||||
element);
|
.extractLocalDateNamed(LoanApiConstants.expectedDisbursementDateParameterName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.expectedDisbursementDateParameterName).value(expectedDisbursementDate)
|
baseDataValidator.reset().parameter(LoanApiConstants.expectedDisbursementDateParameterName).value(expectedDisbursementDate)
|
||||||
.notNull();
|
.notNull();
|
||||||
}
|
}
|
||||||
@@ -1132,17 +1137,18 @@ public final class LoanApplicationValidator {
|
|||||||
atLeastOneParameterPassedForUpdate = true;
|
atLeastOneParameterPassedForUpdate = true;
|
||||||
final LocalDate repaymentsStartingFromDate = this.fromApiJsonHelper
|
final LocalDate repaymentsStartingFromDate = this.fromApiJsonHelper
|
||||||
.extractLocalDateNamed(LoanApiConstants.repaymentsStartingFromDateParameterName, element);
|
.extractLocalDateNamed(LoanApiConstants.repaymentsStartingFromDateParameterName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.repaymentsStartingFromDateParameterName).value(repaymentsStartingFromDate)
|
baseDataValidator.reset().parameter(LoanApiConstants.repaymentsStartingFromDateParameterName)
|
||||||
.ignoreIfNull();
|
.value(repaymentsStartingFromDate).ignoreIfNull();
|
||||||
if (!loan.getLoanTermVariations().isEmpty()) {
|
if (!loan.getLoanTermVariations().isEmpty()) {
|
||||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("cannot.modify.application.due.to.variable.installments");
|
baseDataValidator.reset()
|
||||||
|
.failWithCodeNoParameterAddedToErrorCode("cannot.modify.application.due.to.variable.installments");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.submittedOnDateParameterName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.submittedOnDateParameterName, element)) {
|
||||||
atLeastOneParameterPassedForUpdate = true;
|
atLeastOneParameterPassedForUpdate = true;
|
||||||
final LocalDate submittedOnDate = this.fromApiJsonHelper.extractLocalDateNamed(LoanApiConstants.submittedOnDateParameterName,
|
final LocalDate submittedOnDate = this.fromApiJsonHelper
|
||||||
element);
|
.extractLocalDateNamed(LoanApiConstants.submittedOnDateParameterName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.submittedOnDateParameterName).value(submittedOnDate).notNull();
|
baseDataValidator.reset().parameter(LoanApiConstants.submittedOnDateParameterName).value(submittedOnDate).notNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1293,7 +1299,8 @@ public final class LoanApplicationValidator {
|
|||||||
final Long loanIdToClose = command.longValueOfParameterNamed(LoanApiConstants.loanIdToClose);
|
final Long loanIdToClose = command.longValueOfParameterNamed(LoanApiConstants.loanIdToClose);
|
||||||
final Loan loanToClose = this.loanRepositoryWrapper.findNonClosedLoanThatBelongsToClient(loanIdToClose, clientId);
|
final Loan loanToClose = this.loanRepositoryWrapper.findNonClosedLoanThatBelongsToClient(loanIdToClose, clientId);
|
||||||
if (loanToClose == null) {
|
if (loanToClose == null) {
|
||||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.loanIdToClose.no.active.loan.associated.to.client.found",
|
throw new GeneralPlatformDomainRuleException(
|
||||||
|
"error.msg.loan.loanIdToClose.no.active.loan.associated.to.client.found",
|
||||||
"loanIdToClose is invalid, No Active Loan associated with the given Client ID found.");
|
"loanIdToClose is invalid, No Active Loan associated with the given Client ID found.");
|
||||||
}
|
}
|
||||||
if (loanToClose.isMultiDisburmentLoan() && !loanToClose.isInterestRecalculationEnabledForProduct()) {
|
if (loanToClose.isMultiDisburmentLoan() && !loanToClose.isInterestRecalculationEnabledForProduct()) {
|
||||||
@@ -1303,7 +1310,8 @@ public final class LoanApplicationValidator {
|
|||||||
}
|
}
|
||||||
final LocalDate disbursalDateOfLoanToClose = loanToClose.getDisbursementDate();
|
final LocalDate disbursalDateOfLoanToClose = loanToClose.getDisbursementDate();
|
||||||
if (!DateUtils.isAfter(submittedOnDate, disbursalDateOfLoanToClose)) {
|
if (!DateUtils.isAfter(submittedOnDate, disbursalDateOfLoanToClose)) {
|
||||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.submitted.date.should.be.after.topup.loan.disbursal.date",
|
throw new GeneralPlatformDomainRuleException(
|
||||||
|
"error.msg.loan.submitted.date.should.be.after.topup.loan.disbursal.date",
|
||||||
"Submitted date of this loan application " + submittedOnDate
|
"Submitted date of this loan application " + submittedOnDate
|
||||||
+ " should be after the disbursed date of loan to be closed " + disbursalDateOfLoanToClose);
|
+ " should be after the disbursed date of loan to be closed " + disbursalDateOfLoanToClose);
|
||||||
}
|
}
|
||||||
@@ -1316,10 +1324,12 @@ public final class LoanApplicationValidator {
|
|||||||
throw new GeneralPlatformDomainRuleException(
|
throw new GeneralPlatformDomainRuleException(
|
||||||
"error.msg.loan.disbursal.date.should.be.after.last.transaction.date.of.loan.to.be.closed",
|
"error.msg.loan.disbursal.date.should.be.after.last.transaction.date.of.loan.to.be.closed",
|
||||||
"Disbursal date of this loan application " + expectedDisbursementDate
|
"Disbursal date of this loan application " + expectedDisbursementDate
|
||||||
+ " should be after last transaction date of loan to be closed " + lastUserTransactionOnLoanToClose);
|
+ " should be after last transaction date of loan to be closed "
|
||||||
|
+ lastUserTransactionOnLoanToClose);
|
||||||
}
|
}
|
||||||
BigDecimal loanOutstanding = this.loanReadPlatformService
|
BigDecimal loanOutstanding = this.loanReadPlatformService
|
||||||
.retrieveLoanPrePaymentTemplate(LoanTransactionType.REPAYMENT, loanIdToClose, expectedDisbursementDate).getAmount();
|
.retrieveLoanPrePaymentTemplate(LoanTransactionType.REPAYMENT, loanIdToClose, expectedDisbursementDate)
|
||||||
|
.getAmount();
|
||||||
final BigDecimal firstDisbursalAmount = loan.getFirstDisbursalAmount();
|
final BigDecimal firstDisbursalAmount = loan.getFirstDisbursalAmount();
|
||||||
if (loanOutstanding.compareTo(firstDisbursalAmount) > 0) {
|
if (loanOutstanding.compareTo(firstDisbursalAmount) > 0) {
|
||||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.amount.less.than.outstanding.of.loan.to.be.closed",
|
throw new GeneralPlatformDomainRuleException("error.msg.loan.amount.less.than.outstanding.of.loan.to.be.closed",
|
||||||
@@ -1350,7 +1360,8 @@ public final class LoanApplicationValidator {
|
|||||||
List<LoanProductPaymentAllocationRule> allocationRules = loanProduct.getPaymentAllocationRules();
|
List<LoanProductPaymentAllocationRule> allocationRules = loanProduct.getPaymentAllocationRules();
|
||||||
|
|
||||||
if (LoanScheduleProcessingType.HORIZONTAL.name().equals(loanScheduleProcessingType)
|
if (LoanScheduleProcessingType.HORIZONTAL.name().equals(loanScheduleProcessingType)
|
||||||
&& AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY.equals(transactionProcessingStrategy)) {
|
&& AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY
|
||||||
|
.equals(transactionProcessingStrategy)) {
|
||||||
advancedPaymentAllocationsValidator.checkGroupingOfAllocationRules(allocationRules);
|
advancedPaymentAllocationsValidator.checkGroupingOfAllocationRules(allocationRules);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1387,11 +1398,7 @@ public final class LoanApplicationValidator {
|
|||||||
|
|
||||||
loanProductDataValidator.validateRepaymentPeriodWithGraceSettings(numberOfRepayments, graceOnPrincipalPayment,
|
loanProductDataValidator.validateRepaymentPeriodWithGraceSettings(numberOfRepayments, graceOnPrincipalPayment,
|
||||||
graceOnInterestPayment, graceOnInterestCharged, recurringMoratoriumOnPrincipalPeriods, baseDataValidator);
|
graceOnInterestPayment, graceOnInterestCharged, recurringMoratoriumOnPrincipalPeriods, baseDataValidator);
|
||||||
|
});
|
||||||
if (!dataValidationErrors.isEmpty()) {
|
|
||||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
|
||||||
dataValidationErrors);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateClientOrGroup(Client client, Group group, Long productId) {
|
private void validateClientOrGroup(Client client, Group group, Long productId) {
|
||||||
@@ -1448,8 +1455,7 @@ public final class LoanApplicationValidator {
|
|||||||
}.getType();
|
}.getType();
|
||||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, undoSupportedParameters);
|
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, undoSupportedParameters);
|
||||||
|
|
||||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
validateOrThrow(LOANAPPLICATION_UNDO, baseDataValidator -> {
|
||||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(LOANAPPLICATION_UNDO);
|
|
||||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||||
|
|
||||||
final String note = "note";
|
final String note = "note";
|
||||||
@@ -1457,17 +1463,11 @@ public final class LoanApplicationValidator {
|
|||||||
final String noteText = this.fromApiJsonHelper.extractStringNamed(note, element);
|
final String noteText = this.fromApiJsonHelper.extractStringNamed(note, element);
|
||||||
baseDataValidator.reset().parameter(note).value(noteText).notExceedingLengthOf(1000);
|
baseDataValidator.reset().parameter(note).value(noteText).notExceedingLengthOf(1000);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
if (!dataValidationErrors.isEmpty()) {
|
|
||||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validateMinMaxConstraintValues(final JsonElement element, final LoanProduct loanProduct) {
|
public void validateMinMaxConstraintValues(final JsonElement element, final LoanProduct loanProduct) {
|
||||||
|
validateOrThrow("loan", baseDataValidator -> {
|
||||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
|
||||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan");
|
|
||||||
|
|
||||||
final BigDecimal minPrincipal = loanProduct.getMinPrincipalAmount().getAmount();
|
final BigDecimal minPrincipal = loanProduct.getMinPrincipalAmount().getAmount();
|
||||||
final BigDecimal maxPrincipal = loanProduct.getMaxPrincipalAmount().getAmount();
|
final BigDecimal maxPrincipal = loanProduct.getMaxPrincipalAmount().getAmount();
|
||||||
final String principalParameterName = LoanApiConstants.principalParameterName;
|
final String principalParameterName = LoanApiConstants.principalParameterName;
|
||||||
@@ -1477,11 +1477,7 @@ public final class LoanApplicationValidator {
|
|||||||
baseDataValidator.reset().parameter(principalParameterName).value(principal).notNull().positiveAmount()
|
baseDataValidator.reset().parameter(principalParameterName).value(principal).notNull().positiveAmount()
|
||||||
.inMinAndMaxAmountRange(minPrincipal, maxPrincipal);
|
.inMinAndMaxAmountRange(minPrincipal, maxPrincipal);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
if (!dataValidationErrors.isEmpty()) {
|
|
||||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
|
||||||
dataValidationErrors);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateLoanTermAndRepaidEveryValues(final Integer loanTermFrequency, final Integer loanTermFrequencyType,
|
private void validateLoanTermAndRepaidEveryValues(final Integer loanTermFrequency, final Integer loanTermFrequencyType,
|
||||||
@@ -1490,10 +1486,10 @@ public final class LoanApplicationValidator {
|
|||||||
this.loanScheduleValidator.validateSelectedPeriodFrequencyTypeIsTheSame(dataValidationErrors, loanTermFrequency,
|
this.loanScheduleValidator.validateSelectedPeriodFrequencyTypeIsTheSame(dataValidationErrors, loanTermFrequency,
|
||||||
loanTermFrequencyType, numberOfRepayments, repaymentEvery, repaymentEveryType);
|
loanTermFrequencyType, numberOfRepayments, repaymentEvery, repaymentEveryType);
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* For multi-disbursal loans where schedules are auto-generated based on a fixed EMI, ensure the number of
|
* For multi-disbursal loans where schedules are auto-generated based on a fixed EMI, ensure the number of
|
||||||
* repayments is within the permissible range defined by the loan product
|
* repayments is within the permissible range defined by the loan product
|
||||||
**/
|
*/
|
||||||
// TODO: is this condition necessary?
|
// TODO: is this condition necessary?
|
||||||
if (loan.getFixedEmiAmount() != null) {
|
if (loan.getFixedEmiAmount() != null) {
|
||||||
Integer minimumNoOfRepayments = loan.loanProduct().getMinNumberOfRepayments();
|
Integer minimumNoOfRepayments = loan.loanProduct().getMinNumberOfRepayments();
|
||||||
@@ -1583,6 +1579,12 @@ public final class LoanApplicationValidator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void validateLoanMultiDisbursementDate(final JsonElement element, LocalDate expectedDisbursementDate, BigDecimal principal) {
|
||||||
|
validateOrThrow("loan", baseDataValidator -> {
|
||||||
|
validateLoanMultiDisbursementDate(element, baseDataValidator, expectedDisbursementDate, principal);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public void validateLoanMultiDisbursementDate(final JsonElement element, final DataValidatorBuilder baseDataValidator,
|
public void validateLoanMultiDisbursementDate(final JsonElement element, final DataValidatorBuilder baseDataValidator,
|
||||||
LocalDate expectedDisbursement, BigDecimal totalPrincipal) {
|
LocalDate expectedDisbursement, BigDecimal totalPrincipal) {
|
||||||
this.validateDisbursementsAreDatewiseOrdered(element, baseDataValidator);
|
this.validateDisbursementsAreDatewiseOrdered(element, baseDataValidator);
|
||||||
@@ -1648,23 +1650,16 @@ public final class LoanApplicationValidator {
|
|||||||
.integerSameAsNumber(InterestMethod.DECLINING_BALANCE.getValue());
|
.integerSameAsNumber(InterestMethod.DECLINING_BALANCE.getValue());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validateLoanForCollaterals(final Loan loan, final BigDecimal total) {
|
public void validateLoanForCollaterals(final Loan loan, final BigDecimal total) {
|
||||||
String errorCode;
|
validateOrThrow("loan", baseDataValidator -> {
|
||||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
|
||||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan");
|
|
||||||
if (loan.getProposedPrincipal().compareTo(total) >= 0) {
|
if (loan.getProposedPrincipal().compareTo(total) >= 0) {
|
||||||
errorCode = LoanApiConstants.LOAN_COLLATERAL_TOTAL_VALUE_SHOULD_BE_SUFFICIENT;
|
String errorCode = LoanApiConstants.LOAN_COLLATERAL_TOTAL_VALUE_SHOULD_BE_SUFFICIENT;
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.collateralsParameterName).failWithCode(errorCode);
|
baseDataValidator.reset().parameter(LoanApiConstants.collateralsParameterName).failWithCode(errorCode);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
if (!dataValidationErrors.isEmpty()) {
|
|
||||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validatePartialPeriodSupport(final Integer interestCalculationPeriodType, final DataValidatorBuilder baseDataValidator,
|
private void validatePartialPeriodSupport(final Integer interestCalculationPeriodType, final DataValidatorBuilder baseDataValidator,
|
||||||
@@ -1876,4 +1871,44 @@ public final class LoanApplicationValidator {
|
|||||||
}.getType();
|
}.getType();
|
||||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, SUPPORTED_PARAMETERS);
|
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, SUPPORTED_PARAMETERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void validateTopupLoan(Loan loan, LocalDate expectedDisbursementDate) {
|
||||||
|
final Long loanIdToClose = loan.getTopupLoanDetails().getLoanIdToClose();
|
||||||
|
final Loan loanToClose = loanRepositoryWrapper.findNonClosedLoanThatBelongsToClient(loanIdToClose, loan.getClientId());
|
||||||
|
if (loanToClose == null) {
|
||||||
|
throw new GeneralPlatformDomainRuleException("error.msg.loan.to.be.closed.with.topup.is.not.active",
|
||||||
|
"Loan to be closed with this topup is not active.");
|
||||||
|
}
|
||||||
|
|
||||||
|
final LocalDate lastUserTransactionOnLoanToClose = loanToClose.getLastUserTransactionDate();
|
||||||
|
if (DateUtils.isBefore(loan.getDisbursementDate(), lastUserTransactionOnLoanToClose)) {
|
||||||
|
throw new GeneralPlatformDomainRuleException(
|
||||||
|
"error.msg.loan.disbursal.date.should.be.after.last.transaction.date.of.loan.to.be.closed",
|
||||||
|
"Disbursal date of this loan application " + loan.getDisbursementDate()
|
||||||
|
+ " should be after last transaction date of loan to be closed " + lastUserTransactionOnLoanToClose);
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimal loanOutstanding = loanReadPlatformService
|
||||||
|
.retrieveLoanPrePaymentTemplate(LoanTransactionType.REPAYMENT, loanIdToClose, expectedDisbursementDate).getAmount();
|
||||||
|
final BigDecimal firstDisbursalAmount = loan.getFirstDisbursalAmount();
|
||||||
|
if (loanOutstanding.compareTo(firstDisbursalAmount) > 0) {
|
||||||
|
throw new GeneralPlatformDomainRuleException("error.msg.loan.amount.less.than.outstanding.of.loan.to.be.closed",
|
||||||
|
"Topup loan amount should be greater than outstanding amount of loan to be closed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimal netDisbursalAmount = loan.getApprovedPrincipal().subtract(loanOutstanding);
|
||||||
|
loan.adjustNetDisbursalAmount(netDisbursalAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void validateOrThrow(String resource, Consumer<DataValidatorBuilder> baseDataValidator) {
|
||||||
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||||
|
final DataValidatorBuilder dataValidatorBuilder = new DataValidatorBuilder(dataValidationErrors).resource(resource);
|
||||||
|
|
||||||
|
baseDataValidator.accept(dataValidatorBuilder);
|
||||||
|
|
||||||
|
if (!dataValidationErrors.isEmpty()) {
|
||||||
|
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||||
|
dataValidationErrors);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-16
@@ -18,6 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.portfolio.loanaccount.service;
|
package org.apache.fineract.portfolio.loanaccount.service;
|
||||||
|
|
||||||
|
import static org.apache.fineract.portfolio.loanproduct.domain.RecalculationFrequencyType.SAME_AS_REPAYMENT_PERIOD;
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
@@ -236,28 +238,21 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
|||||||
private void createCalendar(final Loan loan, LocalDate calendarStartDate, Integer recalculationFrequencyNthDay,
|
private void createCalendar(final Loan loan, LocalDate calendarStartDate, Integer recalculationFrequencyNthDay,
|
||||||
final Integer repeatsOnDay, final RecalculationFrequencyType recalculationFrequencyType, Integer frequency,
|
final Integer repeatsOnDay, final RecalculationFrequencyType recalculationFrequencyType, Integer frequency,
|
||||||
CalendarEntityType calendarEntityType, final String title) {
|
CalendarEntityType calendarEntityType, final String title) {
|
||||||
CalendarFrequencyType calendarFrequencyType = CalendarFrequencyType.INVALID;
|
|
||||||
Integer updatedRepeatsOnDay = repeatsOnDay;
|
Integer updatedRepeatsOnDay = repeatsOnDay;
|
||||||
switch (recalculationFrequencyType) {
|
final CalendarFrequencyType calendarFrequencyType = switch (recalculationFrequencyType) {
|
||||||
case DAILY:
|
case DAILY -> CalendarFrequencyType.DAILY;
|
||||||
calendarFrequencyType = CalendarFrequencyType.DAILY;
|
case WEEKLY -> CalendarFrequencyType.WEEKLY;
|
||||||
break;
|
case MONTHLY -> CalendarFrequencyType.MONTHLY;
|
||||||
case MONTHLY:
|
case SAME_AS_REPAYMENT_PERIOD -> CalendarFrequencyType.from(loan.repaymentScheduleDetail().getRepaymentPeriodFrequencyType());
|
||||||
calendarFrequencyType = CalendarFrequencyType.MONTHLY;
|
case INVALID -> CalendarFrequencyType.INVALID;
|
||||||
break;
|
};
|
||||||
case SAME_AS_REPAYMENT_PERIOD:
|
|
||||||
|
if (recalculationFrequencyType == SAME_AS_REPAYMENT_PERIOD) {
|
||||||
frequency = loan.repaymentScheduleDetail().getRepayEvery();
|
frequency = loan.repaymentScheduleDetail().getRepayEvery();
|
||||||
calendarFrequencyType = CalendarFrequencyType.from(loan.repaymentScheduleDetail().getRepaymentPeriodFrequencyType());
|
|
||||||
calendarStartDate = loan.getExpectedDisbursedOnLocalDate();
|
calendarStartDate = loan.getExpectedDisbursedOnLocalDate();
|
||||||
if (updatedRepeatsOnDay == null) {
|
if (updatedRepeatsOnDay == null) {
|
||||||
updatedRepeatsOnDay = calendarStartDate.get(ChronoField.DAY_OF_WEEK);
|
updatedRepeatsOnDay = calendarStartDate.get(ChronoField.DAY_OF_WEEK);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case WEEKLY:
|
|
||||||
calendarFrequencyType = CalendarFrequencyType.WEEKLY;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final Calendar calendar = Calendar.createRepeatingCalendar(title, calendarStartDate, CalendarType.COLLECTION.getValue(),
|
final Calendar calendar = Calendar.createRepeatingCalendar(title, calendarStartDate, CalendarType.COLLECTION.getValue(),
|
||||||
|
|||||||
+6
-2
@@ -971,11 +971,15 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
|||||||
final String defaultUserMessage = "Installment charge cannot be added to the loan.";
|
final String defaultUserMessage = "Installment charge cannot be added to the loan.";
|
||||||
throw new LoanChargeCannotBeAddedException("loanCharge", "overdue.charge", defaultUserMessage, null,
|
throw new LoanChargeCannotBeAddedException("loanCharge", "overdue.charge", defaultUserMessage, null,
|
||||||
chargeDefinition.getName());
|
chargeDefinition.getName());
|
||||||
} else if (loanCharge.getDueLocalDate() != null
|
} else if (loanCharge.getDueLocalDate() != null) {
|
||||||
&& DateUtils.isBefore(loanCharge.getDueLocalDate(), loan.getLastUserTransactionForChargeCalc())) {
|
// TODO: Review, error message seems not valid if interest recalculation is not enabled.
|
||||||
|
LocalDate validationDate = loan.repaymentScheduleDetail().isInterestRecalculationEnabled() ? loan.getLastUserTransactionDate()
|
||||||
|
: loan.getDisbursementDate();
|
||||||
|
if (DateUtils.isBefore(loanCharge.getDueLocalDate(), validationDate)) {
|
||||||
final String defaultUserMessage = "charge with date before last transaction date can not be added to loan.";
|
final String defaultUserMessage = "charge with date before last transaction date can not be added to loan.";
|
||||||
throw new LoanChargeCannotBeAddedException("loanCharge", "date.is.before.last.transaction.date", defaultUserMessage, null,
|
throw new LoanChargeCannotBeAddedException("loanCharge", "date.is.before.last.transaction.date", defaultUserMessage, null,
|
||||||
chargeDefinition.getName());
|
chargeDefinition.getName());
|
||||||
|
}
|
||||||
} else if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
} else if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
||||||
if (loanCharge.isInstalmentFee() && loan.getStatus().isActive()) {
|
if (loanCharge.isInstalmentFee() && loan.getStatus().isActive()) {
|
||||||
final String defaultUserMessage = "installment charge addition not allowed after disbursement";
|
final String defaultUserMessage = "installment charge addition not allowed after disbursement";
|
||||||
|
|||||||
Reference in New Issue
Block a user