You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ad...@apache.org on 2025/04/25 10:35:31 UTC
(fineract) 02/02: FINERACT-2232: Capitalized income - income type config
This is an automated email from the ASF dual-hosted git repository.
adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
commit d88f634197688472530a4fa58a92b7fdbce912b6
Author: adam.magyari <ma...@gmail.com>
AuthorDate: Thu Apr 24 07:56:57 2025 +0200
FINERACT-2232: Capitalized income - income type config
---
.../domain/LoanCapitalizedIncomeType.java | 33 +++++++++++++
.../loanschedule/domain/LoanApplicationTerms.java | 21 ++++++--
.../loanproduct/LoanProductConstants.java | 1 +
.../api/LoanProductsApiResourceSwagger.java | 12 +++++
.../loanproduct/data/LoanProductData.java | 25 +++++++---
.../portfolio/loanproduct/domain/LoanProduct.java | 5 +-
.../domain/LoanProductRelatedDetail.java | 12 +++--
.../loanaccount/api/LoansApiResource.java | 4 +-
.../loanaccount/api/LoansApiResourceSwagger.java | 4 ++
.../loanaccount/data/LoanAccountData.java | 12 +++--
.../service/LoanScheduleAssembler.java | 3 +-
.../loanaccount/service/LoanProductAssembler.java | 6 ++-
.../LoanProductRelatedDetailUpdateUtil.java | 8 +++
.../service/LoanReadPlatformServiceImpl.java | 6 ++-
.../loanproduct/api/LoanProductsApiResource.java | 8 ++-
.../serialization/LoanProductDataValidator.java | 15 +++++-
.../LoanProductReadPlatformServiceImpl.java | 9 +++-
.../db/changelog/tenant/changelog-tenant.xml | 1 +
...74_loan_product_add_capitalized_income_type.xml | 37 ++++++++++++++
.../domain/DefaultScheduledDateGeneratorTest.java | 4 +-
.../fineract/integrationtests/LoanProductTest.java | 57 ++++++++++++++++++----
21 files changed, 242 insertions(+), 41 deletions(-)
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCapitalizedIncomeType.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCapitalizedIncomeType.java
new file mode 100644
index 0000000000..58d233135e
--- /dev/null
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCapitalizedIncomeType.java
@@ -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 LoanCapitalizedIncomeType implements ApiFacingEnum<LoanCapitalizedIncomeType> {
+
+ FEE("capitalizedIncome.incomeType.fee", "Fee"), INTEREST("capitalizedIncome.incomeType.interest", "Interest");
+
+ private final String code;
+ private final String humanReadableName;
+}
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
index f517a1b240..2c2cad5bbc 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
@@ -48,6 +48,7 @@ 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.LoanCapitalizedIncomeType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeOffBehaviour;
import org.apache.fineract.portfolio.loanproduct.data.LoanProductRelatedDetailMinimumData;
import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod;
@@ -237,6 +238,7 @@ public final class LoanApplicationTerms {
private boolean enableIncomeCapitalization;
private LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType;
private LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy;
+ private LoanCapitalizedIncomeType capitalizedIncomeType;
private LoanApplicationTerms(Builder builder) {
this.currency = builder.currency;
@@ -276,6 +278,7 @@ public final class LoanApplicationTerms {
this.enableIncomeCapitalization = builder.enableIncomeCapitalization;
this.capitalizedIncomeCalculationType = builder.capitalizedIncomeCalculationType;
this.capitalizedIncomeStrategy = builder.capitalizedIncomeStrategy;
+ this.capitalizedIncomeType = builder.capitalizedIncomeType;
}
public static class Builder {
@@ -308,6 +311,7 @@ public final class LoanApplicationTerms {
private boolean enableIncomeCapitalization;
private LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType;
private LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy;
+ private LoanCapitalizedIncomeType capitalizedIncomeType;
public Builder currency(CurrencyData currency) {
this.currency = currency;
@@ -439,6 +443,11 @@ public final class LoanApplicationTerms {
return this;
}
+ public Builder capitalizedIncomeType(LoanCapitalizedIncomeType value) {
+ this.capitalizedIncomeType = value;
+ return this;
+ }
+
public LoanApplicationTerms build() {
return new LoanApplicationTerms(this);
}
@@ -508,7 +517,7 @@ public final class LoanApplicationTerms {
final LoanChargeOffBehaviour chargeOffBehaviour, final boolean interestRecognitionOnDisbursementDate,
final DaysInYearCustomStrategyType daysInYearCustomStrategy, final boolean enableIncomeCapitalization,
final LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType,
- final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy) {
+ final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy, final LoanCapitalizedIncomeType capitalizedIncomeType) {
final LoanRescheduleStrategyMethod rescheduleStrategyMethod = null;
final CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
@@ -529,7 +538,7 @@ public final class LoanApplicationTerms {
isAutoRepaymentForDownPaymentEnabled, repaymentStartDateType, submittedOnDate, loanScheduleType, loanScheduleProcessingType,
fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate, daysInYearCustomStrategy, enableIncomeCapitalization,
- capitalizedIncomeCalculationType, capitalizedIncomeStrategy);
+ capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType);
}
@@ -605,7 +614,7 @@ public final class LoanApplicationTerms {
loanProductRelatedDetail.getSupportedInterestRefundTypes(), loanProductRelatedDetail.getChargeOffBehaviour(),
loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate(), loanProductRelatedDetail.getDaysInYearCustomStrategy(),
loanProductRelatedDetail.isEnableIncomeCapitalization(), loanProductRelatedDetail.getCapitalizedIncomeCalculationType(),
- loanProductRelatedDetail.getCapitalizedIncomeStrategy());
+ loanProductRelatedDetail.getCapitalizedIncomeStrategy(), loanProductRelatedDetail.getCapitalizedIncomeType());
}
private LoanApplicationTerms(final CurrencyData currency, final Integer loanTermFrequency,
@@ -638,7 +647,7 @@ 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 LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy, final LoanCapitalizedIncomeType capitalizedIncomeType) {
this.currency = currency;
this.loanTermFrequency = loanTermFrequency;
@@ -743,6 +752,7 @@ public final class LoanApplicationTerms {
this.enableIncomeCapitalization = enableIncomeCapitalization;
this.capitalizedIncomeCalculationType = capitalizedIncomeCalculationType;
this.capitalizedIncomeStrategy = capitalizedIncomeStrategy;
+ this.capitalizedIncomeType = capitalizedIncomeType;
}
public Money adjustPrincipalIfLastRepaymentPeriod(final Money principalForPeriod, final Money totalCumulativePrincipalToDate,
@@ -1605,7 +1615,8 @@ public final class LoanApplicationTerms {
this.disbursedAmountPercentageForDownPayment, this.isAutoRepaymentForDownPaymentEnabled, this.loanScheduleType,
this.loanScheduleProcessingType, this.fixedLength, this.enableAccrualActivityPosting, this.supportedInterestRefundTypes,
this.chargeOffBehaviour, this.interestRecognitionOnDisbursementDate, this.daysInYearCustomStrategy,
- this.enableIncomeCapitalization, this.capitalizedIncomeCalculationType, this.capitalizedIncomeStrategy);
+ this.enableIncomeCapitalization, this.capitalizedIncomeCalculationType, this.capitalizedIncomeStrategy,
+ this.capitalizedIncomeType);
}
public LoanProductMinimumRepaymentScheduleRelatedDetail toLoanProductRelatedDetailMinimumData() {
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/LoanProductConstants.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/LoanProductConstants.java
index 1e803ab0af..bda1839495 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/LoanProductConstants.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/LoanProductConstants.java
@@ -176,4 +176,5 @@ public interface LoanProductConstants {
String ENABLE_INCOME_CAPITALIZATION_PARAM_NAME = "enableIncomeCapitalization";
String CAPITALIZED_INCOME_CALCULATION_TYPE_PARAM_NAME = "capitalizedIncomeCalculationType";
String CAPITALIZED_INCOME_STRATEGY_PARAM_NAME = "capitalizedIncomeStrategy";
+ String CAPITALIZED_INCOME_TYPE_PARAM_NAME = "capitalizedIncomeType";
}
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
index 0ccc7ffeda..3e12aca89f 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
@@ -201,6 +201,8 @@ public final class LoanProductsApiResourceSwagger {
public String capitalizedIncomeCalculationType;
@Schema(example = "EQUAL_AMORTIZATION", allowableValues = "EQUAL_AMORTIZATION")
public String capitalizedIncomeStrategy;
+ @Schema(example = "FEE", allowableValues = { "FEE", "INTEREST" })
+ public String capitalizedIncomeType;
// Interest Recalculation
@Schema(example = "false")
@@ -667,6 +669,8 @@ public final class LoanProductsApiResourceSwagger {
public StringEnumOptionData capitalizedIncomeCalculationType;
@Schema(example = "EQUAL_AMORTIZATION")
public StringEnumOptionData capitalizedIncomeStrategy;
+ @Schema(example = "FEE")
+ public StringEnumOptionData capitalizedIncomeType;
}
@Schema(description = "GetLoanProductsTemplateResponse")
@@ -1119,8 +1123,11 @@ public final class LoanProductsApiResourceSwagger {
public StringEnumOptionData capitalizedIncomeCalculationType;
@Schema(example = "EQUAL_AMORTIZATION")
public StringEnumOptionData capitalizedIncomeStrategy;
+ @Schema(example = "FEE")
+ public StringEnumOptionData capitalizedIncomeType;
public List<StringEnumOptionData> capitalizedIncomeCalculationTypeOptions;
public List<StringEnumOptionData> capitalizedIncomeStrategyOptions;
+ public List<StringEnumOptionData> capitalizedIncomeTypeOptions;
}
@Schema(description = "GetLoanProductsProductIdResponse")
@@ -1448,8 +1455,11 @@ public final class LoanProductsApiResourceSwagger {
public StringEnumOptionData capitalizedIncomeCalculationType;
@Schema(example = "EQUAL_AMORTIZATION")
public StringEnumOptionData capitalizedIncomeStrategy;
+ @Schema(example = "FEE")
+ public StringEnumOptionData capitalizedIncomeType;
public List<StringEnumOptionData> capitalizedIncomeCalculationTypeOptions;
public List<StringEnumOptionData> capitalizedIncomeStrategyOptions;
+ public List<StringEnumOptionData> capitalizedIncomeTypeOptions;
}
@Schema(description = "PutLoanProductsProductIdRequest")
@@ -1713,6 +1723,8 @@ public final class LoanProductsApiResourceSwagger {
public String capitalizedIncomeCalculationType;
@Schema(example = "EQUAL_AMORTIZATION", allowableValues = "EQUAL_AMORTIZATION")
public String capitalizedIncomeStrategy;
+ @Schema(example = "FEE", allowableValues = { "FEE", "INTEREST" })
+ public String capitalizedIncomeType;
}
public static final class AdvancedPaymentData {
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
index bcece9c7a4..a9e0bfbcc5 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
@@ -51,6 +51,7 @@ 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.LoanCapitalizedIncomeType;
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;
@@ -244,8 +245,10 @@ public class LoanProductData implements Serializable {
private Boolean enableIncomeCapitalization;
private StringEnumOptionData capitalizedIncomeCalculationType;
private StringEnumOptionData capitalizedIncomeStrategy;
+ private final StringEnumOptionData capitalizedIncomeType;
private List<StringEnumOptionData> capitalizedIncomeCalculationTypeOptions;
private List<StringEnumOptionData> capitalizedIncomeStrategyOptions;
+ private List<StringEnumOptionData> capitalizedIncomeTypeOptions;
/**
* Used when returning lookup information about loan product for dropdowns.
@@ -353,6 +356,7 @@ public class LoanProductData implements Serializable {
final boolean enableIncomeCapitalization = false;
final StringEnumOptionData capitalizedIncomeCalculationType = null;
final StringEnumOptionData capitalizedIncomeStrategy = null;
+ final StringEnumOptionData capitalizedIncomeType = null;
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
@@ -375,7 +379,7 @@ public class LoanProductData implements Serializable {
paymentAllocation, creditAllocation, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy, enableIncomeCapitalization,
- capitalizedIncomeCalculationType, capitalizedIncomeStrategy);
+ capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType);
}
@@ -483,6 +487,7 @@ public class LoanProductData implements Serializable {
final boolean enableIncomeCapitalization = false;
final StringEnumOptionData capitalizedIncomeCalculationType = null;
final StringEnumOptionData capitalizedIncomeStrategy = null;
+ final StringEnumOptionData capitalizedIncomeType = null;
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
@@ -505,7 +510,7 @@ public class LoanProductData implements Serializable {
paymentAllocation, creditAllocation, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy, enableIncomeCapitalization,
- capitalizedIncomeCalculationType, capitalizedIncomeStrategy);
+ capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType);
}
@@ -620,6 +625,7 @@ public class LoanProductData implements Serializable {
final boolean enableIncomeCapitalization = false;
final StringEnumOptionData capitalizedIncomeCalculationType = null;
final StringEnumOptionData capitalizedIncomeStrategy = null;
+ final StringEnumOptionData capitalizedIncomeType = null;
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
@@ -642,7 +648,7 @@ public class LoanProductData implements Serializable {
paymentAllocation, creditAllocation, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy, enableIncomeCapitalization,
- capitalizedIncomeCalculationType, capitalizedIncomeStrategy);
+ capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType);
}
@@ -751,6 +757,7 @@ public class LoanProductData implements Serializable {
final boolean enableIncomeCapitalization = false;
final StringEnumOptionData capitalizedIncomeCalculationType = null;
final StringEnumOptionData capitalizedIncomeStrategy = null;
+ final StringEnumOptionData capitalizedIncomeType = null;
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
@@ -773,7 +780,7 @@ public class LoanProductData implements Serializable {
paymentAllocation, creditAllocationData, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy, enableIncomeCapitalization,
- capitalizedIncomeCalculationType, capitalizedIncomeStrategy);
+ capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType);
}
public static LoanProductData withAccountingDetails(final LoanProductData productData, final Map<String, Object> accountingMappings,
@@ -829,7 +836,8 @@ public class LoanProductData implements Serializable {
final boolean enableAccrualActivityPosting, final List<StringEnumOptionData> supportedInterestRefundTypes,
StringEnumOptionData chargeOffBehaviour, final boolean interestRecognitionOnDisbursementDate,
final StringEnumOptionData daysInYearCustomStrategy, final boolean enableIncomeCapitalization,
- final StringEnumOptionData capitalizedIncomeCalculationType, final StringEnumOptionData capitalizedIncomeStrategy) {
+ final StringEnumOptionData capitalizedIncomeCalculationType, final StringEnumOptionData capitalizedIncomeStrategy,
+ final StringEnumOptionData capitalizedIncomeType) {
this.id = id;
this.name = name;
this.shortName = shortName;
@@ -889,6 +897,7 @@ public class LoanProductData implements Serializable {
this.enableIncomeCapitalization = enableIncomeCapitalization;
this.capitalizedIncomeCalculationType = capitalizedIncomeCalculationType;
this.capitalizedIncomeStrategy = capitalizedIncomeStrategy;
+ this.capitalizedIncomeType = capitalizedIncomeType;
this.chargeOptions = null;
this.penaltyOptions = null;
@@ -981,6 +990,7 @@ public class LoanProductData implements Serializable {
this.capitalizedIncomeCalculationTypeOptions = ApiFacingEnum
.getValuesAsStringEnumOptionDataList(LoanCapitalizedIncomeCalculationType.class);
this.capitalizedIncomeStrategyOptions = ApiFacingEnum.getValuesAsStringEnumOptionDataList(LoanCapitalizedIncomeStrategy.class);
+ this.capitalizedIncomeTypeOptions = ApiFacingEnum.getValuesAsStringEnumOptionDataList(LoanCapitalizedIncomeType.class);
}
public LoanProductData(final LoanProductData productData, final Collection<ChargeData> chargeOptions,
@@ -1007,7 +1017,8 @@ public class LoanProductData implements Serializable {
final List<StringEnumOptionData> chargeOffBehaviourOptions, final List<CodeValueData> chargeOffReasonOptions,
final List<StringEnumOptionData> daysInYearCustomStrategyOptions,
final List<StringEnumOptionData> capitalizedIncomeCalculationTypeOptions,
- final List<StringEnumOptionData> capitalizedIncomeStrategyOptions) {
+ final List<StringEnumOptionData> capitalizedIncomeStrategyOptions,
+ final List<StringEnumOptionData> capitalizedIncomeTypeOptions) {
this.id = productData.id;
this.name = productData.name;
@@ -1174,8 +1185,10 @@ public class LoanProductData implements Serializable {
this.enableIncomeCapitalization = productData.enableIncomeCapitalization;
this.capitalizedIncomeCalculationType = productData.capitalizedIncomeCalculationType;
this.capitalizedIncomeStrategy = productData.capitalizedIncomeStrategy;
+ this.capitalizedIncomeType = productData.capitalizedIncomeType;
this.capitalizedIncomeCalculationTypeOptions = capitalizedIncomeCalculationTypeOptions;
this.capitalizedIncomeStrategyOptions = capitalizedIncomeStrategyOptions;
+ this.capitalizedIncomeTypeOptions = capitalizedIncomeTypeOptions;
}
private Collection<ChargeData> nullIfEmpty(final Collection<ChargeData> charges) {
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java
index 31e4ab8a1d..d9f7dbd713 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java
@@ -61,6 +61,7 @@ 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.LoanCapitalizedIncomeType;
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;
@@ -284,7 +285,7 @@ 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 LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy, final LoanCapitalizedIncomeType capitalizedIncomeType) {
this.fund = fund;
this.transactionProcessingStrategyCode = transactionProcessingStrategyCode;
@@ -335,7 +336,7 @@ public class LoanProduct extends AbstractPersistableCustom<Long> {
isInterestRecalculationEnabled, isEqualAmortization, enableDownPayment, disbursedAmountPercentageForDownPayment,
enableAutoRepaymentForDownPayment, loanScheduleType, loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting,
supportedInterestRefundTypes, chargeOffBehaviour, isInterestRecognitionOnDisbursementDate, daysInYearCustomStrategy,
- enableIncomeCapitalization, capitalizedIncomeCalculationType, capitalizedIncomeStrategy);
+ enableIncomeCapitalization, capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType);
this.loanProductMinMaxConstraints = new LoanProductMinMaxConstraints(defaultMinPrincipal, defaultMaxPrincipal,
defaultMinNominalInterestRatePerPeriod, defaultMaxNominalInterestRatePerPeriod, defaultMinNumberOfInstallments,
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java
index 29b18e6cea..6ca788655e 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java
@@ -38,6 +38,7 @@ 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.LoanCapitalizedIncomeType;
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;
@@ -181,6 +182,10 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
@Column(name = "capitalized_income_strategy")
private LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy;
+ @Enumerated(EnumType.STRING)
+ @Column(name = "capitalized_income_type")
+ private LoanCapitalizedIncomeType capitalizedIncomeType;
+
public static LoanProductRelatedDetail createFrom(final CurrencyData currencyData, final BigDecimal principal,
final BigDecimal nominalInterestRatePerPeriod, final PeriodFrequencyType interestRatePeriodFrequencyType,
final BigDecimal nominalAnnualInterestRate, final InterestMethod interestMethod,
@@ -197,7 +202,7 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
final LoanChargeOffBehaviour chargeOffBehaviour, final boolean interestRecognitionOnDisbursementDate,
final DaysInYearCustomStrategyType daysInYearCustomStrategy, final boolean enableIncomeCapitalization,
final LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType,
- final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy) {
+ final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy, final LoanCapitalizedIncomeType capitalizedIncomeType) {
final MonetaryCurrency currency = MonetaryCurrency.fromCurrencyData(currencyData);
return new LoanProductRelatedDetail(currency, principal, nominalInterestRatePerPeriod, interestRatePeriodFrequencyType,
@@ -208,7 +213,7 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
isEqualAmortization, enableDownPayment, disbursedAmountPercentageForDownPayment, enableAutoRepaymentForDownPayment,
loanScheduleType, loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes,
chargeOffBehaviour, interestRecognitionOnDisbursementDate, daysInYearCustomStrategy, enableIncomeCapitalization,
- capitalizedIncomeCalculationType, capitalizedIncomeStrategy);
+ capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType);
}
protected LoanProductRelatedDetail() {
@@ -231,7 +236,7 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
final LoanChargeOffBehaviour chargeOffBehaviour, final boolean interestRecognitionOnDisbursementDate,
final DaysInYearCustomStrategyType daysInYearCustomStrategy, final boolean enableIncomeCapitalization,
final LoanCapitalizedIncomeCalculationType capitalizedIncomeCalculationType,
- final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy) {
+ final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy, final LoanCapitalizedIncomeType capitalizedIncomeType) {
this.currency = currency;
this.principal = defaultPrincipal;
this.nominalInterestRatePerPeriod = defaultNominalInterestRatePerPeriod;
@@ -272,6 +277,7 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
this.enableIncomeCapitalization = enableIncomeCapitalization;
this.capitalizedIncomeCalculationType = capitalizedIncomeCalculationType;
this.capitalizedIncomeStrategy = capitalizedIncomeStrategy;
+ this.capitalizedIncomeType = capitalizedIncomeType;
}
private Integer defaultToNullIfZero(final Integer value) {
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
index 04dde09757..2951426646 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
@@ -135,6 +135,7 @@ import org.apache.fineract.portfolio.loanaccount.data.PaidInAdvanceData;
import org.apache.fineract.portfolio.loanaccount.data.RepaymentScheduleRelatedLoanData;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeCalculationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeStrategy;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
import org.apache.fineract.portfolio.loanaccount.domain.LoanSummaryBalancesRepository;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType;
@@ -1160,7 +1161,8 @@ public class LoansApiResource {
LoanScheduleType.getValuesAsEnumOptionDataList(), LoanScheduleProcessingType.getValuesAsEnumOptionDataList(),
loanTermVariations, ApiFacingEnum.getValuesAsStringEnumOptionDataList(DaysInYearCustomStrategyType.class),
ApiFacingEnum.getValuesAsStringEnumOptionDataList(LoanCapitalizedIncomeCalculationType.class),
- ApiFacingEnum.getValuesAsStringEnumOptionDataList(LoanCapitalizedIncomeStrategy.class));
+ ApiFacingEnum.getValuesAsStringEnumOptionDataList(LoanCapitalizedIncomeStrategy.class),
+ ApiFacingEnum.getValuesAsStringEnumOptionDataList(LoanCapitalizedIncomeType.class));
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters(),
mandatoryResponseParameters);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
index 17787426d8..0b146908aa 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
@@ -1212,6 +1212,8 @@ final class LoansApiResourceSwagger {
public StringEnumOptionData capitalizedIncomeCalculationType;
@Schema(example = "EQUAL_AMORTIZATION")
public StringEnumOptionData capitalizedIncomeStrategy;
+ @Schema(example = "FEE")
+ public StringEnumOptionData capitalizedIncomeType;
}
@Schema(description = "GetLoansResponse")
@@ -1321,6 +1323,8 @@ final class LoansApiResourceSwagger {
public String capitalizedIncomeCalculationType;
@Schema(example = "EQUAL_AMORTIZATION", allowableValues = "EQUAL_AMORTIZATION")
public String capitalizedIncomeStrategy;
+ @Schema(example = "FEE")
+ public StringEnumOptionData capitalizedIncomeType;
public List<PostLoansRequestChargeData> charges;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java
index 4376cf077c..f2e4b2f355 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java
@@ -174,6 +174,7 @@ public class LoanAccountData {
private List<StringEnumOptionData> daysInYearCustomStrategyOptions;
private List<StringEnumOptionData> capitalizedIncomeCalculationTypeOptions;
private List<StringEnumOptionData> capitalizedIncomeStrategyOptions;
+ private List<StringEnumOptionData> capitalizedIncomeTypeOptions;
@Transient
private BigDecimal feeChargesAtDisbursementCharged;
@@ -279,6 +280,7 @@ public class LoanAccountData {
private Boolean enableIncomeCapitalization;
private StringEnumOptionData capitalizedIncomeCalculationType;
private StringEnumOptionData capitalizedIncomeStrategy;
+ private StringEnumOptionData capitalizedIncomeType;
public static LoanAccountData importInstanceIndividual(EnumOptionData loanTypeEnumOption, Long clientId, Long productId,
Long loanOfficerId, LocalDate submittedOnDate, Long fundId, BigDecimal principal, Integer numberOfRepayments,
@@ -472,7 +474,7 @@ 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) {
+ final StringEnumOptionData capitalizedIncomeStrategy, StringEnumOptionData capitalizedIncomeType) {
final CollectionData delinquent = CollectionData.template();
@@ -520,7 +522,7 @@ public class LoanAccountData {
.setChargeOffBehaviour(chargeOffBehaviour).setInterestRecognitionOnDisbursementDate(isInterestRecognitionOnDisbursementDate)
.setDaysInYearCustomStrategy(daysInYearCustomStrategy).setEnableIncomeCapitalization(enableIncomeCapitalization)
.setCapitalizedIncomeCalculationType(capitalizedIncomeCalculationType)
- .setCapitalizedIncomeStrategy(capitalizedIncomeStrategy);
+ .setCapitalizedIncomeStrategy(capitalizedIncomeStrategy).setCapitalizedIncomeType(capitalizedIncomeType);
}
/*
@@ -548,7 +550,8 @@ public class LoanAccountData {
final List<EnumOptionData> loanScheduleProcessingTypeOptions, final List<LoanTermVariationsData> loanTermVariations,
final List<StringEnumOptionData> daysInYearCustomStrategyOptions,
final List<StringEnumOptionData> capitalizedIncomeCalculationTypeOptions,
- final List<StringEnumOptionData> capitalizedIncomeStrategyOptions) {
+ final List<StringEnumOptionData> capitalizedIncomeStrategyOptions,
+ final List<StringEnumOptionData> capitalizedIncomeTypeOptions) {
// TODO: why are these variables 'calendarData', 'chargeTemplate' never used (see original private constructor)
@@ -571,7 +574,8 @@ public class LoanAccountData {
.setLoanScheduleProcessingTypeOptions(loanScheduleProcessingTypeOptions).setLoanTermVariations(loanTermVariations)
.setDaysInYearCustomStrategyOptions(daysInYearCustomStrategyOptions)
.setCapitalizedIncomeCalculationTypeOptions(capitalizedIncomeCalculationTypeOptions)
- .setCapitalizedIncomeStrategyOptions(capitalizedIncomeStrategyOptions);
+ .setCapitalizedIncomeStrategyOptions(capitalizedIncomeStrategyOptions)
+ .setCapitalizedIncomeTypeOptions(capitalizedIncomeTypeOptions);
}
public LoanAccountData associationsAndTemplate(final Collection<LoanProductData> productOptions,
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
index fe27ecb806..2db86adb9b 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
@@ -547,7 +547,8 @@ public class LoanScheduleAssembler {
loanProduct.getLoanProductRelatedDetail().getDaysInYearCustomStrategy(),
loanProduct.getLoanProductRelatedDetail().isEnableIncomeCapitalization(),
loanProduct.getLoanProductRelatedDetail().getCapitalizedIncomeCalculationType(),
- loanProduct.getLoanProductRelatedDetail().getCapitalizedIncomeStrategy());
+ loanProduct.getLoanProductRelatedDetail().getCapitalizedIncomeStrategy(),
+ loanProduct.getLoanProductRelatedDetail().getCapitalizedIncomeType());
}
private CalendarInstance createCalendarForSameAsRepayment(final Integer repaymentEvery,
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanProductAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanProductAssembler.java
index 85522bed1a..2e2a3beb6b 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanProductAssembler.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanProductAssembler.java
@@ -42,6 +42,7 @@ 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.LoanCapitalizedIncomeType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeOffBehaviour;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.AprCalculator;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleProcessingType;
@@ -313,6 +314,8 @@ public class LoanProductAssembler {
LoanProductConstants.CAPITALIZED_INCOME_CALCULATION_TYPE_PARAM_NAME, LoanCapitalizedIncomeCalculationType.class);
final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy = command.enumValueOfParameterNamed(
LoanProductConstants.CAPITALIZED_INCOME_STRATEGY_PARAM_NAME, LoanCapitalizedIncomeStrategy.class);
+ final LoanCapitalizedIncomeType capitalizedIncomeType = command
+ .enumValueOfParameterNamed(LoanProductConstants.CAPITALIZED_INCOME_TYPE_PARAM_NAME, LoanCapitalizedIncomeType.class);
return new LoanProduct(fund, loanTransactionProcessingStrategy, loanProductPaymentAllocationRules, loanProductCreditAllocationRules,
name, shortName, description, currency, principal, minPrincipal, maxPrincipal, interestRatePerPeriod,
@@ -334,7 +337,8 @@ public class LoanProductAssembler {
overDueDaysForRepaymentEvent, enableDownPayment, disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment,
repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType, loanScheduleProcessingType, fixedLength,
enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour, interestRecognitionOnDisbursementDate,
- daysInYearCustomStrategy, enableIncomeCapitalization, capitalizedIncomeCalculationType, capitalizedIncomeStrategy);
+ daysInYearCustomStrategy, enableIncomeCapitalization, capitalizedIncomeCalculationType, capitalizedIncomeStrategy,
+ capitalizedIncomeType);
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanProductRelatedDetailUpdateUtil.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanProductRelatedDetailUpdateUtil.java
index da78ccf984..b84cc31e09 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanProductRelatedDetailUpdateUtil.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanProductRelatedDetailUpdateUtil.java
@@ -28,6 +28,7 @@ import org.apache.fineract.portfolio.common.domain.DaysInYearCustomStrategyType;
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeCalculationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeStrategy;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeType;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.AprCalculator;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleProcessingType;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
@@ -320,6 +321,13 @@ public class LoanProductRelatedDetailUpdateUtil {
loanRepaymentScheduleDetail.setCapitalizedIncomeStrategy(newValue);
}
+ if (command.parameterExists(LoanProductConstants.CAPITALIZED_INCOME_TYPE_PARAM_NAME)) {
+ final LoanCapitalizedIncomeType newValue = command
+ .enumValueOfParameterNamed(LoanProductConstants.CAPITALIZED_INCOME_TYPE_PARAM_NAME, LoanCapitalizedIncomeType.class);
+ actualChanges.put(LoanProductConstants.CAPITALIZED_INCOME_TYPE_PARAM_NAME, newValue);
+ loanRepaymentScheduleDetail.setCapitalizedIncomeType(newValue);
+ }
+
return actualChanges;
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
index f853b38d57..1ec838ec76 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
@@ -109,6 +109,7 @@ import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
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.LoanCapitalizedIncomeType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeOffBehaviour;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
@@ -737,6 +738,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
+ " l.enable_income_capitalization as enableIncomeCapitalization, "
+ " l.capitalized_income_calculation_type as capitalizedIncomeCalculationType, "
+ " l.capitalized_income_strategy as capitalizedIncomeStrategy, "
+ + " l.capitalized_income_type as capitalizedIncomeType, " //
+ " l.create_standing_instruction_at_disbursement as createStandingInstructionAtDisbursement, "
+ " lpvi.minimum_gap as minimuminstallmentgap, lpvi.maximum_gap as maximuminstallmentgap, "
+ " lp.can_use_for_topup as canUseForTopup, l.is_topup as isTopup, topup.closure_loan_id as closureLoanId, "
@@ -1118,6 +1120,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
.getStringEnumOptionData(LoanCapitalizedIncomeCalculationType.class, rs.getString("capitalizedIncomeCalculationType"));
final StringEnumOptionData capitalizedIncomeStrategy = ApiFacingEnum
.getStringEnumOptionData(LoanCapitalizedIncomeStrategy.class, rs.getString("capitalizedIncomeStrategy"));
+ final StringEnumOptionData capitalizedIncomeType = ApiFacingEnum.getStringEnumOptionData(LoanCapitalizedIncomeType.class,
+ rs.getString("capitalizedIncomeType"));
return LoanAccountData.basicLoanDetails(id, accountNo, status, externalId, clientId, clientAccountNo, clientName,
clientOfficeId, clientExternalId, groupData, loanType, loanProductId, loanProductName, loanProductDescription,
@@ -1138,7 +1142,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
enableAutoRepaymentForDownPayment, enableInstallmentLevelDelinquency, loanScheduleType.asEnumOptionData(),
loanScheduleProcessingType.asEnumOptionData(), fixedLength, chargeOffBehaviour.getValueAsStringEnumOptionData(),
interestRecognitionOnDisbursementDate, daysInYearCustomStrategy, enableIncomeCapitalization,
- capitalizedIncomeCalculationType, capitalizedIncomeStrategy);
+ capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType);
}
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResource.java
index eb41c4228d..5604d7ff51 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResource.java
@@ -84,6 +84,7 @@ import org.apache.fineract.portfolio.fund.service.FundReadPlatformService;
import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeCalculationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeStrategy;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeType;
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;
@@ -133,7 +134,7 @@ public class LoanProductsApiResource {
LoanProductConstants.REPAYMENT_START_DATE_TYPE, LoanProductConstants.DAYS_IN_YEAR_CUSTOM_STRATEGY_TYPE_PARAMETER_NAME,
LoanProductConstants.ENABLE_INCOME_CAPITALIZATION_PARAM_NAME,
LoanProductConstants.CAPITALIZED_INCOME_CALCULATION_TYPE_PARAM_NAME,
- LoanProductConstants.CAPITALIZED_INCOME_STRATEGY_PARAM_NAME));
+ LoanProductConstants.CAPITALIZED_INCOME_STRATEGY_PARAM_NAME, LoanProductConstants.CAPITALIZED_INCOME_TYPE_PARAM_NAME));
private static final Set<String> PRODUCT_MIX_DATA_PARAMETERS = new HashSet<>(
Arrays.asList("productId", "productName", "restrictedProducts", "allowedProducts", "productOptions"));
@@ -450,6 +451,8 @@ public class LoanProductsApiResource {
.getValuesAsStringEnumOptionDataList(LoanCapitalizedIncomeCalculationType.class);
final List<StringEnumOptionData> capitalizedIncomeStrategyOptions = ApiFacingEnum
.getValuesAsStringEnumOptionDataList(LoanCapitalizedIncomeStrategy.class);
+ final List<StringEnumOptionData> capitalizedIncomeTypeOptions = ApiFacingEnum
+ .getValuesAsStringEnumOptionDataList(LoanCapitalizedIncomeType.class);
return new LoanProductData(productData, chargeOptions, penaltyOptions, paymentTypeOptions, currencyOptions, amortizationTypeOptions,
interestTypeOptions, interestCalculationPeriodTypeOptions, repaymentFrequencyTypeOptions, interestRateFrequencyTypeOptions,
@@ -462,7 +465,8 @@ public class LoanProductsApiResource {
advancedPaymentAllocationTypes, LoanScheduleType.getValuesAsEnumOptionDataList(),
LoanScheduleProcessingType.getValuesAsEnumOptionDataList(), creditAllocationTransactionTypes,
creditAllocationAllocationTypes, supportedInterestRefundTypesOptions, chargeOffBehaviourOptions, chargeOffReasonOptions,
- daysInYearCustomStrategyOptions, capitalizedIncomeCalculationTypeOptions, capitalizedIncomeStrategyOptions);
+ daysInYearCustomStrategyOptions, capitalizedIncomeCalculationTypeOptions, capitalizedIncomeStrategyOptions,
+ capitalizedIncomeTypeOptions);
}
}
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 ae62944b97..3a298ce89d 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
@@ -51,6 +51,7 @@ import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeCalculationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeStrategy;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeOffBehaviour;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor;
@@ -193,7 +194,7 @@ public final class LoanProductDataValidator {
LoanProductConstants.DAYS_IN_YEAR_CUSTOM_STRATEGY_TYPE_PARAMETER_NAME,
LoanProductConstants.ENABLE_INCOME_CAPITALIZATION_PARAM_NAME,
LoanProductConstants.CAPITALIZED_INCOME_CALCULATION_TYPE_PARAM_NAME,
- LoanProductConstants.CAPITALIZED_INCOME_STRATEGY_PARAM_NAME));
+ LoanProductConstants.CAPITALIZED_INCOME_STRATEGY_PARAM_NAME, LoanProductConstants.CAPITALIZED_INCOME_TYPE_PARAM_NAME));
private static final String[] SUPPORTED_LOAN_CONFIGURABLE_ATTRIBUTES = { LoanProductConstants.amortizationTypeParamName,
LoanProductConstants.interestTypeParamName, LoanProductConstants.transactionProcessingStrategyCodeParamName,
@@ -2688,6 +2689,13 @@ public final class LoanProductDataValidator {
.value(capitalizedIncomeStrategy).isOneOfEnumValues(LoanCapitalizedIncomeStrategy.class);
}
+ if (this.fromApiJsonHelper.parameterExists(LoanProductConstants.CAPITALIZED_INCOME_TYPE_PARAM_NAME, element)) {
+ final String capitalizedIncomeType = this.fromApiJsonHelper
+ .extractStringNamed(LoanProductConstants.CAPITALIZED_INCOME_TYPE_PARAM_NAME, element);
+ baseDataValidator.reset().parameter(LoanProductConstants.CAPITALIZED_INCOME_TYPE_PARAM_NAME).value(capitalizedIncomeType)
+ .isOneOfEnumValues(LoanCapitalizedIncomeType.class);
+ }
+
if (AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY.equals(transactionProcessingStrategyCode)
&& this.fromApiJsonHelper.parameterExists(LoanProductConstants.ENABLE_INCOME_CAPITALIZATION_PARAM_NAME, element)) {
Boolean enableIncomeCapitalization = this.fromApiJsonHelper
@@ -2705,6 +2713,11 @@ public final class LoanProductDataValidator {
baseDataValidator.reset().parameter(LoanProductConstants.CAPITALIZED_INCOME_STRATEGY_PARAM_NAME)
.value(capitalizedIncomeStrategy).isOneOfEnumValues(LoanCapitalizedIncomeStrategy.class)
.cantBeBlankWhenParameterProvidedIs(LoanProductConstants.ENABLE_INCOME_CAPITALIZATION_PARAM_NAME, true);
+ final String capitalizedIncomeType = this.fromApiJsonHelper
+ .extractStringNamed(LoanProductConstants.CAPITALIZED_INCOME_TYPE_PARAM_NAME, element);
+ baseDataValidator.reset().parameter(LoanProductConstants.CAPITALIZED_INCOME_TYPE_PARAM_NAME).value(capitalizedIncomeType)
+ .isOneOfEnumValues(LoanCapitalizedIncomeType.class)
+ .cantBeBlankWhenParameterProvidedIs(LoanProductConstants.ENABLE_INCOME_CAPITALIZATION_PARAM_NAME, true);
// Accounting
if (AccountingValidations.isAccrualBasedAccounting(accountingRuleType)) {
final Long deferredIncomeLiabilityAccountId = this.fromApiJsonHelper
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 7c316aa180..91aad12aba 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
@@ -48,6 +48,7 @@ import org.apache.fineract.portfolio.delinquency.data.DelinquencyBucketData;
import org.apache.fineract.portfolio.delinquency.service.DelinquencyReadPlatformService;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeCalculationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeStrategy;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeType;
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;
@@ -294,7 +295,8 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
+ "lp.charge_off_behaviour as chargeOffBehaviour, " //
+ "lp.enable_income_capitalization as enableIncomeCapitalization, " //
+ "lp.capitalized_income_calculation_type as capitalizedIncomeCalculationType, " //
- + "lp.capitalized_income_strategy as capitalizedIncomeStrategy " //
+ + "lp.capitalized_income_strategy as capitalizedIncomeStrategy, " //
+ + "lp.capitalized_income_type as capitalizedIncomeType " //
+ " from m_product_loan lp " + " left join m_fund f on f.id = lp.fund_id "
+ " left join m_product_loan_recalculation_details lpr on lpr.product_id=lp.id "
+ " left join m_product_loan_guarantee_details lpg on lpg.loan_product_id=lp.id "
@@ -563,6 +565,8 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
.getStringEnumOptionData(LoanCapitalizedIncomeCalculationType.class, rs.getString("capitalizedIncomeCalculationType"));
final StringEnumOptionData capitalizedIncomeStrategy = ApiFacingEnum
.getStringEnumOptionData(LoanCapitalizedIncomeStrategy.class, rs.getString("capitalizedIncomeStrategy"));
+ final StringEnumOptionData capitalizedIncome = ApiFacingEnum.getStringEnumOptionData(LoanCapitalizedIncomeType.class,
+ rs.getString("capitalizedIncomeType"));
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
@@ -587,7 +591,8 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
enableInstallmentLevelDelinquency, loanScheduleType.asEnumOptionData(), loanScheduleProcessingType.asEnumOptionData(),
fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes,
loanChargeOffBehaviour.getValueAsStringEnumOptionData(), interestRecognitionOnDisbursementDate,
- daysInYearCustomStrategy, enableIncomeCapitalization, capitalizedIncomeCalculationType, capitalizedIncomeStrategy);
+ daysInYearCustomStrategy, enableIncomeCapitalization, capitalizedIncomeCalculationType, capitalizedIncomeStrategy,
+ capitalizedIncome);
}
}
diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml
index e677629f12..6e48c15a4f 100644
--- a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml
+++ b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml
@@ -192,4 +192,5 @@
<include file="parts/0171_loan_capitalized_income.xml" relativeToChangelogFile="true"/>
<include file="parts/0172_create_loan_capitalized_income_balance.xml" relativeToChangelogFile="true"/>
<include file="parts/0173_user_change_pwd.xml" relativeToChangelogFile="true" />
+ <include file="parts/0174_loan_product_add_capitalized_income_type.xml" relativeToChangelogFile="true" />
</databaseChangeLog>
diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0174_loan_product_add_capitalized_income_type.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0174_loan_product_add_capitalized_income_type.xml
new file mode 100644
index 0000000000..e3e3d20427
--- /dev/null
+++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0174_loan_product_add_capitalized_income_type.xml
@@ -0,0 +1,37 @@
+<?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.3.xsd">
+ <changeSet author="fineract" id="1">
+ <addColumn tableName="m_loan">
+ <column name="capitalized_income_type" type="VARCHAR(10)">
+ <constraints nullable="true"/>
+ </column>
+ </addColumn>
+ <addColumn tableName="m_product_loan">
+ <column name="capitalized_income_type" type="VARCHAR(10)">
+ <constraints nullable="true"/>
+ </column>
+ </addColumn>
+ </changeSet>
+</databaseChangeLog>
diff --git a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGeneratorTest.java b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGeneratorTest.java
index d0d83caa6c..43052d0f80 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGeneratorTest.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGeneratorTest.java
@@ -98,7 +98,7 @@ public class DefaultScheduledDateGeneratorTest {
Money.of(fromApplicationCurrency(dollarCurrency), ZERO), false, null, EMPTY_LIST, BigDecimal.valueOf(36_000L), null,
DaysInMonthType.ACTUAL, DaysInYearType.ACTUAL, false, null, null, null, null, null, ZERO, null, NONE, null, ZERO,
EMPTY_LIST, true, 0, false, holidayDetailDTO, false, false, false, null, false, false, null, false, DISBURSEMENT_DATE,
- submittedOnDate, CUMULATIVE, LoanScheduleProcessingType.HORIZONTAL, null, false, null, null, false, null, false, null,
+ submittedOnDate, CUMULATIVE, LoanScheduleProcessingType.HORIZONTAL, null, false, null, null, false, null, false, null, null,
null);
// when
@@ -180,7 +180,7 @@ public class DefaultScheduledDateGeneratorTest {
EMPTY_LIST, BigDecimal.valueOf(36_000L), null, DaysInMonthType.ACTUAL, DaysInYearType.ACTUAL, false, null, null, null, null,
null, ZERO, null, NONE, null, ZERO, EMPTY_LIST, true, 0, false, holidayDetailDTO, false, false, false, null, false, false,
null, false, DISBURSEMENT_DATE, submittedOnDate, CUMULATIVE, LoanScheduleProcessingType.HORIZONTAL, null, false, null, null,
- false, null, false, null, null);
+ false, null, false, null, null, null);
}
private HolidayDetailDTO createHolidayDTO() {
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductTest.java
index 0a6e22cf9d..6d2b2f33b4 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductTest.java
@@ -28,6 +28,7 @@ import org.apache.fineract.client.models.PutLoanProductsProductIdRequest;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeCalculationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeStrategy;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeType;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@@ -46,7 +47,8 @@ public class LoanProductTest extends BaseLoanIntegrationTest {
.capitalizedIncomeCalculationType(PostLoanProductsRequest.CapitalizedIncomeCalculationTypeEnum.FLAT)
.capitalizedIncomeStrategy(PostLoanProductsRequest.CapitalizedIncomeStrategyEnum.EQUAL_AMORTIZATION)
.deferredIncomeLiabilityAccountId(deferredIncomeLiabilityAccount.getAccountID().longValue())
- .incomeFromCapitalizationAccountId(feeIncomeAccount.getAccountID().longValue()));
+ .incomeFromCapitalizationAccountId(feeIncomeAccount.getAccountID().longValue())
+ .capitalizedIncomeType(PostLoanProductsRequest.CapitalizedIncomeTypeEnum.FEE));
final GetLoanProductsProductIdResponse loanProductsProductIdResponse = loanProductHelper
.retrieveLoanProductById(loanProductsResponse.getResourceId());
@@ -57,6 +59,9 @@ public class LoanProductTest extends BaseLoanIntegrationTest {
Assertions.assertNotNull(loanProductsProductIdResponse.getCapitalizedIncomeStrategy());
Assertions.assertEquals(LoanCapitalizedIncomeStrategy.EQUAL_AMORTIZATION.getCode(),
loanProductsProductIdResponse.getCapitalizedIncomeStrategy().getCode());
+ Assertions.assertNotNull(loanProductsProductIdResponse.getCapitalizedIncomeType());
+ Assertions.assertEquals(LoanCapitalizedIncomeType.FEE.getCode(),
+ loanProductsProductIdResponse.getCapitalizedIncomeType().getCode());
runAt("20 December 2024", () -> {
Long loanId = applyAndApproveProgressiveLoan(client.getClientId(), loanProductsResponse.getResourceId(), "20 December 2024",
@@ -70,6 +75,8 @@ public class LoanProductTest extends BaseLoanIntegrationTest {
Assertions.assertNotNull(loanDetails.getCapitalizedIncomeStrategy());
Assertions.assertEquals(LoanCapitalizedIncomeStrategy.EQUAL_AMORTIZATION.getCode(),
loanDetails.getCapitalizedIncomeStrategy().getCode());
+ Assertions.assertNotNull(loanDetails.getCapitalizedIncomeType());
+ Assertions.assertEquals(LoanCapitalizedIncomeType.FEE.getCode(), loanDetails.getCapitalizedIncomeType().getCode());
Assertions.assertDoesNotThrow(() -> disburseLoan(loanId, BigDecimal.valueOf(430), "20 December 2024"));
});
@@ -84,7 +91,8 @@ public class LoanProductTest extends BaseLoanIntegrationTest {
.capitalizedIncomeCalculationType(PostLoanProductsRequest.CapitalizedIncomeCalculationTypeEnum.FLAT)
.capitalizedIncomeStrategy(PostLoanProductsRequest.CapitalizedIncomeStrategyEnum.EQUAL_AMORTIZATION)
.deferredIncomeLiabilityAccountId(deferredIncomeLiabilityAccount.getAccountID().longValue())
- .incomeFromCapitalizationAccountId(feeIncomeAccount.getAccountID().longValue()));
+ .incomeFromCapitalizationAccountId(feeIncomeAccount.getAccountID().longValue())
+ .capitalizedIncomeType(PostLoanProductsRequest.CapitalizedIncomeTypeEnum.FEE));
final GetLoanProductsProductIdResponse loanProductsProductIdResponse = loanProductHelper
.retrieveLoanProductById(loanProductsResponse.getResourceId());
@@ -95,6 +103,9 @@ public class LoanProductTest extends BaseLoanIntegrationTest {
Assertions.assertNotNull(loanProductsProductIdResponse.getCapitalizedIncomeStrategy());
Assertions.assertEquals(LoanCapitalizedIncomeStrategy.EQUAL_AMORTIZATION.getCode(),
loanProductsProductIdResponse.getCapitalizedIncomeStrategy().getCode());
+ Assertions.assertNotNull(loanProductsProductIdResponse.getCapitalizedIncomeType());
+ Assertions.assertEquals(LoanCapitalizedIncomeType.FEE.getCode(),
+ loanProductsProductIdResponse.getCapitalizedIncomeType().getCode());
runAt("20 December 2024", () -> {
Long loanId = applyAndApproveProgressiveLoan(client.getClientId(), loanProductsResponse.getResourceId(), "20 December 2024",
@@ -108,6 +119,8 @@ public class LoanProductTest extends BaseLoanIntegrationTest {
Assertions.assertNotNull(loanDetails.getCapitalizedIncomeStrategy());
Assertions.assertEquals(LoanCapitalizedIncomeStrategy.EQUAL_AMORTIZATION.getCode(),
loanDetails.getCapitalizedIncomeStrategy().getCode());
+ Assertions.assertNotNull(loanDetails.getCapitalizedIncomeType());
+ Assertions.assertEquals(LoanCapitalizedIncomeType.FEE.getCode(), loanDetails.getCapitalizedIncomeType().getCode());
Assertions.assertDoesNotThrow(() -> disburseLoan(loanId, BigDecimal.valueOf(430), "20 December 2024"));
});
@@ -120,7 +133,8 @@ public class LoanProductTest extends BaseLoanIntegrationTest {
.capitalizedIncomeCalculationType(PostLoanProductsRequest.CapitalizedIncomeCalculationTypeEnum.FLAT)
.capitalizedIncomeStrategy(PostLoanProductsRequest.CapitalizedIncomeStrategyEnum.EQUAL_AMORTIZATION)
.deferredIncomeLiabilityAccountId(deferredIncomeLiabilityAccount.getAccountID().longValue())
- .incomeFromCapitalizationAccountId(feeIncomeAccount.getAccountID().longValue()));
+ .incomeFromCapitalizationAccountId(feeIncomeAccount.getAccountID().longValue())
+ .capitalizedIncomeType(PostLoanProductsRequest.CapitalizedIncomeTypeEnum.FEE));
final GetLoanProductsProductIdResponse loanProductsProductIdResponse = loanProductHelper
.retrieveLoanProductById(loanProductsResponse.getResourceId());
@@ -134,9 +148,14 @@ public class LoanProductTest extends BaseLoanIntegrationTest {
Assertions.assertNotNull(loanProductsProductIdResponse.getAccountingMappings());
Assertions.assertEquals(feeIncomeAccount.getAccountID().longValue(),
loanProductsProductIdResponse.getAccountingMappings().getIncomeFromCapitalizationAccount().getId());
+ Assertions.assertNotNull(loanProductsProductIdResponse.getCapitalizedIncomeType());
+ Assertions.assertEquals(LoanCapitalizedIncomeType.FEE.getCode(),
+ loanProductsProductIdResponse.getCapitalizedIncomeType().getCode());
- loanProductHelper.updateLoanProductById(loanProductsResponse.getResourceId(), new PutLoanProductsProductIdRequest()
- .enableIncomeCapitalization(false).incomeFromCapitalizationAccountId(interestIncomeAccount.getAccountID().longValue()));
+ loanProductHelper.updateLoanProductById(loanProductsResponse.getResourceId(),
+ new PutLoanProductsProductIdRequest().enableIncomeCapitalization(false)
+ .incomeFromCapitalizationAccountId(interestIncomeAccount.getAccountID().longValue())
+ .capitalizedIncomeType(PutLoanProductsProductIdRequest.CapitalizedIncomeTypeEnum.INTEREST));
final GetLoanProductsProductIdResponse updatedLoanProductsProductIdResponse = loanProductHelper
.retrieveLoanProductById(loanProductsResponse.getResourceId());
@@ -150,6 +169,9 @@ public class LoanProductTest extends BaseLoanIntegrationTest {
Assertions.assertNotNull(updatedLoanProductsProductIdResponse.getAccountingMappings());
Assertions.assertEquals(interestIncomeAccount.getAccountID().longValue(),
updatedLoanProductsProductIdResponse.getAccountingMappings().getIncomeFromCapitalizationAccount().getId());
+ Assertions.assertNotNull(updatedLoanProductsProductIdResponse.getCapitalizedIncomeType());
+ Assertions.assertEquals(LoanCapitalizedIncomeType.INTEREST.getCode(),
+ updatedLoanProductsProductIdResponse.getCapitalizedIncomeType().getCode());
}
@Test
@@ -161,7 +183,8 @@ public class LoanProductTest extends BaseLoanIntegrationTest {
.capitalizedIncomeCalculationType(PostLoanProductsRequest.CapitalizedIncomeCalculationTypeEnum.FLAT)
.capitalizedIncomeStrategy(PostLoanProductsRequest.CapitalizedIncomeStrategyEnum.EQUAL_AMORTIZATION)
.deferredIncomeLiabilityAccountId(deferredIncomeLiabilityAccount.getAccountID().longValue())
- .incomeFromCapitalizationAccountId(feeIncomeAccount.getAccountID().longValue())));
+ .incomeFromCapitalizationAccountId(feeIncomeAccount.getAccountID().longValue())
+ .capitalizedIncomeType(PostLoanProductsRequest.CapitalizedIncomeTypeEnum.FEE)));
}
@Test
@@ -170,7 +193,8 @@ public class LoanProductTest extends BaseLoanIntegrationTest {
() -> loanProductHelper.createLoanProduct(create4IProgressive().enableIncomeCapitalization(true)
.capitalizedIncomeStrategy(PostLoanProductsRequest.CapitalizedIncomeStrategyEnum.EQUAL_AMORTIZATION)
.deferredIncomeLiabilityAccountId(deferredIncomeLiabilityAccount.getAccountID().longValue())
- .incomeFromCapitalizationAccountId(feeIncomeAccount.getAccountID().longValue())));
+ .incomeFromCapitalizationAccountId(feeIncomeAccount.getAccountID().longValue())
+ .capitalizedIncomeType(PostLoanProductsRequest.CapitalizedIncomeTypeEnum.FEE)));
}
@Test
@@ -179,7 +203,8 @@ public class LoanProductTest extends BaseLoanIntegrationTest {
() -> loanProductHelper.createLoanProduct(create4IProgressive().enableIncomeCapitalization(true)
.capitalizedIncomeCalculationType(PostLoanProductsRequest.CapitalizedIncomeCalculationTypeEnum.FLAT)
.deferredIncomeLiabilityAccountId(deferredIncomeLiabilityAccount.getAccountID().longValue())
- .incomeFromCapitalizationAccountId(feeIncomeAccount.getAccountID().longValue())));
+ .incomeFromCapitalizationAccountId(feeIncomeAccount.getAccountID().longValue())
+ .capitalizedIncomeType(PostLoanProductsRequest.CapitalizedIncomeTypeEnum.FEE)));
}
@Test
@@ -188,7 +213,8 @@ public class LoanProductTest extends BaseLoanIntegrationTest {
() -> loanProductHelper.createLoanProduct(create4IProgressive().enableIncomeCapitalization(true)
.capitalizedIncomeCalculationType(PostLoanProductsRequest.CapitalizedIncomeCalculationTypeEnum.FLAT)
.capitalizedIncomeStrategy(PostLoanProductsRequest.CapitalizedIncomeStrategyEnum.EQUAL_AMORTIZATION)
- .incomeFromCapitalizationAccountId(feeIncomeAccount.getAccountID().longValue())));
+ .incomeFromCapitalizationAccountId(feeIncomeAccount.getAccountID().longValue())
+ .capitalizedIncomeType(PostLoanProductsRequest.CapitalizedIncomeTypeEnum.FEE)));
}
@Test
@@ -197,7 +223,18 @@ public class LoanProductTest extends BaseLoanIntegrationTest {
() -> loanProductHelper.createLoanProduct(create4IProgressive().enableIncomeCapitalization(true)
.capitalizedIncomeCalculationType(PostLoanProductsRequest.CapitalizedIncomeCalculationTypeEnum.FLAT)
.capitalizedIncomeStrategy(PostLoanProductsRequest.CapitalizedIncomeStrategyEnum.EQUAL_AMORTIZATION)
- .deferredIncomeLiabilityAccountId(deferredIncomeLiabilityAccount.getAccountID().longValue())));
+ .deferredIncomeLiabilityAccountId(deferredIncomeLiabilityAccount.getAccountID().longValue())
+ .capitalizedIncomeType(PostLoanProductsRequest.CapitalizedIncomeTypeEnum.FEE)));
+ }
+
+ @Test
+ public void testIncomeCapitalizationEnabledIncomeTypeNotProvided() {
+ Assertions.assertThrows(RuntimeException.class,
+ () -> loanProductHelper.createLoanProduct(create4IProgressive().enableIncomeCapitalization(true)
+ .capitalizedIncomeCalculationType(PostLoanProductsRequest.CapitalizedIncomeCalculationTypeEnum.FLAT)
+ .capitalizedIncomeStrategy(PostLoanProductsRequest.CapitalizedIncomeStrategyEnum.EQUAL_AMORTIZATION)
+ .deferredIncomeLiabilityAccountId(deferredIncomeLiabilityAccount.getAccountID().longValue())
+ .incomeFromCapitalizationAccountId(feeIncomeAccount.getAccountID().longValue())));
}
}
}