Merge pull request #480 from ShruthiRajaram/FINERACT-628-Guarantors-Support

FINERACT-628 guarantor api for self service user
This commit is contained in:
ShruthiRajaram
2018-11-05 16:27:20 +05:30
committed by GitHub
8 changed files with 412 additions and 6 deletions
+248
View File
@@ -3785,6 +3785,22 @@
<td></td>
<td></td>
</tr>
<tr>
<td><a href="#self_guarantors_list">Guarantor and Obligee details</a></td>
<td>self/loans/{loanId}/guarantors</td>
<td></td>
<td><a href="#self_guarantors_list">Guarantors list</a></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>self/clients/{clientId}/obligeedetails</td>
<td></td>
<td><a href="#self_obligee_list">Obligee list</a></td>
<td></td>
<td></td>
</tr>
</table>
</div>
</div>
@@ -48862,6 +48878,238 @@ Request Body:
</div>
</div>
<a id="self_guarantors_list" name="self_guarantors_list"
class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>List Guarantors</h4>
<p>Example Requests:</p>
<div class=apiClick>self/loans/33/guarantors</div>
<br>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/api/v1/self/loans/{loanId}/guarantors
</code>
<code class="method-response">
[
{
"id":6,
"loanId":33,
"guarantorType":{
"id":1,
"code":"guarantor.existing.customer",
"value":"CUSTOMER"
},
"firstname":"Abhishek v",
"lastname":"M",
"entityId":12,
"officeName":"Head Office",
"joinedDate":[
2014,
7,
5
],
"guarantorFundingDetails":[
{
"id":7,
"status":{
"id":100,
"code":"guarantorFundStatusType.active",
"value":"ACTIVE"
},
"savingsAccount":{
"id":28,
"accountNo":"000000028"
},
"amount":2000,
"amountReleased":0,
"amountRemaining":2000,
"amountTransfered":0,
"guarantorTransactions":[
{
"id":6,
"onHoldTransactionData":{
"id":6,
"amount":2000,
"transactionType":{
"id":1,
"code":"deposutAccountOnHoldTransactionType.hold",
"value":"hold"
},
"transactionDate":[
2018,
10,
10
],
"reversed":false,
"savingsId":0,
"loanId":0
},
"reversed":false
}
]
}
],
"status":true
},
{
"id":7,
"loanId":33,
"clientRelationshipType":{
"id":6,
"name":"Parent",
"active":false,
"mandatory":false
},
"guarantorType":{
"id":1,
"code":"guarantor.existing.customer",
"value":"CUSTOMER"
},
"firstname":"Bheem",
"lastname":"Test",
"entityId":14,
"officeName":"Head Office",
"joinedDate":[
2013,
7,
3
],
"guarantorFundingDetails":[
{
"id":8,
"status":{
"id":100,
"code":"guarantorFundStatusType.active",
"value":"ACTIVE"
},
"savingsAccount":{
"id":37,
"accountNo":"000000037"
},
"amount":1000,
"amountReleased":0,
"amountRemaining":1000,
"amountTransfered":0,
"guarantorTransactions":[
{
"id":7,
"onHoldTransactionData":{
"id":7,
"amount":1000,
"transactionType":{
"id":1,
"code":"deposutAccountOnHoldTransactionType.hold",
"value":"hold"
},
"transactionDate":[
2018,
10,
10
],
"reversed":false,
"savingsId":0,
"loanId":0
},
"reversed":false
}
]
}
],
"status":true
}
]
</code>
</div>
</div>
<a id="self_obligee_list" name="self_obligee_list"
class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Obligee List</h4>
<p>Obligee list provides list of clients and other details, to whom the user has agreed to be a guarantor.</p>
<table class=matrixHeading>
<tr class="matrixHeadingBG"><td><div class="fineractHeading2">Field Descriptions</div></td></tr>
<tr class=alt><td>clientId</td></tr>
<tr><td class=fielddesc>The client id of the self service user.</td></tr>
<tr class=alt><td>firstName, lastName, displayName</td></tr>
<tr><td class=fielddesc>The first name, last name and display name of the obligee</td></tr>
<tr class=alt><td>accountNumber, loanAmount</td></tr>
<tr><td class=fielddesc>The loan account number and principal amount of the obligee </td></tr>
<tr class=alt><td>guaranteeAmount, amountReleased, amountTransferred</td></tr>
<tr><td class=fielddesc>Guranteed amount, released and transferred amount of the client</td></tr>
</table>
<p>Example Requests:</p>
<div class=apiClick>self/clients/14/obligeedetails</div>
<br>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/api/v1/self/clients/{clientId}/obligeedetails
</code>
<code class="method-response">
[
{
"firstName":"App",
"lastName":"Test",
"displayName":"App Test",
"accountNumber":"000000005",
"loanAmount":50000,
"guaranteeAmount":10000,
"amountReleased":0,
"amountTransferred":0
},
{
"firstName":"App",
"lastName":"Test",
"displayName":"App Test",
"accountNumber":"000000005",
"loanAmount":50000,
"guaranteeAmount":5000,
"amountReleased":0,
"amountTransferred":0
},
{
"firstName":"App",
"lastName":"Test",
"displayName":"App Test",
"accountNumber":"000000006",
"loanAmount":50000,
"guaranteeAmount":10000,
"amountReleased":0,
"amountTransferred":0
},
{
"firstName":"Abhishek v",
"lastName":"M",
"displayName":"Abhishek v M",
"accountNumber":"000000032",
"loanAmount":10000,
"guaranteeAmount":1000,
"amountReleased":1000,
"amountTransferred":0
},
{
"firstName":"Abhishek v",
"lastName":"M",
"displayName":"Abhishek v M",
"accountNumber":"000000033",
"loanAmount":10000,
"guaranteeAmount":1000,
"amountReleased":0,
"amountTransferred":0
}
]
</code>
</div>
</div>
<!-- end of Customer Self Service APIs-->
</div>
<!-- main-content-wrapper -->
@@ -186,6 +186,7 @@ public class ClientApiConstants {
public static final String staffOptionsParamName = "staffOptions";
public static final String datatables = "datatables";
public static final String obligeeData = "ObligeeDetails";
/**
@@ -22,6 +22,7 @@ import java.io.InputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.ws.rs.Consumes;
@@ -39,8 +40,6 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam;
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
@@ -59,12 +58,17 @@ import org.apache.fineract.portfolio.accountdetails.data.AccountSummaryCollectio
import org.apache.fineract.portfolio.accountdetails.service.AccountDetailsReadPlatformService;
import org.apache.fineract.portfolio.client.data.ClientData;
import org.apache.fineract.portfolio.client.service.ClientReadPlatformService;
import org.apache.fineract.portfolio.loanaccount.guarantor.data.ObligeeData;
import org.apache.fineract.portfolio.loanaccount.guarantor.service.GuarantorReadPlatformService;
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
import org.apache.fineract.portfolio.savings.service.SavingsAccountReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam;
@Path("/clients")
@Component
@Scope("singleton")
@@ -80,6 +84,7 @@ public class ClientsApiResource {
private final SavingsAccountReadPlatformService savingsAccountReadPlatformService;
private final BulkImportWorkbookService bulkImportWorkbookService;
private final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService;
private final GuarantorReadPlatformService guarantorReadPlatformService;
@Autowired
public ClientsApiResource(final PlatformSecurityContext context, final ClientReadPlatformService readPlatformService,
@@ -90,7 +95,7 @@ public class ClientsApiResource {
final AccountDetailsReadPlatformService accountDetailsReadPlatformService,
final SavingsAccountReadPlatformService savingsAccountReadPlatformService,
final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService,
final BulkImportWorkbookService bulkImportWorkbookService) {
final BulkImportWorkbookService bulkImportWorkbookService, final GuarantorReadPlatformService guarantorReadPlatformService) {
this.context = context;
this.clientReadPlatformService = readPlatformService;
this.toApiJsonSerializer = toApiJsonSerializer;
@@ -101,6 +106,7 @@ public class ClientsApiResource {
this.savingsAccountReadPlatformService = savingsAccountReadPlatformService;
this.bulkImportWorkbookPopulatorService=bulkImportWorkbookPopulatorService;
this.bulkImportWorkbookService=bulkImportWorkbookService;
this.guarantorReadPlatformService = guarantorReadPlatformService;
}
@GET
@@ -341,4 +347,18 @@ public class ClientsApiResource {
final Long importDocumentId = bulkImportWorkbookService.importWorkbook(legalFormType, uploadedInputStream,fileDetail,locale,dateFormat);
return this.toApiJsonSerializer.serialize(importDocumentId);
}
@GET
@Path("{clientId}/obligeedetails")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveObligeeDetails(@PathParam("clientId") final Long clientId, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(ClientApiConstants.CLIENT_RESOURCE_NAME);
final List<ObligeeData> ObligeeList = this.guarantorReadPlatformService.retrieveObligeeDetails(clientId);
return this.toApiJsonSerializer.serialize(ObligeeList);
}
}
@@ -0,0 +1,56 @@
/**
* 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.loanaccount.guarantor.data;
import java.math.BigDecimal;
@SuppressWarnings("unused")
public class ObligeeData {
private final String firstName;
private final String lastName;
private final String displayName;
private final String accountNumber;
private final BigDecimal loanAmount;
private final BigDecimal guaranteeAmount;
private final BigDecimal amountReleased;
private final BigDecimal amountTransferred;
private ObligeeData(String firstname, String lastname, String displayName, String accountNumber,
BigDecimal loanAmount, BigDecimal guaranteeAmount, BigDecimal amountReleased,
BigDecimal amountTransferred) {
this.firstName = firstname;
this.lastName = lastname;
this.displayName = displayName;
this.accountNumber = accountNumber;
this.loanAmount = loanAmount;
this.guaranteeAmount = guaranteeAmount;
this.amountReleased = amountReleased;
this.amountTransferred = amountTransferred;
}
public static ObligeeData instance(final String firstname, final String lastname, final String displayName,
final String accountNumber, final BigDecimal loanAmount, final BigDecimal guaranteeAmount,
final BigDecimal amountReleased, final BigDecimal amountTransferred) {
return new ObligeeData(firstname, lastname, displayName, accountNumber, loanAmount, guaranteeAmount,
amountReleased, amountTransferred);
}
}
@@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.guarantor.service;
import java.util.List;
import org.apache.fineract.portfolio.loanaccount.guarantor.data.GuarantorData;
import org.apache.fineract.portfolio.loanaccount.guarantor.data.ObligeeData;
public interface GuarantorReadPlatformService {
@@ -41,6 +42,8 @@ public interface GuarantorReadPlatformService {
*/
List<GuarantorData> retrieveGuarantorsForLoan(Long loanId);
GuarantorData retrieveGuarantor(Long loanId, Long guarantorId);
GuarantorData retrieveGuarantor(Long loanId, Long guarantorId);
List<ObligeeData> retrieveObligeeDetails(Long clientId);
}
@@ -39,10 +39,12 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
import org.apache.fineract.portfolio.loanaccount.guarantor.data.GuarantorData;
import org.apache.fineract.portfolio.loanaccount.guarantor.data.GuarantorFundingData;
import org.apache.fineract.portfolio.loanaccount.guarantor.data.GuarantorTransactionData;
import org.apache.fineract.portfolio.loanaccount.guarantor.data.ObligeeData;
import org.apache.fineract.portfolio.savings.data.DepositAccountOnHoldTransactionData;
import org.apache.fineract.portfolio.savings.service.SavingsEnumerations;
import org.joda.time.LocalDate;
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;
@@ -254,7 +256,7 @@ public class GuarantorReadPlatformServiceImpl implements GuarantorReadPlatformSe
}
@Override
public GuarantorTransactionData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
public GuarantorTransactionData mapRow(final ResultSet rs, final int rowNum) throws SQLException {
GuarantorTransactionData guarantorTransactionData = null;
final Long id = rs.getLong("gtId");
final Long transactionId = rs.getLong("ohtId");
@@ -288,4 +290,56 @@ public class GuarantorReadPlatformServiceImpl implements GuarantorReadPlatformSe
return guarantorData;
}
@Override
public List<ObligeeData> retrieveObligeeDetails(final Long clientId) {
final ObligeeMapper rm = new ObligeeMapper();
String sql = rm.schema();
try {
return this.jdbcTemplate.query(sql, rm, new Object[] { clientId });
} catch (final EmptyResultDataAccessException e) {
return null;
}
}
private static final class ObligeeMapper implements RowMapper<ObligeeData> {
private final String sql;
public ObligeeMapper() {
StringBuilder sb = new StringBuilder(
"SELECT cl.firstname, cl.lastname,cl.display_name as displayName, loan.account_no as loanAccountNumber, loan.principal_amount as loanAmount, gfd.amount as guaranteedAmount, ");
sb.append(
"gfd.amount_released_derived as amountReleased, gfd.amount_transfered_derived as amountTransferred FROM m_guarantor mg");
sb.append(" JOIN m_guarantor_funding_details gfd on mg.id = gfd.guarantor_id ");
sb.append(
" JOIN m_client mc ON mg.entity_id = mc.id AND mc.id = ? JOIN m_loan loan ON mg.loan_id = loan.id ");
sb.append(" JOIN m_client cl ON loan.client_id = cl.id ");
sql = sb.toString();
}
public String schema() {
return this.sql;
}
@Override
public ObligeeData mapRow(final ResultSet rs, final int rowNum)
throws SQLException {
final String firstName = rs.getString("firstname");
final String lastName = rs.getString("lastname");
final String displayName = rs.getString("displayName");
final String loanAccountNumber = rs.getString("loanAccountNumber");
final BigDecimal loanAmount = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "loanAmount");
final BigDecimal guaranteeAmount = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "guaranteedAmount");
final BigDecimal amountReleased = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amountReleased");
final BigDecimal amountTransferred = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amountTransferred");
return ObligeeData.instance(firstName, lastName, displayName, loanAccountNumber, loanAmount,
guaranteeAmount, amountReleased, amountTransferred);
}
}
}
@@ -218,4 +218,15 @@ public class SelfClientsApiResource {
}
}
@GET
@Path("{clientId}/obligeedetails")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveObligeeDetails(@PathParam("clientId") final Long clientId, @Context final UriInfo uriInfo) {
validateAppuserClientsMapping(clientId);
return this.clientApiResource.retrieveObligeeDetails(clientId, uriInfo);
}
}
@@ -42,6 +42,7 @@ import org.apache.fineract.portfolio.loanaccount.api.LoansApiResource;
import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
import org.apache.fineract.portfolio.loanaccount.exception.LoanTemplateTypeRequiredException;
import org.apache.fineract.portfolio.loanaccount.exception.NotSupportedLoanTemplateTypeException;
import org.apache.fineract.portfolio.loanaccount.guarantor.api.GuarantorsApiResource;
import org.apache.fineract.portfolio.self.client.service.AppuserClientMapperReadService;
import org.apache.fineract.portfolio.self.loanaccount.data.SelfLoansDataValidator;
import org.apache.fineract.portfolio.self.loanaccount.service.AppuserLoansMapperReadService;
@@ -62,6 +63,7 @@ public class SelfLoansApiResource {
private final AppuserLoansMapperReadService appuserLoansMapperReadService;
private final AppuserClientMapperReadService appUserClientMapperReadService;
private final SelfLoansDataValidator dataValidator;
private final GuarantorsApiResource guarantorsApiResource;
@Autowired
public SelfLoansApiResource(final PlatformSecurityContext context,
@@ -70,7 +72,7 @@ public class SelfLoansApiResource {
final LoanChargesApiResource loanChargesApiResource,
final AppuserLoansMapperReadService appuserLoansMapperReadService,
final AppuserClientMapperReadService appUserClientMapperReadService,
final SelfLoansDataValidator dataValidator) {
final SelfLoansDataValidator dataValidator, final GuarantorsApiResource guarantorsApiResource) {
this.context = context;
this.loansApiResource = loansApiResource;
this.loanTransactionsApiResource = loanTransactionsApiResource;
@@ -78,6 +80,7 @@ public class SelfLoansApiResource {
this.appuserLoansMapperReadService = appuserLoansMapperReadService;
this.appUserClientMapperReadService = appUserClientMapperReadService;
this.dataValidator = dataValidator;
this.guarantorsApiResource = guarantorsApiResource;
}
@GET
@@ -232,5 +235,15 @@ public class SelfLoansApiResource {
private boolean is(final String commandParam, final String commandValue) {
return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue);
}
@GET
@Path("{loanId}/guarantors")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveGuarantorDetails(@PathParam("loanId") final Long loanId, @Context final UriInfo uriInfo) {
validateAppuserLoanMapping(loanId);
return this.guarantorsApiResource.retrieveGuarantorDetails(uriInfo, loanId);
}
}