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 0891adb267 FINERACT-2421: Rework code value handling in E2E
0891adb267 is described below

commit 0891adb267c762d1b396e7f83ac92a86244655b8
Author: Adam Saghy <[email protected]>
AuthorDate: Fri Jan 16 13:07:23 2026 +0100

    FINERACT-2421: Rework code value handling in E2E
---
 .../commands/service/CommandWrapperBuilder.java    |  26 +++++
 .../codes/domain/CodeValueRepository.java          |   3 +
 .../codes/service/CodeReadPlatformService.java     |   2 +-
 .../service/CodeValueReadPlatformService.java      |   4 +
 .../fineract/test/data/codevalue/CodeNames.java    |  58 ++++++++++
 .../test/data/codevalue/CodeValueResolver.java     |  16 ++-
 .../test/data/codevalue/DefaultCodeValue.java      |   5 +-
 .../fineract/test/stepdef/loan/LoanStepDef.java    |  49 +++------
 .../global/CodeGlobalInitializerStep.java          | 120 ++++++++++-----------
 .../global/LoanProductGlobalInitializerStep.java   |  10 +-
 .../resources/features/LoanBuyDownFees.feature     |  10 +-
 .../features/LoanCapitalizedIncome.feature         |  14 +--
 .../test/resources/features/LoanProduct.feature    |  20 ++--
 .../codes/api/CodeValuesApiResource.java           |  98 ++++++++++++++++-
 .../infrastructure/codes/api/CodesApiResource.java |   2 +-
 .../codes/service/CodeReadPlatformServiceImpl.java |   2 +-
 .../service/CodeValueReadPlatformServiceImpl.java  |  31 ++++--
 .../service/DatatableWriteServiceImpl.java         |   6 +-
 18 files changed, 328 insertions(+), 148 deletions(-)

diff --git 
a/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
 
b/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
index 9f3d7586d2..d2453dd9c5 100644
--- 
a/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
+++ 
b/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
@@ -1257,6 +1257,14 @@ public class CommandWrapperBuilder {
         return this;
     }
 
+    public CommandWrapperBuilder createCodeValue(final Long codeId, String 
codeName) {
+        this.actionName = "CREATE";
+        this.entityName = "CODEVALUE";
+        this.entityId = codeId;
+        this.href = "/codes/name/" + codeName + "/codevalues/template";
+        return this;
+    }
+
     public CommandWrapperBuilder updateCodeValue(final Long codeId, final Long 
codeValueId) {
         this.actionName = "UPDATE";
         this.entityName = "CODEVALUE";
@@ -1266,6 +1274,15 @@ public class CommandWrapperBuilder {
         return this;
     }
 
+    public CommandWrapperBuilder updateCodeValue(String codeName, Long codeId, 
Long codeValueId) {
+        this.actionName = "UPDATE";
+        this.entityName = "CODEVALUE";
+        this.entityId = codeId;
+        this.subentityId = codeValueId;
+        this.href = "/codes/name/" + codeName + "/codevalues/" + codeValueId;
+        return this;
+    }
+
     public CommandWrapperBuilder deleteCodeValue(final Long codeId, final Long 
codeValueId) {
         this.actionName = "DELETE";
         this.entityName = "CODEVALUE";
@@ -1275,6 +1292,15 @@ public class CommandWrapperBuilder {
         return this;
     }
 
+    public CommandWrapperBuilder deleteCodeValue(String codeName, Long codeId, 
Long codeValueId) {
+        this.actionName = "DELETE";
+        this.entityName = "CODEVALUE";
+        this.entityId = codeId;
+        this.subentityId = codeValueId;
+        this.href = "/codes/name/" + codeName + "/codevalues/" + codeValueId;
+        return this;
+    }
+
     public CommandWrapperBuilder createGLClosure() {
         this.actionName = "CREATE";
         this.entityName = "GLCLOSURE";
diff --git 
a/fineract-core/src/main/java/org/apache/fineract/infrastructure/codes/domain/CodeValueRepository.java
 
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/codes/domain/CodeValueRepository.java
index 60ba58e544..fbff80ae01 100644
--- 
a/fineract-core/src/main/java/org/apache/fineract/infrastructure/codes/domain/CodeValueRepository.java
+++ 
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/codes/domain/CodeValueRepository.java
@@ -18,6 +18,7 @@
  */
 package org.apache.fineract.infrastructure.codes.domain;
 
+import java.util.List;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 
@@ -26,4 +27,6 @@ public interface CodeValueRepository extends 
JpaRepository<CodeValue, Long>, Jpa
     CodeValue findByCodeNameAndId(String codeName, Long id);
 
     CodeValue findByCodeNameAndLabel(String codeName, String label);
+
+    List<CodeValue> findByCodeName(String codeName);
 }
diff --git 
a/fineract-core/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeReadPlatformService.java
 
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeReadPlatformService.java
index 67d10caead..b2c5340ff5 100644
--- 
a/fineract-core/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeReadPlatformService.java
+++ 
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeReadPlatformService.java
@@ -27,5 +27,5 @@ public interface CodeReadPlatformService {
 
     CodeData retrieveCode(Long codeId);
 
-    CodeData retriveCode(String codeName);
+    CodeData retrieveCode(String codeName);
 }
diff --git 
a/fineract-core/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeValueReadPlatformService.java
 
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeValueReadPlatformService.java
index f56a9ddc89..7243bfba38 100644
--- 
a/fineract-core/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeValueReadPlatformService.java
+++ 
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeValueReadPlatformService.java
@@ -46,4 +46,8 @@ public interface CodeValueReadPlatformService {
     Collection<CodeValueData> retrieveAllCodeValues(Long codeId);
 
     CodeValueData retrieveCodeValue(Long codeValueId);
+
+    List<CodeValueData> retrieveAllCodeValues(String codeName);
+
+    CodeValueData retrieveCodeValue(String codeName, Long codeValueId);
 }
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/codevalue/CodeNames.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/codevalue/CodeNames.java
new file mode 100644
index 0000000000..e10df2afac
--- /dev/null
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/codevalue/CodeNames.java
@@ -0,0 +1,58 @@
+/**
+ * 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.data.codevalue;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+@Getter
+@RequiredArgsConstructor
+public enum CodeNames {
+
+    FINANCIAL_INSTRUMENT("financial_instrument"), //
+    TRANSACTION_TYPE("transaction_type"), //
+    BANKRUPTCY_TAG("bankruptcy_tag"), //
+    PENDING_FRAUD_TAG("pending_fraud_tag"), //
+    PENDING_DECEASED_TAG("pending_deceased_tag"), //
+    HARDSHIP_TAG("hardship_tag"), //
+    ACTIVE_DUTY_TAG("active_duty_tag"), //
+    ADDRESS_TYPE("ADDRESS_TYPE"), //
+    COUNTRY("COUNTRY"), //
+    STATE("STATE"), //
+    CHARGE_OFF("ChargeOffReasons"), //
+    CUSTOMER_IDENTIFIER("Customer Identifier"), //
+    GENDER("Gender"), //
+    CLIENT_TYPE("ClientType"), //
+    CLIENT_CLASSIFICATION("ClientClassification"), //
+    FAMILY_MEMBER_RELATIONSHIP("RELATIONSHIP"), //
+    FAMILY_MEMBER_PROFESSION("PROFESSION"), //
+    FAMILY_MARITAL_STATUS("MARITAL STATUS"), //
+    CONSTITUTION("Constitution"), //
+    LOAN_RESCHEDULE_REASON("LoanRescheduleReason"), //
+    WRITE_OFF_REASON("WriteOffReasons"), //
+    
BUYDOWN_FEE_TRANSACTION_CLASSIFICATION("buydown_fee_transaction_classification"),
 //
+    
CAPITALIZED_INCOME_TRANSACTION_CLASSIFICATION("capitalized_income_transaction_classification");
 //
+
+    private final String value;
+
+    @Override
+    public String toString() {
+        return value;
+    }
+}
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/codevalue/CodeValueResolver.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/codevalue/CodeValueResolver.java
index 2875b14686..0c8409d5b5 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/codevalue/CodeValueResolver.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/codevalue/CodeValueResolver.java
@@ -36,14 +36,26 @@ public class CodeValueResolver {
 
     private final FineractFeignClient fineractClient;
 
-    @Cacheable(key = "#codeValue.getName()", value = "codeValuesByName")
+    @Cacheable(key = "#codeId + '-' + #codeValue", value = "codeValuesByName")
     public long resolve(Long codeId, CodeValue codeValue) {
         String codeValueName = codeValue.getName();
 
         log.debug("Resolving code value by code id and name [{}]", codeValue);
         List<GetCodeValuesDataResponse> codeValuesResponses = ok(() -> 
fineractClient.codeValues().retrieveAllCodeValues(codeId, Map.of()));
         GetCodeValuesDataResponse foundPtr = 
codeValuesResponses.stream().filter(ptr -> 
codeValueName.equals(ptr.getName())).findAny()
-                .orElseThrow(() -> new IllegalArgumentException("Payment type 
[%s] not found".formatted(codeValueName)));
+                .orElseThrow(
+                        () -> new IllegalArgumentException("Code Value [%s] 
not found for Code [%s]".formatted(codeValueName, codeId)));
+
+        return foundPtr.getId();
+    }
+
+    @Cacheable(key = "#codeName + '-' + #codeValue", value = 
"codeValuesByName")
+    public long resolve(String codeName, String codeValue) {
+        log.debug("Resolving code value by code id and name [{}]", codeValue);
+        List<GetCodeValuesDataResponse> codeValuesResponses = ok(
+                () -> 
fineractClient.codeValues().retrieveAllCodeValues1(codeName, Map.of()));
+        GetCodeValuesDataResponse foundPtr = 
codeValuesResponses.stream().filter(ptr -> 
codeValue.equals(ptr.getName())).findAny()
+                .orElseThrow(() -> new IllegalArgumentException("Code Value 
[%s] not found for Code [%s]".formatted(codeValue, codeName)));
 
         return foundPtr.getId();
     }
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/codevalue/DefaultCodeValue.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/codevalue/DefaultCodeValue.java
index 59d77da1eb..29cfe91fae 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/codevalue/DefaultCodeValue.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/codevalue/DefaultCodeValue.java
@@ -23,7 +23,10 @@ public enum DefaultCodeValue implements CodeValue {
     // Charge-off reason
     FRAUD("Fraud"), //
     DELINQUENT("Delinquent"), //
-    OTHER("Other"), BAD_DEBT("Bad Debt"), FORGIVEN("Forgiven"), TEST("Test"); 
//
+    OTHER("Other"), //
+    BAD_DEBT("Bad Debt"), //
+    FORGIVEN("Forgiven"), //
+    TEST("Test"); //
 
     private final String customName;
 
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java
index cf0bc2ac9d..f9302c6e5d 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java
@@ -79,7 +79,6 @@ import 
org.apache.fineract.client.models.CommandProcessingResult;
 import org.apache.fineract.client.models.DeleteLoansLoanIdResponse;
 import org.apache.fineract.client.models.DisbursementDetail;
 import org.apache.fineract.client.models.GetCodeValuesDataResponse;
-import org.apache.fineract.client.models.GetCodesResponse;
 import org.apache.fineract.client.models.GetLoanProductsChargeOffReasonOptions;
 import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
 import org.apache.fineract.client.models.GetLoanProductsResponse;
@@ -105,8 +104,6 @@ import 
org.apache.fineract.client.models.OldestCOBProcessedLoanDTO;
 import org.apache.fineract.client.models.PaymentAllocationOrder;
 import 
org.apache.fineract.client.models.PostAddAndDeleteDisbursementDetailRequest;
 import org.apache.fineract.client.models.PostClientsResponse;
-import org.apache.fineract.client.models.PostCodeValueDataResponse;
-import org.apache.fineract.client.models.PostCodeValuesDataRequest;
 import org.apache.fineract.client.models.PostLoansDisbursementData;
 import org.apache.fineract.client.models.PostLoansLoanIdRequest;
 import org.apache.fineract.client.models.PostLoansLoanIdResponse;
@@ -131,6 +128,7 @@ import org.apache.fineract.test.data.LoanTermFrequencyType;
 import org.apache.fineract.test.data.RepaymentFrequencyType;
 import org.apache.fineract.test.data.TransactionProcessingStrategyCode;
 import org.apache.fineract.test.data.TransactionType;
+import org.apache.fineract.test.data.codevalue.CodeNames;
 import org.apache.fineract.test.data.codevalue.CodeValue;
 import org.apache.fineract.test.data.codevalue.CodeValueResolver;
 import org.apache.fineract.test.data.codevalue.DefaultCodeValue;
@@ -4879,14 +4877,6 @@ public class LoanStepDef extends AbstractStepDef {
         testContext().set(TestContextKey.LOAN_CAPITALIZED_INCOME_RESPONSE, 
capitalizedIncomeResponse);
     }
 
-    @And("Admin adds capitalized income with {string} payment type to the loan 
on {string} with {string} EUR transaction amount and classification: 
scheduled_payment")
-    public void 
adminAddsCapitalizedIncomeToTheLoanOnWithEURTransactionAmountWithClassificationScheduledPayment(
-            final String transactionPaymentType, final String transactionDate, 
final String amount) {
-        final PostLoansLoanIdTransactionsResponse capitalizedIncomeResponse = 
addCapitalizedIncomeToTheLoanOnWithEURTransactionAmountWithClassificationScheduledPayment(
-                transactionPaymentType, transactionDate, amount);
-        testContext().set(TestContextKey.LOAN_CAPITALIZED_INCOME_RESPONSE, 
capitalizedIncomeResponse);
-    }
-
     @And("Admin adds capitalized income with {string} payment type to the loan 
on {string} with {string} EUR transaction amount and {string} classification")
     public void adminAddsCapitalizedIncomeWithClassification(final String 
transactionPaymentType, final String transactionDate,
             final String amount, final String classificationCodeName) {
@@ -4904,7 +4894,8 @@ public class LoanStepDef extends AbstractStepDef {
         final Long paymentTypeValue = paymentTypeResolver.resolve(paymentType);
 
         // Get classification code value
-        final Long classificationId = 
getClassificationCodeValueId(classificationCodeName);
+        final Long classificationId = 
getClassificationCodeValueId(CodeNames.CAPITALIZED_INCOME_TRANSACTION_CLASSIFICATION.getValue(),
+                classificationCodeName);
 
         final PostLoansLoanIdTransactionsRequest capitalizedIncomeRequest = 
LoanRequestFactory.defaultCapitalizedIncomeRequest()
                 
.transactionDate(transactionDate).transactionAmount(Double.valueOf(amount)).paymentTypeId(paymentTypeValue)
@@ -5373,24 +5364,16 @@ public class LoanStepDef extends AbstractStepDef {
         testContext().set(TestContextKey.LOAN_BUY_DOWN_FEE_RESPONSE, 
buyDownFeesIncomeResponse);
     }
 
-    @And("Admin adds buy down fee with {string} payment type to the loan on 
{string} with {string} EUR transaction amount and classification: 
pending_bankruptcy")
-    public void 
adminAddsBuyDownFeesToTheLoanOnWithEURTransactionAmountWithClassification(final 
String transactionPaymentType,
-            final String transactionDate, final String amount) {
-        final PostLoansLoanIdTransactionsResponse buyDownFeesIncomeResponse = 
addBuyDownFeeToTheLoanOnWithEURTransactionAmountWithClassification(
-                transactionPaymentType, transactionDate, amount);
-        testContext().set(TestContextKey.LOAN_BUY_DOWN_FEE_RESPONSE, 
buyDownFeesIncomeResponse);
-    }
-
     @When("Admin adds buy down fee with {string} payment type to the loan on 
{string} with {string} EUR transaction amount and {string} classification")
     public void adminAddsBuyDownFeeWithClassification(final String 
transactionPaymentType, final String transactionDate,
-            final String amount, final String classificationCodeName) {
+            final String amount, final String classificationCodeValueName) {
         final PostLoansLoanIdTransactionsResponse buyDownFeesIncomeResponse = 
addBuyDownFeeWithClassification(transactionPaymentType,
-                transactionDate, amount, classificationCodeName);
+                transactionDate, amount, classificationCodeValueName);
         testContext().set(TestContextKey.LOAN_BUY_DOWN_FEE_RESPONSE, 
buyDownFeesIncomeResponse);
     }
 
     public PostLoansLoanIdTransactionsResponse 
addBuyDownFeeWithClassification(final String transactionPaymentType,
-            final String transactionDate, final String amount, final String 
classificationCodeName) {
+            final String transactionDate, final String amount, final String 
classificationCodeValueName) {
         final PostLoansResponse loanResponse = 
testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
         final long loanId = loanResponse.getLoanId();
 
@@ -5398,7 +5381,8 @@ public class LoanStepDef extends AbstractStepDef {
         final Long paymentTypeValue = paymentTypeResolver.resolve(paymentType);
 
         // Get classification code value
-        final Long classificationId = 
getClassificationCodeValueId(classificationCodeName);
+        final Long classificationId = 
getClassificationCodeValueId(CodeNames.BUYDOWN_FEE_TRANSACTION_CLASSIFICATION.getValue(),
+                classificationCodeValueName);
 
         final PostLoansLoanIdTransactionsRequest buyDownFeeRequest = 
LoanRequestFactory.defaultBuyDownFeeIncomeRequest()
                 
.transactionDate(transactionDate).transactionAmount(Double.valueOf(amount)).paymentTypeId(paymentTypeValue)
@@ -5740,27 +5724,18 @@ public class LoanStepDef extends AbstractStepDef {
                 .isEqualTo(expectedClassification);
     }
 
-    private Long getClassificationCodeValueId(String classificationName) {
-        final GetCodesResponse code = 
codeHelper.retrieveCodeByName(classificationName);
-
+    private Long getClassificationCodeValueId(String codeName, String 
codeValueName) {
         // Check if code value already exists
-        List<GetCodeValuesDataResponse> existingCodeValues = 
fineractClient.codeValues().retrieveAllCodeValues(code.getId());
-        String codeValueName = classificationName + "_value";
-
+        List<GetCodeValuesDataResponse> existingCodeValues = 
fineractClient.codeValues().retrieveAllCodeValues1(codeName);
         // Try to find existing code value with the same name
         for (GetCodeValuesDataResponse codeValue : existingCodeValues) {
             if (codeValueName.equals(codeValue.getName())) {
-                log.info("Reusing existing code value: {}", codeValueName);
+                log.debug("Reusing existing code value: {}", codeValueName);
                 return codeValue.getId();
             }
         }
 
-        // If not found, create a new code value
-        PostCodeValuesDataRequest codeValueRequest = new 
PostCodeValuesDataRequest().name(codeValueName).isActive(true).position(1);
-
-        PostCodeValueDataResponse response = 
codeHelper.createCodeValue(code.getId(), codeValueRequest);
-
-        return response.getSubResourceId();
+        throw new IllegalStateException(String.format("Code [%s] with code 
value [%s] cannot be found", codeName, codeValueName));
     }
 
     @And("Loan Amortization Allocation Mapping for {string} transaction 
created on {string} contains the following data:")
diff --git 
a/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/initializer/global/CodeGlobalInitializerStep.java
 
b/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/initializer/global/CodeGlobalInitializerStep.java
index 983099fc24..24bb9b6994 100644
--- 
a/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/initializer/global/CodeGlobalInitializerStep.java
+++ 
b/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/initializer/global/CodeGlobalInitializerStep.java
@@ -30,6 +30,7 @@ import 
org.apache.fineract.client.feign.util.CallFailedRuntimeException;
 import org.apache.fineract.client.models.PostCodeValuesDataRequest;
 import org.apache.fineract.client.models.PostCodesRequest;
 import org.apache.fineract.client.models.PutCodeValuesDataRequest;
+import org.apache.fineract.test.data.codevalue.CodeNames;
 import org.springframework.core.Ordered;
 import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Component;
@@ -40,44 +41,26 @@ import org.springframework.stereotype.Component;
 @Order(Ordered.HIGHEST_PRECEDENCE)
 public class CodeGlobalInitializerStep implements 
FineractGlobalInitializerStep {
 
-    public static final String CODE_NAME_FINANCIAL_INSTRUMENT = 
"financial_instrument";
-    public static final String CODE_NAME_TRANSACTION_TYPE = "transaction_type";
-    public static final String CODE_NAME_BANKRUPTCY_TAG = "bankruptcy_tag";
-    public static final String CODE_NAME_PENDING_FRAUD_TAG = 
"pending_fraud_tag";
-    public static final String CODE_NAME_PENDING_DECEASED_TAG = 
"pending_deceased_tag";
-    public static final String CODE_NAME_HARDSHIP_TAG = "hardship_tag";
-    public static final String CODE_NAME_ACTIVE_DUTY_TAG = "active_duty_tag";
-    public static final Long CODE_VALUE_ADDRESS_TYPE_ID = 29L;
     public static final String CODE_VALUE_ADDRESS_TYPE_RESIDENTIAL = 
"Residential address";
     public static final String CODE_VALUE_ADDRESS_TYPE_OFFICE = "Office 
address";
-    public static final Long CODE_VALUE_COUNTRY_ID = 28L;
     public static final String CODE_VALUE_COUNTRY_GERMANY = "Germany";
-    public static final Long CODE_VALUE_STATE_ID = 27L;
     public static final String CODE_VALUE_STATE_BERLIN = "Berlin";
-    public static final Long CODE_VALUE_FINANCIAL_INSTRUMENT_ID = 39L;
     public static final String CODE_VALUE_FINANCIAL_INSTRUMENT_DEBIT = 
"debit_card";
     public static final String CODE_VALUE_FINANCIAL_INSTRUMENT_CREDIT = 
"credit_card";
-    public static final String CODE_VALUE_FINANCIAL_INSTRUMENT_FRAUD = "Fraud";
-    public static final String CODE_VALUE_FINANCIAL_INSTRUMENT_DELINQUENT = 
"Delinquent";
-    public static final String CODE_VALUE_FINANCIAL_INSTRUMENT_OTHER = "Other";
-    public static final Long CODE_VALUE_TRANSACTION_TYPE_ID = 40L;
+    public static final String CODE_VALUE_CHARGE_OFF_REASON_FRAUD = "Fraud";
+    public static final String CODE_VALUE_CHARGE_OFF_REASON_DELINQUENT = 
"Delinquent";
+    public static final String CODE_VALUE_CHARGE_OFF_REASON_OTHER = "Other";
     public static final String CODE_VALUE_TRANSACTION_TYPE_SCHEDULED_PAYMENT = 
"scheduled_payment";
-    public static final Long CODE_VALUE_BANKRUPTCY_TAG_ID = 41L;
     public static final String CODE_VALUE_BANKRUPTCY_TAG_PENDING = 
"pending_bankruptcy";
     public static final String CODE_VALUE_BANKRUPTCY_TAG_BANKRUPTCY = 
"bankruptcy";
-    public static final Long CODE_VALUE_PENDING_FRAUD_TAG_ID = 42L;
     public static final String CODE_VALUE_PENDING_FRAUD_TAG_PENDING = 
"pending_fraud";
     public static final String CODE_VALUE_PENDING_FRAUD_TAG_FRAUD = "fraud";
-    public static final Long CODE_VALUE_PENDING_DECEASED_TAG_ID = 43L;
     public static final String CODE_VALUE_PENDING_DECEASED_TAG_PENDING = 
"pending_deceased";
     public static final String CODE_VALUE_PENDING_DECEASED_TAG_DECEASED = 
"deceased";
-    public static final Long CODE_VALUE_HARDSHIP_TAG_ID = 44L;
     public static final String CODE_VALUE_HARDSHIP_TAG_ACTIVE = "active";
     public static final String CODE_VALUE_HARDSHIP_TAG_INACTIVE = "inactive";
-    public static final Long CODE_VALUE_ACTIVE_DUTY_TAG_ID = 45L;
     public static final String CODE_VALUE_ACTIVE_DUTY_TAG_ACTIVE = "active";
     public static final String CODE_VALUE_ACTIVE_DUTY_TAG_INACTIVE = 
"inactive";
-    public static final Long CODE_VALUE_CUSTOMER_IDENTIFIERS_ID = 1L;
     public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_1 = "Passport";
     public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_2 = "Id";
     public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_3 = "Drivers 
License";
@@ -86,37 +69,30 @@ public class CodeGlobalInitializerStep implements 
FineractGlobalInitializerStep
     public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_6 = "TIN";
     public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_7 = "ITIN";
     public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_8 = "EIN";
-    public static final Long CODE_VALUE_GENDER_ID = 4L;
     public static final String CODE_VALUE_GENDER_FEMALE = "Female";
     public static final String CODE_VALUE_GENDER_MALE = "Male";
-    public static final Long CODE_VALUE_CLIENT_TYPE_ID = 16L;
     public static final String CODE_VALUE_CLIENT_TYPE_CORPORATE = "Corporate";
     public static final String CODE_VALUE_CLIENT_TYPE_LEGAL = "Legal";
     public static final String CODE_VALUE_CLIENT_TYPE_NON_LEGAL = "Non-legal";
-    public static final Long CODE_VALUE_CLIENT_CLASSIFICATION_ID = 17L;
     public static final String CODE_VALUE_CLIENT_CLASSIFICATION_LAWYER = 
"Lawyer";
     public static final String CODE_VALUE_CLIENT_CLASSIFICATION_DIRECTOR = 
"Director";
     public static final String CODE_VALUE_CLIENT_CLASSIFICATION_NONE = "None";
-    public static final Long CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_ID = 31L;
     public static final String CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_SPOUSE = 
"Spouse";
     public static final String CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_FATHER = 
"Father";
     public static final String CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_MOTHER = 
"Mother";
     public static final String CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_CHILD = 
"Child";
-    public static final Long CODE_VALUE_FAMILY_MEMBER_PROFESSION_ID = 32L;
     public static final String CODE_VALUE_FAMILY_MEMBER_PROFESSION_EMPLOYEE = 
"Employee";
     public static final String 
CODE_VALUE_FAMILY_MEMBER_PROFESSION_SELF_EMPLOYED = "Self-Employed";
-    public static final Long CODE_VALUE_FAMILY_MARITAL_STATUS_ID = 30L;
     public static final String CODE_VALUE_FAMILY_MARITAL_STATUS_MARRIED = 
"Married";
     public static final String CODE_VALUE_FAMILY_MARITAL_STATUS_SINGLE = 
"Single";
     public static final String CODE_VALUE_FAMILY_MARITAL_STATUS_WIDOWED = 
"Widowed";
-    public static final Long CODE_VALUE_CONSTITUTION_ID = 24L;
     public static final String CODE_VALUE_CONSTITUTION_TEST = "Test";
-    public static final Long CODE_VALUE_RESCHEDULE_REASON_ID = 23L;
     public static final String CODE_VALUE_RESCHEDULE_REASON_TEST = "Test";
-    public static final Long CODE_VALUE_WRITE_OFF_REASON_ID = 26L;
     public static final String CODE_VALUE_WRITE_OFF_REASON_TEST_1 = "Bad Debt";
     public static final String CODE_VALUE_WRITE_OFF_REASON_TEST_2 = "Forgiven";
     public static final String CODE_VALUE_WRITE_OFF_REASON_TEST_3 = "Test";
+    public static final String BUYDOWN_FEE_TRANSACTION_CLASSIFICATION_VALUE = 
"buydown_fee_transaction_classification_value";
+    public static final String 
CAPITALIZED_INCOME_TRANSACTION_CLASSIFICATION_VALUE = 
"capitalized_income_transaction_classification_value";
 
     private final FineractFeignClient fineractClient;
 
@@ -131,61 +107,64 @@ public class CodeGlobalInitializerStep implements 
FineractGlobalInitializerStep
         List<String> addressNames = new ArrayList<>();
         addressNames.add(CODE_VALUE_ADDRESS_TYPE_RESIDENTIAL);
         addressNames.add(CODE_VALUE_ADDRESS_TYPE_OFFICE);
-        createCodeValues(CODE_VALUE_ADDRESS_TYPE_ID, addressNames);
+        createCodeValues(CodeNames.ADDRESS_TYPE.getValue(), addressNames);
 
         // Country
         List<String> countryNames = new ArrayList<>();
         countryNames.add(CODE_VALUE_COUNTRY_GERMANY);
-        createCodeValues(CODE_VALUE_COUNTRY_ID, countryNames);
+        createCodeValues(CodeNames.COUNTRY.getValue(), countryNames);
 
         // State
         List<String> stateNames = new ArrayList<>();
         stateNames.add(CODE_VALUE_STATE_BERLIN);
-        createCodeValues(CODE_VALUE_STATE_ID, stateNames);
+        createCodeValues(CodeNames.STATE.getValue(), stateNames);
 
         // financial instrument
         List<String> financialInstrumentNames = new ArrayList<>();
         financialInstrumentNames.add(CODE_VALUE_FINANCIAL_INSTRUMENT_DEBIT);
         financialInstrumentNames.add(CODE_VALUE_FINANCIAL_INSTRUMENT_CREDIT);
-        financialInstrumentNames.add(CODE_VALUE_FINANCIAL_INSTRUMENT_FRAUD);
-        
financialInstrumentNames.add(CODE_VALUE_FINANCIAL_INSTRUMENT_DELINQUENT);
-        financialInstrumentNames.add(CODE_VALUE_FINANCIAL_INSTRUMENT_OTHER);
-        createCodeValues(CODE_VALUE_FINANCIAL_INSTRUMENT_ID, 
financialInstrumentNames);
+        createCodeValues(CodeNames.FINANCIAL_INSTRUMENT.getValue(), 
financialInstrumentNames);
+
+        List<String> chargeOffReasonNames = new ArrayList<>();
+        chargeOffReasonNames.add(CODE_VALUE_CHARGE_OFF_REASON_FRAUD);
+        chargeOffReasonNames.add(CODE_VALUE_CHARGE_OFF_REASON_DELINQUENT);
+        chargeOffReasonNames.add(CODE_VALUE_CHARGE_OFF_REASON_OTHER);
+        createCodeValues(CodeNames.CHARGE_OFF.getValue(), 
chargeOffReasonNames);
 
         // transaction type
         List<String> transactionTypeNames = new ArrayList<>();
         
transactionTypeNames.add(CODE_VALUE_TRANSACTION_TYPE_SCHEDULED_PAYMENT);
-        createCodeValues(CODE_VALUE_TRANSACTION_TYPE_ID, transactionTypeNames);
+        createCodeValues(CodeNames.TRANSACTION_TYPE.getValue(), 
transactionTypeNames);
 
         // bankruptcy tag
         List<String> bankruptcyTagNames = new ArrayList<>();
         bankruptcyTagNames.add(CODE_VALUE_BANKRUPTCY_TAG_PENDING);
         bankruptcyTagNames.add(CODE_VALUE_BANKRUPTCY_TAG_BANKRUPTCY);
-        createCodeValues(CODE_VALUE_BANKRUPTCY_TAG_ID, bankruptcyTagNames);
+        createCodeValues(CodeNames.BANKRUPTCY_TAG.getValue(), 
bankruptcyTagNames);
 
         // pending fraud tag
         List<String> pendingFraudTagNames = new ArrayList<>();
         pendingFraudTagNames.add(CODE_VALUE_PENDING_FRAUD_TAG_PENDING);
         pendingFraudTagNames.add(CODE_VALUE_PENDING_FRAUD_TAG_FRAUD);
-        createCodeValues(CODE_VALUE_PENDING_FRAUD_TAG_ID, 
pendingFraudTagNames);
+        createCodeValues(CodeNames.PENDING_FRAUD_TAG.getValue(), 
pendingFraudTagNames);
 
         // pending deceased tag
         List<String> pendingDeceasedTagNames = new ArrayList<>();
         pendingDeceasedTagNames.add(CODE_VALUE_PENDING_DECEASED_TAG_PENDING);
         pendingDeceasedTagNames.add(CODE_VALUE_PENDING_DECEASED_TAG_DECEASED);
-        createCodeValues(CODE_VALUE_PENDING_DECEASED_TAG_ID, 
pendingDeceasedTagNames);
+        createCodeValues(CodeNames.PENDING_DECEASED_TAG.getValue(), 
pendingDeceasedTagNames);
 
         // hardship tag
         List<String> hardshipTagNames = new ArrayList<>();
         hardshipTagNames.add(CODE_VALUE_HARDSHIP_TAG_ACTIVE);
         hardshipTagNames.add(CODE_VALUE_HARDSHIP_TAG_INACTIVE);
-        createCodeValues(CODE_VALUE_HARDSHIP_TAG_ID, hardshipTagNames);
+        createCodeValues(CodeNames.HARDSHIP_TAG.getValue(), hardshipTagNames);
 
         // active duty tag
         List<String> activeDutyTagNames = new ArrayList<>();
         activeDutyTagNames.add(CODE_VALUE_ACTIVE_DUTY_TAG_ACTIVE);
         activeDutyTagNames.add(CODE_VALUE_ACTIVE_DUTY_TAG_INACTIVE);
-        createCodeValues(CODE_VALUE_ACTIVE_DUTY_TAG_ID, activeDutyTagNames);
+        createCodeValues(CodeNames.ACTIVE_DUTY_TAG.getValue(), 
activeDutyTagNames);
 
         // customer identifiers put/post
         List<String> customerIdentifierNamesPut = new ArrayList<>();
@@ -193,34 +172,34 @@ public class CodeGlobalInitializerStep implements 
FineractGlobalInitializerStep
         customerIdentifierNamesPut.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_2);
         customerIdentifierNamesPut.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_3);
         customerIdentifierNamesPut.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_4);
-        updateCodeValues(CODE_VALUE_CUSTOMER_IDENTIFIERS_ID, 
customerIdentifierNamesPut);
+        updateCodeValues(CodeNames.CUSTOMER_IDENTIFIER.getValue(), 
customerIdentifierNamesPut);
 
         List<String> customerIdentifierNamesPost = new ArrayList<>();
         customerIdentifierNamesPost.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_5);
         customerIdentifierNamesPost.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_6);
         customerIdentifierNamesPost.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_7);
         customerIdentifierNamesPost.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_8);
-        createCodeValues(CODE_VALUE_CUSTOMER_IDENTIFIERS_ID, 
customerIdentifierNamesPost);
+        createCodeValues(CodeNames.CUSTOMER_IDENTIFIER.getValue(), 
customerIdentifierNamesPost);
 
         // gender
         List<String> genderNames = new ArrayList<>();
         genderNames.add(CODE_VALUE_GENDER_FEMALE);
         genderNames.add(CODE_VALUE_GENDER_MALE);
-        createCodeValues(CODE_VALUE_GENDER_ID, genderNames);
+        createCodeValues(CodeNames.GENDER.getValue(), genderNames);
 
         // client type
         List<String> clientTypeNames = new ArrayList<>();
         clientTypeNames.add(CODE_VALUE_CLIENT_TYPE_CORPORATE);
         clientTypeNames.add(CODE_VALUE_CLIENT_TYPE_LEGAL);
         clientTypeNames.add(CODE_VALUE_CLIENT_TYPE_NON_LEGAL);
-        createCodeValues(CODE_VALUE_CLIENT_TYPE_ID, clientTypeNames);
+        createCodeValues(CodeNames.CLIENT_TYPE.getValue(), clientTypeNames);
 
         // client classification
         List<String> clientClassificationNames = new ArrayList<>();
         clientClassificationNames.add(CODE_VALUE_CLIENT_CLASSIFICATION_LAWYER);
         
clientClassificationNames.add(CODE_VALUE_CLIENT_CLASSIFICATION_DIRECTOR);
         clientClassificationNames.add(CODE_VALUE_CLIENT_CLASSIFICATION_NONE);
-        createCodeValues(CODE_VALUE_CLIENT_CLASSIFICATION_ID, 
clientClassificationNames);
+        createCodeValues(CodeNames.CLIENT_CLASSIFICATION.getValue(), 
clientClassificationNames);
 
         // add family member - relationship
         List<String> familyMemberRelationshipNames = new ArrayList<>();
@@ -228,40 +207,51 @@ public class CodeGlobalInitializerStep implements 
FineractGlobalInitializerStep
         
familyMemberRelationshipNames.add(CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_FATHER);
         
familyMemberRelationshipNames.add(CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_MOTHER);
         
familyMemberRelationshipNames.add(CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_CHILD);
-        createCodeValues(CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_ID, 
familyMemberRelationshipNames);
+        createCodeValues(CodeNames.FAMILY_MEMBER_RELATIONSHIP.getValue(), 
familyMemberRelationshipNames);
 
         // add family member - profession
         List<String> familyMemberProfessionNames = new ArrayList<>();
         
familyMemberProfessionNames.add(CODE_VALUE_FAMILY_MEMBER_PROFESSION_EMPLOYEE);
         
familyMemberProfessionNames.add(CODE_VALUE_FAMILY_MEMBER_PROFESSION_SELF_EMPLOYED);
-        createCodeValues(CODE_VALUE_FAMILY_MEMBER_PROFESSION_ID, 
familyMemberProfessionNames);
+        createCodeValues(CodeNames.FAMILY_MEMBER_PROFESSION.getValue(), 
familyMemberProfessionNames);
 
         // add family member - marital status
         List<String> familyMemberMaritalStatusNames = new ArrayList<>();
         
familyMemberMaritalStatusNames.add(CODE_VALUE_FAMILY_MARITAL_STATUS_MARRIED);
         
familyMemberMaritalStatusNames.add(CODE_VALUE_FAMILY_MARITAL_STATUS_SINGLE);
         
familyMemberMaritalStatusNames.add(CODE_VALUE_FAMILY_MARITAL_STATUS_WIDOWED);
-        createCodeValues(CODE_VALUE_FAMILY_MARITAL_STATUS_ID, 
familyMemberMaritalStatusNames);
+        createCodeValues(CodeNames.FAMILY_MARITAL_STATUS.getValue(), 
familyMemberMaritalStatusNames);
 
         // add constitution (for client creation as Entity)
         List<String> constitutionNames = new ArrayList<>();
         constitutionNames.add(CODE_VALUE_CONSTITUTION_TEST);
-        createCodeValues(CODE_VALUE_CONSTITUTION_ID, constitutionNames);
+        createCodeValues(CodeNames.CONSTITUTION.getValue(), constitutionNames);
 
         // add LoanRescheduleReason
         List<String> rescheduleReasonNames = new ArrayList<>();
         rescheduleReasonNames.add(CODE_VALUE_RESCHEDULE_REASON_TEST);
-        createCodeValues(CODE_VALUE_RESCHEDULE_REASON_ID, 
rescheduleReasonNames);
+        createCodeValues(CodeNames.LOAN_RESCHEDULE_REASON.getValue(), 
rescheduleReasonNames);
 
         // add Write-off reasons
         List<String> writeOffReasonNames = new ArrayList<>();
         writeOffReasonNames.add(CODE_VALUE_WRITE_OFF_REASON_TEST_1);
         writeOffReasonNames.add(CODE_VALUE_WRITE_OFF_REASON_TEST_2);
         writeOffReasonNames.add(CODE_VALUE_WRITE_OFF_REASON_TEST_3);
-        createCodeValues(CODE_VALUE_WRITE_OFF_REASON_ID, writeOffReasonNames);
+        createCodeValues(CodeNames.WRITE_OFF_REASON.getValue(), 
writeOffReasonNames);
+
+        // Add buy down fee transaction classification
+        List<String> buydownFeeTransactionClassificationName = new 
ArrayList<>();
+        
buydownFeeTransactionClassificationName.add(BUYDOWN_FEE_TRANSACTION_CLASSIFICATION_VALUE);
+        
createCodeValues(CodeNames.BUYDOWN_FEE_TRANSACTION_CLASSIFICATION.getValue(), 
buydownFeeTransactionClassificationName);
+
+        // Add capitalized income transaction classification
+        List<String> capitalizedIncomeTransactionClassificationName = new 
ArrayList<>();
+        
capitalizedIncomeTransactionClassificationName.add(CAPITALIZED_INCOME_TRANSACTION_CLASSIFICATION_VALUE);
+        
createCodeValues(CodeNames.CAPITALIZED_INCOME_TRANSACTION_CLASSIFICATION.getValue(),
+                capitalizedIncomeTransactionClassificationName);
     }
 
-    public void createCodeValues(Long codeId, List<String> codeValueNames) {
+    public void createCodeValues(String codeName, List<String> codeValueNames) 
{
         codeValueNames.forEach(name -> {
             Integer position = codeValueNames.indexOf(name);
             PostCodeValuesDataRequest postCodeValuesDataRequest = new 
PostCodeValuesDataRequest();
@@ -270,7 +260,7 @@ public class CodeGlobalInitializerStep implements 
FineractGlobalInitializerStep
             postCodeValuesDataRequest.position(position);
 
             try {
-                executeVoid(() -> 
fineractClient.codeValues().createCodeValue(codeId, postCodeValuesDataRequest, 
Map.of()));
+                executeVoid(() -> 
fineractClient.codeValues().createCodeValue1(codeName, 
postCodeValuesDataRequest, Map.of()));
                 log.debug("Code value '{}' created successfully", name);
             } catch (CallFailedRuntimeException e) {
                 if (e.getStatus() == 403 && e.getDeveloperMessage() != null && 
e.getDeveloperMessage().contains("already exists")) {
@@ -282,7 +272,7 @@ public class CodeGlobalInitializerStep implements 
FineractGlobalInitializerStep
         });
     }
 
-    public void updateCodeValues(Long codeId, List<String> codeValueNames) {
+    public void updateCodeValues(String codeName, List<String> codeValueNames) 
{
         codeValueNames.forEach(name -> {
             int position = codeValueNames.indexOf(name) + 1;
             PutCodeValuesDataRequest putCodeValuesDataRequest = new 
PutCodeValuesDataRequest();
@@ -290,19 +280,19 @@ public class CodeGlobalInitializerStep implements 
FineractGlobalInitializerStep
             putCodeValuesDataRequest.name(name);
             putCodeValuesDataRequest.position(position);
 
-            executeVoid(() -> 
fineractClient.codeValues().updateCodeValue(codeId, (long) position, 
putCodeValuesDataRequest, Map.of()));
+            executeVoid(() -> 
fineractClient.codeValues().updateCodeValue1(codeName, (long) position, 
putCodeValuesDataRequest, Map.of()));
         });
     }
 
     private void createCodeNames() {
         List<String> codesNameList = new ArrayList<>();
-        codesNameList.add(CODE_NAME_FINANCIAL_INSTRUMENT);
-        codesNameList.add(CODE_NAME_TRANSACTION_TYPE);
-        codesNameList.add(CODE_NAME_BANKRUPTCY_TAG);
-        codesNameList.add(CODE_NAME_PENDING_FRAUD_TAG);
-        codesNameList.add(CODE_NAME_PENDING_DECEASED_TAG);
-        codesNameList.add(CODE_NAME_HARDSHIP_TAG);
-        codesNameList.add(CODE_NAME_ACTIVE_DUTY_TAG);
+        codesNameList.add(CodeNames.FINANCIAL_INSTRUMENT.getValue());
+        codesNameList.add(CodeNames.TRANSACTION_TYPE.getValue());
+        codesNameList.add(CodeNames.BANKRUPTCY_TAG.getValue());
+        codesNameList.add(CodeNames.PENDING_FRAUD_TAG.getValue());
+        codesNameList.add(CodeNames.PENDING_DECEASED_TAG.getValue());
+        codesNameList.add(CodeNames.HARDSHIP_TAG.getValue());
+        codesNameList.add(CodeNames.ACTIVE_DUTY_TAG.getValue());
 
         codesNameList.forEach(codeName -> {
             try {
diff --git 
a/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
 
b/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
index 233e272153..840b409a60 100644
--- 
a/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
+++ 
b/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
@@ -62,6 +62,7 @@ import 
org.apache.fineract.test.data.OverAppliedCalculationType;
 import org.apache.fineract.test.data.PreClosureInterestCalculationRule;
 import org.apache.fineract.test.data.RecalculationRestFrequencyType;
 import org.apache.fineract.test.data.TransactionProcessingStrategyCode;
+import org.apache.fineract.test.data.codevalue.CodeNames;
 import org.apache.fineract.test.data.codevalue.CodeValue;
 import org.apache.fineract.test.data.codevalue.CodeValueResolver;
 import org.apache.fineract.test.data.codevalue.DefaultCodeValue;
@@ -3697,7 +3698,9 @@ public class LoanProductGlobalInitializerStep implements 
FineractGlobalInitializ
 
         List<PostClassificationToIncomeAccountMappings> 
buydownfeeClassificationToIncomeAccountMappings = new ArrayList<>();
         PostClassificationToIncomeAccountMappings 
classificationToIncomeAccountMappings = new 
PostClassificationToIncomeAccountMappings();
-        
classificationToIncomeAccountMappings.setClassificationCodeValueId(25L);
+        long classificationId = 
codeValueResolver.resolve(CodeNames.BUYDOWN_FEE_TRANSACTION_CLASSIFICATION.getValue(),
+                
CodeGlobalInitializerStep.BUYDOWN_FEE_TRANSACTION_CLASSIFICATION_VALUE);
+        
classificationToIncomeAccountMappings.setClassificationCodeValueId(classificationId);
         classificationToIncomeAccountMappings.setIncomeAccountId(10L);
         
buydownfeeClassificationToIncomeAccountMappings.add(classificationToIncomeAccountMappings);
 
@@ -3736,7 +3739,10 @@ public class LoanProductGlobalInitializerStep implements 
FineractGlobalInitializ
 
         List<PostClassificationToIncomeAccountMappings> 
capitalizedIncomeClassificationToIncomeAccountMappings = new ArrayList<>();
         PostClassificationToIncomeAccountMappings 
classificationToIncomeAccountMappingsCapitalizedIncome = new 
PostClassificationToIncomeAccountMappings();
-        
classificationToIncomeAccountMappingsCapitalizedIncome.setClassificationCodeValueId(24L);
+        long capitalizedIncomeClassificationId = codeValueResolver.resolve(
+                
CodeNames.CAPITALIZED_INCOME_TRANSACTION_CLASSIFICATION.getValue(),
+                
CodeGlobalInitializerStep.CAPITALIZED_INCOME_TRANSACTION_CLASSIFICATION_VALUE);
+        
classificationToIncomeAccountMappingsCapitalizedIncome.setClassificationCodeValueId(capitalizedIncomeClassificationId);
         
classificationToIncomeAccountMappingsCapitalizedIncome.setIncomeAccountId(15L);
         
capitalizedIncomeClassificationToIncomeAccountMappings.add(classificationToIncomeAccountMappingsCapitalizedIncome);
 
diff --git 
a/fineract-e2e-tests-runner/src/test/resources/features/LoanBuyDownFees.feature 
b/fineract-e2e-tests-runner/src/test/resources/features/LoanBuyDownFees.feature
index c300e33bc8..161024f8fe 100644
--- 
a/fineract-e2e-tests-runner/src/test/resources/features/LoanBuyDownFees.feature
+++ 
b/fineract-e2e-tests-runner/src/test/resources/features/LoanBuyDownFees.feature
@@ -3232,7 +3232,7 @@ Feature:Feature: Buy Down Fees
     And Admin successfully approves the loan on "01 January 2024" with "100" 
amount and expected disbursement date on "01 January 2024"
     And Admin successfully disburse the loan on "01 January 2024" with "100" 
EUR transaction amount
     Then Loan status will be "ACTIVE"
-    When Admin adds buy down fee with "AUTOPAY" payment type to the loan on 
"01 January 2024" with "50" EUR transaction amount and 
"buydown_fee_transaction_classification" classification
+    When Admin adds buy down fee with "AUTOPAY" payment type to the loan on 
"01 January 2024" with "50" EUR transaction amount and 
"buydown_fee_transaction_classification_value" classification
     Then Loan Repayment schedule has 3 periods, with the following data for 
periods:
       | Nr | Days | Date             | Paid date | Balance of loan | Principal 
due | Interest | Fees | Penalties | Due   | Paid | In advance | Late | 
Outstanding |
       |    |      | 01 January 2024  |           | 100.0           |           
    |          | 0.0  |           | 0.0   | 0.0  |            |      |          
   |
@@ -3841,7 +3841,7 @@ Feature:Feature: Buy Down Fees
       | 
LP2_PROGRESSIVE_ADVANCED_PAYMENT_ALLOCATION_BUYDOWN_FEES_CLASSIFICATION_INCOME_MAP
 | 01 January 2024   | 350            | 7                      | 
DECLINING_BALANCE | DAILY                       | EQUAL_INSTALLMENTS | 3        
         | MONTHS                | 1              | MONTHS                 | 3  
                | 0                       | 0                      | 0          
          | ADVANCED_PAYMENT_ALLOCATION |
     And Admin successfully approves the loan on "01 January 2024" with "350" 
amount and expected disbursement date on "01 January 2024"
     And Admin successfully disburse the loan on "01 January 2024" with "100" 
EUR transaction amount
-    And Admin adds buy down fee with "AUTOPAY" payment type to the loan on "01 
January 2024" with "50" EUR transaction amount and classification: 
pending_bankruptcy
+    When Admin adds buy down fee with "AUTOPAY" payment type to the loan on 
"01 January 2024" with "50" EUR transaction amount and 
"buydown_fee_transaction_classification_value" classification
     And Admin sets the business date to "02 January 2024"
     And Admin runs inline COB job for Loan
     Then Loan Transactions tab has a "BUY_DOWN_FEE" transaction with date "01 
January 2024" which has the following Journal entries:
@@ -3868,7 +3868,7 @@ Feature:Feature: Buy Down Fees
     And Admin adds buy down fee with "AUTOPAY" payment type to the loan on "01 
January 2024" with "50" EUR transaction amount
     And Admin sets the business date to "02 January 2024"
     And Admin runs inline COB job for Loan
-    And Admin adds buy down fee with "AUTOPAY" payment type to the loan on "02 
January 2024" with "20" EUR transaction amount and classification: 
pending_bankruptcy
+    When Admin adds buy down fee with "AUTOPAY" payment type to the loan on 
"02 January 2024" with "20" EUR transaction amount and 
"buydown_fee_transaction_classification_value" classification
     And Admin sets the business date to "03 January 2024"
     And Admin runs inline COB job for Loan
     Then Loan Transactions tab has a "BUY_DOWN_FEE" transaction with date "01 
January 2024" which has the following Journal entries:
@@ -3902,7 +3902,7 @@ Feature:Feature: Buy Down Fees
     And Admin successfully approves the loan on "01 January 2024" with "100" 
amount and expected disbursement date on "01 January 2024"
     And Admin successfully disburse the loan on "01 January 2024" with "100" 
EUR transaction amount
     Then Loan status will be "ACTIVE"
-    When Admin adds buy down fee with "AUTOPAY" payment type to the loan on 
"01 January 2024" with "50" EUR transaction amount and classification: 
pending_bankruptcy
+    When Admin adds buy down fee with "AUTOPAY" payment type to the loan on 
"01 January 2024" with "50" EUR transaction amount and 
"buydown_fee_transaction_classification_value" classification
     Then Loan Repayment schedule has 3 periods, with the following data for 
periods:
       | Nr | Days | Date             | Paid date | Balance of loan | Principal 
due | Interest | Fees | Penalties | Due   | Paid | In advance | Late | 
Outstanding |
       |    |      | 01 January 2024  |           | 100.0           |           
    |          | 0.0  |           | 0.0   | 0.0  |            |      |          
   |
@@ -3920,7 +3920,7 @@ Feature:Feature: Buy Down Fees
       | Type      | Account code | Account name                | Debit | 
Credit |
       | EXPENSE   | 450280       | Buy Down Expense            | 50.0  |       
 |
       | LIABILITY | 145024       | Deferred Capitalized Income |       | 50.0  
 |
-    And Loan Transactions tab has a "Buy Down Fee" transaction with date "01 
January 2024" which has classification code value "pending_bankruptcy"
+    And Loan Transactions tab has a "Buy Down Fee" transaction with date "01 
January 2024" which has classification code value 
"buydown_fee_transaction_classification_value"
     And Buy down fee contains the following data:
       | Date            | Fee Amount | Amortized Amount | Not Yet Amortized 
Amount | Adjusted Amount | Charged Off Amount |
       | 01 January 2024 | 50.0       | 0.0              | 50.0                 
    | 0.0             | 0.0                |
diff --git 
a/fineract-e2e-tests-runner/src/test/resources/features/LoanCapitalizedIncome.feature
 
b/fineract-e2e-tests-runner/src/test/resources/features/LoanCapitalizedIncome.feature
index 5a68961728..9857723ed2 100644
--- 
a/fineract-e2e-tests-runner/src/test/resources/features/LoanCapitalizedIncome.feature
+++ 
b/fineract-e2e-tests-runner/src/test/resources/features/LoanCapitalizedIncome.feature
@@ -7673,7 +7673,7 @@ Feature: Capitalized Income
     And Admin successfully disburse the loan on "1 January 2024" with "900" 
EUR transaction amount
     Then Loan status will be "ACTIVE"
     When Admin sets the business date to "2 January 2024"
-    And Admin adds capitalized income with "AUTOPAY" payment type to the loan 
on "2 January 2024" with "100" EUR transaction amount and 
"capitalized_income_transaction_classification" classification
+    And Admin adds capitalized income with "AUTOPAY" payment type to the loan 
on "2 January 2024" with "100" EUR transaction amount and 
"capitalized_income_transaction_classification_value" classification
     Then Loan Repayment schedule has 2 periods, with the following data for 
periods:
       | Nr | Days | Date            | Paid date       | Balance of loan | 
Principal due | Interest | Fees | Penalties | Due   | Paid  | In advance | Late 
| Outstanding |
       |    |      | 01 January 2024 |                 | 900.0           |      
         |          | 0.0  |           | 0.0   | 0.0   |            |      |    
         |
@@ -8277,7 +8277,7 @@ Feature: Capitalized Income
     Then Loan is closed with zero outstanding balance and it's all 
installments have obligations met
 
   @TestRailId:C4096
-  Scenario: Verify GL entries for Capitalized Income Amortization - UC2: 
Amortization for Capitalized Income with classification rule: pending_bankruptcy
+  Scenario: Verify GL entries for Capitalized Income Amortization - UC2: 
Amortization for Capitalized Income with classification rule: 
capitalized_income_transaction_classification_value
     When Admin sets the business date to "01 January 2024"
     And Admin creates a client with random data
     When Admin creates a fully customized loan with the following data:
@@ -8285,7 +8285,7 @@ Feature: Capitalized Income
       | 
LP2_PROGRESSIVE_ADV_PMNT_ALLOCATION_CAPITALIZED_INCOME_ADJ_CUSTOM_ALLOC_CLASSIFICATION_INCOME_MAP
 | 01 January 2024   | 350            | 7                      | 
DECLINING_BALANCE | DAILY                       | EQUAL_INSTALLMENTS | 3        
         | MONTHS                | 1              | MONTHS                 | 3  
                | 0                       | 0                      | 0          
          | ADVANCED_PAYMENT_ALLOCATION |
     And Admin successfully approves the loan on "01 January 2024" with "350" 
amount and expected disbursement date on "01 January 2024"
     And Admin successfully disburse the loan on "01 January 2024" with "100" 
EUR transaction amount
-    And Admin adds capitalized income with "AUTOPAY" payment type to the loan 
on "01 January 2024" with "50" EUR transaction amount and classification: 
scheduled_payment
+    And Admin adds capitalized income with "AUTOPAY" payment type to the loan 
on "01 January 2024" with "50" EUR transaction amount and 
"capitalized_income_transaction_classification_value" classification
     When Admin sets the business date to "02 January 2024"
     And Admin runs inline COB job for Loan
     Then Loan Transactions tab has a "CAPITALIZED_INCOME" transaction with 
date "01 January 2024" which has the following Journal entries:
@@ -8301,7 +8301,7 @@ Feature: Capitalized Income
     Then Loan is closed with zero outstanding balance and it's all 
installments have obligations met
 
   @TestRailId:C4097
-  Scenario: Verify GL entries for Capitalized Income Amortization - UC3: 
Amortization for Capitalized Incomes with NO classification and with 
classification rule: pending_bankruptcy
+  Scenario: Verify GL entries for Capitalized Income Amortization - UC3: 
Amortization for Capitalized Incomes with NO classification and with 
classification rule: capitalized_income_transaction_classification_value
     When Admin sets the business date to "01 January 2024"
     And Admin creates a client with random data
     When Admin creates a fully customized loan with the following data:
@@ -8312,7 +8312,7 @@ Feature: Capitalized Income
     And Admin adds capitalized income with "AUTOPAY" payment type to the loan 
on "01 January 2024" with "50" EUR transaction amount
     When Admin sets the business date to "02 January 2024"
     And Admin runs inline COB job for Loan
-    And Admin adds capitalized income with "AUTOPAY" payment type to the loan 
on "02 January 2024" with "20" EUR transaction amount and classification: 
scheduled_payment
+    And Admin adds capitalized income with "AUTOPAY" payment type to the loan 
on "02 January 2024" with "20" EUR transaction amount and 
"capitalized_income_transaction_classification_value" classification
     When Admin sets the business date to "03 January 2024"
     And Admin runs inline COB job for Loan
     Then Loan Transactions tab has a "CAPITALIZED_INCOME" transaction with 
date "01 January 2024" which has the following Journal entries:
@@ -8346,7 +8346,7 @@ Feature: Capitalized Income
     And Admin successfully approves the loan on "01 January 2024" with "200" 
amount and expected disbursement date on "01 January 2024"
     And Admin successfully disburse the loan on "01 January 2024" with "100" 
EUR transaction amount
     Then Loan status will be "ACTIVE"
-    And Admin adds capitalized income with "AUTOPAY" payment type to the loan 
on "01 January 2024" with "50" EUR transaction amount and classification: 
scheduled_payment
+    And Admin adds capitalized income with "AUTOPAY" payment type to the loan 
on "01 January 2024" with "50" EUR transaction amount and 
"capitalized_income_transaction_classification_value" classification
     Then Loan Repayment schedule has 3 periods, with the following data for 
periods:
       | Nr | Days | Date             | Paid date | Balance of loan | Principal 
due | Interest | Fees | Penalties | Due   | Paid | In advance | Late | 
Outstanding |
       |    |      | 01 January 2024  |           | 100.0           |           
    |          | 0.0  |           | 0.0   | 0.0  |            |      |          
   |
@@ -8365,7 +8365,7 @@ Feature: Capitalized Income
       | Type      | Account code | Account name                | Debit | 
Credit |
       | ASSET     | 112601       | Loans Receivable            | 50.0  |       
 |
       | LIABILITY | 145024       | Deferred Capitalized Income |       | 50.0  
 |
-    And Loan Transactions tab has a "Capitalized Income" transaction with date 
"01 January 2024" which has classification code value "scheduled_payment"
+    And Loan Transactions tab has a "Capitalized Income" transaction with date 
"01 January 2024" which has classification code value 
"capitalized_income_transaction_classification_value"
     Then LoanCapitalizedIncomeTransactionCreatedBusinessEvent is raised on "01 
January 2024"
     And Admin adds capitalized income adjustment with "AUTOPAY" payment type 
to the loan on "01 January 2024" with "25" EUR transaction amount
     Then Loan Transactions tab has the following data:
diff --git 
a/fineract-e2e-tests-runner/src/test/resources/features/LoanProduct.feature 
b/fineract-e2e-tests-runner/src/test/resources/features/LoanProduct.feature
index 4808c43a30..5938f70d77 100644
--- a/fineract-e2e-tests-runner/src/test/resources/features/LoanProduct.feature
+++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanProduct.feature
@@ -187,26 +187,22 @@ Feature: LoanProduct
     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 5 options, with the following data:
+    Then Loan Product Charge-Off reasons options from loan product template 
have 3 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    
    |
-      | Fraud                  |             | 2        | true      | false    
    |
-      | Delinquent             |             | 3        | true      | false    
    |
-      | Other                  |             | 4        | true      | false    
    |
+      | Fraud                  |             | 0        | true      | false    
    |
+      | Delinquent             |             | 1        | true      | false    
    |
+      | Other                  |             | 2        | true      | false    
    |
 
   @TestRailId:C3482
   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 5 options, with the following data:
+    Then Loan Product "LP1" Charge-Off reasons options from specific loan 
product have 3 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    
    |
-      | Fraud                  |             | 2        | true      | false    
    |
-      | Delinquent             |             | 3        | true      | false    
    |
-      | Other                  |             | 4        | true      | false    
    |
+      | Fraud                  |             | 0        | true      | false    
    |
+      | Delinquent             |             | 1        | true      | false    
    |
+      | Other                  |             | 2        | true      | false    
    |
 
   @TestRailId:C3587
   Scenario: As a user I would like to verify 
interestRecognitionOnDisbursementDate=false flag in loan product response
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/api/CodeValuesApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/api/CodeValuesApiResource.java
index 2bb9a318cc..6c3ecc774e 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/api/CodeValuesApiResource.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/api/CodeValuesApiResource.java
@@ -41,6 +41,7 @@ import jakarta.ws.rs.core.UriInfo;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 import lombok.RequiredArgsConstructor;
 import org.apache.fineract.commands.domain.CommandWrapper;
@@ -49,6 +50,7 @@ import 
org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformS
 import 
org.apache.fineract.infrastructure.codes.CodeConstants.CodevalueJSONinputParams;
 import org.apache.fineract.infrastructure.codes.data.CodeData;
 import org.apache.fineract.infrastructure.codes.data.CodeValueData;
+import 
org.apache.fineract.infrastructure.codes.service.CodeReadPlatformService;
 import 
org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService;
 import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
 import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
@@ -57,7 +59,7 @@ import 
org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSer
 import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
 import org.springframework.stereotype.Component;
 
-@Path("/v1/codes/{codeId}/codevalues")
+@Path("/v1/codes")
 @Component
 @Tag(name = "Code Values", description = "Code and code values: Codes 
represent a specific category of data, their code values are a specific 
instance of that category.\n"
         + "\n"
@@ -76,11 +78,13 @@ public class CodeValuesApiResource {
 
     private final PlatformSecurityContext context;
     private final CodeValueReadPlatformService readPlatformService;
+    private final CodeReadPlatformService codeReadPlatformService;
     private final DefaultToApiJsonSerializer<CodeValueData> 
toApiJsonSerializer;
     private final ApiRequestParameterHelper apiRequestParameterHelper;
     private final PortfolioCommandSourceWritePlatformService 
commandsSourceWritePlatformService;
 
     @GET
+    @Path("{codeId}/codevalues")
     @Consumes({ MediaType.APPLICATION_JSON })
     @Produces({ MediaType.APPLICATION_JSON })
     @Operation(summary = "List Code Values", description = "Returns the list 
of Code Values for a given Code\n" + "\n"
@@ -99,7 +103,7 @@ public class CodeValuesApiResource {
     }
 
     @GET
-    @Path("{codeValueId}")
+    @Path("{codeId}/codevalues/{codeValueId}")
     @Consumes({ MediaType.APPLICATION_JSON })
     @Produces({ MediaType.APPLICATION_JSON })
     @Operation(summary = "Retrieve a Code description", description = "Returns 
the details of a Code Value\n" + "\n" + "Example Requests:\n"
@@ -119,6 +123,7 @@ public class CodeValuesApiResource {
     }
 
     @POST
+    @Path("{codeId}/codevalues")
     @Consumes({ MediaType.APPLICATION_JSON })
     @Produces({ MediaType.APPLICATION_JSON })
     @Operation(summary = "Create a Code description", description = "")
@@ -137,7 +142,7 @@ public class CodeValuesApiResource {
     }
 
     @PUT
-    @Path("{codeValueId}")
+    @Path("{codeId}/codevalues/{codeValueId}")
     @Consumes({ MediaType.APPLICATION_JSON })
     @Produces({ MediaType.APPLICATION_JSON })
     @Operation(summary = "Update a Code description", description = "Updates 
the details of a code description.")
@@ -157,7 +162,7 @@ public class CodeValuesApiResource {
     }
 
     @DELETE
-    @Path("{codeValueId}")
+    @Path("{codeId}/codevalues/{codeValueId}")
     @Consumes({ MediaType.APPLICATION_JSON })
     @Produces({ MediaType.APPLICATION_JSON })
     @Operation(summary = "Delete a Code description", description = "Deletes a 
code description")
@@ -172,4 +177,89 @@ public class CodeValuesApiResource {
 
         return this.toApiJsonSerializer.serialize(result);
     }
+
+    @GET
+    @Path("name/{codeName}/codevalues")
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Operation(summary = "List Code Values", description = "Returns the list 
of Code Values for a given Code\n" + "\n"
+            + "Example Requests:\n" + "\n" + "codes/1/codevalues", parameters 
= @Parameter(name = "codeId", description = "co"))
+    @ApiResponses({
+            @ApiResponse(responseCode = "200", description = "A List of code 
values for a given code", content = @Content(array = @ArraySchema(schema = 
@Schema(implementation = 
CodeValuesApiResourceSwagger.GetCodeValuesDataResponse.class)))) })
+    public List<CodeValueData> retrieveAllCodeValues(@Context final UriInfo 
uriInfo,
+            @PathParam("codeName") @Parameter(description = "codeName") final 
String codeName) {
+
+        
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
+
+        return this.readPlatformService.retrieveAllCodeValues(codeName);
+    }
+
+    @GET
+    @Path("name/{codeName}/codevalues/{codeValueId}")
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Operation(summary = "Retrieve a Code description", description = "Returns 
the details of a Code Value\n" + "\n" + "Example Requests:\n"
+            + "\n" + "codes/name/ADDRESS_TYPE/codevalues/1")
+    @ApiResponses({
+            @ApiResponse(responseCode = "200", description = "OK", content = 
@Content(schema = @Schema(implementation = 
CodeValuesApiResourceSwagger.GetCodeValuesDataResponse.class))) })
+    public CodeValueData retrieveCodeValue(@Context final UriInfo uriInfo,
+            @PathParam("codeName") @Parameter(description = "codeName") final 
String codeName,
+            @PathParam("codeValueId") @Parameter(description = "codeValueId") 
final Long codeValueId) {
+
+        
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
+
+        return this.readPlatformService.retrieveCodeValue(codeName, 
codeValueId);
+    }
+
+    @POST
+    @Path("name/{codeName}/codevalues")
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Operation(summary = "Create a Code description", description = "")
+    @RequestBody(required = true, content = @Content(schema = 
@Schema(implementation = 
CodeValuesApiResourceSwagger.PostCodeValuesDataRequest.class)))
+    @ApiResponses({
+            @ApiResponse(responseCode = "200", description = "OK", content = 
@Content(schema = @Schema(implementation = 
CodeValuesApiResourceSwagger.PostCodeValueDataResponse.class))) })
+    public CommandProcessingResult createCodeValue(@PathParam("codeName") 
@Parameter(description = "codeName") final String codeName,
+            @Parameter(hidden = true) final String apiRequestBodyAsJson) {
+        CodeData code = codeReadPlatformService.retrieveCode(codeName);
+        final CommandWrapper commandRequest = new 
CommandWrapperBuilder().createCodeValue(code.getId(), codeName)
+                .withJson(apiRequestBodyAsJson).build();
+
+        return 
this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
+    }
+
+    @PUT
+    @Path("name/{codeName}/codevalues/{codeValueId}")
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Operation(summary = "Update a Code description", description = "Updates 
the details of a code description.")
+    @RequestBody(required = true, content = @Content(schema = 
@Schema(implementation = 
CodeValuesApiResourceSwagger.PutCodeValuesDataRequest.class)))
+    @ApiResponses({
+            @ApiResponse(responseCode = "200", description = "OK", content = 
@Content(schema = @Schema(implementation = 
CodeValuesApiResourceSwagger.PutCodeValueDataResponse.class))) })
+    public CommandProcessingResult updateCodeValue(@PathParam("codeName") 
@Parameter(description = "codeName") final String codeName,
+            @PathParam("codeValueId") @Parameter(description = "codeValueId") 
final Long codeValueId,
+            @Parameter(hidden = true) final String apiRequestBodyAsJson) {
+
+        CodeData code = codeReadPlatformService.retrieveCode(codeName);
+        final CommandWrapper commandRequest = new 
CommandWrapperBuilder().updateCodeValue(codeName, code.getId(), codeValueId)
+                .withJson(apiRequestBodyAsJson).build();
+
+        return 
this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
+    }
+
+    @DELETE
+    @Path("name/{codeName}/codevalues/{codeValueId}")
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Operation(summary = "Delete a Code description", description = "Deletes a 
code description")
+    @ApiResponses({
+            @ApiResponse(responseCode = "200", description = "OK", content = 
@Content(schema = @Schema(implementation = 
CodeValuesApiResourceSwagger.DeleteCodeValueDataResponse.class))) })
+    public CommandProcessingResult deleteCodeValue(@PathParam("codeName") 
@Parameter(description = "codeName") final String codeName,
+            @PathParam("codeValueId") @Parameter(description = "codeValueId") 
final Long codeValueId) {
+
+        CodeData code = codeReadPlatformService.retrieveCode(codeName);
+        final CommandWrapper commandRequest = new 
CommandWrapperBuilder().deleteCodeValue(codeName, code.getId(), 
codeValueId).build();
+
+        return 
this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
+    }
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/api/CodesApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/api/CodesApiResource.java
index 409bf3bf10..0f275432df 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/api/CodesApiResource.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/api/CodesApiResource.java
@@ -134,7 +134,7 @@ public class CodesApiResource {
     public String retrieveCodeByName(@PathParam("codeName") 
@Parameter(description = "codeName") final String codeName,
             @Context final UriInfo uriInfo) {
 
-        final CodeData code = this.readPlatformService.retriveCode(codeName);
+        final CodeData code = this.readPlatformService.retrieveCode(codeName);
 
         final ApiRequestJsonSerializationSettings settings = 
this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
         return this.toApiJsonSerializer.serialize(settings, code, 
RESPONSE_DATA_PARAMETERS);
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeReadPlatformServiceImpl.java
index 8191710323..5f9970f2b4 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeReadPlatformServiceImpl.java
@@ -86,7 +86,7 @@ public class CodeReadPlatformServiceImpl implements 
CodeReadPlatformService {
     }
 
     @Override
-    public CodeData retriveCode(final String codeName) {
+    public CodeData retrieveCode(final String codeName) {
         try {
             this.context.authenticatedUser();
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeValueReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeValueReadPlatformServiceImpl.java
index 23a2e13066..f4f8957c02 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeValueReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/codes/service/CodeValueReadPlatformServiceImpl.java
@@ -22,10 +22,12 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.Collection;
 import java.util.List;
+import lombok.RequiredArgsConstructor;
 import org.apache.fineract.infrastructure.codes.data.CodeValueData;
+import org.apache.fineract.infrastructure.codes.domain.CodeValueRepository;
 import 
org.apache.fineract.infrastructure.codes.exception.CodeValueNotFoundException;
+import org.apache.fineract.infrastructure.codes.mapper.CodeValueMapper;
 import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.dao.EmptyResultDataAccessException;
 import org.springframework.jdbc.core.JdbcTemplate;
@@ -33,16 +35,13 @@ import org.springframework.jdbc.core.RowMapper;
 import org.springframework.stereotype.Service;
 
 @Service
+@RequiredArgsConstructor
 public class CodeValueReadPlatformServiceImpl implements 
CodeValueReadPlatformService {
 
     private final JdbcTemplate jdbcTemplate;
     private final PlatformSecurityContext context;
-
-    @Autowired
-    public CodeValueReadPlatformServiceImpl(final PlatformSecurityContext 
context, final JdbcTemplate jdbcTemplate) {
-        this.context = context;
-        this.jdbcTemplate = jdbcTemplate;
-    }
+    private final CodeValueRepository codeValueRepository;
+    private final CodeValueMapper codeValueMapper;
 
     private static final class CodeValueDataMapper implements 
RowMapper<CodeValueData> {
 
@@ -105,4 +104,22 @@ public class CodeValueReadPlatformServiceImpl implements 
CodeValueReadPlatformSe
         }
 
     }
+
+    @Override
+    public List<CodeValueData> retrieveAllCodeValues(String codeName) {
+        // TODO: review whether it is needed.
+        this.context.authenticatedUser();
+        return 
codeValueMapper.map(codeValueRepository.findByCodeName(codeName));
+    }
+
+    @Override
+    public CodeValueData retrieveCodeValue(String codeName, Long codeValueId) {
+        // TODO: review whether it is needed.
+        this.context.authenticatedUser();
+        CodeValueData codeValueData = 
codeValueMapper.map(codeValueRepository.findByCodeNameAndId(codeName, 
codeValueId));
+        if (codeValueData == null) {
+            throw new CodeValueNotFoundException(codeName, codeValueId);
+        }
+        return codeValueData;
+    }
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/DatatableWriteServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/DatatableWriteServiceImpl.java
index 018f3cb4de..ae4c0db88d 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/DatatableWriteServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/DatatableWriteServiceImpl.java
@@ -689,7 +689,7 @@ public class DatatableWriteServiceImpl implements 
DatatableWriteService {
 
         if (StringUtils.isNotBlank(code)) {
             if (isConstraintApproach) {
-                codeMappings.put(dataTableNameAlias + "_" + name, 
this.codeReadPlatformService.retriveCode(code).getId());
+                codeMappings.put(dataTableNameAlias + "_" + name, 
this.codeReadPlatformService.retrieveCode(code).getId());
                 String fkName = "fk_" + dataTableNameAlias + "_" + name;
                 constrainBuilder.append(", CONSTRAINT 
").append(sqlGenerator.escape(fkName)).append(" ").append("FOREIGN KEY (")
                         .append(sqlGenerator.escape(name)).append(") 
").append(REFERENCES_CLAUSE)
@@ -753,7 +753,7 @@ public class DatatableWriteServiceImpl implements 
DatatableWriteService {
         if (StringUtils.isNotBlank(code)) {
             if (isConstraintApproach) {
                 String fkName = "fk_" + dataTableNameAlias + "_" + name;
-                codeMappings.put(dataTableNameAlias + "_" + name, 
this.codeReadPlatformService.retriveCode(code).getId());
+                codeMappings.put(dataTableNameAlias + "_" + name, 
this.codeReadPlatformService.retrieveCode(code).getId());
                 constrainBuilder.append(",ADD CONSTRAINT  
").append(sqlGenerator.escape(fkName)).append(" ").append("FOREIGN KEY (")
                         .append(sqlGenerator.escape(name)).append(") 
").append(REFERENCES_CLAUSE)
                         
.append(sqlGenerator.escape(CODE_VALUES_TABLE)).append(" 
(").append(TABLE_FIELD_ID).append(")");
@@ -823,7 +823,7 @@ public class DatatableWriteServiceImpl implements 
DatatableWriteService {
                         }
                     }
                     if (newCode != null) {
-                        codeMappings.put(dataTableNameAlias + "_" + newName, 
this.codeReadPlatformService.retriveCode(newCode).getId());
+                        codeMappings.put(dataTableNameAlias + "_" + newName, 
this.codeReadPlatformService.retrieveCode(newCode).getId());
                         if (code == null || 
!StringUtils.equalsIgnoreCase(oldName, newName)) {
                             constrainBuilder.append(", ADD CONSTRAINT  
").append(sqlGenerator.escape(newFkName)).append(" ")
                                     .append("FOREIGN KEY 
(").append(sqlGenerator.escape(newName)).append(") ").append(REFERENCES_CLAUSE)

Reply via email to