FINERACT-2232: Progressive loan income capitalization config

This commit is contained in:
adam.magyari
2025-04-15 19:45:25 +02:00
committed by Adam Saghy
parent 6a65bc6592
commit 7df7be2b16
22 changed files with 601 additions and 32 deletions
@@ -0,0 +1,48 @@
/**
* 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 java.util.Arrays;
import java.util.List;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.core.data.StringEnumOptionData;
@Getter
@RequiredArgsConstructor
public enum LoanCapitalizedIncomeCalculationType {
FLAT("loanCapitalizedIncomeCalculationType.flat", "Flat");
private final String code;
private final String humanReadableName;
public static List<StringEnumOptionData> getValuesAsStringEnumOptionDataList() {
return Arrays.stream(values()).map(v -> new StringEnumOptionData(v.name(), v.getCode(), v.getHumanReadableName())).toList();
}
public StringEnumOptionData getValueAsStringEnumOptionData() {
return new StringEnumOptionData(name(), getCode(), getHumanReadableName());
}
public static StringEnumOptionData getStringEnumOptionData(String name) {
return name == null || name.trim().isEmpty() ? null
: LoanCapitalizedIncomeCalculationType.valueOf(name).getValueAsStringEnumOptionData();
}
}
@@ -0,0 +1,47 @@
/**
* 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 java.util.Arrays;
import java.util.List;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.core.data.StringEnumOptionData;
@Getter
@RequiredArgsConstructor
public enum LoanCapitalizedIncomeStrategy {
EQUAL_AMORTIZATION("capitalizedIncome.strategy.equalAmortization", "Equal amortization");
private final String code;
private final String humanReadableName;
public static List<StringEnumOptionData> getValuesAsStringEnumOptionDataList() {
return Arrays.stream(values()).map(v -> new StringEnumOptionData(v.name(), v.getCode(), v.getHumanReadableName())).toList();
}
public StringEnumOptionData getValueAsStringEnumOptionData() {
return new StringEnumOptionData(name(), getCode(), getHumanReadableName());
}
public static StringEnumOptionData getStringEnumOptionData(String name) {
return name == null || name.trim().isEmpty() ? null : LoanCapitalizedIncomeStrategy.valueOf(name).getValueAsStringEnumOptionData();
}
}
@@ -46,6 +46,8 @@ 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.LoanCapitalizedIncomeCalculationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeStrategy;
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeOffBehaviour;
import org.apache.fineract.portfolio.loanproduct.data.LoanProductRelatedDetailMinimumData;
import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod;
@@ -232,6 +234,9 @@ public final class LoanApplicationTerms {
private LoanChargeOffBehaviour chargeOffBehaviour;
private boolean interestRecognitionOnDisbursementDate;
private DaysInYearCustomStrategyType daysInYearCustomStrategy;
private boolean enableIncomeCapitalization;
private LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType;
private LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy;
private LoanApplicationTerms(Builder builder) {
this.currency = builder.currency;
@@ -268,6 +273,9 @@ public final class LoanApplicationTerms {
} else {
this.downPaymentAmount = Money.zero(getCurrency(), builder.mc);
}
this.enableIncomeCapitalization = builder.enableIncomeCapitalization;
this.capitalizedIncomeCalculationType = builder.capitalizedIncomeCalculationType;
this.capitalizedIncomeStrategy = builder.capitalizedIncomeStrategy;
}
public static class Builder {
@@ -297,6 +305,9 @@ public final class LoanApplicationTerms {
private MathContext mc;
private Boolean interestRecognitionOnDisbursementDate;
private DaysInYearCustomStrategyType daysInYearCustomStrategy;
private boolean enableIncomeCapitalization;
private LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType;
private LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy;
public Builder currency(CurrencyData currency) {
this.currency = currency;
@@ -413,6 +424,21 @@ public final class LoanApplicationTerms {
return this;
}
public Builder enableIncomeCapitalization(boolean value) {
this.enableIncomeCapitalization = value;
return this;
}
public Builder capitalizedIncomeCalculationType(LoanCapitalizedIncomeCalculationType value) {
this.capitalizedIncomeCalculationType = value;
return this;
}
public Builder capitalizedIncomeStrategy(LoanCapitalizedIncomeStrategy value) {
this.capitalizedIncomeStrategy = value;
return this;
}
public LoanApplicationTerms build() {
return new LoanApplicationTerms(this);
}
@@ -480,7 +506,9 @@ public final class LoanApplicationTerms {
final LoanScheduleProcessingType loanScheduleProcessingType, final Integer fixedLength,
final boolean enableAccrualActivityPosting, final List<LoanSupportedInterestRefundTypes> supportedInterestRefundTypes,
final LoanChargeOffBehaviour chargeOffBehaviour, final boolean interestRecognitionOnDisbursementDate,
final DaysInYearCustomStrategyType daysInYearCustomStrategy) {
final DaysInYearCustomStrategyType daysInYearCustomStrategy, final boolean enableIncomeCapitalization,
final LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType,
final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy) {
final LoanRescheduleStrategyMethod rescheduleStrategyMethod = null;
final CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
@@ -500,7 +528,8 @@ public final class LoanApplicationTerms {
isPrincipalCompoundingDisabledForOverdueLoans, enableDownPayment, disbursedAmountPercentageForDownPayment,
isAutoRepaymentForDownPaymentEnabled, repaymentStartDateType, submittedOnDate, loanScheduleType, loanScheduleProcessingType,
fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate, daysInYearCustomStrategy);
interestRecognitionOnDisbursementDate, daysInYearCustomStrategy, enableIncomeCapitalization,
capitalizedIncomeCalculationType, capitalizedIncomeStrategy);
}
@@ -574,7 +603,9 @@ public final class LoanApplicationTerms {
disbursedAmountPercentageForDownPayment, isAutoRepaymentForDownPaymentEnabled, repaymentStartDateType, submittedOnDate,
loanScheduleType, loanScheduleProcessingType, fixedLength, loanProductRelatedDetail.isEnableAccrualActivityPosting(),
loanProductRelatedDetail.getSupportedInterestRefundTypes(), loanProductRelatedDetail.getChargeOffBehaviour(),
loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate(), loanProductRelatedDetail.getDaysInYearCustomStrategy());
loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate(), loanProductRelatedDetail.getDaysInYearCustomStrategy(),
loanProductRelatedDetail.isEnableIncomeCapitalization(), loanProductRelatedDetail.getCapitalizedIncomeCalculationType(),
loanProductRelatedDetail.getCapitalizedIncomeStrategy());
}
private LoanApplicationTerms(final CurrencyData currency, final Integer loanTermFrequency,
@@ -605,7 +636,9 @@ public final class LoanApplicationTerms {
final RepaymentStartDateType repaymentStartDateType, final LocalDate submittedOnDate, final LoanScheduleType loanScheduleType,
final LoanScheduleProcessingType loanScheduleProcessingType, final Integer fixedLength, boolean enableAccrualActivityPosting,
final List<LoanSupportedInterestRefundTypes> supportedInterestRefundTypes, final LoanChargeOffBehaviour chargeOffBehaviour,
final boolean interestRecognitionOnDisbursementDate, final DaysInYearCustomStrategyType daysInYearCustomStrategy) {
final boolean interestRecognitionOnDisbursementDate, final DaysInYearCustomStrategyType daysInYearCustomStrategy,
final boolean enableIncomeCapitalization, final LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType,
final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy) {
this.currency = currency;
this.loanTermFrequency = loanTermFrequency;
@@ -707,6 +740,9 @@ public final class LoanApplicationTerms {
this.chargeOffBehaviour = chargeOffBehaviour;
this.interestRecognitionOnDisbursementDate = interestRecognitionOnDisbursementDate;
this.daysInYearCustomStrategy = daysInYearCustomStrategy;
this.enableIncomeCapitalization = enableIncomeCapitalization;
this.capitalizedIncomeCalculationType = capitalizedIncomeCalculationType;
this.capitalizedIncomeStrategy = capitalizedIncomeStrategy;
}
public Money adjustPrincipalIfLastRepaymentPeriod(final Money principalForPeriod, final Money totalCumulativePrincipalToDate,
@@ -1568,7 +1604,8 @@ public final class LoanApplicationTerms {
this.interestRecalculationEnabled, this.isEqualAmortization, this.isDownPaymentEnabled,
this.disbursedAmountPercentageForDownPayment, this.isAutoRepaymentForDownPaymentEnabled, this.loanScheduleType,
this.loanScheduleProcessingType, this.fixedLength, this.enableAccrualActivityPosting, this.supportedInterestRefundTypes,
this.chargeOffBehaviour, this.interestRecognitionOnDisbursementDate, this.daysInYearCustomStrategy);
this.chargeOffBehaviour, this.interestRecognitionOnDisbursementDate, this.daysInYearCustomStrategy,
this.enableIncomeCapitalization, this.capitalizedIncomeCalculationType, this.capitalizedIncomeStrategy);
}
public LoanProductMinimumRepaymentScheduleRelatedDetail toLoanProductRelatedDetailMinimumData() {
@@ -171,4 +171,9 @@ public interface LoanProductConstants {
String CHARGE_OFF_BEHAVIOUR = "chargeOffBehaviour";
String INTEREST_RECOGNITION_ON_DISBURSEMENT_DATE = "interestRecognitionOnDisbursementDate";
// Capitalized income
String ENABLE_INCOME_CAPITALIZATION_PARAM_NAME = "enableIncomeCapitalization";
String CAPITALIZED_INCOME_CALCULATION_TYPE_PARAM_NAME = "capitalizedIncomeCalculationType";
String CAPITALIZED_INCOME_STRATEGY_PARAM_NAME = "capitalizedIncomeStrategy";
}
@@ -195,6 +195,12 @@ public final class LoanProductsApiResourceSwagger {
public Boolean enableAccrualActivityPosting;
@Schema(example = "false")
public Boolean interestRecognitionOnDisbursementDate;
@Schema(example = "false")
public Boolean enableIncomeCapitalization;
@Schema(example = "FLAT", allowableValues = "FLAT")
public String capitalizedIncomeCalculationType;
@Schema(example = "EQUAL_AMORTIZATION", allowableValues = "EQUAL_AMORTIZATION")
public String capitalizedIncomeStrategy;
// Interest Recalculation
@Schema(example = "false")
@@ -651,6 +657,12 @@ public final class LoanProductsApiResourceSwagger {
public StringEnumOptionData chargeOffBehaviour;
@Schema(example = "false")
public Boolean interestRecognitionOnDisbursementDate;
@Schema(example = "false")
public Boolean enableIncomeCapitalization;
@Schema(example = "FLAT")
public StringEnumOptionData capitalizedIncomeCalculationType;
@Schema(example = "EQUAL_AMORTIZATION")
public StringEnumOptionData capitalizedIncomeStrategy;
}
@Schema(description = "GetLoanProductsTemplateResponse")
@@ -1097,6 +1109,14 @@ public final class LoanProductsApiResourceSwagger {
public List<GetLoanProductsChargeOffReasonOptions> chargeOffReasonOptions;
public StringEnumOptionData chargeOffBehaviour;
public List<StringEnumOptionData> chargeOffBehaviourOptions;
@Schema(example = "false")
public Boolean enableIncomeCapitalization;
@Schema(example = "FLAT")
public StringEnumOptionData capitalizedIncomeCalculationType;
@Schema(example = "EQUAL_AMORTIZATION")
public StringEnumOptionData capitalizedIncomeStrategy;
public List<StringEnumOptionData> capitalizedIncomeCalculationTypeOptions;
public List<StringEnumOptionData> capitalizedIncomeStrategyOptions;
}
@Schema(description = "GetLoanProductsProductIdResponse")
@@ -1416,6 +1436,14 @@ public final class LoanProductsApiResourceSwagger {
public StringEnumOptionData chargeOffBehaviour;
@Schema(example = "false")
public Boolean interestRecognitionOnDisbursementDate;
@Schema(example = "false")
public Boolean enableIncomeCapitalization;
@Schema(example = "FLAT")
public StringEnumOptionData capitalizedIncomeCalculationType;
@Schema(example = "EQUAL_AMORTIZATION")
public StringEnumOptionData capitalizedIncomeStrategy;
public List<StringEnumOptionData> capitalizedIncomeCalculationTypeOptions;
public List<StringEnumOptionData> capitalizedIncomeStrategyOptions;
}
@Schema(description = "PutLoanProductsProductIdRequest")
@@ -1669,6 +1697,12 @@ public final class LoanProductsApiResourceSwagger {
public List<String> supportedInterestRefundTypes;
@Schema(example = "REGULAR")
public String chargeOffBehaviour;
@Schema(example = "false")
public Boolean enableIncomeCapitalization;
@Schema(example = "FLAT", allowableValues = "FLAT")
public String capitalizedIncomeCalculationType;
@Schema(example = "EQUAL_AMORTIZATION", allowableValues = "EQUAL_AMORTIZATION")
public String capitalizedIncomeStrategy;
}
public static final class AdvancedPaymentData {
@@ -48,6 +48,8 @@ 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.LoanCapitalizedIncomeCalculationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeStrategy;
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeOffBehaviour;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleProcessingType;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
@@ -238,6 +240,11 @@ public class LoanProductData implements Serializable {
private final boolean interestRecognitionOnDisbursementDate;
private final List<StringEnumOptionData> daysInYearCustomStrategyOptions;
private final StringEnumOptionData daysInYearCustomStrategy;
private Boolean enableIncomeCapitalization;
private StringEnumOptionData capitalizedIncomeCalculationType;
private StringEnumOptionData capitalizedIncomeStrategy;
private List<StringEnumOptionData> capitalizedIncomeCalculationTypeOptions;
private List<StringEnumOptionData> capitalizedIncomeStrategyOptions;
/**
* Used when returning lookup information about loan product for dropdowns.
@@ -342,6 +349,9 @@ public class LoanProductData implements Serializable {
final StringEnumOptionData chargeOffBehaviour = null;
final boolean interestRecognitionOnDisbursementDate = false;
final StringEnumOptionData daysInYearTypeCustomStrategy = null;
final boolean enableIncomeCapitalization = false;
final StringEnumOptionData capitalizedIncomeCalculationType = null;
final StringEnumOptionData capitalizedIncomeStrategy = null;
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
@@ -363,7 +373,8 @@ public class LoanProductData implements Serializable {
overDueDaysForRepaymentEvent, enableDownPayment, disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment,
paymentAllocation, creditAllocation, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy);
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy, enableIncomeCapitalization,
capitalizedIncomeCalculationType, capitalizedIncomeStrategy);
}
@@ -468,6 +479,9 @@ public class LoanProductData implements Serializable {
final StringEnumOptionData chargeOffBehaviour = null;
final boolean interestRecognitionOnDisbursementDate = false;
final StringEnumOptionData daysInYearTypeCustomStrategy = null;
final boolean enableIncomeCapitalization = false;
final StringEnumOptionData capitalizedIncomeCalculationType = null;
final StringEnumOptionData capitalizedIncomeStrategy = null;
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
@@ -489,7 +503,8 @@ public class LoanProductData implements Serializable {
overDueDaysForRepaymentEvent, enableDownPayment, disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment,
paymentAllocation, creditAllocation, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy);
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy, enableIncomeCapitalization,
capitalizedIncomeCalculationType, capitalizedIncomeStrategy);
}
@@ -601,6 +616,9 @@ public class LoanProductData implements Serializable {
final StringEnumOptionData chargeOffBehaviour = LoanChargeOffBehaviour.REGULAR.getValueAsStringEnumOptionData();
final boolean interestRecognitionOnDisbursementDate = false;
final StringEnumOptionData daysInYearTypeCustomStrategy = null;
final boolean enableIncomeCapitalization = false;
final StringEnumOptionData capitalizedIncomeCalculationType = null;
final StringEnumOptionData capitalizedIncomeStrategy = null;
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
@@ -622,7 +640,8 @@ public class LoanProductData implements Serializable {
overDueDaysForRepaymentEvent, enableDownPayment, disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment,
paymentAllocation, creditAllocation, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy);
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy, enableIncomeCapitalization,
capitalizedIncomeCalculationType, capitalizedIncomeStrategy);
}
@@ -728,6 +747,9 @@ public class LoanProductData implements Serializable {
final StringEnumOptionData chargeOffBehaviour = null;
final boolean interestRecognitionOnDisbursementDate = false;
final StringEnumOptionData daysInYearTypeCustomStrategy = null;
final boolean enableIncomeCapitalization = false;
final StringEnumOptionData capitalizedIncomeCalculationType = null;
final StringEnumOptionData capitalizedIncomeStrategy = null;
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
@@ -749,7 +771,8 @@ public class LoanProductData implements Serializable {
overDueDaysForRepaymentEvent, enableDownPayment, disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment,
paymentAllocation, creditAllocationData, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy);
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy, enableIncomeCapitalization,
capitalizedIncomeCalculationType, capitalizedIncomeStrategy);
}
public static LoanProductData withAccountingDetails(final LoanProductData productData, final Map<String, Object> accountingMappings,
@@ -804,7 +827,8 @@ public class LoanProductData implements Serializable {
final EnumOptionData loanScheduleType, final EnumOptionData loanScheduleProcessingType, final Integer fixedLength,
final boolean enableAccrualActivityPosting, final List<StringEnumOptionData> supportedInterestRefundTypes,
StringEnumOptionData chargeOffBehaviour, final boolean interestRecognitionOnDisbursementDate,
final StringEnumOptionData daysInYearCustomStrategy) {
final StringEnumOptionData daysInYearCustomStrategy, final boolean enableIncomeCapitalization,
final StringEnumOptionData capitalizedIncomeCalculationType, final StringEnumOptionData capitalizedIncomeStrategy) {
this.id = id;
this.name = name;
this.shortName = shortName;
@@ -861,6 +885,9 @@ public class LoanProductData implements Serializable {
this.rates = rates;
this.isRatesEnabled = isRatesEnabled;
this.daysInYearCustomStrategy = daysInYearCustomStrategy;
this.enableIncomeCapitalization = enableIncomeCapitalization;
this.capitalizedIncomeCalculationType = capitalizedIncomeCalculationType;
this.capitalizedIncomeStrategy = capitalizedIncomeStrategy;
this.chargeOptions = null;
this.penaltyOptions = null;
@@ -950,6 +977,8 @@ public class LoanProductData implements Serializable {
this.chargeOffReasonOptions = null;
this.interestRecognitionOnDisbursementDate = interestRecognitionOnDisbursementDate;
this.daysInYearCustomStrategyOptions = DaysInYearCustomStrategyType.getValuesAsStringEnumOptionDataList();
this.capitalizedIncomeCalculationTypeOptions = LoanCapitalizedIncomeCalculationType.getValuesAsStringEnumOptionDataList();
this.capitalizedIncomeStrategyOptions = LoanCapitalizedIncomeStrategy.getValuesAsStringEnumOptionDataList();
}
public LoanProductData(final LoanProductData productData, final Collection<ChargeData> chargeOptions,
@@ -974,7 +1003,9 @@ public class LoanProductData implements Serializable {
final List<EnumOptionData> creditAllocationAllocationTypes,
final List<StringEnumOptionData> supportedInterestRefundTypesOptions,
final List<StringEnumOptionData> chargeOffBehaviourOptions, final List<CodeValueData> chargeOffReasonOptions,
final List<StringEnumOptionData> daysInYearCustomStrategyOptions) {
final List<StringEnumOptionData> daysInYearCustomStrategyOptions,
final List<StringEnumOptionData> capitalizedIncomeCalculationTypeOptions,
final List<StringEnumOptionData> capitalizedIncomeStrategyOptions) {
this.id = productData.id;
this.name = productData.name;
@@ -1138,6 +1169,11 @@ public class LoanProductData implements Serializable {
this.interestRecognitionOnDisbursementDate = productData.interestRecognitionOnDisbursementDate;
this.daysInYearCustomStrategyOptions = daysInYearCustomStrategyOptions;
this.daysInYearCustomStrategy = productData.daysInYearCustomStrategy;
this.enableIncomeCapitalization = productData.enableIncomeCapitalization;
this.capitalizedIncomeCalculationType = productData.capitalizedIncomeCalculationType;
this.capitalizedIncomeStrategy = productData.capitalizedIncomeStrategy;
this.capitalizedIncomeCalculationTypeOptions = capitalizedIncomeCalculationTypeOptions;
this.capitalizedIncomeStrategyOptions = capitalizedIncomeStrategyOptions;
}
private Collection<ChargeData> nullIfEmpty(final Collection<ChargeData> charges) {
@@ -59,6 +59,8 @@ 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.LoanCapitalizedIncomeCalculationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeStrategy;
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeOffBehaviour;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleProcessingType;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
@@ -280,7 +282,9 @@ public class LoanProduct extends AbstractPersistableCustom<Long> {
final LoanScheduleProcessingType loanScheduleProcessingType, final Integer fixedLength,
final boolean enableAccrualActivityPosting, final List<LoanSupportedInterestRefundTypes> supportedInterestRefundTypes,
final LoanChargeOffBehaviour chargeOffBehaviour, final boolean isInterestRecognitionOnDisbursementDate,
final DaysInYearCustomStrategyType daysInYearCustomStrategy) {
final DaysInYearCustomStrategyType daysInYearCustomStrategy, final boolean enableIncomeCapitalization,
final LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType,
final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy) {
this.fund = fund;
this.transactionProcessingStrategyCode = transactionProcessingStrategyCode;
@@ -330,7 +334,8 @@ public class LoanProduct extends AbstractPersistableCustom<Long> {
inArrearsTolerance, graceOnArrearsAgeing, daysInMonthType.getValue(), daysInYearType.getValue(),
isInterestRecalculationEnabled, isEqualAmortization, enableDownPayment, disbursedAmountPercentageForDownPayment,
enableAutoRepaymentForDownPayment, loanScheduleType, loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting,
supportedInterestRefundTypes, chargeOffBehaviour, isInterestRecognitionOnDisbursementDate, daysInYearCustomStrategy);
supportedInterestRefundTypes, chargeOffBehaviour, isInterestRecognitionOnDisbursementDate, daysInYearCustomStrategy,
enableIncomeCapitalization, capitalizedIncomeCalculationType, capitalizedIncomeStrategy);
this.loanProductMinMaxConstraints = new LoanProductMinMaxConstraints(defaultMinPrincipal, defaultMaxPrincipal,
defaultMinNominalInterestRatePerPeriod, defaultMaxNominalInterestRatePerPeriod, defaultMinNumberOfInstallments,
@@ -36,6 +36,8 @@ 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.LoanCapitalizedIncomeCalculationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeStrategy;
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeOffBehaviour;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleProcessingType;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
@@ -168,6 +170,17 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
@Column(name = "days_in_year_custom_strategy")
private DaysInYearCustomStrategyType daysInYearCustomStrategy;
@Column(name = "enable_income_capitalization")
private boolean enableIncomeCapitalization = false;
@Enumerated(EnumType.STRING)
@Column(name = "capitalized_income_calculation_type")
private LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType;
@Enumerated(EnumType.STRING)
@Column(name = "capitalized_income_strategy")
private LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy;
public static LoanProductRelatedDetail createFrom(final CurrencyData currencyData, final BigDecimal principal,
final BigDecimal nominalInterestRatePerPeriod, final PeriodFrequencyType interestRatePeriodFrequencyType,
final BigDecimal nominalAnnualInterestRate, final InterestMethod interestMethod,
@@ -182,7 +195,9 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
final LoanScheduleProcessingType loanScheduleProcessingType, final Integer fixedLength,
final boolean enableAccrualActivityPosting, final List<LoanSupportedInterestRefundTypes> supportedInterestRefundTypes,
final LoanChargeOffBehaviour chargeOffBehaviour, final boolean interestRecognitionOnDisbursementDate,
final DaysInYearCustomStrategyType daysInYearCustomStrategy) {
final DaysInYearCustomStrategyType daysInYearCustomStrategy, final boolean enableIncomeCapitalization,
final LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType,
final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy) {
final MonetaryCurrency currency = MonetaryCurrency.fromCurrencyData(currencyData);
return new LoanProductRelatedDetail(currency, principal, nominalInterestRatePerPeriod, interestRatePeriodFrequencyType,
@@ -192,7 +207,8 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
inArrearsTolerance, graceOnArrearsAgeing, daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
isEqualAmortization, enableDownPayment, disbursedAmountPercentageForDownPayment, enableAutoRepaymentForDownPayment,
loanScheduleType, loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes,
chargeOffBehaviour, interestRecognitionOnDisbursementDate, daysInYearCustomStrategy);
chargeOffBehaviour, interestRecognitionOnDisbursementDate, daysInYearCustomStrategy, enableIncomeCapitalization,
capitalizedIncomeCalculationType, capitalizedIncomeStrategy);
}
protected LoanProductRelatedDetail() {
@@ -213,7 +229,9 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
final LoanScheduleProcessingType loanScheduleProcessingType, final Integer fixedLength,
final boolean enableAccrualActivityPosting, List<LoanSupportedInterestRefundTypes> supportedInterestRefundTypes,
final LoanChargeOffBehaviour chargeOffBehaviour, final boolean interestRecognitionOnDisbursementDate,
final DaysInYearCustomStrategyType daysInYearCustomStrategy) {
final DaysInYearCustomStrategyType daysInYearCustomStrategy, final boolean enableIncomeCapitalization,
final LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType,
final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy) {
this.currency = currency;
this.principal = defaultPrincipal;
this.nominalInterestRatePerPeriod = defaultNominalInterestRatePerPeriod;
@@ -251,6 +269,9 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
this.chargeOffBehaviour = chargeOffBehaviour;
this.interestRecognitionOnDisbursementDate = interestRecognitionOnDisbursementDate;
this.daysInYearCustomStrategy = daysInYearCustomStrategy;
this.enableIncomeCapitalization = enableIncomeCapitalization;
this.capitalizedIncomeCalculationType = capitalizedIncomeCalculationType;
this.capitalizedIncomeStrategy = capitalizedIncomeStrategy;
}
private Integer defaultToNullIfZero(final Integer value) {