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
The following commit(s) were added to refs/heads/develop by this push:
new e1d043bb2 FINERACT-1806: Advanced accounting - Charge-off reason
e1d043bb2 is described below
commit e1d043bb2d3422e3ade71db169293a04100c3b0c
Author: Adam Saghy <[email protected]>
AuthorDate: Tue Jan 7 16:46:59 2025 +0100
FINERACT-1806: Advanced accounting - Charge-off reason
---
.../ProductToGLAccountMappingRepository.java | 2 +-
.../portfolio/loanaccount/domain/Loan.java | 16 +--
.../accounting/journalentry/data/LoanDTO.java | 2 +-
.../service/AccountingProcessorHelper.java | 4 +-
.../AccrualBasedAccountingProcessorForLoan.java | 2 +-
.../codes/api/CodeValuesApiResourceSwagger.java | 2 +
.../CreateJournalEntriesForChargeOffLoanTest.java | 2 +-
.../integrationtests/BaseLoanIntegrationTest.java | 1 +
.../LoanChargeOffAccountingTest.java | 129 +++++++++++++++++++++
.../integrationtests/common/system/CodeHelper.java | 17 ++-
10 files changed, 159 insertions(+), 18 deletions(-)
diff --git
a/fineract-accounting/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/domain/ProductToGLAccountMappingRepository.java
b/fineract-accounting/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/domain/ProductToGLAccountMappingRepository.java
index 9a5436e6c..4f05f8a43 100644
---
a/fineract-accounting/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/domain/ProductToGLAccountMappingRepository.java
+++
b/fineract-accounting/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/domain/ProductToGLAccountMappingRepository.java
@@ -67,7 +67,7 @@ public interface ProductToGLAccountMappingRepository
@Param("productType") int productType);
@Query("select mapping from ProductToGLAccountMapping mapping where
mapping.chargeOffReason.id =:chargeOffReasonId")
- ProductToGLAccountMapping
findChargeOffReasonMappingById(@Param("chargeOffReasonId") Integer
chargeOffReasonId);
+ ProductToGLAccountMapping
findChargeOffReasonMappingById(@Param("chargeOffReasonId") Long
chargeOffReasonId);
@Query("select mapping from ProductToGLAccountMapping mapping where
mapping.productId =:productId AND mapping.productType =:productType AND
mapping.charge IS NULL AND mapping.paymentType IS NULL AND
mapping.chargeOffReason IS NULL")
List<ProductToGLAccountMapping> findAllRegularMappings(@Param("productId")
Long productId, @Param("productType") Integer productType);
diff --git
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index c6524c9d9..e50e6822e 100644
---
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -2190,13 +2190,9 @@ public class Loan extends
AbstractAuditableWithUTCDateTimeCustom<Long> {
boolean isBeforeChargeOffDate) {
final Map<String, Object> accountingBridgeDataChargeOff = new
LinkedHashMap<>(
getAccountingBridgeDataGenericAttributes(currencyCode,
isAccountTransfer));
- if (isBeforeChargeOffDate) {
- accountingBridgeDataChargeOff.put("isChargeOff", false);
- accountingBridgeDataChargeOff.put("isFraud", isFraud());
- } else {
- accountingBridgeDataChargeOff.put("isChargeOff", isChargedOff());
- accountingBridgeDataChargeOff.put("isFraud", isFraud());
- }
+ accountingBridgeDataChargeOff.put("isChargeOff",
!isBeforeChargeOffDate && isChargedOff());
+ accountingBridgeDataChargeOff.put("isFraud", isFraud());
+ accountingBridgeDataChargeOff.put("chargeOffReasonCodeValue",
fetchChargeOffReasonId());
return accountingBridgeDataChargeOff;
}
@@ -2274,6 +2270,8 @@ public class Loan extends
AbstractAuditableWithUTCDateTimeCustom<Long> {
accountingBridgeData.put("periodicAccrualBasedAccountingEnabled",
isPeriodicAccrualAccountingEnabledOnLoanProduct());
accountingBridgeData.put("isAccountTransfer", isAccountTransfer);
accountingBridgeData.put("isChargeOff", isChargedOff());
+ accountingBridgeData.put("chargeOffReasonCodeValue",
fetchChargeOffReasonId());
+
accountingBridgeData.put("isFraud", isFraud());
final List<Map<String, Object>> newLoanTransactions = new
ArrayList<>();
@@ -2290,6 +2288,10 @@ public class Loan extends
AbstractAuditableWithUTCDateTimeCustom<Long> {
return accountingBridgeData;
}
+ private Long fetchChargeOffReasonId() {
+ return isChargedOff() && getChargeOffReason() != null ?
getChargeOffReason().getId() : null;
+ }
+
public Money getReceivableInterest(final LocalDate tillDate) {
Money receivableInterest = Money.zero(getCurrency());
for (final LoanTransaction transaction : this.loanTransactions) {
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/LoanDTO.java
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/LoanDTO.java
index bbdf9f3c7..8b7fd8933 100755
---
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/LoanDTO.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/LoanDTO.java
@@ -45,5 +45,5 @@ public class LoanDTO {
private boolean markedAsChargeOff;
@Setter
private boolean markedAsFraud;
- private Integer chargeOffReasonCodeValue;
+ private Long chargeOffReasonCodeValue;
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
index 5e32eb780..49098705f 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
@@ -112,7 +112,7 @@ public class AccountingProcessorHelper {
boolean isAccountTransfer = (Boolean)
accountingBridgeData.get("isAccountTransfer");
boolean isLoanMarkedAsChargeOff = (Boolean)
accountingBridgeData.get("isChargeOff");
boolean isLoanMarkedAsFraud = (Boolean)
accountingBridgeData.get("isFraud");
- final Integer chargeOffReasonCodeValue = (Integer)
accountingBridgeData.get("chargeOffReasonCodeValue");
+ final Long chargeOffReasonCodeValue = (Long)
accountingBridgeData.get("chargeOffReasonCodeValue");
@SuppressWarnings("unchecked")
final List<Map<String, Object>> newTransactionsMap = (List<Map<String,
Object>>) accountingBridgeData.get("newLoanTransactions");
@@ -177,7 +177,7 @@ public class AccountingProcessorHelper {
chargeOffReasonCodeValue);
}
- public ProductToGLAccountMapping getChargeOffMappingByCodeValue(Integer
chargeOffReasonCodeValue) {
+ public ProductToGLAccountMapping getChargeOffMappingByCodeValue(Long
chargeOffReasonCodeValue) {
return
accountMappingRepository.findChargeOffReasonMappingById(chargeOffReasonCodeValue);
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
index 773fcadf1..17c437874 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
@@ -230,7 +230,7 @@ public class AccrualBasedAccountingProcessorForLoan
implements AccountingProcess
GLAccountBalanceHolder glAccountBalanceHolder = new
GLAccountBalanceHolder();
// need to fetch if there are account mappings (always one)
- Integer chargeOffReasonCodeValue =
loanDTO.getChargeOffReasonCodeValue();
+ Long chargeOffReasonCodeValue = loanDTO.getChargeOffReasonCodeValue();
ProductToGLAccountMapping mapping = chargeOffReasonCodeValue != null
?
helper.getChargeOffMappingByCodeValue(chargeOffReasonCodeValue)
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/api/CodeValuesApiResourceSwagger.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/api/CodeValuesApiResourceSwagger.java
index 98d98dad8..2407ec3ba 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/api/CodeValuesApiResourceSwagger.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/api/CodeValuesApiResourceSwagger.java
@@ -72,6 +72,8 @@ final class CodeValuesApiResourceSwagger {
@Schema(example = "4")
public Long resourceId;
+ @Schema(example = "4")
+ public Long subResourceId;
}
@Schema(description = "PutCodeValuesDataRequest")
diff --git
a/fineract-provider/src/test/java/org/apache/fineract/accounting/journalentry/CreateJournalEntriesForChargeOffLoanTest.java
b/fineract-provider/src/test/java/org/apache/fineract/accounting/journalentry/CreateJournalEntriesForChargeOffLoanTest.java
index 07a183f51..9f7be1503 100644
---
a/fineract-provider/src/test/java/org/apache/fineract/accounting/journalentry/CreateJournalEntriesForChargeOffLoanTest.java
+++
b/fineract-provider/src/test/java/org/apache/fineract/accounting/journalentry/CreateJournalEntriesForChargeOffLoanTest.java
@@ -48,7 +48,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class CreateJournalEntriesForChargeOffLoanTest {
- private static final Integer chargeOffReasons = 15;
+ private static final Long chargeOffReasons = 15L;
@Mock
private AccountingProcessorHelper helper;
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
index b164f88a7..845c98a97 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
@@ -159,6 +159,7 @@ public abstract class BaseLoanIntegrationTest {
protected BusinessDateHelper businessDateHelper = new BusinessDateHelper();
protected DateTimeFormatter dateTimeFormatter =
DateTimeFormatter.ofPattern(DATETIME_PATTERN);
protected GlobalConfigurationHelper globalConfigurationHelper = new
GlobalConfigurationHelper();
+ protected final CodeHelper codeHelper = new CodeHelper();
protected static void validateRepaymentPeriod(GetLoansLoanIdResponse
loanDetails, Integer index, LocalDate dueDate, double principalDue,
double principalPaid, double principalOutstanding, double
paidInAdvance, double paidLate) {
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargeOffAccountingTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargeOffAccountingTest.java
index 78c0bea50..4b458b0bc 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargeOffAccountingTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargeOffAccountingTest.java
@@ -26,12 +26,21 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
+import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
+import java.util.Collections;
import java.util.List;
import java.util.UUID;
+import org.apache.fineract.client.models.AllowAttributeOverrides;
+import org.apache.fineract.client.models.GetCodesResponse;
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
+import
org.apache.fineract.client.models.PostChargeOffReasonToExpenseAccountMappings;
+import org.apache.fineract.client.models.PostCodeValueDataResponse;
+import org.apache.fineract.client.models.PostCodeValuesDataRequest;
+import org.apache.fineract.client.models.PostLoanProductsRequest;
+import org.apache.fineract.client.models.PostLoanProductsResponse;
import org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdRequest;
import
org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdResponse;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
@@ -54,6 +63,7 @@ import
org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
import org.apache.fineract.integrationtests.common.system.CodeHelper;
import org.apache.fineract.integrationtests.inlinecob.InlineLoanCOBHelper;
+import
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -789,6 +799,125 @@ public class LoanChargeOffAccountingTest extends
BaseLoanIntegrationTest {
}
}
+ @Test
+ public void advancedAccountingForChargeOff() {
+ runAt("02 January 2023", () -> {
+ final Account chargeOffDelinquentExpenseAccount = accountHelper
+
.createExpenseAccount("delinquent_expense_for_charge_off_reason");
+ GetCodesResponse chargeOffReasonCode = fetchChargeOffReasonCode();
+ PostCodeValueDataResponse chargeOffReason =
codeHelper.createCodeValue(chargeOffReasonCode.getId(),
+ new
PostCodeValuesDataRequest().name(Utils.uniqueRandomStringGenerator("DELINQUENT_",
6)).isActive(true).position(10));
+ Long clientId =
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+ PostLoanProductsResponse productsResponse =
createLoanProductWithAdvancedChargeOffAccounting(chargeOffReason,
+ chargeOffDelinquentExpenseAccount);
+ // Apply and Approve Loan
+ Long loanId = applyAndApproveLoan(clientId,
productsResponse.getResourceId(), "01 January 2023", 1000.0, 1);
+ // Disburse Loan
+ disburseLoan(loanId, BigDecimal.valueOf(1000.00), "01 January
2023");
+
+ PostLoansLoanIdTransactionsResponse chargeOffTransaction =
this.loanTransactionHelper.chargeOffLoan(loanId,
+ new
PostLoansLoanIdTransactionsRequest().transactionDate("02 January
2023").locale("en").dateFormat("dd MMMM yyyy")
+
.chargeOffReasonId(chargeOffReason.getSubResourceId()));
+ // verify journal entries
+ verifyTRJournalEntries(chargeOffTransaction.getResourceId(),
journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
+ journalEntry(1000.0, chargeOffDelinquentExpenseAccount,
"DEBIT"));
+ });
+ }
+
+ private PostLoanProductsResponse
createLoanProductWithAdvancedChargeOffAccounting(PostCodeValueDataResponse
chargeOffReason,
+ Account chargeOffDelinquentExpenseAccount) {
+ return this.loanTransactionHelper.createLoanProduct(new
PostLoanProductsRequest()
+ .name(Utils.uniqueRandomStringGenerator("LOAN_PRODUCT_", 6))//
+ .shortName(Utils.uniqueRandomStringGenerator("", 4))//
+ .description("Loan Product Description")//
+ .includeInBorrowerCycle(false)//
+ .currencyCode("USD")//
+ .digitsAfterDecimal(2)//
+ .inMultiplesOf(0)//
+ .installmentAmountInMultiplesOf(1)//
+ .useBorrowerCycle(false)//
+ .minPrincipal(100.0)//
+ .principal(1000.0)//
+ .maxPrincipal(100000.0)//
+ .minNumberOfRepayments(1)//
+ .numberOfRepayments(1)//
+ .maxNumberOfRepayments(30)//
+ .isLinkedToFloatingInterestRates(false)//
+ .minInterestRatePerPeriod((double) 0)//
+ .interestRatePerPeriod(0.0)//
+ .maxInterestRatePerPeriod((double) 100)//
+ .interestRateFrequencyType(2)//
+ .repaymentEvery(30)//
+ .repaymentFrequencyType(0L)//
+ .amortizationType(1)//
+ .interestType(0)//
+ .isEqualAmortization(false)//
+ .interestCalculationPeriodType(1)//
+ .transactionProcessingStrategyCode(
+
LoanProductTestBuilder.DUE_PENALTY_FEE_INTEREST_PRINCIPAL_IN_ADVANCE_PRINCIPAL_PENALTY_FEE_INTEREST_STRATEGY)//
+ .loanScheduleType(LoanScheduleType.CUMULATIVE.toString()) //
+ .daysInYearType(1)//
+ .daysInMonthType(1)//
+ .canDefineInstallmentAmount(true)//
+ .graceOnArrearsAgeing(3)//
+ .overdueDaysForNPA(179)//
+ .accountMovesOutOfNPAOnlyOnArrearsCompletion(false)//
+ .principalThresholdForLastInstallment(50)//
+ .allowVariableInstallments(false)//
+ .canUseForTopup(false)//
+ .isInterestRecalculationEnabled(false)//
+ .holdGuaranteeFunds(false)//
+ .multiDisburseLoan(true)//
+ .allowAttributeOverrides(new AllowAttributeOverrides()//
+ .amortizationType(true)//
+ .interestType(true)//
+ .transactionProcessingStrategyCode(true)//
+ .interestCalculationPeriodType(true)//
+ .inArrearsTolerance(true)//
+ .repaymentEvery(true)//
+ .graceOnPrincipalAndInterestPayment(true)//
+ .graceOnArrearsAgeing(true))//
+ .allowPartialPeriodInterestCalcualtion(true)//
+ .maxTrancheCount(10)//
+ .outstandingLoanBalance(10000.0)//
+ .charges(Collections.emptyList())//
+ .accountingRule(3)//
+ .fundSourceAccountId(fundSource.getAccountID().longValue())//
+
.loanPortfolioAccountId(loansReceivableAccount.getAccountID().longValue())//
+
.transfersInSuspenseAccountId(suspenseAccount.getAccountID().longValue())//
+
.interestOnLoanAccountId(interestIncomeAccount.getAccountID().longValue())//
+
.incomeFromFeeAccountId(feeIncomeAccount.getAccountID().longValue())//
+
.incomeFromPenaltyAccountId(penaltyIncomeAccount.getAccountID().longValue())//
+
.incomeFromRecoveryAccountId(recoveriesAccount.getAccountID().longValue())//
+
.writeOffAccountId(writtenOffAccount.getAccountID().longValue())//
+
.overpaymentLiabilityAccountId(overpaymentAccount.getAccountID().longValue())//
+
.receivableInterestAccountId(interestReceivableAccount.getAccountID().longValue())//
+
.receivableFeeAccountId(feeReceivableAccount.getAccountID().longValue())//
+
.receivablePenaltyAccountId(penaltyReceivableAccount.getAccountID().longValue())//
+
.goodwillCreditAccountId(goodwillExpenseAccount.getAccountID().longValue())//
+
.incomeFromGoodwillCreditInterestAccountId(interestIncomeChargeOffAccount.getAccountID().longValue())//
+
.incomeFromGoodwillCreditFeesAccountId(feeChargeOffAccount.getAccountID().longValue())//
+
.incomeFromGoodwillCreditPenaltyAccountId(feeChargeOffAccount.getAccountID().longValue())//
+
.incomeFromChargeOffInterestAccountId(interestIncomeChargeOffAccount.getAccountID().longValue())//
+
.incomeFromChargeOffFeesAccountId(feeChargeOffAccount.getAccountID().longValue())//
+
.incomeFromChargeOffPenaltyAccountId(penaltyChargeOffAccount.getAccountID().longValue())//
+
.chargeOffExpenseAccountId(chargeOffExpenseAccount.getAccountID().longValue())//
+
.chargeOffFraudExpenseAccountId(chargeOffFraudExpenseAccount.getAccountID().longValue())//
+ .addChargeOffReasonToExpenseAccountMappingsItem(
+ new
PostChargeOffReasonToExpenseAccountMappings().chargeOffReasonCodeValueId(chargeOffReason.getSubResourceId())
+
.expenseAccountId(chargeOffDelinquentExpenseAccount.getAccountID().longValue()))
+ .dateFormat(DATETIME_PATTERN)//
+ .locale("en_GB")//
+ .disallowExpectedDisbursements(true)//
+ .allowApprovedDisbursedAmountsOverApplied(true)//
+ .overAppliedCalculationType("percentage")//
+ .overAppliedNumber(50));
+ }
+
+ private GetCodesResponse fetchChargeOffReasonCode() {
+ return codeHelper.retrieveCodes().stream().filter(c ->
"ChargeOffReasons".equals(c.getName())).findFirst().orElseThrow();
+ }
+
private Integer createLoanAccount(final Integer clientID, final Integer
loanProductID, final String externalId) {
String loanApplicationJSON = new
LoanApplicationTestBuilder().withPrincipal("1000").withLoanTermFrequency("1")
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/system/CodeHelper.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/system/CodeHelper.java
index 2f0cce363..1ba9e1c5b 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/system/CodeHelper.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/system/CodeHelper.java
@@ -27,19 +27,19 @@ import io.restassured.specification.ResponseSpecification;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import org.apache.fineract.client.models.GetCodesResponse;
+import org.apache.fineract.client.models.PostCodeValueDataResponse;
+import org.apache.fineract.client.models.PostCodeValuesDataRequest;
+import org.apache.fineract.integrationtests.client.IntegrationTest;
import org.apache.fineract.integrationtests.common.Utils;
-public final class CodeHelper {
+public final class CodeHelper extends IntegrationTest {
private static final String COUNTRY_CODE_NAME = "COUNTRY";
private static final String STATE_CODE_NAME = "STATE";
private static final String ADDRESS_TYPE_CODE_NAME = "ADDRESS_TYPE";
private static final String CHARGE_OFF_REASONS_CODE_NAME =
"ChargeOffReasons";
- private CodeHelper() {
-
- }
-
public static final String CODE_ID_ATTRIBUTE_NAME = "id";
public static final String RESPONSE_ID_ATTRIBUTE_NAME = "resourceId";
public static final String SUBRESPONSE_ID_ATTRIBUTE_NAME = "subResourceId";
@@ -280,4 +280,11 @@ public final class CodeHelper {
getTestCodeValueAsJSON(codeValueName, description, position),
jsonAttributeToGetback);
}
+ public PostCodeValueDataResponse createCodeValue(Long codeId,
PostCodeValuesDataRequest request) {
+ return ok(fineract().codeValues.createCodeValue(codeId, request));
+ }
+
+ public List<GetCodesResponse> retrieveCodes() {
+ return ok(fineract().codes.retrieveCodes());
+ }
}