diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/ReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/ReadPlatformService.java index 0de2ef21b..5a6fbce27 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/ReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/ReadPlatformService.java @@ -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); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/ReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/ReadPlatformServiceImpl.java index bbc57ae08..6f4c6d68b 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/ReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/ReadPlatformServiceImpl.java @@ -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); - } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java new file mode 100644 index 000000000..2c38c7170 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java @@ -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(); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformService.java new file mode 100644 index 000000000..189be73c5 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformService.java @@ -0,0 +1,8 @@ +package org.mifosng.platform.loan.service; + +import org.mifosng.data.LoanAccountData; + +public interface LoanReadPlatformService { + + LoanAccountData retrieveLoanAccountDetails(Long loanId); +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java new file mode 100644 index 000000000..1509cac64 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java @@ -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); + } + +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/rest/LoanResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/rest/LoanResource.java index d3d259faf..2943450c4 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/rest/LoanResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/rest/LoanResource.java @@ -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 allErrors = new ArrayList(); - 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 })