reschedule bulk loan 149 and 481
This commit is contained in:
+2
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
+78
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+10
-1
@@ -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));
|
||||
}
|
||||
|
||||
+20
-1
@@ -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}")
|
||||
|
||||
+36
@@ -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
|
||||
*/
|
||||
|
||||
+50
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -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); }
|
||||
|
||||
|
||||
+11
@@ -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);
|
||||
}
|
||||
|
||||
+54
@@ -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[] {});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user