This is an automated email from the ASF dual-hosted git repository.
bagrijp pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new b2685ce9c FINERACT-2065: Fixed length loan configuration
b2685ce9c is described below
commit b2685ce9cf9360a6503bcf76e081d6426de9c804
Author: Peter Bagrij <[email protected]>
AuthorDate: Wed Mar 13 14:54:40 2024 +0100
FINERACT-2065: Fixed length loan configuration
---
.../loanschedule/domain/LoanApplicationTerms.java | 18 ++--
.../loanproduct/LoanProductConstants.java | 2 +
.../portfolio/loanproduct/domain/LoanProduct.java | 14 ++-
.../domain/LoanProductRelatedDetail.java | 18 +++-
.../tenant/module/loan/module-changelog-master.xml | 1 +
.../module/loan/parts/1019_add_fixed_length.xml | 33 +++++++
.../importhandler/loan/LoanImportHandler.java | 6 +-
.../loanaccount/api/LoansApiResourceSwagger.java | 6 ++
.../loanaccount/data/LoanAccountData.java | 34 ++++---
.../service/LoanScheduleAssembler.java | 17 +++-
.../LoanApplicationCommandFromApiJsonHelper.java | 2 +-
.../service/LoanReadPlatformServiceImpl.java | 4 +-
.../api/LoanProductsApiResourceSwagger.java | 8 ++
.../loanproduct/data/LoanProductData.java | 17 +++-
.../serialization/LoanProductDataValidator.java | 2 +-
.../LoanProductReadPlatformServiceImpl.java | 5 +-
.../domain/DefaultScheduledDateGeneratorTest.java | 2 +-
...PaymentAllocationLoanRepaymentScheduleTest.java | 16 ++-
.../FixedLengthLoanProductIntegrationTest.java | 108 +++++++++++++++++++++
.../common/loans/LoanProductHelper.java | 4 +
20 files changed, 266 insertions(+), 51 deletions(-)
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 f908d0df4..32f855433 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
@@ -68,6 +68,8 @@ public final class LoanApplicationTerms {
private Integer actualNumberOfRepayments;
private final Integer repaymentEvery;
private final PeriodFrequencyType repaymentPeriodFrequencyType;
+
+ private final Integer fixedLength;
private final Integer nthDay;
private final DayOfWeekType weekDayType;
@@ -249,7 +251,7 @@ public final class LoanApplicationTerms {
final Boolean enableDownPayment, final BigDecimal
disbursedAmountPercentageForDownPayment,
final Boolean isAutoRepaymentForDownPaymentEnabled, final
RepaymentStartDateType repaymentStartDateType,
final LocalDate submittedOnDate, final LoanScheduleType
loanScheduleType,
- final LoanScheduleProcessingType loanScheduleProcessingType) {
+ final LoanScheduleProcessingType loanScheduleProcessingType, final
Integer fixedLength) {
final LoanRescheduleStrategyMethod rescheduleStrategyMethod = null;
final CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
@@ -267,8 +269,8 @@ public final class LoanApplicationTerms {
isSkipRepaymentOnFirstDayOfMonth, holidayDetailDTO,
allowCompoundingOnEod, isEqualAmortization, false,
isInterestToBeRecoveredFirstWhenGreaterThanEMI,
fixedPrincipalPercentagePerInstallment,
isPrincipalCompoundingDisabledForOverdueLoans,
enableDownPayment, disbursedAmountPercentageForDownPayment,
- isAutoRepaymentForDownPaymentEnabled, repaymentStartDateType,
submittedOnDate, loanScheduleType,
- loanScheduleProcessingType);
+ isAutoRepaymentForDownPaymentEnabled, repaymentStartDateType,
submittedOnDate, loanScheduleType, loanScheduleProcessingType,
+ fixedLength);
}
@@ -324,6 +326,7 @@ public final class LoanApplicationTerms {
}
LoanScheduleType loanScheduleType =
loanProductRelatedDetail.getLoanScheduleType();
LoanScheduleProcessingType loanScheduleProcessingType =
loanProductRelatedDetail.getLoanScheduleProcessingType();
+ final Integer fixedLength = loanProductRelatedDetail.getFixedLength();
return new LoanApplicationTerms(applicationCurrency,
loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments,
repaymentEvery, repaymentPeriodFrequencyType, ((nthDay !=
null) ? nthDay.getValue() : null), dayOfWeek, amortizationMethod,
interestMethod, interestRatePerPeriod,
interestRatePeriodFrequencyType, annualNominalInterestRate,
@@ -339,8 +342,8 @@ public final class LoanApplicationTerms {
allowCompoundingOnEod, isEqualAmortization,
isFirstRepaymentDateAllowedOnHoliday,
isInterestToBeRecoveredFirstWhenGreaterThanEMI,
fixedPrincipalPercentagePerInstallment,
isPrincipalCompoundingDisabledForOverdueLoans,
isDownPaymentEnabled, disbursedAmountPercentageForDownPayment,
- isAutoRepaymentForDownPaymentEnabled, repaymentStartDateType,
submittedOnDate, loanScheduleType,
- loanScheduleProcessingType);
+ isAutoRepaymentForDownPaymentEnabled, repaymentStartDateType,
submittedOnDate, loanScheduleType, loanScheduleProcessingType,
+ fixedLength);
}
private LoanApplicationTerms(final ApplicationCurrency currency, final
Integer loanTermFrequency,
@@ -369,7 +372,7 @@ public final class LoanApplicationTerms {
final boolean isPrincipalCompoundingDisabledForOverdueLoans, final
boolean isDownPaymentEnabled,
final BigDecimal disbursedAmountPercentageForDownPayment, final
boolean isAutoRepaymentForDownPaymentEnabled,
final RepaymentStartDateType repaymentStartDateType, final
LocalDate submittedOnDate, final LoanScheduleType loanScheduleType,
- final LoanScheduleProcessingType loanScheduleProcessingType) {
+ final LoanScheduleProcessingType loanScheduleProcessingType, final
Integer fixedLength) {
this.currency = currency;
this.loanTermFrequency = loanTermFrequency;
@@ -463,6 +466,7 @@ public final class LoanApplicationTerms {
this.submittedOnDate = submittedOnDate;
this.loanScheduleType = loanScheduleType;
this.loanScheduleProcessingType = loanScheduleProcessingType;
+ this.fixedLength = fixedLength;
}
public Money adjustPrincipalIfLastRepaymentPeriod(final Money
principalForPeriod, final Money totalCumulativePrincipalToDate,
@@ -1326,7 +1330,7 @@ public final class LoanApplicationTerms {
this.graceOnArrearsAgeing, this.daysInMonthType.getValue(),
this.daysInYearType.getValue(),
this.interestRecalculationEnabled, this.isEqualAmortization,
this.isDownPaymentEnabled,
this.disbursedAmountPercentageForDownPayment,
this.isAutoRepaymentForDownPaymentEnabled, this.loanScheduleType,
- this.loanScheduleProcessingType);
+ this.loanScheduleProcessingType, this.fixedLength);
}
public Integer getLoanTermFrequency() {
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 532bd5efa..d18c5da69 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
@@ -161,4 +161,6 @@ public interface LoanProductConstants {
// Repayment Strategies
String ADVANCED_PAYMENT_ALLOCATION_STRATEGY =
"advanced-payment-allocation-strategy";
+
+ String FIXED_LENGTH = "fixedLength";
}
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 83a848d60..53abbff42 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
@@ -429,6 +429,8 @@ public class LoanProduct extends AbstractPersistableCustom {
final boolean enableInstallmentLevelDelinquency = command
.booleanPrimitiveValueOfParameterNamed(LoanProductConstants.ENABLE_INSTALLMENT_LEVEL_DELINQUENCY);
+ final Integer fixedLength =
command.integerValueOfParameterNamed(LoanProductConstants.FIXED_LENGTH);
+
return new LoanProduct(fund, loanTransactionProcessingStrategy,
loanProductPaymentAllocationRules, loanProductCreditAllocationRules,
name, shortName, description, currency, principal,
minPrincipal, maxPrincipal, interestRatePerPeriod,
minInterestRatePerPeriod, maxInterestRatePerPeriod,
interestFrequencyType, annualInterestRate, interestMethod,
@@ -447,7 +449,7 @@ public class LoanProduct extends AbstractPersistableCustom {
isEqualAmortization, productRates,
fixedPrincipalPercentagePerInstallment, disallowExpectedDisbursements,
allowApprovedDisbursedAmountsOverApplied,
overAppliedCalculationType, overAppliedNumber, dueDaysForRepaymentEvent,
overDueDaysForRepaymentEvent, enableDownPayment,
disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment,
- repaymentStartDateType, enableInstallmentLevelDelinquency,
loanScheduleType, loanScheduleProcessingType);
+ repaymentStartDateType, enableInstallmentLevelDelinquency,
loanScheduleType, loanScheduleProcessingType, fixedLength);
}
@@ -664,7 +666,7 @@ public class LoanProduct extends AbstractPersistableCustom {
final boolean enableDownPayment, final BigDecimal
disbursedAmountPercentageForDownPayment,
final boolean enableAutoRepaymentForDownPayment, final
RepaymentStartDateType repaymentStartDateType,
final boolean enableInstallmentLevelDelinquency, final
LoanScheduleType loanScheduleType,
- final LoanScheduleProcessingType loanScheduleProcessingType) {
+ final LoanScheduleProcessingType loanScheduleProcessingType, final
Integer fixedLength) {
this.fund = fund;
this.transactionProcessingStrategyCode =
transactionProcessingStrategyCode;
@@ -713,7 +715,7 @@ public class LoanProduct extends AbstractPersistableCustom {
recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment,
graceOnInterestCharged, amortizationMethod,
inArrearsTolerance, graceOnArrearsAgeing,
daysInMonthType.getValue(), daysInYearType.getValue(),
isInterestRecalculationEnabled, isEqualAmortization,
enableDownPayment, disbursedAmountPercentageForDownPayment,
- enableAutoRepaymentForDownPayment, loanScheduleType,
loanScheduleProcessingType);
+ enableAutoRepaymentForDownPayment, loanScheduleType,
loanScheduleProcessingType, fixedLength);
this.loanProductRelatedDetail.validateRepaymentPeriodWithGraceSettings();
@@ -1364,6 +1366,12 @@ public class LoanProduct extends
AbstractPersistableCustom {
this.updateEnableInstallmentLevelDelinquency(newValue);
}
+ if
(command.isChangeInIntegerParameterNamed(LoanProductConstants.FIXED_LENGTH,
loanProductRelatedDetail.getFixedLength())) {
+ final Integer newValue =
command.integerValueOfParameterNamed(LoanProductConstants.FIXED_LENGTH);
+ actualChanges.put(LoanProductConstants.FIXED_LENGTH, newValue);
+ loanProductRelatedDetail.setFixedLength(newValue);
+ }
+
return actualChanges;
}
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 f956cf963..6c74c7534 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
@@ -92,6 +92,9 @@ public class LoanProductRelatedDetail implements
LoanProductMinimumRepaymentSche
@Column(name = "repayment_period_frequency_enum", nullable = false)
private PeriodFrequencyType repaymentPeriodFrequencyType;
+ @Column(name = "fixed_length", nullable = false)
+ private Integer fixedLength;
+
@Column(name = "number_of_repayments", nullable = false)
private Integer numberOfRepayments;
@@ -159,7 +162,7 @@ public class LoanProductRelatedDetail implements
LoanProductMinimumRepaymentSche
final Integer daysInYearType, final boolean
isInterestRecalculationEnabled, final boolean isEqualAmortization,
final boolean enableDownPayment, final BigDecimal
disbursedAmountPercentageForDownPayment,
final boolean enableAutoRepaymentForDownPayment, final
LoanScheduleType loanScheduleType,
- final LoanScheduleProcessingType loanScheduleProcessingType) {
+ final LoanScheduleProcessingType loanScheduleProcessingType, final
Integer fixedLength) {
return new LoanProductRelatedDetail(currency, principal,
nominalInterestRatePerPeriod, interestRatePeriodFrequencyType,
nominalAnnualInterestRate, interestMethod,
interestCalculationPeriodMethod, allowPartialPeriodInterestCalcualtion,
@@ -167,7 +170,7 @@ public class LoanProductRelatedDetail implements
LoanProductMinimumRepaymentSche
recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment,
graceOnInterestCharged, amortizationMethod,
inArrearsTolerance, graceOnArrearsAgeing, daysInMonthType,
daysInYearType, isInterestRecalculationEnabled,
isEqualAmortization, enableDownPayment,
disbursedAmountPercentageForDownPayment, enableAutoRepaymentForDownPayment,
- loanScheduleType, loanScheduleProcessingType);
+ loanScheduleType, loanScheduleProcessingType, fixedLength);
}
protected LoanProductRelatedDetail() {
@@ -185,7 +188,7 @@ public class LoanProductRelatedDetail implements
LoanProductMinimumRepaymentSche
final Integer daysInYearType, final boolean
isInterestRecalculationEnabled, final boolean isEqualAmortization,
final boolean enableDownPayment, final BigDecimal
disbursedAmountPercentageForDownPayment,
final boolean enableAutoRepaymentForDownPayment, final
LoanScheduleType loanScheduleType,
- final LoanScheduleProcessingType loanScheduleProcessingType) {
+ final LoanScheduleProcessingType loanScheduleProcessingType, final
Integer fixedLength) {
this.currency = currency;
this.principal = defaultPrincipal;
this.nominalInterestRatePerPeriod =
defaultNominalInterestRatePerPeriod;
@@ -197,6 +200,7 @@ public class LoanProductRelatedDetail implements
LoanProductMinimumRepaymentSche
this.repayEvery = repayEvery;
this.repaymentPeriodFrequencyType = repaymentFrequencyType;
this.numberOfRepayments = defaultNumberOfRepayments;
+ this.fixedLength = fixedLength;
this.graceOnPrincipalPayment =
defaultToNullIfZero(graceOnPrincipalPayment);
this.recurringMoratoriumOnPrincipalPeriods =
recurringMoratoriumOnPrincipalPeriods;
this.graceOnInterestPayment =
defaultToNullIfZero(graceOnInterestPayment);
@@ -753,4 +757,12 @@ public class LoanProductRelatedDetail implements
LoanProductMinimumRepaymentSche
public LoanScheduleProcessingType getLoanScheduleProcessingType() {
return loanScheduleProcessingType;
}
+
+ public Integer getFixedLength() {
+ return this.fixedLength;
+ }
+
+ public void setFixedLength(Integer fixedLength) {
+ this.fixedLength = fixedLength;
+ }
}
diff --git
a/fineract-loan/src/main/resources/db/changelog/tenant/module/loan/module-changelog-master.xml
b/fineract-loan/src/main/resources/db/changelog/tenant/module/loan/module-changelog-master.xml
index b90df0097..530477091 100644
---
a/fineract-loan/src/main/resources/db/changelog/tenant/module/loan/module-changelog-master.xml
+++
b/fineract-loan/src/main/resources/db/changelog/tenant/module/loan/module-changelog-master.xml
@@ -41,4 +41,5 @@
<include relativeToChangelogFile="true"
file="parts/1016_add_credit_allocation_rule.xml"/>
<include relativeToChangelogFile="true"
file="parts/1017_add_fee_and_penalty_adjustments_to_loan.xml"/>
<include relativeToChangelogFile="true"
file="parts/1018_rename_credited_principal_back_to_credits_amount.xml"/>
+ <include relativeToChangelogFile="true"
file="parts/1019_add_fixed_length.xml"/>
</databaseChangeLog>
diff --git
a/fineract-loan/src/main/resources/db/changelog/tenant/module/loan/parts/1019_add_fixed_length.xml
b/fineract-loan/src/main/resources/db/changelog/tenant/module/loan/parts/1019_add_fixed_length.xml
new file mode 100644
index 000000000..e557d9388
--- /dev/null
+++
b/fineract-loan/src/main/resources/db/changelog/tenant/module/loan/parts/1019_add_fixed_length.xml
@@ -0,0 +1,33 @@
+<?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_product_loan">
+ <column name="fixed_length" type="SMALLINT"/>
+ </addColumn>
+ <addColumn tableName="m_loan">
+ <column name="fixed_length" type="SMALLINT"/>
+ </addColumn>
+ </changeSet>
+</databaseChangeLog>
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loan/LoanImportHandler.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loan/LoanImportHandler.java
index 401cd13ab..dea87fc35 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loan/LoanImportHandler.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loan/LoanImportHandler.java
@@ -351,7 +351,7 @@ public class LoanImportHandler implements ImportHandler {
nominalInterestRate, submittedOnDate,
amortizationEnumOption, interestMethodEnum, interestCalculationPeriodEnum,
arrearsTolerance, repaymentStrategyCode,
graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged,
interestChargedFromDate, firstRepaymentOnDate,
row.getRowNum(), externalId, null, charges, linkAccountId, locale,
- dateFormat, loanCollateralManagementData);
+ dateFormat, loanCollateralManagementData, null);
} else if (loanType.equals("jlg")) {
Long clientId =
ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.CLIENT_SHEET_NAME),
clientOrGroupName);
@@ -360,7 +360,7 @@ public class LoanImportHandler implements ImportHandler {
nominalInterestRate, submittedOnDate,
amortizationEnumOption, interestMethodEnum, interestCalculationPeriodEnum,
arrearsTolerance, repaymentStrategyCode,
graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged,
interestChargedFromDate, firstRepaymentOnDate,
row.getRowNum(), externalId, groupId, charges, linkAccountId, locale,
- dateFormat, null);
+ dateFormat, null, null);
} else {
Long groupIdforGroupLoan = ImportHandlerUtils
.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.GROUP_SHEET_NAME),
clientOrGroupName);
@@ -369,7 +369,7 @@ public class LoanImportHandler implements ImportHandler {
loanTermFrequencyEnum, nominalInterestRate,
amortizationEnumOption, interestMethodEnum,
interestCalculationPeriodEnum, arrearsTolerance,
repaymentStrategyCode, graceOnPrincipalPayment,
graceOnInterestPayment, graceOnInterestCharged,
interestChargedFromDate, firstRepaymentOnDate, row.getRowNum(),
- externalId, linkAccountId, locale, dateFormat);
+ externalId, linkAccountId, locale, dateFormat, null);
}
}
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 375d506e2..67002b0d9 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
@@ -1085,6 +1085,8 @@ final class LoansApiResourceSwagger {
@Schema(example = "1")
public Integer repaymentEvery;
public GetLoansLoanIdRepaymentFrequencyType repaymentFrequencyType;
+ @Schema(example = "1")
+ public Integer fixedLength;
@Schema(example = "24")
public BigDecimal interestRatePerPeriod;
public GetLoansLoanIdInterestRateFrequencyType
interestRateFrequencyType;
@@ -1181,6 +1183,8 @@ final class LoansApiResourceSwagger {
public Integer repaymentEvery;
@Schema(example = "2")
public Integer repaymentFrequencyType;
+ @Schema(example = "1")
+ public Integer fixedLength;
@Schema(example = "2")
public BigDecimal interestRatePerPeriod;
@Schema(example = "1")
@@ -1317,6 +1321,8 @@ final class LoansApiResourceSwagger {
public Integer repaymentEvery;
@Schema(example = "0")
public Integer repaymentFrequencyType;
+ @Schema(example = "1")
+ public Integer fixedLength;
@Schema(example = "2")
public BigDecimal interestRatePerPeriod;
@Schema(example = "0")
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 3e315a2ac..20350f534 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
@@ -104,6 +104,7 @@ public class LoanAccountData {
private EnumOptionData termPeriodFrequencyType;
private Integer numberOfRepayments;
private Integer repaymentEvery;
+ private Integer fixedLength;
private EnumOptionData repaymentFrequencyType;
private EnumOptionData repaymentFrequencyNthDayType;
private EnumOptionData repaymentFrequencyDayOfWeekType;
@@ -274,7 +275,8 @@ public class LoanAccountData {
BigDecimal inArrearsTolerance, String
transactionProcessingStrategyCode, Integer graceOnPrincipalPayment,
Integer graceOnInterestPayment, Integer graceOnInterestCharged,
LocalDate interestChargedFromDate,
LocalDate repaymentsStartingFromDate, Integer rowIndex, ExternalId
externalId, Long groupId, Collection<LoanChargeData> charges,
- String linkAccountId, String locale, String dateFormat,
List<LoanCollateralManagementData> loanCollateralManagementData) {
+ String linkAccountId, String locale, String dateFormat,
List<LoanCollateralManagementData> loanCollateralManagementData,
+ Integer fixedLength) {
return new
LoanAccountData().setLoanType(loanTypeEnumOption).setClientId(clientId).setProductId(productId)
.setLoanOfficerId(loanOfficerId).setSubmittedOnDate(submittedOnDate).setFundId(fundId).setPrincipal(principal)
@@ -288,7 +290,7 @@ public class LoanAccountData {
.setGraceOnInterestCharged(graceOnInterestCharged).setInterestChargedFromDate(interestChargedFromDate)
.setRepaymentsStartingFromDate(repaymentsStartingFromDate).setRowIndex(rowIndex).setExternalId(externalId)
.setGroupId(groupId).setCharges(charges).setLinkAccountId(linkAccountId).setLocale(locale).setDateFormat(dateFormat)
- .setCollateral(loanCollateralManagementData);
+
.setCollateral(loanCollateralManagementData).setFixedLength(fixedLength);
}
public static LoanAccountData importInstanceGroup(EnumOptionData
loanTypeEnumOption, Long groupIdforGroupLoan, Long productId,
@@ -298,7 +300,7 @@ public class LoanAccountData {
EnumOptionData interestMethodEnum, EnumOptionData
interestCalculationPeriodEnum, BigDecimal arrearsTolerance,
String transactionProcessingStrategyCode, Integer
graceOnPrincipalPayment, Integer graceOnInterestPayment,
Integer graceOnInterestCharged, LocalDate interestChargedFromDate,
LocalDate repaymentsStartingFromDate, Integer rowIndex,
- ExternalId externalId, String linkAccountId, String locale, String
dateFormat) {
+ ExternalId externalId, String linkAccountId, String locale, String
dateFormat, Integer fixedLength) {
return new
LoanAccountData().setLoanType(loanTypeEnumOption).setGroupId(groupIdforGroupLoan).setProductId(productId)
.setLoanOfficerId(loanOfficerId).setSubmittedOnDate(submittedOnDate).setFundId(fundId).setPrincipal(principal)
@@ -310,8 +312,8 @@ public class LoanAccountData {
.setTransactionProcessingStrategyCode(transactionProcessingStrategyCode).setGraceOnPrincipalPayment(graceOnPrincipalPayment)
.setGraceOnInterestPayment(graceOnInterestPayment).setGraceOnInterestCharged(graceOnInterestCharged)
.setInterestChargedFromDate(interestChargedFromDate).setRepaymentsStartingFromDate(repaymentsStartingFromDate)
-
.setRowIndex(rowIndex).setExternalId(externalId).setLinkAccountId(linkAccountId).setLocale(locale)
- .setDateFormat(dateFormat);
+
.setRowIndex(rowIndex).setExternalId(externalId).setLinkAccountId(linkAccountId).setLocale(locale).setDateFormat(dateFormat)
+ .setFixedLength(fixedLength);
}
/**
@@ -350,7 +352,7 @@ public class LoanAccountData {
.setTermPeriodFrequencyType(acc.termPeriodFrequencyType).setNumberOfRepayments(acc.numberOfRepayments)
.setRepaymentEvery(acc.repaymentEvery).setRepaymentFrequencyType(acc.repaymentFrequencyType)
.setRepaymentFrequencyNthDayType(acc.repaymentFrequencyNthDayType)
-
.setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType)
+
.setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType).setFixedLength(acc.fixedLength)
.setTransactionProcessingStrategyCode(acc.transactionProcessingStrategyCode)
.setTransactionProcessingStrategyName(acc.transactionProcessingStrategyName).setAmortizationType(acc.amortizationType)
.setInterestRatePerPeriod(acc.interestRatePerPeriod).setInterestRateFrequencyType(acc.interestRateFrequencyType)
@@ -424,7 +426,7 @@ public class LoanAccountData {
.setTermPeriodFrequencyType(acc.termPeriodFrequencyType).setNumberOfRepayments(acc.numberOfRepayments)
.setRepaymentEvery(acc.repaymentEvery).setRepaymentFrequencyType(acc.repaymentFrequencyType)
.setRepaymentFrequencyNthDayType(acc.repaymentFrequencyNthDayType)
-
.setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType)
+
.setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType).setFixedLength(acc.fixedLength)
.setTransactionProcessingStrategyCode(acc.transactionProcessingStrategyCode)
.setTransactionProcessingStrategyName(acc.transactionProcessingStrategyName).setAmortizationType(acc.amortizationType)
.setInterestRatePerPeriod(acc.interestRatePerPeriod).setInterestRateFrequencyType(acc.interestRateFrequencyType)
@@ -643,7 +645,7 @@ public class LoanAccountData {
.setFixedPrincipalPercentagePerInstallment(product.getFixedPrincipalPercentagePerInstallment()).setDelinquent(delinquent)
.setDisallowExpectedDisbursements(product.getDisallowExpectedDisbursements()).setFraud(acc.fraud)
.setOverpaidOnDate(acc.overpaidOnDate).setChargedOff(acc.chargedOff).setLoanScheduleType(acc.getLoanScheduleType())
-
.setLoanScheduleProcessingType(acc.getLoanScheduleProcessingType());
+
.setLoanScheduleProcessingType(acc.getLoanScheduleProcessingType()).setFixedLength(product.getFixedLength());
}
/*
@@ -680,7 +682,7 @@ public class LoanAccountData {
LocalDate lastClosedBusinessDate, LocalDate overpaidOnDate, final
boolean chargedOff, final boolean enableDownPayment,
final BigDecimal disbursedAmountPercentageForDownPayment, final
boolean enableAutoRepaymentForDownPayment,
final boolean enableInstallmentLevelDelinquency, final
EnumOptionData loanScheduleType,
- final EnumOptionData loanScheduleProcessingType) {
+ final EnumOptionData loanScheduleProcessingType, final Integer
fixedLength) {
final CollectionData delinquent = CollectionData.template();
@@ -724,7 +726,7 @@ public class LoanAccountData {
.setEnableDownPayment(enableDownPayment).setDisbursedAmountPercentageForDownPayment(disbursedAmountPercentageForDownPayment)
.setEnableAutoRepaymentForDownPayment(enableAutoRepaymentForDownPayment)
.setEnableInstallmentLevelDelinquency(enableInstallmentLevelDelinquency).setLoanScheduleType(loanScheduleType)
- .setLoanScheduleProcessingType(loanScheduleProcessingType);
+
.setLoanScheduleProcessingType(loanScheduleProcessingType).setFixedLength(fixedLength);
}
/*
@@ -764,7 +766,7 @@ public class LoanAccountData {
.setPrincipal(acc.principal).setApprovedPrincipal(acc.approvedPrincipal).setNetDisbursalAmount(acc.netDisbursalAmount)
.setTotalOverpaid(acc.totalOverpaid).setInArrearsTolerance(acc.inArrearsTolerance).setTermFrequency(acc.termFrequency)
.setTermPeriodFrequencyType(acc.termPeriodFrequencyType).setNumberOfRepayments(acc.numberOfRepayments)
-
.setRepaymentEvery(acc.repaymentEvery).setRepaymentFrequencyType(acc.repaymentFrequencyType)
+
.setRepaymentEvery(acc.repaymentEvery).setRepaymentFrequencyType(acc.repaymentFrequencyType).setFixedLength(acc.fixedLength)
.setRepaymentFrequencyNthDayType(acc.repaymentFrequencyNthDayType)
.setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType)
.setTransactionProcessingStrategyCode(acc.transactionProcessingStrategyCode)
@@ -848,7 +850,7 @@ public class LoanAccountData {
.setTermPeriodFrequencyType(acc.termPeriodFrequencyType).setNumberOfRepayments(acc.numberOfRepayments)
.setRepaymentEvery(acc.repaymentEvery).setRepaymentFrequencyType(acc.repaymentFrequencyType)
.setRepaymentFrequencyNthDayType(acc.repaymentFrequencyNthDayType)
-
.setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType)
+
.setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType).setFixedLength(acc.fixedLength)
.setTransactionProcessingStrategyCode(acc.transactionProcessingStrategyCode)
.setTransactionProcessingStrategyName(acc.transactionProcessingStrategyName).setAmortizationType(acc.amortizationType)
.setInterestRatePerPeriod(acc.interestRatePerPeriod).setInterestRateFrequencyType(acc.interestRateFrequencyType)
@@ -947,7 +949,7 @@ public class LoanAccountData {
.setTotalOverpaid(acc.totalOverpaid).setInArrearsTolerance(acc.inArrearsTolerance).setTermFrequency(acc.termFrequency)
.setTermPeriodFrequencyType(acc.termPeriodFrequencyType).setNumberOfRepayments(acc.numberOfRepayments)
.setRepaymentEvery(acc.repaymentEvery).setRepaymentFrequencyType(acc.repaymentFrequencyType)
-
.setRepaymentFrequencyNthDayType(acc.repaymentFrequencyNthDayType)
+
.setRepaymentFrequencyNthDayType(acc.repaymentFrequencyNthDayType).setFixedLength(acc.fixedLength)
.setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType)
.setTransactionProcessingStrategyCode(acc.transactionProcessingStrategyCode)
.setTransactionProcessingStrategyName(acc.transactionProcessingStrategyName).setAmortizationType(acc.amortizationType)
@@ -1016,7 +1018,7 @@ public class LoanAccountData {
.setTermPeriodFrequencyType(acc.termPeriodFrequencyType).setNumberOfRepayments(acc.numberOfRepayments)
.setRepaymentEvery(acc.repaymentEvery).setRepaymentFrequencyType(acc.repaymentFrequencyType)
.setRepaymentFrequencyNthDayType(acc.repaymentFrequencyNthDayType)
-
.setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType)
+
.setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType).setFixedLength(acc.fixedLength)
.setTransactionProcessingStrategyCode(acc.transactionProcessingStrategyCode)
.setTransactionProcessingStrategyName(acc.transactionProcessingStrategyName).setAmortizationType(acc.amortizationType)
.setInterestRatePerPeriod(acc.interestRatePerPeriod).setInterestRateFrequencyType(acc.interestRateFrequencyType)
@@ -1094,7 +1096,7 @@ public class LoanAccountData {
.setMeeting(acc.meeting).setProductOptions(acc.productOptions).setTermFrequencyTypeOptions(acc.termFrequencyTypeOptions)
.setRepaymentFrequencyTypeOptions(acc.repaymentFrequencyTypeOptions)
.setRepaymentFrequencyNthDayTypeOptions(acc.repaymentFrequencyNthDayTypeOptions)
-
.setRepaymentFrequencyDaysOfWeekTypeOptions(acc.repaymentFrequencyDaysOfWeekTypeOptions)
+
.setRepaymentFrequencyDaysOfWeekTypeOptions(acc.repaymentFrequencyDaysOfWeekTypeOptions).setFixedLength(acc.fixedLength)
.setTransactionProcessingStrategyOptions(acc.transactionProcessingStrategyOptions)
.setInterestRateFrequencyTypeOptions(acc.interestRateFrequencyTypeOptions)
.setAmortizationTypeOptions(acc.amortizationTypeOptions).setInterestTypeOptions(acc.interestTypeOptions)
@@ -1141,7 +1143,7 @@ public class LoanAccountData {
.setTermPeriodFrequencyType(acc.termPeriodFrequencyType).setNumberOfRepayments(acc.numberOfRepayments)
.setRepaymentEvery(acc.repaymentEvery).setRepaymentFrequencyType(acc.repaymentFrequencyType)
.setRepaymentFrequencyNthDayType(acc.repaymentFrequencyNthDayType)
-
.setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType)
+
.setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType).setFixedLength(acc.fixedLength)
.setTransactionProcessingStrategyCode(acc.transactionProcessingStrategyCode)
.setTransactionProcessingStrategyName(acc.transactionProcessingStrategyName).setAmortizationType(acc.amortizationType)
.setInterestRatePerPeriod(acc.interestRatePerPeriod).setInterestRateFrequencyType(acc.interestRateFrequencyType)
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 946d1e565..ba296caf0 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
@@ -469,14 +469,21 @@ public class LoanScheduleAssembler {
LoanScheduleType loanScheduleType =
loanProduct.getLoanProductRelatedDetail().getLoanScheduleType();
if
(this.fromApiJsonHelper.parameterExists(LoanProductConstants.LOAN_SCHEDULE_TYPE,
element)) {
-
LoanScheduleType.valueOf(this.fromApiJsonHelper.extractStringNamed(LoanProductConstants.LOAN_SCHEDULE_TYPE,
element));
+ loanScheduleType = LoanScheduleType
+
.valueOf(this.fromApiJsonHelper.extractStringNamed(LoanProductConstants.LOAN_SCHEDULE_TYPE,
element));
}
- LoanScheduleProcessingType loanScheduleProcessingType =
loanProduct.getLoanProductRelatedDetail().getLoanScheduleProcessingType();
- if
(this.fromApiJsonHelper.parameterExists(LoanProductConstants.LOAN_SCHEDULE_TYPE,
element)) {
- LoanScheduleProcessingType
+ LoanScheduleProcessingType loanScheduleProcessingType =
loanProduct.getLoanProductRelatedDetail().getLoanScheduleProcessingType();
+ if
(this.fromApiJsonHelper.parameterExists(LoanProductConstants.LOAN_SCHEDULE_PROCESSING_TYPE,
element)) {
+ loanScheduleProcessingType = LoanScheduleProcessingType
.valueOf(this.fromApiJsonHelper.extractStringNamed(LoanProductConstants.LOAN_SCHEDULE_PROCESSING_TYPE,
element));
}
+
+ Integer fixedLength =
loanProduct.getLoanProductRelatedDetail().getFixedLength();
+ if
(this.fromApiJsonHelper.parameterExists(LoanProductConstants.FIXED_LENGTH,
element)) {
+ fixedLength =
this.fromApiJsonHelper.extractIntegerWithLocaleNamed(LoanProductConstants.FIXED_LENGTH,
element);
+ }
+
return LoanApplicationTerms.assembleFrom(applicationCurrency,
loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments,
repaymentEvery, repaymentPeriodFrequencyType, nthDay,
weekDayType, amortizationMethod, interestMethod,
interestRatePerPeriod, interestRatePeriodFrequencyType,
annualNominalInterestRate, interestCalculationPeriodMethod,
@@ -491,7 +498,7 @@ public class LoanScheduleAssembler {
allowCompoundingOnEod, isEqualAmortization,
isInterestToBeRecoveredFirstWhenGreaterThanEMI,
fixedPrincipalPercentagePerInstallment,
isPrincipalCompoundingDisabledForOverdueLoans, isDownPaymentEnabled,
disbursedAmountPercentageForDownPayment,
isAutoRepaymentForDownPaymentEnabled, repaymentStartDateType, submittedOnDate,
- loanScheduleType, loanScheduleProcessingType);
+ loanScheduleType, loanScheduleProcessingType, fixedLength);
}
private CalendarInstance createCalendarForSameAsRepayment(final Integer
repaymentEvery,
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java
index f075d7fbe..2c1251f49 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java
@@ -104,7 +104,7 @@ public final class LoanApplicationCommandFromApiJsonHelper {
LoanApiConstants.lastApplication, // glim specific
LoanApiConstants.daysInYearTypeParameterName,
LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName,
LoanApiConstants.DISALLOW_EXPECTED_DISBURSEMENTS,
LoanApiConstants.FRAUD_ATTRIBUTE_NAME,
- LoanProductConstants.LOAN_SCHEDULE_PROCESSING_TYPE));
+ LoanProductConstants.LOAN_SCHEDULE_PROCESSING_TYPE,
LoanProductConstants.FIXED_LENGTH));
public static final String LOANAPPLICATION_UNDO = "loanapplication.undo";
private final FromJsonHelper fromApiJsonHelper;
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 a84d4127b..bfa5b96b5 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
@@ -637,6 +637,7 @@ public class LoanReadPlatformServiceImpl implements
LoanReadPlatformService, Loa
+ " l.grace_on_principal_periods as
graceOnPrincipalPayment, l.recurring_moratorium_principal_periods as
recurringMoratoriumOnPrincipalPeriods, l.grace_on_interest_periods as
graceOnInterestPayment, l.grace_interest_free_periods as
graceOnInterestCharged,l.grace_on_arrears_ageing as graceOnArrearsAgeing,"
+ " l.nominal_interest_rate_per_period as
interestRatePerPeriod, l.annual_nominal_interest_rate as annualInterestRate, "
+ " l.repayment_period_frequency_enum as
repaymentFrequencyType, l.interest_period_frequency_enum as
interestRateFrequencyType, "
+ + " l.fixed_length as fixedLength, "
+ " l.term_frequency as termFrequency,
l.term_period_frequency_enum as termPeriodFrequencyType, "
+ " l.amortization_method_enum as amortizationType,
l.interest_method_enum as interestType, l.is_equal_amortization as
isEqualAmortization, l.interest_calculated_in_period_enum as
interestCalculationPeriodType,"
+ " l.fixed_principal_percentage_per_installment
fixedPrincipalPercentagePerInstallment, "
@@ -1059,6 +1060,7 @@ public class LoanReadPlatformServiceImpl implements
LoanReadPlatformService, Loa
final LoanScheduleType loanScheduleType =
LoanScheduleType.valueOf(loanScheduleTypeStr);
final String loanScheduleProcessingTypeStr =
rs.getString("loanScheduleProcessingType");
final LoanScheduleProcessingType loanScheduleProcessingType =
LoanScheduleProcessingType.valueOf(loanScheduleProcessingTypeStr);
+ final Integer fixedLength = JdbcSupport.getInteger(rs,
"fixedLength");
return LoanAccountData.basicLoanDetails(id, accountNo, status,
externalId, clientId, clientAccountNo, clientName,
clientOfficeId, clientExternalId, groupData, loanType,
loanProductId, loanProductName, loanProductDescription,
@@ -1077,7 +1079,7 @@ public class LoanReadPlatformServiceImpl implements
LoanReadPlatformService, Loa
fixedPrincipalPercentagePerInstallment, delinquencyRange,
disallowExpectedDisbursements, isFraud,
lastClosedBusinessDate, overpaidOnDate, isChargedOff,
enableDownPayment, disbursedAmountPercentageForDownPayment,
enableAutoRepaymentForDownPayment,
enableInstallmentLevelDelinquency, loanScheduleType.asEnumOptionData(),
- loanScheduleProcessingType.asEnumOptionData());
+ loanScheduleProcessingType.asEnumOptionData(),
fixedLength);
}
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
index ed031bb64..c96e00148 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
@@ -95,6 +95,8 @@ final class LoanProductsApiResourceSwagger {
public BigDecimal fixedPrincipalPercentagePerInstallment;
@Schema(example = "true")
public Boolean canDefineInstallmentAmount;
+ @Schema(example = "10")
+ public Integer fixedLength;
// Settings
@Schema(example = "false")
@@ -555,6 +557,8 @@ final class LoanProductsApiResourceSwagger {
@Schema(example = "7")
public Integer repaymentEvery;
public GetLoanProductsRepaymentFrequencyType repaymentFrequencyType;
+ @Schema(example = "10")
+ public Integer fixedLength;
@Schema(example = "15.000000")
public Double interestRatePerPeriod;
public
GetLoanProductsResponse.GetLoanProductsInterestRateFrequencyType
interestRateFrequencyType;
@@ -1210,6 +1214,8 @@ final class LoanProductsApiResourceSwagger {
@Schema(example = "7")
public Integer repaymentEvery;
public GetLoanProductsResponse.GetLoanProductsRepaymentFrequencyType
repaymentFrequencyType;
+ @Schema(example = "10")
+ public Integer fixedLength;
@Schema(example = "5.000000")
public Double interestRatePerPeriod;
public
GetLoanProductsProductIdResponse.GetLoanProductsInterestRateFrequencyType
interestRateFrequencyType;
@@ -1332,6 +1338,8 @@ final class LoanProductsApiResourceSwagger {
public BigDecimal fixedPrincipalPercentagePerInstallment;
@Schema(example = "true")
public Boolean canDefineInstallmentAmount;
+ @Schema(example = "10.0")
+ public Integer fixedLength;
// Settings
@Schema(example = "false")
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
index ddded6d7c..7403e82e4 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
@@ -89,6 +89,7 @@ public class LoanProductData implements Serializable {
private final Integer maxNumberOfRepayments;
private final Integer repaymentEvery;
private final EnumOptionData repaymentFrequencyType;
+ private final Integer fixedLength;
private final BigDecimal interestRatePerPeriod;
private final BigDecimal minInterestRatePerPeriod;
private final BigDecimal maxInterestRatePerPeriod;
@@ -237,6 +238,7 @@ public class LoanProductData implements Serializable {
final Integer minNumberOfRepayments = null;
final Integer maxNumberOfRepayments = null;
final Integer repaymentEvery = null;
+ final Integer fixedLength = null;
final BigDecimal interestRatePerPeriod = null;
final BigDecimal minInterestRatePerPeriod = null;
final BigDecimal maxInterestRatePerPeriod = null;
@@ -341,7 +343,7 @@ public class LoanProductData implements Serializable {
fixedPrincipalPercentagePerInstallment,
delinquencyBucketOptions, delinquencyBucket, dueDaysForRepaymentEvent,
overDueDaysForRepaymentEvent, enableDownPayment,
disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment,
paymentAllocation, creditAllocation, repaymentStartDateType,
enableInstallmentLevelDelinquency, loanScheduleType,
- loanScheduleProcessingType);
+ loanScheduleProcessingType, fixedLength);
}
@@ -356,6 +358,7 @@ public class LoanProductData implements Serializable {
final Integer minNumberOfRepayments = null;
final Integer maxNumberOfRepayments = null;
final Integer repaymentEvery = null;
+ final Integer fixedLength = null;
final BigDecimal interestRatePerPeriod = null;
final BigDecimal minInterestRatePerPeriod = null;
final BigDecimal maxInterestRatePerPeriod = null;
@@ -460,7 +463,7 @@ public class LoanProductData implements Serializable {
fixedPrincipalPercentagePerInstallment,
delinquencyBucketOptions, delinquencyBucket, dueDaysForRepaymentEvent,
overDueDaysForRepaymentEvent, enableDownPayment,
disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment,
paymentAllocation, creditAllocation, repaymentStartDateType,
enableInstallmentLevelDelinquency, loanScheduleType,
- loanScheduleProcessingType);
+ loanScheduleProcessingType, fixedLength);
}
@@ -479,6 +482,7 @@ public class LoanProductData implements Serializable {
final Integer maxNumberOfRepayments = null;
final Integer repaymentEvery = null;
+ final Integer fixedLength = null;
final BigDecimal interestRatePerPeriod = null;
final BigDecimal minInterestRatePerPeriod = null;
final BigDecimal maxInterestRatePerPeriod = null;
@@ -586,7 +590,7 @@ public class LoanProductData implements Serializable {
fixedPrincipalPercentagePerInstallment,
delinquencyBucketOptions, delinquencyBucket, dueDaysForRepaymentEvent,
overDueDaysForRepaymentEvent, enableDownPayment,
disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment,
paymentAllocation, creditAllocation, repaymentStartDateType,
enableInstallmentLevelDelinquency, loanScheduleType,
- loanScheduleProcessingType);
+ loanScheduleProcessingType, fixedLength);
}
@@ -607,6 +611,7 @@ public class LoanProductData implements Serializable {
final Integer maxNumberOfRepayments = null;
final Integer repaymentEvery = null;
+ final Integer fixedLength = null;
final BigDecimal interestRatePerPeriod = null;
final BigDecimal minInterestRatePerPeriod = null;
final BigDecimal maxInterestRatePerPeriod = null;
@@ -706,7 +711,7 @@ public class LoanProductData implements Serializable {
fixedPrincipalPercentagePerInstallment,
delinquencyBucketOptions, delinquencyBucket, dueDaysForRepaymentEvent,
overDueDaysForRepaymentEvent, enableDownPayment,
disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment,
paymentAllocation, creditAllocationData,
repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
- loanScheduleProcessingType);
+ loanScheduleProcessingType, fixedLength);
}
public static LoanProductData withAccountingDetails(final LoanProductData
productData, final Map<String, Object> accountingMappings,
@@ -756,7 +761,7 @@ public class LoanProductData implements Serializable {
final BigDecimal disbursedAmountPercentageForDownPayment, final
boolean enableAutoRepaymentForDownPayment,
final Collection<AdvancedPaymentData> paymentAllocation, final
Collection<CreditAllocationData> creditAllocation,
final EnumOptionData repaymentStartDateType, final boolean
enableInstallmentLevelDelinquency,
- final EnumOptionData loanScheduleType, final EnumOptionData
loanScheduleProcessingType) {
+ final EnumOptionData loanScheduleType, final EnumOptionData
loanScheduleProcessingType, final Integer fixedLength) {
this.id = id;
this.name = name;
this.shortName = shortName;
@@ -774,6 +779,7 @@ public class LoanProductData implements Serializable {
this.graceOnInterestPayment = graceOnInterestPayment;
this.graceOnInterestCharged = graceOnInterestCharged;
this.repaymentEvery = repaymentEvery;
+ this.fixedLength = fixedLength;
this.interestRatePerPeriod = interestRatePerPeriod;
this.minInterestRatePerPeriod = minInterestRatePerPeriod;
this.maxInterestRatePerPeriod = maxInterestRatePerPeriod;
@@ -929,6 +935,7 @@ public class LoanProductData implements Serializable {
this.minNumberOfRepayments = productData.minNumberOfRepayments;
this.maxNumberOfRepayments = productData.maxNumberOfRepayments;
this.repaymentEvery = productData.repaymentEvery;
+ this.fixedLength = productData.fixedLength;
this.interestRatePerPeriod = productData.interestRatePerPeriod;
this.minInterestRatePerPeriod = productData.minInterestRatePerPeriod;
this.maxInterestRatePerPeriod = productData.maxInterestRatePerPeriod;
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 c5ee18fbf..625c7de60 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
@@ -171,7 +171,7 @@ public final class LoanProductDataValidator {
LoanProductConstants.ENABLE_DOWN_PAYMENT,
LoanProductConstants.DISBURSED_AMOUNT_PERCENTAGE_DOWN_PAYMENT,
LoanProductConstants.ENABLE_AUTO_REPAYMENT_DOWN_PAYMENT,
LoanProductConstants.REPAYMENT_START_DATE_TYPE,
LoanProductConstants.ENABLE_INSTALLMENT_LEVEL_DELINQUENCY,
LoanProductConstants.LOAN_SCHEDULE_TYPE,
- LoanProductConstants.LOAN_SCHEDULE_PROCESSING_TYPE));
+ LoanProductConstants.LOAN_SCHEDULE_PROCESSING_TYPE,
LoanProductConstants.FIXED_LENGTH));
private static final String[] SUPPORTED_LOAN_CONFIGURABLE_ATTRIBUTES = {
LoanProductConstants.amortizationTypeParamName,
LoanProductConstants.interestTypeParamName,
LoanProductConstants.transactionProcessingStrategyCodeParamName,
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 a09ac1f58..31b776163 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
@@ -234,6 +234,7 @@ public class LoanProductReadPlatformServiceImpl implements
LoanProductReadPlatfo
+ "lp.nominal_interest_rate_per_period as
interestRatePerPeriod, lp.min_nominal_interest_rate_per_period as
minInterestRatePerPeriod, lp.max_nominal_interest_rate_per_period as
maxInterestRatePerPeriod, lp.interest_period_frequency_enum as
interestRatePerPeriodFreq, "
+ "lp.annual_nominal_interest_rate as annualInterestRate,
lp.interest_method_enum as interestMethod,
lp.interest_calculated_in_period_enum as
interestCalculationInPeriodMethod,lp.allow_partial_period_interest_calcualtion
as allowPartialPeriodInterestCalcualtion, "
+ "lp.repay_every as repaidEvery,
lp.repayment_period_frequency_enum as repaymentPeriodFrequency,
lp.number_of_repayments as numberOfRepayments, lp.min_number_of_repayments as
minNumberOfRepayments, lp.max_number_of_repayments as maxNumberOfRepayments, "
+ + "lp.fixed_length as fixedLength, "
+ "lp.grace_on_principal_periods as
graceOnPrincipalPayment, lp.recurring_moratorium_principal_periods as
recurringMoratoriumOnPrincipalPeriods, lp.grace_on_interest_periods as
graceOnInterestPayment, lp.grace_interest_free_periods as
graceOnInterestCharged,lp.grace_on_arrears_ageing as
graceOnArrearsAgeing,lp.overdue_days_for_npa as overdueDaysForNPA, "
+ "lp.min_days_between_disbursal_and_first_repayment As
minimumDaysBetweenDisbursalAndFirstRepayment, "
+ "lp.amortization_method_enum as amortizationMethod,
lp.arrearstolerance_amount as tolerance, "
@@ -319,6 +320,7 @@ public class LoanProductReadPlatformServiceImpl implements
LoanProductReadPlatfo
final Integer minNumberOfRepayments = JdbcSupport.getInteger(rs,
"minNumberOfRepayments");
final Integer maxNumberOfRepayments = JdbcSupport.getInteger(rs,
"maxNumberOfRepayments");
final Integer repaymentEvery = JdbcSupport.getInteger(rs,
"repaidEvery");
+ final Integer fixedLength = JdbcSupport.getInteger(rs,
"fixedLength");
final Integer graceOnPrincipalPayment =
JdbcSupport.getIntegerDefaultToNullIfZero(rs, "graceOnPrincipalPayment");
final Integer recurringMoratoriumOnPrincipalPeriods =
JdbcSupport.getIntegerDefaultToNullIfZero(rs,
@@ -544,7 +546,8 @@ public class LoanProductReadPlatformServiceImpl implements
LoanProductReadPlatfo
isRatesEnabled, fixedPrincipalPercentagePerInstallment,
delinquencyBucketOptions, delinquencyBucket,
dueDaysForRepaymentEvent, overDueDaysForRepaymentEvent,
enableDownPayment, disbursedAmountPercentageForDownPayment,
enableAutoRepaymentForDownPayment, advancedPaymentData,
creditAllocationData, repaymentStartDateType,
- enableInstallmentLevelDelinquency,
loanScheduleType.asEnumOptionData(),
loanScheduleProcessingType.asEnumOptionData());
+ enableInstallmentLevelDelinquency,
loanScheduleType.asEnumOptionData(),
loanScheduleProcessingType.asEnumOptionData(),
+ fixedLength);
}
}
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 82421fa84..10d966e4d 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
@@ -123,7 +123,7 @@ public class DefaultScheduledDateGeneratorTest {
null, null, null, null, null,
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);
+ DISBURSEMENT_DATE, submittedOnDate, CUMULATIVE,
LoanScheduleProcessingType.HORIZONTAL, null);
}
private HolidayDetailDTO createHolidayDTO() {
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
index 7a25c2e47..e42afa47a 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
@@ -1962,7 +1962,8 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("500", "15", "4",
true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.VERTICAL, assetAccount,
incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), localLoanProductId,
- BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023");
+ BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01
January 2023", "01 January 2023",
+ LoanScheduleProcessingType.VERTICAL);
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -2489,7 +2490,8 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("1000", "15", "3",
true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.VERTICAL, assetAccount,
incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse =
applyForLoanApplication(client.getClientId(), localLoanProductId,
- BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO,
"01 September 2023", "01 September 2023");
+ BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO,
"01 September 2023", "01 September 2023",
+ LoanScheduleProcessingType.VERTICAL);
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -3621,11 +3623,17 @@ public class
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
private static PostLoansResponse applyForLoanApplication(final Long
clientId, final Integer loanProductId, final BigDecimal principal,
final int loanTermFrequency, final int repaymentAfterEvery, final
int numberOfRepayments, final BigDecimal interestRate,
final String expectedDisbursementDate, final String
submittedOnDate) {
+ return applyForLoanApplication(clientId, loanProductId, principal,
loanTermFrequency, repaymentAfterEvery, numberOfRepayments,
+ interestRate, expectedDisbursementDate, submittedOnDate,
LoanScheduleProcessingType.HORIZONTAL);
+ }
+
+ private static PostLoansResponse applyForLoanApplication(final Long
clientId, final Integer loanProductId, final BigDecimal principal,
+ final int loanTermFrequency, final int repaymentAfterEvery, final
int numberOfRepayments, final BigDecimal interestRate,
+ final String expectedDisbursementDate, final String
submittedOnDate, LoanScheduleProcessingType loanScheduleProcessingType) {
LOG.info("--------------------------------APPLYING FOR LOAN
APPLICATION--------------------------------");
return applyForLoanApplication(clientId, loanProductId, principal,
loanTermFrequency, repaymentAfterEvery, numberOfRepayments,
interestRate, expectedDisbursementDate, submittedOnDate,
-
AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY,
- LoanScheduleProcessingType.HORIZONTAL.name());
+
AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY,
loanScheduleProcessingType.name());
}
private static void validateLoanTransaction(GetLoansLoanIdResponse
loanDetails, int index, double transactionAmount,
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/FixedLengthLoanProductIntegrationTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/FixedLengthLoanProductIntegrationTest.java
new file mode 100644
index 000000000..a85931ed5
--- /dev/null
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/FixedLengthLoanProductIntegrationTest.java
@@ -0,0 +1,108 @@
+/**
+ * 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.integrationtests;
+
+import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
+import org.apache.fineract.client.models.GetLoansLoanIdResponse;
+import org.apache.fineract.client.models.PostLoanProductsRequest;
+import org.apache.fineract.client.models.PostLoanProductsResponse;
+import org.apache.fineract.client.models.PutLoanProductsProductIdRequest;
+import org.apache.fineract.client.models.PutLoanProductsProductIdResponse;
+import org.apache.fineract.integrationtests.common.ClientHelper;
+import
org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(LoanTestLifecycleExtension.class)
+public class FixedLengthLoanProductIntegrationTest extends
BaseLoanIntegrationTest {
+
+ @Test
+ public void testCreateReadUpdateReadLoanProductWithFixedLength() {
+ // create with 5
+ PostLoanProductsRequest loanProductsRequest =
fixedLengthLoanProduct(5);
+ PostLoanProductsResponse loanProduct =
loanProductHelper.createLoanProduct(loanProductsRequest);
+ Assertions.assertNotNull(loanProduct.getResourceId());
+
+ // read
+ GetLoanProductsProductIdResponse getLoanProductsProductIdResponse =
loanProductHelper
+ .retrieveLoanProductById(loanProduct.getResourceId());
+ Assertions.assertEquals(5,
getLoanProductsProductIdResponse.getFixedLength());
+
+ // update to 6
+ PutLoanProductsProductIdRequest updateRequest = new
PutLoanProductsProductIdRequest().fixedLength(6).locale("en");
+ PutLoanProductsProductIdResponse putLoanProductsProductIdResponse =
loanProductHelper
+ .updateLoanProductById(loanProduct.getResourceId(),
updateRequest);
+
Assertions.assertNotNull(putLoanProductsProductIdResponse.getResourceId());
+
+ // read again
+ getLoanProductsProductIdResponse =
loanProductHelper.retrieveLoanProductById(loanProduct.getResourceId());
+ Assertions.assertEquals(6,
getLoanProductsProductIdResponse.getFixedLength());
+
+ // update to null
+
loanTransactionHelper.updateLoanProduct(putLoanProductsProductIdResponse.getResourceId(),
"""
+ {
+ "fixedLength": null,
+ "locale": "en"
+ }
+ """);
+
+ // read again
+ getLoanProductsProductIdResponse =
loanProductHelper.retrieveLoanProductById(loanProduct.getResourceId());
+
Assertions.assertNull(getLoanProductsProductIdResponse.getFixedLength());
+ }
+
+ @Test
+ public void testLoanApplicationWithFixedLengthInheritedFromLoanProduct() {
+ runAt("01 January 2023", () -> {
+ Long clientId =
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+
+ PostLoanProductsResponse loanProduct =
loanProductHelper.createLoanProduct(fixedLengthLoanProduct(6));
+ Assertions.assertNotNull(loanProduct.getResourceId());
+
+ Long loanId = applyAndApproveLoan(clientId,
loanProduct.getResourceId(), "01 January 2023", 1000.0);
+ GetLoansLoanIdResponse loanDetails =
loanTransactionHelper.getLoanDetails(loanId);
+ Assertions.assertEquals(6, loanDetails.getFixedLength());
+ });
+ }
+
+ @Test
+ public void
testLoanApplicationWithFixedLengthOverriddenByLoanApplication() {
+ runAt("01 January 2023", () -> {
+ Long clientId =
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+
+ PostLoanProductsResponse loanProduct =
loanProductHelper.createLoanProduct(fixedLengthLoanProduct(6));
+ Assertions.assertNotNull(loanProduct.getResourceId());
+
+ Long loanId = applyAndApproveLoan(clientId,
loanProduct.getResourceId(), "01 January 2023", 1000.0, 1, //
+ loanApplication -> loanApplication.fixedLength(5) //
+ );
+ GetLoansLoanIdResponse loanDetails =
loanTransactionHelper.getLoanDetails(loanId);
+ Assertions.assertEquals(5, loanDetails.getFixedLength());
+ });
+ }
+
+ private PostLoanProductsRequest fixedLengthLoanProduct(Integer
fixedLength) {
+ return
createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct().numberOfRepayments(4)//
+ .repaymentEvery(1)//
+
.repaymentFrequencyType(RepaymentFrequencyType.MONTHS.longValue())//
+
.transactionProcessingStrategyCode("mifos-standard-strategy").fixedLength(fixedLength);
+ }
+
+}
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductHelper.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductHelper.java
index b899f20d1..5e20943e6 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductHelper.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductHelper.java
@@ -46,6 +46,10 @@ public class LoanProductHelper extends IntegrationTest {
return ok(fineract().loanProducts.updateLoanProduct1(externalId,
request));
}
+ public PutLoanProductsProductIdResponse updateLoanProductById(Long
loanProductId, PutLoanProductsProductIdRequest request) {
+ return ok(fineract().loanProducts.updateLoanProduct(loanProductId,
request));
+ }
+
public GetLoanProductsTemplateResponse getLoanProductTemplate(boolean
isProductMixTemplate) {
return
ok(fineract().loanProducts.retrieveTemplate11(isProductMixTemplate));
}