FINERACT-1806: Add charge-off reasons to loan product response

This commit is contained in:
Oleksii Novikov
2024-11-14 15:10:42 +01:00
committed by Adam Saghy
parent 6286d1f821
commit 628f27bf32
11 changed files with 197 additions and 5 deletions
@@ -19,6 +19,7 @@
package org.apache.fineract.infrastructure.codes.service; package org.apache.fineract.infrastructure.codes.service;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import org.apache.fineract.infrastructure.codes.data.CodeValueData; import org.apache.fineract.infrastructure.codes.data.CodeValueData;
/** /**
@@ -40,7 +41,7 @@ import org.apache.fineract.infrastructure.codes.data.CodeValueData;
*/ */
public interface CodeValueReadPlatformService { public interface CodeValueReadPlatformService {
Collection<CodeValueData> retrieveCodeValuesByCode(String code); List<CodeValueData> retrieveCodeValuesByCode(String code);
Collection<CodeValueData> retrieveAllCodeValues(Long codeId); Collection<CodeValueData> retrieveAllCodeValues(Long codeId);
@@ -53,6 +53,7 @@ import org.apache.fineract.client.services.SchedulerApi;
import org.apache.fineract.client.services.SchedulerJobApi; import org.apache.fineract.client.services.SchedulerJobApi;
import org.apache.fineract.client.services.UsersApi; import org.apache.fineract.client.services.UsersApi;
import org.apache.fineract.client.util.FineractClient; import org.apache.fineract.client.util.FineractClient;
import org.apache.fineract.test.stepdef.loan.LoanProductsCustomApi;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@@ -98,6 +99,11 @@ public class ApiConfiguration {
return fineractClient.createService(LoanProductsApi.class); return fineractClient.createService(LoanProductsApi.class);
} }
@Bean
public LoanProductsCustomApi loanProductsCustomApi() {
return fineractClient.createService(LoanProductsCustomApi.class);
}
@Bean @Bean
public SavingsProductApi savingsProductApi() { public SavingsProductApi savingsProductApi() {
return fineractClient.createService(SavingsProductApi.class); return fineractClient.createService(SavingsProductApi.class);
@@ -24,6 +24,7 @@ import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.client.models.BatchResponse; import org.apache.fineract.client.models.BatchResponse;
import org.apache.fineract.client.models.GetJournalEntriesTransactionIdResponse; import org.apache.fineract.client.models.GetJournalEntriesTransactionIdResponse;
@@ -888,4 +889,19 @@ public final class ErrorMessageHelper {
public static String downpaymentDisabledOnProductErrorCodeMsg() { public static String downpaymentDisabledOnProductErrorCodeMsg() {
return "The Loan can not override the downpayment properties because in the Loan Product the downpayment is disabled"; return "The Loan can not override the downpayment properties because in the Loan Product the downpayment is disabled";
} }
public static String wrongValueInLineInChargeOffReasonOptions(final int line, final List<List<String>> actual,
final List<String> expected) {
final String actualValues = actual.stream().map(List::toString).collect(Collectors.joining(System.lineSeparator()));
return String.format(
"%nWrong value in Loan Charge-Off Reason Options line %s. %nActual values in line: %s %nExpected values in line: %s", line,
actualValues, expected);
}
public static String wrongNumberOfLinesInChargeOffReasonOptions(final int actual, final int expected) {
return String.format(
"Number of lines in loan charge-off reason options is not correct. Actual value is: %d - Expected value is: %d", actual,
expected);
}
} }
@@ -0,0 +1,30 @@
/**
* 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.test.stepdef.loan;
import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
import retrofit2.Call;
import retrofit2.http.GET;
public interface LoanProductsCustomApi {
@GET("v1/loanproducts/{productId}")
Call<GetLoanProductsProductIdResponse> retrieveLoanProductDetails(@retrofit2.http.Path("productId") Long productId,
@retrofit2.http.Query("template") String isTemplate);
}
@@ -52,7 +52,9 @@ import org.apache.fineract.avro.loan.v1.LoanStatusEnumDataV1;
import org.apache.fineract.avro.loan.v1.LoanTransactionDataV1; import org.apache.fineract.avro.loan.v1.LoanTransactionDataV1;
import org.apache.fineract.client.models.AdvancedPaymentData; import org.apache.fineract.client.models.AdvancedPaymentData;
import org.apache.fineract.client.models.DeleteLoansLoanIdResponse; import org.apache.fineract.client.models.DeleteLoansLoanIdResponse;
import org.apache.fineract.client.models.GetLoanProductsChargeOffReasonOptions;
import org.apache.fineract.client.models.GetLoanProductsProductIdResponse; import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
import org.apache.fineract.client.models.GetLoanProductsTemplateResponse;
import org.apache.fineract.client.models.GetLoansLoanIdDelinquencySummary; import org.apache.fineract.client.models.GetLoansLoanIdDelinquencySummary;
import org.apache.fineract.client.models.GetLoansLoanIdLoanChargeData; import org.apache.fineract.client.models.GetLoansLoanIdLoanChargeData;
import org.apache.fineract.client.models.GetLoansLoanIdLoanChargePaidByData; import org.apache.fineract.client.models.GetLoansLoanIdLoanChargePaidByData;
@@ -158,6 +160,9 @@ public class LoanStepDef extends AbstractStepDef {
@Autowired @Autowired
private LoanProductsApi loanProductsApi; private LoanProductsApi loanProductsApi;
@Autowired
private LoanProductsCustomApi loanProductsCustomApi;
@Autowired @Autowired
private EventStore eventStore; private EventStore eventStore;
@@ -2550,6 +2555,66 @@ public class LoanStepDef extends AbstractStepDef {
assertTrue(relationshipOptional.isPresent(), "Missed relationship between transactions"); assertTrue(relationshipOptional.isPresent(), "Missed relationship between transactions");
} }
@Then("Loan Product Charge-Off reasons options from loan product template have {int} options, with the following data:")
public void loanProductTemplateChargeOffReasonOptionsCheck(final int linesExpected, final DataTable table) throws IOException {
final Response<GetLoanProductsTemplateResponse> loanProductDetails = loanProductsApi.retrieveTemplate11(false).execute();
ErrorHelper.checkSuccessfulApiCall(loanProductDetails);
assertNotNull(loanProductDetails.body());
final List<GetLoanProductsChargeOffReasonOptions> chargeOffReasonOptions = loanProductDetails.body().getChargeOffReasonOptions();
assertNotNull(chargeOffReasonOptions);
final List<List<String>> data = table.asLists();
final int linesActual = chargeOffReasonOptions.size();
data.stream().skip(1) // skip headers
.forEach(expectedValues -> {
final List<List<String>> actualValuesList = chargeOffReasonOptions.stream()
.map(chargeOffReason -> fetchValuesOfLoanChargeOffReasonOptions(data.get(0), chargeOffReason))
.collect(Collectors.toList());
final boolean containsExpectedValues = actualValuesList.stream()
.anyMatch(actualValues -> actualValues.equals(expectedValues));
assertThat(containsExpectedValues).as(ErrorMessageHelper
.wrongValueInLineInChargeOffReasonOptions(data.indexOf(expectedValues), actualValuesList, expectedValues))
.isTrue();
assertThat(linesActual).as(ErrorMessageHelper.wrongNumberOfLinesInChargeOffReasonOptions(linesActual, linesExpected))
.isEqualTo(linesExpected);
});
}
@Then("Loan Product {string} Charge-Off reasons options from specific loan product have {int} options, with the following data:")
public void specificLoanProductChargeOffReasonOptionsCheck(final String loanProductName, final int linesExpected, final DataTable table)
throws IOException {
final DefaultLoanProduct product = DefaultLoanProduct.valueOf(loanProductName);
final Long loanProductId = loanProductResolver.resolve(product);
final Response<GetLoanProductsProductIdResponse> loanProductDetails = loanProductsCustomApi
.retrieveLoanProductDetails(loanProductId, "true").execute();
ErrorHelper.checkSuccessfulApiCall(loanProductDetails);
assertNotNull(loanProductDetails.body());
final List<GetLoanProductsChargeOffReasonOptions> chargeOffReasonOptions = loanProductDetails.body().getChargeOffReasonOptions();
assertNotNull(chargeOffReasonOptions);
final List<List<String>> data = table.asLists();
final int linesActual = chargeOffReasonOptions.size();
data.stream().skip(1) // skip headers
.forEach(expectedValues -> {
final List<List<String>> actualValuesList = chargeOffReasonOptions.stream()
.map(chargeOffReason -> fetchValuesOfLoanChargeOffReasonOptions(data.get(0), chargeOffReason))
.collect(Collectors.toList());
final boolean containsExpectedValues = actualValuesList.stream()
.anyMatch(actualValues -> actualValues.equals(expectedValues));
assertThat(containsExpectedValues).as(ErrorMessageHelper
.wrongValueInLineInChargeOffReasonOptions(data.indexOf(expectedValues), actualValuesList, expectedValues))
.isTrue();
assertThat(linesActual).as(ErrorMessageHelper.wrongNumberOfLinesInChargeOffReasonOptions(linesActual, linesExpected))
.isEqualTo(linesExpected);
});
}
private void createCustomizedLoan(final List<String> loanData, final boolean withEmi) throws IOException { private void createCustomizedLoan(final List<String> loanData, final boolean withEmi) throws IOException {
final String loanProduct = loanData.get(0); final String loanProduct = loanData.get(0);
final String submitDate = loanData.get(1); final String submitDate = loanData.get(1);
@@ -2928,4 +2993,29 @@ public class LoanStepDef extends AbstractStepDef {
} }
return actualValues; return actualValues;
} }
@SuppressFBWarnings("SF_SWITCH_NO_DEFAULT")
private List<String> fetchValuesOfLoanChargeOffReasonOptions(final List<String> header,
final GetLoanProductsChargeOffReasonOptions chargeOffReasonOption) {
final List<String> actualValues = new ArrayList<>();
for (String headerName : header) {
switch (headerName) {
case "Charge-Off Reason Name" ->
actualValues.add(chargeOffReasonOption.getName() == null ? null : chargeOffReasonOption.getName());
case "Description" -> {
assertNotNull(chargeOffReasonOption.getDescription());
actualValues
.add(chargeOffReasonOption.getDescription().isEmpty() || chargeOffReasonOption.getDescription() == null ? null
: chargeOffReasonOption.getDescription());
}
case "Position" -> actualValues
.add(chargeOffReasonOption.getPosition() == null ? null : String.valueOf(chargeOffReasonOption.getPosition()));
case "Is Active" ->
actualValues.add(chargeOffReasonOption.getActive() == null ? null : String.valueOf(chargeOffReasonOption.getActive()));
case "Is Mandatory" -> actualValues
.add(chargeOffReasonOption.getMandatory() == null ? null : String.valueOf(chargeOffReasonOption.getMandatory()));
}
}
return actualValues;
}
} }
@@ -181,3 +181,21 @@ Feature: LoanProduct
Then Loan has 500 outstanding amount Then Loan has 500 outstanding amount
When Refund undo happens on "1 July 2022" When Refund undo happens on "1 July 2022"
Then Loan has 1000 outstanding amount Then Loan has 1000 outstanding amount
Scenario: As a user I would like to verify Charge-Off reasons options in loan product template response
When Admin sets the business date to "12 December 2021"
When Admin creates a client with random data
And Admin successfully creates a new customised Loan submitted on date: "12 December 2021", with Principal: "1000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
Then Loan Product Charge-Off reasons options from loan product template have 2 options, with the following data:
| Charge-Off Reason Name | Description | Position | Is Active | Is Mandatory |
| debit_card | | 0 | true | false |
| credit_card | | 1 | true | false |
Scenario: As a user I would like to verify Charge-Off reasons options in specific loan product response
When Admin sets the business date to "12 December 2021"
When Admin creates a client with random data
And Admin successfully creates a new customised Loan submitted on date: "12 December 2021", with Principal: "1000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
Then Loan Product "LP1" Charge-Off reasons options from specific loan product have 2 options, with the following data:
| Charge-Off Reason Name | Description | Position | Is Active | Is Mandatory |
| debit_card | | 0 | true | false |
| credit_card | | 1 | true | false |
@@ -1016,6 +1016,24 @@ final class LoanProductsApiResourceSwagger {
public String description; public String description;
} }
static final class GetLoanProductsChargeOffReasonOptions {
private GetLoanProductsChargeOffReasonOptions() {}
@Schema(example = "2")
public Long id;
@Schema(example = "debit_card")
public String name;
@Schema(example = "2")
public Integer position;
@Schema(example = "Charge-Off reason description")
public String description;
@Schema(example = "true")
public Boolean active;
@Schema(example = "false")
public Boolean mandatory;
}
@Schema(example = "false") @Schema(example = "false")
public Boolean includeInBorrowerCycle; public Boolean includeInBorrowerCycle;
@Schema(example = "false") @Schema(example = "false")
@@ -1068,6 +1086,7 @@ final class LoanProductsApiResourceSwagger {
public List<StringEnumOptionData> supportedInterestRefundTypes; public List<StringEnumOptionData> supportedInterestRefundTypes;
public List<StringEnumOptionData> supportedInterestRefundTypesOptions; public List<StringEnumOptionData> supportedInterestRefundTypesOptions;
public List<GetLoanProductsChargeOffReasonOptions> chargeOffReasonOptions;
} }
@Schema(description = "GetLoanProductsProductIdResponse") @Schema(description = "GetLoanProductsProductIdResponse")
@@ -1342,6 +1361,7 @@ final class LoanProductsApiResourceSwagger {
@Schema(example = "false") @Schema(example = "false")
public Boolean enableAccrualActivityPosting; public Boolean enableAccrualActivityPosting;
public List<StringEnumOptionData> supportedInterestRefundTypes; public List<StringEnumOptionData> supportedInterestRefundTypes;
public List<GetLoanProductsTemplateResponse.GetLoanProductsChargeOffReasonOptions> chargeOffReasonOptions;
} }
@Schema(description = "PutLoanProductsProductIdRequest") @Schema(description = "PutLoanProductsProductIdRequest")
@@ -32,6 +32,7 @@ import org.apache.fineract.accounting.common.AccountingRuleType;
import org.apache.fineract.accounting.glaccount.data.GLAccountData; import org.apache.fineract.accounting.glaccount.data.GLAccountData;
import org.apache.fineract.accounting.producttoaccountmapping.data.ChargeToGLAccountMapper; import org.apache.fineract.accounting.producttoaccountmapping.data.ChargeToGLAccountMapper;
import org.apache.fineract.accounting.producttoaccountmapping.data.PaymentTypeToGLAccountMapper; import org.apache.fineract.accounting.producttoaccountmapping.data.PaymentTypeToGLAccountMapper;
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
import org.apache.fineract.infrastructure.core.data.EnumOptionData; import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.infrastructure.core.data.StringEnumOptionData; import org.apache.fineract.infrastructure.core.data.StringEnumOptionData;
import org.apache.fineract.organisation.monetary.data.CurrencyData; import org.apache.fineract.organisation.monetary.data.CurrencyData;
@@ -212,6 +213,8 @@ public class LoanProductData implements Serializable {
private final boolean isEqualAmortization; private final boolean isEqualAmortization;
private final BigDecimal fixedPrincipalPercentagePerInstallment; private final BigDecimal fixedPrincipalPercentagePerInstallment;
private final List<CodeValueData> chargeOffReasonOptions;
// Delinquency Buckets // Delinquency Buckets
private final Collection<DelinquencyBucketData> delinquencyBucketOptions; private final Collection<DelinquencyBucketData> delinquencyBucketOptions;
private final DelinquencyBucketData delinquencyBucket; private final DelinquencyBucketData delinquencyBucket;
@@ -913,6 +916,7 @@ public class LoanProductData implements Serializable {
this.enableAccrualActivityPosting = enableAccrualActivityPosting; this.enableAccrualActivityPosting = enableAccrualActivityPosting;
this.supportedInterestRefundTypes = supportedInterestRefundTypes; this.supportedInterestRefundTypes = supportedInterestRefundTypes;
this.supportedInterestRefundTypesOptions = null; this.supportedInterestRefundTypesOptions = null;
this.chargeOffReasonOptions = null;
} }
public LoanProductData(final LoanProductData productData, final Collection<ChargeData> chargeOptions, public LoanProductData(final LoanProductData productData, final Collection<ChargeData> chargeOptions,
@@ -935,7 +939,7 @@ public class LoanProductData implements Serializable {
final List<EnumOptionData> advancedPaymentAllocationTypes, final List<EnumOptionData> loanScheduleTypeOptions, final List<EnumOptionData> advancedPaymentAllocationTypes, final List<EnumOptionData> loanScheduleTypeOptions,
final List<EnumOptionData> loanScheduleProcessingTypeOptions, final List<EnumOptionData> creditAllocationTransactionTypes, final List<EnumOptionData> loanScheduleProcessingTypeOptions, final List<EnumOptionData> creditAllocationTransactionTypes,
final List<EnumOptionData> creditAllocationAllocationTypes, final List<EnumOptionData> creditAllocationAllocationTypes,
final List<StringEnumOptionData> supportedInterestRefundTypesOptions) { final List<StringEnumOptionData> supportedInterestRefundTypesOptions, final List<CodeValueData> chargeOffReasonOptions) {
this.id = productData.id; this.id = productData.id;
this.name = productData.name; this.name = productData.name;
@@ -1092,6 +1096,7 @@ public class LoanProductData implements Serializable {
this.enableAccrualActivityPosting = productData.enableAccrualActivityPosting; this.enableAccrualActivityPosting = productData.enableAccrualActivityPosting;
this.supportedInterestRefundTypesOptions = supportedInterestRefundTypesOptions; this.supportedInterestRefundTypesOptions = supportedInterestRefundTypesOptions;
this.supportedInterestRefundTypes = productData.supportedInterestRefundTypes; this.supportedInterestRefundTypes = productData.supportedInterestRefundTypes;
this.chargeOffReasonOptions = chargeOffReasonOptions;
} }
private Collection<ChargeData> nullIfEmpty(final Collection<ChargeData> charges) { private Collection<ChargeData> nullIfEmpty(final Collection<ChargeData> charges) {
@@ -300,7 +300,7 @@ public class BulkImportWorkbookPopulatorServiceImpl implements BulkImportWorkboo
private List<CodeValueData> fetchCodeValuesByCodeName(String codeName) { private List<CodeValueData> fetchCodeValuesByCodeName(String codeName) {
List<CodeValueData> codeValues = null; List<CodeValueData> codeValues = null;
if (codeName != null) { if (codeName != null) {
codeValues = (List<CodeValueData>) codeValueReadPlatformService.retrieveCodeValuesByCode(codeName); codeValues = codeValueReadPlatformService.retrieveCodeValuesByCode(codeName);
} else { } else {
throw new NullPointerException(); throw new NullPointerException();
} }
@@ -21,6 +21,7 @@ package org.apache.fineract.infrastructure.codes.service;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import org.apache.fineract.infrastructure.codes.data.CodeValueData; import org.apache.fineract.infrastructure.codes.data.CodeValueData;
import org.apache.fineract.infrastructure.codes.exception.CodeValueNotFoundException; import org.apache.fineract.infrastructure.codes.exception.CodeValueNotFoundException;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
@@ -66,7 +67,7 @@ public class CodeValueReadPlatformServiceImpl implements CodeValueReadPlatformSe
@Override @Override
@Cacheable(value = "code_values", key = "T(org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil).getTenant().getTenantIdentifier().concat(#code+'cv')") @Cacheable(value = "code_values", key = "T(org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil).getTenant().getTenantIdentifier().concat(#code+'cv')")
public Collection<CodeValueData> retrieveCodeValuesByCode(final String code) { public List<CodeValueData> retrieveCodeValuesByCode(final String code) {
this.context.authenticatedUser(); this.context.authenticatedUser();
@@ -54,6 +54,8 @@ import org.apache.fineract.accounting.producttoaccountmapping.service.ProductToG
import org.apache.fineract.commands.domain.CommandWrapper; import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder; import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService; import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService;
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService; import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.apache.fineract.infrastructure.core.api.ApiParameterHelper; import org.apache.fineract.infrastructure.core.api.ApiParameterHelper;
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper; import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
@@ -150,6 +152,7 @@ public class LoanProductsApiResource {
private final RateReadService rateReadService; private final RateReadService rateReadService;
private final ConfigurationDomainService configurationDomainService; private final ConfigurationDomainService configurationDomainService;
private final DelinquencyReadPlatformService delinquencyReadPlatformService; private final DelinquencyReadPlatformService delinquencyReadPlatformService;
private final CodeValueReadPlatformService codeValueReadPlatformService;
@POST @POST
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@@ -425,6 +428,8 @@ public class LoanProductsApiResource {
final List<EnumOptionData> creditAllocationAllocationTypes = AllocationType.getValuesAsEnumOptionDataList(); final List<EnumOptionData> creditAllocationAllocationTypes = AllocationType.getValuesAsEnumOptionDataList();
final List<StringEnumOptionData> supportedInterestRefundTypesOptions = LoanSupportedInterestRefundTypes final List<StringEnumOptionData> supportedInterestRefundTypesOptions = LoanSupportedInterestRefundTypes
.getValuesAsStringEnumOptionDataList(); .getValuesAsStringEnumOptionDataList();
final List<CodeValueData> chargeOffReasonOptions = codeValueReadPlatformService
.retrieveCodeValuesByCode(LoanApiConstants.CHARGE_OFF_REASONS);
return new LoanProductData(productData, chargeOptions, penaltyOptions, paymentTypeOptions, currencyOptions, amortizationTypeOptions, return new LoanProductData(productData, chargeOptions, penaltyOptions, paymentTypeOptions, currencyOptions, amortizationTypeOptions,
interestTypeOptions, interestCalculationPeriodTypeOptions, repaymentFrequencyTypeOptions, interestRateFrequencyTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, repaymentFrequencyTypeOptions, interestRateFrequencyTypeOptions,
@@ -436,7 +441,7 @@ public class LoanProductsApiResource {
advancedPaymentAllocationTransactionTypes, advancedPaymentAllocationFutureInstallmentAllocationRules, advancedPaymentAllocationTransactionTypes, advancedPaymentAllocationFutureInstallmentAllocationRules,
advancedPaymentAllocationTypes, LoanScheduleType.getValuesAsEnumOptionDataList(), advancedPaymentAllocationTypes, LoanScheduleType.getValuesAsEnumOptionDataList(),
LoanScheduleProcessingType.getValuesAsEnumOptionDataList(), creditAllocationTransactionTypes, LoanScheduleProcessingType.getValuesAsEnumOptionDataList(), creditAllocationTransactionTypes,
creditAllocationAllocationTypes, supportedInterestRefundTypesOptions); creditAllocationAllocationTypes, supportedInterestRefundTypesOptions, chargeOffReasonOptions);
} }
} }