add loan resource to support retrieve of individual loan.

This commit is contained in:
Keith Woodlock
2012-05-15 23:37:02 +01:00
parent 04d4fbaf85
commit b0a8b84f6f
6 changed files with 215 additions and 154 deletions
@@ -2,7 +2,6 @@ package org.mifosng.platform;
import java.util.Collection;
import org.mifosng.data.LoanAccountData;
import org.mifosng.data.LoanRepaymentData;
import org.mifosng.data.NewLoanWorkflowStepOneData;
import org.mifosng.data.OrganisationReadModel;
@@ -13,8 +12,6 @@ public interface ReadPlatformService {
NewLoanWorkflowStepOneData retrieveClientAndProductDetails(Long clientId, Long productId);
LoanAccountData retrieveLoanAccountDetails(Long loanId);
LoanRepaymentData retrieveNewLoanRepaymentDetails(Long loanId);
LoanRepaymentData retrieveNewLoanWaiverDetails(Long loanId);
@@ -13,14 +13,11 @@ import javax.sql.DataSource;
import org.joda.time.LocalDate;
import org.mifosng.data.ClientData;
import org.mifosng.data.CurrencyData;
import org.mifosng.data.DerivedLoanData;
import org.mifosng.data.LoanAccountData;
import org.mifosng.data.LoanProductData;
import org.mifosng.data.LoanRepaymentData;
import org.mifosng.data.MoneyData;
import org.mifosng.data.NewLoanWorkflowStepOneData;
import org.mifosng.data.OrganisationReadModel;
import org.mifosng.platform.client.domain.ClientRepository;
import org.mifosng.platform.client.service.ClientReadPlatformService;
import org.mifosng.platform.currency.domain.ApplicationCurrency;
import org.mifosng.platform.currency.domain.ApplicationCurrencyRepository;
@@ -32,7 +29,6 @@ import org.mifosng.platform.loan.domain.LoanTransaction;
import org.mifosng.platform.loan.domain.LoanTransactionRepository;
import org.mifosng.platform.loanproduct.service.LoanProductReadPlatformService;
import org.mifosng.platform.user.domain.AppUser;
import org.mifosng.platform.user.service.AppUserReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
@@ -45,31 +41,25 @@ import org.springframework.stereotype.Service;
public class ReadPlatformServiceImpl implements ReadPlatformService {
private final SimpleJdbcTemplate jdbcTemplate;
private final ClientRepository clientRepository;
private final LoanRepository loanRepository;
private final LoanTransactionRepository loanTransactionRepository;
private final ApplicationCurrencyRepository applicationCurrencyRepository;
private final LoanProductReadPlatformService loanProductReadPlatformService;
private final AppUserReadPlatformService appUserReadPlatformService;
private final ClientReadPlatformService clientReadPlatformService;
@Autowired
public ReadPlatformServiceImpl(
final LoanProductReadPlatformService loanProductReadPlatformService,
final AppUserReadPlatformService appUserReadPlatformService,
final ClientReadPlatformService clientReadPlatformService,
final DataSource dataSource,
final ClientRepository clientRepository,
final LoanRepository loanRepository,
final LoanTransactionRepository loanTransactionRepository,
final ApplicationCurrencyRepository applicationCurrencyRepository) {
this.loanProductReadPlatformService = loanProductReadPlatformService;
this.appUserReadPlatformService = appUserReadPlatformService;
this.clientReadPlatformService = clientReadPlatformService;
this.loanTransactionRepository = loanTransactionRepository;
this.applicationCurrencyRepository = applicationCurrencyRepository;
this.jdbcTemplate = new SimpleJdbcTemplate(dataSource);
this.clientRepository = clientRepository;
this.loanRepository = loanRepository;
}
@@ -260,112 +250,4 @@ public class ReadPlatformServiceImpl implements ReadPlatformService {
}
return match;
}
@Override
public LoanAccountData retrieveLoanAccountDetails(Long loanId) {
// TODO - OPTIMISE - prefer jdbc sql approach to return only what we
// need of loan information.
AppUser currentUser = extractAuthenticatedUser();
Loan loan = this.loanRepository.findOne(loansThatMatch(
currentUser.getOrganisation(), loanId));
ApplicationCurrency currency = this.applicationCurrencyRepository
.findOneByCode(loan.getLoanRepaymentScheduleDetail()
.getPrincipal().getCurrencyCode());
CurrencyData currencyData = new CurrencyData(currency.getCode(),
currency.getName(), currency.getDecimalPlaces(),
currency.getDisplaySymbol(), currency.getNameCode());
LoanAccountData loanData = convertToData(loan, currencyData);
return loanData;
}
private LoanAccountData convertToData(final Loan realLoan,
CurrencyData currencyData) {
DerivedLoanData loanData = realLoan.deriveLoanData(currencyData);
LocalDate expectedDisbursementDate = null;
if (realLoan.getExpectedDisbursedOnDate() != null) {
expectedDisbursementDate = new LocalDate(
realLoan.getExpectedDisbursedOnDate());
}
Money loanPrincipal = realLoan.getLoanRepaymentScheduleDetail()
.getPrincipal();
MoneyData principal = MoneyData.of(currencyData,
loanPrincipal.getAmount());
Money loanArrearsTolerance = realLoan.getInArrearsTolerance();
MoneyData tolerance = MoneyData.of(currencyData,
loanArrearsTolerance.getAmount());
Money interestRebate = realLoan.getInterestRebateOwed();
MoneyData interestRebateOwed = MoneyData.of(currencyData,
interestRebate.getAmount());
boolean interestRebateOutstanding = false; // realLoan.isInterestRebateOutstanding(),
// permissions
boolean waiveAllowed = loanData.getSummary().isWaiveAllowed(tolerance)
&& realLoan.isNotClosed();
boolean undoDisbursalAllowed = realLoan.isDisbursed()
&& realLoan.isOpenWithNoRepaymentMade();
boolean makeRepaymentAllowed = realLoan.isDisbursed()
&& realLoan.isNotClosed();
LocalDate loanStatusDate = realLoan.getLoanStatusSinceDate();
boolean rejectAllowed = realLoan.isNotApproved()
&& realLoan.isNotDisbursed() && realLoan.isNotClosed();
boolean withdrawnByApplicantAllowed = realLoan.isNotDisbursed()
&& realLoan.isNotClosed();
boolean undoApprovalAllowed = realLoan.isApproved()
&& realLoan.isNotClosed();
boolean disbursalAllowed = realLoan.isApproved()
&& realLoan.isNotDisbursed() && realLoan.isNotClosed();
return new LoanAccountData(realLoan.isClosed(), realLoan.isOpen(),
realLoan.isOpenWithRepaymentMade(), interestRebateOutstanding,
realLoan.isSubmittedAndPendingApproval(),
realLoan.isWaitingForDisbursal(), undoDisbursalAllowed,
makeRepaymentAllowed, rejectAllowed,
withdrawnByApplicantAllowed, undoApprovalAllowed,
disbursalAllowed, realLoan.getLoanStatusDisplayName(),
loanStatusDate, realLoan.getId(), realLoan.getExternalId(),
realLoan.getLoanProduct().getName(),
realLoan.getClosedOnDate(), realLoan.getSubmittedOnDate(),
realLoan.getApprovedOnDate(), expectedDisbursementDate,
realLoan.getDisbursedOnDate(),
realLoan.getExpectedMaturityDate(),
realLoan.getExpectedFirstRepaymentOnDate(),
realLoan.getInterestCalculatedFromDate(), principal, realLoan
.getLoanRepaymentScheduleDetail()
.getAnnualNominalInterestRate(), realLoan
.getLoanRepaymentScheduleDetail()
.getNominalInterestRatePerPeriod(), realLoan
.getLoanRepaymentScheduleDetail()
.getInterestPeriodFrequencyType().getValue(), realLoan
.getLoanRepaymentScheduleDetail()
.getInterestPeriodFrequencyType().toString(), realLoan
.getLoanRepaymentScheduleDetail().getInterestMethod()
.getValue(), realLoan.getLoanRepaymentScheduleDetail()
.getInterestMethod().toString(), realLoan
.getLoanRepaymentScheduleDetail()
.getAmortizationMethod().getValue(), realLoan
.getLoanRepaymentScheduleDetail()
.getAmortizationMethod().toString(), realLoan
.getLoanRepaymentScheduleDetail()
.getNumberOfRepayments(), realLoan
.getLoanRepaymentScheduleDetail().getRepayEvery(),
realLoan.getLoanRepaymentScheduleDetail()
.getRepaymentPeriodFrequencyType().getValue(), realLoan
.getLoanRepaymentScheduleDetail()
.getRepaymentPeriodFrequencyType().toString(),
tolerance, loanData, waiveAllowed, interestRebateOwed);
}
}
@@ -0,0 +1,58 @@
package org.mifosng.platform.api;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.mifosng.data.LoanAccountData;
import org.mifosng.platform.ReadPlatformService;
import org.mifosng.platform.loan.service.LoanReadPlatformService;
import org.mifosng.platform.user.domain.AppUser;
import org.mifosng.platform.user.domain.AppUserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
@Path("/v1/loans")
@Component
@Scope("singleton")
public class LoansApiResource {
@Autowired
private LoanReadPlatformService loanReadPlatformService;
@Autowired
private ReadPlatformService readPlatformService;
@Autowired
private AppUserRepository appUserRepository;
private void hardcodeUserIntoSecurityContext() {
AppUser currentUser = this.appUserRepository.findOne(Long.valueOf(1));
Authentication auth = new UsernamePasswordAuthenticationToken(currentUser, currentUser, currentUser.getAuthorities());
SecurityContext context = SecurityContextHolder.getContext();
context.setAuthentication(auth);
}
@GET
@Path("{loanId}")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({ MediaType.APPLICATION_JSON})
public Response retrieveLoanAccountDetails(@PathParam("loanId") final Long loanId) {
hardcodeUserIntoSecurityContext();
LoanAccountData loanAccount = this.loanReadPlatformService.retrieveLoanAccountDetails(loanId);
return Response.ok().entity(loanAccount).build();
}
}
@@ -0,0 +1,8 @@
package org.mifosng.platform.loan.service;
import org.mifosng.data.LoanAccountData;
public interface LoanReadPlatformService {
LoanAccountData retrieveLoanAccountDetails(Long loanId);
}
@@ -0,0 +1,148 @@
package org.mifosng.platform.loan.service;
import static org.mifosng.platform.Specifications.loansThatMatch;
import javax.sql.DataSource;
import org.joda.time.LocalDate;
import org.mifosng.data.CurrencyData;
import org.mifosng.data.DerivedLoanData;
import org.mifosng.data.LoanAccountData;
import org.mifosng.data.MoneyData;
import org.mifosng.platform.currency.domain.ApplicationCurrency;
import org.mifosng.platform.currency.domain.ApplicationCurrencyRepository;
import org.mifosng.platform.currency.domain.Money;
import org.mifosng.platform.loan.domain.Loan;
import org.mifosng.platform.loan.domain.LoanRepository;
import org.mifosng.platform.security.PlatformSecurityContext;
import org.mifosng.platform.user.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.stereotype.Service;
@Service
public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
private final SimpleJdbcTemplate jdbcTemplate;
private final PlatformSecurityContext context;
private final LoanRepository loanRepository;
private final ApplicationCurrencyRepository applicationCurrencyRepository;
@Autowired
public LoanReadPlatformServiceImpl(final PlatformSecurityContext context, final DataSource dataSource,
final LoanRepository loanRepository, final ApplicationCurrencyRepository applicationCurrencyRepository) {
this.context = context;
this.loanRepository = loanRepository;
this.applicationCurrencyRepository = applicationCurrencyRepository;
this.jdbcTemplate = new SimpleJdbcTemplate(dataSource);
}
@Override
public LoanAccountData retrieveLoanAccountDetails(Long loanId) {
// TODO - OPTIMISE - prefer jdbc sql approach to return only what we
// need of loan information.
AppUser currentUser = context.authenticatedUser();
Loan loan = this.loanRepository.findOne(loansThatMatch(
currentUser.getOrganisation(), loanId));
ApplicationCurrency currency = this.applicationCurrencyRepository
.findOneByCode(loan.getLoanRepaymentScheduleDetail()
.getPrincipal().getCurrencyCode());
CurrencyData currencyData = new CurrencyData(currency.getCode(),
currency.getName(), currency.getDecimalPlaces(),
currency.getDisplaySymbol(), currency.getNameCode());
LoanAccountData loanData = convertToData(loan, currencyData);
return loanData;
}
private LoanAccountData convertToData(final Loan realLoan,
CurrencyData currencyData) {
DerivedLoanData loanData = realLoan.deriveLoanData(currencyData);
LocalDate expectedDisbursementDate = null;
if (realLoan.getExpectedDisbursedOnDate() != null) {
expectedDisbursementDate = new LocalDate(
realLoan.getExpectedDisbursedOnDate());
}
Money loanPrincipal = realLoan.getLoanRepaymentScheduleDetail()
.getPrincipal();
MoneyData principal = MoneyData.of(currencyData,
loanPrincipal.getAmount());
Money loanArrearsTolerance = realLoan.getInArrearsTolerance();
MoneyData tolerance = MoneyData.of(currencyData,
loanArrearsTolerance.getAmount());
Money interestRebate = realLoan.getInterestRebateOwed();
MoneyData interestRebateOwed = MoneyData.of(currencyData,
interestRebate.getAmount());
boolean interestRebateOutstanding = false; // realLoan.isInterestRebateOutstanding(),
// permissions
boolean waiveAllowed = loanData.getSummary().isWaiveAllowed(tolerance)
&& realLoan.isNotClosed();
boolean undoDisbursalAllowed = realLoan.isDisbursed()
&& realLoan.isOpenWithNoRepaymentMade();
boolean makeRepaymentAllowed = realLoan.isDisbursed()
&& realLoan.isNotClosed();
LocalDate loanStatusDate = realLoan.getLoanStatusSinceDate();
boolean rejectAllowed = realLoan.isNotApproved()
&& realLoan.isNotDisbursed() && realLoan.isNotClosed();
boolean withdrawnByApplicantAllowed = realLoan.isNotDisbursed()
&& realLoan.isNotClosed();
boolean undoApprovalAllowed = realLoan.isApproved()
&& realLoan.isNotClosed();
boolean disbursalAllowed = realLoan.isApproved()
&& realLoan.isNotDisbursed() && realLoan.isNotClosed();
return new LoanAccountData(realLoan.isClosed(), realLoan.isOpen(),
realLoan.isOpenWithRepaymentMade(), interestRebateOutstanding,
realLoan.isSubmittedAndPendingApproval(),
realLoan.isWaitingForDisbursal(), undoDisbursalAllowed,
makeRepaymentAllowed, rejectAllowed,
withdrawnByApplicantAllowed, undoApprovalAllowed,
disbursalAllowed, realLoan.getLoanStatusDisplayName(),
loanStatusDate, realLoan.getId(), realLoan.getExternalId(),
realLoan.getLoanProduct().getName(),
realLoan.getClosedOnDate(), realLoan.getSubmittedOnDate(),
realLoan.getApprovedOnDate(), expectedDisbursementDate,
realLoan.getDisbursedOnDate(),
realLoan.getExpectedMaturityDate(),
realLoan.getExpectedFirstRepaymentOnDate(),
realLoan.getInterestCalculatedFromDate(), principal, realLoan
.getLoanRepaymentScheduleDetail()
.getAnnualNominalInterestRate(), realLoan
.getLoanRepaymentScheduleDetail()
.getNominalInterestRatePerPeriod(), realLoan
.getLoanRepaymentScheduleDetail()
.getInterestPeriodFrequencyType().getValue(), realLoan
.getLoanRepaymentScheduleDetail()
.getInterestPeriodFrequencyType().toString(), realLoan
.getLoanRepaymentScheduleDetail().getInterestMethod()
.getValue(), realLoan.getLoanRepaymentScheduleDetail()
.getInterestMethod().toString(), realLoan
.getLoanRepaymentScheduleDetail()
.getAmortizationMethod().getValue(), realLoan
.getLoanRepaymentScheduleDetail()
.getAmortizationMethod().toString(), realLoan
.getLoanRepaymentScheduleDetail()
.getNumberOfRepayments(), realLoan
.getLoanRepaymentScheduleDetail().getRepayEvery(),
realLoan.getLoanRepaymentScheduleDetail()
.getRepaymentPeriodFrequencyType().getValue(), realLoan
.getLoanRepaymentScheduleDetail()
.getRepaymentPeriodFrequencyType().toString(),
tolerance, loanData, waiveAllowed, interestRebateOwed);
}
}
@@ -19,7 +19,6 @@ import javax.ws.rs.core.Response.Status;
import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.ErrorResponse;
import org.mifosng.data.ErrorResponseList;
import org.mifosng.data.LoanAccountData;
import org.mifosng.data.LoanRepaymentData;
import org.mifosng.data.LoanSchedule;
import org.mifosng.data.NewLoanWorkflowStepOneData;
@@ -35,8 +34,8 @@ import org.mifosng.platform.ReadPlatformService;
import org.mifosng.platform.ReadPlatformServiceImpl;
import org.mifosng.platform.WritePlatformService;
import org.mifosng.platform.exceptions.ApplicationDomainRuleException;
import org.mifosng.platform.exceptions.UnAuthenticatedUserException;
import org.mifosng.platform.exceptions.NewDataValidationException;
import org.mifosng.platform.exceptions.UnAuthenticatedUserException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -153,37 +152,6 @@ public class LoanResource {
}
}
@GET
@Path("{loanId}")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response retrieveLoanAccountDetails(@PathParam("loanId") final Long loanId) {
try {
LoanAccountData loanAccount = this.readPlatformService.retrieveLoanAccountDetails(loanId);
return Response.ok().entity(loanAccount).build();
} catch (UnAuthenticatedUserException e) {
throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build());
} catch (AccessDeniedException e) {
ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission", "id");
ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse));
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build());
} catch (ApplicationDomainRuleException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getErrors())).build());
} catch (NewDataValidationException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getValidationErrors())).build());
} catch (Exception e) {
logger.error(e.getMessage(), e);
List<ErrorResponse> allErrors = new ArrayList<ErrorResponse>();
ErrorResponse err = new ErrorResponse("unknown.error", "error", e.getMessage());
allErrors.add(err);
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(allErrors)).build());
}
}
@DELETE
@Path("{loanId}")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })