You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by av...@apache.org on 2020/09/29 17:52:31 UTC

[fineract] branch develop updated: Interop KYC and Interop Loan Disbursement (#1330)

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

avikg pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new e5f3e87  Interop KYC and Interop Loan Disbursement (#1330)
e5f3e87 is described below

commit e5f3e8720d3c48494072bf4671080c7396a5a588
Author: SubhamPramanik <su...@gmail.com>
AuthorDate: Tue Sep 29 23:22:18 2020 +0530

    Interop KYC and Interop Loan Disbursement (#1330)
    
    * Interop get account KYC
    
    * loan interop disbursement
    
    * checkstyle fix
    
    Co-authored-by: Subham Pramanik <su...@google.com>
---
 .../interoperation/api/InteropApiResource.java     |  26 ++++
 .../fineract/interoperation/data/IdDocument.java   |  69 ++++++++++
 .../interoperation/data/InteropKycData.java        | 145 ++++++++++++++++++++
 .../data/InteropKycResponseData.java               | 147 +++++++++++++++++++++
 .../interoperation/data/PostalAddress.java         |  89 +++++++++++++
 .../fineract/interoperation/data/SubjectName.java  |  68 ++++++++++
 .../interoperation/service/InteropService.java     |   7 +
 .../interoperation/service/InteropServiceImpl.java | 119 ++++++++++++++++-
 8 files changed, 667 insertions(+), 3 deletions(-)

diff --git a/fineract-provider/src/main/java/org/apache/fineract/interoperation/api/InteropApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/interoperation/api/InteropApiResource.java
index c74d7bc..ace4dbe 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/interoperation/api/InteropApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/interoperation/api/InteropApiResource.java
@@ -58,6 +58,7 @@ import org.apache.fineract.interoperation.data.InteropAccountData;
 import org.apache.fineract.interoperation.data.InteropIdentifierAccountResponseData;
 import org.apache.fineract.interoperation.data.InteropIdentifierRequestData;
 import org.apache.fineract.interoperation.data.InteropIdentifiersResponseData;
+import org.apache.fineract.interoperation.data.InteropKycResponseData;
 import org.apache.fineract.interoperation.data.InteropQuoteRequestData;
 import org.apache.fineract.interoperation.data.InteropQuoteResponseData;
 import org.apache.fineract.interoperation.data.InteropTransactionRequestData;
@@ -389,4 +390,29 @@ public class InteropApiResource {
 
         return jsonSerializer.serialize(settings, result);
     }
+
+    @GET
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Path("accounts/{accountId}/kyc")
+    @Operation(summary = "Query KYC by Account Id", description = "")
+    @ApiResponses({
+            @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = InteropKycResponseData.class))) })
+    public String getClientKyc(@PathParam("accountId") @Parameter(description = "accountId") String accountId, @Context UriInfo uriInfo) {
+        InteropKycResponseData result = interopService.getKyc(accountId);
+        ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
+
+        return jsonSerializer.serialize(settings, result);
+    }
+
+    @POST
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    @Path("transactions/{accountId}/disburse")
+    @Operation(summary = "Disburse Loan by Account Id", description = "")
+    public String disburseLoan(@PathParam("accountId") @Parameter(description = "accountId") String accountId,
+            @Parameter(hidden = true) final String apiRequestBodyAsJson, @Context UriInfo uriInfo) {
+        return interopService.disburseLoan(accountId, apiRequestBodyAsJson);
+    }
+
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/IdDocument.java b/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/IdDocument.java
new file mode 100644
index 0000000..5d70633
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/IdDocument.java
@@ -0,0 +1,69 @@
+/**
+ * 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.interoperation.data;
+
+import java.io.Serializable;
+
+public class IdDocument implements Serializable {
+
+    String idType;
+    String idNumber;
+    String issuerCountry;
+    String otherIdDescription;
+
+    public IdDocument(String idType, String idNumber, String issuerCountry, String otherIdDescription) {
+        this.idType = idType;
+        this.idNumber = idNumber;
+        this.issuerCountry = issuerCountry;
+        this.otherIdDescription = otherIdDescription;
+    }
+
+    public String getIdType() {
+        return idType;
+    }
+
+    public void setIdType(String idType) {
+        this.idType = idType;
+    }
+
+    public String getIdNumber() {
+        return idNumber;
+    }
+
+    public void setIdNumber(String idNumber) {
+        this.idNumber = idNumber;
+    }
+
+    public String getIssuerCountry() {
+        return issuerCountry;
+    }
+
+    public void setIssuerCountry(String issuerCountry) {
+        this.issuerCountry = issuerCountry;
+    }
+
+    public String getOtherIdDescription() {
+        return otherIdDescription;
+    }
+
+    public void setOtherIdDescription(String otherIdDescription) {
+        this.otherIdDescription = otherIdDescription;
+    }
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/InteropKycData.java b/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/InteropKycData.java
new file mode 100644
index 0000000..a385f93
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/InteropKycData.java
@@ -0,0 +1,145 @@
+/**
+ * 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.interoperation.data;
+
+import java.io.Serializable;
+
+public class InteropKycData implements Serializable {
+
+    private String nationality;
+    private String dateOfBirth;
+    private String contactPhone;
+    private String gender;
+    private String email;
+    private String idType;
+    private String idNo;
+    private String description;
+    private String country;
+    private String addressLine1;
+    private String addressLine2;
+    private String city;
+    private String stateProvince;
+    private String postalCode;
+    private String firstName;
+    private String middleName;
+    private String lastName;
+    private String displayName;
+
+    public InteropKycData(String nationality, String dateOfBirth, String contactPhone, String gender, String email, String idType,
+            String idNo, String description, String country, String addressLine1, String addressLine2, String city, String stateProvince,
+            String postalCode, String firstName, String middleName, String lastName, String displayName) {
+        this.nationality = nationality;
+        this.dateOfBirth = dateOfBirth;
+        this.contactPhone = contactPhone;
+        this.gender = gender;
+        this.email = email;
+        this.idType = idType;
+        this.idNo = idNo;
+        this.description = description;
+        this.country = country;
+        this.addressLine1 = addressLine1;
+        this.addressLine2 = addressLine2;
+        this.city = city;
+        this.stateProvince = stateProvince;
+        this.postalCode = postalCode;
+        this.firstName = firstName;
+        this.middleName = middleName;
+        this.lastName = lastName;
+        this.displayName = displayName;
+    }
+
+    public static InteropKycData instance(String nationality, String dateOfBirth, String contactPhone, String gender, String email,
+            String idType, String idNo, String description, String country, String address_line_1, String address_line_2, String city,
+            String stateProvince, String postalCode, String firstName, String middleName, String lastName, String displayName) {
+        return new InteropKycData(nationality, dateOfBirth, contactPhone, gender, email, idType, idNo, description, country, address_line_1,
+                address_line_2, city, stateProvince, postalCode, firstName, middleName, lastName, displayName);
+    }
+
+    public String getNationality() {
+        return nationality;
+    }
+
+    public String getDateOfBirth() {
+        return dateOfBirth;
+    }
+
+    public String getContactPhone() {
+        return contactPhone;
+    }
+
+    public String getGender() {
+        return gender;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public String getIdType() {
+        return idType;
+    }
+
+    public String getIdNo() {
+        return idNo;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public String getCountry() {
+        return country;
+    }
+
+    public String getAddressLine1() {
+        return addressLine1;
+    }
+
+    public String getAddressLine2() {
+        return addressLine2;
+    }
+
+    public String getCity() {
+        return city;
+    }
+
+    public String getStateProvince() {
+        return stateProvince;
+    }
+
+    public String getPostalCode() {
+        return postalCode;
+    }
+
+    public String getFirstName() {
+        return firstName;
+    }
+
+    public String getLastName() {
+        return lastName;
+    }
+
+    public String getMiddleName() {
+        return middleName;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/InteropKycResponseData.java b/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/InteropKycResponseData.java
new file mode 100644
index 0000000..309af31
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/InteropKycResponseData.java
@@ -0,0 +1,147 @@
+/**
+ * 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.interoperation.data;
+
+import java.util.Map;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+
+public class InteropKycResponseData extends CommandProcessingResult {
+
+    private String nationality;
+    private String dateOfBirth;
+    private String contactPhone;
+    private String gender;
+
+    private IdDocument[] idDocument;
+
+    private PostalAddress postalAddress;
+
+    private SubjectName subjectName;
+
+    private String emailAddress;
+    private String birthCountry;
+
+    public InteropKycResponseData(Long resourceId, Long officeId, Long commandId, Map<String, Object> changesOnly, String nationality,
+            String dateOfBirth, String contactPhone, String gender, IdDocument[] idDocument, PostalAddress postalAddress,
+            SubjectName subjectName, String emailAddress, String birthCountry) {
+        super(resourceId, officeId, commandId, changesOnly);
+        this.nationality = nationality;
+        this.dateOfBirth = dateOfBirth;
+        this.contactPhone = contactPhone;
+        this.gender = gender;
+        this.idDocument = idDocument;
+        this.postalAddress = postalAddress;
+        this.subjectName = subjectName;
+        this.emailAddress = emailAddress;
+        this.birthCountry = birthCountry;
+    }
+
+    public InteropKycResponseData(String nationality, String dateOfBirth, String contactPhone, String gender, IdDocument[] idDocument,
+            PostalAddress postalAddress, SubjectName subjectName, String emailAddress, String birthCountry) {
+        this(null, null, null, null, nationality, dateOfBirth, contactPhone, gender, idDocument, postalAddress, subjectName, emailAddress,
+                birthCountry);
+    }
+
+    public static InteropKycResponseData build(InteropKycData accountKyc) {
+
+        PostalAddress postalAddress = new PostalAddress(accountKyc.getAddressLine1(), accountKyc.getAddressLine2(), accountKyc.getCity(),
+                accountKyc.getStateProvince(), accountKyc.getPostalCode(), accountKyc.getCountry());
+        IdDocument idDocument = new IdDocument(accountKyc.getIdType(), accountKyc.getIdNo(), accountKyc.getCountry(),
+                accountKyc.getDescription());
+        SubjectName subjectName = new SubjectName(accountKyc.getFirstName(), accountKyc.getMiddleName(), accountKyc.getLastName(),
+                accountKyc.getDisplayName());
+
+        return new InteropKycResponseData(accountKyc.getNationality(), accountKyc.getDateOfBirth(), accountKyc.getContactPhone(),
+                accountKyc.getGender(), new IdDocument[] { idDocument }, postalAddress, subjectName, accountKyc.getEmail(),
+                accountKyc.getCountry());
+    }
+
+    public String getNationality() {
+        return nationality;
+    }
+
+    public void setNationality(String nationality) {
+        this.nationality = nationality;
+    }
+
+    public String getDateOfBirth() {
+        return dateOfBirth;
+    }
+
+    public void setDateOfBirth(String dateOfBirth) {
+        this.dateOfBirth = dateOfBirth;
+    }
+
+    public String getContactPhone() {
+        return contactPhone;
+    }
+
+    public void setContactPhone(String contactPhone) {
+        this.contactPhone = contactPhone;
+    }
+
+    public String getGender() {
+        return gender;
+    }
+
+    public void setGender(String gender) {
+        this.gender = gender;
+    }
+
+    public IdDocument[] getIdDocument() {
+        return idDocument;
+    }
+
+    public void setIdDocument(IdDocument[] idDocument) {
+        this.idDocument = idDocument;
+    }
+
+    public PostalAddress getPostalAddress() {
+        return postalAddress;
+    }
+
+    public void setPostalAddress(PostalAddress postalAddress) {
+        this.postalAddress = postalAddress;
+    }
+
+    public SubjectName getSubjectName() {
+        return subjectName;
+    }
+
+    public void setSubjectName(SubjectName subjectName) {
+        this.subjectName = subjectName;
+    }
+
+    public String getEmailAddress() {
+        return emailAddress;
+    }
+
+    public void setEmailAddress(String emailAddress) {
+        this.emailAddress = emailAddress;
+    }
+
+    public String getBirthCountry() {
+        return birthCountry;
+    }
+
+    public void setBirthCountry(String birthCountry) {
+        this.birthCountry = birthCountry;
+    }
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/PostalAddress.java b/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/PostalAddress.java
new file mode 100644
index 0000000..0c8f990
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/PostalAddress.java
@@ -0,0 +1,89 @@
+/**
+ * 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.interoperation.data;
+
+import java.io.Serializable;
+
+public class PostalAddress implements Serializable {
+
+    String addressLine1;
+    String addressLine2;
+    String city;
+    String stateProvince;
+    String postalCode;
+    String country;
+
+    public PostalAddress(String addressLine1, String addressLine2, String city, String stateProvince, String postalCode, String country) {
+        this.addressLine1 = addressLine1;
+        this.addressLine2 = addressLine2;
+        this.city = city;
+        this.stateProvince = stateProvince;
+        this.postalCode = postalCode;
+        this.country = country;
+    }
+
+    public String getAddressLine1() {
+        return addressLine1;
+    }
+
+    public void setAddressLine1(String addressLine1) {
+        this.addressLine1 = addressLine1;
+    }
+
+    public String getAddressLine2() {
+        return addressLine2;
+    }
+
+    public void setAddressLine2(String addressLine2) {
+        this.addressLine2 = addressLine2;
+    }
+
+    public String getCity() {
+        return city;
+    }
+
+    public void setCity(String city) {
+        this.city = city;
+    }
+
+    public String getStateProvince() {
+        return stateProvince;
+    }
+
+    public void setStateProvince(String stateProvince) {
+        this.stateProvince = stateProvince;
+    }
+
+    public String getPostalCode() {
+        return postalCode;
+    }
+
+    public void setPostalCode(String postalCode) {
+        this.postalCode = postalCode;
+    }
+
+    public String getCountry() {
+        return country;
+    }
+
+    public void setCountry(String country) {
+        this.country = country;
+    }
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/SubjectName.java b/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/SubjectName.java
new file mode 100644
index 0000000..3c67caa
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/interoperation/data/SubjectName.java
@@ -0,0 +1,68 @@
+/**
+ * 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.interoperation.data;
+
+import java.io.Serializable;
+
+public class SubjectName implements Serializable {
+
+    String firstName;
+    String middleName;
+    String lastName;
+    String displayName;
+
+    public SubjectName(String firstName, String middleName, String lastName, String displayName) {
+        this.firstName = firstName;
+        this.middleName = middleName;
+        this.lastName = lastName;
+        this.displayName = displayName;
+    }
+
+    public String getFirstName() {
+        return firstName;
+    }
+
+    public void setFirstName(String firstName) {
+        this.firstName = firstName;
+    }
+
+    public String getMiddleName() {
+        return middleName;
+    }
+
+    public void setMiddleName(String middleName) {
+        this.middleName = middleName;
+    }
+
+    public String getLastName() {
+        return lastName;
+    }
+
+    public void setLastName(String lastName) {
+        this.lastName = lastName;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public void setDisplayName(String displayName) {
+        this.displayName = displayName;
+    }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropService.java b/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropService.java
index 5746673..170b419 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropService.java
@@ -24,6 +24,7 @@ import org.apache.fineract.infrastructure.core.api.JsonCommand;
 import org.apache.fineract.interoperation.data.InteropAccountData;
 import org.apache.fineract.interoperation.data.InteropIdentifierAccountResponseData;
 import org.apache.fineract.interoperation.data.InteropIdentifiersResponseData;
+import org.apache.fineract.interoperation.data.InteropKycResponseData;
 import org.apache.fineract.interoperation.data.InteropQuoteResponseData;
 import org.apache.fineract.interoperation.data.InteropTransactionRequestResponseData;
 import org.apache.fineract.interoperation.data.InteropTransactionsData;
@@ -74,4 +75,10 @@ public interface InteropService {
 
     @NotNull
     InteropTransferResponseData releaseTransfer(@NotNull JsonCommand command);
+
+    @NotNull
+    InteropKycResponseData getKyc(@NotNull String accountId);
+
+    @NotNull
+    String disburseLoan(@NotNull String accountId, String apiRequestBodyAsJson);
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropServiceImpl.java
index 789c6fd..4fb0fff 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropServiceImpl.java
@@ -28,20 +28,30 @@ import static org.apache.fineract.portfolio.savings.domain.SavingsAccountTransac
 
 import jakarta.validation.constraints.NotNull;
 import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
 import java.time.ZoneId;
 import java.util.Date;
 import java.util.List;
 import java.util.Locale;
 import java.util.function.Predicate;
 import org.apache.commons.lang3.StringUtils;
+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.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
+import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
 import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
 import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
 import org.apache.fineract.interoperation.data.InteropAccountData;
 import org.apache.fineract.interoperation.data.InteropIdentifierAccountResponseData;
 import org.apache.fineract.interoperation.data.InteropIdentifierRequestData;
 import org.apache.fineract.interoperation.data.InteropIdentifiersResponseData;
+import org.apache.fineract.interoperation.data.InteropKycData;
+import org.apache.fineract.interoperation.data.InteropKycResponseData;
 import org.apache.fineract.interoperation.data.InteropQuoteRequestData;
 import org.apache.fineract.interoperation.data.InteropQuoteResponseData;
 import org.apache.fineract.interoperation.data.InteropRequestData;
@@ -61,6 +71,9 @@ import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
 import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepository;
 import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
 import org.apache.fineract.organisation.monetary.domain.Money;
+import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData;
+import org.apache.fineract.portfolio.loanaccount.domain.Loan;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
 import org.apache.fineract.portfolio.note.domain.Note;
 import org.apache.fineract.portfolio.note.domain.NoteRepository;
 import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
@@ -84,6 +97,9 @@ import org.joda.time.format.DateTimeFormatter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
@@ -102,19 +118,28 @@ public class InteropServiceImpl implements InteropService {
     private final NoteRepository noteRepository;
     private final PaymentTypeRepository paymentTypeRepository;
     private final InteropIdentifierRepository identifierRepository;
+    private final LoanRepository loanRepository;
 
     private final SavingsHelper savingsHelper;
     private final SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper;
 
     private final SavingsAccountDomainService savingsAccountService;
 
+    private final JdbcTemplate jdbcTemplate;
+
+    private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+
+    private final DefaultToApiJsonSerializer<LoanAccountData> toApiJsonSerializer;
+
     @Autowired
     public InteropServiceImpl(PlatformSecurityContext securityContext, InteropDataValidator interopDataValidator,
             SavingsAccountRepository savingsAccountRepository, SavingsAccountTransactionRepository savingsAccountTransactionRepository,
             ApplicationCurrencyRepository applicationCurrencyRepository, NoteRepository noteRepository,
-            PaymentTypeRepository paymentTypeRepository, InteropIdentifierRepository identifierRepository, SavingsHelper savingsHelper,
-            SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper,
-            SavingsAccountDomainService savingsAccountService) {
+            PaymentTypeRepository paymentTypeRepository, InteropIdentifierRepository identifierRepository, LoanRepository loanRepository,
+            SavingsHelper savingsHelper, SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper,
+            SavingsAccountDomainService savingsAccountService, final RoutingDataSource dataSource,
+            final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
+            final DefaultToApiJsonSerializer<LoanAccountData> toApiJsonSerializer) {
         this.securityContext = securityContext;
         this.dataValidator = interopDataValidator;
         this.savingsAccountRepository = savingsAccountRepository;
@@ -123,9 +148,56 @@ public class InteropServiceImpl implements InteropService {
         this.noteRepository = noteRepository;
         this.paymentTypeRepository = paymentTypeRepository;
         this.identifierRepository = identifierRepository;
+        this.loanRepository = loanRepository;
         this.savingsHelper = savingsHelper;
         this.savingsAccountTransactionSummaryWrapper = savingsAccountTransactionSummaryWrapper;
         this.savingsAccountService = savingsAccountService;
+        this.jdbcTemplate = new JdbcTemplate(dataSource);
+        this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+        this.toApiJsonSerializer = toApiJsonSerializer;
+    }
+
+    private static final class KycMapper implements RowMapper<InteropKycData> {
+
+        public String schema() {
+            return " country.code_value as nationality, c.`date_of_birth` as dateOfBirth, c.`mobile_no` as contactPhone, gender.code_value as gender, c.`email_address` as email, "
+                    + "kyc.code_value as idType, ci.`document_key` as idNo, ci.`description` as description, "
+                    + "country.code_value as country, a.`address_line_1`, a.`address_line_2`, "
+                    + "a.`city`, state.code_value as stateProvince, a.`postal_code` as postalCode, c.`firstname` as firstName, c.`middlename` as middleName,"
+                    + "c.`lastname` as lastName, c.`display_name` as displayName" + " from " + "m_client c "
+                    + "left join m_client_address ca on c.id=ca.client_id " + "left join m_address a on a.id = ca.address_id "
+                    + "inner join m_code_value gender on gender.id=c.`gender_cv_id` "
+                    + "left join m_code_value country on country.id=a.`country_id` "
+                    + "left join m_code_value state on state.id = a.`state_province_id` "
+                    + "left join m_client_identifier ci on c.id=ci.`client_id` "
+                    + "left join m_code_value kyc on kyc.id = ci.`document_type_id` ";
+        }
+
+        @Override
+        public InteropKycData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
+
+            final String nationality = rs.getString("nationality");
+            final String dateOfBirth = rs.getString("dateOfBirth");
+            final String contactPhone = rs.getString("contactPhone");
+            final String gender = rs.getString("gender");
+            final String email = rs.getString("email");
+            final String idType = rs.getString("idType");
+            final String idNo = rs.getString("idNo");
+            final String description = rs.getString("description");
+            final String country = rs.getString("country");
+            final String addressLine1 = rs.getString("address_line_1");
+            final String addressLine2 = rs.getString("address_line_2");
+            final String city = rs.getString("city");
+            final String stateProvince = rs.getString("stateProvince");
+            final String postalCode = rs.getString("postalCode");
+            final String firstName = rs.getString("firstName");
+            final String middleName = rs.getString("middleName");
+            final String lastName = rs.getString("lastName");
+            final String displayName = rs.getString("displayName");
+
+            return InteropKycData.instance(nationality, dateOfBirth, contactPhone, gender, email, idType, idNo, description, country,
+                    addressLine1, addressLine2, city, stateProvince, postalCode, firstName, middleName, lastName, displayName);
+        }
     }
 
     @NotNull
@@ -409,6 +481,39 @@ public class InteropServiceImpl implements InteropService {
                 request.getExpiration(), request.getExtensionList(), request.getTransferCode(), transactionDateTime);
     }
 
+    @Override
+    public @NotNull InteropKycResponseData getKyc(@NotNull @NotNull String accountId) {
+
+        SavingsAccount savingsAccount = validateAndGetSavingAccount(accountId);
+        Long client_id = savingsAccount.getClient().getId();
+
+        try {
+            final InteropServiceImpl.KycMapper rm = new InteropServiceImpl.KycMapper();
+            final String sql = "select " + rm.schema() + " where c.id = ?";
+
+            final InteropKycData accountKyc = this.jdbcTemplate.queryForObject(sql, rm, new Object[] { client_id });
+
+            return InteropKycResponseData.build(accountKyc);
+        } catch (final EmptyResultDataAccessException e) {
+            throw new UnsupportedOperationException("Error in retrieving KYC information: " + e);
+        }
+    }
+
+    @Override
+    public @NotNull String disburseLoan(@NotNull String accountId, String apiRequestBodyAsJson) {
+        Loan loan = validateAndGetLoan(accountId);
+        Long loanId = loan.getId();
+
+        LocalDateTime disbursedOnDate = DateUtils.getLocalDateTimeOfTenant();
+
+        final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
+
+        final CommandWrapper commandRequest = builder.disburseLoanApplication(loanId).build();
+        CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
+
+        return this.toApiJsonSerializer.serialize(result);
+    }
+
     private SavingsAccount validateAndGetSavingAccount(String accountId) {
         SavingsAccount savingsAccount = savingsAccountRepository.findByExternalId(accountId);
         if (savingsAccount == null) {
@@ -417,6 +522,14 @@ public class InteropServiceImpl implements InteropService {
         return savingsAccount;
     }
 
+    private Loan validateAndGetLoan(String accountId) {
+        Loan loan = loanRepository.findNonClosedLoanByAccountNumber(accountId);
+        if (loan == null) {
+            throw new UnsupportedOperationException("Loan not found for the given account No: " + accountId);
+        }
+        return loan;
+    }
+
     private SavingsAccount validateAndGetSavingAccount(@NotNull InteropRequestData request) {
         // TODO: error handling
         SavingsAccount savingsAccount = validateAndGetSavingAccount(request.getAccountId());