FINERACT-1515 Allow multi-disbursements without setting up expected tranche details
This commit is contained in:
committed by
Aleksandar Vidakovic
parent
2bb8ae2f16
commit
de64de876c
+88
-36
@@ -121,6 +121,7 @@ import org.apache.fineract.portfolio.loanaccount.exception.LoanForeclosureExcept
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanOfficerAssignmentDateException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanOfficerAssignmentException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanOfficerUnassignmentDateException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.MultiDisbursementDataNotAllowedException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.MultiDisbursementDataRequiredException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.UndoLastTrancheDisbursementException;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleDTO;
|
||||
@@ -1330,8 +1331,10 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
public void updateLoanScheduleDependentDerivedFields() {
|
||||
this.expectedMaturityDate = Date.from(determineExpectedMaturityDate().atStartOfDay(ZoneId.systemDefault()).toInstant());
|
||||
this.actualMaturityDate = Date.from(determineExpectedMaturityDate().atStartOfDay(ZoneId.systemDefault()).toInstant());
|
||||
if (this.getLoanRepaymentScheduleInstallmentsSize() > 0) {
|
||||
this.expectedMaturityDate = Date.from(determineExpectedMaturityDate().atStartOfDay(ZoneId.systemDefault()).toInstant());
|
||||
this.actualMaturityDate = Date.from(determineExpectedMaturityDate().atStartOfDay(ZoneId.systemDefault()).toInstant());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLoanSummaryDerivedFields() {
|
||||
@@ -1620,9 +1623,16 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
final JsonArray disbursementDataArray = command.arrayOfParameterNamed(LoanApiConstants.disbursementDataParameterName);
|
||||
|
||||
if (disbursementDataArray == null || disbursementDataArray.size() == 0) {
|
||||
final String errorMessage = "For this loan product, disbursement details must be provided";
|
||||
throw new MultiDisbursementDataRequiredException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
||||
if (loanProduct.isDisallowExpectedDisbursements()) {
|
||||
if (disbursementDataArray != null) {
|
||||
final String errorMessage = "For this loan product, disbursement details are not allowed";
|
||||
throw new MultiDisbursementDataNotAllowedException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
||||
}
|
||||
} else {
|
||||
if (disbursementDataArray == null || disbursementDataArray.size() == 0) {
|
||||
final String errorMessage = "For this loan product, disbursement details must be provided";
|
||||
throw new MultiDisbursementDataRequiredException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
||||
}
|
||||
}
|
||||
if (disbursementDataArray.size() > loanProduct.maxTrancheCount()) {
|
||||
final String errorMessage = "Number of tranche shouldn't be greter than " + loanProduct.maxTrancheCount();
|
||||
@@ -2224,31 +2234,19 @@ public class Loan extends AbstractPersistableCustom {
|
||||
LocalDate expecteddisbursementDate = command.localDateValueOfParameterNamed("expectedDisbursementDate");
|
||||
|
||||
BigDecimal approvedLoanAmount = command.bigDecimalValueOfParameterNamed(LoanApiConstants.approvedLoanAmountParameterName);
|
||||
|
||||
if (approvedLoanAmount != null) {
|
||||
compareApprovedToProposedPrincipal(approvedLoanAmount);
|
||||
|
||||
// Approved amount has to be less than or equal to principal
|
||||
// amount demanded
|
||||
/*
|
||||
* All the calculations are done based on the principal amount, so it is necessary to set principal
|
||||
* amount to approved amount
|
||||
*/
|
||||
this.approvedPrincipal = approvedLoanAmount;
|
||||
|
||||
if (approvedLoanAmount.compareTo(this.proposedPrincipal) < 0) {
|
||||
|
||||
this.approvedPrincipal = approvedLoanAmount;
|
||||
|
||||
/*
|
||||
* All the calculations are done based on the principal amount, so it is necessary to set principal
|
||||
* amount to approved amount
|
||||
*/
|
||||
|
||||
this.loanRepaymentScheduleDetail.setPrincipal(approvedLoanAmount);
|
||||
|
||||
actualChanges.put(LoanApiConstants.approvedLoanAmountParameterName, approvedLoanAmount);
|
||||
actualChanges.put(LoanApiConstants.disbursementPrincipalParameterName, approvedLoanAmount);
|
||||
actualChanges.put(LoanApiConstants.disbursementNetDisbursalAmountParameterName, netDisbursalAmount);
|
||||
} else if (approvedLoanAmount.compareTo(this.proposedPrincipal) > 0) {
|
||||
final String errorMessage = "Loan approved amount can't be greater than loan amount demanded.";
|
||||
throw new InvalidLoanStateTransitionException("approval", "amount.can't.be.greater.than.loan.amount.demanded",
|
||||
errorMessage, this.proposedPrincipal, approvedLoanAmount);
|
||||
}
|
||||
this.loanRepaymentScheduleDetail.setPrincipal(approvedLoanAmount);
|
||||
actualChanges.put(LoanApiConstants.approvedLoanAmountParameterName, approvedLoanAmount);
|
||||
actualChanges.put(LoanApiConstants.disbursementPrincipalParameterName, approvedLoanAmount);
|
||||
actualChanges.put(LoanApiConstants.disbursementNetDisbursalAmountParameterName, netDisbursalAmount);
|
||||
|
||||
/* Update disbursement details */
|
||||
if (disbursementDataArray != null) {
|
||||
@@ -2259,10 +2257,16 @@ public class Loan extends AbstractPersistableCustom {
|
||||
recalculateAllCharges();
|
||||
|
||||
if (loanProduct.isMultiDisburseLoan()) {
|
||||
|
||||
if (this.disbursementDetails.isEmpty()) {
|
||||
final String errorMessage = "For this loan product, disbursement details must be provided";
|
||||
throw new MultiDisbursementDataRequiredException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
||||
if (loanProduct.isDisallowExpectedDisbursements()) {
|
||||
if (!disbursementDetails.isEmpty()) {
|
||||
final String errorMessage = "For this loan product, disbursement details are not allowed";
|
||||
throw new MultiDisbursementDataNotAllowedException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
||||
}
|
||||
} else {
|
||||
if (disbursementDetails.isEmpty()) {
|
||||
final String errorMessage = "For this loan product, disbursement details must be provided";
|
||||
throw new MultiDisbursementDataRequiredException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.disbursementDetails.size() > loanProduct.maxTrancheCount()) {
|
||||
@@ -2313,6 +2317,39 @@ public class Loan extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
|
||||
}
|
||||
|
||||
private void compareApprovedToProposedPrincipal(BigDecimal approvedLoanAmount) {
|
||||
|
||||
if (this.loanProduct().isDisallowExpectedDisbursements() && this.loanProduct().isAllowApprovedDisbursedAmountsOverApplied()) {
|
||||
BigDecimal maxApprovedLoanAmount = getOverAppliedMax();
|
||||
if (approvedLoanAmount.compareTo(maxApprovedLoanAmount) > 0) {
|
||||
final String errorMessage = "Loan approved amount can't be greater than maximum applied loan amount calculation.";
|
||||
throw new InvalidLoanStateTransitionException("approval",
|
||||
"amount.can't.be.greater.than.maximum.applied.loan.amount.calculation", errorMessage, approvedLoanAmount,
|
||||
maxApprovedLoanAmount);
|
||||
}
|
||||
} else {
|
||||
if (approvedLoanAmount.compareTo(this.proposedPrincipal) > 0) {
|
||||
final String errorMessage = "Loan approved amount can't be greater than loan amount demanded.";
|
||||
throw new InvalidLoanStateTransitionException("approval", "amount.can't.be.greater.than.loan.amount.demanded", errorMessage,
|
||||
this.proposedPrincipal, approvedLoanAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal getOverAppliedMax() {
|
||||
BigDecimal maxAmount = null;
|
||||
if (this.getLoanProduct().getOverAppliedCalculationType().equals("percentage")) {
|
||||
BigDecimal overAppliedNumber = BigDecimal.valueOf(getLoanProduct().getOverAppliedNumber());
|
||||
BigDecimal x = overAppliedNumber.divide(BigDecimal.valueOf(100));
|
||||
BigDecimal totalPercentage = BigDecimal.valueOf(1).add(x);
|
||||
maxAmount = this.proposedPrincipal.multiply(totalPercentage);
|
||||
} else {
|
||||
maxAmount = this.proposedPrincipal.add(BigDecimal.valueOf(getLoanProduct().getOverAppliedNumber()));
|
||||
}
|
||||
return maxAmount;
|
||||
}
|
||||
|
||||
public Map<String, Object> undoApproval(final LoanLifecycleStateMachine loanLifecycleStateMachine) {
|
||||
@@ -2542,11 +2579,7 @@ public class Loan extends AbstractPersistableCustom {
|
||||
totalAmount = totalAmount.add(disbursementDetails.principal());
|
||||
}
|
||||
this.loanRepaymentScheduleDetail.setPrincipal(setPrincipalAmount);
|
||||
if (totalAmount.compareTo(this.approvedPrincipal) > 0) {
|
||||
final String errorMsg = "Loan can't be disbursed,disburse amount is exceeding approved principal ";
|
||||
throw new LoanDisbursalException(errorMsg, "disburse.amount.must.be.less.than.approved.principal", principalDisbursed,
|
||||
this.approvedPrincipal);
|
||||
}
|
||||
compareDisbursedToApprovedOrProposedPrincipal(disburseAmount.getAmount(), totalAmount);
|
||||
} else {
|
||||
this.loanRepaymentScheduleDetail.setPrincipal(this.loanRepaymentScheduleDetail.getPrincipal().minus(diff).getAmount());
|
||||
}
|
||||
@@ -2559,6 +2592,25 @@ public class Loan extends AbstractPersistableCustom {
|
||||
return disburseAmount;
|
||||
}
|
||||
|
||||
private void compareDisbursedToApprovedOrProposedPrincipal(BigDecimal disbursedAmount, BigDecimal totalDisbursed) {
|
||||
|
||||
if (this.loanProduct().isDisallowExpectedDisbursements() && this.loanProduct().isAllowApprovedDisbursedAmountsOverApplied()) {
|
||||
BigDecimal maxDisbursedAmount = getOverAppliedMax();
|
||||
if (disbursedAmount.compareTo(maxDisbursedAmount) > 0) {
|
||||
final String errorMessage = "Loan disbursal amount can't be greater than maximum applied loan amount calculation.";
|
||||
throw new InvalidLoanStateTransitionException("disbursal",
|
||||
"amount.can't.be.greater.than.maximum.applied.loan.amount.calculation", errorMessage, disbursedAmount,
|
||||
maxDisbursedAmount);
|
||||
}
|
||||
} else {
|
||||
if (totalDisbursed.compareTo(this.approvedPrincipal) > 0) {
|
||||
final String errorMsg = "Loan can't be disbursed,disburse amount is exceeding approved principal ";
|
||||
throw new LoanDisbursalException(errorMsg, "disburse.amount.must.be.less.than.approved.principal", totalDisbursed,
|
||||
this.approvedPrincipal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ChangedTransactionDetail reprocessTransactionForDisbursement() {
|
||||
ChangedTransactionDetail changedTransactionDetail = null;
|
||||
if (this.loanProduct.isMultiDisburseLoan()) {
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.portfolio.loanaccount.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class MultiDisbursementDataNotAllowedException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public MultiDisbursementDataNotAllowedException(final String entity, final String defaultUserMessage,
|
||||
final Object... defaultUserMessageArgs) {
|
||||
super("error.msg." + entity + ".not.allowed", defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
|
||||
}
|
||||
+13
-4
@@ -75,6 +75,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionProcessin
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.ExceedingTrancheCountException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.InvalidAmountOfCollaterals;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanTransactionProcessingStrategyNotFoundException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.MultiDisbursementDataNotAllowedException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.MultiDisbursementDataRequiredException;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
|
||||
@@ -200,13 +201,21 @@ public class LoanAssembler {
|
||||
}
|
||||
BigDecimal maxOutstandingLoanBalance = null;
|
||||
if (loanProduct.isMultiDisburseLoan()) {
|
||||
disbursementDetails = this.loanUtilService.fetchDisbursementData(element.getAsJsonObject());
|
||||
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(element.getAsJsonObject());
|
||||
maxOutstandingLoanBalance = this.fromApiJsonHelper.extractBigDecimalNamed(LoanApiConstants.maxOutstandingBalanceParameterName,
|
||||
element, locale);
|
||||
if (disbursementDetails.isEmpty()) {
|
||||
final String errorMessage = "For this loan product, disbursement details must be provided";
|
||||
throw new MultiDisbursementDataRequiredException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
||||
|
||||
disbursementDetails = this.loanUtilService.fetchDisbursementData(element.getAsJsonObject());
|
||||
if (loanProduct.isDisallowExpectedDisbursements()) {
|
||||
if (!disbursementDetails.isEmpty()) {
|
||||
final String errorMessage = "For this loan product, disbursement details are not allowed";
|
||||
throw new MultiDisbursementDataNotAllowedException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
||||
}
|
||||
} else {
|
||||
if (disbursementDetails.isEmpty()) {
|
||||
final String errorMessage = "For this loan product, disbursement details must be provided";
|
||||
throw new MultiDisbursementDataRequiredException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
if (disbursementDetails.size() > loanProduct.maxTrancheCount()) {
|
||||
|
||||
+36
-8
@@ -173,6 +173,7 @@ import org.apache.fineract.portfolio.loanaccount.exception.LoanMultiDisbursement
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanOfficerAssignmentException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanOfficerUnassignmentException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanTransactionNotFoundException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.MultiDisbursementDataNotAllowedException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.MultiDisbursementDataRequiredException;
|
||||
import org.apache.fineract.portfolio.loanaccount.guarantor.service.GuarantorDomainService;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.OverdueLoanScheduleData;
|
||||
@@ -373,6 +374,16 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
|
||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
if (loan.loanProduct().isDisallowExpectedDisbursements()) {
|
||||
// create artificial 'tranche/expected disbursal' as current disburse code expects it for multi-disbursal
|
||||
// products
|
||||
final Date artificialExpectedDate = Date
|
||||
.from(loan.getExpectedDisbursedOnLocalDate().atStartOfDay(ZoneId.systemDefault()).toInstant());
|
||||
LoanDisbursementDetails disbursementDetail = new LoanDisbursementDetails(artificialExpectedDate, null,
|
||||
loan.getDisbursedAmount(), null);
|
||||
disbursementDetail.updateLoan(loan);
|
||||
loan.getDisbursementDetails().add(disbursementDetail);
|
||||
}
|
||||
|
||||
// Get disbursedAmount
|
||||
final BigDecimal disbursedAmount = loan.getDisbursedAmount();
|
||||
@@ -2900,17 +2911,27 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
.build();
|
||||
}
|
||||
|
||||
private void validateMultiDisbursementData(final JsonCommand command, LocalDate expectedDisbursementDate) {
|
||||
private void validateMultiDisbursementData(final JsonCommand command, LocalDate expectedDisbursementDate,
|
||||
boolean isDisallowExpectedDisbursements) {
|
||||
final String json = command.json();
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan");
|
||||
final JsonArray disbursementDataArray = command.arrayOfParameterNamed(LoanApiConstants.disbursementDataParameterName);
|
||||
if (disbursementDataArray == null || disbursementDataArray.size() == 0) {
|
||||
final String errorMessage = "For this loan product, disbursement details must be provided";
|
||||
throw new MultiDisbursementDataRequiredException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
||||
|
||||
if (isDisallowExpectedDisbursements) {
|
||||
if (disbursementDataArray != null) {
|
||||
final String errorMessage = "For this loan product, disbursement details are not allowed";
|
||||
throw new MultiDisbursementDataNotAllowedException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
||||
}
|
||||
} else {
|
||||
if (disbursementDataArray == null || disbursementDataArray.size() == 0) {
|
||||
final String errorMessage = "For this loan product, disbursement details must be provided";
|
||||
throw new MultiDisbursementDataRequiredException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
final BigDecimal principal = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("approvedLoanAmount", element);
|
||||
|
||||
loanApplicationCommandFromApiJsonHelper.validateLoanMultiDisbursementDate(element, baseDataValidator, expectedDisbursementDate,
|
||||
@@ -2952,15 +2973,22 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final String errorMessage = "cannot.modify.tranches.if.loan.is.pendingapproval.closed.overpaid.writtenoff";
|
||||
throw new LoanMultiDisbursementException(errorMessage);
|
||||
}
|
||||
validateMultiDisbursementData(command, expectedDisbursementDate);
|
||||
validateMultiDisbursementData(command, expectedDisbursementDate, loan.loanProduct().isDisallowExpectedDisbursements());
|
||||
|
||||
this.validateForAddAndDeleteTranche(loan);
|
||||
|
||||
loan.updateDisbursementDetails(command, actualChanges);
|
||||
|
||||
if (loan.getDisbursementDetails().isEmpty()) {
|
||||
final String errorMessage = "For this loan product, disbursement details must be provided";
|
||||
throw new MultiDisbursementDataRequiredException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
||||
if (loan.loanProduct().isDisallowExpectedDisbursements()) {
|
||||
if (!loan.getDisbursementDetails().isEmpty()) {
|
||||
final String errorMessage = "For this loan product, disbursement details are not allowed";
|
||||
throw new MultiDisbursementDataNotAllowedException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
||||
}
|
||||
} else {
|
||||
if (loan.getDisbursementDetails().isEmpty()) {
|
||||
final String errorMessage = "For this loan product, disbursement details must be provided";
|
||||
throw new MultiDisbursementDataRequiredException(LoanApiConstants.disbursementDataParameterName, errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
if (loan.getDisbursementDetails().size() > loan.loanProduct().maxTrancheCount()) {
|
||||
|
||||
+28
@@ -191,6 +191,18 @@ public class LoanProduct extends AbstractPersistableCustom {
|
||||
@Column(name = "fixed_principal_percentage_per_installment", scale = 2, precision = 5, nullable = true)
|
||||
private BigDecimal fixedPrincipalPercentagePerInstallment;
|
||||
|
||||
@Column(name = "disallow_expected_disbursements", nullable = false)
|
||||
private boolean disallowExpectedDisbursements;
|
||||
|
||||
@Column(name = "allow_approved_disbursed_amounts_over_applied", nullable = false)
|
||||
private boolean allowApprovedDisbursedAmountsOverApplied;
|
||||
|
||||
@Column(name = "over_applied_calculation_type", nullable = true)
|
||||
private String overAppliedCalculationType;
|
||||
|
||||
@Column(name = "over_applied_number", nullable = true)
|
||||
private Integer overAppliedNumber;
|
||||
|
||||
public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy,
|
||||
final List<Charge> productCharges, final JsonCommand command, final AprCalculator aprCalculator, FloatingRate floatingRate,
|
||||
final List<Rate> productRates) {
|
||||
@@ -1461,4 +1473,20 @@ public class LoanProduct extends AbstractPersistableCustom {
|
||||
public BigDecimal getFixedPrincipalPercentagePerInstallment() {
|
||||
return fixedPrincipalPercentagePerInstallment;
|
||||
}
|
||||
|
||||
public boolean isDisallowExpectedDisbursements() {
|
||||
return disallowExpectedDisbursements;
|
||||
}
|
||||
|
||||
public boolean isAllowApprovedDisbursedAmountsOverApplied() {
|
||||
return allowApprovedDisbursedAmountsOverApplied;
|
||||
}
|
||||
|
||||
public String getOverAppliedCalculationType() {
|
||||
return overAppliedCalculationType;
|
||||
}
|
||||
|
||||
public Integer getOverAppliedNumber() {
|
||||
return overAppliedNumber;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,4 +25,6 @@
|
||||
<include file="parts/0003_postgresql_specific_initial_data.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0004_camelcase_column_renaming.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0005_savings_transaction_reversal.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0006_product_loan_disallow_expected_disbursements.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0007_product_loan_higher_than_applied_loan_amount_management.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
<changeSet author="fineract" id="1">
|
||||
<addColumn tableName="m_product_loan">
|
||||
<column name="disallow_expected_disbursements" type="BOOLEAN" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
<changeSet author="fineract" id="1">
|
||||
<addColumn tableName="m_product_loan">
|
||||
<column name="allow_approved_disbursed_amounts_over_applied" type="BOOLEAN" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="over_applied_calculation_type" type="VARCHAR(10)"/>
|
||||
<column defaultValueComputed="NULL" name="over_applied_number" type="INT"/>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
Reference in New Issue
Block a user