Merge branch 'PR378' into develop
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 de85e43..0ad3612 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
@@ -101,6 +101,31 @@
         this.clientId=clientId;
         return this;
     }
+    
+    
+    public CommandWrapperBuilder addFamilyMembers(final long clientId) {
+        this.actionName = "CREATE";
+        this.entityName = "FAMILYMEMBERS";
+        this.href = "/clients/"+clientId+"/familymembers";
+        this.clientId=clientId;
+        return this;
+    }
+  
+    public CommandWrapperBuilder updateFamilyMembers(final long familyMemberId) {
+        this.actionName = "UPDATE";
+        this.entityName = "FAMILYMEMBERS";
+        this.href = "/clients/"+clientId+"/familymembers";
+        this.entityId=familyMemberId;
+        return this;
+    }
+    
+    public CommandWrapperBuilder deleteFamilyMembers(final long familyMemberId) {
+        this.actionName = "DELETE";
+        this.entityName = "FAMILYMEMBERS";
+        this.href = "/clients/"+clientId+"/familymembers";
+        this.entityId=familyMemberId;
+        return this;
+    }
   
     public CommandWrapperBuilder withLoanId(final Long withLoanId) {
         this.loanId = withLoanId;
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 b4d248c..090cc0a 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
@@ -69,6 +69,11 @@
     public static final String localeParamName = "locale";
     public static final String dateFormatParamName = "dateFormat";
     public static final String address = "address";
+    public static final String familyMembers = "familyMembers";
+    public static final String MARITALSTATUS="MARITALSTATUS";
+    public static final String maritalStatusIdParamName="maritalStatusId";
+    
+    
     
     public static final String CLIENT_TYPE_INDIVIDUAL = "Individual";
 
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientFamilyMembersApiResources.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientFamilyMembersApiResources.java
new file mode 100644
index 0000000..92aff71
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientFamilyMembersApiResources.java
@@ -0,0 +1,172 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fineract.portfolio.client.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.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.ToApiJsonSerializer;
+import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.apache.fineract.portfolio.client.data.ClientFamilyMembersData;
+import org.apache.fineract.portfolio.client.service.ClientFamilyMembersReadPlatformService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+@Path("/clients/{clientId}/familymembers")
+@Component
+@Scope("singleton")
+public class ClientFamilyMembersApiResources 
+{
+	private final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("id","clientId","firstName","middleName","lastName","qualification",
+			"relationship","maritalStatus","gender","dateOfBirth","profession","clientFamilyMemberId"));
+	private final String resourceNameForPermissions = "FamilyMembers";
+	private final PlatformSecurityContext context;
+	private final ClientFamilyMembersReadPlatformService readPlatformService;
+	private final ToApiJsonSerializer<ClientFamilyMembersData> toApiJsonSerializer;
+	private final ApiRequestParameterHelper apiRequestParameterHelper;
+	private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+	
+	@Autowired
+	public ClientFamilyMembersApiResources(final PlatformSecurityContext context,final ClientFamilyMembersReadPlatformService readPlatformService,
+			final ToApiJsonSerializer<ClientFamilyMembersData> toApiJsonSerializer,final ApiRequestParameterHelper apiRequestParameterHelper,
+			final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService)
+	{
+		this.context=context;
+		this.readPlatformService=readPlatformService;
+		this.toApiJsonSerializer=toApiJsonSerializer;
+		this.apiRequestParameterHelper=apiRequestParameterHelper;
+		this.commandsSourceWritePlatformService=commandsSourceWritePlatformService; 
+		
+	}
+	
+	@GET
+	@Path("/{familyMemberId}")
+	@Consumes({ MediaType.APPLICATION_JSON })
+	@Produces({ MediaType.APPLICATION_JSON })
+	public String getFamilyMember(@Context final UriInfo uriInfo,@PathParam("familyMemberId") final Long familyMemberId) {
+		
+		this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
+			
+		final ClientFamilyMembersData familyMembers =this.readPlatformService.getClientFamilyMember(familyMemberId);
+	
+		final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
+		return this.toApiJsonSerializer.serialize(settings, familyMembers, this.RESPONSE_DATA_PARAMETERS);
+
+	}
+	
+	
+	
+	@GET
+	@Consumes({ MediaType.APPLICATION_JSON })
+	@Produces({ MediaType.APPLICATION_JSON })
+	public String getFamilyMembers(@Context final UriInfo uriInfo,@PathParam("clientId") final long clientId) {
+		
+		this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
+			
+		final Collection<ClientFamilyMembersData> familyMembers = this.readPlatformService.getClientFamilyMembers(clientId);
+		
+		final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
+		return this.toApiJsonSerializer.serialize(settings, familyMembers, this.RESPONSE_DATA_PARAMETERS);
+
+	}
+	
+	@GET
+	@Path("/template")
+	@Consumes({ MediaType.APPLICATION_JSON })
+	@Produces({ MediaType.APPLICATION_JSON })
+	public String getTemplate(@Context final UriInfo uriInfo,@PathParam("clientId") final long clientId) {
+		
+		this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
+
+		final ClientFamilyMembersData options = this.readPlatformService.retrieveTemplate();
+
+		final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
+		return this.toApiJsonSerializer.serialize(settings, options, this.RESPONSE_DATA_PARAMETERS);
+
+	}
+	
+	
+	@PUT
+	@Path("/{familyMemberId}")
+	@Consumes({ MediaType.APPLICATION_JSON })
+	@Produces({ MediaType.APPLICATION_JSON })
+	public String updateClientFamilyMembers(@PathParam("familyMemberId") final long familyMemberId, final String apiRequestBodyAsJson) {
+
+		final CommandWrapper commandRequest = new CommandWrapperBuilder().updateFamilyMembers(familyMemberId)
+				.withJson(apiRequestBodyAsJson).build();
+
+		final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
+
+		return this.toApiJsonSerializer.serialize(result);
+	}
+	
+	
+	@POST
+	@Consumes({ MediaType.APPLICATION_JSON })
+	@Produces({ MediaType.APPLICATION_JSON })
+	public String addClientFamilyMembers(@PathParam("clientId") final long clientid, final String apiRequestBodyAsJson) {
+
+		final CommandWrapper commandRequest = new CommandWrapperBuilder().addFamilyMembers(clientid)
+				.withJson(apiRequestBodyAsJson).build();
+
+		final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
+
+		return this.toApiJsonSerializer.serialize(result);
+	}
+	
+	
+	@DELETE
+	@Path("/{familyMemberId}")
+	@Consumes({ MediaType.APPLICATION_JSON })
+	@Produces({ MediaType.APPLICATION_JSON })
+	public String deleteClientFamilyMembers(@PathParam("familyMemberId") final long familyMemberId, final String apiRequestBodyAsJson) {
+
+		final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteFamilyMembers(familyMemberId)
+				.withJson(apiRequestBodyAsJson).build();
+
+		final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
+
+		return this.toApiJsonSerializer.serialize(result);
+	}
+	
+	
+	
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientApiCollectionConstants.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientApiCollectionConstants.java
index bf60ba8..04b5fe4 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientApiCollectionConstants.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientApiCollectionConstants.java
@@ -28,14 +28,14 @@
 public class ClientApiCollectionConstants extends ClientApiConstants{
 
     protected static final Set<String> CLIENT_CREATE_REQUEST_DATA_PARAMETERS = new HashSet<>(
-            Arrays.asList(address,localeParamName, dateFormatParamName, groupIdParamName, accountNoParamName, externalIdParamName,
+            Arrays.asList(familyMembers,address,localeParamName, dateFormatParamName, groupIdParamName, accountNoParamName, externalIdParamName,
                     mobileNoParamName, firstnameParamName, middlenameParamName, lastnameParamName, fullnameParamName, officeIdParamName,
                     activeParamName, activationDateParamName, staffIdParamName, submittedOnDateParamName, savingsProductIdParamName,
                     dateOfBirthParamName, genderIdParamName, clientTypeIdParamName, clientClassificationIdParamName,
                     clientNonPersonDetailsParamName, displaynameParamName, legalFormIdParamName, datatables, isStaffParamName));
 
     protected static final Set<String> CLIENT_NON_PERSON_CREATE_REQUEST_DATA_PARAMETERS = new HashSet<>(
-            Arrays.asList(address,localeParamName, dateFormatParamName, incorpNumberParamName, remarksParamName, incorpValidityTillParamName,
+            Arrays.asList(familyMembers,address,localeParamName, dateFormatParamName, incorpNumberParamName, remarksParamName, incorpValidityTillParamName,
                     constitutionIdParamName, mainBusinessLineIdParamName, datatables));
 
     protected static final Set<String> CLIENT_UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
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 5d7e500..3827307 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
@@ -96,6 +96,7 @@
     private final Collection<CodeValueData> clientNonPersonConstitutionOptions;
     private final Collection<CodeValueData> clientNonPersonMainBusinessLineOptions;
     private final List<EnumOptionData> clientLegalFormOptions;
+    private final ClientFamilyMembersData familyMemberOptions;
     
     private final ClientNonPersonData clientNonPersonDetails;
     
@@ -109,7 +110,7 @@
             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 Collection<CodeValueData> clientNonPersonMainBusinessLineOptions, final List<EnumOptionData> clientLegalFormOptions,final ClientFamilyMembersData familyMemberOptions, final AddressData address,
             final Boolean isAddressEnabled, final List<DatatableData> datatables) {
         final String accountNo = null;
         final EnumOptionData status = null;
@@ -146,7 +147,7 @@
                 staffName, officeOptions, groups, staffOptions, narrations, genderOptions, timeline, savingProductOptions,
                 savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType, clientClassification,
                 clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, 
-                clientNonPersonDetails, clientLegalFormOptions, legalForm,address, isAddressEnabled, datatables, isStaff);
+                clientNonPersonDetails, clientLegalFormOptions,familyMemberOptions, legalForm,address, isAddressEnabled, datatables, isStaff);
 
     }
 
@@ -161,7 +162,7 @@
                 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, null, clientData.isStaff);
+                templateData.clientLegalFormOptions,templateData.familyMemberOptions, clientData.legalForm, clientData.address,clientData.isAddressEnabled, null, clientData.isStaff);
 
     }
 
@@ -177,7 +178,7 @@
                 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, null, clientData.isStaff);
+                clientData.clientLegalFormOptions,clientData.familyMemberOptions, clientData.legalForm,clientData.address, clientData.isAddressEnabled, null, clientData.isStaff);
 
     }
 
@@ -190,7 +191,7 @@
                 clientData.savingProductOptions, clientData.savingsProductId, clientData.savingsProductName, clientData.savingsAccountId,
                 clientData.savingAccountOptions, clientData.clientType, clientData.clientClassification, clientData.clientTypeOptions,
                 clientData.clientClassificationOptions, clientData.clientNonPersonConstitutionOptions, clientData.clientNonPersonMainBusinessLineOptions, 
-                clientData.clientNonPersonDetails, clientData.clientLegalFormOptions, clientData.legalForm,clientData.address,
+                clientData.clientNonPersonDetails, clientData.clientLegalFormOptions,clientData.familyMemberOptions, clientData.legalForm,clientData.address,
 				clientData.isAddressEnabled, null, clientData.isStaff);
 
     }
@@ -226,6 +227,7 @@
         final Collection<CodeValueData> clientNonPersonConstitutionOptions = null;
         final Collection<CodeValueData> clientNonPersonMainBusinessLineOptions = null;
         final List<EnumOptionData> clientLegalFormOptions = null;
+        final ClientFamilyMembersData familyMemberOptions=null;
         final EnumOptionData status = null;
         final CodeValueData subStatus = null;
         final EnumOptionData legalForm = null;
@@ -236,7 +238,7 @@
                 staffName, allowedOffices, groups, staffOptions, closureReasons, genderOptions, timeline, savingProductOptions,
                 savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType, clientClassification,
                 clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, 
-                clientNonPerson, clientLegalFormOptions, legalForm,null,null, null, isStaff);
+                clientNonPerson, clientLegalFormOptions,familyMemberOptions, legalForm,null,null, null, isStaff);
     }
 
     public static ClientData lookup(final Long id, final String displayName, final Long officeId, final String officeName) {
@@ -275,6 +277,7 @@
         final Collection<CodeValueData> clientNonPersonConstitutionOptions = null;
         final Collection<CodeValueData> clientNonPersonMainBusinessLineOptions = null;
         final List<EnumOptionData> clientLegalFormOptions = null;
+        final ClientFamilyMembersData familyMemberOptions=null;
         final EnumOptionData legalForm = null;
 		final Boolean isStaff = false;
         final ClientNonPersonData clientNonPerson = null;
@@ -283,7 +286,7 @@
                 staffName, allowedOffices, groups, staffOptions, closureReasons, genderOptions, timeline, savingProductOptions,
                 savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType, clientClassification,
                 clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, 
-                clientNonPerson, clientLegalFormOptions, legalForm,null,null, null, isStaff);
+                clientNonPerson, clientLegalFormOptions,familyMemberOptions, legalForm,null,null, null, isStaff);
 
     }
 
@@ -306,12 +309,13 @@
         final Collection<CodeValueData> clientNonPersonConstitutionOptions = null;
         final Collection<CodeValueData> clientNonPersonMainBusinessLineOptions = null;
         final List<EnumOptionData> clientLegalFormOptions = null;
+        final ClientFamilyMembersData familyMemberOptions=null;
         return new ClientData(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname,
                 middlename, lastname, fullname, displayName, externalId, mobileNo, dateOfBirth, gender, activationDate, imageId, staffId,
                 staffName, allowedOffices, groups, staffOptions, closureReasons, genderOptions, timeline, savingProductOptions,
                 savingsProductId, savingsProductName, savingsAccountId, null, clientType, clientClassification, clientTypeOptions,
                 clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, clientNonPerson,
-                clientLegalFormOptions, legalForm,null,null, null, isStaff);
+                clientLegalFormOptions,familyMemberOptions, legalForm,null,null, null, isStaff);
 
     }
 
@@ -328,7 +332,7 @@
             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 List<EnumOptionData> clientLegalFormOptions,final ClientFamilyMembersData familyMemberOptions, final EnumOptionData legalForm, final AddressData address,
             final Boolean isAddressEnabled, final List<DatatableData> datatables, final Boolean isStaff) {
         this.accountNo = accountNo;
         this.status = status;
@@ -379,6 +383,7 @@
         this.clientNonPersonConstitutionOptions = clientNonPersonConstitutionOptions;
         this.clientNonPersonMainBusinessLineOptions = clientNonPersonMainBusinessLineOptions;
         this.clientLegalFormOptions = clientLegalFormOptions;
+        this.familyMemberOptions=familyMemberOptions;
 
         this.timeline = timeline;
         this.savingProductOptions = savingProductOptions;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientFamilyMembersData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientFamilyMembersData.java
new file mode 100644
index 0000000..305ba4b
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientFamilyMembersData.java
@@ -0,0 +1,197 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fineract.portfolio.client.data;
+
+import java.util.Collection;
+
+import org.apache.fineract.infrastructure.codes.data.CodeValueData;
+import org.joda.time.LocalDate;
+
+public class ClientFamilyMembersData {
+
+	private final Long id;
+
+	private final Long clientId;
+
+	private final String firstName;
+
+	private final String middleName;
+
+	private final String lastName;
+
+	private final String qualification;
+
+	private final Long relationshipId;
+
+	private final String relationship;
+
+	private final Long maritalStatusId;
+
+	private final String maritalStatus;
+
+	private final Long genderId;
+
+	private final String gender;
+
+	private final LocalDate dateOfBirth;
+
+	private final Long professionId;
+
+	private final String profession;
+	
+	private final String mobileNumber;
+	
+	private final Long age;
+	
+	private final Boolean isDependent;
+
+	// template holder
+	private final Collection<CodeValueData> relationshipIdOptions;
+	private final Collection<CodeValueData> genderIdOptions;
+	private final Collection<CodeValueData> maritalStatusIdOptions;
+	private final Collection<CodeValueData> professionIdOptions;
+
+	private ClientFamilyMembersData(final Long id, final Long clientId, final String firstName, final String middleName,
+			final String lastName, final String qualification,final String mobileNumber,final Long age,final Boolean isDependent, final String relationship, final Long relationshipId,
+			final String maritalStatus, final Long maritalStatusId, final String gender, final Long genderId,
+			final LocalDate dateOfBirth, final String profession, final Long professionId,
+			final Collection<CodeValueData> relationshipIdOptions,final Collection<CodeValueData> genderIdOptions,final Collection<CodeValueData> maritalStatusIdOptions,
+			final Collection<CodeValueData> professionIdOptions) {
+		this.id = id;
+		this.clientId = clientId;
+		this.firstName = firstName;
+		this.middleName = middleName;
+		this.lastName = lastName;
+		this.qualification = qualification;
+		this.relationship = relationship;
+		this.relationshipId = relationshipId;
+		this.maritalStatus = maritalStatus;
+		this.maritalStatusId = maritalStatusId;
+		this.gender = gender;
+		this.genderId = genderId;
+		this.dateOfBirth = dateOfBirth;
+		this.profession = profession;
+		this.professionId = professionId;
+		this.mobileNumber=mobileNumber;
+		this.age=age;
+		this.isDependent=isDependent;
+		this.relationshipIdOptions=relationshipIdOptions;
+		this.genderIdOptions=genderIdOptions;
+		this.maritalStatusIdOptions=maritalStatusIdOptions;
+		this.professionIdOptions=professionIdOptions;
+		
+	}
+
+	public static ClientFamilyMembersData instance(final Long id, final Long clientId, final String firstName,
+			final String middleName, final String lastName, final String qualification,final String mobileNumber,final Long age,final Boolean isDependent, final String relationship,
+			final Long relationshipId, final String maritalStatus, final Long maritalStatusId, final String gender,
+			final Long genderId, final LocalDate dateOfBirth, final String profession, final Long professionId
+			) {
+		return new ClientFamilyMembersData(id, clientId, firstName, middleName, lastName, qualification,mobileNumber,age,isDependent, relationship,
+				relationshipId, maritalStatus, maritalStatusId, gender, genderId, dateOfBirth, profession,
+				professionId,null,null,null,null);
+	}
+	
+	
+	public static ClientFamilyMembersData templateInstance(final Collection<CodeValueData> relationshipIdOptions,
+			final Collection<CodeValueData> genderIdOptions,final Collection<CodeValueData> maritalStatusIdOptions,
+			final Collection<CodeValueData> professionIdOptions) {
+		
+		
+		return new ClientFamilyMembersData(null, null, null, null, null, null,null,
+				null, null, null, null, null, null, null,
+				null,null,null,null,relationshipIdOptions,genderIdOptions,maritalStatusIdOptions,professionIdOptions);
+	}
+
+	public Long getId() {
+		return this.id;
+	}
+
+	public Long getClientId() {
+		return this.clientId;
+	}
+
+	public String getFirstName() {
+		return this.firstName;
+	}
+
+	public String getMiddleName() {
+		return this.middleName;
+	}
+
+	public String getLastName() {
+		return this.lastName;
+	}
+
+	public String getQualification() {
+		return this.qualification;
+	}
+
+	public Long getRelationshipId() {
+		return this.relationshipId;
+	}
+
+	public String getRelationship() {
+		return this.relationship;
+	}
+
+	public Long getMaritalStatusId() {
+		return this.maritalStatusId;
+	}
+
+	public String getMaritalStatus() {
+		return this.maritalStatus;
+	}
+
+	public Long getGenderId() {
+		return this.genderId;
+	}
+
+	public String getGender() {
+		return this.gender;
+	}
+
+	public LocalDate getDateOfBirth() {
+		return this.dateOfBirth;
+	}
+
+	public Long getProfessionId() {
+		return this.professionId;
+	}
+
+	public String getProfession() {
+		return this.profession;
+	}
+
+	public String getMobileNumber() {
+		return this.mobileNumber;
+	}
+
+	public Long getAge() {
+		return this.age;
+	}
+
+	public Boolean getIsDependent() {
+		return this.isDependent;
+	}
+	
+	
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientFamilyMembers.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientFamilyMembers.java
new file mode 100644
index 0000000..a1419c4
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientFamilyMembers.java
@@ -0,0 +1,238 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fineract.portfolio.client.domain;
+
+import java.util.Date;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import org.apache.fineract.infrastructure.codes.domain.CodeValue;
+import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
+
+@Entity
+@Table(name = "m_family_members")
+public class ClientFamilyMembers extends AbstractPersistableCustom<Long> {
+	
+	@ManyToOne
+	@JoinColumn(name="client_id")
+	private Client client;
+	
+	@Column(name="firstname")
+	private String firstName;
+	
+	@Column(name="middleName")
+	private String middleName;
+	
+	@Column(name="lastName")
+	private String lastName;
+	
+	@Column(name="qualification")
+	private String qualification;
+	
+	@Column(name="mobile_number")
+	private String mobileNumber;
+	
+	@Column(name="age")
+	private Long age;
+	
+	@Column(name="is_dependent")
+	private Boolean isDependent;
+	
+	
+	@ManyToOne
+	@JoinColumn(name = "relationship_cv_id")
+	private CodeValue relationship;
+	
+	@ManyToOne
+	@JoinColumn(name = "marital_status_cv_id")
+	private CodeValue maritalStatus;
+	
+	
+	@ManyToOne
+	@JoinColumn(name = "gender_cv_id")
+	private CodeValue gender;
+	
+	@ManyToOne
+	@JoinColumn(name = "profession_cv_id")
+	private CodeValue profession;
+	
+	 @Column(name = "date_of_birth", nullable = true)
+	 @Temporal(TemporalType.DATE)
+	 private Date dateOfBirth;
+	
+		private ClientFamilyMembers(final Client client,final String firstName,
+				final String middleName,final String lastName,final String qualification,
+				final String mobileNumber,final Long age,final Boolean isDependent,
+				final CodeValue relationship,final CodeValue maritalStatus,final CodeValue gender,
+				final Date dateOfBirth,final CodeValue profession)
+		{
+			
+			this.client=client;
+			this.firstName=firstName;
+			this.middleName=middleName;
+			this.lastName=lastName;
+			this.qualification=qualification;
+			this.age=age;
+			this.mobileNumber=mobileNumber;
+			this.isDependent=isDependent;
+			this.relationship=relationship;
+			this.maritalStatus=maritalStatus;
+			this.gender=gender;
+			this.dateOfBirth=dateOfBirth;
+			this.profession=profession;
+		}
+		
+		
+		public ClientFamilyMembers()
+		{
+			
+		}
+		
+		public static ClientFamilyMembers fromJson(final Client client,final String firstName,
+				final String middleName,final String lastName,final String qualification,
+				final String mobileNumber,final Long age,final Boolean isDependent,
+				final CodeValue relationship,final CodeValue maritalStatus,final CodeValue gender,
+				final Date dateOfBirth,final CodeValue profession)
+		{
+			return new ClientFamilyMembers(client,firstName,middleName,lastName,qualification,
+					mobileNumber,age,isDependent,relationship,maritalStatus,gender,
+					dateOfBirth,profession);
+		}
+
+		public Client getClient() {
+			return this.client;
+		}
+
+		public void setClient(Client client) {
+			this.client = client;
+		}
+
+		public String getFirstName() {
+			return this.firstName;
+		}
+
+		public void setFirstName(String firstName) {
+			this.firstName = firstName;
+		}
+
+		public String getMiddleName() {
+			return this.middleName;
+		}
+
+		public void setMiddleName(String middleName) {
+			this.middleName = middleName;
+		}
+
+		public String getLastName() {
+			return this.lastName;
+		}
+
+		public void setLastName(String lastName) {
+			this.lastName = lastName;
+		}
+
+		public String getQualification() {
+			return this.qualification;
+		}
+
+		public void setQualification(String qualification) {
+			this.qualification = qualification;
+		}
+
+		public CodeValue getRelationship() {
+			return this.relationship;
+		}
+
+		public void setRelationship(CodeValue relationship) {
+			this.relationship = relationship;
+		}
+
+		public CodeValue getMaritalStatus() {
+			return this.maritalStatus;
+		}
+
+		public void setMaritalStatus(CodeValue maritalStatus) {
+			this.maritalStatus = maritalStatus;
+		}
+
+		public CodeValue getGender() {
+			return this.gender;
+		}
+
+		public void setGender(CodeValue gender) {
+			this.gender = gender;
+		}
+
+		public CodeValue getProfession() {
+			return this.profession;
+		}
+
+		public void setProfession(CodeValue profession) {
+			this.profession = profession;
+		}
+
+		public Date getDateOfBirth() {
+			return this.dateOfBirth;
+		}
+
+		public void setDateOfBirth(Date dateOfBirth) {
+			this.dateOfBirth = dateOfBirth;
+		}
+
+
+		public String getMobileNumber() {
+			return this.mobileNumber;
+		}
+
+
+		public void setMobileNumber(String mobileNumber) {
+			this.mobileNumber = mobileNumber;
+		}
+
+
+		public Long getAge() {
+			return this.age;
+		}
+
+
+		public void setAge(Long age) {
+			this.age = age;
+		}
+
+
+		public Boolean getIsDependent() {
+			return this.isDependent;
+		}
+
+
+		public void setIsDependent(Boolean isDependent) {
+			this.isDependent = isDependent;
+		}
+		
+		
+	
+	
+	
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientFamilyMembersRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientFamilyMembersRepository.java
new file mode 100644
index 0000000..8aebd90
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientFamilyMembersRepository.java
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fineract.portfolio.client.domain;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+public interface ClientFamilyMembersRepository 
+extends JpaRepository<ClientFamilyMembers, Long>, JpaSpecificationExecutor<ClientFamilyMembers>
+{
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/AddClientFamilyMemberCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/AddClientFamilyMemberCommandHandler.java
new file mode 100644
index 0000000..7ab2c58
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/AddClientFamilyMemberCommandHandler.java
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fineract.portfolio.client.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.portfolio.client.service.ClientFamilyMembersWritePlatformService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+
+@Service
+@CommandType(entity = "FAMILYMEMBERS", action = "CREATE")
+public class AddClientFamilyMemberCommandHandler implements NewCommandSourceHandler 
+{
+
+	private final ClientFamilyMembersWritePlatformService clientFamilyMembersWritePlatformService;
+	
+	@Autowired
+	public AddClientFamilyMemberCommandHandler(final ClientFamilyMembersWritePlatformService clientFamilyMembersWritePlatformService)
+	{
+		this.clientFamilyMembersWritePlatformService=clientFamilyMembersWritePlatformService;
+	}
+	
+	@Override
+	public CommandProcessingResult processCommand(JsonCommand command) {
+	
+		return this.clientFamilyMembersWritePlatformService.addFamilyMember(command.getClientId(), command);
+	}
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/DeleteClientFamilyMemberCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/DeleteClientFamilyMemberCommandHandler.java
new file mode 100644
index 0000000..484478c
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/DeleteClientFamilyMemberCommandHandler.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fineract.portfolio.client.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.portfolio.client.service.ClientFamilyMembersWritePlatformService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+@CommandType(entity = "FAMILYMEMBERS", action = "DELETE")
+public class DeleteClientFamilyMemberCommandHandler implements NewCommandSourceHandler {
+
+private final ClientFamilyMembersWritePlatformService clientFamilyMembersWritePlatformService;
+	
+	@Autowired
+	public DeleteClientFamilyMemberCommandHandler(final ClientFamilyMembersWritePlatformService clientFamilyMembersWritePlatformService)
+	{
+		this.clientFamilyMembersWritePlatformService=clientFamilyMembersWritePlatformService;
+	}
+	
+	@Override
+	public CommandProcessingResult processCommand(JsonCommand command) {
+	
+		return this.clientFamilyMembersWritePlatformService.deleteFamilyMember(command.entityId(), command);
+	}
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/UpdateClientFamilyMemberCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/UpdateClientFamilyMemberCommandHandler.java
new file mode 100644
index 0000000..69c25f3
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/UpdateClientFamilyMemberCommandHandler.java
@@ -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.
+ */
+
+package org.apache.fineract.portfolio.client.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.portfolio.client.service.ClientFamilyMembersWritePlatformService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+
+@Service
+@CommandType(entity = "FAMILYMEMBERS", action = "UPDATE")
+public class UpdateClientFamilyMemberCommandHandler implements NewCommandSourceHandler {
+
+	private final ClientFamilyMembersWritePlatformService clientFamilyMembersWritePlatformService;
+	
+	@Autowired
+	public UpdateClientFamilyMemberCommandHandler(final ClientFamilyMembersWritePlatformService clientFamilyMembersWritePlatformService)
+	{
+		this.clientFamilyMembersWritePlatformService=clientFamilyMembersWritePlatformService;
+	}
+	
+	@Override
+	public CommandProcessingResult processCommand(JsonCommand command) {
+	
+		return this.clientFamilyMembersWritePlatformService.updateFamilyMember(command.entityId(), command);
+	}
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/serialization/ClientFamilyMemberCommandFromApiJsonDeserializer.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/serialization/ClientFamilyMemberCommandFromApiJsonDeserializer.java
new file mode 100644
index 0000000..e5354fe
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/serialization/ClientFamilyMemberCommandFromApiJsonDeserializer.java
@@ -0,0 +1,313 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fineract.portfolio.client.serialization;
+
+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.serialization.FromJsonHelper;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
+import org.joda.time.LocalDate;
+import org.joda.time.LocalDateTime;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.reflect.TypeToken;
+
+@Component
+public class ClientFamilyMemberCommandFromApiJsonDeserializer 
+{
+	private final FromJsonHelper fromApiJsonHelper;
+	 private final Set<String> supportedParameters = new HashSet<>(Arrays.asList("id","clientId","firstName","middleName","lastName","qualification","mobileNumber",
+			 "age","isDependent","relationshipId","maritalStatusId","genderId","dateOfBirth","professionId","locale","dateFormat","familyMembers"));
+	
+	@Autowired
+	private ClientFamilyMemberCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper)
+	{
+			this.fromApiJsonHelper=fromApiJsonHelper;
+	}
+	
+	
+	public void validateForCreate(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("FamilyMembers");
+		
+		final JsonElement element = this.fromApiJsonHelper.parse(json);
+		
+		
+			
+			
+			if(this.fromApiJsonHelper.extractArrayNamed("familyMembers", element)!=null)
+			{
+				final JsonArray familyMembers= this.fromApiJsonHelper.extractJsonArrayNamed("familyMembers", element);
+				baseDataValidator.reset().value(familyMembers).arrayNotEmpty();
+			}
+			else
+			{
+				baseDataValidator.reset().value(this.fromApiJsonHelper.extractJsonArrayNamed("familyMembers", element)).arrayNotEmpty();
+			}
+			
+			
+			validateForCreate(1,json);
+			
+		}
+		
+	
+	
+	public void validateForCreate(final long clientId,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("FamilyMembers");
+
+		final JsonElement element = this.fromApiJsonHelper.parse(json);
+		
+		baseDataValidator.reset().value(clientId).notBlank().integerGreaterThanZero();
+		
+		if(this.fromApiJsonHelper.extractStringNamed("firstName", element)!=null)
+		{
+			final String firstName = this.fromApiJsonHelper.extractStringNamed("firstName", element);
+			baseDataValidator.reset().parameter("firstName").value(firstName).notNull().notBlank().notExceedingLengthOf(100);	
+		}
+		else
+		{
+			baseDataValidator.reset().parameter("firstName").value(this.fromApiJsonHelper.extractStringNamed("firstName", element)).notNull().notBlank().notExceedingLengthOf(100);
+		}
+		
+		if(this.fromApiJsonHelper.extractStringNamed("lastName", element)!=null)
+		{
+			final String lastName = this.fromApiJsonHelper.extractStringNamed("lastName", element);
+			baseDataValidator.reset().parameter("lastName").value(lastName).notNull().notBlank().notExceedingLengthOf(100);	
+		}
+		
+		
+		if(this.fromApiJsonHelper.extractStringNamed("middleName", element)!=null)
+		{
+			final String middleName = this.fromApiJsonHelper.extractStringNamed("middleName", element);
+			baseDataValidator.reset().parameter("middleName").value(middleName).notNull().notBlank().notExceedingLengthOf(100);	
+		}
+		
+		
+		if(this.fromApiJsonHelper.extractStringNamed("qualification", element)!=null)
+		{
+			final String qualification = this.fromApiJsonHelper.extractStringNamed("qualification", element);
+			baseDataValidator.reset().parameter("qualification").value(qualification).notNull().notBlank().notExceedingLengthOf(100);	
+		}
+		
+		if(this.fromApiJsonHelper.extractStringNamed("mobileNumber", element)!=null)
+		{
+			final String mobileNumber = this.fromApiJsonHelper.extractStringNamed("mobileNumber", element);
+			baseDataValidator.reset().parameter("mobileNumber").value(mobileNumber).notNull().notBlank().notExceedingLengthOf(100);	
+		}
+		
+		if(this.fromApiJsonHelper.extractBooleanNamed("isDependent", element)!=null)
+		{
+			final Boolean isDependent = this.fromApiJsonHelper.extractBooleanNamed("isDependent", element);
+			baseDataValidator.reset().parameter("isDependent").value(isDependent).notNull().notBlank().notExceedingLengthOf(100);	
+		}
+		
+		if(this.fromApiJsonHelper.extractLongNamed("relationShipId", element)!=null)
+		{
+			final long relationShipId=this.fromApiJsonHelper.extractLongNamed("relationShipId", element);
+			baseDataValidator.reset().parameter("relationShipId").value(relationShipId).notBlank().longGreaterThanZero();
+			
+		}
+		else
+		{
+			baseDataValidator.reset().parameter("relationShipId").value(this.fromApiJsonHelper.extractLongNamed("relationShipId", element)).notBlank().longGreaterThanZero();
+		}
+		
+		if(this.fromApiJsonHelper.extractLongNamed("maritalStatusId", element)!=null)
+		{
+			final long maritalStatusId=this.fromApiJsonHelper.extractLongNamed("maritalStatusId", element);
+			baseDataValidator.reset().parameter("maritalStatusId").value(maritalStatusId).notBlank().longGreaterThanZero();
+			
+		}
+		
+		if(this.fromApiJsonHelper.extractLongNamed("genderId", element)!=null)
+		{
+			final long genderId=this.fromApiJsonHelper.extractLongNamed("genderId", element);
+			baseDataValidator.reset().parameter("genderId").value(genderId).notBlank().longGreaterThanZero();
+			
+		}
+		
+		if(this.fromApiJsonHelper.extractLongNamed("age", element)!=null)
+		{
+			final long age=this.fromApiJsonHelper.extractLongNamed("age", element);
+			baseDataValidator.reset().parameter("age").value(age).notBlank().longGreaterThanZero();
+			
+		}
+		
+		if(this.fromApiJsonHelper.extractLongNamed("professionId", element)!=null)
+		{
+			final long professionId=this.fromApiJsonHelper.extractLongNamed("professionId", element);
+			baseDataValidator.reset().parameter("professionId").value(professionId).notBlank().longGreaterThanZero();
+			
+		}
+		
+		
+		if(this.fromApiJsonHelper.extractLocalDateNamed("dateOfBirth", element)!=null)
+		{
+			final LocalDate dateOfBirth=this.fromApiJsonHelper.extractLocalDateNamed("dateOfBirth", element);
+			baseDataValidator.reset().parameter("dateOfBirth").value(dateOfBirth).value(dateOfBirth).notNull()
+            .validateDateBefore(DateUtils.getLocalDateOfTenant());
+			
+		}
+		
+	
+		
+	}
+	
+	
+	public void validateForUpdate(final long familyMemberId,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("FamilyMembers");
+
+		final JsonElement element = this.fromApiJsonHelper.parse(json);
+		
+		baseDataValidator.reset().value(familyMemberId).notBlank().integerGreaterThanZero();
+		
+		if(this.fromApiJsonHelper.extractStringNamed("firstName", element)!=null)
+		{
+			final String firstName = this.fromApiJsonHelper.extractStringNamed("firstName", element);
+			baseDataValidator.reset().parameter("firstName").value(firstName).notNull().notBlank().notExceedingLengthOf(100);	
+		}
+		
+		
+		if(this.fromApiJsonHelper.extractStringNamed("lastName", element)!=null)
+		{
+			final String lastName = this.fromApiJsonHelper.extractStringNamed("lastName", element);
+			baseDataValidator.reset().parameter("lastName").value(lastName).notNull().notBlank().notExceedingLengthOf(100);	
+		}
+		
+		
+		if(this.fromApiJsonHelper.extractStringNamed("middleName", element)!=null)
+		{
+			final String middleName = this.fromApiJsonHelper.extractStringNamed("middleName", element);
+			baseDataValidator.reset().parameter("middleName").value(middleName).notNull().notBlank().notExceedingLengthOf(100);	
+		}
+		
+		
+		if(this.fromApiJsonHelper.extractStringNamed("qualification", element)!=null)
+		{
+			final String qualification = this.fromApiJsonHelper.extractStringNamed("qualification", element);
+			baseDataValidator.reset().parameter("qualification").value(qualification).notNull().notBlank().notExceedingLengthOf(100);	
+		}
+		
+		if(this.fromApiJsonHelper.extractLongNamed("relationShipId", element)!=null)
+		{
+			final long relationShipId=this.fromApiJsonHelper.extractLongNamed("relationShipId", element);
+			baseDataValidator.reset().parameter("relationShipId").value(relationShipId).notBlank().longGreaterThanZero();
+			
+		}
+	
+		
+		if(this.fromApiJsonHelper.extractLongNamed("maritalStatusId", element)!=null)
+		{
+			final long maritalStatusId=this.fromApiJsonHelper.extractLongNamed("maritalStatusId", element);
+			baseDataValidator.reset().parameter("maritalStatusId").value(maritalStatusId).notBlank().longGreaterThanZero();
+			
+		}
+		
+		if(this.fromApiJsonHelper.extractLongNamed("genderId", element)!=null)
+		{
+			final long genderId=this.fromApiJsonHelper.extractLongNamed("genderId", element);
+			baseDataValidator.reset().parameter("genderId").value(genderId).longGreaterThanZero();
+			
+		}
+		
+		if(this.fromApiJsonHelper.extractLongNamed("professionId", element)!=null)
+		{
+			final long professionId=this.fromApiJsonHelper.extractLongNamed("professionId", element);
+			baseDataValidator.reset().parameter("professionId").value(professionId).longGreaterThanZero();
+			
+		}
+		
+		
+		if(this.fromApiJsonHelper.extractLocalDateNamed("dateOfBirth", element)!=null)
+		{
+			LocalDateTime currentDate = LocalDateTime.now();
+			
+			final LocalDate dateOfBirth=this.fromApiJsonHelper.extractLocalDateNamed("dateOfBirth", element);
+			baseDataValidator.reset().parameter("dateOfBirth").value(dateOfBirth).validateDateBefore(currentDate.toLocalDate());
+			
+		}
+		
+	
+		
+	}
+	
+	public void  validateForDelete(final long familyMemberId)
+	{
+		
+
+		
+
+		final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+		final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
+				.resource("FamilyMembers");
+
+		//final JsonElement element = this.fromApiJsonHelper.parse(json);
+		
+		baseDataValidator.reset().value(familyMemberId).notBlank().integerGreaterThanZero();
+	}
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersReadPlatformService.java
new file mode 100644
index 0000000..7a916a6
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersReadPlatformService.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.portfolio.client.service;
+
+import java.util.Collection;
+
+import org.apache.fineract.portfolio.client.data.ClientFamilyMembersData;
+
+public interface ClientFamilyMembersReadPlatformService 
+{
+
+	Collection<ClientFamilyMembersData> getClientFamilyMembers(long clientId);
+	
+	ClientFamilyMembersData getClientFamilyMember(long id);
+
+	ClientFamilyMembersData retrieveTemplate();
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersReadPlatformServiceImpl.java
new file mode 100644
index 0000000..19c376f
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersReadPlatformServiceImpl.java
@@ -0,0 +1,142 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.client.service;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.fineract.infrastructure.codes.data.CodeValueData;
+import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService;
+import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
+import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
+import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.apache.fineract.portfolio.address.data.AddressData;
+import org.apache.fineract.portfolio.client.data.ClientFamilyMembersData;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ClientFamilyMembersReadPlatformServiceImpl implements ClientFamilyMembersReadPlatformService
+{
+	private final JdbcTemplate jdbcTemplate;
+	private final PlatformSecurityContext context;
+	private final CodeValueReadPlatformService codeValueReadPlatformService;
+	
+
+	@Autowired
+	public ClientFamilyMembersReadPlatformServiceImpl(final PlatformSecurityContext context,
+			final RoutingDataSource dataSource,final CodeValueReadPlatformService codeValueReadPlatformService) {
+		this.context = context;
+		this.jdbcTemplate = new JdbcTemplate(dataSource);
+		this.codeValueReadPlatformService=codeValueReadPlatformService;
+		
+	}
+
+	private static final class ClientFamilyMembersMapper implements RowMapper<ClientFamilyMembersData> {
+		public String schema() {
+			return "fmb.id AS id, fmb.client_id AS clientId, fmb.firstname AS firstName, fmb.middlename AS middleName,"
+					+"fmb.lastname AS lastName,fmb.qualification AS qualification,fmb.mobile_number as mobileNumber,fmb.age as age,fmb.is_dependent as isDependent,cv.code_value AS relationship,fmb.relationship_cv_id AS relationshipId,"
+					+"c.code_value AS maritalStatus,fmb.marital_status_cv_id AS maritalStatusId,"
+					+"c1.code_value AS gender, fmb.gender_cv_id AS genderId, fmb.date_of_birth AS dateOfBirth, c2.code_value AS profession, fmb.profession_cv_id AS professionId"
+					+" FROM m_family_members fmb"
+					+" LEFT JOIN m_code_value cv ON fmb.relationship_cv_id=cv.id"
+					+" LEFT JOIN m_code_value c ON fmb.marital_status_cv_id=c.id"
+					+" LEFT JOIN m_code_value c1 ON fmb.gender_cv_id=c1.id"
+					+" LEFT JOIN m_code_value c2 ON fmb.profession_cv_id=c2.id";
+		}
+
+		@Override
+		public ClientFamilyMembersData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum)
+				throws SQLException {
+			final long id = rs.getLong("id");
+			final long clientId = rs.getLong("clientId");
+			final String firstName=rs.getString("firstName");
+			final String middleName=rs.getString("middleName");
+			final String lastName=rs.getString("lastName");
+			final String qualification=rs.getString("qualification");
+			final String mobileNumber=rs.getString("mobileNumber");
+			final long age=rs.getLong("age");
+			final boolean isDependent=rs.getBoolean("isDependent");
+			final String relationship = rs.getString("relationship");
+			final long relationshipId = rs.getLong("relationshipId");
+			final String maritalStatus = rs.getString("maritalStatus");
+			final long maritalStatusId = rs.getLong("maritalStatusId");
+			final String gender = rs.getString("gender");
+			final long genderId = rs.getLong("genderId");
+			final LocalDate dateOfBirth = JdbcSupport.getLocalDate(rs, "dateOfBirth");
+			final String profession = rs.getString("profession");
+			final long professionId = rs.getLong("professionId");
+					
+			return ClientFamilyMembersData.instance(id, clientId, firstName, middleName, lastName,
+					qualification,mobileNumber,age,isDependent,relationship,relationshipId,maritalStatus,maritalStatusId,gender,genderId,dateOfBirth,profession,professionId);
+			
+			
+
+		}
+	}
+	
+	
+	@Override
+	public Collection<ClientFamilyMembersData> getClientFamilyMembers(long clientId) {
+
+		this.context.authenticatedUser();
+
+		final ClientFamilyMembersMapper rm = new ClientFamilyMembersMapper();
+		final String sql = "select " + rm.schema() + " where fmb.client_id=?";
+
+		return this.jdbcTemplate.query(sql, rm, new Object[] { clientId });
+	}
+	
+	
+	@Override
+	public ClientFamilyMembersData getClientFamilyMember(long id) {
+
+		this.context.authenticatedUser();
+
+		final ClientFamilyMembersMapper rm = new ClientFamilyMembersMapper();
+		final String sql = "select " + rm.schema() + " where fmb.id=? ";
+
+		return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { id });
+	}
+	
+	@Override
+	public ClientFamilyMembersData retrieveTemplate() {
+		
+		final List<CodeValueData> maritalStatusOptions = new ArrayList<>(
+				this.codeValueReadPlatformService.retrieveCodeValuesByCode("MARITAL STATUS"));
+
+		final List<CodeValueData> genderOptions = new ArrayList<>(this.codeValueReadPlatformService.retrieveCodeValuesByCode("Gender"));
+
+		final List<CodeValueData> relationshipOptions = new ArrayList<>(
+				this.codeValueReadPlatformService.retrieveCodeValuesByCode("RELATIONSHIP"));
+		
+		final List<CodeValueData> professionOptions = new ArrayList<>(
+				this.codeValueReadPlatformService.retrieveCodeValuesByCode("PROFESSION"));
+
+		return ClientFamilyMembersData.templateInstance(relationshipOptions,genderOptions, 
+				maritalStatusOptions, professionOptions);
+	}
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersWritePlatformService.java
new file mode 100644
index 0000000..2667f4d
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersWritePlatformService.java
@@ -0,0 +1,37 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fineract.portfolio.client.service;
+
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.portfolio.client.domain.Client;
+
+public interface ClientFamilyMembersWritePlatformService 
+{
+	
+	CommandProcessingResult addFamilyMember(final long clientId,final JsonCommand command);
+	
+	CommandProcessingResult addClientFamilyMember(final Client client,final JsonCommand command);
+
+	CommandProcessingResult updateFamilyMember(Long familyMemberId, JsonCommand command);
+
+	CommandProcessingResult deleteFamilyMember(Long familyMemberId, JsonCommand command);
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersWritePlatformServiceImpl.java
new file mode 100644
index 0000000..e26b542
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersWritePlatformServiceImpl.java
@@ -0,0 +1,449 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fineract.portfolio.client.service;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.fineract.infrastructure.codes.domain.CodeValue;
+import org.apache.fineract.infrastructure.codes.domain.CodeValueRepository;
+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.security.service.PlatformSecurityContext;
+import org.apache.fineract.portfolio.client.domain.Client;
+import org.apache.fineract.portfolio.client.domain.ClientFamilyMembers;
+import org.apache.fineract.portfolio.client.domain.ClientFamilyMembersRepository;
+import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
+import org.apache.fineract.portfolio.client.serialization.ClientFamilyMemberCommandFromApiJsonDeserializer;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+@Service
+public class ClientFamilyMembersWritePlatformServiceImpl implements ClientFamilyMembersWritePlatformService 
+{
+	
+	private final PlatformSecurityContext context;
+	private final CodeValueRepository codeValueRepository;
+	private final ClientFamilyMembersRepository clientFamilyRepository;
+	private final ClientRepositoryWrapper clientRepositoryWrapper;
+	private final ClientFamilyMemberCommandFromApiJsonDeserializer  apiJsonDeserializer;
+	
+	
+	@Autowired
+	public ClientFamilyMembersWritePlatformServiceImpl(final PlatformSecurityContext context,final CodeValueRepository codeValueRepository,
+			final ClientFamilyMembersRepository clientFamilyRepository,final ClientRepositoryWrapper clientRepositoryWrapper,final ClientFamilyMemberCommandFromApiJsonDeserializer  apiJsonDeserializer
+			)
+	{
+		this.context=context;
+		this.codeValueRepository=codeValueRepository;
+		this.clientFamilyRepository=clientFamilyRepository;
+		this.clientRepositoryWrapper=clientRepositoryWrapper;
+		this.apiJsonDeserializer=apiJsonDeserializer;
+		
+	}
+	
+	
+
+	@Override
+	public CommandProcessingResult addFamilyMember(final long clientId,final JsonCommand command) 
+	{
+		
+		Long relationshipId=null;
+		CodeValue relationship=null;
+		CodeValue maritalStatus=null;
+		Long maritalStatusId=null;
+		Long genderId=null;
+		CodeValue gender=null;
+		Long professionId=null;
+		CodeValue profession=null;
+		String firstName="";
+		String middleName="";
+		String lastName="";
+		String qualification="";
+		String mobileNumber="";
+		Long age=null;
+		Boolean isDependent=false;
+		Date dateOfBirth=null;
+		
+		
+		this.context.authenticatedUser();
+		apiJsonDeserializer.validateForCreate(clientId, command.json());
+		
+		
+		Client client=clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
+		
+		if (command.stringValueOfParameterNamed("firstName") != null) {
+			firstName = command.stringValueOfParameterNamed("firstName");
+			}
+		
+		if (command.stringValueOfParameterNamed("middleName") != null) {
+			middleName = command.stringValueOfParameterNamed("middleName");
+			}
+		
+		if (command.stringValueOfParameterNamed("lastName") != null) {
+			lastName = command.stringValueOfParameterNamed("lastName");
+			}
+		
+		
+		if (command.stringValueOfParameterNamed("qualification") != null) {
+			qualification = command.stringValueOfParameterNamed("qualification");
+			}
+		
+		if (command.stringValueOfParameterNamed("mobileNumber") != null) {
+			mobileNumber = command.stringValueOfParameterNamed("mobileNumber");
+			}
+		
+		
+		if (command.longValueOfParameterNamed("age") != null) {
+			age = command.longValueOfParameterNamed("age");
+			}
+		
+		if (command.booleanObjectValueOfParameterNamed("isDependent") != null) {
+			isDependent = command.booleanObjectValueOfParameterNamed("isDependent");
+			}
+		
+		if (command.longValueOfParameterNamed("relationshipId") != null) {
+			relationshipId = command.longValueOfParameterNamed("relationshipId");
+			relationship = this.codeValueRepository.getOne(relationshipId);
+		}
+		
+		if (command.longValueOfParameterNamed("maritalStatusId") != null) {
+			maritalStatusId = command.longValueOfParameterNamed("maritalStatusId");
+			maritalStatus = this.codeValueRepository.getOne(maritalStatusId);
+		}
+
+		if (command.longValueOfParameterNamed("genderId") != null) {
+			genderId = command.longValueOfParameterNamed("genderId");
+			gender = this.codeValueRepository.getOne(genderId);
+		}
+		
+		if (command.longValueOfParameterNamed("professionId") != null) {
+			professionId = command.longValueOfParameterNamed("professionId");
+			profession = this.codeValueRepository.getOne(professionId);
+		}
+		
+		if(command.DateValueOfParameterNamed("dateOfBirth")!=null)
+		{
+			dateOfBirth=command.DateValueOfParameterNamed("dateOfBirth");
+					
+		}
+		
+		ClientFamilyMembers clientFamilyMembers=ClientFamilyMembers.fromJson(client, firstName, middleName, lastName, qualification,mobileNumber,age,isDependent, relationship, maritalStatus, gender, dateOfBirth, profession);
+		
+		this.clientFamilyRepository.save(clientFamilyMembers);
+		
+		return new CommandProcessingResultBuilder().withCommandId(command.commandId())
+				.withEntityId(clientFamilyMembers.getId()).build();
+		
+		
+	
+	}
+	
+	@Override
+	public CommandProcessingResult addClientFamilyMember(final Client client,final JsonCommand command)
+	{
+		
+		Long relationshipId=null;
+		CodeValue relationship=null;
+		CodeValue maritalStatus=null;
+		Long maritalStatusId=null;
+		Long genderId=null;
+		CodeValue gender=null;
+		Long professionId=null;
+		CodeValue profession=null;
+		String firstName="";
+		String middleName="";
+		String lastName="";
+		String qualification="";
+		Date dateOfBirth=null;
+		String mobileNumber="";
+		Long age=null;
+		Boolean isDependent=false;
+		
+		
+		
+		
+		this.context.authenticatedUser();
+		
+		
+		//Client client=clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
+		
+		ClientFamilyMembers familyMember=new ClientFamilyMembers();
+		
+		//apiJsonDeserializer.validateForCreate(command.json());
+							
+		
+		JsonArray familyMembers=command.arrayOfParameterNamed("familyMembers");
+		
+		for(JsonElement members :familyMembers)
+		{
+			
+			apiJsonDeserializer.validateForCreate(members.toString());
+			
+			JsonObject member=members.getAsJsonObject();
+			
+			
+			if (member.get("firstName") != null) {
+				firstName = member.get("firstName").getAsString();
+				}
+			
+			if (member.get("middleName") != null) {
+				middleName = member.get("middleName").getAsString();
+				}
+			
+			if (member.get("lastName") != null) {
+				lastName = member.get("lastName").getAsString();
+				}
+			
+			
+			if (member.get("qualification") != null) {
+				qualification = member.get("qualification").getAsString();
+				}
+			
+			if (member.get("mobileNumber") != null) {
+				mobileNumber = member.get("mobileNumber").getAsString();
+				}
+			
+			
+			if (member.get("age") != null) {
+				age = member.get("age").getAsLong();
+				}
+			
+			if (member.get("isDependent") != null) {
+				isDependent = member.get("isDependent").getAsBoolean();
+				}
+			
+			if (member.get("relationshipId") != null) {
+				relationshipId = member.get("relationshipId").getAsLong();
+				relationship = this.codeValueRepository.getOne(relationshipId);
+			}
+			
+			if (member.get("maritalStatusId") != null) {
+				maritalStatusId = member.get("maritalStatusId").getAsLong();
+				maritalStatus = this.codeValueRepository.getOne(maritalStatusId);
+			}
+
+			if (member.get("genderId") != null) {
+				genderId = member.get("genderId").getAsLong();
+				gender = this.codeValueRepository.getOne(genderId);
+			}
+			
+			if (member.get("professionId") != null) {
+				professionId = member.get("professionId").getAsLong();
+				profession = this.codeValueRepository.getOne(professionId);
+			}
+			
+			if(member.get("dateOfBirth")!=null)
+			{
+				
+				DateFormat format = new SimpleDateFormat(member.get("dateFormat").getAsString());
+				Date date;
+				try {
+					date = format.parse(member.get("dateOfBirth").getAsString());
+					dateOfBirth=date;
+				} catch (ParseException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				}
+				
+				
+				
+		/*	this.fromApiJsonHelper.extractDateFormatParameter(member.get("dateOfBirth").getAsJsonObject());*/
+				
+						
+			}
+			
+			familyMember=ClientFamilyMembers.fromJson(client, firstName, middleName, lastName, qualification,mobileNumber,age,isDependent, relationship, maritalStatus, gender, dateOfBirth, profession);
+			
+			this.clientFamilyRepository.save(familyMember);	
+			
+		}
+		
+		
+		
+		return new CommandProcessingResultBuilder().withCommandId(command.commandId())
+				.withEntityId(familyMember.getId()).build();
+		
+		
+	}
+
+
+
+	@Override
+	public CommandProcessingResult updateFamilyMember(Long familyMemberId, JsonCommand command) {
+		
+		
+		Long relationshipId=null;
+		CodeValue relationship=null;
+		CodeValue maritalStatus=null;
+		Long maritalStatusId=null;
+		Long genderId=null;
+		CodeValue gender=null;
+		Long professionId=null;
+		CodeValue profession=null;
+		String firstName="";
+		String middleName="";
+		String lastName="";
+		String qualification="";
+		Date dateOfBirth=null;
+		String mobileNumber="";
+		Long age=null;
+		Boolean isDependent=false;
+		//long clientFamilyMemberId=0;
+		
+		
+		this.context.authenticatedUser();
+		
+		apiJsonDeserializer.validateForUpdate(familyMemberId, command.json());
+		
+		/*if (command.stringValueOfParameterNamed("clientFamilyMemberId") != null) {
+			clientFamilyMemberId = command.longValueOfParameterNamed("clientFamilyMemberId");
+			}*/
+		
+		
+		ClientFamilyMembers clientFamilyMember=clientFamilyRepository.getOne(familyMemberId);
+				
+		//Client client=clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
+		
+		if (command.stringValueOfParameterNamed("firstName") != null) {
+			firstName = command.stringValueOfParameterNamed("firstName");
+			clientFamilyMember.setFirstName(firstName);
+			}
+		
+		if (command.stringValueOfParameterNamed("middleName") != null) {
+			middleName = command.stringValueOfParameterNamed("middleName");
+			clientFamilyMember.setMiddleName(middleName);
+			}
+		
+		if (command.stringValueOfParameterNamed("lastName") != null) {
+			lastName = command.stringValueOfParameterNamed("lastName");
+			clientFamilyMember.setLastName(lastName);
+			}
+		
+		
+		if (command.stringValueOfParameterNamed("qualification") != null) {
+			qualification = command.stringValueOfParameterNamed("qualification");
+			clientFamilyMember.setQualification(qualification);
+			}
+		
+		
+		if (command.stringValueOfParameterNamed("mobileNumber") != null) {
+			mobileNumber = command.stringValueOfParameterNamed("mobileNumber");
+			clientFamilyMember.setMobileNumber(mobileNumber);
+			}
+		
+		
+		if (command.longValueOfParameterNamed("age") != null) {
+			age = command.longValueOfParameterNamed("age");
+			clientFamilyMember.setAge(age);
+			}
+		
+		if (command.booleanObjectValueOfParameterNamed("isDependent") != null) {
+			isDependent = command.booleanObjectValueOfParameterNamed("isDependent");
+			clientFamilyMember.setIsDependent(isDependent);
+			}
+		
+		if (command.longValueOfParameterNamed("relationShipId") != null) {
+			relationshipId = command.longValueOfParameterNamed("relationShipId");
+			relationship = this.codeValueRepository.getOne(relationshipId);
+			clientFamilyMember.setRelationship(relationship);
+		}
+		
+		if (command.longValueOfParameterNamed("maritalStatusId") != null) {
+			maritalStatusId = command.longValueOfParameterNamed("maritalStatusId");
+			maritalStatus = this.codeValueRepository.getOne(maritalStatusId);
+			clientFamilyMember.setMaritalStatus(maritalStatus);
+		}
+
+		if (command.longValueOfParameterNamed("genderId") != null) {
+			genderId = command.longValueOfParameterNamed("genderId");
+			gender = this.codeValueRepository.getOne(genderId);
+			clientFamilyMember.setGender(gender);
+		}
+		
+		if (command.longValueOfParameterNamed("professionId") != null) {
+			professionId = command.longValueOfParameterNamed("professionId");
+			profession = this.codeValueRepository.getOne(professionId);
+			clientFamilyMember.setProfession(profession);
+		}
+		
+		if(command.DateValueOfParameterNamed("dateOfBirth")!=null)
+		{
+			dateOfBirth=command.DateValueOfParameterNamed("dateOfBirth");
+			clientFamilyMember.setDateOfBirth(dateOfBirth);
+			
+					
+		}
+		
+		//ClientFamilyMembers clientFamilyMembers=ClientFamilyMembers.fromJson(client, firstName, middleName, lastName, qualification, relationship, maritalStatus, gender, dateOfBirth, profession);
+		
+		this.clientFamilyRepository.save(clientFamilyMember);
+		
+		return new CommandProcessingResultBuilder().withCommandId(command.commandId())
+				.withEntityId(clientFamilyMember.getId()).build();
+	}
+
+
+
+	@Override
+	public CommandProcessingResult deleteFamilyMember(Long clientFamilyMemberId, JsonCommand command) {
+		// TODO Auto-generated method stub
+		
+		this.context.authenticatedUser();
+		
+		System.out.println("clientFamilyMemberId "+clientFamilyMemberId);
+		apiJsonDeserializer.validateForDelete(clientFamilyMemberId);
+		
+		ClientFamilyMembers clientFamilyMember=null;
+		
+		
+		
+		if(clientFamilyMemberId!=null)
+		{
+			 clientFamilyMember=clientFamilyRepository.getOne(clientFamilyMemberId);
+			clientFamilyRepository.delete(clientFamilyMember);
+			
+		}
+		
+		
+		if(clientFamilyMember!=null)
+		{
+			return new CommandProcessingResultBuilder().withCommandId(command.commandId())
+					.withEntityId(clientFamilyMember.getId()).build();	
+		}
+		else
+		{
+			return new CommandProcessingResultBuilder().withCommandId(command.commandId())
+					.withEntityId(Long.valueOf(clientFamilyMemberId)).build();	
+		}
+		
+	}
+	
+	
+	
+
+}
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 d29126c..b5e8825 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
@@ -51,6 +51,7 @@
 import org.apache.fineract.portfolio.address.service.AddressReadPlatformService;
 import org.apache.fineract.portfolio.client.api.ClientApiConstants;
 import org.apache.fineract.portfolio.client.data.ClientData;
+import org.apache.fineract.portfolio.client.data.ClientFamilyMembersData;
 import org.apache.fineract.portfolio.client.data.ClientNonPersonData;
 import org.apache.fineract.portfolio.client.data.ClientTimelineData;
 import org.apache.fineract.portfolio.client.domain.ClientEnumerations;
@@ -86,6 +87,7 @@
     private final ParentGroupsMapper clientGroupsMapper = new ParentGroupsMapper();
     
     private final AddressReadPlatformService addressReadPlatformService;
+    private final ClientFamilyMembersReadPlatformService clientFamilyMembersReadPlatformService;
     private final ConfigurationReadPlatformService configurationReadPlatformService;
     private final EntityDatatableChecksReadService entityDatatableChecksReadService;
     private final ColumnValidator columnValidator;
@@ -95,7 +97,7 @@
             final OfficeReadPlatformService officeReadPlatformService, final StaffReadPlatformService staffReadPlatformService,
             final CodeValueReadPlatformService codeValueReadPlatformService,
             final SavingsProductReadPlatformService savingsProductReadPlatformService,
-            final AddressReadPlatformService addressReadPlatformService,
+            final AddressReadPlatformService addressReadPlatformService,final ClientFamilyMembersReadPlatformService clientFamilyMembersReadPlatformService,
             final ConfigurationReadPlatformService configurationReadPlatformService,
             final EntityDatatableChecksReadService entityDatatableChecksReadService,
             final ColumnValidator columnValidator) {
@@ -106,6 +108,7 @@
         this.codeValueReadPlatformService = codeValueReadPlatformService;
         this.savingsProductReadPlatformService = savingsProductReadPlatformService;
         this.addressReadPlatformService=addressReadPlatformService;
+        this.clientFamilyMembersReadPlatformService=clientFamilyMembersReadPlatformService;
         this.configurationReadPlatformService=configurationReadPlatformService;
         this.entityDatatableChecksReadService = entityDatatableChecksReadService;
         this.columnValidator = columnValidator;
@@ -130,7 +133,7 @@
         	 address = this.addressReadPlatformService.retrieveTemplate();
         }
         
-       
+        final ClientFamilyMembersData familyMemberOptions=this.clientFamilyMembersReadPlatformService.retrieveTemplate();
 
         Collection<StaffData> staffOptions = null;
 
@@ -166,7 +169,7 @@
 
         return ClientData.template(defaultOfficeId, new LocalDate(), offices, staffOptions, null, genderOptions, savingsProductDatas,
                 clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions,
-                clientLegalFormOptions,address,isAddressEnabled, datatableTemplates);
+                clientLegalFormOptions,familyMemberOptions,address,isAddressEnabled, datatableTemplates);
     }
 
     @Override
@@ -804,7 +807,7 @@
         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, null);
+        		clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, clientLegalFormOptions,null,null,null, null);
     }
 
 }
\ No newline at end of file
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 2e109c4..a649e51 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
@@ -122,6 +122,7 @@
     private final FromJsonHelper fromApiJsonHelper;
     private final ConfigurationReadPlatformService configurationReadPlatformService;
     private final AddressWritePlatformService addressWritePlatformService;
+    private final ClientFamilyMembersWritePlatformService clientFamilyMembersWritePlatformService;
     private final BusinessEventNotifierService businessEventNotifierService;
     private final EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService;
     @Autowired
@@ -136,7 +137,7 @@
             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 ClientFamilyMembersWritePlatformService clientFamilyMembersWritePlatformService, final BusinessEventNotifierService businessEventNotifierService,
             final EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService) {
         this.context = context;
         this.clientRepository = clientRepository;
@@ -158,6 +159,7 @@
         this.fromApiJsonHelper = fromApiJsonHelper;
         this.configurationReadPlatformService = configurationReadPlatformService;
         this.addressWritePlatformService = addressWritePlatformService;
+        this.clientFamilyMembersWritePlatformService=clientFamilyMembersWritePlatformService;
         this.businessEventNotifierService = businessEventNotifierService;
         this.entityDatatableChecksWritePlatformService = entityDatatableChecksWritePlatformService;
     }
@@ -327,6 +329,12 @@
             if (isAddressEnabled) {
                 this.addressWritePlatformService.addNewClientAddress(newClient, command);
             }
+            
+            
+            if(command.arrayOfParameterNamed("familyMembers")!=null)
+            {
+            	this.clientFamilyMembersWritePlatformService.addClientFamilyMember(newClient, command);
+            }
 
             if(command.parameterExists(ClientApiConstants.datatables)){
                 this.entityDatatableChecksWritePlatformService.saveDatatables(StatusEnum.CREATE.getCode().longValue(),
diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V328__family_members_sql_support.txt b/fineract-provider/src/main/resources/sql/migrations/core_db/V328__family_members_sql_support.txt
new file mode 100644
index 0000000..e6e1101
--- /dev/null
+++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V328__family_members_sql_support.txt
@@ -0,0 +1,60 @@
+--
+-- 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_family_members` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `client_id` bigint(20) NOT NULL,
+  `firstname` varchar(50) NOT NULL,
+  `middlename` varchar(50) DEFAULT NULL,
+  `lastname` varchar(50) DEFAULT NULL,
+  `qualification` varchar(50) DEFAULT NULL,
+  `relationship_cv_id` int(11) NOT NULL,
+  `marital_status_cv_id` int(11) DEFAULT NULL,
+  `gender_cv_id` int(11) DEFAULT NULL,
+  `date_of_birth` date DEFAULT NULL,
+  `age` int(11) DEFAULT NULL,
+  `profession_cv_id` int(11) DEFAULT NULL,
+  `mobile_number` varchar(50) DEFAULT NULL,
+  `is_dependent` tinyint(4) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `FK_m_family_members_client_id_m_client` (`client_id`),
+  KEY `FK_m_family_members_relationship_m_code_value` (`relationship_cv_id`),
+  KEY `FK_m_family_members_marital_status_m_code_value` (`marital_status_cv_id`),
+  KEY `FK_m_family_members_gender_m_code_value` (`gender_cv_id`),
+  KEY `FK_m_family_members_profession_m_code_value` (`profession_cv_id`),
+  CONSTRAINT `FK_m_family_members_client_id_m_client` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`),
+  CONSTRAINT `FK_m_family_members_gender_m_code_value` FOREIGN KEY (`gender_cv_id`) REFERENCES `m_code_value` (`id`),
+  CONSTRAINT `FK_m_family_members_marital_status_m_code_value` FOREIGN KEY (`marital_status_cv_id`) REFERENCES `m_code_value` (`id`),
+  CONSTRAINT `FK_m_family_members_profession_m_code_value` FOREIGN KEY (`profession_cv_id`) REFERENCES `m_code_value` (`id`),
+  CONSTRAINT `FK_m_family_members_relationship_m_code_value` FOREIGN KEY (`relationship_cv_id`) REFERENCES `m_code_value` (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8
+
+
+-- permissions
+
+INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'CREATE_FAMILYMEMBERS', 'FAMILYMEMBERS', 'CREATE', 0);
+INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'UPDATE_FAMILYMEMBERS', 'FAMILYMEMBERS', 'UPDATE', 0);
+INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'DELETE_FAMILYMEMBERS', 'FAMILYMEMBERS', 'DELETE', 0);
+
+-- code inserts
+
+INSERT INTO `m_code` (`code_name`, `is_system_defined`) VALUES ('MARITAL STATUS', 1);
+INSERT INTO `m_code` (`code_name`, `is_system_defined`) VALUES ('RELATIONSHIP', 1);
+INSERT INTO `m_code` (`code_name`, `is_system_defined`) VALUES ('PROFESSION', 1);