diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanTransactionValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanTransactionValidator.java index 4ff6935bc06..0ff728f1162 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanTransactionValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanTransactionValidator.java @@ -72,6 +72,7 @@ import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException; import org.apache.fineract.portfolio.loanaccount.exception.LoanRepaymentScheduleNotFoundException; import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService; +import org.jetbrains.annotations.NotNull; import org.springframework.stereotype.Component; @Component @@ -91,13 +92,50 @@ private void throwExceptionIfValidationWarningsExist(final List disbursementParameters = null; + final Type typeOfMap = new TypeToken>() { + }.getType(); + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, getDisbursementParameters(isAccountTransfer)); + + LoanApplicationValidator.validateOrThrow("loan.disbursement", baseDataValidator -> { + final JsonElement element = this.fromApiJsonHelper.parse(json); + final LocalDate actualDisbursementDate = this.fromApiJsonHelper.extractLocalDateNamed("actualDisbursementDate", element); + baseDataValidator.reset().parameter("actualDisbursementDate").value(actualDisbursementDate).notNull(); + + final String note = this.fromApiJsonHelper.extractStringNamed("note", element); + baseDataValidator.reset().parameter("note").value(note).notExceedingLengthOf(1000); + + final BigDecimal principal = this.fromApiJsonHelper + .extractBigDecimalWithLocaleNamed(LoanApiConstants.principalDisbursedParameterName, element); + baseDataValidator.reset().parameter(LoanApiConstants.principalDisbursedParameterName).value(principal).ignoreIfNull() + .positiveAmount(); + + final BigDecimal netDisbursalAmount = this.fromApiJsonHelper + .extractBigDecimalWithLocaleNamed(LoanApiConstants.disbursementNetDisbursalAmountParameterName, element); + baseDataValidator.reset().parameter(LoanApiConstants.disbursementNetDisbursalAmountParameterName).value(netDisbursalAmount) + .ignoreIfNull().positiveAmount(); + + final BigDecimal emiAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(LoanApiConstants.fixedEmiAmountParameterName, + element); + baseDataValidator.reset().parameter(LoanApiConstants.fixedEmiAmountParameterName).value(emiAmount).ignoreIfNull().positiveAmount() + .notGreaterThanMax(principal); + + validatePaymentDetails(baseDataValidator, element); + + if (command.parameterExists("postDatedChecks")) { + // validate with post dated checks for the disbursement + this.validateDisbursementWithPostDatedChecks(command.json(), loanId); + } + }); + } + + private static @NotNull Set getDisbursementParameters(boolean isAccountTransfer) { + Set disbursementParameters; if (isAccountTransfer) { disbursementParameters = new HashSet<>(Arrays.asList("actualDisbursementDate", "externalId", "note", "locale", "dateFormat", @@ -109,38 +147,7 @@ public void validateDisbursement(final String json, boolean isAccountTransfer) { LoanApiConstants.principalDisbursedParameterName, LoanApiConstants.fixedEmiAmountParameterName, LoanApiConstants.postDatedChecks, LoanApiConstants.disbursementNetDisbursalAmountParameterName)); } - - final Type typeOfMap = new TypeToken>() {}.getType(); - this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters); - - final List dataValidationErrors = new ArrayList<>(); - final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan.disbursement"); - - final JsonElement element = this.fromApiJsonHelper.parse(json); - final LocalDate actualDisbursementDate = this.fromApiJsonHelper.extractLocalDateNamed("actualDisbursementDate", element); - baseDataValidator.reset().parameter("actualDisbursementDate").value(actualDisbursementDate).notNull(); - - final String note = this.fromApiJsonHelper.extractStringNamed("note", element); - baseDataValidator.reset().parameter("note").value(note).notExceedingLengthOf(1000); - - final BigDecimal principal = this.fromApiJsonHelper - .extractBigDecimalWithLocaleNamed(LoanApiConstants.principalDisbursedParameterName, element); - baseDataValidator.reset().parameter(LoanApiConstants.principalDisbursedParameterName).value(principal).ignoreIfNull() - .positiveAmount(); - - final BigDecimal netDisbursalAmount = this.fromApiJsonHelper - .extractBigDecimalWithLocaleNamed(LoanApiConstants.disbursementNetDisbursalAmountParameterName, element); - baseDataValidator.reset().parameter(LoanApiConstants.disbursementNetDisbursalAmountParameterName).value(netDisbursalAmount) - .ignoreIfNull().positiveAmount(); - - final BigDecimal emiAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(LoanApiConstants.fixedEmiAmountParameterName, - element); - baseDataValidator.reset().parameter(LoanApiConstants.fixedEmiAmountParameterName).value(emiAmount).ignoreIfNull().positiveAmount() - .notGreaterThanMax(principal); - - validatePaymentDetails(baseDataValidator, element); - - throwExceptionIfValidationWarningsExist(dataValidationErrors); + return disbursementParameters; } public void validateDisbursementWithPostDatedChecks(final String json, final Long loanId) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 0040243bfe5..13f8b2630d1 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -291,15 +291,7 @@ public CommandProcessingResult disburseLoan(Long loanId, JsonCommand command, Bo @Override public CommandProcessingResult disburseLoan(final Long loanId, final JsonCommand command, Boolean isAccountTransfer, Boolean isWithoutAutoPayment) { - - final AppUser currentUser = getAppUserIfPresent(); - - this.loanTransactionValidator.validateDisbursement(command.json(), isAccountTransfer); - - if (command.parameterExists("postDatedChecks")) { - // validate with post dated checks for the disbursement - this.loanTransactionValidator.validateDisbursementWithPostDatedChecks(command.json(), loanId); - } + this.loanTransactionValidator.validateDisbursement(command, isAccountTransfer, loanId); Loan loan = this.loanAssembler.assembleFrom(loanId); // Fail fast if client/group is not active or actual loan status disallows disbursal @@ -337,7 +329,6 @@ public CommandProcessingResult disburseLoan(final Long loanId, final JsonCommand // Get relevant loan collateral modules if ((loanCollateralManagements != null && !loanCollateralManagements.isEmpty()) && loan.getLoanType().isIndividualAccount()) { - BigDecimal totalCollateral = BigDecimal.valueOf(0); for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagements) { @@ -384,6 +375,7 @@ public CommandProcessingResult disburseLoan(final Long loanId, final JsonCommand final List existingTransactionIds = new ArrayList<>(); final List existingReversedTransactionIds = new ArrayList<>(); + final AppUser currentUser = getAppUserIfPresent(); final Map changes = new LinkedHashMap<>(); final PaymentDetail paymentDetail = this.paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, changes);