family members

Project: http://git-wip-us.apache.org/repos/asf/fineract/repo
Commit: http://git-wip-us.apache.org/repos/asf/fineract/commit/d4672f9b
Tree: http://git-wip-us.apache.org/repos/asf/fineract/tree/d4672f9b
Diff: http://git-wip-us.apache.org/repos/asf/fineract/diff/d4672f9b

Branch: refs/heads/develop
Commit: d4672f9beb80007e4c343691c5276cd86ee08d42
Parents: ee150b1
Author: nikpawar89 <[email protected]>
Authored: Sat Jul 1 18:11:03 2017 +0530
Committer: nikpawar89 <[email protected]>
Committed: Wed Aug 2 14:19:42 2017 +0530

----------------------------------------------------------------------
 .../commands/service/CommandWrapperBuilder.java |  25 ++
 .../client/api/ClientApiConstants.java          |   5 +
 .../api/ClientFamilyMembersApiResources.java    | 172 +++++++
 .../data/ClientApiCollectionConstants.java      |   4 +-
 .../portfolio/client/data/ClientData.java       |  23 +-
 .../client/data/ClientFamilyMembersData.java    | 197 ++++++++
 .../client/domain/ClientFamilyMembers.java      | 238 ++++++++++
 .../domain/ClientFamilyMembersRepository.java   |  29 ++
 .../AddClientFamilyMemberCommandHandler.java    |  50 +++
 .../DeleteClientFamilyMemberCommandHandler.java |  47 ++
 .../UpdateClientFamilyMemberCommandHandler.java |  49 ++
 ...ilyMemberCommandFromApiJsonDeserializer.java | 313 +++++++++++++
 .../ClientFamilyMembersReadPlatformService.java |  34 ++
 ...entFamilyMembersReadPlatformServiceImpl.java | 142 ++++++
 ...ClientFamilyMembersWritePlatformService.java |  37 ++
 ...ntFamilyMembersWritePlatformServiceImpl.java | 449 +++++++++++++++++++
 .../service/ClientReadPlatformServiceImpl.java  |  11 +-
 ...ntWritePlatformServiceJpaRepositoryImpl.java |  10 +-
 .../V328__family_members_sql_support.txt        |  60 +++
 19 files changed, 1879 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/fineract/blob/d4672f9b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
 
b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
index 46c585b..a940150 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 @@ public class CommandWrapperBuilder {
         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;

http://git-wip-us.apache.org/repos/asf/fineract/blob/d4672f9b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientApiConstants.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientApiConstants.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientApiConstants.java
index 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 class ClientApiConstants {
     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";
 

http://git-wip-us.apache.org/repos/asf/fineract/blob/d4672f9b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientFamilyMembersApiResources.java
----------------------------------------------------------------------
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);
+       }
+       
+       
+       
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/d4672f9b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientApiCollectionConstants.java
----------------------------------------------------------------------
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 @@ import java.util.Set;
 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,

http://git-wip-us.apache.org/repos/asf/fineract/blob/d4672f9b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java
index 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 @@ final public class ClientData implements 
Comparable<ClientData> {
     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 public class ClientData implements 
Comparable<ClientData> {
             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 @@ final public class ClientData implements 
Comparable<ClientData> {
                 staffName, officeOptions, groups, staffOptions, narrations, 
genderOptions, timeline, savingProductOptions,
                 savingsProductId, savingsProductName, savingsAccountId, 
savingAccountOptions, clientType, clientClassification,
                 clientTypeOptions, clientClassificationOptions, 
clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, 
-                clientNonPersonDetails, clientLegalFormOptions, 
legalForm,address, isAddressEnabled, datatables, isStaff);
+                clientNonPersonDetails, 
clientLegalFormOptions,familyMemberOptions, legalForm,address, 
isAddressEnabled, datatables, isStaff);
 
     }
 
@@ -161,7 +162,7 @@ final public class ClientData implements 
Comparable<ClientData> {
                 clientData.savingsProductName, clientData.savingsAccountId, 
clientData.savingAccountOptions, clientData.clientType,
                 clientData.clientClassification, 
templateData.clientTypeOptions, templateData.clientClassificationOptions, 
                 templateData.clientNonPersonConstitutionOptions, 
templateData.clientNonPersonMainBusinessLineOptions, 
clientData.clientNonPersonDetails,
-                templateData.clientLegalFormOptions, clientData.legalForm, 
clientData.address,clientData.isAddressEnabled, null, clientData.isStaff);
+                
templateData.clientLegalFormOptions,templateData.familyMemberOptions, 
clientData.legalForm, clientData.address,clientData.isAddressEnabled, null, 
clientData.isStaff);
 
     }
 
@@ -177,7 +178,7 @@ final public class ClientData implements 
Comparable<ClientData> {
                 clientData.savingsProductName, clientData.savingsAccountId, 
savingAccountOptions, clientData.clientType,
                 clientData.clientClassification, clientData.clientTypeOptions, 
clientData.clientClassificationOptions,
                 clientData.clientNonPersonConstitutionOptions, 
clientData.clientNonPersonMainBusinessLineOptions, 
clientData.clientNonPersonDetails,
-                clientData.clientLegalFormOptions, 
clientData.legalForm,clientData.address, clientData.isAddressEnabled, null, 
clientData.isStaff);
+                
clientData.clientLegalFormOptions,clientData.familyMemberOptions, 
clientData.legalForm,clientData.address, clientData.isAddressEnabled, null, 
clientData.isStaff);
 
     }
 
@@ -190,7 +191,7 @@ final public class ClientData implements 
Comparable<ClientData> {
                 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 public class ClientData implements 
Comparable<ClientData> {
         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 @@ final public class ClientData implements 
Comparable<ClientData> {
                 staffName, allowedOffices, groups, staffOptions, 
closureReasons, genderOptions, timeline, savingProductOptions,
                 savingsProductId, savingsProductName, savingsAccountId, 
savingAccountOptions, clientType, clientClassification,
                 clientTypeOptions, clientClassificationOptions, 
clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, 
-                clientNonPerson, clientLegalFormOptions, legalForm,null,null, 
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 public class ClientData implements 
Comparable<ClientData> {
         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 @@ final public class ClientData implements 
Comparable<ClientData> {
                 staffName, allowedOffices, groups, staffOptions, 
closureReasons, genderOptions, timeline, savingProductOptions,
                 savingsProductId, savingsProductName, savingsAccountId, 
savingAccountOptions, clientType, clientClassification,
                 clientTypeOptions, clientClassificationOptions, 
clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, 
-                clientNonPerson, clientLegalFormOptions, legalForm,null,null, 
null, isStaff);
+                clientNonPerson, clientLegalFormOptions,familyMemberOptions, 
legalForm,null,null, null, isStaff);
 
     }
 
@@ -306,12 +309,13 @@ final public class ClientData implements 
Comparable<ClientData> {
         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 public class ClientData implements 
Comparable<ClientData> {
             final CodeValueData clientClassification, final 
Collection<CodeValueData> clientTypeOptions,
             final Collection<CodeValueData> clientClassificationOptions, final 
Collection<CodeValueData> clientNonPersonConstitutionOptions,
             final Collection<CodeValueData> 
clientNonPersonMainBusinessLineOptions, final ClientNonPersonData 
clientNonPerson,
-            final List<EnumOptionData> clientLegalFormOptions, final 
EnumOptionData legalForm, final AddressData address,
+            final 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 @@ final public class ClientData implements 
Comparable<ClientData> {
         this.clientNonPersonConstitutionOptions = 
clientNonPersonConstitutionOptions;
         this.clientNonPersonMainBusinessLineOptions = 
clientNonPersonMainBusinessLineOptions;
         this.clientLegalFormOptions = clientLegalFormOptions;
+        this.familyMemberOptions=familyMemberOptions;
 
         this.timeline = timeline;
         this.savingProductOptions = savingProductOptions;

http://git-wip-us.apache.org/repos/asf/fineract/blob/d4672f9b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientFamilyMembersData.java
----------------------------------------------------------------------
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;
+       }
+       
+       
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/d4672f9b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientFamilyMembers.java
----------------------------------------------------------------------
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;
+               }
+               
+               
+       
+       
+       
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/d4672f9b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientFamilyMembersRepository.java
----------------------------------------------------------------------
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>
+{
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/d4672f9b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/AddClientFamilyMemberCommandHandler.java
----------------------------------------------------------------------
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);
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/d4672f9b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/DeleteClientFamilyMemberCommandHandler.java
----------------------------------------------------------------------
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);
+       }
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/d4672f9b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/UpdateClientFamilyMemberCommandHandler.java
----------------------------------------------------------------------
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);
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/d4672f9b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/serialization/ClientFamilyMemberCommandFromApiJsonDeserializer.java
----------------------------------------------------------------------
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();
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/d4672f9b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersReadPlatformService.java
----------------------------------------------------------------------
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();
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/d4672f9b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersReadPlatformServiceImpl.java
----------------------------------------------------------------------
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);
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/d4672f9b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersWritePlatformService.java
----------------------------------------------------------------------
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);
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/d4672f9b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientFamilyMembersWritePlatformServiceImpl.java
----------------------------------------------------------------------
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();      
+               }
+               
+       }
+       
+       
+       
+
+}

Reply via email to