You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by pt...@apache.org on 2022/01/05 22:29:42 UTC

[fineract] branch develop updated: FINERACT-1375:ClientPersonEntity

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

ptuomola 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 4a40485  FINERACT-1375:ClientPersonEntity
4a40485 is described below

commit 4a4048561ec43c5224fbbd29e464b35c98edc9e8
Author: rrpawar96 <rr...@gmail.com>
AuthorDate: Wed Dec 29 22:57:45 2021 +0530

    FINERACT-1375:ClientPersonEntity
---
 .../DatatableCommandFromApiJsonDeserializer.java   | 15 +++++++-
 .../dataqueries/data/DatatableData.java            |  9 +++--
 .../service/ReadWriteNonCoreDataService.java       |  2 +-
 .../service/ReadWriteNonCoreDataServiceImpl.java   | 43 ++++++++++++++--------
 .../survey/service/ReadSurveyServiceImpl.java      | 14 ++++---
 .../client/api/ClientsApiResourceSwagger.java      |  2 +
 .../portfolio/client/data/ClientDataValidator.java | 11 ++----
 ...V324_1__add_entity_subtype_registered_table.sql | 20 ++++++++++
 .../importhandler/loan/LoanImportHandlerTest.java  |  3 +-
 .../savings/SavingsImportHandlerTest.java          |  3 +-
 .../integrationtests/client/ClientTest.java        |  4 +-
 .../integrationtests/common/BatchHelper.java       |  9 +++--
 .../integrationtests/common/ClientHelper.java      | 11 ++++--
 .../common/system/DatatableHelper.java             |  1 +
 14 files changed, 101 insertions(+), 46 deletions(-)

diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/serialization/DatatableCommandFromApiJsonDeserializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/serialization/DatatableCommandFromApiJsonDeserializer.java
index f74a537..3e4579c 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/serialization/DatatableCommandFromApiJsonDeserializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/serialization/DatatableCommandFromApiJsonDeserializer.java
@@ -46,11 +46,11 @@ public class DatatableCommandFromApiJsonDeserializer {
      * The parameters supported for this command.
      */
     private final Set<String> supportedParametersForCreate = new HashSet<>(
-            Arrays.asList("datatableName", "apptableName", "multiRow", "columns"));
+            Arrays.asList("datatableName", "entitySubType", "apptableName", "multiRow", "columns"));
     private final Set<String> supportedParametersForCreateColumns = new HashSet<>(
             Arrays.asList("name", "type", "length", "mandatory", "code"));
     private final Set<String> supportedParametersForUpdate = new HashSet<>(
-            Arrays.asList("apptableName", "changeColumns", "addColumns", "dropColumns"));
+            Arrays.asList("apptableName", "entitySubType", "changeColumns", "addColumns", "dropColumns"));
     private final Set<String> supportedParametersForAddColumns = new HashSet<>(
             Arrays.asList("name", "type", "length", "mandatory", "after", "code"));
     private final Set<String> supportedParametersForChangeColumns = new HashSet<>(
@@ -122,6 +122,11 @@ public class DatatableCommandFromApiJsonDeserializer {
         final String apptableName = this.fromApiJsonHelper.extractStringNamed("apptableName", element);
         baseDataValidator.reset().parameter("apptableName").value(apptableName).notBlank().notExceedingLengthOf(50)
                 .isOneOfTheseValues(this.supportedApptableNames);
+
+        if ("m_client".equals(apptableName)) {
+            String entitySubType = this.fromApiJsonHelper.extractStringNamed("entitySubType", element);
+            baseDataValidator.reset().parameter("entitySubType").value(entitySubType).notBlank(); // Person or Entity
+        }
         final String fkColumnName = (apptableName != null) ? apptableName.substring(2) + "_id" : "";
 
         final Boolean multiRow = this.fromApiJsonHelper.extractBooleanNamed("multiRow", element);
@@ -171,6 +176,12 @@ public class DatatableCommandFromApiJsonDeserializer {
         final String apptableName = this.fromApiJsonHelper.extractStringNamed("apptableName", element);
         baseDataValidator.reset().parameter("apptableName").value(apptableName).ignoreIfNull().notBlank()
                 .isOneOfTheseValues(this.supportedApptableNames);
+
+        if ("m_client".equals(apptableName)) {
+            String entitySubType = this.fromApiJsonHelper.extractStringNamed("entitySubType", element);
+            baseDataValidator.reset().parameter("entitySubType").value(entitySubType).notBlank(); // Person or Entity
+        }
+
         final String fkColumnName = (apptableName != null) ? apptableName.substring(2) + "_id" : "";
 
         final JsonArray changeColumns = this.fromApiJsonHelper.extractJsonArrayNamed("changeColumns", element);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/data/DatatableData.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/data/DatatableData.java
index fb149ce..8e22cbb 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/data/DatatableData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/data/DatatableData.java
@@ -31,17 +31,20 @@ public final class DatatableData implements Serializable {
     @SuppressWarnings("unused")
     private final String registeredTableName;
     @SuppressWarnings("unused")
+    private final String entitySubType;
+    @SuppressWarnings("unused")
     private final List<ResultsetColumnHeaderData> columnHeaderData;
 
-    public static DatatableData create(final String applicationTableName, final String registeredTableName,
+    public static DatatableData create(final String applicationTableName, final String registeredTableName, final String entitySubType,
             final List<ResultsetColumnHeaderData> columnHeaderData) {
-        return new DatatableData(applicationTableName, registeredTableName, columnHeaderData);
+        return new DatatableData(applicationTableName, registeredTableName, entitySubType, columnHeaderData);
     }
 
-    private DatatableData(final String applicationTableName, final String registeredTableName,
+    private DatatableData(final String applicationTableName, final String registeredTableName, final String entitySubType,
             final List<ResultsetColumnHeaderData> columnHeaderData) {
         this.applicationTableName = applicationTableName;
         this.registeredTableName = registeredTableName;
+        this.entitySubType = entitySubType;
         this.columnHeaderData = columnHeaderData;
 
     }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataService.java
index f348b38..079982b 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataService.java
@@ -35,7 +35,7 @@ public interface ReadWriteNonCoreDataService {
     void registerDatatable(JsonCommand command);
 
     @PreAuthorize(value = "hasAnyAuthority('ALL_FUNCTIONS', 'REGISTER_DATATABLE')")
-    void registerDatatable(String dataTableName, String applicationTableName);
+    void registerDatatable(String dataTableName, String applicationTableName, String entitySubType);
 
     @PreAuthorize(value = "hasAnyAuthority('ALL_FUNCTIONS', 'REGISTER_DATATABLE')")
     void registerDatatable(JsonCommand command, String permissionTable);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java
index 4a43db0..fcf6e58 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java
@@ -149,8 +149,8 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
         }
 
         // PERMITTED datatables
-        final String sql = "select application_table_name, registered_table_name" + " from x_registered_table " + " where exists"
-                + " (select 'f'" + " from m_appuser_role ur " + " join m_role r on r.id = ur.role_id"
+        final String sql = "select application_table_name, registered_table_name, entity_subtype " + " from x_registered_table "
+                + " where exists" + " (select 'f'" + " from m_appuser_role ur " + " join m_role r on r.id = ur.role_id"
                 + " left join m_role_permission rp on rp.role_id = r.id" + " left join m_permission p on p.id = rp.permission_id"
                 + " where ur.appuser_id = " + this.context.authenticatedUser().getId()
                 + " and (p.code in ('ALL_FUNCTIONS', 'ALL_FUNCTIONS_READ') or p.code = concat('READ_', registered_table_name))) "
@@ -162,10 +162,11 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
         while (rs.next()) {
             final String appTableName = rs.getString("application_table_name");
             final String registeredDatatableName = rs.getString("registered_table_name");
+            final String entitySubType = rs.getString("entity_subtype");
             final List<ResultsetColumnHeaderData> columnHeaderData = this.genericDataService
                     .fillResultsetColumnHeaders(registeredDatatableName);
 
-            datatables.add(DatatableData.create(appTableName, registeredDatatableName, columnHeaderData));
+            datatables.add(DatatableData.create(appTableName, registeredDatatableName, entitySubType, columnHeaderData));
         }
 
         return datatables;
@@ -176,8 +177,8 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
 
         // PERMITTED datatables
         SQLInjectionValidator.validateSQLInput(datatable);
-        final String sql = "select application_table_name, registered_table_name" + " from x_registered_table " + " where exists"
-                + " (select 'f'" + " from m_appuser_role ur " + " join m_role r on r.id = ur.role_id"
+        final String sql = "select application_table_name, registered_table_name, entity_subtype" + " from x_registered_table "
+                + " where exists" + " (select 'f'" + " from m_appuser_role ur " + " join m_role r on r.id = ur.role_id"
                 + " left join m_role_permission rp on rp.role_id = r.id" + " left join m_permission p on p.id = rp.permission_id"
                 + " where ur.appuser_id = " + this.context.authenticatedUser().getId() + " and registered_table_name='" + datatable + "'"
                 + " and (p.code in ('ALL_FUNCTIONS', 'ALL_FUNCTIONS_READ') or p.code = concat('READ_', registered_table_name))) "
@@ -189,10 +190,11 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
         while (rs.next()) {
             final String appTableName = rs.getString("application_table_name");
             final String registeredDatatableName = rs.getString("registered_table_name");
+            final String entitySubType = rs.getString("entity_subtype");
             final List<ResultsetColumnHeaderData> columnHeaderData = this.genericDataService
                     .fillResultsetColumnHeaders(registeredDatatableName);
 
-            datatableData = DatatableData.create(appTableName, registeredDatatableName, columnHeaderData);
+            datatableData = DatatableData.create(appTableName, registeredDatatableName, entitySubType, columnHeaderData);
         }
 
         return datatableData;
@@ -204,12 +206,12 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
 
     @Transactional
     @Override
-    public void registerDatatable(final String dataTableName, final String applicationTableName) {
+    public void registerDatatable(final String dataTableName, final String applicationTableName, final String entitySubType) {
 
         Integer category = DataTableApiConstant.CATEGORY_DEFAULT;
 
         final String permissionSql = this.getPermissionSql(dataTableName);
-        this.registerDataTable(applicationTableName, dataTableName, category, permissionSql);
+        this.registerDataTable(applicationTableName, dataTableName, entitySubType, category, permissionSql);
 
     }
 
@@ -219,12 +221,13 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
 
         final String applicationTableName = this.getTableName(command.getUrl());
         final String dataTableName = this.getDataTableName(command.getUrl());
+        final String entitySubType = command.stringValueOfParameterNamed("entitySubType");
 
         Integer category = this.getCategory(command);
 
         this.dataTableValidator.validateDataTableRegistration(command.json());
         final String permissionSql = this.getPermissionSql(dataTableName);
-        this.registerDataTable(applicationTableName, dataTableName, category, permissionSql);
+        this.registerDataTable(applicationTableName, dataTableName, entitySubType, category, permissionSql);
 
     }
 
@@ -233,27 +236,29 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
     public void registerDatatable(final JsonCommand command, final String permissionSql) {
         final String applicationTableName = this.getTableName(command.getUrl());
         final String dataTableName = this.getDataTableName(command.getUrl());
+        final String entitySubType = command.stringValueOfParameterNamed("entitySubType");
 
         Integer category = this.getCategory(command);
 
         this.dataTableValidator.validateDataTableRegistration(command.json());
 
-        this.registerDataTable(applicationTableName, dataTableName, category, permissionSql);
+        this.registerDataTable(applicationTableName, dataTableName, entitySubType, category, permissionSql);
 
     }
 
     @Transactional
-    private void registerDataTable(final String applicationTableName, final String dataTableName, final Integer category,
-            final String permissionsSql) {
+    private void registerDataTable(final String applicationTableName, final String dataTableName, final String entitySubType,
+            final Integer category, final String permissionsSql) {
 
         validateAppTable(applicationTableName);
         validateDatatableName(dataTableName);
         assertDataTableExists(dataTableName);
 
         Map<String, Object> paramMap = new HashMap<>(3);
-        final String registerDatatableSql = "insert into x_registered_table (registered_table_name, application_table_name,category) values ( :dataTableName, :applicationTableName, :category)";
+        final String registerDatatableSql = "insert into x_registered_table (registered_table_name, application_table_name, entity_subtype, category) values ( :dataTableName, :applicationTableName, :entitySubType ,:category)";
         paramMap.put("dataTableName", dataTableName);
         paramMap.put("applicationTableName", applicationTableName);
+        paramMap.put("entitySubType", entitySubType);
         paramMap.put("category", category);
 
         try {
@@ -568,6 +573,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
             final JsonElement element = this.fromJsonHelper.parse(command.json());
             final JsonArray columns = this.fromJsonHelper.extractJsonArrayNamed("columns", element);
             datatableName = this.fromJsonHelper.extractStringNamed("datatableName", element);
+            String entitySubType = this.fromJsonHelper.extractStringNamed("entitySubType", element);
             final String apptableName = this.fromJsonHelper.extractStringNamed("apptableName", element);
             Boolean multiRow = this.fromJsonHelper.extractBooleanNamed("multiRow", element);
 
@@ -623,7 +629,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
             sqlBuilder = sqlBuilder.append(") ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4;");
             this.jdbcTemplate.execute(sqlBuilder.toString());
 
-            registerDatatable(datatableName, apptableName);
+            registerDatatable(datatableName, apptableName, entitySubType);
             registerColumnCodeMapping(codeMappings);
         } catch (final JpaSystemException | DataIntegrityViolationException e) {
             final Throwable realCause = e.getCause();
@@ -888,6 +894,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
             final JsonArray addColumns = this.fromJsonHelper.extractJsonArrayNamed("addColumns", element);
             final JsonArray dropColumns = this.fromJsonHelper.extractJsonArrayNamed("dropColumns", element);
             final String apptableName = this.fromJsonHelper.extractStringNamed("apptableName", element);
+            final String entitySubType = this.fromJsonHelper.extractStringNamed("entitySubType", element);
 
             validateDatatableName(datatableName);
             int rowCount = getRowCount(datatableName);
@@ -899,6 +906,12 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
 
             final boolean isConstraintApproach = this.configurationDomainService.isConstraintApproachEnabledForDatatables();
 
+            if (!StringUtils.isBlank(entitySubType)) {
+                String updateLegalFormSQL = "update `x_registered_table` SET `entity_subtype`='" + entitySubType
+                        + "' WHERE registered_table_name = '" + datatableName + "'";
+                this.jdbcTemplate.execute(updateLegalFormSQL);
+            }
+
             if (!StringUtils.isBlank(apptableName)) {
                 validateAppTable(apptableName);
 
@@ -929,7 +942,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
                     this.jdbcTemplate.execute(sqlBuilder.toString());
 
                     deregisterDatatable(datatableName);
-                    registerDatatable(datatableName, apptableName);
+                    registerDatatable(datatableName, apptableName, entitySubType);
                 }
             }
 
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/survey/service/ReadSurveyServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/survey/service/ReadSurveyServiceImpl.java
index 9ade315..ddd7c66 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/survey/service/ReadSurveyServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/survey/service/ReadSurveyServiceImpl.java
@@ -72,12 +72,13 @@ public class ReadSurveyServiceImpl implements ReadSurveyService {
         while (rs.next()) {
             final String appTableName = rs.getString("application_table_name");
             final String registeredDatatableName = rs.getString("registered_table_name");
+            final String entitySubType = rs.getString("entity_subtype");
             final boolean enabled = rs.getBoolean("enabled");
             final List<ResultsetColumnHeaderData> columnHeaderData = this.genericDataService
                     .fillResultsetColumnHeaders(registeredDatatableName);
 
-            surveyDataTables.add(
-                    SurveyDataTableData.create(DatatableData.create(appTableName, registeredDatatableName, columnHeaderData), enabled));
+            surveyDataTables.add(SurveyDataTableData
+                    .create(DatatableData.create(appTableName, registeredDatatableName, entitySubType, columnHeaderData), enabled));
         }
 
         return surveyDataTables;
@@ -85,7 +86,7 @@ public class ReadSurveyServiceImpl implements ReadSurveyService {
 
     private String retrieveAllSurveySQL(String andClause) {
         // PERMITTED datatables
-        return "select application_table_name, cf.enabled, registered_table_name" + " from x_registered_table "
+        return "select application_table_name, cf.enabled, registered_table_name, entity_subtype" + " from x_registered_table "
                 + " left join c_configuration cf on x_registered_table.registered_table_name = cf.name " + " where exists" + " (select 'f'"
                 + " from m_appuser_role ur " + " join m_role r on r.id = ur.role_id"
                 + " left join m_role_permission rp on rp.role_id = r.id" + " left join m_permission p on p.id = rp.permission_id"
@@ -98,7 +99,7 @@ public class ReadSurveyServiceImpl implements ReadSurveyService {
     @Override
     public SurveyDataTableData retrieveSurvey(String surveyName) {
         SQLInjectionValidator.validateSQLInput(surveyName);
-        final String sql = "select cf.enabled, application_table_name, registered_table_name" + " from x_registered_table "
+        final String sql = "select cf.enabled, application_table_name, registered_table_name, entity_subtype" + " from x_registered_table "
                 + " left join c_configuration cf on x_registered_table.registered_table_name = cf.name " + " where exists" + " (select 'f'"
                 + " from m_appuser_role ur " + " join m_role r on r.id = ur.role_id"
                 + " left join m_role_permission rp on rp.role_id = r.id" + " left join m_permission p on p.id = rp.permission_id"
@@ -112,12 +113,13 @@ public class ReadSurveyServiceImpl implements ReadSurveyService {
         while (rs.next()) {
             final String appTableName = rs.getString("application_table_name");
             final String registeredDatatableName = rs.getString("registered_table_name");
+            final String entitySubType = rs.getString("entity_subtype");
             final boolean enabled = rs.getBoolean("enabled");
             final List<ResultsetColumnHeaderData> columnHeaderData = this.genericDataService
                     .fillResultsetColumnHeaders(registeredDatatableName);
 
-            datatableData = SurveyDataTableData.create(DatatableData.create(appTableName, registeredDatatableName, columnHeaderData),
-                    enabled);
+            datatableData = SurveyDataTableData
+                    .create(DatatableData.create(appTableName, registeredDatatableName, entitySubType, columnHeaderData), enabled);
 
         }
 
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResourceSwagger.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResourceSwagger.java
index 02d6111..1101588 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResourceSwagger.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResourceSwagger.java
@@ -268,6 +268,8 @@ final class ClientsApiResourceSwagger {
 
         @Schema(example = "1")
         public Integer officeId;
+        @Schema(example = "1")
+        public Integer legalFormId;
         @Schema(example = "Client of group")
         public String fullname;
         @Schema(example = "1")
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientDataValidator.java
index a1ce47b..46d98aa 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientDataValidator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientDataValidator.java
@@ -211,12 +211,8 @@ public final class ClientDataValidator {
                     .integerGreaterThanZero();
         }
 
-        if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.legalFormIdParamName, element)) {
-            final Integer legalFormId = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(ClientApiConstants.legalFormIdParamName,
-                    element);
-            baseDataValidator.reset().parameter(ClientApiConstants.legalFormIdParamName).value(legalFormId).ignoreIfNull().inMinMaxRange(1,
-                    2);
-        }
+        final Integer legalFormId = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(ClientApiConstants.legalFormIdParamName, element);
+        baseDataValidator.reset().parameter(ClientApiConstants.legalFormIdParamName).value(legalFormId).notNull().inMinMaxRange(1, 2);
 
         if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.datatables, element)) {
             final JsonArray datatables = this.fromApiJsonHelper.extractJsonArrayNamed(ClientApiConstants.datatables, element);
@@ -508,8 +504,7 @@ public final class ClientDataValidator {
             atLeastOneParameterPassedForUpdate = true;
             final Integer legalFormId = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(ClientApiConstants.legalFormIdParamName,
                     element);
-            baseDataValidator.reset().parameter(ClientApiConstants.legalFormIdParamName).value(legalFormId).ignoreIfNull().inMinMaxRange(1,
-                    2);
+            baseDataValidator.reset().parameter(ClientApiConstants.legalFormIdParamName).value(legalFormId).notNull().inMinMaxRange(1, 2);
         }
 
         if (this.fromApiJsonHelper.parameterExists("isStaff", element)) {
diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V324_1__add_entity_subtype_registered_table.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V324_1__add_entity_subtype_registered_table.sql
new file mode 100644
index 0000000..0867962
--- /dev/null
+++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V324_1__add_entity_subtype_registered_table.sql
@@ -0,0 +1,20 @@
+--
+-- 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.
+--
+
+ALTER TABLE `x_registered_table` ADD COLUMN `entity_subtype` VARCHAR(50) NULL AFTER `application_table_name`;
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java
index 746e40e..cd3a962 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java
@@ -99,12 +99,13 @@ public class LoanImportHandlerTest {
         String lastName = Utils.randomNameGenerator("Client_LastName_", 4);
         String externalId = Utils.randomStringGenerator("ID_", 7, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
 
-        final HashMap<String, String> clientMap = new HashMap<>();
+        final HashMap<String, Object> clientMap = new HashMap<>();
         clientMap.put("officeId", outcome_office_creation.toString());
         clientMap.put("firstname", firstName);
         clientMap.put("lastname", lastName);
         clientMap.put("externalId", externalId);
         clientMap.put("dateFormat", DATE_FORMAT);
+        clientMap.put("legalFormId", 1);
         clientMap.put("locale", "en");
         clientMap.put("active", "true");
         clientMap.put("activationDate", "04 March 2011");
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/savings/SavingsImportHandlerTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/savings/SavingsImportHandlerTest.java
index a7ff0fa..c039167 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/savings/SavingsImportHandlerTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/savings/SavingsImportHandlerTest.java
@@ -89,8 +89,9 @@ public class SavingsImportHandlerTest {
         String lastName = Utils.randomNameGenerator("Client_LastName_", 4);
         String externalId = Utils.randomStringGenerator("ID_", 7, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
 
-        final HashMap<String, String> clientMap = new HashMap<>();
+        final HashMap<String, Object> clientMap = new HashMap<>();
         clientMap.put("officeId", outcome_office_creation.toString());
+        clientMap.put("legalFormId", 1);
         clientMap.put("firstname", firstName);
         clientMap.put("lastname", lastName);
         clientMap.put("externalId", externalId);
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/ClientTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/ClientTest.java
index 5d44ff0..d33d463 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/ClientTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/ClientTest.java
@@ -55,8 +55,8 @@ public class ClientTest extends IntegrationTest {
         // TODO activationDate() why String? https://issues.apache.org/jira/browse/FINERACT-1232
         // TODO why dateFormat and locale required even when no activationDate?!
         // https://issues.apache.org/jira/browse/FINERACT-1233
-        return (long) ok(fineract().clients
-                .create6(new PostClientsRequest().officeId(1).fullname("TestClient").dateFormat(dateFormat()).locale("en_US")))
+        return (long) ok(fineract().clients.create6(
+                new PostClientsRequest().legalFormId(1).officeId(1).fullname("TestClient").dateFormat(dateFormat()).locale("en_US")))
                         .getClientId();
     }
 
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/BatchHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/BatchHelper.java
index 1a447c8..7fca25d 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/BatchHelper.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/BatchHelper.java
@@ -156,8 +156,9 @@ public final class BatchHelper {
             extId = externalId;
         }
 
-        final String body = "{ \"officeId\": 1, \"firstname\": \"Petra\", \"lastname\": \"Yton\"," + "\"externalId\": " + extId
-                + ",  \"dateFormat\": \"dd MMMM yyyy\", \"locale\": \"en\"," + "\"active\": false, \"submittedOnDate\": \"04 March 2009\"}";
+        final String body = "{ \"officeId\": 1, \"legalFormId\":1, \"firstname\": \"Petra\", \"lastname\": \"Yton\"," + "\"externalId\": "
+                + extId + ",  \"dateFormat\": \"dd MMMM yyyy\", \"locale\": \"en\","
+                + "\"active\": false, \"submittedOnDate\": \"04 March 2009\"}";
 
         br.setBody(body);
 
@@ -186,8 +187,8 @@ public final class BatchHelper {
             extId = externalId;
         }
 
-        final String body = "{ \"officeId\": 1, \"firstname\": \"Petra\", \"lastname\": \"Yton\"," + "\"externalId\": \"" + externalId
-                + "\",  \"dateFormat\": \"dd MMMM yyyy\", \"locale\": \"en\","
+        final String body = "{ \"officeId\": 1, \"legalFormId\":1, \"firstname\": \"Petra\", \"lastname\": \"Yton\"," + "\"externalId\": \""
+                + externalId + "\",  \"dateFormat\": \"dd MMMM yyyy\", \"locale\": \"en\","
                 + "\"active\": true, \"activationDate\": \"04 March 2010\", \"submittedOnDate\": \"04 March 2010\"}";
 
         br.setBody(body);
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ClientHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ClientHelper.java
index 2cc5f3f..8fce44e 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ClientHelper.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ClientHelper.java
@@ -55,6 +55,7 @@ public class ClientHelper {
     private static final String WITHDRAW_CLIENT_COMMAND = "withdraw";
     private static final String UNDOREJECT_CLIENT_COMMAND = "undoRejection";
     private static final String UNDOWITHDRAWN_CLIENT_COMMAND = "undoWithdrawal";
+    private static final Integer LEGALFORM_ID_PERSON = 1;
 
     public static final String CREATED_DATE = "27 November 2014";
     public static final String CREATED_DATE_PLUS_ONE = "28 November 2014";
@@ -181,8 +182,9 @@ public class ClientHelper {
     }
 
     public static String getTestClientAsJSON(final String dateOfJoining, final String officeId) {
-        final HashMap<String, String> map = new HashMap<>();
+        final HashMap<String, Object> map = new HashMap<>();
         map.put("officeId", officeId);
+        map.put("legalFormId", LEGALFORM_ID_PERSON);
         map.put("firstname", Utils.randomNameGenerator("Client_FirstName_", 5));
         map.put("lastname", Utils.randomNameGenerator("Client_LastName_", 4));
         map.put("externalId", randomIDGenerator("ID_", 7));
@@ -195,8 +197,9 @@ public class ClientHelper {
     }
 
     public static String getTestClientAsJSONPending(final String submittedOnDate, final String officeId) {
-        final HashMap<String, String> map = new HashMap<>();
+        final HashMap<String, Object> map = new HashMap<>();
         map.put("officeId", officeId);
+        map.put("legalFormId", LEGALFORM_ID_PERSON);
         map.put("firstname", Utils.randomNameGenerator("Client_FirstName_", 5));
         map.put("lastname", Utils.randomNameGenerator("Client_LastName_", 4));
         map.put("externalId", randomIDGenerator("ID_", 7));
@@ -211,6 +214,7 @@ public class ClientHelper {
     public static String getTestPendingClientWithDatatableAsJson(final String registeredTableName) {
         final HashMap<String, Object> map = new HashMap<>();
         map.put("officeId", "1");
+        map.put("legalFormId", LEGALFORM_ID_PERSON);
         map.put("firstname", Utils.randomNameGenerator("Client_FirstName_", 5));
         map.put("lastname", Utils.randomNameGenerator("Client_LastName_", 4));
         map.put("externalId", randomIDGenerator("ID_", 7));
@@ -276,8 +280,9 @@ public class ClientHelper {
     }
 
     public static String getTestClientWithClientTypeAsJSON(final String dateOfJoining, final String officeId, final String clientType) {
-        final HashMap<String, String> map = new HashMap<>();
+        final HashMap<String, Object> map = new HashMap<>();
         map.put("officeId", officeId);
+        map.put("legalFormId", LEGALFORM_ID_PERSON);
         map.put("firstname", Utils.randomNameGenerator("Client_FirstName_", 5));
         map.put("lastname", Utils.randomNameGenerator("Client_LastName_", 4));
         map.put("externalId", randomIDGenerator("ID_", 7));
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/system/DatatableHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/system/DatatableHelper.java
index f537f55..eb966d4 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/system/DatatableHelper.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/system/DatatableHelper.java
@@ -72,6 +72,7 @@ public class DatatableHelper {
         final List<HashMap<String, Object>> datatableColumnsList = new ArrayList<>();
         map.put("datatableName", Utils.randomNameGenerator(apptableName + "_", 5));
         map.put("apptableName", apptableName);
+        map.put("entitySubType", "PERSON");
         map.put("multiRow", multiRow);
         addDatatableColumns(datatableColumnsList, "Spouse Name", "String", true, 25);
         addDatatableColumns(datatableColumnsList, "Number of Dependents", "Number", true, null);