You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by an...@apache.org on 2019/06/12 22:33:05 UTC

[fineract] 02/02: FINERACT-737: Updated Api Docs to include loan charges paid by FINERACT-736: Api Docs were updated to include rates documentation FINERACT-735: Integration test were created for rates creation, retrieval and update

This is an automated email from the ASF dual-hosted git repository.

angelboxes pushed a commit to branch Fineract-614
in repository https://gitbox.apache.org/repos/asf/fineract.git

commit 5ac6ae79c81584a79b0af02d4c40ab0147c48201
Author: Angel Cajas <an...@bowpi.com>
AuthorDate: Mon May 27 09:35:15 2019 -0600

    FINERACT-737: Updated Api Docs to include loan charges paid by
    FINERACT-736: Api Docs were updated to include rates documentation
    FINERACT-735: Integration test were created for rates creation, retrieval and update
---
 api-docs/apiLive.htm                               | 227 ++++++++++++++++++++-
 .../fineract/integrationtests/RatesTest.java       |  71 +++++++
 .../integrationtests/common/rates/RatesHelper.java |  91 +++++++++
 .../fineract/portfolio/rate/data/RateData.java     |   8 +-
 .../fineract/portfolio/rate/domain/Rate.java       |  36 ++--
 .../portfolio/rate/domain/RateAppliesTo.java       |  66 ++++++
 .../portfolio/rate/service/RateEnumerations.java   |  47 +++++
 .../rate/service/RateReadServiceImpl.java          |  12 +-
 .../sql/migrations/core_db/V352__rates.sql         |   3 +-
 9 files changed, 533 insertions(+), 28 deletions(-)

diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm
index 67dfc71..b91380c 100644
--- a/api-docs/apiLive.htm
+++ b/api-docs/apiLive.htm
@@ -2546,6 +2546,24 @@
 								<td></td>
 								<td></td>
 							</tr>
+                            <tr>
+                                <td><a href="#rates">Rates</a></td>
+                                <td>rates</td>
+                                <td><a href="#create_rate">Create Rate</a></td>
+                                <td><a href="#rate_list">List Rates</a></td>
+                                <td></td>
+                                <td></td>
+                                <td></td>
+                            </tr>
+                            <tr>
+                                <td></td>
+                                <td>rates/{rateId}</td>
+                                <td></td>
+                                <td><a href="#retrieve_rate">Retrieve Rate</a></td>
+                                <td><a href="#update_rate">Update Rate</a></td>
+                                <td></td>
+                                <td></td>
+                            </tr>
 						</table>
 					</div>
 				</div>
@@ -12141,7 +12159,17 @@ GET https://DomainName/api/v1/loans/{loanId}/transactions/{transactionId}
     "displayLabel": "US Dollar ($)"
   },
   "amount": 559.88,
-  "interestPortion": 559.88
+  "interestPortion": 559.88,
+  "loanChargePaidByList": [
+    {
+      "id": 29,
+      "amount": 138.700000,
+      "installmentNumber": 0,
+      "chargeId": 7,
+      "transactionId": 35,
+      "name": "Late Penalty Charge"
+    } 
+  ]
 }
 					</code>
 				</div>
@@ -16173,7 +16201,7 @@ GET https://DomainName/api/v1/loanproducts/{productId}
 							numberOfRepaymentVariationsForBorrowerCycle,
 							interestRateVariationsForBorrowerCycle,
 							multiDisburseLoan,maxTrancheCount,
-							outstandingLoanBalance,overdueDaysForNPA,holdGuaranteeFunds, principalThresholdForLastInstalment, accountMovesOutOfNPAOnlyOnArrearsCompletion, canDefineInstallmentAmount, installmentAmountInMultiplesOf, allowAttributeOverrides, allowPartialPeriodInterestCalcualtion
+							outstandingLoanBalance,overdueDaysForNPA,holdGuaranteeFunds, principalThresholdForLastInstalment, accountMovesOutOfNPAOnlyOnArrearsCompletion, canDefineInstallmentAmount, installmentAmountInMultiplesOf, allowAttributeOverrides, allowPartialPeriodInterestCalcualtion, rates
 							</td>
 						</tr>
 					</table>
@@ -43264,7 +43292,198 @@ No Request Body:
 			</div>
 			<!-- End of Tax Group -->
 
-		<!-- start of clients api docs -->
+            <!-- Start of Rates-->
+            <a id="rates" name="rates" class="old-syle-anchor">&nbsp;</a>
+            <div class="method-section">
+                <div class="method-description">
+                    <h3>Rates</h3>
+                    <p>This defines the Rates</p>
+                    <table class=matrixHeading>
+                        <tr class="matrixHeadingBG">
+                            <td>
+                                <div class="fineractHeading2">Field Descriptions</div>
+                            </td>
+                        </tr>
+                        <tr class=alt>
+                            <td>name</td>
+                        </tr>
+                        <tr>
+                            <td class=fielddesc>Name of Rate
+                            </td>
+                        </tr>
+                        <tr class=alt>
+                            <td>productApply</td>
+                        </tr>
+                        <tr>
+                            <td class=fielddesc>
+                                Enum value that defines to which entity the rate will be applicable.
+                                Available options are:
+                                1=Loans
+
+                                Once a rate definition is created, this attribute cannot be changed at any point
+                            </td>
+                        </tr>
+                        <tr class=alt>
+                            <td>Active</td>
+                        </tr>
+                        <tr>
+                            <td class=fielddesc>
+                                Flag indicating if the rate is currently active
+                            </td>
+                        </tr>
+                    </table>
+                </div>
+            </div>
+            <a id="create_rate" name="create_rate"
+               class="old-syle-anchor">&nbsp;</a>
+            <div class="method-section">
+                <div class="method-description">
+                    <h4>Create a new Rate</h4>
+                    <p>Creates a new Rate</p>
+                    <table class=matrixHeading>
+                        <tr class="matrixHeadingBG">
+                            <td>
+                                <div class="fineractHeading2">Mandatory Fields</div>
+                            </td>
+                        </tr>
+                        <tr class=alt>
+                            <td>name</td>
+                        </tr>
+                        <tr class=alt>
+                            <td>percentage</td>
+                        </tr>
+                        <tr class=alt>
+                            <td>productApply</td>
+                        </tr>
+                        <tr class=alt>
+                            <td>active</td>
+                        </tr>
+                    </table>
+                </div>
+                <div class="method-example">
+                    <code class="method-declaration">
+                        POST https://DomainName/api/v1/rates
+                    </code>
+                    <code class="method-request">
+                        POST rates
+                        Content-Type: application/json
+                        Request Body:
+                        {
+                        "productApply":1,
+                        "name":"Loan rate",
+                        "percentage":"12",
+                        "active":true,
+                        "locale":"en"
+                        }
+                    </code>
+                    <code class="method-response">
+                        {
+                        "resourceId": 1
+                        }
+                    </code>
+                </div>
+            </div>
+            <a id="rate_list" name="rate_list"
+               class="old-syle-anchor">&nbsp;</a>
+            <div class="method-section">
+                <div class="method-description">
+                    <h4>List Rates</h4>
+                    <p>List Rates</p>
+                </div>
+                <div class="method-example">
+                    <code class="method-declaration">
+                        GET https://DomainName/api/v1/rates
+                    </code>
+                    <code class="method-request">
+                        GET rates
+                        Content-Type: application/json
+                    </code>
+                    <code class="method-response">
+                        [
+                        {
+                        "id":1,
+                        "name":"Loan Rate",
+                        "percentage":12.00,
+                        "productApply":1,
+                        "active":true
+                        },
+                        {
+                        "id":2,
+                        "name":"Public Rate",
+                        "percentage":30.00,
+                        "productApply":1,
+                        "active":true
+                        },
+                        {
+                        "id":3,
+                        "name":"Private Rate",
+                        "percentage":14.00,
+                        "productApply":1,
+                        "active":true
+                        }
+                        ]
+                    </code>
+                </div>
+            </div>
+            <a id="retrieve_rate" name="retrieve_rate"
+               class="old-syle-anchor">&nbsp;</a>
+            <div class="method-section">
+                <div class="method-description">
+                    <h4>Retrieve a Rate</h4>
+                    <p>Return the details of an existing Rate</p>
+                </div>
+                <div class="method-example">
+                    <code class="method-declaration">
+                        GET https://DomainName/api/v1/rates/{rateId}
+                    </code>
+                    <code class="method-request">
+                        GET rates/1
+                        Content-Type: application/json
+                    </code>
+                    <code class="method-response">
+                        {
+                        "id":1,
+                        "name":"Loan Rate",
+                        "percentage":12.00,
+                        "productApply":1,
+                        "active":true
+                        }
+                    </code>
+                </div>
+            </div>
+            <a id="update_rate" name="update_rate"
+               class="old-syle-anchor">&nbsp;</a>
+            <div class="method-section">
+                <div class="method-description">
+                    <h4>Update a Rate</h4>
+                    <p>Updates an existing Rate</p>
+                </div>
+                <div class="method-example">
+                    <code class="method-declaration">
+                        POST https://DomainName/api/v1/rates/{rateId}
+                    </code>
+                    <code class="method-request">
+                        POST rates/3
+                        Content-Type: application/json
+                        Request Body:
+                        {
+                        "percentage":"17",
+                        }
+                    </code>
+                    <code class="method-response">
+                        {
+                        "resourceId":3,
+                        "changes":
+                        {
+                        "percentage":17
+                        }
+                        }
+                    </code>
+                </div>
+            </div>
+            <!-- End of Rates -->
+
+            <!-- start of clients api docs -->
 		<a id="templates" name="clients" class="old-syle-anchor">&nbsp;</a>
 		<div class="method-section">
 			<div class="method-description">
@@ -46736,7 +46955,7 @@ GET https://DomainName/api/v1/self/loans/{loanId}/transactions/{transactionId}
   },
   "amount": 559.88,
   "interestPortion": 559.88
-}
+   }
 					</code>
 				</div>
 			</div>
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/RatesTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/RatesTest.java
new file mode 100644
index 0000000..0feb648
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/RatesTest.java
@@ -0,0 +1,71 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.integrationtests;
+
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.builder.ResponseSpecBuilder;
+import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.fineract.integrationtests.common.rates.RatesHelper;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+@SuppressWarnings({"rawtypes"})
+public class RatesTest {
+
+    private ResponseSpecification responseSpec;
+    private RequestSpecification requestSpec;
+
+    @Before
+    public void setup() {
+        Utils.initializeRESTAssured();
+        this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
+        this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
+        this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
+    }
+
+    @Test
+    public void testRatesForLoans() {
+
+        // Retrieving all Rates
+        ArrayList<HashMap> allRatesData = RatesHelper.getRates(this.requestSpec, this.responseSpec);
+        Assert.assertNotNull(allRatesData);
+
+        // Testing Creation and Update of Loan Rate
+        final Integer loanRateId = RatesHelper.createRates(this.requestSpec, this.responseSpec,
+                RatesHelper.getLoanRateJSON());
+        Assert.assertNotNull(loanRateId);
+
+        //Update Rate percentage
+        HashMap changes = RatesHelper.updateRates(this.requestSpec, this.responseSpec, loanRateId,
+                RatesHelper.getModifyRateJSON());
+
+        HashMap rateDataAfterChanges = RatesHelper.getRateById(this.requestSpec, this.responseSpec, loanRateId);
+        Assert.assertEquals("Verifying Rate after modification", rateDataAfterChanges.get("percentage"), changes.get("percentage"));
+
+    }
+
+   
+}
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/rates/RatesHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/rates/RatesHelper.java
new file mode 100644
index 0000000..43fd0d7
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/rates/RatesHelper.java
@@ -0,0 +1,91 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.integrationtests.common.rates;
+
+import com.google.gson.Gson;
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+import org.apache.fineract.integrationtests.common.CommonConstants;
+import org.apache.fineract.integrationtests.common.Utils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+@SuppressWarnings({ "rawtypes", "unchecked" })
+public class RatesHelper {
+
+    private static final String RATES_URL = "/fineract-provider/api/v1/rates";
+    private static final String CREATE_RATES_URL = RATES_URL + "?" + Utils.TENANT_IDENTIFIER;
+    private final static String PERCENTAGE = "10";
+    private final static Integer PRODUCT_APPLY_LOAN = 1;
+    private final static Boolean ACTIVE = true;
+
+    public static ArrayList<HashMap> getRates(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) {
+        return (ArrayList) Utils.performServerGet(requestSpec, responseSpec, RATES_URL + "?" + Utils.TENANT_IDENTIFIER, "");
+    }
+
+
+    public static Integer createRates(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
+                                      final String request) {
+        return Utils.performServerPost(requestSpec, responseSpec, CREATE_RATES_URL, request, "resourceId");
+    }
+
+    public static HashMap getRateById(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
+                                      final Integer rateId) {
+        return Utils.performServerGet(requestSpec, responseSpec, RATES_URL + "/" + rateId + "?" + Utils.TENANT_IDENTIFIER, "");
+    }
+
+    public static HashMap updateRates(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
+                                      final Integer rateId, final String request) {
+        return Utils.performServerPut(requestSpec, responseSpec, RATES_URL + "/" + rateId + "?" + Utils.TENANT_IDENTIFIER, request,
+                CommonConstants.RESPONSE_CHANGES);
+    }
+
+    public static String getLoanRateJSON() {
+        return getLoanRateJSON(RatesHelper.PRODUCT_APPLY_LOAN, RatesHelper.PERCENTAGE);
+    }
+
+    public static String getLoanRateJSON(final Integer productApply, final String percentage) {
+        final HashMap<String, Object> map = populateDefaultsForLoan();
+        map.put("percentage", percentage);
+        map.put("productApply", productApply);
+        String crateRateJSON = new Gson().toJson(map);
+        return crateRateJSON;
+    }
+
+    public static HashMap<String, Object> populateDefaultsForLoan() {
+        final HashMap<String, Object> map = new HashMap<>();
+        map.put("active", RatesHelper.ACTIVE);
+        map.put("percentage", RatesHelper.PERCENTAGE);
+        map.put("locale", "en");
+        map.put("productApply", RatesHelper.PRODUCT_APPLY_LOAN);
+        map.put("name", Utils.randomNameGenerator("Rate_Loans_", 6));
+        return map;
+    }
+
+    public static String getModifyRateJSON() {
+        final HashMap<String, Object> map = new HashMap<>();
+        map.put("percentage", "15.0");
+        map.put("locale", "en");
+        String json = new Gson().toJson(map);
+        return json;
+    }
+
+}
+
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/data/RateData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/data/RateData.java
index d60c8dd..e249a1f 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/data/RateData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/data/RateData.java
@@ -19,6 +19,8 @@
 
 package org.apache.fineract.portfolio.rate.data;
 
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+
 import java.io.Serializable;
 import java.math.BigDecimal;
 
@@ -33,17 +35,17 @@ public class RateData implements Serializable {
 
   private BigDecimal percentage;
 
-  private String productApply;
+  private EnumOptionData productApply;
 
   private boolean active;
 
   public static RateData instance(final Long id, final String name, final BigDecimal percentage,
-      final String productApply, final boolean active) {
+      final EnumOptionData productApply, final boolean active) {
     return new RateData(id, name, percentage, productApply, active);
   }
 
   private RateData(final Long id, final String name, final BigDecimal percentage,
-      final String productApply, final boolean active) {
+      final EnumOptionData productApply, final boolean active) {
     this.id = id;
     this.name = name;
     this.percentage = percentage;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/domain/Rate.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/domain/Rate.java
index 3d0803b..ad808f4 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/domain/Rate.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/domain/Rate.java
@@ -19,11 +19,18 @@
 
 package org.apache.fineract.portfolio.rate.domain;
 
+import java.util.ArrayList;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 import org.apache.commons.lang.StringUtils;
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.ApiParameterError;
+import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
+import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
+import org.apache.fineract.portfolio.charge.exception.ChargeParameterUpdateNotSupportedException;
 import org.apache.fineract.useradministration.domain.AppUser;
+import org.apache.fineract.portfolio.rate.domain.RateAppliesTo;
 
 import javax.persistence.*;
 import java.math.BigDecimal;
@@ -45,7 +52,7 @@ public class Rate extends AbstractAuditableCustom<AppUser, Long> {
   private BigDecimal percentage;
 
   @Column(name = "product_apply", length = 100)
-  private String productApply;
+  private Integer productApply;
 
   @Column(name = "active", nullable = false)
   private boolean active;
@@ -59,19 +66,19 @@ public class Rate extends AbstractAuditableCustom<AppUser, Long> {
   }
 
 
-  public Rate(String name, BigDecimal percentage, String productApply, boolean active,
+  public Rate(String name, BigDecimal percentage, RateAppliesTo productApply, boolean active,
       AppUser approveUser) {
     this.name = name;
     this.percentage = percentage;
-    this.productApply = productApply;
+    this.productApply = productApply.getValue();
     this.active = active;
     this.approveUser = approveUser;
   }
 
-  public Rate(String name, BigDecimal percentage, String productApply, boolean active) {
+  public Rate(String name, BigDecimal percentage, RateAppliesTo productApply, boolean active) {
     this.name = name;
     this.percentage = percentage;
-    this.productApply = productApply;
+    this.productApply = productApply.getValue();
     this.active = active;
   }
 
@@ -107,11 +114,11 @@ public class Rate extends AbstractAuditableCustom<AppUser, Long> {
     this.approveUser = approveUser;
   }
 
-  public String getProductApply() {
+  public Integer getProductApply() {
     return productApply;
   }
 
-  public void setProductApply(String productApply) {
+  public void setProductApply(Integer productApply) {
     this.productApply = productApply;
   }
 
@@ -126,7 +133,7 @@ public class Rate extends AbstractAuditableCustom<AppUser, Long> {
         '}';
   }
 
-  public static Rate from(String name, BigDecimal percentage, String productApply, Boolean active) {
+  public static Rate from(String name, BigDecimal percentage, RateAppliesTo productApply, Boolean active) {
     return new Rate(name, percentage, productApply, active);
   }
 
@@ -136,8 +143,8 @@ public class Rate extends AbstractAuditableCustom<AppUser, Long> {
 
     final BigDecimal percentage = command.bigDecimalValueOfParameterNamed("percentage");
 
-    final String productApply = command.stringValueOfParameterNamed("productApply");
-
+    final RateAppliesTo productApply = RateAppliesTo.fromInt(command.integerValueOfParameterNamed("productApply"));
+    
     final boolean active = command.booleanPrimitiveValueOfParameterNamed("active");
 
     return new Rate(name, percentage, productApply, active, user);
@@ -162,10 +169,9 @@ public class Rate extends AbstractAuditableCustom<AppUser, Long> {
     }
 
     final String productApplyParamName = "productApply";
-    if (command.isChangeInStringParameterNamed(productApplyParamName, this.productApply)) {
-      final String newValue = command.stringValueOfParameterNamed(productApplyParamName);
-      actualChanges.put(productApplyParamName, newValue);
-      this.productApply = StringUtils.defaultIfEmpty(newValue, null);
+    if (command.isChangeInIntegerParameterNamed(productApplyParamName, this.productApply)) {
+      final String errorMessage = "Update of Rate applies to is not supported";
+      throw new ChargeParameterUpdateNotSupportedException("rate.applies.to", errorMessage);
     }
 
     final String activeParamName = "active";
@@ -192,7 +198,7 @@ public class Rate extends AbstractAuditableCustom<AppUser, Long> {
     return approveUserId;
   }
 
-  public void assembleFrom(String name, BigDecimal percentage, String productApply, boolean active){
+  public void assembleFrom(String name, BigDecimal percentage, Integer productApply, boolean active){
     this.name = name;
     this.percentage = percentage;
     this.productApply = productApply;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/domain/RateAppliesTo.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/domain/RateAppliesTo.java
new file mode 100644
index 0000000..684e142
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/domain/RateAppliesTo.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+ 
+ package org.apache.fineract.portfolio.rate.domain;
+
+public enum RateAppliesTo {
+
+    INVALID(0, "rateAppliesTo.invalid"), 
+    LOAN(1, "rateAppliesTo.loan");
+    
+    private final Integer value;
+    private final String code;
+
+    private RateAppliesTo(final Integer value, final String code) {
+        this.value = value;
+        this.code = code;
+    }
+
+    public Integer getValue() {
+        return this.value;
+    }
+
+    public String getCode() {
+        return this.code;
+    }
+
+    public static RateAppliesTo fromInt(final Integer rateAppliesTo) {
+        RateAppliesTo rateAppliesToType = RateAppliesTo.INVALID;
+
+        if (rateAppliesTo != null) {
+            switch (rateAppliesTo) {
+                case 1:
+                    rateAppliesToType = LOAN;
+                break;
+                default:
+                    rateAppliesToType = INVALID;
+                break;
+            }
+        }
+
+        return rateAppliesToType;
+    }
+
+    public boolean isLoanRate() {
+        return this.value.equals(RateAppliesTo.LOAN.getValue());
+    }
+    public static Object[] validValues() {
+        return new Object[] { RateAppliesTo.LOAN.getValue() };
+    }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/service/RateEnumerations.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/service/RateEnumerations.java
new file mode 100644
index 0000000..a1d79a8
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/service/RateEnumerations.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fineract.portfolio.rate.service;
+
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.portfolio.rate.domain.RateAppliesTo;
+
+public class RateEnumerations {
+
+    public static EnumOptionData rateAppliesTo(final int id) {
+        return rateAppliesTo(RateAppliesTo.fromInt(id));
+    }
+
+    public static EnumOptionData rateAppliesTo(final RateAppliesTo type) {
+        EnumOptionData optionData = null;
+        switch (type) {
+            case LOAN:
+                optionData = new EnumOptionData(RateAppliesTo.LOAN.getValue().longValue(), RateAppliesTo.LOAN.getCode(), "Loan");
+                break;
+            default:
+                optionData = new EnumOptionData(RateAppliesTo.INVALID.getValue().longValue(), RateAppliesTo.INVALID.getCode(),
+                        "Invalid");
+                break;
+        }
+        return optionData;
+    }
+
+ 
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/service/RateReadServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/service/RateReadServiceImpl.java
index 44682de..f3e5e4f 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/service/RateReadServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/rate/service/RateReadServiceImpl.java
@@ -19,8 +19,11 @@
 
 package org.apache.fineract.portfolio.rate.service;
 
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
 import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
 import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.apache.fineract.portfolio.charge.service.ChargeEnumerations;
+import org.apache.fineract.portfolio.rate.domain.RateAppliesTo;
 import org.apache.fineract.portfolio.rate.exception.RateNotFoundException;
 import org.apache.fineract.portfolio.rate.domain.Rate;
 import org.apache.fineract.portfolio.rate.data.RateData;
@@ -92,7 +95,7 @@ public class RateReadServiceImpl implements RateReadService {
     this.context.authenticatedUser();
     final RateMapper rm = new RateMapper();
     final String sql = "select " + rm.rateSchema() + " where r.active = ? and product_apply=?";
-    return this.jdbcTemplate.query(sql, rm, new Object[]{true, "m_loan"});
+    return this.jdbcTemplate.query(sql, rm, new Object[]{true, RateAppliesTo.LOAN.getValue() });
   }
 
   @Override
@@ -133,16 +136,17 @@ public class RateReadServiceImpl implements RateReadService {
       final Long id = resultSet.getLong("id");
       final String name = resultSet.getString("name");
       final BigDecimal percentage = resultSet.getBigDecimal("percentage");
-      final String productApply = resultSet.getString("productApply");
+      final Integer productApply = resultSet.getInt("productApply");
+      final EnumOptionData productAppliesTo = RateEnumerations.rateAppliesTo(productApply);
       final boolean active = resultSet.getBoolean("active");
-      return RateData.instance(id, name, percentage, productApply, active);
+      return RateData.instance(id, name, percentage, productAppliesTo, active);
     }
 
     public RateData mapRow(Rate rateResponse, int i) {
       final Long id = rateResponse.getId();
       final String name = rateResponse.getName();
       final BigDecimal percentage = rateResponse.getPercentage();
-      final String productApply = rateResponse.getProductApply();
+      final EnumOptionData productApply = RateEnumerations.rateAppliesTo(rateResponse.getProductApply());;
       final boolean active = rateResponse.isActive();
       return RateData.instance(id, name, percentage, productApply, active);
     }
diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V352__rates.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V352__rates.sql
index 1ca0986..37fe62f 100644
--- a/fineract-provider/src/main/resources/sql/migrations/core_db/V352__rates.sql
+++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V352__rates.sql
@@ -22,7 +22,7 @@ CREATE TABLE IF NOT EXISTS `m_rate` (
   `name` varchar(250) NOT NULL,
   `percentage` decimal(10,2) NOT NULL,
   `active` tinyint(1) DEFAULT '0',
-  `product_apply` varchar(100) NOT NULL,
+  `product_apply` smallint(5) NOT NULL,
   `created_date` datetime NULL DEFAULT NULL,
   `createdby_id` bigint(20) NOT NULL,
   `lastmodifiedby_id` bigint(20) NOT NULL,
@@ -63,5 +63,4 @@ INSERT INTO `m_permission`
 
 INSERT INTO `c_configuration`
 (`name`, `value`, `enabled`, `is_trap_door`, `description`) VALUES
-('vat-tax', 12, 0, 0, 'VAT tax'),
 ('sub-rates', 12, 0, 0, 'Enable Rates Module');;