http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/dde6eaec/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/EntityDatatableChecksWritePlatformServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/EntityDatatableChecksWritePlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/EntityDatatableChecksWritePlatformServiceImpl.java
new file mode 100644
index 0000000..34f1312
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/EntityDatatableChecksWritePlatformServiceImpl.java
@@ -0,0 +1,315 @@
+/**
+ * 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.infrastructure.dataqueries.service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.PersistenceException;
+
+import org.apache.commons.lang.exception.ExceptionUtils;
+import 
org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.ApiParameterError;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import 
org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
+import 
org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
+import 
org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
+import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
+import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
+import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
+import 
org.apache.fineract.infrastructure.dataqueries.domain.EntityDatatableChecks;
+import 
org.apache.fineract.infrastructure.dataqueries.domain.EntityDatatableChecksRepository;
+import org.apache.fineract.infrastructure.dataqueries.exception.*;
+import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import 
org.apache.fineract.portfolio.loanproduct.service.LoanProductReadPlatformService;
+import 
org.apache.fineract.portfolio.savings.service.SavingsProductReadPlatformService;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataAccessException;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+@Service
+public class EntityDatatableChecksWritePlatformServiceImpl implements 
EntityDatatableChecksWritePlatformService {
+
+       private final static Logger logger = 
LoggerFactory.getLogger(EntityDatatableChecksWritePlatformServiceImpl.class);
+
+       private final PlatformSecurityContext context;
+       private final EntityDatatableChecksDataValidator 
fromApiJsonDeserializer;
+       private final EntityDatatableChecksRepository 
entityDatatableChecksRepository;
+       private final ReadWriteNonCoreDataService readWriteNonCoreDataService;
+       private final LoanProductReadPlatformService 
loanProductReadPlatformService;
+       private final SavingsProductReadPlatformService 
savingsProductReadPlatformService;
+       private final FromJsonHelper fromApiJsonHelper;
+       private final ConfigurationDomainService configurationDomainService;
+
+       @Autowired
+       public EntityDatatableChecksWritePlatformServiceImpl(final 
PlatformSecurityContext context,
+                       final EntityDatatableChecksDataValidator 
fromApiJsonDeserializer,
+                       final EntityDatatableChecksRepository 
entityDatatableChecksRepository,
+                       final ReadWriteNonCoreDataService 
readWriteNonCoreDataService,
+                       final LoanProductReadPlatformService 
loanProductReadPlatformService,
+                       final SavingsProductReadPlatformService 
savingsProductReadPlatformService,
+                       final FromJsonHelper fromApiJsonHelper,
+                       final ConfigurationDomainService 
configurationDomainService) {
+               this.context = context;
+               this.fromApiJsonDeserializer = fromApiJsonDeserializer;
+               this.entityDatatableChecksRepository = 
entityDatatableChecksRepository;
+               this.readWriteNonCoreDataService = readWriteNonCoreDataService;
+               this.loanProductReadPlatformService = 
loanProductReadPlatformService;
+               this.savingsProductReadPlatformService = 
savingsProductReadPlatformService;
+               this.fromApiJsonHelper = fromApiJsonHelper;
+               this.configurationDomainService = configurationDomainService;
+       }
+
+       @Transactional
+       @Override
+       public CommandProcessingResult createCheck(final JsonCommand command) {
+
+               try {
+                       this.context.authenticatedUser();
+
+                       
this.fromApiJsonDeserializer.validateForCreate(command.json());
+
+                       // check if the datatable is linked to the entity
+
+                       String datatableName = 
command.stringValueOfParameterNamed("datatableName");
+                       DatatableData datatableData = 
this.readWriteNonCoreDataService.retrieveDatatable(datatableName);
+
+                       if (datatableData == null) {
+                               throw new 
DatatableNotFoundException(datatableName);
+                       }
+
+                       final String entity = 
command.stringValueOfParameterNamed("entity");
+                       final String foreignKeyColumnName = 
EntityTables.getForeignKeyColumnNameOnDatatable(entity);
+                       final boolean columnExist = 
datatableData.hasColumn(foreignKeyColumnName);
+
+                       logger.info(datatableData.getRegisteredTableName() + 
"has column " + foreignKeyColumnName + " ? "
+                                       + columnExist);
+
+                       if (!columnExist) {
+                               throw new 
EntityDatatableCheckNotSupportedException(datatableData.getRegisteredTableName(),
 entity);
+                       }
+
+                       final Long productId = 
command.longValueOfParameterNamed("productId");
+                       final Long status = 
command.longValueOfParameterNamed("status");
+
+
+                       List<EntityDatatableChecks> entityDatatableCheck = null;
+                       if (productId == null) {
+                               entityDatatableCheck = 
this.entityDatatableChecksRepository
+                                               
.findByEntityStatusAndDatatableIdAndNoProduct(entity, status, datatableName);
+                               if (!entityDatatableCheck.isEmpty()) {
+                                       throw new 
EntityDatatableCheckAlreadyExistsException(entity, status, datatableName);
+                               }
+                       } else {
+                               if (entity.equals("m_loan")) {
+                                       // if invalid loan product id, throws 
exception
+                                       
this.loanProductReadPlatformService.retrieveLoanProduct(productId);
+                               } else if (entity.equals("m_savings_account")) {
+                                       // if invalid savings product id, 
throws exception
+                                       
this.savingsProductReadPlatformService.retrieveOne(productId);
+                               } else {
+                                       throw new 
EntityDatatableCheckNotSupportedException(entity, productId);
+                               }
+                               entityDatatableCheck = 
this.entityDatatableChecksRepository
+                                               
.findByEntityStatusAndDatatableIdAndProductId(entity, status, datatableName, 
productId);
+                               if (!entityDatatableCheck.isEmpty()) {
+                                       throw new 
EntityDatatableCheckAlreadyExistsException(entity, status, datatableName, 
productId);
+                               }
+                       }
+
+                       final EntityDatatableChecks check = 
EntityDatatableChecks.fromJson(command);
+
+                       
this.entityDatatableChecksRepository.saveAndFlush(check);
+
+                       return new CommandProcessingResultBuilder() //
+                                       .withCommandId(command.commandId()) //
+                                       .withEntityId(check.getId()) //
+                                       .build();
+               } catch (final DataAccessException e) {
+                       handleReportDataIntegrityIssues(command, 
e.getMostSpecificCause(), e);
+                       return CommandProcessingResult.empty();
+               }catch (final PersistenceException dve) {
+                       Throwable throwable = 
ExceptionUtils.getRootCause(dve.getCause()) ;
+                       handleReportDataIntegrityIssues(command, throwable, 
dve);
+                       return CommandProcessingResult.empty();
+               }
+       }
+
+       public void runTheCheck(final Long entityId, final String entityName, 
final Long statusCode,
+                       String foreignKeyColumn) {
+               final List<EntityDatatableChecks> 
tableRequiredBeforeClientActivation = entityDatatableChecksRepository
+                               .findByEntityAndStatus(entityName, statusCode);
+
+               if (tableRequiredBeforeClientActivation != null) {
+                       List<String> reqDatatables = new ArrayList<>();
+                       for (EntityDatatableChecks t : 
tableRequiredBeforeClientActivation) {
+
+                               final String datatableName = 
t.getDatatableName();
+                               final Long countEntries = 
readWriteNonCoreDataService.countDatatableEntries(datatableName, entityId,
+                                               foreignKeyColumn);
+
+                               logger.info("The are " + countEntries + " 
entries in the table " + datatableName);
+                               if (countEntries.intValue() == 0) {
+                                       reqDatatables.add(datatableName);
+                               }
+                       }
+                       if(reqDatatables.size() > 0){
+                               throw new 
DatatabaleEntryRequiredException(reqDatatables.toString());
+                       }
+               }
+
+       }
+
+       public void runTheCheckForProduct(final Long entityId, final String 
entityName, final Long statusCode,
+                       String foreignKeyColumn, long productId) {
+               List<EntityDatatableChecks> tableRequiredBeforAction = 
entityDatatableChecksRepository
+                               .findByEntityStatusAndProduct(entityName, 
statusCode, productId);
+
+               if (tableRequiredBeforAction == null || 
tableRequiredBeforAction.size() < 1) {
+                       tableRequiredBeforAction = 
entityDatatableChecksRepository.findByEntityStatusAndNoProduct(entityName,
+                                       statusCode);
+               }
+               if (tableRequiredBeforAction != null) {
+                       List<String> reqDatatables = new ArrayList<>();
+                       for (EntityDatatableChecks t : 
tableRequiredBeforAction) {
+
+                               final String datatableName = 
t.getDatatableName();
+                               final Long countEntries = 
readWriteNonCoreDataService.countDatatableEntries(datatableName, entityId,
+                                               foreignKeyColumn);
+
+                               logger.info("The are " + countEntries + " 
entries in the table " + datatableName);
+                               if (countEntries.intValue() == 0) {
+                                       reqDatatables.add(datatableName);
+                               }
+                       }
+                       if(reqDatatables.size() > 0){
+                               throw new 
DatatabaleEntryRequiredException(reqDatatables.toString());
+                       }
+               }
+
+       }
+
+       @Transactional
+       @Override
+       public boolean saveDatatables(final Long status, final String entity, 
final Long entityId,
+               final Long productId, final JsonArray datatableDatas) {
+               final AppUser user = this.context.authenticatedUser();
+               boolean isMakerCheckerEnabled = false;
+               if(datatableDatas != null && datatableDatas.size() > 0){
+                       for(JsonElement element : datatableDatas){
+                               final String datatableName = 
this.fromApiJsonHelper.extractStringNamed("registeredTableName",element);
+                               final JsonObject datatableData = 
this.fromApiJsonHelper.extractJsonObjectNamed("data", element);
+
+                               if(datatableName == null || datatableData == 
null){
+                                       final ApiParameterError error = 
ApiParameterError.generalError("registeredTableName.and.data.parameters.must.be.present.in.each.list.items.in.datatables",
+                                               "registeredTableName and data 
parameters must be present in each list items in datatables");
+                                       List<ApiParameterError> errors = new 
ArrayList<>();
+                                       errors.add(error);
+                                       throw new 
PlatformApiDataValidationException(errors);
+                               }
+                               final String taskPermissionName = "CREATE_" + 
datatableName;
+                               
user.validateHasPermissionTo(taskPermissionName);
+                               
if(this.configurationDomainService.isMakerCheckerEnabledForTask(taskPermissionName)){
+                                       isMakerCheckerEnabled = true;
+                               }
+                               try{
+                                       
this.readWriteNonCoreDataService.createNewDatatableEntry(datatableName, 
entityId, datatableData.toString());
+                               } catch(PlatformApiDataValidationException e){
+                                       List<ApiParameterError> errors = 
e.getErrors();
+                                       for(ApiParameterError error : 
e.getErrors()){
+                                               
error.setParameterName("datatables."+datatableName+"."+error.getParameterName());
+                                       }
+                                       throw e;
+                               }
+                       }
+               }
+               return isMakerCheckerEnabled;
+       }
+
+       private List<String> getDatatableNames(Long status, String entity, Long 
productId) {
+               List<String> ret = new ArrayList<>();
+               List<EntityDatatableChecks> tableRequiredBeforeAction = null;
+               if(productId != null){
+                       tableRequiredBeforeAction = 
this.entityDatatableChecksRepository
+                               .findByEntityStatusAndProduct(entity, status, 
productId);
+               }
+
+               if (tableRequiredBeforeAction == null || 
tableRequiredBeforeAction.size() < 1) {
+                       tableRequiredBeforeAction = 
this.entityDatatableChecksRepository.findByEntityStatusAndNoProduct(entity,
+                               status);
+               }
+               if (tableRequiredBeforeAction != null && 
tableRequiredBeforeAction.size() > 0) {
+                       for (EntityDatatableChecks t : 
tableRequiredBeforeAction) {
+                               ret.add(t.getDatatableName());
+                       }
+               }
+               return ret;
+       }
+
+       @Transactional
+       @Override
+       public CommandProcessingResult deleteCheck(final Long 
entityDatatableCheckId) {
+
+               final EntityDatatableChecks check = 
this.entityDatatableChecksRepository.findOne(entityDatatableCheckId);
+               if (check == null) {
+                       throw new 
EntityDatatableChecksNotFoundException(entityDatatableCheckId);
+               }
+
+               this.entityDatatableChecksRepository.delete(check);
+
+               return new CommandProcessingResultBuilder() //
+                               .withEntityId(entityDatatableCheckId) //
+                               .build();
+       }
+
+       /*
+        * Guaranteed to throw an exception no matter what the data integrity 
issue
+        * is.
+        */
+       private void handleReportDataIntegrityIssues(final JsonCommand command, 
final Throwable realCause,  final Exception dae) {
+
+               if (realCause.getMessage().contains("FOREIGN KEY 
(`x_registered_table_name`)")) {
+                       final String datatableName = 
command.stringValueOfParameterNamed("datatableName");
+                       throw new 
PlatformDataIntegrityException("error.msg.entityDatatableCheck.foreign.key.constraint",
+                                       "datatable with name '" + datatableName 
+ "' do not exist", "datatableName", datatableName);
+               }
+
+               if (realCause.getMessage().contains("unique_entity_check")) {
+                       final String datatableName = 
command.stringValueOfParameterNamed("datatableName");
+                       final long status = 
command.longValueOfParameterNamed("status");
+                       final String entity = 
command.stringValueOfParameterNamed("entity");
+                       final long productId = 
command.longValueOfParameterNamed("productId");
+                       throw new 
EntityDatatableCheckAlreadyExistsException(entity, status, datatableName, 
productId);
+               }
+
+               logger.error(dae.getMessage(), dae);
+               throw new 
PlatformDataIntegrityException("error.msg.report.unknown.data.integrity.issue",
+                               "Unknown data integrity issue with resource: " 
+ realCause.getMessage());
+       }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/dde6eaec/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataService.java
----------------------------------------------------------------------
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 22529a3..e7f6364 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
@@ -54,6 +54,8 @@ public interface ReadWriteNonCoreDataService {
 
     CommandProcessingResult createNewDatatableEntry(String datatable, Long 
appTableId, JsonCommand command);
 
+    CommandProcessingResult createNewDatatableEntry(String datatable, Long 
appTableId, String json);
+
     CommandProcessingResult createPPIEntry(String datatable, Long appTableId, 
JsonCommand command);
 
     CommandProcessingResult updateDatatableEntryOneToOne(String datatable, 
Long appTableId, JsonCommand command);
@@ -68,4 +70,5 @@ public interface ReadWriteNonCoreDataService {
 
     String getDataTableName(String Url);
 
+    Long countDatatableEntries(String datatableName,Long appTableId,String 
foreignKeyColumn);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/dde6eaec/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java
----------------------------------------------------------------------
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 c40b949..e0a0696 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
@@ -20,13 +20,7 @@ package 
org.apache.fineract.infrastructure.dataqueries.service;
 
 import java.lang.reflect.Type;
 import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 import javax.persistence.PersistenceException;
 import javax.sql.DataSource;
@@ -50,11 +44,7 @@ import 
org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
 import org.apache.fineract.infrastructure.core.serialization.JsonParserHelper;
 import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
 import org.apache.fineract.infrastructure.dataqueries.api.DataTableApiConstant;
-import org.apache.fineract.infrastructure.dataqueries.data.DataTableValidator;
-import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
-import 
org.apache.fineract.infrastructure.dataqueries.data.GenericResultsetData;
-import 
org.apache.fineract.infrastructure.dataqueries.data.ResultsetColumnHeaderData;
-import org.apache.fineract.infrastructure.dataqueries.data.ResultsetRowData;
+import org.apache.fineract.infrastructure.dataqueries.data.*;
 import 
org.apache.fineract.infrastructure.dataqueries.exception.DatatableNotFoundException;
 import 
org.apache.fineract.infrastructure.dataqueries.exception.DatatableSystemErrorException;
 import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
@@ -359,7 +349,12 @@ public class ReadWriteNonCoreDataServiceImpl implements 
ReadWriteNonCoreDataServ
     @Transactional
     @Override
     public CommandProcessingResult createNewDatatableEntry(final String 
dataTableName, final Long appTableId, final JsonCommand command) {
+        return createNewDatatableEntry(dataTableName, appTableId, 
command.json());
+    }
 
+    @Transactional
+    @Override
+    public CommandProcessingResult createNewDatatableEntry(final String 
dataTableName, final Long appTableId, final String json) {
         try {
             final String appTable = 
queryForApplicationTableName(dataTableName);
             final CommandProcessingResult commandProcessingResult = 
checkMainResourceExistsWithinScope(appTable, appTableId);
@@ -367,7 +362,7 @@ public class ReadWriteNonCoreDataServiceImpl implements 
ReadWriteNonCoreDataServ
             final List<ResultsetColumnHeaderData> columnHeaders = 
this.genericDataService.fillResultsetColumnHeaders(dataTableName);
 
             final Type typeOfMap = new TypeToken<Map<String, String>>() 
{}.getType();
-            final Map<String, String> dataParams = 
this.fromJsonHelper.extractDataMap(typeOfMap, command.json());
+            final Map<String, String> dataParams = 
this.fromJsonHelper.extractDataMap(typeOfMap, json);
 
             final String sql = getAddSql(columnHeaders, dataTableName, 
getFKField(appTable), appTableId, dataParams);
 
@@ -378,29 +373,32 @@ public class ReadWriteNonCoreDataServiceImpl implements 
ReadWriteNonCoreDataServ
         } catch (final DataAccessException dve) {
             final Throwable cause = dve.getCause() ;
             final Throwable realCause = dve.getMostSpecificCause();
-            if (realCause.getMessage()
-                    .contains("Duplicate entry") || cause.getMessage()
-                    .contains("Duplicate entry")) { throw new 
PlatformDataIntegrityException(
-                            "error.msg.datatable.entry.duplicate", "An entry 
already exists for datatable `" + dataTableName
-                                    + "` and application table with identifier 
`" + appTableId + "`.",
-                            "dataTableName", dataTableName, appTableId); }
+            if (realCause.getMessage().contains("Duplicate entry") || 
cause.getMessage().contains("Duplicate entry")) {
+                throw new 
PlatformDataIntegrityException("error.msg.datatable.entry.duplicate", "An entry 
already exists for datatable `"
+                        + dataTableName + "` and application table with 
identifier `" + appTableId + "`.", "dataTableName", dataTableName,
+                        appTableId);
+            } else if (realCause.getMessage().contains("doesn't have a default 
value")
+                    || cause.getMessage().contains("doesn't have a default 
value")) { throw new PlatformDataIntegrityException(
+                    
"error.msg.datatable.no.value.provided.for.required.fields", "No values 
provided for the datatable `" + dataTableName
+                            + "` and application table with identifier `" + 
appTableId + "`.", "dataTableName", dataTableName, appTableId); }
 
             logAsErrorUnexpectedDataIntegrityException(dve);
             throw new 
PlatformDataIntegrityException("error.msg.unknown.data.integrity.issue",
                     "Unknown data integrity issue with resource.");
-        }catch(final PersistenceException e) {
-               final Throwable cause = e.getCause() ;
-            if (cause.getMessage()
-                    .contains("Duplicate entry")) { 
-               throw new PlatformDataIntegrityException(
-                            "error.msg.datatable.entry.duplicate", "An entry 
already exists for datatable `" + dataTableName
-                                    + "` and application table with identifier 
`" + appTableId + "`.",
-                            "dataTableName", dataTableName, appTableId); }
+        } catch (final PersistenceException e) {
+            final Throwable cause = e.getCause();
+            if (cause.getMessage().contains("Duplicate entry")) {
+                throw new 
PlatformDataIntegrityException("error.msg.datatable.entry.duplicate", "An entry 
already exists for datatable `"
+                        + dataTableName + "` and application table with 
identifier `" + appTableId + "`.", "dataTableName", dataTableName,
+                        appTableId);
+            } else if (cause.getMessage().contains("doesn't have a default 
value")) { throw new PlatformDataIntegrityException(
+                    
"error.msg.datatable.no.value.provided.for.required.fields", "No values 
provided for the datatable `" + dataTableName
+                            + "` and application table with identifier `" + 
appTableId + "`.", "dataTableName", dataTableName, appTableId); }
 
             logAsErrorUnexpectedDataIntegrityException(e);
             throw new 
PlatformDataIntegrityException("error.msg.unknown.data.integrity.issue",
                     "Unknown data integrity issue with resource.");
-               
+
         }
     }
 
@@ -1722,4 +1720,14 @@ public class ReadWriteNonCoreDataServiceImpl implements 
ReadWriteNonCoreDataServ
 
         return true;
     }
+
+    @Override
+    public Long countDatatableEntries(final String datatableName, final Long 
appTableId, String foreignKeyColumn) {
+
+        final String sqlString = "SELECT COUNT(`" + foreignKeyColumn + "`) 
FROM `" + datatableName + "` WHERE `" + foreignKeyColumn + "`="
+                + appTableId;
+        final Long count = this.jdbcTemplate.queryForObject(sqlString, 
Long.class);
+        return count;
+    }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/dde6eaec/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientApiConstants.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientApiConstants.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientApiConstants.java
index e4f3ef1..fe5ec64 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientApiConstants.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientApiConstants.java
@@ -177,16 +177,18 @@ public class ClientApiConstants {
     public static final String officeOptionsParamName = "officeOptions";
     public static final String staffOptionsParamName = "staffOptions";
 
+    public static final String datatables = "datatables";
+
     public static final Set<String> CLIENT_CREATE_REQUEST_DATA_PARAMETERS = 
new HashSet<>(
             Arrays.asList(address,localeParamName, dateFormatParamName, 
groupIdParamName, accountNoParamName, externalIdParamName,
                     mobileNoParamName, firstnameParamName, 
middlenameParamName, lastnameParamName, fullnameParamName, officeIdParamName,
                     activeParamName, activationDateParamName, 
staffIdParamName, submittedOnDateParamName, savingsProductIdParamName,
                     dateOfBirthParamName, genderIdParamName, 
clientTypeIdParamName, clientClassificationIdParamName, 
-                    clientNonPersonDetailsParamName, displaynameParamName, 
legalFormIdParamName));
+                    clientNonPersonDetailsParamName, displaynameParamName, 
legalFormIdParamName, datatables));
     
     public static final Set<String> 
CLIENT_NON_PERSON_CREATE_REQUEST_DATA_PARAMETERS = new HashSet<>(
             Arrays.asList(address,localeParamName, dateFormatParamName, 
incorpNumberParamName, remarksParamName, incorpValidityTillParamName, 
-                       constitutionIdParamName, mainBusinessLineIdParamName));
+                       constitutionIdParamName, mainBusinessLineIdParamName, 
datatables));
 
     public static final Set<String> CLIENT_UPDATE_REQUEST_DATA_PARAMETERS = 
new HashSet<>(Arrays.asList(localeParamName,
             dateFormatParamName, accountNoParamName, externalIdParamName, 
mobileNoParamName, firstnameParamName, middlenameParamName,

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/dde6eaec/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java
index bcba0fc..913ac17 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java
@@ -27,6 +27,7 @@ import org.apache.commons.lang.builder.EqualsBuilder;
 import org.apache.commons.lang.builder.HashCodeBuilder;
 import org.apache.fineract.infrastructure.codes.data.CodeValueData;
 import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
 import org.apache.fineract.organisation.office.data.OfficeData;
 import org.apache.fineract.organisation.staff.data.StaffData;
 import org.apache.fineract.portfolio.address.data.AddressData;
@@ -101,12 +102,14 @@ final public class ClientData implements 
Comparable<ClientData> {
 
        private final Boolean isAddressEnabled;
 
+    private final List<DatatableData> datatables;
+
     public static ClientData template(final Long officeId, final LocalDate 
joinedDate, final Collection<OfficeData> officeOptions,
             final Collection<StaffData> staffOptions, final 
Collection<CodeValueData> narrations,
             final Collection<CodeValueData> genderOptions, final 
Collection<SavingsProductData> savingProductOptions,
-            final Collection<CodeValueData> clientTypeOptions, final 
Collection<CodeValueData> clientClassificationOptions, 
-            final Collection<CodeValueData> 
clientNonPersonConstitutionOptions, final Collection<CodeValueData> 
clientNonPersonMainBusinessLineOptions,
-            final List<EnumOptionData> clientLegalFormOptions, final 
AddressData address,final Boolean isAddressEnabled) {
+            final Collection<CodeValueData> clientTypeOptions, final 
Collection<CodeValueData> clientClassificationOptions, final 
Collection<CodeValueData> clientNonPersonConstitutionOptions,
+            final Collection<CodeValueData> 
clientNonPersonMainBusinessLineOptions, final List<EnumOptionData> 
clientLegalFormOptions, final AddressData address,
+            final Boolean isAddressEnabled, final List<DatatableData> 
datatables) {
         final String accountNo = null;
         final EnumOptionData status = null;
         final CodeValueData subStatus = null;
@@ -141,7 +144,7 @@ final public class ClientData implements 
Comparable<ClientData> {
                 staffName, officeOptions, groups, staffOptions, narrations, 
genderOptions, timeline, savingProductOptions,
                 savingsProductId, savingsProductName, savingsAccountId, 
savingAccountOptions, clientType, clientClassification,
                 clientTypeOptions, clientClassificationOptions, 
clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, 
-                clientNonPersonDetails, clientLegalFormOptions, 
legalForm,address, isAddressEnabled);
+                clientNonPersonDetails, clientLegalFormOptions, 
legalForm,address, isAddressEnabled, datatables);
 
     }
 
@@ -156,7 +159,7 @@ final public class ClientData implements 
Comparable<ClientData> {
                 clientData.savingsProductName, clientData.savingsAccountId, 
clientData.savingAccountOptions, clientData.clientType,
                 clientData.clientClassification, 
templateData.clientTypeOptions, templateData.clientClassificationOptions, 
                 templateData.clientNonPersonConstitutionOptions, 
templateData.clientNonPersonMainBusinessLineOptions, 
clientData.clientNonPersonDetails,
-                templateData.clientLegalFormOptions, clientData.legalForm, 
clientData.address,clientData.isAddressEnabled);
+                templateData.clientLegalFormOptions, clientData.legalForm, 
clientData.address,clientData.isAddressEnabled, null);
 
     }
 
@@ -172,7 +175,7 @@ final public class ClientData implements 
Comparable<ClientData> {
                 clientData.savingsProductName, clientData.savingsAccountId, 
savingAccountOptions, clientData.clientType,
                 clientData.clientClassification, clientData.clientTypeOptions, 
clientData.clientClassificationOptions,
                 clientData.clientNonPersonConstitutionOptions, 
clientData.clientNonPersonMainBusinessLineOptions, 
clientData.clientNonPersonDetails,
-                clientData.clientLegalFormOptions, 
clientData.legalForm,clientData.address, clientData.isAddressEnabled);
+                clientData.clientLegalFormOptions, 
clientData.legalForm,clientData.address, clientData.isAddressEnabled, null);
 
     }
 
@@ -186,7 +189,7 @@ final public class ClientData implements 
Comparable<ClientData> {
                 clientData.savingAccountOptions, clientData.clientType, 
clientData.clientClassification, clientData.clientTypeOptions,
                 clientData.clientClassificationOptions, 
clientData.clientNonPersonConstitutionOptions, 
clientData.clientNonPersonMainBusinessLineOptions, 
                 clientData.clientNonPersonDetails, 
clientData.clientLegalFormOptions, clientData.legalForm,clientData.address,
-                               clientData.isAddressEnabled);
+                               clientData.isAddressEnabled, null);
 
     }
 
@@ -230,7 +233,7 @@ final public class ClientData implements 
Comparable<ClientData> {
                 staffName, allowedOffices, groups, staffOptions, 
closureReasons, genderOptions, timeline, savingProductOptions,
                 savingsProductId, savingsProductName, savingsAccountId, 
savingAccountOptions, clientType, clientClassification,
                 clientTypeOptions, clientClassificationOptions, 
clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, 
-                clientNonPerson, clientLegalFormOptions, legalForm,null,null);
+                clientNonPerson, clientLegalFormOptions, legalForm,null,null, 
null);
     }
 
     public static ClientData lookup(final Long id, final String displayName, 
final Long officeId, final String officeName) {
@@ -276,7 +279,7 @@ final public class ClientData implements 
Comparable<ClientData> {
                 staffName, allowedOffices, groups, staffOptions, 
closureReasons, genderOptions, timeline, savingProductOptions,
                 savingsProductId, savingsProductName, savingsAccountId, 
savingAccountOptions, clientType, clientClassification,
                 clientTypeOptions, clientClassificationOptions, 
clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, 
-                clientNonPerson, clientLegalFormOptions, legalForm,null,null);
+                clientNonPerson, clientLegalFormOptions, legalForm,null,null, 
null);
 
     }
 
@@ -304,7 +307,7 @@ final public class ClientData implements 
Comparable<ClientData> {
                 staffName, allowedOffices, groups, staffOptions, 
closureReasons, genderOptions, timeline, savingProductOptions,
                 savingsProductId, savingsProductName, savingsAccountId, null, 
clientType, clientClassification, clientTypeOptions,
                 clientClassificationOptions, 
clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, 
clientNonPerson,
-                clientLegalFormOptions, legalForm,null,null);
+                clientLegalFormOptions, legalForm,null,null, null);
 
     }
 
@@ -321,7 +324,8 @@ final public class ClientData implements 
Comparable<ClientData> {
             final CodeValueData clientClassification, final 
Collection<CodeValueData> clientTypeOptions,
             final Collection<CodeValueData> clientClassificationOptions, final 
Collection<CodeValueData> clientNonPersonConstitutionOptions,
             final Collection<CodeValueData> 
clientNonPersonMainBusinessLineOptions, final ClientNonPersonData 
clientNonPerson,
-            final List<EnumOptionData> clientLegalFormOptions, final 
EnumOptionData legalForm,final AddressData address, final Boolean 
isAddressEnabled) {
+            final List<EnumOptionData> clientLegalFormOptions, final 
EnumOptionData legalForm, final AddressData address,
+            final Boolean isAddressEnabled, final List<DatatableData> 
datatables) {
         this.accountNo = accountNo;
         this.status = status;
         if (status != null) {
@@ -382,7 +386,8 @@ final public class ClientData implements 
Comparable<ClientData> {
         this.clientNonPersonDetails = clientNonPerson;
         
        this.address = address;
-                               this.isAddressEnabled = isAddressEnabled;
+               this.isAddressEnabled = isAddressEnabled;
+        this.datatables = datatables;
 
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/dde6eaec/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientDataValidator.java
----------------------------------------------------------------------
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 6634916..4c2f538 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
@@ -27,6 +27,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import com.google.gson.JsonArray;
 import org.apache.commons.lang.StringUtils;
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
 import org.apache.fineract.infrastructure.core.data.ApiParameterError;
@@ -94,6 +95,13 @@ public final class ClientDataValidator {
             final Long savingsProductId = 
this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.savingsProductIdParamName,
 element);
             
baseDataValidator.reset().parameter(ClientApiConstants.savingsProductIdParamName).value(savingsProductId).ignoreIfNull()
                     .longGreaterThanZero();
+            /*if (savingsProductId != null && 
this.fromApiJsonHelper.parameterExists(ClientApiConstants.datatables, element)) 
{
+                final JsonArray datatables = 
this.fromApiJsonHelper.extractJsonArrayNamed(ClientApiConstants.datatables, 
element);
+                if (datatables.size() > 0) {
+                    
baseDataValidator.reset().parameter(ClientApiConstants.savingsProductIdParamName).value(savingsProductId)
+                            
.failWithCodeNoParameterAddedToErrorCode("should.not.be.used.with.datatables.parameter");
+                }
+            }*/
         }
 
         if (isFullnameProvided(element) || isIndividualNameProvided(element)) {
@@ -154,6 +162,10 @@ public final class ClientDataValidator {
                 final LocalDate joinedDate = 
this.fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.activationDateParamName,
                         element);
                 
baseDataValidator.reset().parameter(ClientApiConstants.activationDateParamName).value(joinedDate).notNull();
+                
/*if(this.fromApiJsonHelper.parameterExists(ClientApiConstants.datatables,element)){
+                    
baseDataValidator.reset().parameter(ClientApiConstants.activeParamName).value(active)
+                            
.failWithCodeNoParameterAddedToErrorCode("should.not.be.used.with.datatables.parameter");
+                }*/
             }
         } else {
             
baseDataValidator.reset().parameter(ClientApiConstants.activeParamName).value(active).trueOrFalseRequired(false);
@@ -193,8 +205,13 @@ public final class ClientDataValidator {
                final Integer legalFormId = 
this.fromApiJsonHelper.extractIntegerSansLocaleNamed(ClientApiConstants.legalFormIdParamName,
 element);
             
baseDataValidator.reset().parameter(ClientApiConstants.legalFormIdParamName).value(legalFormId).ignoreIfNull().inMinMaxRange(1,
 2);
         }
-        
-        List<ApiParameterError> dataValidationErrorsForClientNonPerson = 
getDataValidationErrorsForCreateOnClientNonPerson(element.getAsJsonObject().get(ClientApiConstants.clientNonPersonDetailsParamName));
        
+
+        
if(this.fromApiJsonHelper.parameterExists(ClientApiConstants.datatables, 
element)){
+            final JsonArray datatables = 
this.fromApiJsonHelper.extractJsonArrayNamed(ClientApiConstants.datatables, 
element);
+            
baseDataValidator.reset().parameter(ClientApiConstants.datatables).value(datatables).notNull().jsonArrayNotEmpty();
+        }
+
+        List<ApiParameterError> dataValidationErrorsForClientNonPerson = 
getDataValidationErrorsForCreateOnClientNonPerson(element.getAsJsonObject().get(ClientApiConstants.clientNonPersonDetailsParamName));
         dataValidationErrors.addAll(dataValidationErrorsForClientNonPerson);
         
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
@@ -236,8 +253,8 @@ public final class ClientDataValidator {
                     element);
             
baseDataValidator.reset().parameter(ClientApiConstants.mainBusinessLineIdParamName).value(mainBusinessLine).integerGreaterThanZero();
         }
-       
-               return dataValidationErrors;            
+
+               return dataValidationErrors;
     }
 
     private void validateIndividualNamePartsCannotBeUsedWithFullname(final 
JsonElement element, final DataValidatorBuilder baseDataValidator) {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/dde6eaec/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java
index bec5369..cab88f7 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java
@@ -36,6 +36,10 @@ import org.apache.fineract.infrastructure.core.service.Page;
 import org.apache.fineract.infrastructure.core.service.PaginationHelper;
 import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
 import org.apache.fineract.infrastructure.core.service.SearchParameters;
+import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
+import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
+import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum;
+import 
org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksReadService;
 import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
 import org.apache.fineract.organisation.office.data.OfficeData;
 import 
org.apache.fineract.organisation.office.service.OfficeReadPlatformService;
@@ -81,6 +85,7 @@ public class ClientReadPlatformServiceImpl implements 
ClientReadPlatformService
     
     private final AddressReadPlatformService addressReadPlatformService;
     private final ConfigurationReadPlatformService 
configurationReadPlatformService;
+    private final EntityDatatableChecksReadService 
entityDatatableChecksReadService;
 
     @Autowired
     public ClientReadPlatformServiceImpl(final PlatformSecurityContext 
context, final RoutingDataSource dataSource,
@@ -88,7 +93,8 @@ public class ClientReadPlatformServiceImpl implements 
ClientReadPlatformService
             final CodeValueReadPlatformService codeValueReadPlatformService,
             final SavingsProductReadPlatformService 
savingsProductReadPlatformService,
             final AddressReadPlatformService addressReadPlatformService,
-            final ConfigurationReadPlatformService 
configurationReadPlatformService) {
+            final ConfigurationReadPlatformService 
configurationReadPlatformService,
+            final EntityDatatableChecksReadService 
entityDatatableChecksReadService) {
         this.context = context;
         this.officeReadPlatformService = officeReadPlatformService;
         this.jdbcTemplate = new JdbcTemplate(dataSource);
@@ -97,6 +103,7 @@ public class ClientReadPlatformServiceImpl implements 
ClientReadPlatformService
         this.savingsProductReadPlatformService = 
savingsProductReadPlatformService;
         this.addressReadPlatformService=addressReadPlatformService;
         this.configurationReadPlatformService=configurationReadPlatformService;
+        this.entityDatatableChecksReadService = 
entityDatatableChecksReadService;
     }
 
     @Override
@@ -149,9 +156,12 @@ public class ClientReadPlatformServiceImpl implements 
ClientReadPlatformService
         
         final List<EnumOptionData> clientLegalFormOptions = 
ClientEnumerations.legalForm(LegalForm.values());
 
+        final List<DatatableData> datatableTemplates = 
this.entityDatatableChecksReadService
+                .retrieveTemplates(StatusEnum.CREATE.getCode().longValue(), 
EntityTables.CLIENT.getName(), null);
+
         return ClientData.template(defaultOfficeId, new LocalDate(), offices, 
staffOptions, null, genderOptions, savingsProductDatas,
                 clientTypeOptions, clientClassificationOptions, 
clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions,
-                clientLegalFormOptions,address,isAddressEnabled);
+                clientLegalFormOptions,address,isAddressEnabled, 
datatableTemplates);
     }
 
     @Override
@@ -782,7 +792,7 @@ public class ClientReadPlatformServiceImpl implements 
ClientReadPlatformService
         final Collection<CodeValueData> clientNonPersonMainBusinessLineOptions 
= null;
         final List<EnumOptionData> clientLegalFormOptions = null;
         return ClientData.template(null, null, null, null, narrations, null, 
null, clientTypeOptions, clientClassificationOptions, 
-                       clientNonPersonConstitutionOptions, 
clientNonPersonMainBusinessLineOptions, clientLegalFormOptions,null,null);
+                       clientNonPersonConstitutionOptions, 
clientNonPersonMainBusinessLineOptions, clientLegalFormOptions,null,null, null);
     }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/dde6eaec/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java
index 9a25264..d2fa74c 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java
@@ -18,12 +18,7 @@
  */
 package org.apache.fineract.portfolio.client.service;
 
-
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
+import java.util.*;
 
 import javax.persistence.PersistenceException;
 
@@ -44,6 +39,9 @@ import 
org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
 import 
org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
 import 
org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
 import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
+import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
+import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum;
+import 
org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksWritePlatformService;
 import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
 import org.apache.fineract.organisation.office.domain.Office;
 import org.apache.fineract.organisation.office.domain.OfficeRepositoryWrapper;
@@ -52,18 +50,8 @@ import 
org.apache.fineract.organisation.staff.domain.StaffRepositoryWrapper;
 import 
org.apache.fineract.portfolio.address.service.AddressWritePlatformService;
 import org.apache.fineract.portfolio.client.api.ClientApiConstants;
 import org.apache.fineract.portfolio.client.data.ClientDataValidator;
-import org.apache.fineract.portfolio.client.domain.AccountNumberGenerator;
-import org.apache.fineract.portfolio.client.domain.Client;
-import org.apache.fineract.portfolio.client.domain.ClientNonPerson;
-import 
org.apache.fineract.portfolio.client.domain.ClientNonPersonRepositoryWrapper;
-import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
-import org.apache.fineract.portfolio.client.domain.ClientStatus;
-import org.apache.fineract.portfolio.client.domain.LegalForm;
-import 
org.apache.fineract.portfolio.client.exception.ClientActiveForUpdateException;
-import 
org.apache.fineract.portfolio.client.exception.ClientHasNoStaffException;
-import 
org.apache.fineract.portfolio.client.exception.ClientMustBePendingToBeDeletedException;
-import 
org.apache.fineract.portfolio.client.exception.InvalidClientSavingProductException;
-import 
org.apache.fineract.portfolio.client.exception.InvalidClientStateTransitionException;
+import org.apache.fineract.portfolio.client.domain.*;
+import org.apache.fineract.portfolio.client.exception.*;
 import 
org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_ENTITY;
 import 
org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS;
 import 
org.apache.fineract.portfolio.common.service.BusinessEventNotifierService;
@@ -121,7 +109,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl 
implements ClientWriteP
     private final ConfigurationReadPlatformService 
configurationReadPlatformService;
     private final AddressWritePlatformService addressWritePlatformService;
     private final BusinessEventNotifierService businessEventNotifierService;
-
+    private final EntityDatatableChecksWritePlatformService 
entityDatatableChecksWritePlatformService;
     @Autowired
     public ClientWritePlatformServiceJpaRepositoryImpl(final 
PlatformSecurityContext context,
             final ClientRepositoryWrapper clientRepository, final 
ClientNonPersonRepositoryWrapper clientNonPersonRepository,
@@ -134,7 +122,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl 
implements ClientWriteP
             final CommandProcessingService commandProcessingService, final 
ConfigurationDomainService configurationDomainService,
             final AccountNumberFormatRepositoryWrapper 
accountNumberFormatRepository, final FromJsonHelper fromApiJsonHelper,
             final ConfigurationReadPlatformService 
configurationReadPlatformService,
-            final AddressWritePlatformService addressWritePlatformService, 
final BusinessEventNotifierService businessEventNotifierService) {
+            final AddressWritePlatformService addressWritePlatformService, 
final BusinessEventNotifierService businessEventNotifierService,
+            final EntityDatatableChecksWritePlatformService 
entityDatatableChecksWritePlatformService) {
         this.context = context;
         this.clientRepository = clientRepository;
         this.clientNonPersonRepository = clientNonPersonRepository;
@@ -156,6 +145,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl 
implements ClientWriteP
         this.configurationReadPlatformService = 
configurationReadPlatformService;
         this.addressWritePlatformService = addressWritePlatformService;
         this.businessEventNotifierService = businessEventNotifierService;
+        this.entityDatatableChecksWritePlatformService = 
entityDatatableChecksWritePlatformService;
     }
 
     @Transactional
@@ -314,6 +304,15 @@ public class ClientWritePlatformServiceJpaRepositoryImpl 
implements ClientWriteP
                 
this.addressWritePlatformService.addNewClientAddress(newClient, command);
             }
 
+            if(command.parameterExists(ClientApiConstants.datatables)){
+                
this.entityDatatableChecksWritePlatformService.saveDatatables(StatusEnum.CREATE.getCode().longValue(),
+                        EntityTables.CLIENT.getName(), newClient.getId(), null,
+                        
command.arrayOfParameterNamed(ClientApiConstants.datatables));
+            }
+
+            
this.entityDatatableChecksWritePlatformService.runTheCheck(newClient.getId(), 
EntityTables.CLIENT.getName(),
+                    StatusEnum.CREATE.getCode().longValue(), 
EntityTables.CLIENT.getForeignKeyColumnNameOnDatatable());
+
             return new CommandProcessingResultBuilder() //
                     .withCommandId(command.commandId()) //
                     .withOfficeId(clientOffice.getId()) //
@@ -534,6 +533,9 @@ public class ClientWritePlatformServiceJpaRepositoryImpl 
implements ClientWriteP
             final DateTimeFormatter fmt = 
DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
             final LocalDate activationDate = 
command.localDateValueOfParameterNamed("activationDate");
 
+            entityDatatableChecksWritePlatformService.runTheCheck(clientId, 
EntityTables.CLIENT.getName(),
+                    StatusEnum.ACTIVATE.getCode().longValue(), 
EntityTables.CLIENT.getForeignKeyColumnNameOnDatatable());
+
             final AppUser currentUser = this.context.authenticatedUser();
             client.activate(currentUser, fmt, activationDate);
             CommandProcessingResult result = openSavingsAccount(client, fmt);
@@ -668,6 +670,9 @@ public class ClientWritePlatformServiceJpaRepositoryImpl 
implements ClientWriteP
                 throw new InvalidClientStateTransitionException("close", 
"date.cannot.before.client.actvation.date", errorMessage,
                         closureDate, client.getActivationLocalDate());
             }
+            
entityDatatableChecksWritePlatformService.runTheCheck(clientId,EntityTables.CLIENT.getName(),
+                    
StatusEnum.CLOSE.getCode().longValue(),EntityTables.CLIENT.getForeignKeyColumnNameOnDatatable());
+
             final List<Loan> clientLoans = 
this.loanRepositoryWrapper.findLoanByClientId(clientId);
             for (final Loan loan : clientLoans) {
                 final LoanStatusMapper loanStatus = new 
LoanStatusMapper(loan.status().getValue());

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/dde6eaec/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/CentersApiResource.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/CentersApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/CentersApiResource.java
index 367cae5..0195e99 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/CentersApiResource.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/CentersApiResource.java
@@ -18,11 +18,7 @@
  */
 package org.apache.fineract.portfolio.group.api;
 
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.*;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -54,6 +50,10 @@ import 
org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
 import 
org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
 import org.apache.fineract.infrastructure.core.service.Page;
 import org.apache.fineract.infrastructure.core.service.SearchParameters;
+import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
+import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
+import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum;
+import 
org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksReadService;
 import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
 import 
org.apache.fineract.portfolio.accountdetails.data.AccountSummaryCollectionData;
 import 
org.apache.fineract.portfolio.accountdetails.service.AccountDetailsReadPlatformService;
@@ -92,6 +92,7 @@ public class CentersApiResource {
     private final AccountDetailsReadPlatformService 
accountDetailsReadPlatformService;
     private final CalendarReadPlatformService calendarReadPlatformService;
     private final MeetingReadPlatformService meetingReadPlatformService;
+    private final EntityDatatableChecksReadService 
entityDatatableChecksReadService;
 
     @Autowired
     public CentersApiResource(final PlatformSecurityContext context, final 
CenterReadPlatformService centerReadPlatformService,
@@ -101,7 +102,8 @@ public class CentersApiResource {
             final PortfolioCommandSourceWritePlatformService 
commandsSourceWritePlatformService,
             final CollectionSheetReadPlatformService 
collectionSheetReadPlatformService, final FromJsonHelper fromJsonHelper,
             final AccountDetailsReadPlatformService 
accountDetailsReadPlatformService,
-            final CalendarReadPlatformService calendarReadPlatformService, 
final MeetingReadPlatformService meetingReadPlatformService) {
+            final CalendarReadPlatformService calendarReadPlatformService, 
final MeetingReadPlatformService meetingReadPlatformService,
+            final EntityDatatableChecksReadService 
entityDatatableChecksReadService) {
         this.context = context;
         this.centerReadPlatformService = centerReadPlatformService;
         this.centerApiJsonSerializer = centerApiJsonSerializer;
@@ -114,6 +116,7 @@ public class CentersApiResource {
         this.accountDetailsReadPlatformService = 
accountDetailsReadPlatformService;
         this.calendarReadPlatformService = calendarReadPlatformService;
         this.meetingReadPlatformService = meetingReadPlatformService;
+        this.entityDatatableChecksReadService = 
entityDatatableChecksReadService;
     }
 
     @GET
@@ -134,6 +137,9 @@ public class CentersApiResource {
         }
 
         final CenterData template = 
this.centerReadPlatformService.retrieveTemplate(officeId, 
staffInSelectedOfficeOnly);
+        final List<DatatableData> datatableTemplates = 
this.entityDatatableChecksReadService
+                .retrieveTemplates(StatusEnum.CREATE.getCode().longValue(), 
EntityTables.GROUP.getName(), null);
+        template.setDatatables(datatableTemplates);
 
         final ApiRequestJsonSerializationSettings settings = 
this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
         return this.centerApiJsonSerializer.serialize(settings, template, 
GroupingTypesApiConstants.CENTER_RESPONSE_DATA_PARAMETERS);

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/dde6eaec/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/GroupingTypesApiConstants.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/GroupingTypesApiConstants.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/GroupingTypesApiConstants.java
index bf1d6d0..bc3ebd0 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/GroupingTypesApiConstants.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/GroupingTypesApiConstants.java
@@ -87,13 +87,15 @@ public class GroupingTypesApiConstants {
     // staff centres parameters
     public static final String meetingFallCenters = "meetingFallCenters";
 
+    public static final String datatables = "datatables";
+
     public static final Set<String> CENTER_REQUEST_DATA_PARAMETERS = new 
HashSet<>(Arrays.asList(localeParamName,
             dateFormatParamName, idParamName, nameParamName, 
externalIdParamName, officeIdParamName, staffIdParamName, activeParamName,
-            activationDateParamName, groupMembersParamName, 
submittedOnDateParamName));
+            activationDateParamName, groupMembersParamName, 
submittedOnDateParamName, datatables));
 
     public static final Set<String> GROUP_REQUEST_DATA_PARAMETERS = new 
HashSet<>(Arrays.asList(localeParamName, dateFormatParamName,
             idParamName, nameParamName, externalIdParamName, 
centerIdParamName, officeIdParamName, staffIdParamName, activeParamName,
-            activationDateParamName, clientMembersParamName, 
collectionMeetingCalendar, submittedOnDateParamName));
+            activationDateParamName, clientMembersParamName, 
collectionMeetingCalendar, submittedOnDateParamName, datatables));
 
     public static final Set<String> GROUP_ROLES_REQUEST_DATA_PARAMETERS = new 
HashSet<>(Arrays.asList(roleParamName,
             clientIdParamName));
@@ -106,16 +108,16 @@ public class GroupingTypesApiConstants {
     public static final Set<String> CENTER_RESPONSE_DATA_PARAMETERS = new 
HashSet<>(Arrays.asList(idParamName, nameParamName,
             externalIdParamName, officeIdParamName, officeNameParamName, 
staffIdParamName, staffNameParamName, hierarchyParamName,
             officeOptionsParamName, staffOptionsParamName, statusParamName, 
activeParamName, activationDateParamName, timeLine,
-            groupMembersParamName, collectionMeetingCalendar, closureReasons));
+            groupMembersParamName, collectionMeetingCalendar, closureReasons, 
datatables));
 
     public static final Set<String> CENTER_GROUP_RESPONSE_DATA_PARAMETERS = 
new HashSet<>(Arrays.asList(idParamName, nameParamName,
             externalIdParamName, officeIdParamName, officeNameParamName, 
staffIdParamName, staffNameParamName, hierarchyParamName,
-            officeOptionsParamName, staffOptionsParamName, 
clientOptionsParamName));
+            officeOptionsParamName, staffOptionsParamName, 
clientOptionsParamName, datatables));
 
     public static final Set<String> GROUP_RESPONSE_DATA_PARAMETERS = new 
HashSet<>(Arrays.asList(idParamName, nameParamName,
             externalIdParamName, officeIdParamName, officeNameParamName, 
"parentId", "parentName", staffIdParamName, staffNameParamName,
             hierarchyParamName, officeOptionsParamName, statusParamName, 
activeParamName, activationDateParamName, staffOptionsParamName,
-            clientOptionsParamName, timeLine));
+            clientOptionsParamName, timeLine, datatables));
 
     public static final Set<String> ACTIVATION_REQUEST_DATA_PARAMETERS = new 
HashSet<>(Arrays.asList(localeParamName,
             dateFormatParamName, activationDateParamName));

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/dde6eaec/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/GroupsApiResource.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/GroupsApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/GroupsApiResource.java
index 033a8db..96dc132 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/GroupsApiResource.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/GroupsApiResource.java
@@ -53,6 +53,10 @@ import 
org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
 import 
org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
 import org.apache.fineract.infrastructure.core.service.Page;
 import org.apache.fineract.infrastructure.core.service.SearchParameters;
+import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
+import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
+import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum;
+import 
org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksReadService;
 import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
 import 
org.apache.fineract.portfolio.accountdetails.data.AccountSummaryCollectionData;
 import 
org.apache.fineract.portfolio.accountdetails.service.AccountDetailsReadPlatformService;
@@ -99,6 +103,7 @@ public class GroupsApiResource {
     private final AccountDetailsReadPlatformService 
accountDetailsReadPlatformService;
     private final CalendarReadPlatformService calendarReadPlatformService;
     private final MeetingReadPlatformService meetingReadPlatformService;
+    private final EntityDatatableChecksReadService 
entityDatatableChecksReadService;
 
     @Autowired
     public GroupsApiResource(final PlatformSecurityContext context, final 
GroupReadPlatformService groupReadPlatformService,
@@ -111,7 +116,8 @@ public class GroupsApiResource {
             final CollectionSheetReadPlatformService 
collectionSheetReadPlatformService, final FromJsonHelper fromJsonHelper,
             final GroupRolesReadPlatformService groupRolesReadPlatformService,
             final AccountDetailsReadPlatformService 
accountDetailsReadPlatformService,
-            final CalendarReadPlatformService calendarReadPlatformService, 
final MeetingReadPlatformService meetingReadPlatformService) {
+            final CalendarReadPlatformService calendarReadPlatformService, 
final MeetingReadPlatformService meetingReadPlatformService,
+            final EntityDatatableChecksReadService 
entityDatatableChecksReadService) {
 
         this.context = context;
         this.groupReadPlatformService = groupReadPlatformService;
@@ -128,6 +134,7 @@ public class GroupsApiResource {
         this.accountDetailsReadPlatformService = 
accountDetailsReadPlatformService;
         this.calendarReadPlatformService = calendarReadPlatformService;
         this.meetingReadPlatformService = meetingReadPlatformService;
+        this.entityDatatableChecksReadService = 
entityDatatableChecksReadService;
     }
 
     @GET
@@ -148,8 +155,11 @@ public class GroupsApiResource {
                     GroupingTypesApiConstants.GROUP_RESPONSE_DATA_PARAMETERS);
         }
 
+        final List<DatatableData> datatableTemplates = 
this.entityDatatableChecksReadService
+                .retrieveTemplates(StatusEnum.CREATE.getCode().longValue(), 
EntityTables.GROUP.getName(), null);
         if (centerId != null) {
             final GroupGeneralData centerGroupTemplate = 
this.centerReadPlatformService.retrieveCenterGroupTemplate(centerId);
+            centerGroupTemplate.setDatatables(datatableTemplates);
             final ApiRequestJsonSerializationSettings settings = 
this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
             return this.groupGeneralApiJsonSerializer.serialize(settings, 
centerGroupTemplate,
                     
GroupingTypesApiConstants.CENTER_GROUP_RESPONSE_DATA_PARAMETERS);
@@ -157,6 +167,8 @@ public class GroupsApiResource {
 
         final GroupGeneralData groupTemplate = 
this.groupReadPlatformService.retrieveTemplate(officeId, isCenterGroup,
                 staffInSelectedOfficeOnly);
+        groupTemplate.setDatatables(datatableTemplates);
+
         final ApiRequestJsonSerializationSettings settings = 
this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
         return this.groupGeneralApiJsonSerializer.serialize(settings, 
groupTemplate,
                 GroupingTypesApiConstants.GROUP_RESPONSE_DATA_PARAMETERS);

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/dde6eaec/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/CenterData.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/CenterData.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/CenterData.java
index b05267d..2d2828d 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/CenterData.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/CenterData.java
@@ -20,9 +20,11 @@ package org.apache.fineract.portfolio.group.data;
 
 import java.math.BigDecimal;
 import java.util.Collection;
+import java.util.List;
 
 import org.apache.fineract.infrastructure.codes.data.CodeValueData;
 import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
 import org.apache.fineract.organisation.office.data.OfficeData;
 import org.apache.fineract.organisation.staff.data.StaffData;
 import org.apache.fineract.portfolio.calendar.data.CalendarData;
@@ -63,6 +65,8 @@ public class CenterData {
     private final BigDecimal totaldue;
     private final BigDecimal installmentDue;
 
+    private List<DatatableData> datatables = null;
+
     public static CenterData template(final Long officeId, final String 
accountNo, final LocalDate activationDate,
             final Collection<OfficeData> officeOptions, final 
Collection<StaffData> staffOptions,
             final Collection<GroupGeneralData> groupMembersOptions, final 
BigDecimal totalCollected, final BigDecimal totalOverdue,
@@ -204,4 +208,8 @@ public class CenterData {
     public String getStaffName() {
         return this.staffName;
     }
+
+    public void setDatatables(final List<DatatableData> datatables) {
+        this.datatables = datatables;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/dde6eaec/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/GroupGeneralData.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/GroupGeneralData.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/GroupGeneralData.java
index 942e655..d6c2259 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/GroupGeneralData.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/GroupGeneralData.java
@@ -19,9 +19,11 @@
 package org.apache.fineract.portfolio.group.data;
 
 import java.util.Collection;
+import java.util.List;
 
 import org.apache.fineract.infrastructure.codes.data.CodeValueData;
 import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
 import org.apache.fineract.organisation.office.data.OfficeData;
 import org.apache.fineract.organisation.staff.data.StaffData;
 import org.apache.fineract.portfolio.calendar.data.CalendarData;
@@ -70,6 +72,8 @@ public class GroupGeneralData {
     private final Collection<CodeValueData> closureReasons;
     private final GroupTimelineData timeline;
 
+    private List<DatatableData> datatables = null;
+
     public static GroupGeneralData lookup(final Long groupId, final String 
accountNo, final String groupName) {
         final Collection<ClientData> clientMembers = null;
         final Collection<GroupRoleData> groupRoles = null;
@@ -256,4 +260,8 @@ public class GroupGeneralData {
     public Collection<ClientData> clientMembers() {
         return this.clientMembers;
     }
+
+    public void setDatatables(final List<DatatableData> datatables) {
+            this.datatables = datatables;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/dde6eaec/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/serialization/GroupingTypesDataValidator.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/serialization/GroupingTypesDataValidator.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/serialization/GroupingTypesDataValidator.java
index bf5362d..b30de36 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/serialization/GroupingTypesDataValidator.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/serialization/GroupingTypesDataValidator.java
@@ -26,6 +26,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import com.google.gson.JsonArray;
 import org.apache.commons.lang.StringUtils;
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
 import org.apache.fineract.infrastructure.core.data.ApiParameterError;
@@ -116,6 +117,11 @@ public final class GroupingTypesDataValidator {
             
baseDataValidator.reset().parameter(GroupingTypesApiConstants.submittedOnDateParamName).value(submittedOnDate).notNull();
         }
 
+        
if(this.fromApiJsonHelper.parameterExists(GroupingTypesApiConstants.datatables, 
element)){
+            final JsonArray datatables = 
this.fromApiJsonHelper.extractJsonArrayNamed(GroupingTypesApiConstants.datatables,
 element);
+            
baseDataValidator.reset().parameter(GroupingTypesApiConstants.datatables).value(datatables).notNull().jsonArrayNotEmpty();
+        }
+
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
     }
 
@@ -180,6 +186,11 @@ public final class GroupingTypesDataValidator {
             
baseDataValidator.reset().parameter(GroupingTypesApiConstants.submittedOnDateParamName).value(submittedOnDate).notNull();
         }
 
+        
if(this.fromApiJsonHelper.parameterExists(GroupingTypesApiConstants.datatables, 
element)){
+            final JsonArray datatables = 
this.fromApiJsonHelper.extractJsonArrayNamed(GroupingTypesApiConstants.datatables,
 element);
+            
baseDataValidator.reset().parameter(GroupingTypesApiConstants.datatables).value(datatables).notNull().jsonArrayNotEmpty();
+        }
+
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
     }
 
@@ -240,6 +251,11 @@ public final class GroupingTypesDataValidator {
             
baseDataValidator.reset().parameter(GroupingTypesApiConstants.submittedOnDateParamName).value(submittedOnDate).notNull();
         }
 
+        
if(this.fromApiJsonHelper.parameterExists(GroupingTypesApiConstants.datatables, 
element)){
+            final JsonArray datatables = 
this.fromApiJsonHelper.extractJsonArrayNamed(GroupingTypesApiConstants.datatables,
 element);
+            
baseDataValidator.reset().parameter(GroupingTypesApiConstants.datatables).value(datatables).notNull().jsonArrayNotEmpty();
+        }
+
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/dde6eaec/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java
index 0cfc7f9..19b4a41 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java
@@ -18,13 +18,7 @@
  */
 package org.apache.fineract.portfolio.group.service;
 
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 import javax.persistence.PersistenceException;
 
@@ -43,33 +37,24 @@ import 
org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
 import 
org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
 import 
org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
 import 
org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
+import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
+import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum;
+import 
org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksWritePlatformService;
 import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
 import org.apache.fineract.organisation.office.domain.Office;
 import org.apache.fineract.organisation.office.domain.OfficeRepositoryWrapper;
 import 
org.apache.fineract.organisation.office.exception.InvalidOfficeException;
 import org.apache.fineract.organisation.staff.domain.Staff;
 import org.apache.fineract.organisation.staff.domain.StaffRepositoryWrapper;
+import org.apache.fineract.portfolio.calendar.domain.*;
 import org.apache.fineract.portfolio.calendar.domain.Calendar;
-import org.apache.fineract.portfolio.calendar.domain.CalendarEntityType;
-import org.apache.fineract.portfolio.calendar.domain.CalendarInstance;
-import 
org.apache.fineract.portfolio.calendar.domain.CalendarInstanceRepository;
-import org.apache.fineract.portfolio.calendar.domain.CalendarType;
 import org.apache.fineract.portfolio.client.domain.AccountNumberGenerator;
 import org.apache.fineract.portfolio.client.domain.Client;
 import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
 import org.apache.fineract.portfolio.client.service.LoanStatusMapper;
 import org.apache.fineract.portfolio.group.api.GroupingTypesApiConstants;
-import org.apache.fineract.portfolio.group.domain.Group;
-import org.apache.fineract.portfolio.group.domain.GroupLevel;
-import org.apache.fineract.portfolio.group.domain.GroupLevelRepository;
-import org.apache.fineract.portfolio.group.domain.GroupRepositoryWrapper;
-import org.apache.fineract.portfolio.group.domain.GroupTypes;
-import 
org.apache.fineract.portfolio.group.exception.GroupAccountExistsException;
-import org.apache.fineract.portfolio.group.exception.GroupHasNoStaffException;
-import 
org.apache.fineract.portfolio.group.exception.GroupMemberCountNotInPermissibleRangeException;
-import 
org.apache.fineract.portfolio.group.exception.GroupMustBePendingToBeDeletedException;
-import 
org.apache.fineract.portfolio.group.exception.InvalidGroupLevelException;
-import 
org.apache.fineract.portfolio.group.exception.InvalidGroupStateTransitionException;
+import org.apache.fineract.portfolio.group.domain.*;
+import org.apache.fineract.portfolio.group.exception.*;
 import 
org.apache.fineract.portfolio.group.serialization.GroupingTypesDataValidator;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
@@ -109,6 +94,7 @@ public class 
GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
     private final SavingsAccountRepositoryWrapper 
savingsAccountRepositoryWrapper;
     private final AccountNumberFormatRepositoryWrapper 
accountNumberFormatRepository;
     private final AccountNumberGenerator accountNumberGenerator;
+    private final EntityDatatableChecksWritePlatformService 
entityDatatableChecksWritePlatformService;
 
     @Autowired
     public GroupingTypesWritePlatformServiceJpaRepositoryImpl(final 
PlatformSecurityContext context,
@@ -119,7 +105,8 @@ public class 
GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
             final CodeValueRepositoryWrapper codeValueRepository, final 
CommandProcessingService commandProcessingService,
             final CalendarInstanceRepository calendarInstanceRepository, final 
ConfigurationDomainService configurationDomainService,
             final LoanRepositoryWrapper loanRepositoryWrapper, 
-            final AccountNumberFormatRepositoryWrapper 
accountNumberFormatRepository, final AccountNumberGenerator 
accountNumberGenerator) {
+            final AccountNumberFormatRepositoryWrapper 
accountNumberFormatRepository, final AccountNumberGenerator 
accountNumberGenerator,
+            final EntityDatatableChecksWritePlatformService 
entityDatatableChecksWritePlatformService) {
         this.context = context;
         this.groupRepository = groupRepository;
         this.clientRepositoryWrapper = clientRepositoryWrapper;
@@ -136,6 +123,7 @@ public class 
GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
         this.loanRepositoryWrapper = loanRepositoryWrapper;
         this.accountNumberFormatRepository = accountNumberFormatRepository;
         this.accountNumberGenerator = accountNumberGenerator;
+        this.entityDatatableChecksWritePlatformService = 
entityDatatableChecksWritePlatformService;
     }
 
     private CommandProcessingResult createGroupingType(final JsonCommand 
command, final GroupTypes groupingType, final Long centerId) {
@@ -219,6 +207,16 @@ public class 
GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
 
             this.groupRepository.saveAndFlush(newGroup);
             newGroup.captureStaffHistoryDuringCenterCreation(staff, 
activationDate);
+
+            if(command.parameterExists(GroupingTypesApiConstants.datatables)){
+                
this.entityDatatableChecksWritePlatformService.saveDatatables(StatusEnum.CREATE.getCode().longValue(),
+                        EntityTables.GROUP.getName(), newGroup.getId(), null,
+                        
command.arrayOfParameterNamed(GroupingTypesApiConstants.datatables));
+            }
+
+            
this.entityDatatableChecksWritePlatformService.runTheCheck(newGroup.getId(), 
EntityTables.GROUP.getName(),
+                    StatusEnum.CREATE.getCode().longValue(), 
EntityTables.GROUP.getForeignKeyColumnNameOnDatatable());
+
             return new CommandProcessingResultBuilder() //
                     .withCommandId(command.commandId()) //
                     .withOfficeId(groupOffice.getId()) //
@@ -296,6 +294,10 @@ public class 
GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
             final LocalDate activationDate = 
command.localDateValueOfParameterNamed("activationDate");
 
             
validateOfficeOpeningDateisAfterGroupOrCenterOpeningDate(group.getOffice(), 
group.getGroupLevel(), activationDate);
+
+            entityDatatableChecksWritePlatformService.runTheCheck(groupId, 
EntityTables.GROUP.getName(),
+                    StatusEnum.ACTIVATE.getCode().longValue(), 
EntityTables.GROUP.getForeignKeyColumnNameOnDatatable());
+
             group.activate(currentUser, activationDate);
 
             this.groupRepository.saveAndFlush(group);
@@ -585,6 +587,9 @@ public class 
GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
 
         validateLoansAndSavingsForGroupOrCenterClose(group, closureDate);
 
+        entityDatatableChecksWritePlatformService.runTheCheck(groupId, 
EntityTables.GROUP.getName(),
+                
StatusEnum.CLOSE.getCode().longValue(),EntityTables.GROUP.getForeignKeyColumnNameOnDatatable());
+
         group.close(currentUser, closureReason, closureDate);
 
         this.groupRepository.saveAndFlush(group);
@@ -657,6 +662,10 @@ public class 
GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
 
         validateLoansAndSavingsForGroupOrCenterClose(center, closureDate);
 
+        entityDatatableChecksWritePlatformService.runTheCheck(centerId, 
EntityTables.GROUP.getName(),
+                StatusEnum.ACTIVATE.getCode().longValue(), 
EntityTables.GROUP.getForeignKeyColumnNameOnDatatable());
+
+
         center.close(currentUser, closureReason, closureDate);
 
         this.groupRepository.saveAndFlush(center);

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/dde6eaec/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java
index d312324..6e5376a 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java
@@ -123,4 +123,5 @@ public interface LoanApiConstants {
     public static final String loanIdToClose = "loanIdToClose";
     public static final String topupAmount = "topupAmount";
 
+    public static final String datatables = "datatables";
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/dde6eaec/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
index c236e37..bded415 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
@@ -20,12 +20,7 @@ package org.apache.fineract.portfolio.loanaccount.api;
 
 import static 
org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations.interestType;
 
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -58,6 +53,10 @@ import 
org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSer
 import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
 import org.apache.fineract.infrastructure.core.service.Page;
 import org.apache.fineract.infrastructure.core.service.SearchParameters;
+import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
+import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
+import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum;
+import 
org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksReadService;
 import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
 import org.apache.fineract.organisation.monetary.data.CurrencyData;
 import org.apache.fineract.organisation.staff.data.StaffData;
@@ -139,7 +138,8 @@ public class LoansApiResource {
             "loanOfficerOptions", "loanPurposeOptions", 
"loanCollateralOptions", "chargeTemplate", "calendarOptions",
             "syncDisbursementWithMeeting", "loanCounter", 
"loanProductCounter", "notes", "accountLinkingOptions", "linkedAccount",
             "interestRateDifferential", "isFloatingInterestRate", 
"interestRatesPeriods", LoanApiConstants.canUseForTopup,
-            LoanApiConstants.isTopup, LoanApiConstants.loanIdToClose, 
LoanApiConstants.topupAmount, LoanApiConstants.clientActiveLoanOptions));
+            LoanApiConstants.isTopup, LoanApiConstants.loanIdToClose, 
LoanApiConstants.topupAmount, LoanApiConstants.clientActiveLoanOptions,
+            LoanApiConstants.datatables));
 
     private final Set<String> LOAN_APPROVAL_DATA_PARAMETERS = new 
HashSet<>(Arrays.asList("approvalDate", "approvalAmount"));
     private final String resourceNameForPermissions = "LOAN";
@@ -168,6 +168,7 @@ public class LoansApiResource {
     private final AccountAssociationsReadPlatformService 
accountAssociationsReadPlatformService;
     private final LoanScheduleHistoryReadPlatformService 
loanScheduleHistoryReadPlatformService;
     private final AccountDetailsReadPlatformService 
accountDetailsReadPlatformService;
+    private final EntityDatatableChecksReadService 
entityDatatableChecksReadService;
 
     @Autowired
     public LoansApiResource(final PlatformSecurityContext context, final 
LoanReadPlatformService loanReadPlatformService,
@@ -187,7 +188,8 @@ public class LoansApiResource {
             final PortfolioAccountReadPlatformService 
portfolioAccountReadPlatformServiceImpl,
             final AccountAssociationsReadPlatformService 
accountAssociationsReadPlatformService,
             final LoanScheduleHistoryReadPlatformService 
loanScheduleHistoryReadPlatformService,
-            final AccountDetailsReadPlatformService 
accountDetailsReadPlatformService) {
+            final AccountDetailsReadPlatformService 
accountDetailsReadPlatformService,
+            final EntityDatatableChecksReadService 
entityDatatableChecksReadService) {
         this.context = context;
         this.loanReadPlatformService = loanReadPlatformService;
         this.loanProductReadPlatformService = loanProductReadPlatformService;
@@ -212,6 +214,7 @@ public class LoansApiResource {
         this.accountAssociationsReadPlatformService = 
accountAssociationsReadPlatformService;
         this.loanScheduleHistoryReadPlatformService = 
loanScheduleHistoryReadPlatformService;
         this.accountDetailsReadPlatformService = 
accountDetailsReadPlatformService;
+        this.entityDatatableChecksReadService = 
entityDatatableChecksReadService;
     }
 
     /*
@@ -347,6 +350,10 @@ public class LoansApiResource {
             newLoanAccount = 
LoanAccountData.associationsAndTemplate(newLoanAccount, productOptions, 
allowedLoanOfficers, calendarOptions,
                     accountLinkingOptions);
         }
+        final List<DatatableData> datatableTemplates = 
this.entityDatatableChecksReadService
+                .retrieveTemplates(StatusEnum.CREATE.getCode().longValue(), 
EntityTables.LOAN.getName(), productId);
+        newLoanAccount.setDatatables(datatableTemplates);
+
         final ApiRequestJsonSerializationSettings settings = 
this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
         return this.toApiJsonSerializer.serialize(settings, newLoanAccount, 
this.LOAN_DATA_PARAMETERS);
     }


Reply via email to