Adhoc Query
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/api/AdHocApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/api/AdHocApiResource.java
new file mode 100644
index 0000000..75380f1
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/api/AdHocApiResource.java
@@ -0,0 +1,170 @@
+/**
+ * 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.adhocquery.api;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.fineract.adhocquery.data.AdHocData;
+import org.apache.fineract.adhocquery.service.AdHocReadPlatformService;
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
+import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
+import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+@Path("/adhocquery")
+@Component
+@Scope("singleton")
+public class AdHocApiResource {
+
+    /**
+     * The set of parameters that are supported in response for {@link AdhocData}
+     */ 
+    private final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("id", "name", "query", "tableName","tableField","isActive","createdBy","createdOn","createdById","updatedById","updatedOn","email"));
+    
+    private final PlatformSecurityContext context;
+    private final AdHocReadPlatformService adHocReadPlatformService;
+    private final DefaultToApiJsonSerializer<AdHocData> toApiJsonSerializer;
+    private final ApiRequestParameterHelper apiRequestParameterHelper;
+    private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+
+    @Autowired
+    public AdHocApiResource(final PlatformSecurityContext context, final AdHocReadPlatformService readPlatformService,
+            final DefaultToApiJsonSerializer<AdHocData> toApiJsonSerializer,
+            final ApiRequestParameterHelper apiRequestParameterHelper,
+            final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
+        this.context = context;
+        this.adHocReadPlatformService = readPlatformService;
+        this.toApiJsonSerializer = toApiJsonSerializer;
+        this.apiRequestParameterHelper = apiRequestParameterHelper;
+        this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+    }
+
+    @GET
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String retrieveAll(@Context final UriInfo uriInfo) {
+    	
+        this.context.authenticatedUser();
+        final Collection<AdHocData> adhocs = this.adHocReadPlatformService.retrieveAllAdHocQuery();
+        final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
+        return this.toApiJsonSerializer.serialize(settings, adhocs, this.RESPONSE_DATA_PARAMETERS);
+    }
+    @GET
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Path("template")
+    public String template(@Context final UriInfo uriInfo) {
+        this.context.authenticatedUser();
+        final AdHocData user = this.adHocReadPlatformService.retrieveNewAdHocDetails();
+        final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
+        return this.toApiJsonSerializer.serialize(settings, user, this.RESPONSE_DATA_PARAMETERS);
+    }
+    @POST
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String createAdHocQuery(final String apiRequestBodyAsJson) {
+
+        final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+                .createAdHoc() //
+                .withJson(apiRequestBodyAsJson) //
+                .build();
+
+        final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
+
+        return this.toApiJsonSerializer.serialize(result);
+    }
+
+    @GET
+    @Path("{adHocId}")
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String retrieveAdHocQuery(@PathParam("adHocId") final Long adHocId, @Context final UriInfo uriInfo) {
+
+        this.context.authenticatedUser();
+
+        final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
+
+        final AdHocData adhoc = this.adHocReadPlatformService.retrieveOne(adHocId);
+
+        return this.toApiJsonSerializer.serialize(settings, adhoc, this.RESPONSE_DATA_PARAMETERS);
+    }
+    @PUT
+    @Path("{adHocId}")
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String update(@PathParam("adHocId") final Long adHocId, final String apiRequestBodyAsJson) {
+
+        final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+                .updateAdHoc(adHocId) //
+                .withJson(apiRequestBodyAsJson) //
+                .build();
+
+        final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
+
+        return this.toApiJsonSerializer.serialize(result);
+    }
+     /**
+     * Delete AdHocQuery
+     * 
+     * @param adHocId
+     * @return
+     */
+    @DELETE
+    @Path("{adHocId}")
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String deleteAdHocQuery(@PathParam("adHocId") final Long adHocId) {
+
+        final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+                .deleteAdHoc(adHocId) //
+                .build();
+
+        final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
+
+        return this.toApiJsonSerializer.serialize(result);
+    }
+
+    private boolean is(final String commandParam, final String commandValue) {
+        return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue);
+    }
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/api/AdHocJsonInputParams.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/api/AdHocJsonInputParams.java
new file mode 100644
index 0000000..0cb3384
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/api/AdHocJsonInputParams.java
@@ -0,0 +1,55 @@
+/**
+ * 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.adhocquery.api;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/***
+ * Enum of all parameters passed in while creating/updating a AdHocQuery 
+ ***/
+public enum AdHocJsonInputParams {
+    ID("id"), NAME("name"),QUERY("query"),TABLENAME("tableName"),TABLEFIELD("tableFields"), ISACTIVE("isActive"),EMAIL("email");
+
+    private final String value;
+
+    private AdHocJsonInputParams(final String value) {
+        this.value = value;
+    }
+
+    private static final Set<String> values = new HashSet<>();
+    static {
+        for (final AdHocJsonInputParams type : AdHocJsonInputParams.values()) {
+            values.add(type.value);
+        }
+    }
+
+    public static Set<String> getAllValues() {
+        return values;
+    }
+
+    @Override
+    public String toString() {
+        return name().toString().replaceAll("_", " ");
+    }
+
+    public String getValue() {
+        return this.value;
+    }
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/data/AdHocData.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/data/AdHocData.java
new file mode 100644
index 0000000..f0fd7a8
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/data/AdHocData.java
@@ -0,0 +1,122 @@
+/**
+ * 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.adhocquery.data;
+
+import java.util.Collection;
+
+import org.apache.fineract.organisation.office.data.OfficeData;
+import org.apache.fineract.useradministration.data.AppUserData;
+import org.apache.fineract.useradministration.data.RoleData;
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+
+/**
+ * Immutable data object represent note or case information AdHocData
+ * 
+ */
+public class AdHocData {
+
+	
+    
+	@SuppressWarnings("unused")
+    private final Long id;
+    @SuppressWarnings("unused")
+    private final String name;
+	@SuppressWarnings("unused")
+    private final String query;
+	@SuppressWarnings("unused")
+    private final String tableName;
+	@SuppressWarnings("unused")
+    private final String tableFields;
+	@SuppressWarnings("unused")
+	private final String email;
+	@SuppressWarnings("unused")
+    private final boolean isActive;
+	@SuppressWarnings("unused")
+    private final DateTime createdOn;
+	@SuppressWarnings("unused")
+	private final Long createdById;
+	@SuppressWarnings("unused")
+    private final Long updatedById;   
+	@SuppressWarnings("unused")
+    private final DateTime updatedOn;
+	@SuppressWarnings("unused")
+	private final String createdBy;
+	
+    
+	
+
+    public AdHocData(final Long id, final String name,final String query, final String tableName,final String tableFields, 
+    		final boolean isActive, final DateTime createdOn, final Long createdById,final Long updatedById,
+    		final DateTime updatedOn,final String createdBy,final String email
+            ) {
+        this.id = id;
+        this.name=name;
+        this.query=query;
+        this.tableName = tableName;
+        this.tableFields = tableFields;
+        this.isActive = isActive;
+        this.createdOn = createdOn;
+        this.createdById = createdById;
+        this.updatedById=updatedById;
+        this.updatedOn=updatedOn;
+        this.createdBy=createdBy;
+        this.email=email;
+    }
+    public static AdHocData template() {
+        AdHocData adHocData = new AdHocData(null,null,null,null,null,false,null,null,null,null,null,null);
+		return adHocData;
+    }
+    public Long getId() {
+		return this.id;
+	}
+	public String getName() {
+		return this.name;
+	}
+	public String getQuery() {
+		return this.query;
+	}
+	public String getTableName() {
+		return this.tableName;
+	}
+	public String getTableFields() {
+		return this.tableFields;
+	}
+	public String getEmail() {
+		return this.email;
+	}
+	public boolean isActive() {
+		return this.isActive;
+	}
+	public DateTime getCreatedOn() {
+		return this.createdOn;
+	}
+	public Long getCreatedById() {
+		return this.createdById;
+	}
+	public Long getUpdatedById() {
+		return this.updatedById;
+	}
+	public DateTime getUpdatedOn() {
+		return this.updatedOn;
+	}
+	public String getCreatedBy() {
+		return this.createdBy;
+	}
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/domain/AdHoc.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/domain/AdHoc.java
new file mode 100644
index 0000000..be315ba
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/domain/AdHoc.java
@@ -0,0 +1,153 @@
+/**
+ * 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.adhocquery.domain;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+import org.apache.commons.lang.BooleanUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.fineract.adhocquery.api.AdHocJsonInputParams;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom;
+import org.apache.fineract.infrastructure.security.utils.SQLInjectionValidator;
+import org.apache.fineract.useradministration.domain.AppUser;
+
+
+@Entity
+@Table(name = "m_adhoc")
+public class AdHoc extends AbstractAuditableCustom<AppUser, Long> {
+
+  	@Column(name = "name", length = 100)
+    private  String name;
+    
+    @Column(name = "query", length = 2000)
+    private  String query;
+   	
+    @Column(name = "table_name", length = 100)
+    private  String tableName;
+    
+    
+    @Column(name = "table_fields", length = 2000)
+    private  String tableFields;
+   	
+    @Column(name = "email", length = 500)
+    private  String email;
+    
+   
+	@Column(name = "IsActive", nullable = false)
+    private boolean isActive = false;
+   	
+    private AdHoc(final String name, final String query,final String tableName,final String tableFields ,final String email,final boolean isActive) {
+        this.name = StringUtils.defaultIfEmpty(name, null);
+        this.query=StringUtils.defaultIfEmpty(query,null);
+        this.tableName=StringUtils.defaultIfEmpty(tableName,null);
+        this.tableFields=StringUtils.defaultIfEmpty(tableFields,null);
+        this.email=StringUtils.defaultIfEmpty(email,null);
+        this.isActive = BooleanUtils.toBooleanDefaultIfNull(isActive, false);
+       
+    }
+    public static AdHoc fromJson(final JsonCommand command) {
+        final String name = command.stringValueOfParameterNamed(AdHocJsonInputParams.NAME.getValue());
+        
+        String commandQuery=command.stringValueOfParameterNamed(AdHocJsonInputParams.QUERY.getValue());
+        
+        SQLInjectionValidator.validateAdhocQuery(commandQuery);
+        final String query = commandQuery;
+        final String tableName = command.stringValueOfParameterNamed(AdHocJsonInputParams.TABLENAME.getValue());
+        final String tableFields = command.stringValueOfParameterNamed(AdHocJsonInputParams.TABLEFIELD.getValue());
+        final String email = command.stringValueOfParameterNamed(AdHocJsonInputParams.EMAIL.getValue());
+        final boolean isActive = command.booleanPrimitiveValueOfParameterNamed(AdHocJsonInputParams.ISACTIVE.getValue());
+        return new AdHoc(name,query,tableName,tableFields ,email,isActive);
+    }
+    
+    public Map<String, Object> update(final JsonCommand command) {
+
+        final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
+
+        final String nameParamName = "name";
+        if (command.isChangeInStringParameterNamed(nameParamName, this.name)) {
+            final String newValue = command.stringValueOfParameterNamed(nameParamName);
+            actualChanges.put(nameParamName, newValue);
+            this.name = newValue;
+        }
+
+        final String descriptionParamName = "query";
+        if (command.isChangeInStringParameterNamed(descriptionParamName, this.query)) {
+            final String newValue = command.stringValueOfParameterNamed(descriptionParamName);
+            actualChanges.put(descriptionParamName, newValue);
+            this.query = newValue;
+        }
+        final String tableName = "tableName";
+        if (command.isChangeInStringParameterNamed(tableName, this.tableName)) {
+            final String newValue = command.stringValueOfParameterNamed(tableName);
+            actualChanges.put(tableName, newValue);
+            this.tableName = newValue;
+        }
+        final String tableField = "tableField";
+        if (command.isChangeInStringParameterNamed(tableField, this.tableFields)) {
+            final String newValue = command.stringValueOfParameterNamed(tableField);
+            actualChanges.put(tableField, newValue);
+            this.tableFields = newValue;
+        }
+        final String email = "email";
+        if (command.isChangeInStringParameterNamed(email, this.email)) {
+            final String newValue = command.stringValueOfParameterNamed(email);
+            actualChanges.put(email, newValue);
+            this.email = newValue;
+        }
+        final String paramisActive = "isActive";
+        if (command.isChangeInBooleanParameterNamed(paramisActive, this.isActive)) {
+        	final Boolean newValue = command.booleanObjectValueOfParameterNamed(paramisActive);
+            actualChanges.put(paramisActive, newValue);
+            this.isActive = newValue;
+        }
+        return actualChanges;
+    }
+    
+    public String getName() {
+		return name;
+	}
+	public String getQuery() {
+		return query;
+	}
+	public String getTableName() {
+		return tableName;
+	}
+	public String getTableFields() {
+		return tableFields;
+	}
+    public boolean isActive() {
+        return this.isActive;
+    }
+	public String getEmail() {
+		return email;
+	}
+    public void disableActive() {
+        this.isActive = true;
+    }
+    public void enableActive() {
+    	this.isActive = false;
+    }
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/domain/AdHocRepository.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/domain/AdHocRepository.java
new file mode 100644
index 0000000..fc31eb7
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/domain/AdHocRepository.java
@@ -0,0 +1,26 @@
+/**
+ * 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.adhocquery.domain;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+public interface AdHocRepository extends JpaRepository<AdHoc, Long>, JpaSpecificationExecutor<AdHoc> {
+    // no added behaviour
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/exception/AdHocNotFoundException.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/exception/AdHocNotFoundException.java
new file mode 100644
index 0000000..7de67f5
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/exception/AdHocNotFoundException.java
@@ -0,0 +1,32 @@
+/**
+ * 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.adhocquery.exception;
+
+import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
+
+/**
+ * A {@link RuntimeException} thrown when AdHoc  resources are not
+ * found.
+ */
+public class AdHocNotFoundException extends AbstractPlatformResourceNotFoundException {
+
+    public AdHocNotFoundException(final Long id) {
+        super("error.msg.adhocquery.adhoc.id.invalid", "Adhoc Record with identifier " + id + " does not exist", id);
+    }
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/handler/CreateAdHocCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/handler/CreateAdHocCommandHandler.java
new file mode 100644
index 0000000..73f09dc
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/handler/CreateAdHocCommandHandler.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.adhocquery.handler;
+
+import org.apache.fineract.adhocquery.service.AdHocWritePlatformService;
+import org.apache.fineract.commands.annotation.CommandType;
+import org.apache.fineract.commands.handler.NewCommandSourceHandler;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@CommandType(entity = "ADHOC", action = "CREATE")
+public class CreateAdHocCommandHandler implements NewCommandSourceHandler {
+
+    private final AdHocWritePlatformService writePlatformService;
+
+    @Autowired
+    public CreateAdHocCommandHandler(final AdHocWritePlatformService writePlatformService) {
+        this.writePlatformService = writePlatformService;
+    }
+
+    @Transactional
+    @Override
+    public CommandProcessingResult processCommand(final JsonCommand command) {
+
+        return this.writePlatformService.createAdHocQuery(command);
+    }
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/handler/DeleteAdHocCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/handler/DeleteAdHocCommandHandler.java
new file mode 100644
index 0000000..eb8e9f6
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/handler/DeleteAdHocCommandHandler.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.adhocquery.handler;
+
+import org.apache.fineract.commands.annotation.CommandType;
+import org.apache.fineract.commands.handler.NewCommandSourceHandler;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.adhocquery.service.AdHocWritePlatformService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@CommandType(entity = "ADHOC", action = "DELETE")
+public class DeleteAdHocCommandHandler implements NewCommandSourceHandler {
+
+    private final AdHocWritePlatformService writePlatformService;
+
+    @Autowired
+    public DeleteAdHocCommandHandler(final AdHocWritePlatformService writePlatformService) {
+        this.writePlatformService = writePlatformService;
+    }
+
+    @Transactional
+    @Override
+    public CommandProcessingResult processCommand(final JsonCommand command) {
+
+        return this.writePlatformService.deleteAdHocQuery(command.entityId());
+    }
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/handler/UpdateAdHocCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/handler/UpdateAdHocCommandHandler.java
new file mode 100644
index 0000000..db9d4ac
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/handler/UpdateAdHocCommandHandler.java
@@ -0,0 +1,48 @@
+/**
+ * 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.adhocquery.handler;
+
+import org.apache.fineract.commands.annotation.CommandType;
+import org.apache.fineract.commands.handler.NewCommandSourceHandler;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.adhocquery.service.AdHocWritePlatformService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@CommandType(entity = "ADHOC", action = "UPDATE")
+public class UpdateAdHocCommandHandler implements NewCommandSourceHandler {
+
+    private final AdHocWritePlatformService writePlatformService;
+
+    @Autowired
+    public UpdateAdHocCommandHandler(final AdHocWritePlatformService writePlatformService) {
+        this.writePlatformService = writePlatformService;
+    }
+
+    @Transactional
+    @Override
+    public CommandProcessingResult processCommand(final JsonCommand command) {
+
+        final Long adHocId = command.entityId();
+        return this.writePlatformService.updateAdHocQuery(adHocId, command);
+    }
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocDataValidator.java
new file mode 100644
index 0000000..2cdd294
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocDataValidator.java
@@ -0,0 +1,127 @@
+/**
+ * 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.adhocquery.service;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.fineract.infrastructure.core.data.ApiParameterError;
+import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
+import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
+import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
+import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.google.gson.JsonElement;
+import com.google.gson.reflect.TypeToken;
+
+@Component
+public final class AdHocDataValidator {
+
+    /**
+     * The parameters supported for this command.
+     */
+    private final Set<String> supportedParameters = new HashSet<>(Arrays.asList("name","query","tableName","tableFields","email","isActive"));
+
+    private final FromJsonHelper fromApiJsonHelper;
+
+    @Autowired
+    public AdHocDataValidator(final FromJsonHelper fromApiJsonHelper) {
+        this.fromApiJsonHelper = fromApiJsonHelper;
+    }
+
+    public void validateForCreate(final String json) {
+        if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
+
+        final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
+        this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters);
+
+        final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+        final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("adhoc");
+
+        final JsonElement element = this.fromApiJsonHelper.parse(json);
+
+        final String name = this.fromApiJsonHelper.extractStringNamed("name", element);
+        baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(100);
+
+        final String description = this.fromApiJsonHelper.extractStringNamed("query", element);
+        baseDataValidator.reset().parameter("query").value(description).notBlank().notExceedingLengthOf(2000);
+        
+        final String tableName = this.fromApiJsonHelper.extractStringNamed("tableName", element);
+        baseDataValidator.reset().parameter("tableName").value(tableName).notBlank().notExceedingLengthOf(100);
+        
+        final String tableFields = this.fromApiJsonHelper.extractStringNamed("tableFields", element);
+        baseDataValidator.reset().parameter("tableFields").value(tableFields).notBlank().notExceedingLengthOf(1000);
+
+        final String email = this.fromApiJsonHelper.extractStringNamed("email", element);
+        baseDataValidator.reset().parameter("email").value(email).notBlank().notExceedingLengthOf(500);
+        throwExceptionIfValidationWarningsExist(dataValidationErrors);
+    }
+
+    public void validateForUpdate(final String json) {
+        if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
+
+        final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
+        this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters);
+
+        final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+        final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("adhoc");
+
+        final JsonElement element = this.fromApiJsonHelper.parse(json);
+
+        if (this.fromApiJsonHelper.parameterExists("name", element)) {
+            final String name = this.fromApiJsonHelper.extractStringNamed("name", element);
+            baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(100);
+        }
+
+        if (this.fromApiJsonHelper.parameterExists("query", element)) {
+            final String query = this.fromApiJsonHelper.extractStringNamed("query", element);
+            baseDataValidator.reset().parameter("query").value(query).notBlank().notExceedingLengthOf(2000);
+        }
+        if (this.fromApiJsonHelper.parameterExists("tableName", element)) {
+            final String tableName = this.fromApiJsonHelper.extractStringNamed("tableName", element);
+            baseDataValidator.reset().parameter("tableName").value(tableName).notBlank().notExceedingLengthOf(100);
+        }
+        if (this.fromApiJsonHelper.parameterExists("tableFields", element)) {
+            final String tableField = this.fromApiJsonHelper.extractStringNamed("tableFields", element);
+            baseDataValidator.reset().parameter("tableFields").value(tableField).notBlank().notExceedingLengthOf(2000);
+        }
+        if (this.fromApiJsonHelper.parameterExists("email", element)) {
+            final String email = this.fromApiJsonHelper.extractStringNamed("email", element);
+            baseDataValidator.reset().parameter("email").value(email).notBlank().notExceedingLengthOf(500);
+        }
+        /*if (this.fromApiJsonHelper.parameterExists("isActive", element)) {
+            final Integer isActive = this.fromApiJsonHelper.extractIntegerNamed("isActive", element, Locale.getDefault());
+            baseDataValidator.reset().parameter("isActive").value(isActive).notNull().inMinMaxRange(1, 2);
+        }*/
+        
+        throwExceptionIfValidationWarningsExist(dataValidationErrors);
+    }
+
+    private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
+        if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
+    }
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocReadPlatformService.java
new file mode 100644
index 0000000..414a2b2
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocReadPlatformService.java
@@ -0,0 +1,34 @@
+/**
+ * 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.adhocquery.service;
+
+import java.util.Collection;
+
+import org.apache.fineract.adhocquery.data.AdHocData;
+
+public interface AdHocReadPlatformService {
+
+    Collection<AdHocData> retrieveAllAdHocQuery();
+
+    Collection<AdHocData> retrieveAllActiveAdHocQuery();
+
+    AdHocData retrieveOne(Long adHocId);
+    AdHocData retrieveNewAdHocDetails();
+    
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocReadPlatformServiceImpl.java
new file mode 100644
index 0000000..eb1f633
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocReadPlatformServiceImpl.java
@@ -0,0 +1,109 @@
+/**
+ * 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.adhocquery.service;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+
+import org.apache.fineract.adhocquery.data.AdHocData;
+import org.apache.fineract.adhocquery.exception.AdHocNotFoundException;
+import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
+import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
+import org.joda.time.DateTime;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Service;
+
+@Service
+public class AdHocReadPlatformServiceImpl implements AdHocReadPlatformService {
+
+    private final JdbcTemplate jdbcTemplate;
+    private final AdHocMapper adHocRowMapper;
+
+    @Autowired
+    public AdHocReadPlatformServiceImpl(final RoutingDataSource dataSource) {
+        this.jdbcTemplate = new JdbcTemplate(dataSource);
+        this.adHocRowMapper = new AdHocMapper();
+    }
+
+    @Override
+    public Collection<AdHocData> retrieveAllAdHocQuery() {
+        final String sql = "select " + this.adHocRowMapper.schema() + " order by r.id";
+
+        return this.jdbcTemplate.query(sql, this.adHocRowMapper);
+    }
+
+    @Override
+    public Collection<AdHocData> retrieveAllActiveAdHocQuery() {
+        final String sql = "select " + this.adHocRowMapper.schema() + " where r.IsActive = 1 order by r.id";
+
+        return this.jdbcTemplate.query(sql, this.adHocRowMapper);
+    }
+
+    @Override
+    public AdHocData retrieveOne(final Long id) {
+
+        try {
+            final String sql = "select " + this.adHocRowMapper.schema() + " where r.id=?";
+
+            return this.jdbcTemplate.queryForObject(sql, this.adHocRowMapper, new Object[] { id });
+        } catch (final EmptyResultDataAccessException e) {
+            throw new AdHocNotFoundException(id);
+        }
+    }
+
+    protected static final class AdHocMapper implements RowMapper<AdHocData> {
+
+        @Override
+        public AdHocData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
+
+            final Long id = JdbcSupport.getLong(rs, "id");
+            final String name = rs.getString("name");
+            final String query = rs.getString("query");
+            final String tableName=rs.getString("tableName");
+            final String tableFields=rs.getString("tableField");
+            final Boolean isActive = rs.getBoolean("isActive");
+            final DateTime createdDate = JdbcSupport.getDateTime(rs, "createdDate");
+            final Long createdById = JdbcSupport.getLong(rs, "createdById");
+            final Long updatedById=JdbcSupport.getLong(rs, "updatedById");
+            final DateTime updatedOn=JdbcSupport.getDateTime(rs, "updatedOn");
+            final String createdByUsername=rs.getString("createdBy");
+            final String email=rs.getString("email");
+          
+            return new AdHocData(id,name,query, tableName,tableFields,isActive,createdDate,createdById,updatedById,updatedOn,createdByUsername,email);
+        }
+
+        public String schema() {
+            return " r.id as id, r.name as name, r.query as query, r.table_name as tableName,r.table_fields as tableField ,r.IsActive as isActive ,r.email as email ,"
+            		+" r.created_date as createdDate, r.createdby_id as createdById,cb.username as createdBy,r.lastmodifiedby_id as updatedById ,r.lastmodified_date as updatedOn "
+                    + " from m_adhoc r left join m_appuser cb on cb.id=r.createdby_id left join m_appuser mb on mb.id=r.lastmodifiedby_id";
+            		        
+        }
+    }
+
+	@Override
+	public AdHocData retrieveNewAdHocDetails() {
+		 return AdHocData.template();
+	}
+
+   
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocScheduledJobRunnerService.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocScheduledJobRunnerService.java
new file mode 100644
index 0000000..88e24a2
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocScheduledJobRunnerService.java
@@ -0,0 +1,23 @@
+/**
+ * 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.adhocquery.service;
+
+public interface AdHocScheduledJobRunnerService {
+    void generateClientSchedule();
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocScheduledJobRunnerServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocScheduledJobRunnerServiceImpl.java
new file mode 100644
index 0000000..d10cddd
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocScheduledJobRunnerServiceImpl.java
@@ -0,0 +1,77 @@
+/**
+ * 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.adhocquery.service;
+
+import java.util.Collection;
+
+import org.apache.fineract.adhocquery.data.AdHocData;
+import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
+import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
+import org.apache.fineract.infrastructure.jobs.annotation.CronTarget;
+import org.apache.fineract.infrastructure.jobs.service.JobName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service(value = "adHocScheduledJobRunnerService")
+public class AdHocScheduledJobRunnerServiceImpl implements AdHocScheduledJobRunnerService {
+
+    private final static Logger logger = LoggerFactory.getLogger(AdHocScheduledJobRunnerServiceImpl.class);
+    private final AdHocReadPlatformService adHocReadPlatformService;
+    private final JdbcTemplate jdbcTemplate;
+    
+    @Autowired
+    public AdHocScheduledJobRunnerServiceImpl(final RoutingDataSource dataSource,
+    		final AdHocReadPlatformService adHocReadPlatformService
+            ) {
+    	this.jdbcTemplate = new JdbcTemplate(dataSource);
+        this.adHocReadPlatformService = adHocReadPlatformService;
+       
+    }
+    @Transactional
+    @Override
+    @CronTarget(jobName = JobName.GENERATE_ADHOCCLIENT_SCEHDULE)
+    public void generateClientSchedule() {
+    	final Collection<AdHocData> adhocs = this.adHocReadPlatformService.retrieveAllActiveAdHocQuery();
+        if(adhocs.size()>0){
+        	adhocs.forEach(adhoc->{
+            	//jdbcTemplate.execute("truncate table "+adhoc.getTableName());
+            	final StringBuilder insertSqlBuilder = new StringBuilder(900);
+                insertSqlBuilder
+                        .append("INSERT INTO ")
+                        .append(adhoc.getTableName()+"(")
+                		.append(adhoc.getTableFields()+") ")
+                		.append(adhoc.getQuery());
+                if (insertSqlBuilder.length() > 0) {
+                	final int result = this.jdbcTemplate.update(insertSqlBuilder.toString());
+                	logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Results affected by inserted: " + result);
+                }
+            });	
+        }else{
+        	logger.info(ThreadLocalContextUtil.getTenant().getName() + "Nothing to update ");
+        }
+        
+        
+   
+    }
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocWritePlatformService.java
new file mode 100644
index 0000000..23427fc
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocWritePlatformService.java
@@ -0,0 +1,35 @@
+/**
+ * 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.adhocquery.service;
+
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+
+public interface AdHocWritePlatformService {
+
+    CommandProcessingResult createAdHocQuery(JsonCommand command);
+
+    CommandProcessingResult updateAdHocQuery(Long adHocId, JsonCommand command);
+ 
+    CommandProcessingResult deleteAdHocQuery(Long adHocId);
+
+    CommandProcessingResult disableAdHocQuery(Long adHocId);
+
+    CommandProcessingResult enableAdHocQuery(Long adHocId);
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocWritePlatformServiceJpaRepositoryImpl.java
new file mode 100644
index 0000000..1cec38d
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocWritePlatformServiceJpaRepositoryImpl.java
@@ -0,0 +1,193 @@
+/**
+ * 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.adhocquery.service;
+
+import java.util.Map;
+
+import org.apache.fineract.adhocquery.domain.AdHoc;
+import org.apache.fineract.adhocquery.domain.AdHocRepository;
+import org.apache.fineract.adhocquery.exception.AdHocNotFoundException;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+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.security.service.PlatformSecurityContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+public class AdHocWritePlatformServiceJpaRepositoryImpl implements AdHocWritePlatformService {
+
+    private final static Logger logger = LoggerFactory.getLogger(AdHocWritePlatformServiceJpaRepositoryImpl.class);
+    private final PlatformSecurityContext context;
+    private final AdHocRepository adHocRepository;
+    private final AdHocDataValidator adHocCommandFromApiJsonDeserializer;
+   
+
+    @Autowired
+    public AdHocWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final AdHocRepository adHocRepository,
+             final AdHocDataValidator adHocCommandFromApiJsonDeserializer) {
+        this.context = context;
+        this.adHocRepository = adHocRepository;
+        this.adHocCommandFromApiJsonDeserializer = adHocCommandFromApiJsonDeserializer;
+       
+    }
+
+    @Transactional
+    @Override
+    public CommandProcessingResult createAdHocQuery(final JsonCommand command) {
+
+        try {
+            this.context.authenticatedUser();
+
+            this.adHocCommandFromApiJsonDeserializer.validateForCreate(command.json());
+
+            final AdHoc entity = AdHoc.fromJson(command);
+            this.adHocRepository.save(entity);
+
+            return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(entity.getId()).build();
+        } catch (final DataIntegrityViolationException dve) {
+            handleDataIntegrityIssues(command, dve);
+            return new CommandProcessingResultBuilder() //
+                    .withCommandId(command.commandId()) //
+                    .build();
+        }
+    }
+
+    /*
+     * Guaranteed to throw an exception no matter what the data integrity issue
+     * is.
+     */
+    private void handleDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) {
+
+        final Throwable realCause = dve.getMostSpecificCause();
+        if (realCause.getMessage().contains("unq_name")) {
+
+            final String name = command.stringValueOfParameterNamed("name");
+            throw new PlatformDataIntegrityException("error.msg.adhocquery.duplicate.name", "AdHocQuery with name `" + name + "` already exists",
+                    "name", name);
+        }
+
+        logAsErrorUnexpectedDataIntegrityException(dve);
+        throw new PlatformDataIntegrityException("error.msg.adhocquery.unknown.data.integrity.issue",
+                "Unknown data integrity issue with resource.");
+    }
+
+    private void logAsErrorUnexpectedDataIntegrityException(final DataIntegrityViolationException dve) {
+        logger.error(dve.getMessage(), dve);
+    }
+
+    @Transactional
+    @Override
+    public CommandProcessingResult updateAdHocQuery(final Long adHocId, final JsonCommand command) {
+        try {
+            this.context.authenticatedUser();
+
+            this.adHocCommandFromApiJsonDeserializer.validateForUpdate(command.json());
+
+            final AdHoc adHoc = this.adHocRepository.findOne(adHocId);
+            if (adHoc == null) { throw new AdHocNotFoundException(adHocId); }
+
+            final Map<String, Object> changes = adHoc.update(command);
+            if (!changes.isEmpty()) {
+                this.adHocRepository.saveAndFlush(adHoc);
+            }
+
+            return new CommandProcessingResultBuilder() //
+                    .withCommandId(command.commandId()) //
+                    .withEntityId(adHocId) //
+                    .with(changes) //
+                    .build();
+        } catch (final DataIntegrityViolationException dve) {
+            handleDataIntegrityIssues(command, dve);
+            return new CommandProcessingResultBuilder() //
+                    .withCommandId(command.commandId()) //
+                    .build();
+        }
+    }
+    /**
+     * Method for Delete adhoc
+     */
+    @Transactional
+    @Override
+    public CommandProcessingResult deleteAdHocQuery(Long adHocId) {
+
+        try {
+            /**
+             * Checking the adhocQuery present in DB or not using adHocId
+             */
+            final AdHoc adHoc = this.adHocRepository.findOne(adHocId);
+            if (adHoc == null) { throw new AdHocNotFoundException(adHocId); }
+            
+            this.adHocRepository.delete(adHoc);
+            return new CommandProcessingResultBuilder().withEntityId(adHocId).build();
+        } catch (final DataIntegrityViolationException e) {
+            throw new PlatformDataIntegrityException("error.msg.unknown.data.integrity.issue",
+                    "Unknown data integrity issue with resource: " + e.getMostSpecificCause());
+        }
+    }
+
+    /**
+     * Method for disabling the adhocquery
+     */
+    @Transactional
+    @Override
+    public CommandProcessingResult disableAdHocQuery(Long adHocId) {
+        try {
+            /**
+             * Checking the adhocquery present in DB or not using adHocId
+             */
+            final AdHoc adHoc = this.adHocRepository.findOne(adHocId);
+            if (adHoc == null) { throw new AdHocNotFoundException(adHocId); }
+            adHoc.disableActive();
+            this.adHocRepository.save(adHoc);
+            return new CommandProcessingResultBuilder().withEntityId(adHocId).build();
+
+        } catch (final DataIntegrityViolationException e) {
+            throw new PlatformDataIntegrityException("error.msg.unknown.data.integrity.issue",
+                    "Unknown data integrity issue with resource: " + e.getMostSpecificCause());
+        }
+    }
+
+    /**
+     * Method for Enabling the Active
+     */
+    @Transactional
+    @Override
+    public CommandProcessingResult enableAdHocQuery(Long adHocId) {
+        try {
+            /**
+             * Checking the adHoc present in DB or not using id
+             */
+            final AdHoc adHoc = this.adHocRepository.findOne(adHocId);
+            if (adHoc == null) { throw new AdHocNotFoundException(adHocId); }
+            adHoc.enableActive();
+            this.adHocRepository.save(adHoc);
+            return new CommandProcessingResultBuilder().withEntityId(adHocId).build();
+
+        } catch (final DataIntegrityViolationException e) {
+            throw new PlatformDataIntegrityException("error.msg.unknown.data.integrity.issue",
+                    "Unknown data integrity issue with resource: " + e.getMostSpecificCause());
+        }
+    }
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
index 46c585b..de85e43 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
@@ -2977,4 +2977,43 @@
         this.href = "/savingsaccounts/" + accountId + "?command=unblock";
         return this;
     }
+	public CommandWrapperBuilder disableAdHoc(Long adHocId) {
+        this.actionName = "DISABLE";
+        this.entityName = "ADHOC";
+        this.entityId = adHocId;
+        this.href = "/adhoc/" + adHocId + "/disbale";
+        this.json = "{}";
+        return this;
+    }
+
+    public CommandWrapperBuilder enableAdHoc(Long adHocId) {
+        this.actionName = "ENABLE";
+        this.entityName = "ADHOC";
+        this.entityId = adHocId;
+        this.href = "/adhoc/" + adHocId + "/enable";
+        this.json = "{}";
+        return this;
+    }
+    public CommandWrapperBuilder createAdHoc() {
+        this.actionName = "CREATE";
+        this.entityName = "ADHOC";
+        this.href = "/adhocquery/template";
+        return this;
+    }
+    public CommandWrapperBuilder updateAdHoc(final Long adHocId) {
+        this.actionName = "UPDATE";
+        this.entityName = "ADHOC";
+        this.entityId = adHocId;
+        this.href = "/adhocquery/" + adHocId;
+        return this;
+    }
+
+    public CommandWrapperBuilder deleteAdHoc(Long adHocId) {
+        this.actionName = "DELETE";
+        this.entityName = "ADHOC";
+        this.entityId = adHocId;
+        this.href = "/adhocquery/" + adHocId;
+        this.json = "{}";
+        return this;
+    }
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
index b0b75b1..f3a160f 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
@@ -45,8 +45,8 @@
     EXECUTE_REPORT_MAILING_JOBS("Execute Report Mailing Jobs"),
     UPDATE_SMS_OUTBOUND_WITH_CAMPAIGN_MESSAGE("Update SMS Outbound with Campaign Message"),
     SEND_MESSAGES_TO_SMS_GATEWAY("Send Messages to SMS Gateway"), 
-    GET_DELIVERY_REPORTS_FROM_SMS_GATEWAY("Get Delivery Reports from SMS Gateway");
-
+    GET_DELIVERY_REPORTS_FROM_SMS_GATEWAY("Get Delivery Reports from SMS Gateway"),
+	GENERATE_ADHOCCLIENT_SCEHDULE("Generate AdhocClient Schedule");
     private final String name;
 
     private JobName(final String name) {
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/utils/SQLInjectionValidator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/utils/SQLInjectionValidator.java
index ef28243..60c2070 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/utils/SQLInjectionValidator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/utils/SQLInjectionValidator.java
@@ -114,4 +114,81 @@
 			throw new SQLInjectionException();
 		}
 	}
+	public final static void validateAdhocQuery(final String sqlSearch) {
+		String lowerCaseSQL = sqlSearch.toLowerCase();
+		for (String ddl : DDL_COMMANDS) {
+			if (lowerCaseSQL.contains(ddl)) {
+				throw new SQLInjectionException();
+			}
+		}
+
+		
+		for (String comments : COMMENTS) {
+			if (lowerCaseSQL.contains(comments)) {
+				throw new SQLInjectionException();
+			}
+		}
+
+		//Removing the space before and after '=' operator 
+		//String s = "          \"              OR 1    =    1"; For the cases like this
+		boolean injectionFound = false;
+		String inputSqlString = lowerCaseSQL;
+		while (inputSqlString.indexOf(" =") > 0) { //Don't remove space before = operator
+			inputSqlString = inputSqlString.replaceAll(" =", "=");
+		}
+
+		while (inputSqlString.indexOf("= ") > 0) { //Don't remove space after = operator
+			inputSqlString = inputSqlString.replaceAll("= ", "=");
+		}
+
+		StringTokenizer tokenizer = new StringTokenizer(inputSqlString, " ");
+		while (tokenizer.hasMoreTokens()) {
+			String token = tokenizer.nextToken().trim();
+			if (token.equals("'")) {
+				if (tokenizer.hasMoreElements()) {
+					String nextToken = tokenizer.nextToken().trim();
+					if (!nextToken.equals("'")) {
+						injectionFound = true;
+						break;
+					}
+				} else {
+					injectionFound = true;
+					break ;
+				}
+			}
+			if (token.equals("\"")) {
+				if (tokenizer.hasMoreElements()) {
+					String nextToken = tokenizer.nextToken().trim();
+					if (!nextToken.equals("\"")) {
+						injectionFound = true;
+						break;
+					}
+				} else {
+					injectionFound = true;
+					break ;
+				}
+			} else if (token.indexOf('=') > 0) {
+				StringTokenizer operatorToken = new StringTokenizer(token, "=");
+				String operand = operatorToken.nextToken().trim();
+				if (!operatorToken.hasMoreTokens()) {
+					injectionFound = true;
+					break;
+				}
+				String value = operatorToken.nextToken().trim();
+				if (operand.equals(value)) {
+					injectionFound = true;
+					break;
+				}
+			}
+		}
+		if (injectionFound) {
+			throw new SQLInjectionException();
+		}
+		
+		Pattern pattern = Pattern.compile(SQL_PATTERN);
+		Matcher matcher = pattern.matcher(sqlSearch);
+		if (!matcher.matches()) {
+			throw new SQLInjectionException();
+		}
+	}
 }
diff --git a/fineract-provider/src/main/resources/META-INF/spring/appContext.xml b/fineract-provider/src/main/resources/META-INF/spring/appContext.xml
index 9fe95d4..dffd1b2 100644
--- a/fineract-provider/src/main/resources/META-INF/spring/appContext.xml
+++ b/fineract-provider/src/main/resources/META-INF/spring/appContext.xml
@@ -55,7 +55,8 @@
 										  org.apache.fineract.template.*,
 										  org.apache.fineract.template.service.*,
 										  org.apache.fineract.useradministration.*,
-										  org.apache.fineract.batch">
+										  org.apache.fineract.batch,
+										  org.apache.fineract.adhocquery.*">
 		<context:exclude-filter expression="org.springframework.stereotype.Controller"
 			type="annotation" />
 
@@ -80,6 +81,7 @@
 	<jpa:repositories base-package="org.apache.fineract.scheduledjobs.domain" />
 	<jpa:repositories base-package="org.apache.fineract.template.domain" />
 	<jpa:repositories base-package="org.apache.fineract.infrastructure.campaigns.sms.domain" />
+	<jpa:repositories base-package="org.apache.fineract.adhocquery.domain" />
 	
 	<import resource="infrastructure.xml" />
 
diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V333__adhocquery.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V333__adhocquery.sql
new file mode 100644
index 0000000..1da45cf
--- /dev/null
+++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V333__adhocquery.sql
@@ -0,0 +1,49 @@
+--
+-- 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.
+--
+
+CREATE TABLE `m_adhoc` (
+	`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
+	`name` VARCHAR(100) NULL DEFAULT NULL,
+	`query` VARCHAR(2000) NULL DEFAULT NULL,
+	`table_name` VARCHAR(100) NULL DEFAULT NULL,
+	`table_fields` VARCHAR(1000) NULL DEFAULT NULL,
+	`email` VARCHAR(500) NOT NULL,
+	`IsActive` TINYINT(1) NOT NULL DEFAULT '0',
+	`created_date` DATETIME NULL DEFAULT NULL,
+	`createdby_id` BIGINT NOT NULL,
+	`lastmodifiedby_id` BIGINT(20) NOT NULL,
+	`lastmodified_date` DATETIME NULL DEFAULT NULL,
+	PRIMARY KEY (`id`),
+	CONSTRAINT `createdby_id` FOREIGN KEY (`createdby_id`) REFERENCES `m_appuser` (`id`),
+	CONSTRAINT `lastmodifiedby_id` FOREIGN KEY (`lastmodifiedby_id`) REFERENCES `m_appuser` (`id`)
+)
+COLLATE='latin1_swedish_ci'
+ENGINE=InnoDB
+;
+
+INSERT INTO `m_permission`
+(`grouping`,`code`,`entity_name`,`action_name`,`can_maker_checker`) VALUES
+('authorisation','UPDATE_ADHOC','ADHOC','UPDATE',1),
+('authorisation','UPDATE_ADHOC_CHECKER','ADHOC','UPDATE',0),
+('authorisation','DELETE_ADHOC','ADHOC','DELETE',1),
+('authorisation','DELETE_ADHOC_CHECKER','ADHOC','DELETE',0),
+('authorisation','CREATE_ADHOC','ADHOC','CREATE',1),
+('authorisation','CREATE_ADHOC_CHECKER','ADHOC','CREATE',0);
+
+INSERT INTO `job` (`name`, `display_name`, `cron_expression`, `create_time`) VALUES ('Generate AdhocClient Schedule', 'Generate AdhocClient Schedule', '0 0 12 1/1 * ? *', now());