diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java index 27813b127..4ac8c2528 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java @@ -1280,10 +1280,12 @@ public class Loan extends AbstractPersistableCustom { */ private void applyAccurals(AppUser currentUser) { Collection accruals = retreiveListOfAccrualTransactions(); - if (isPeriodicAccrualAccountingEnabledOnLoanProduct()) { - applyPeriodicAccruals(accruals); - } else if (isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) { - updateAccrualsForNonPeriodicAccruals(accruals, currentUser); + if (accruals.size() > 0) { + if (isPeriodicAccrualAccountingEnabledOnLoanProduct()) { + applyPeriodicAccruals(accruals); + } else if (isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) { + updateAccrualsForNonPeriodicAccruals(accruals, currentUser); + } } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java index 6aaf01e76..40077a8cb 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java @@ -183,6 +183,11 @@ public class LoanProductData implements Serializable { private final Boolean multiDisburseLoan; private final Integer maxTrancheCount; private final BigDecimal outstandingLoanBalance; + private final Boolean disallowExpectedDisbursements; + private final Boolean allowApprovedDisbursedAmountsOverApplied; + private final String overAppliedCalculationType; + private final Integer overAppliedNumber; + private final BigDecimal principalThresholdForLastInstallment; private final Boolean holdGuaranteeFunds; @@ -252,6 +257,11 @@ public class LoanProductData implements Serializable { final String externalId = null; final Integer maxTrancheCount = null; final BigDecimal outstandingLoanBalance = null; + final Boolean disallowExpectedDisbursements = false; + final Boolean allowApprovedDisbursedAmountsOverApplied = false; + final String overAppliedCalculationType = null; + final Integer overAppliedNumber = null; + final LoanProductGuaranteeData productGuaranteeData = null; final Boolean holdGuaranteeFunds = false; final BigDecimal principalThresholdForLastInstallment = null; @@ -280,6 +290,7 @@ public class LoanProductData implements Serializable { recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, graceOnInterestCharged, charges, accountingType, includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status, externalId, principalVariations, interestRateVariations, numberOfRepaymentVariations, multiDisburseLoan, maxTrancheCount, outstandingLoanBalance, + disallowExpectedDisbursements, allowApprovedDisbursedAmountsOverApplied, overAppliedCalculationType, overAppliedNumber, graceOnArrearsAgeing, overdueDaysForNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, interestRecalculationData, minimumDaysBetweenDisbursalAndFirstRepayment, holdGuaranteeFunds, productGuaranteeData, principalThresholdForLastInstallment, accountMovesOutOfNPAOnlyOnArrearsCompletion, canDefineInstallmentAmount, @@ -349,6 +360,10 @@ public class LoanProductData implements Serializable { final Boolean multiDisburseLoan = null; final Integer maxTrancheCount = null; final BigDecimal outstandingLoanBalance = null; + final Boolean disallowExpectedDisbursements = false; + final Boolean allowApprovedDisbursedAmountsOverApplied = false; + final String overAppliedCalculationType = null; + final Integer overAppliedNumber = null; final EnumOptionData daysInMonthType = null; final EnumOptionData daysInYearType = null; @@ -378,6 +393,7 @@ public class LoanProductData implements Serializable { recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, graceOnInterestCharged, charges, accountingType, includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status, externalId, principalVariations, interestRateVariations, numberOfRepaymentVariations, multiDisburseLoan, maxTrancheCount, outstandingLoanBalance, + disallowExpectedDisbursements, allowApprovedDisbursedAmountsOverApplied, overAppliedCalculationType, overAppliedNumber, graceOnArrearsAgeing, overdueDaysForNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, interestRecalculationData, minimumDaysBetweenDisbursalAndFirstRepayment, holdGuaranteeFunds, productGuaranteeData, principalThresholdForLastInstallment, accountMovesOutOfNPAOnlyOnArrearsCompletion, canDefineInstallmentAmount, @@ -453,6 +469,10 @@ public class LoanProductData implements Serializable { final Boolean multiDisburseLoan = null; final Integer maxTrancheCount = null; final BigDecimal outstandingLoanBalance = null; + final Boolean disallowExpectedDisbursements = false; + final Boolean allowApprovedDisbursedAmountsOverApplied = false; + final String overAppliedCalculationType = null; + final Integer overAppliedNumber = null; final EnumOptionData daysInMonthType = CommonEnumerations.daysInMonthType(DaysInMonthType.ACTUAL); final EnumOptionData daysInYearType = CommonEnumerations.daysInYearType(DaysInYearType.ACTUAL); @@ -483,14 +503,15 @@ public class LoanProductData implements Serializable { recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, graceOnInterestCharged, charges, accountingType, includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status, externalId, principalVariationsForBorrowerCycle, interestRateVariationsForBorrowerCycle, numberOfRepaymentVariationsForBorrowerCycle, multiDisburseLoan, maxTrancheCount, - outstandingLoanBalance, graceOnArrearsAgeing, overdueDaysForNPA, daysInMonthType, daysInYearType, - isInterestRecalculationEnabled, interestRecalculationData, minimumDaysBetweenDisbursalAndFirstRepayment, holdGuaranteeFunds, - productGuaranteeData, principalThresholdForLastInstallment, accountMovesOutOfNPAOnlyOnArrearsCompletion, - canDefineInstallmentAmount, installmentAmountInMultiplesOf, loanProductConfigurableAttributes, - isLinkedToFloatingInterestRates, floatingRateId, floatingRateName, interestRateDifferential, minDifferentialLendingRate, - defaultDifferentialLendingRate, maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, - isVariableInstallmentsAllowed, minimumGap, maximumGap, syncExpectedWithDisbursementDate, canUseForTopup, - isEqualAmortization, rateOptions, rates, isRatesEnabled, fixedPrincipalPercentagePerInstallment); + outstandingLoanBalance, disallowExpectedDisbursements, allowApprovedDisbursedAmountsOverApplied, overAppliedCalculationType, + overAppliedNumber, graceOnArrearsAgeing, overdueDaysForNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, + interestRecalculationData, minimumDaysBetweenDisbursalAndFirstRepayment, holdGuaranteeFunds, productGuaranteeData, + principalThresholdForLastInstallment, accountMovesOutOfNPAOnlyOnArrearsCompletion, canDefineInstallmentAmount, + installmentAmountInMultiplesOf, loanProductConfigurableAttributes, isLinkedToFloatingInterestRates, floatingRateId, + floatingRateName, interestRateDifferential, minDifferentialLendingRate, defaultDifferentialLendingRate, + maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, minimumGap, maximumGap, + syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, rateOptions, rates, isRatesEnabled, + fixedPrincipalPercentagePerInstallment); } @@ -552,6 +573,10 @@ public class LoanProductData implements Serializable { final Boolean multiDisburseLoan = null; final Integer maxTrancheCount = null; final BigDecimal outstandingLoanBalance = null; + final Boolean disallowExpectedDisbursements = false; + final Boolean allowApprovedDisbursedAmountsOverApplied = false; + final String overAppliedCalculationType = null; + final Integer overAppliedNumber = null; final EnumOptionData daysInMonthType = CommonEnumerations.daysInMonthType(DaysInMonthType.ACTUAL); final EnumOptionData daysInYearType = CommonEnumerations.daysInYearType(DaysInYearType.ACTUAL); @@ -582,14 +607,15 @@ public class LoanProductData implements Serializable { recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, graceOnInterestCharged, charges, accountingType, includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status, externalId, principalVariationsForBorrowerCycle, interestRateVariationsForBorrowerCycle, numberOfRepaymentVariationsForBorrowerCycle, multiDisburseLoan, maxTrancheCount, - outstandingLoanBalance, graceOnArrearsAgeing, overdueDaysForNPA, daysInMonthType, daysInYearType, - isInterestRecalculationEnabled, interestRecalculationData, minimumDaysBetweenDisbursalAndFirstRepayment, holdGuaranteeFunds, - productGuaranteeData, principalThresholdForLastInstallment, accountMovesOutOfNPAOnlyOnArrearsCompletion, - canDefineInstallmentAmount, installmentAmountInMultiplesOf, loanProductConfigurableAttributes, - isLinkedToFloatingInterestRates, floatingRateId, floatingRateName, interestRateDifferential, minDifferentialLendingRate, - defaultDifferentialLendingRate, maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, - isVariableInstallmentsAllowed, minimumGap, maximumGap, syncExpectedWithDisbursementDate, canUseForTopup, - isEqualAmortization, rateOptions, rates, isRatesEnabled, fixedPrincipalPercentagePerInstallment); + outstandingLoanBalance, disallowExpectedDisbursements, allowApprovedDisbursedAmountsOverApplied, overAppliedCalculationType, + overAppliedNumber, graceOnArrearsAgeing, overdueDaysForNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, + interestRecalculationData, minimumDaysBetweenDisbursalAndFirstRepayment, holdGuaranteeFunds, productGuaranteeData, + principalThresholdForLastInstallment, accountMovesOutOfNPAOnlyOnArrearsCompletion, canDefineInstallmentAmount, + installmentAmountInMultiplesOf, loanProductConfigurableAttributes, isLinkedToFloatingInterestRates, floatingRateId, + floatingRateName, interestRateDifferential, minDifferentialLendingRate, defaultDifferentialLendingRate, + maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, minimumGap, maximumGap, + syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, rateOptions, rates, isRatesEnabled, + fixedPrincipalPercentagePerInstallment); } @@ -619,7 +645,9 @@ public class LoanProductData implements Serializable { Collection principalVariations, Collection interestRateVariations, Collection numberOfRepaymentVariations, Boolean multiDisburseLoan, - Integer maxTrancheCount, BigDecimal outstandingLoanBalance, final Integer graceOnArrearsAgeing, final Integer overdueDaysForNPA, + Integer maxTrancheCount, BigDecimal outstandingLoanBalance, final Boolean disallowExpectedDisbursements, + final Boolean allowApprovedDisbursedAmountsOverApplied, final String overAppliedCalculationType, + final Integer overAppliedNumber, final Integer graceOnArrearsAgeing, final Integer overdueDaysForNPA, final EnumOptionData daysInMonthType, final EnumOptionData daysInYearType, final boolean isInterestRecalculationEnabled, final LoanProductInterestRecalculationData interestRecalculationData, final Integer minimumDaysBetweenDisbursalAndFirstRepayment, boolean holdGuaranteeFunds, @@ -714,6 +742,11 @@ public class LoanProductData implements Serializable { this.multiDisburseLoan = multiDisburseLoan; this.outstandingLoanBalance = outstandingLoanBalance; this.maxTrancheCount = maxTrancheCount; + this.disallowExpectedDisbursements = disallowExpectedDisbursements; + this.allowApprovedDisbursedAmountsOverApplied = allowApprovedDisbursedAmountsOverApplied; + this.overAppliedCalculationType = overAppliedCalculationType; + this.overAppliedNumber = overAppliedNumber; + this.graceOnArrearsAgeing = graceOnArrearsAgeing; this.overdueDaysForNPA = overdueDaysForNPA; this.daysInMonthType = daysInMonthType; @@ -837,6 +870,11 @@ public class LoanProductData implements Serializable { this.multiDisburseLoan = productData.multiDisburseLoan; this.maxTrancheCount = productData.maxTrancheCount; this.outstandingLoanBalance = productData.outstandingLoanBalance; + this.disallowExpectedDisbursements = productData.disallowExpectedDisbursements; + this.allowApprovedDisbursedAmountsOverApplied = productData.allowApprovedDisbursedAmountsOverApplied; + this.overAppliedCalculationType = productData.overAppliedCalculationType; + this.overAppliedNumber = productData.overAppliedNumber; + this.minimumDaysBetweenDisbursalAndFirstRepayment = productData.minimumDaysBetweenDisbursalAndFirstRepayment; this.amortizationTypeOptions = amortizationTypeOptions; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java index b44c102ef..d428672f8 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java @@ -756,6 +756,8 @@ public final class LoanProductDataValidator { .integerSameAsNumber(InterestMethod.DECLINING_BALANCE.getValue()); } + final String overAppliedCalculationType = this.fromApiJsonHelper.extractStringNamed("overAppliedCalculationType", element); + baseDataValidator.reset().parameter("overAppliedCalculationType").value(overAppliedCalculationType).notExceedingLengthOf(10); } private void validateInterestRecalculationParams(final JsonElement element, final DataValidatorBuilder baseDataValidator, diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java index f228311b1..f201a9387 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java @@ -203,6 +203,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo + "lp.amortization_method_enum as amortizationMethod, lp.arrearstolerance_amount as tolerance, " + "lp.accounting_type as accountingType, lp.include_in_borrower_cycle as includeInBorrowerCycle,lp.use_borrower_cycle as useBorrowerCycle, lp.start_date as startDate, lp.close_date as closeDate, " + "lp.allow_multiple_disbursals as multiDisburseLoan, lp.max_disbursals as maxTrancheCount, lp.max_outstanding_loan_balance as outstandingLoanBalance, " + + "lp.disallow_expected_disbursements as disallowExpectedDisbursements, lp.allow_approved_disbursed_amounts_over_applied as allowApprovedDisbursedAmountsOverApplied, lp.over_applied_calculation_type as overAppliedCalculationType, over_applied_number as overAppliedNumber, " + "lp.days_in_month_enum as daysInMonth, lp.days_in_year_enum as daysInYear, lp.interest_recalculation_enabled as isInterestRecalculationEnabled, " + "lp.can_define_fixed_emi_amount as canDefineInstallmentAmount, lp.instalment_amount_in_multiples_of as installmentAmountInMultiplesOf, " + "lpr.pre_close_interest_calculation_strategy as preCloseInterestCalculationStrategy, " @@ -360,6 +361,10 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo final Boolean multiDisburseLoan = rs.getBoolean("multiDisburseLoan"); final Integer maxTrancheCount = rs.getInt("maxTrancheCount"); final BigDecimal outstandingLoanBalance = rs.getBigDecimal("outstandingLoanBalance"); + final Boolean disallowExpectedDisbursements = rs.getBoolean("disallowExpectedDisbursements"); + final Boolean allowApprovedDisbursedAmountsOverApplied = rs.getBoolean("allowApprovedDisbursedAmountsOverApplied"); + final String overAppliedCalculationType = rs.getString("overAppliedCalculationType"); + final Integer overAppliedNumber = rs.getInt("overAppliedNumber"); final int daysInMonth = JdbcSupport.getInteger(rs, "daysInMonth"); final EnumOptionData daysInMonthType = CommonEnumerations.daysInMonthType(daysInMonth); @@ -470,6 +475,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo this.charges, accountingRuleType, includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status, externalId, principalVariationsForBorrowerCycle, interestRateVariationsForBorrowerCycle, numberOfRepaymentVariationsForBorrowerCycle, multiDisburseLoan, maxTrancheCount, outstandingLoanBalance, + disallowExpectedDisbursements, allowApprovedDisbursedAmountsOverApplied, overAppliedCalculationType, overAppliedNumber, graceOnArrearsAgeing, overdueDaysForNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, interestRecalculationData, minimumDaysBetweenDisbursalAndFirstRepayment, holdGuaranteeFunds, loanProductGuaranteeData, principalThresholdForLastInstallment, accountMovesOutOfNPAOnlyOnArrearsCompletion, canDefineInstallmentAmount,