Merge branch 'PR372' into develop

This commit is contained in:
Nazeer Hussain Shaik
2017-06-28 15:33:24 +05:30
9 changed files with 265 additions and 6 deletions
@@ -98,6 +98,8 @@ public class CommandStrategyProvider {
"approveLoanCommandStrategy");
this.commandStrategies.put(CommandContext.resource("loans\\/\\d+\\?command=disburse").method("POST").build(),
"disburseLoanCommandStrategy");
this.commandStrategies.put(CommandContext.resource("rescheduleloans\\/\\d+\\?command=approve").method("POST").build(),
"approveLoanRescheduleCommandStrategy");
}
}
@@ -0,0 +1,78 @@
/**
* 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.batch.command.internal;
import javax.ws.rs.core.UriInfo;
import org.apache.fineract.batch.command.CommandStrategy;
import org.apache.fineract.batch.domain.BatchRequest;
import org.apache.fineract.batch.domain.BatchResponse;
import org.apache.fineract.batch.exception.ErrorHandler;
import org.apache.fineract.batch.exception.ErrorInfo;
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.api.RescheduleLoansApiResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class ApproveLoanRescheduleCommandStrategy implements CommandStrategy {
private final RescheduleLoansApiResource rescheduleLoansApiResource;
@Autowired
public ApproveLoanRescheduleCommandStrategy(final RescheduleLoansApiResource rescheduleLoansApiResource) {
this.rescheduleLoansApiResource = rescheduleLoansApiResource;
}
@Override
public BatchResponse execute(BatchRequest request, UriInfo uriInfo) {
final BatchResponse response = new BatchResponse();
final String responseBody;
response.setRequestId(request.getRequestId());
response.setHeaders(request.getHeaders());
final String[] pathParameters = request.getRelativeUrl().split("/");
Long scheduleId = Long.parseLong(pathParameters[1].substring(0, pathParameters[1].indexOf("?")));
// Try-catch blocks to map exceptions to appropriate status codes
try {
// Calls 'approve' function from 'Loans reschedule Request' to approve a
// loan
responseBody = rescheduleLoansApiResource.updateLoanRescheduleRequest(scheduleId, "approve", request.getBody());
response.setStatusCode(200);
// Sets the body of the response after the successful approval of a
// Loans reschedule Request
response.setBody(responseBody);
} catch (RuntimeException e) {
// Gets an object of type ErrorInfo, containing information about
// raised exception
ErrorInfo ex = ErrorHandler.handler(e);
response.setStatusCode(ex.getStatusCode());
response.setBody(ex.getMessage());
}
return response;
}
}
@@ -47,10 +47,19 @@ public class RescheduleLoansApiConstants {
public static final String adjustedDueDateParamName = "adjustedDueDate";
public static final String resheduleForMultiDisbursementNotSupportedErrorCode = "loan.reschedule.multidisbursement.error.code";
public static final String resheduleWithInterestRecalculationNotSupportedErrorCode = "loan.reschedule.interestrecalculation.error.code";
public static final String allCommandParamName = "all";
public static final String approveCommandParamName = "approve";
public static final String pendingCommandParamName = "pending";
public static final String rejectCommandParamName = "reject";
// reject action request parameters
public static final String rejectedOnDateParam = "rejectedOnDate";
// approve action request parameters
public static final String approvedOnDateParam = "approvedOnDate";
public static final Set<String> APPROVE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName, dateFormatParamName,
approvedOnDateParam));
public static final Set<String> commandParams = new HashSet<>(Arrays.asList(allCommandParamName, approveCommandParamName, pendingCommandParamName, rejectCommandParamName));
}
@@ -19,6 +19,7 @@
package org.apache.fineract.portfolio.loanaccount.rescheduleloan.api;
import java.util.HashSet;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@@ -96,7 +97,7 @@ public class RescheduleLoansApiResource {
return this.loanRescheduleRequestToApiJsonSerializer.serialize(settings, loanRescheduleReasons);
}
@GET
@Path("{scheduleId}")
@Consumes({ MediaType.APPLICATION_JSON })
@@ -170,6 +171,24 @@ public class RescheduleLoansApiResource {
private boolean compareIgnoreCase(String firstString, String secondString) {
return StringUtils.isNotBlank(firstString) && firstString.trim().equalsIgnoreCase(secondString);
}
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllRescheduleRequest(@Context final UriInfo uriInfo, @QueryParam("command") final String command) {
this.platformSecurityContext.authenticatedUser().validateHasReadPermission(RescheduleLoansApiConstants.ENTITY_NAME);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
if (StringUtils.isNotBlank(command) && !RescheduleLoansApiConstants.commandParams.contains(command.toLowerCase())) { throw new UnrecognizedQueryParamException(
"command", command, new Object[] { RescheduleLoansApiConstants.allCommandParamName,
RescheduleLoansApiConstants.pendingCommandParamName, RescheduleLoansApiConstants.approveCommandParamName,
RescheduleLoansApiConstants.rejectCommandParamName }); }
final List<LoanRescheduleRequestData> loanRescheduleRequestsData = this.loanRescheduleRequestReadPlatformService
.retrieveAllRescheduleRequests(command);
return this.loanRescheduleRequestToApiJsonSerializer.serialize(settings, loanRescheduleRequestsData);
}
/*@GET
@Path("{scheduleId}")
@@ -86,7 +86,43 @@ public class LoanRescheduleRequestData {
rescheduleReasonCodeValue, rescheduleReasonComment, timeline, clientName, loanAccountNumber, clientId, recalculateInterest,
rescheduleReasons, loanTermVariationsData);
}
/**
* LoanRescheduleRequestData constructor
*
* @param loanTermVariationsData
* TODO
**/
private LoanRescheduleRequestData(Long id, Long loanId, LoanRescheduleRequestStatusEnumData statusEnum, final String clientName,
final String loanAccountNumber, final Long clientId, final LocalDate rescheduleFromDate,
final CodeValueData rescheduleReasonCodeValue) {
this.id = id;
this.loanId = loanId;
this.statusEnum = statusEnum;
this.clientName = clientName;
this.loanAccountNumber = loanAccountNumber;
this.clientId = clientId;
this.rescheduleFromDate = rescheduleFromDate;
this.rescheduleReasonCodeValue = rescheduleReasonCodeValue;
this.rescheduleFromInstallment = null;
this.rescheduleReasonComment = null;
this.timeline = null;
this.recalculateInterest = null;
this.rescheduleReasons = null;
this.loanTermVariationsData = null;
}
/**
* @return an instance of the LoanRescheduleRequestData class
**/
public static LoanRescheduleRequestData instance(Long id, Long loanId, LoanRescheduleRequestStatusEnumData statusEnum,
final String clientName, final String loanAccountNumber, final Long clientId, final LocalDate rescheduleFromDate,
final CodeValueData rescheduleReasonCodeValue) {
return new LoanRescheduleRequestData(id, loanId, statusEnum, clientName, loanAccountNumber, clientId, rescheduleFromDate,
rescheduleReasonCodeValue);
}
/**
* @return the id
*/
@@ -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.loanaccount.rescheduleloan.domain;
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.exception.LoanRescheduleRequestNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class LoanRescheduleRequestRepositoryWrapper {
private final LoanRescheduleRequestRepository loanRescheduleRequestRepository;
@Autowired
public LoanRescheduleRequestRepositoryWrapper(final LoanRescheduleRequestRepository loanRescheduleRequestRepository) {
this.loanRescheduleRequestRepository = loanRescheduleRequestRepository;
}
public LoanRescheduleRequest findOneWithNotFoundDetection(final Long id) {
return this.findOneWithNotFoundDetection(id, false);
}
@Transactional(readOnly = true)
public LoanRescheduleRequest findOneWithNotFoundDetection(final Long id, boolean loadLazyCollections) {
final LoanRescheduleRequest loanRescheduleRequest = this.loanRescheduleRequestRepository.findOne(id);
if (loanRescheduleRequest == null) { throw new LoanRescheduleRequestNotFoundException(id); }
if (loadLazyCollections) {
loanRescheduleRequest.getLoan().initializeLazyCollections();
}
return loanRescheduleRequest;
}
}
@@ -41,7 +41,7 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanSchedul
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleGeneratorFactory;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequest;
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequestRepository;
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequestRepositoryWrapper;
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.exception.LoanRescheduleRequestNotFoundException;
import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
import org.joda.time.LocalDate;
@@ -51,7 +51,7 @@ import org.springframework.stereotype.Service;
@Service
public class LoanReschedulePreviewPlatformServiceImpl implements LoanReschedulePreviewPlatformService {
private final LoanRescheduleRequestRepository loanRescheduleRequestRepository;
private final LoanRescheduleRequestRepositoryWrapper loanRescheduleRequestRepository;
private final LoanUtilService loanUtilService;
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
private final LoanScheduleGeneratorFactory loanScheduleFactory;
@@ -59,7 +59,7 @@ public class LoanReschedulePreviewPlatformServiceImpl implements LoanRescheduleP
private final DefaultScheduledDateGenerator scheduledDateGenerator = new DefaultScheduledDateGenerator();
@Autowired
public LoanReschedulePreviewPlatformServiceImpl(final LoanRescheduleRequestRepository loanRescheduleRequestRepository,
public LoanReschedulePreviewPlatformServiceImpl(final LoanRescheduleRequestRepositoryWrapper loanRescheduleRequestRepository,
final LoanUtilService loanUtilService,
final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory,
final LoanScheduleGeneratorFactory loanScheduleFactory, final LoanSummaryWrapper loanSummaryWrapper) {
@@ -72,7 +72,7 @@ public class LoanReschedulePreviewPlatformServiceImpl implements LoanRescheduleP
@Override
public LoanScheduleModel previewLoanReschedule(Long requestId) {
final LoanRescheduleRequest loanRescheduleRequest = this.loanRescheduleRequestRepository.findOne(requestId);
final LoanRescheduleRequest loanRescheduleRequest = this.loanRescheduleRequestRepository.findOneWithNotFoundDetection(requestId, true);
if (loanRescheduleRequest == null) { throw new LoanRescheduleRequestNotFoundException(requestId); }
@@ -59,4 +59,15 @@ public interface LoanRescheduleRequestReadPlatformService {
* @return list of LoanRescheduleRequestData objects
**/
public LoanRescheduleRequestData retrieveAllRescheduleReasons(String loanRescheduleReason);
/**
* get all loan reschedule request
*
* @param command
* all/null - give all request
* approved - give all approved request
* pending - give all request which is pending for approval
* reject - give all rejected requests
* @return list of LoanRescheduleRequestData objects
**/
public List<LoanRescheduleRequestData> retrieveAllRescheduleRequests(String command);
}
@@ -31,6 +31,7 @@ import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.RescheduleLoansApiConstants;
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.data.LoanRescheduleRequestData;
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.data.LoanRescheduleRequestEnumerations;
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.data.LoanRescheduleRequestStatusEnumData;
@@ -43,6 +44,8 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import com.amazonaws.util.StringUtils;
@Service
public class LoanRescheduleRequestReadPlatformServiceImpl implements LoanRescheduleRequestReadPlatformService {
@@ -190,6 +193,40 @@ public class LoanRescheduleRequestReadPlatformServiceImpl implements LoanResched
}
private static final class LoanRescheduleRequestRowMapperForBulkApproval implements RowMapper<LoanRescheduleRequestData> {
public String schema() {
final StringBuilder sqlBuilder = new StringBuilder(200);
sqlBuilder.append("lrr.id as id, lrr.status_enum as statusEnum, lrr.reschedule_from_date as rescheduleFromDate, ");
sqlBuilder.append("cv.id as rescheduleReasonCvId, cv.code_value as rescheduleReasonCvValue, ");
sqlBuilder
.append(" loan.id as loanId, loan.account_no as loanAccountNumber, client.id as clientId, client.display_name as clientName ");
sqlBuilder.append("from m_loan_reschedule_request lrr ");
sqlBuilder.append("left join m_loan loan on loan.id = lrr.loan_id ");
sqlBuilder.append("left join m_client client on client.id = loan.client_id ");
sqlBuilder.append("left join m_code_value cv on cv.id = lrr.reschedule_reason_cv_id ");
return sqlBuilder.toString();
}
@Override
public LoanRescheduleRequestData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final Long loanId = rs.getLong("loanId");
final Integer statusEnumId = JdbcSupport.getInteger(rs, "statusEnum");
final LoanRescheduleRequestStatusEnumData statusEnum = LoanRescheduleRequestEnumerations.status(statusEnumId);
final String clientName = rs.getString("clientName");
final String loanAccountNumber = rs.getString("loanAccountNumber");
final Long clientId = rs.getLong("clientId");
final LocalDate rescheduleFromDate = JdbcSupport.getLocalDate(rs, "rescheduleFromDate");
final Long rescheduleReasonCvId = JdbcSupport.getLong(rs, "rescheduleReasonCvId");
final String rescheduleReasonCvValue = rs.getString("rescheduleReasonCvValue");
final CodeValueData rescheduleReasonCodeValue = CodeValueData.instance(rescheduleReasonCvId, rescheduleReasonCvValue);
return LoanRescheduleRequestData.instance(id, loanId, statusEnum, clientName, loanAccountNumber, clientId, rescheduleFromDate,
rescheduleReasonCodeValue);
}
}
@Override
public List<LoanRescheduleRequestData> readLoanRescheduleRequests(Long loanId) {
this.loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
@@ -241,4 +278,21 @@ public class LoanRescheduleRequestReadPlatformServiceImpl implements LoanResched
rescheduleReasonCodeValue, rescheduleReasonComment, timeline, clientName, loanAccountNumber, clientId, recalculateInterest,
rescheduleReasons, loanTermVariationsData);
}
@Override
public List<LoanRescheduleRequestData> retrieveAllRescheduleRequests(String command) {
LoanRescheduleRequestRowMapperForBulkApproval loanRescheduleRequestRowMapperForBulkApproval = new LoanRescheduleRequestRowMapperForBulkApproval();
String sql = "select " + loanRescheduleRequestRowMapperForBulkApproval.schema();
if (!StringUtils.isNullOrEmpty(command) && !command.equalsIgnoreCase(RescheduleLoansApiConstants.allCommandParamName)) {
sql = sql + " where lrr.status_enum = ? ";
Integer statusParam = 100;
if (command.equalsIgnoreCase(RescheduleLoansApiConstants.approveCommandParamName)) {
statusParam = 200;
} else if (command.equalsIgnoreCase(RescheduleLoansApiConstants.rejectCommandParamName)) {
statusParam = 300;
}
return this.jdbcTemplate.query(sql, loanRescheduleRequestRowMapperForBulkApproval, new Object[] { statusParam });
}
return this.jdbcTemplate.query(sql, loanRescheduleRequestRowMapperForBulkApproval, new Object[] {});
}
}