FINERACT-2311: Loan product - Buy down fees configuration

This commit is contained in:
adam.magyari
2025-06-24 15:06:54 +02:00
committed by Adam Saghy
parent 29d1ed3cd4
commit 1b1d6be956
23 changed files with 708 additions and 31 deletions
@@ -174,6 +174,9 @@ public class LoanAccountData {
private List<StringEnumOptionData> capitalizedIncomeCalculationTypeOptions;
private List<StringEnumOptionData> capitalizedIncomeStrategyOptions;
private List<StringEnumOptionData> capitalizedIncomeTypeOptions;
private List<StringEnumOptionData> buyDownFeeCalculationTypeOptions;
private List<StringEnumOptionData> buyDownFeeStrategyOptions;
private List<StringEnumOptionData> buyDownFeeIncomeTypeOptions;
@Transient
private BigDecimal feeChargesAtDisbursementCharged;
@@ -281,6 +284,11 @@ public class LoanAccountData {
private StringEnumOptionData capitalizedIncomeStrategy;
private StringEnumOptionData capitalizedIncomeType;
private Boolean enableBuyDownFee;
private StringEnumOptionData buyDownFeeCalculationType;
private StringEnumOptionData buyDownFeeStrategy;
private StringEnumOptionData buyDownFeeIncomeType;
public static LoanAccountData importInstanceIndividual(EnumOptionData loanTypeEnumOption, Long clientId, Long productId,
Long loanOfficerId, LocalDate submittedOnDate, Long fundId, BigDecimal principal, Integer numberOfRepayments,
Integer repaymentEvery, EnumOptionData repaidEveryFrequencyEnums, Integer loanTermFrequency,
@@ -473,7 +481,9 @@ public class LoanAccountData {
final EnumOptionData loanScheduleProcessingType, final Integer fixedLength, final StringEnumOptionData chargeOffBehaviour,
final boolean isInterestRecognitionOnDisbursementDate, final StringEnumOptionData daysInYearCustomStrategy,
final boolean enableIncomeCapitalization, final StringEnumOptionData capitalizedIncomeCalculationType,
final StringEnumOptionData capitalizedIncomeStrategy, StringEnumOptionData capitalizedIncomeType) {
final StringEnumOptionData capitalizedIncomeStrategy, StringEnumOptionData capitalizedIncomeType,
final boolean enableBuyDownFee, final StringEnumOptionData buyDownFeeCalculationType,
final StringEnumOptionData buyDownFeeStrategy, final StringEnumOptionData buyDownFeeIncomeType) {
final CollectionData delinquent = CollectionData.template();
@@ -521,7 +531,9 @@ public class LoanAccountData {
.setChargeOffBehaviour(chargeOffBehaviour).setInterestRecognitionOnDisbursementDate(isInterestRecognitionOnDisbursementDate)
.setDaysInYearCustomStrategy(daysInYearCustomStrategy).setEnableIncomeCapitalization(enableIncomeCapitalization)
.setCapitalizedIncomeCalculationType(capitalizedIncomeCalculationType)
.setCapitalizedIncomeStrategy(capitalizedIncomeStrategy).setCapitalizedIncomeType(capitalizedIncomeType);
.setCapitalizedIncomeStrategy(capitalizedIncomeStrategy).setCapitalizedIncomeType(capitalizedIncomeType)
.setEnableBuyDownFee(enableBuyDownFee).setBuyDownFeeCalculationType(buyDownFeeCalculationType)
.setBuyDownFeeStrategy(buyDownFeeStrategy).setBuyDownFeeIncomeType(buyDownFeeIncomeType);
}
/*
@@ -550,7 +562,9 @@ public class LoanAccountData {
final List<StringEnumOptionData> daysInYearCustomStrategyOptions,
final List<StringEnumOptionData> capitalizedIncomeCalculationTypeOptions,
final List<StringEnumOptionData> capitalizedIncomeStrategyOptions,
final List<StringEnumOptionData> capitalizedIncomeTypeOptions) {
final List<StringEnumOptionData> capitalizedIncomeTypeOptions,
final List<StringEnumOptionData> buyDownFeeCalculationTypeOptions, final List<StringEnumOptionData> buyDownFeeStrategyOptions,
final List<StringEnumOptionData> buyDownFeeIncomeTypeOptions) {
// TODO: why are these variables 'calendarData', 'chargeTemplate' never used (see original private constructor)
@@ -574,7 +588,9 @@ public class LoanAccountData {
.setDaysInYearCustomStrategyOptions(daysInYearCustomStrategyOptions)
.setCapitalizedIncomeCalculationTypeOptions(capitalizedIncomeCalculationTypeOptions)
.setCapitalizedIncomeStrategyOptions(capitalizedIncomeStrategyOptions)
.setCapitalizedIncomeTypeOptions(capitalizedIncomeTypeOptions);
.setCapitalizedIncomeTypeOptions(capitalizedIncomeTypeOptions)
.setBuyDownFeeCalculationTypeOptions(buyDownFeeCalculationTypeOptions)
.setBuyDownFeeStrategyOptions(buyDownFeeStrategyOptions).setBuyDownFeeIncomeTypeOptions(buyDownFeeIncomeTypeOptions);
}
public LoanAccountData associationsAndTemplate(final Collection<LoanProductData> productOptions,
@@ -0,0 +1,33 @@
/**
* 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.domain;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.core.api.ApiFacingEnum;
@Getter
@RequiredArgsConstructor
public enum LoanBuyDownFeeCalculationType implements ApiFacingEnum<LoanBuyDownFeeCalculationType> {
FLAT("loanBuyDownFeeCalculationType.flat", "Flat");
private final String code;
private final String humanReadableName;
}
@@ -0,0 +1,34 @@
/**
* 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.domain;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.core.api.ApiFacingEnum;
@Getter
@RequiredArgsConstructor
public enum LoanBuyDownFeeIncomeType implements ApiFacingEnum<LoanBuyDownFeeIncomeType> {
FEE("buyDownFee.incomeType.fee", "Fee"), //
INTEREST("buyDownFee.incomeType.interest", "Interest"); //
private final String code;
private final String humanReadableName;
}
@@ -0,0 +1,33 @@
/**
* 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.domain;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.core.api.ApiFacingEnum;
@Getter
@RequiredArgsConstructor
public enum LoanBuyDownFeeStrategy implements ApiFacingEnum<LoanBuyDownFeeStrategy> {
EQUAL_AMORTIZATION("buyDownFee.strategy.equalAmortization", "Equal amortization");
private final String code;
private final String humanReadableName;
}
@@ -46,6 +46,9 @@ import org.apache.fineract.portfolio.loanaccount.data.DisbursementData;
import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsDataWrapper;
import org.apache.fineract.portfolio.loanaccount.domain.LoanBuyDownFeeCalculationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanBuyDownFeeIncomeType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanBuyDownFeeStrategy;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeCalculationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeStrategy;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeType;
@@ -239,6 +242,10 @@ public final class LoanApplicationTerms {
private LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType;
private LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy;
private LoanCapitalizedIncomeType capitalizedIncomeType;
private boolean enableBuyDownFee;
private LoanBuyDownFeeCalculationType buyDownFeeCalculationType;
private LoanBuyDownFeeStrategy buyDownFeeStrategy;
private LoanBuyDownFeeIncomeType buyDownFeeIncomeType;
private LoanApplicationTerms(Builder builder) {
this.currency = builder.currency;
@@ -279,6 +286,10 @@ public final class LoanApplicationTerms {
this.capitalizedIncomeCalculationType = builder.capitalizedIncomeCalculationType;
this.capitalizedIncomeStrategy = builder.capitalizedIncomeStrategy;
this.capitalizedIncomeType = builder.capitalizedIncomeType;
this.enableBuyDownFee = builder.enableBuyDownFee;
this.buyDownFeeCalculationType = builder.buyDownFeeCalculationType;
this.buyDownFeeStrategy = builder.buyDownFeeStrategy;
this.buyDownFeeIncomeType = builder.buyDownFeeIncomeType;
}
public static class Builder {
@@ -312,6 +323,10 @@ public final class LoanApplicationTerms {
private LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType;
private LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy;
private LoanCapitalizedIncomeType capitalizedIncomeType;
private boolean enableBuyDownFee;
private LoanBuyDownFeeCalculationType buyDownFeeCalculationType;
private LoanBuyDownFeeStrategy buyDownFeeStrategy;
private LoanBuyDownFeeIncomeType buyDownFeeIncomeType;
public Builder currency(CurrencyData currency) {
this.currency = currency;
@@ -448,6 +463,26 @@ public final class LoanApplicationTerms {
return this;
}
public Builder enableBuyDownFee(boolean value) {
this.enableBuyDownFee = value;
return this;
}
public Builder buyDownFeeCalculationType(LoanBuyDownFeeCalculationType value) {
this.buyDownFeeCalculationType = value;
return this;
}
public Builder buyDownFeeStrategy(LoanBuyDownFeeStrategy value) {
this.buyDownFeeStrategy = value;
return this;
}
public Builder buyDownFeeIncomeType(LoanBuyDownFeeIncomeType value) {
this.buyDownFeeIncomeType = value;
return this;
}
public LoanApplicationTerms build() {
return new LoanApplicationTerms(this);
}
@@ -517,7 +552,9 @@ public final class LoanApplicationTerms {
final LoanChargeOffBehaviour chargeOffBehaviour, final boolean interestRecognitionOnDisbursementDate,
final DaysInYearCustomStrategyType daysInYearCustomStrategy, final boolean enableIncomeCapitalization,
final LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType,
final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy, final LoanCapitalizedIncomeType capitalizedIncomeType) {
final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy, final LoanCapitalizedIncomeType capitalizedIncomeType,
final boolean enableBuyDownFee, final LoanBuyDownFeeCalculationType buyDownFeeCalculationType,
final LoanBuyDownFeeStrategy buyDownFeeStrategy, final LoanBuyDownFeeIncomeType buyDownFeeIncomeType) {
final LoanRescheduleStrategyMethod rescheduleStrategyMethod = null;
final CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
@@ -538,7 +575,8 @@ public final class LoanApplicationTerms {
isAutoRepaymentForDownPaymentEnabled, repaymentStartDateType, submittedOnDate, loanScheduleType, loanScheduleProcessingType,
fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate, daysInYearCustomStrategy, enableIncomeCapitalization,
capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType);
capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType, enableBuyDownFee,
buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType);
}
@@ -614,7 +652,9 @@ public final class LoanApplicationTerms {
loanProductRelatedDetail.getSupportedInterestRefundTypes(), loanProductRelatedDetail.getChargeOffBehaviour(),
loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate(), loanProductRelatedDetail.getDaysInYearCustomStrategy(),
loanProductRelatedDetail.isEnableIncomeCapitalization(), loanProductRelatedDetail.getCapitalizedIncomeCalculationType(),
loanProductRelatedDetail.getCapitalizedIncomeStrategy(), loanProductRelatedDetail.getCapitalizedIncomeType());
loanProductRelatedDetail.getCapitalizedIncomeStrategy(), loanProductRelatedDetail.getCapitalizedIncomeType(),
loanProductRelatedDetail.isEnableBuyDownFee(), loanProductRelatedDetail.getBuyDownFeeCalculationType(),
loanProductRelatedDetail.getBuyDownFeeStrategy(), loanProductRelatedDetail.getBuyDownFeeIncomeType());
}
private LoanApplicationTerms(final CurrencyData currency, final Integer loanTermFrequency,
@@ -647,7 +687,9 @@ public final class LoanApplicationTerms {
final List<LoanSupportedInterestRefundTypes> supportedInterestRefundTypes, final LoanChargeOffBehaviour chargeOffBehaviour,
final boolean interestRecognitionOnDisbursementDate, final DaysInYearCustomStrategyType daysInYearCustomStrategy,
final boolean enableIncomeCapitalization, final LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType,
final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy, final LoanCapitalizedIncomeType capitalizedIncomeType) {
final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy, final LoanCapitalizedIncomeType capitalizedIncomeType,
final boolean enableBuyDownFee, final LoanBuyDownFeeCalculationType buyDownFeeCalculationType,
final LoanBuyDownFeeStrategy buyDownFeeStrategy, final LoanBuyDownFeeIncomeType buyDownFeeIncomeType) {
this.currency = currency;
this.loanTermFrequency = loanTermFrequency;
@@ -753,6 +795,10 @@ public final class LoanApplicationTerms {
this.capitalizedIncomeCalculationType = capitalizedIncomeCalculationType;
this.capitalizedIncomeStrategy = capitalizedIncomeStrategy;
this.capitalizedIncomeType = capitalizedIncomeType;
this.enableBuyDownFee = enableBuyDownFee;
this.buyDownFeeCalculationType = buyDownFeeCalculationType;
this.buyDownFeeStrategy = buyDownFeeStrategy;
this.buyDownFeeIncomeType = buyDownFeeIncomeType;
}
public Money adjustPrincipalIfLastRepaymentPeriod(final Money principalForPeriod, final Money totalCumulativePrincipalToDate,
@@ -1616,7 +1662,8 @@ public final class LoanApplicationTerms {
this.loanScheduleProcessingType, this.fixedLength, this.enableAccrualActivityPosting, this.supportedInterestRefundTypes,
this.chargeOffBehaviour, this.interestRecognitionOnDisbursementDate, this.daysInYearCustomStrategy,
this.enableIncomeCapitalization, this.capitalizedIncomeCalculationType, this.capitalizedIncomeStrategy,
this.capitalizedIncomeType, this.installmentAmountInMultiplesOf);
this.capitalizedIncomeType, this.installmentAmountInMultiplesOf, this.enableBuyDownFee, this.buyDownFeeCalculationType,
this.buyDownFeeStrategy, this.buyDownFeeIncomeType);
}
public LoanProductMinimumRepaymentScheduleRelatedDetail toLoanProductRelatedDetailMinimumData() {
@@ -177,4 +177,10 @@ public interface LoanProductConstants {
String CAPITALIZED_INCOME_CALCULATION_TYPE_PARAM_NAME = "capitalizedIncomeCalculationType";
String CAPITALIZED_INCOME_STRATEGY_PARAM_NAME = "capitalizedIncomeStrategy";
String CAPITALIZED_INCOME_TYPE_PARAM_NAME = "capitalizedIncomeType";
// Buy down fee
String ENABLE_BUY_DOWN_FEE_PARAM_NAME = "enableBuyDownFee";
String BUY_DOWN_FEE_CALCULATION_TYPE_PARAM_NAME = "buyDownFeeCalculationType";
String BUY_DOWN_FEE_STRATEGY_PARAM_NAME = "buyDownFeeStrategy";
String BUY_DOWN_FEE_INCOME_TYPE_PARAM_NAME = "buyDownFeeIncomeType";
}
@@ -203,6 +203,14 @@ public final class LoanProductsApiResourceSwagger {
public String capitalizedIncomeStrategy;
@Schema(example = "FEE", allowableValues = { "FEE", "INTEREST" })
public String capitalizedIncomeType;
@Schema(example = "false")
public Boolean enableBuyDownFee;
@Schema(example = "FLAT", allowableValues = "FLAT")
public String buyDownFeeCalculationType;
@Schema(example = "EQUAL_AMORTIZATION", allowableValues = "EQUAL_AMORTIZATION")
public String buyDownFeeStrategy;
@Schema(example = "FEE", allowableValues = { "FEE", "INTEREST" })
public String buyDownFeeIncomeType;
// Interest Recalculation
@Schema(example = "false")
@@ -671,6 +679,14 @@ public final class LoanProductsApiResourceSwagger {
public StringEnumOptionData capitalizedIncomeStrategy;
@Schema(example = "FEE")
public StringEnumOptionData capitalizedIncomeType;
@Schema(example = "false")
public Boolean enableBuyDownFee;
@Schema(example = "FLAT")
public StringEnumOptionData buyDownFeeCalculationType;
@Schema(example = "EQUAL_AMORTIZATION")
public StringEnumOptionData buyDownFeeStrategy;
@Schema(example = "FEE")
public StringEnumOptionData buyDownFeeIncomeType;
}
@Schema(description = "GetLoanProductsTemplateResponse")
@@ -1128,6 +1144,18 @@ public final class LoanProductsApiResourceSwagger {
public List<StringEnumOptionData> capitalizedIncomeCalculationTypeOptions;
public List<StringEnumOptionData> capitalizedIncomeStrategyOptions;
public List<StringEnumOptionData> capitalizedIncomeTypeOptions;
@Schema(example = "false")
public Boolean enableBuyDownFee;
@Schema(example = "FLAT")
public StringEnumOptionData buyDownFeeCalculationType;
@Schema(example = "EQUAL_AMORTIZATION")
public StringEnumOptionData buyDownFeeStrategy;
@Schema(example = "FEE")
public StringEnumOptionData buyDownFeeIncomeType;
public List<StringEnumOptionData> buyDownFeeCalculationTypeOptions;
public List<StringEnumOptionData> buyDownFeeStrategyOptions;
public List<StringEnumOptionData> buyDownFeeIncomeTypeOptions;
}
@Schema(description = "GetLoanProductsProductIdResponse")
@@ -1460,6 +1488,18 @@ public final class LoanProductsApiResourceSwagger {
public List<StringEnumOptionData> capitalizedIncomeCalculationTypeOptions;
public List<StringEnumOptionData> capitalizedIncomeStrategyOptions;
public List<StringEnumOptionData> capitalizedIncomeTypeOptions;
@Schema(example = "false")
public Boolean enableBuyDownFee;
@Schema(example = "FLAT")
public StringEnumOptionData buyDownFeeCalculationType;
@Schema(example = "EQUAL_AMORTIZATION")
public StringEnumOptionData buyDownFeeStrategy;
@Schema(example = "FEE")
public StringEnumOptionData buyDownFeeIncomeType;
public List<StringEnumOptionData> buyDownFeeCalculationTypeOptions;
public List<StringEnumOptionData> buyDownFeeStrategyOptions;
public List<StringEnumOptionData> buyDownFeeIncomeTypeOptions;
}
@Schema(description = "PutLoanProductsProductIdRequest")
@@ -1727,6 +1767,14 @@ public final class LoanProductsApiResourceSwagger {
public String capitalizedIncomeStrategy;
@Schema(example = "FEE", allowableValues = { "FEE", "INTEREST" })
public String capitalizedIncomeType;
@Schema(example = "false")
public Boolean enableBuyDownFee;
@Schema(example = "FLAT", allowableValues = "FLAT")
public String buyDownFeeCalculationType;
@Schema(example = "EQUAL_AMORTIZATION", allowableValues = "EQUAL_AMORTIZATION")
public String buyDownFeeStrategy;
@Schema(example = "FEE", allowableValues = { "FEE", "INTEREST" })
public String buyDownFeeIncomeType;
}
public static final class AdvancedPaymentData {
@@ -49,6 +49,9 @@ import org.apache.fineract.portfolio.delinquency.data.DelinquencyBucketData;
import org.apache.fineract.portfolio.floatingrates.data.FloatingRateData;
import org.apache.fineract.portfolio.fund.data.FundData;
import org.apache.fineract.portfolio.loanaccount.data.LoanInterestRecalculationData;
import org.apache.fineract.portfolio.loanaccount.domain.LoanBuyDownFeeCalculationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanBuyDownFeeIncomeType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanBuyDownFeeStrategy;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeCalculationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeStrategy;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeType;
@@ -249,6 +252,13 @@ public class LoanProductData implements Serializable {
private List<StringEnumOptionData> capitalizedIncomeCalculationTypeOptions;
private List<StringEnumOptionData> capitalizedIncomeStrategyOptions;
private List<StringEnumOptionData> capitalizedIncomeTypeOptions;
private Boolean enableBuyDownFee;
private StringEnumOptionData buyDownFeeCalculationType;
private StringEnumOptionData buyDownFeeStrategy;
private StringEnumOptionData buyDownFeeIncomeType;
private List<StringEnumOptionData> buyDownFeeCalculationTypeOptions;
private List<StringEnumOptionData> buyDownFeeStrategyOptions;
private List<StringEnumOptionData> buyDownFeeIncomeTypeOptions;
/**
* Used when returning lookup information about loan product for dropdowns.
@@ -357,6 +367,10 @@ public class LoanProductData implements Serializable {
final StringEnumOptionData capitalizedIncomeCalculationType = null;
final StringEnumOptionData capitalizedIncomeStrategy = null;
final StringEnumOptionData capitalizedIncomeType = null;
final boolean enableBuyDownFee = false;
final StringEnumOptionData buyDownFeeCalculationType = null;
final StringEnumOptionData buyDownFeeStrategy = null;
final StringEnumOptionData buyDownFeeIncomeType = null;
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
@@ -379,7 +393,8 @@ public class LoanProductData implements Serializable {
paymentAllocation, creditAllocation, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy, enableIncomeCapitalization,
capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType);
capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType, enableBuyDownFee,
buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType);
}
@@ -488,6 +503,10 @@ public class LoanProductData implements Serializable {
final StringEnumOptionData capitalizedIncomeCalculationType = null;
final StringEnumOptionData capitalizedIncomeStrategy = null;
final StringEnumOptionData capitalizedIncomeType = null;
final boolean enableBuyDownFee = false;
final StringEnumOptionData buyDownFeeCalculationType = null;
final StringEnumOptionData buyDownFeeStrategy = null;
final StringEnumOptionData buyDownFeeIncomeType = null;
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
@@ -510,7 +529,8 @@ public class LoanProductData implements Serializable {
paymentAllocation, creditAllocation, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy, enableIncomeCapitalization,
capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType);
capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType, enableBuyDownFee,
buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType);
}
@@ -626,6 +646,10 @@ public class LoanProductData implements Serializable {
final StringEnumOptionData capitalizedIncomeCalculationType = null;
final StringEnumOptionData capitalizedIncomeStrategy = null;
final StringEnumOptionData capitalizedIncomeType = null;
final boolean enableBuyDownFee = false;
final StringEnumOptionData buyDownFeeCalculationType = null;
final StringEnumOptionData buyDownFeeStrategy = null;
final StringEnumOptionData buyDownFeeIncomeType = null;
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
@@ -648,7 +672,8 @@ public class LoanProductData implements Serializable {
paymentAllocation, creditAllocation, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy, enableIncomeCapitalization,
capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType);
capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType, enableBuyDownFee,
buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType);
}
@@ -758,6 +783,10 @@ public class LoanProductData implements Serializable {
final StringEnumOptionData capitalizedIncomeCalculationType = null;
final StringEnumOptionData capitalizedIncomeStrategy = null;
final StringEnumOptionData capitalizedIncomeType = null;
final boolean enableBuyDownFee = false;
final StringEnumOptionData buyDownFeeCalculationType = null;
final StringEnumOptionData buyDownFeeStrategy = null;
final StringEnumOptionData buyDownFeeIncomeType = null;
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
@@ -780,7 +809,8 @@ public class LoanProductData implements Serializable {
paymentAllocation, creditAllocationData, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy, enableIncomeCapitalization,
capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType);
capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType, enableBuyDownFee,
buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType);
}
public static LoanProductData withAccountingDetails(final LoanProductData productData, final Map<String, Object> accountingMappings,
@@ -837,7 +867,9 @@ public class LoanProductData implements Serializable {
StringEnumOptionData chargeOffBehaviour, final boolean interestRecognitionOnDisbursementDate,
final StringEnumOptionData daysInYearCustomStrategy, final boolean enableIncomeCapitalization,
final StringEnumOptionData capitalizedIncomeCalculationType, final StringEnumOptionData capitalizedIncomeStrategy,
final StringEnumOptionData capitalizedIncomeType) {
final StringEnumOptionData capitalizedIncomeType, final boolean enableBuyDownFee,
final StringEnumOptionData buyDownFeeCalculationType, final StringEnumOptionData buyDownFeeStrategy,
final StringEnumOptionData buyDownFeeIncomeType) {
this.id = id;
this.name = name;
this.shortName = shortName;
@@ -898,6 +930,10 @@ public class LoanProductData implements Serializable {
this.capitalizedIncomeCalculationType = capitalizedIncomeCalculationType;
this.capitalizedIncomeStrategy = capitalizedIncomeStrategy;
this.capitalizedIncomeType = capitalizedIncomeType;
this.enableBuyDownFee = enableBuyDownFee;
this.buyDownFeeCalculationType = buyDownFeeCalculationType;
this.buyDownFeeStrategy = buyDownFeeStrategy;
this.buyDownFeeIncomeType = buyDownFeeIncomeType;
this.chargeOptions = null;
this.penaltyOptions = null;
@@ -991,6 +1027,9 @@ public class LoanProductData implements Serializable {
.getValuesAsStringEnumOptionDataList(LoanCapitalizedIncomeCalculationType.class);
this.capitalizedIncomeStrategyOptions = ApiFacingEnum.getValuesAsStringEnumOptionDataList(LoanCapitalizedIncomeStrategy.class);
this.capitalizedIncomeTypeOptions = ApiFacingEnum.getValuesAsStringEnumOptionDataList(LoanCapitalizedIncomeType.class);
this.buyDownFeeCalculationTypeOptions = ApiFacingEnum.getValuesAsStringEnumOptionDataList(LoanBuyDownFeeCalculationType.class);
this.buyDownFeeStrategyOptions = ApiFacingEnum.getValuesAsStringEnumOptionDataList(LoanBuyDownFeeStrategy.class);
this.buyDownFeeIncomeTypeOptions = ApiFacingEnum.getValuesAsStringEnumOptionDataList(LoanBuyDownFeeIncomeType.class);
}
public LoanProductData(final LoanProductData productData, final Collection<ChargeData> chargeOptions,
@@ -1018,7 +1057,9 @@ public class LoanProductData implements Serializable {
final List<StringEnumOptionData> daysInYearCustomStrategyOptions,
final List<StringEnumOptionData> capitalizedIncomeCalculationTypeOptions,
final List<StringEnumOptionData> capitalizedIncomeStrategyOptions,
final List<StringEnumOptionData> capitalizedIncomeTypeOptions) {
final List<StringEnumOptionData> capitalizedIncomeTypeOptions,
final List<StringEnumOptionData> buyDownFeeCalculationTypeOptions, final List<StringEnumOptionData> buyDownFeeStrategyOptions,
final List<StringEnumOptionData> buyDownFeeIncomeTypeOptions) {
this.id = productData.id;
this.name = productData.name;
@@ -1189,6 +1230,14 @@ public class LoanProductData implements Serializable {
this.capitalizedIncomeCalculationTypeOptions = capitalizedIncomeCalculationTypeOptions;
this.capitalizedIncomeStrategyOptions = capitalizedIncomeStrategyOptions;
this.capitalizedIncomeTypeOptions = capitalizedIncomeTypeOptions;
this.enableBuyDownFee = productData.enableBuyDownFee;
this.buyDownFeeCalculationType = productData.buyDownFeeCalculationType;
this.buyDownFeeStrategy = productData.buyDownFeeStrategy;
this.buyDownFeeIncomeType = productData.buyDownFeeIncomeType;
this.buyDownFeeCalculationTypeOptions = buyDownFeeCalculationTypeOptions;
this.buyDownFeeStrategyOptions = buyDownFeeStrategyOptions;
this.buyDownFeeIncomeTypeOptions = buyDownFeeIncomeTypeOptions;
}
private Collection<ChargeData> nullIfEmpty(final Collection<ChargeData> charges) {
@@ -59,6 +59,9 @@ import org.apache.fineract.portfolio.floatingrates.data.FloatingRateDTO;
import org.apache.fineract.portfolio.floatingrates.data.FloatingRatePeriodData;
import org.apache.fineract.portfolio.floatingrates.domain.FloatingRate;
import org.apache.fineract.portfolio.fund.domain.Fund;
import org.apache.fineract.portfolio.loanaccount.domain.LoanBuyDownFeeCalculationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanBuyDownFeeIncomeType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanBuyDownFeeStrategy;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeCalculationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeStrategy;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeType;
@@ -282,7 +285,9 @@ public class LoanProduct extends AbstractPersistableCustom<Long> {
final LoanChargeOffBehaviour chargeOffBehaviour, final boolean isInterestRecognitionOnDisbursementDate,
final DaysInYearCustomStrategyType daysInYearCustomStrategy, final boolean enableIncomeCapitalization,
final LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType,
final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy, final LoanCapitalizedIncomeType capitalizedIncomeType) {
final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy, final LoanCapitalizedIncomeType capitalizedIncomeType,
final boolean enableBuyDownFee, final LoanBuyDownFeeCalculationType buyDownFeeCalculationType,
final LoanBuyDownFeeStrategy buyDownFeeStrategy, final LoanBuyDownFeeIncomeType buyDownFeeIncomeType) {
this.fund = fund;
this.transactionProcessingStrategyCode = transactionProcessingStrategyCode;
@@ -334,7 +339,7 @@ public class LoanProduct extends AbstractPersistableCustom<Long> {
enableAutoRepaymentForDownPayment, loanScheduleType, loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting,
supportedInterestRefundTypes, chargeOffBehaviour, isInterestRecognitionOnDisbursementDate, daysInYearCustomStrategy,
enableIncomeCapitalization, capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType,
installmentAmountInMultiplesOf);
installmentAmountInMultiplesOf, enableBuyDownFee, buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType);
this.loanProductMinMaxConstraints = new LoanProductMinMaxConstraints(defaultMinPrincipal, defaultMaxPrincipal,
defaultMinNominalInterestRatePerPeriod, defaultMaxNominalInterestRatePerPeriod, defaultMinNumberOfInstallments,
@@ -36,6 +36,9 @@ import org.apache.fineract.portfolio.common.domain.DaysInYearCustomStrategyType;
import org.apache.fineract.portfolio.common.domain.DaysInYearType;
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanBuyDownFeeCalculationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanBuyDownFeeIncomeType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanBuyDownFeeStrategy;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeCalculationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeStrategy;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeType;
@@ -186,6 +189,21 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
@Column(name = "capitalized_income_type")
private LoanCapitalizedIncomeType capitalizedIncomeType;
@Column(name = "enable_buy_down_fee")
private boolean enableBuyDownFee = false;
@Enumerated(EnumType.STRING)
@Column(name = "buy_down_fee_calculation_type")
private LoanBuyDownFeeCalculationType buyDownFeeCalculationType;
@Enumerated(EnumType.STRING)
@Column(name = "buy_down_fee_strategy")
private LoanBuyDownFeeStrategy buyDownFeeStrategy;
@Enumerated(EnumType.STRING)
@Column(name = "buy_down_fee_income_type")
private LoanBuyDownFeeIncomeType buyDownFeeIncomeType;
@Column(name = "installment_amount_in_multiples_of")
private Integer installmentAmountInMultiplesOf;
@@ -206,7 +224,9 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
final DaysInYearCustomStrategyType daysInYearCustomStrategy, final boolean enableIncomeCapitalization,
final LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType,
final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy, final LoanCapitalizedIncomeType capitalizedIncomeType,
final Integer installmentAmountInMultiplesOf) {
final Integer installmentAmountInMultiplesOf, final boolean enableBuyDownFee,
final LoanBuyDownFeeCalculationType buyDownFeeCalculationType, final LoanBuyDownFeeStrategy buyDownFeeStrategy,
final LoanBuyDownFeeIncomeType buyDownFeeIncomeType) {
final MonetaryCurrency currency = MonetaryCurrency.fromCurrencyData(currencyData);
return new LoanProductRelatedDetail(currency, principal, nominalInterestRatePerPeriod, interestRatePeriodFrequencyType,
@@ -217,7 +237,8 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
isEqualAmortization, enableDownPayment, disbursedAmountPercentageForDownPayment, enableAutoRepaymentForDownPayment,
loanScheduleType, loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes,
chargeOffBehaviour, interestRecognitionOnDisbursementDate, daysInYearCustomStrategy, enableIncomeCapitalization,
capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType, installmentAmountInMultiplesOf);
capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType, installmentAmountInMultiplesOf,
enableBuyDownFee, buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType);
}
protected LoanProductRelatedDetail() {
@@ -241,7 +262,9 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
final DaysInYearCustomStrategyType daysInYearCustomStrategy, final boolean enableIncomeCapitalization,
final LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType,
final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy, final LoanCapitalizedIncomeType capitalizedIncomeType,
final Integer installmentAmountInMultiplesOf) {
final Integer installmentAmountInMultiplesOf, final boolean enableBuyDownFee,
final LoanBuyDownFeeCalculationType buyDownFeeCalculationType, final LoanBuyDownFeeStrategy buyDownFeeStrategy,
final LoanBuyDownFeeIncomeType buyDownFeeIncomeType) {
this.currency = currency;
this.principal = defaultPrincipal;
this.nominalInterestRatePerPeriod = defaultNominalInterestRatePerPeriod;
@@ -284,6 +307,10 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
this.capitalizedIncomeStrategy = capitalizedIncomeStrategy;
this.capitalizedIncomeType = capitalizedIncomeType;
this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
this.enableBuyDownFee = enableBuyDownFee;
this.buyDownFeeCalculationType = buyDownFeeCalculationType;
this.buyDownFeeStrategy = buyDownFeeStrategy;
this.buyDownFeeIncomeType = buyDownFeeIncomeType;
}
private Integer defaultToNullIfZero(final Integer value) {