support submit new loan application and delete loan capabilities through api.
This commit is contained in:
@@ -2,9 +2,10 @@ package org.mifosng.data;
|
|||||||
|
|
||||||
import javax.xml.bind.annotation.XmlRootElement;
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* TODO - Arguments is still not correctly supported
|
* Being removed in favour of {@link ApiGlobalErrorResponse} and {@link ApiParameterError}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
@XmlRootElement(name="errorResponse")
|
@XmlRootElement(name="errorResponse")
|
||||||
public class ErrorResponse {
|
public class ErrorResponse {
|
||||||
|
|
||||||
|
|||||||
+101
-87
@@ -9,13 +9,28 @@ import org.joda.time.LocalDate;
|
|||||||
@XmlRootElement
|
@XmlRootElement
|
||||||
public class CalculateLoanScheduleCommand {
|
public class CalculateLoanScheduleCommand {
|
||||||
|
|
||||||
private CommonLoanProperties commonLoanProperties;
|
private String currencyCode;
|
||||||
|
private Integer digitsAfterDecimal;
|
||||||
|
private BigDecimal principal;
|
||||||
|
private BigDecimal inArrearsToleranceAmount;
|
||||||
|
|
||||||
|
private Integer repaymentEvery;
|
||||||
|
private Integer repaymentFrequency;
|
||||||
|
private Integer numberOfRepayments;
|
||||||
|
|
||||||
|
private BigDecimal interestRatePerPeriod;
|
||||||
|
private Integer interestRateFrequencyMethod;
|
||||||
|
private Integer amortizationMethod;
|
||||||
|
private Integer interestMethod;
|
||||||
|
private Integer interestCalculationPeriodMethod;
|
||||||
|
private boolean flexibleRepaymentSchedule = false;
|
||||||
|
private boolean interestRebateAllowed = false;
|
||||||
|
|
||||||
private LocalDate expectedDisbursementDate;
|
private LocalDate expectedDisbursementDate;
|
||||||
private LocalDate repaymentsStartingFromDate;
|
private LocalDate repaymentsStartingFromDate;
|
||||||
private LocalDate interestCalculatedFromDate;
|
private LocalDate interestCalculatedFromDate;
|
||||||
|
|
||||||
public CalculateLoanScheduleCommand() {
|
protected CalculateLoanScheduleCommand() {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,132 +38,139 @@ public class CalculateLoanScheduleCommand {
|
|||||||
final Integer digitsAfterDecimal, final Number principal,
|
final Integer digitsAfterDecimal, final Number principal,
|
||||||
final Number interestRatePerPeriod, Integer interestRateFrequencyMethod, final Integer interestMethod, final Integer interestCalculationPeriodMethod,
|
final Number interestRatePerPeriod, Integer interestRateFrequencyMethod, final Integer interestMethod, final Integer interestCalculationPeriodMethod,
|
||||||
final Integer repaymentEvery, final Integer repaymentFrequency, final Integer numberOfRepayments, Integer amortizationMethod,
|
final Integer repaymentEvery, final Integer repaymentFrequency, final Integer numberOfRepayments, Integer amortizationMethod,
|
||||||
final boolean flexibleRepaymentSchedule,
|
|
||||||
final boolean interestRebateAllowed,
|
|
||||||
final LocalDate expectedDisbursementDate,
|
final LocalDate expectedDisbursementDate,
|
||||||
final LocalDate repaymentsStartingFromDate, final LocalDate interestCalculatedFromDate) {
|
final LocalDate repaymentsStartingFromDate, final LocalDate interestCalculatedFromDate) {
|
||||||
|
|
||||||
commonLoanProperties = new CommonLoanProperties(currencyCode, digitsAfterDecimal, principal, interestRatePerPeriod, interestRateFrequencyMethod,
|
this.currencyCode = currencyCode;
|
||||||
interestMethod, interestCalculationPeriodMethod,
|
this.digitsAfterDecimal = digitsAfterDecimal;
|
||||||
repaymentEvery, repaymentFrequency, numberOfRepayments, amortizationMethod, Integer.valueOf(0),
|
this.principal = BigDecimal.valueOf(principal.doubleValue());
|
||||||
flexibleRepaymentSchedule, interestRebateAllowed);
|
this.interestRatePerPeriod = BigDecimal.valueOf(interestRatePerPeriod.doubleValue());
|
||||||
|
this.interestRateFrequencyMethod = interestRateFrequencyMethod;
|
||||||
|
this.interestMethod = interestMethod;
|
||||||
|
this.interestCalculationPeriodMethod = interestCalculationPeriodMethod;
|
||||||
|
this.repaymentEvery = repaymentEvery;
|
||||||
|
this.repaymentFrequency = repaymentFrequency;
|
||||||
|
this.numberOfRepayments = numberOfRepayments;
|
||||||
|
this.amortizationMethod = amortizationMethod;
|
||||||
|
this.flexibleRepaymentSchedule = false;
|
||||||
|
this.interestRebateAllowed = false;
|
||||||
|
|
||||||
this.expectedDisbursementDate = expectedDisbursementDate;
|
this.expectedDisbursementDate = expectedDisbursementDate;
|
||||||
this.repaymentsStartingFromDate = repaymentsStartingFromDate;
|
this.repaymentsStartingFromDate = repaymentsStartingFromDate;
|
||||||
this.interestCalculatedFromDate = interestCalculatedFromDate;
|
this.interestCalculatedFromDate = interestCalculatedFromDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCurrencyCode() {
|
public String getCurrencyCode() {
|
||||||
return this.commonLoanProperties.getCurrencyCode();
|
return currencyCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrencyCode(final String currencyCode) {
|
public void setCurrencyCode(String currencyCode) {
|
||||||
this.commonLoanProperties.setCurrencyCode(currencyCode);
|
this.currencyCode = currencyCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getDigitsAfterDecimal() {
|
public Integer getDigitsAfterDecimal() {
|
||||||
return this.commonLoanProperties.getDigitsAfterDecimal();
|
return digitsAfterDecimal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDigitsAfterDecimal(final Integer digitsAfterDecimal) {
|
public void setDigitsAfterDecimal(Integer digitsAfterDecimal) {
|
||||||
this.commonLoanProperties.setDigitsAfterDecimal(digitsAfterDecimal);
|
this.digitsAfterDecimal = digitsAfterDecimal;
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getRepaymentEvery() {
|
|
||||||
return this.commonLoanProperties.getRepaymentEvery();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRepaymentEvery(final Integer repaymentEvery) {
|
|
||||||
this.commonLoanProperties.setRepaymentEvery(repaymentEvery);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getRepaymentFrequency() {
|
|
||||||
return this.commonLoanProperties.getRepaymentFrequency();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRepaymentFrequency(final Integer repaymentFrequency) {
|
|
||||||
this.commonLoanProperties.setRepaymentFrequency(repaymentFrequency);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean isFlexibleRepaymentSchedule() {
|
|
||||||
return this.commonLoanProperties.isFlexibleRepaymentSchedule();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFlexibleRepaymentSchedule(
|
|
||||||
final Boolean flexibleRepaymentSchedule) {
|
|
||||||
this.commonLoanProperties.setFlexibleRepaymentSchedule(flexibleRepaymentSchedule);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean isInterestRebateAllowed() {
|
|
||||||
return this.commonLoanProperties.isInterestRebateAllowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInterestRebateAllowed(final Boolean interestRebateAllowed) {
|
|
||||||
this.commonLoanProperties.setInterestRebateAllowed(interestRebateAllowed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getPrincipal() {
|
public BigDecimal getPrincipal() {
|
||||||
return this.commonLoanProperties.getPrincipal();
|
return principal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPrincipal(final BigDecimal principal) {
|
public void setPrincipal(BigDecimal principal) {
|
||||||
this.commonLoanProperties.setPrincipal(principal);
|
this.principal = principal;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public Boolean getFlexibleRepaymentSchedule() {
|
public BigDecimal getInArrearsToleranceAmount() {
|
||||||
// return this.commonLoanProperties.getFlexibleRepaymentSchedule();
|
return inArrearsToleranceAmount;
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public Boolean getInterestRebateAllowed() {
|
|
||||||
// return this.commonLoanProperties.getInterestRebateAllowed();
|
|
||||||
// }
|
|
||||||
|
|
||||||
public Integer getInterestRateFrequencyMethod() {
|
|
||||||
return commonLoanProperties.getInterestRateFrequencyMethod();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInterestRateFrequencyMethod(Integer interestRateFrequencyMethod) {
|
public void setInArrearsToleranceAmount(BigDecimal inArrearsToleranceAmount) {
|
||||||
this.commonLoanProperties.setInterestRateFrequencyMethod(interestRateFrequencyMethod);
|
this.inArrearsToleranceAmount = inArrearsToleranceAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getInterestMethod() {
|
public Integer getRepaymentEvery() {
|
||||||
return commonLoanProperties.getInterestMethod();
|
return repaymentEvery;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInterestMethod(Integer interestMethod) {
|
public void setRepaymentEvery(Integer repaymentEvery) {
|
||||||
this.commonLoanProperties.setInterestMethod(interestMethod);
|
this.repaymentEvery = repaymentEvery;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getAmortizationMethod() {
|
public Integer getRepaymentFrequency() {
|
||||||
return commonLoanProperties.getAmortizationMethod();
|
return repaymentFrequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAmortizationMethod(Integer amortizationMethod) {
|
public void setRepaymentFrequency(Integer repaymentFrequency) {
|
||||||
this.commonLoanProperties.setAmortizationMethod(amortizationMethod);
|
this.repaymentFrequency = repaymentFrequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getNumberOfRepayments() {
|
public Integer getNumberOfRepayments() {
|
||||||
return commonLoanProperties.getNumberOfRepayments();
|
return numberOfRepayments;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNumberOfRepayments(Integer numberOfRepayments) {
|
public void setNumberOfRepayments(Integer numberOfRepayments) {
|
||||||
this.commonLoanProperties.setNumberOfRepayments(numberOfRepayments);
|
this.numberOfRepayments = numberOfRepayments;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getInterestRatePerPeriod() {
|
public BigDecimal getInterestRatePerPeriod() {
|
||||||
return commonLoanProperties.getInterestRatePerPeriod();
|
return interestRatePerPeriod;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInterestRatePerPeriod(BigDecimal interestRatePerPeriod) {
|
public void setInterestRatePerPeriod(BigDecimal interestRatePerPeriod) {
|
||||||
this.commonLoanProperties.setInterestRatePerPeriod(interestRatePerPeriod);
|
this.interestRatePerPeriod = interestRatePerPeriod;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommonLoanProperties getCommonLoanProperties() {
|
public Integer getInterestRateFrequencyMethod() {
|
||||||
return commonLoanProperties;
|
return interestRateFrequencyMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCommonLoanProperties(CommonLoanProperties commonLoanProperties) {
|
public void setInterestRateFrequencyMethod(Integer interestRateFrequencyMethod) {
|
||||||
this.commonLoanProperties = commonLoanProperties;
|
this.interestRateFrequencyMethod = interestRateFrequencyMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getAmortizationMethod() {
|
||||||
|
return amortizationMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAmortizationMethod(Integer amortizationMethod) {
|
||||||
|
this.amortizationMethod = amortizationMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getInterestMethod() {
|
||||||
|
return interestMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInterestMethod(Integer interestMethod) {
|
||||||
|
this.interestMethod = interestMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getInterestCalculationPeriodMethod() {
|
||||||
|
return interestCalculationPeriodMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInterestCalculationPeriodMethod(
|
||||||
|
Integer interestCalculationPeriodMethod) {
|
||||||
|
this.interestCalculationPeriodMethod = interestCalculationPeriodMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFlexibleRepaymentSchedule() {
|
||||||
|
return flexibleRepaymentSchedule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFlexibleRepaymentSchedule(boolean flexibleRepaymentSchedule) {
|
||||||
|
this.flexibleRepaymentSchedule = flexibleRepaymentSchedule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInterestRebateAllowed() {
|
||||||
|
return interestRebateAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInterestRebateAllowed(boolean interestRebateAllowed) {
|
||||||
|
this.interestRebateAllowed = interestRebateAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalDate getExpectedDisbursementDate() {
|
public LocalDate getExpectedDisbursementDate() {
|
||||||
@@ -174,12 +196,4 @@ public class CalculateLoanScheduleCommand {
|
|||||||
public void setInterestCalculatedFromDate(LocalDate interestCalculatedFromDate) {
|
public void setInterestCalculatedFromDate(LocalDate interestCalculatedFromDate) {
|
||||||
this.interestCalculatedFromDate = interestCalculatedFromDate;
|
this.interestCalculatedFromDate = interestCalculatedFromDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getInterestCalculationPeriodMethod() {
|
|
||||||
return this.commonLoanProperties.getInterestCalculationPeriodMethod();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInterestCalculationPeriodMethod(final Integer interestCalculationPeriodMethod) {
|
|
||||||
this.commonLoanProperties.setInterestCalculationPeriodMethod(interestCalculationPeriodMethod);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
package org.mifosng.data.command;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
public interface LoanProductCommandData {
|
|
||||||
|
|
||||||
String getName();
|
|
||||||
|
|
||||||
String getDescription();
|
|
||||||
|
|
||||||
String getCurrencyCode();
|
|
||||||
|
|
||||||
Integer getDigitsAfterDecimal();
|
|
||||||
|
|
||||||
Integer getRepaymentEvery();
|
|
||||||
|
|
||||||
Integer getRepaymentFrequency();
|
|
||||||
|
|
||||||
Boolean isFlexibleRepaymentSchedule();
|
|
||||||
|
|
||||||
Boolean isInterestRebateAllowed();
|
|
||||||
|
|
||||||
BigDecimal getPrincipal();
|
|
||||||
|
|
||||||
// Boolean getFlexibleRepaymentSchedule();
|
|
||||||
|
|
||||||
// Boolean getInterestRebateAllowed();
|
|
||||||
|
|
||||||
Integer getInterestRateFrequencyMethod();
|
|
||||||
|
|
||||||
Integer getInterestMethod();
|
|
||||||
|
|
||||||
Integer getAmortizationMethod();
|
|
||||||
|
|
||||||
Integer getNumberOfRepayments();
|
|
||||||
|
|
||||||
BigDecimal getInterestRatePerPeriod();
|
|
||||||
|
|
||||||
CommonLoanProperties getCommonLoanProperties();
|
|
||||||
|
|
||||||
BigDecimal getInArrearsToleranceAmount();
|
|
||||||
|
|
||||||
Integer getInterestCalculationPeriodMethod();
|
|
||||||
}
|
|
||||||
+206
-116
@@ -9,20 +9,45 @@ import org.mifosng.data.LoanSchedule;
|
|||||||
|
|
||||||
@XmlRootElement
|
@XmlRootElement
|
||||||
public class SubmitLoanApplicationCommand {
|
public class SubmitLoanApplicationCommand {
|
||||||
|
|
||||||
private Long applicantId;
|
private Long applicantId;
|
||||||
private Long productId;
|
private Long productId;
|
||||||
|
|
||||||
|
// product
|
||||||
|
private String currencyCode;
|
||||||
|
private Integer digitsAfterDecimal;
|
||||||
|
private String principalFormatted;
|
||||||
|
private BigDecimal principal;
|
||||||
|
private String inArrearsToleranceAmountFormatted;
|
||||||
|
private BigDecimal inArrearsToleranceAmount;
|
||||||
|
|
||||||
|
private Integer repaymentEvery;
|
||||||
|
private Integer repaymentFrequency;
|
||||||
|
private Integer numberOfRepayments;
|
||||||
|
|
||||||
|
private String interestRatePerPeriodFormatted;
|
||||||
|
private BigDecimal interestRatePerPeriod;
|
||||||
|
private Integer interestRateFrequencyMethod;
|
||||||
|
private Integer amortizationMethod;
|
||||||
|
private Integer interestMethod;
|
||||||
|
private Integer interestCalculationPeriodMethod;
|
||||||
|
private boolean flexibleRepaymentSchedule = false;
|
||||||
|
private boolean interestRebateAllowed = false;
|
||||||
|
//
|
||||||
|
|
||||||
|
private String expectedDisbursementDateFormatted;
|
||||||
|
private String repaymentsStartingFromDateFormatted;
|
||||||
|
private String interestCalculatedFromDateFormatted;
|
||||||
private LocalDate expectedDisbursementDate;
|
private LocalDate expectedDisbursementDate;
|
||||||
private LocalDate repaymentsStartingFromDate;
|
private LocalDate repaymentsStartingFromDate;
|
||||||
private LocalDate interestCalculatedFromDate;
|
private LocalDate interestCalculatedFromDate;
|
||||||
|
|
||||||
|
private String dateFormat;
|
||||||
|
private String submittedOnDateFormatted;
|
||||||
private LocalDate submittedOnDate;
|
private LocalDate submittedOnDate;
|
||||||
private String submittedOnNote;
|
private String submittedOnNote;
|
||||||
private String externalId;
|
private String externalId;
|
||||||
|
|
||||||
private CommonLoanProperties commonLoanProperties;
|
|
||||||
|
|
||||||
private LoanSchedule loanSchedule;
|
private LoanSchedule loanSchedule;
|
||||||
|
|
||||||
protected SubmitLoanApplicationCommand() {
|
protected SubmitLoanApplicationCommand() {
|
||||||
@@ -38,22 +63,34 @@ public class SubmitLoanApplicationCommand {
|
|||||||
final LoanSchedule loanSchedule, final String currencyCode,
|
final LoanSchedule loanSchedule, final String currencyCode,
|
||||||
final Integer digitsAfterDecimal, final Number principal,
|
final Integer digitsAfterDecimal, final Number principal,
|
||||||
final Number interestRatePerPeriod, Integer interestRateFrequencyMethod, final Integer interestMethod, final Integer interestCalculationPeriodMethod,
|
final Number interestRatePerPeriod, Integer interestRateFrequencyMethod, final Integer interestMethod, final Integer interestCalculationPeriodMethod,
|
||||||
final Integer repaymentEvery, final Integer repaymentFrequency, final Integer numberOfRepayments, Integer amortizationMethod, final Number toleranceAmount,
|
final Integer repaymentEvery, final Integer repaymentFrequency, final Integer numberOfRepayments, Integer amortizationMethod, final Number toleranceAmount) {
|
||||||
final boolean flexibleRepaymentSchedule,
|
|
||||||
final boolean interestRebateAllowed) {
|
|
||||||
this.applicantId = applicantId;
|
this.applicantId = applicantId;
|
||||||
this.productId = productId;
|
this.productId = productId;
|
||||||
this.submittedOnDate = submittedOnDate;
|
this.submittedOnDate = submittedOnDate;
|
||||||
this.submittedOnNote = submittedOnNote;
|
this.submittedOnNote = submittedOnNote;
|
||||||
|
|
||||||
commonLoanProperties = new CommonLoanProperties(currencyCode, digitsAfterDecimal, principal, interestRatePerPeriod, interestRateFrequencyMethod,
|
|
||||||
interestMethod, interestCalculationPeriodMethod,
|
|
||||||
repaymentEvery, repaymentFrequency, numberOfRepayments, amortizationMethod, toleranceAmount, flexibleRepaymentSchedule, interestRebateAllowed);
|
|
||||||
|
|
||||||
this.expectedDisbursementDate = expectedDisbursementDate;
|
this.expectedDisbursementDate = expectedDisbursementDate;
|
||||||
this.repaymentsStartingFromDate = repaymentsStartingFromDate;
|
this.repaymentsStartingFromDate = repaymentsStartingFromDate;
|
||||||
this.interestCalculatedFromDate = interestCalculatedFromDate;
|
this.interestCalculatedFromDate = interestCalculatedFromDate;
|
||||||
this.loanSchedule = loanSchedule;
|
this.loanSchedule = loanSchedule;
|
||||||
|
this.inArrearsToleranceAmount = BigDecimal.valueOf(toleranceAmount.doubleValue());
|
||||||
|
|
||||||
|
this.currencyCode = currencyCode;
|
||||||
|
this.digitsAfterDecimal = digitsAfterDecimal;
|
||||||
|
this.principal = BigDecimal.valueOf(principal.doubleValue());
|
||||||
|
this.interestRatePerPeriod = BigDecimal.valueOf(interestRatePerPeriod.doubleValue());
|
||||||
|
this.interestRateFrequencyMethod = interestRateFrequencyMethod;
|
||||||
|
this.interestMethod = interestMethod;
|
||||||
|
this.interestCalculationPeriodMethod = interestCalculationPeriodMethod;
|
||||||
|
this.repaymentEvery = repaymentEvery;
|
||||||
|
this.repaymentFrequency = repaymentFrequency;
|
||||||
|
this.numberOfRepayments = numberOfRepayments;
|
||||||
|
this.amortizationMethod = amortizationMethod;
|
||||||
|
this.flexibleRepaymentSchedule = false;
|
||||||
|
this.interestRebateAllowed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CalculateLoanScheduleCommand toCalculateLoanScheduleCommand() {
|
||||||
|
return new CalculateLoanScheduleCommand(currencyCode, digitsAfterDecimal, principal, interestRatePerPeriod, interestRateFrequencyMethod, interestMethod, interestCalculationPeriodMethod, repaymentEvery, repaymentFrequency, numberOfRepayments, amortizationMethod, expectedDisbursementDate, repaymentsStartingFromDate, interestCalculatedFromDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getApplicantId() {
|
public Long getApplicantId() {
|
||||||
@@ -122,125 +159,117 @@ public class SubmitLoanApplicationCommand {
|
|||||||
this.externalId = externalId;
|
this.externalId = externalId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommonLoanProperties getCommonLoanProperties() {
|
|
||||||
return commonLoanProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCommonLoanProperties(CommonLoanProperties commonLoanProperties) {
|
|
||||||
this.commonLoanProperties = commonLoanProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCurrencyCode() {
|
public String getCurrencyCode() {
|
||||||
return this.commonLoanProperties.getCurrencyCode();
|
return currencyCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrencyCode(final String currencyCode) {
|
public void setCurrencyCode(String currencyCode) {
|
||||||
this.commonLoanProperties.setCurrencyCode(currencyCode);
|
this.currencyCode = currencyCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getDigitsAfterDecimal() {
|
public Integer getDigitsAfterDecimal() {
|
||||||
return this.commonLoanProperties.getDigitsAfterDecimal();
|
return digitsAfterDecimal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDigitsAfterDecimal(final Integer digitsAfterDecimal) {
|
public void setDigitsAfterDecimal(Integer digitsAfterDecimal) {
|
||||||
this.commonLoanProperties.setDigitsAfterDecimal(digitsAfterDecimal);
|
this.digitsAfterDecimal = digitsAfterDecimal;
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getRepaymentEvery() {
|
|
||||||
return this.commonLoanProperties.getRepaymentEvery();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRepaymentEvery(final Integer repaymentEvery) {
|
|
||||||
this.commonLoanProperties.setRepaymentEvery(repaymentEvery);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getRepaymentFrequency() {
|
|
||||||
return this.commonLoanProperties.getRepaymentFrequency();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRepaymentFrequency(final Integer repaymentFrequency) {
|
|
||||||
this.commonLoanProperties.setRepaymentFrequency(repaymentFrequency);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean isFlexibleRepaymentSchedule() {
|
|
||||||
return this.commonLoanProperties.isFlexibleRepaymentSchedule();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFlexibleRepaymentSchedule(
|
|
||||||
final Boolean flexibleRepaymentSchedule) {
|
|
||||||
this.commonLoanProperties.setFlexibleRepaymentSchedule(flexibleRepaymentSchedule);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean isInterestRebateAllowed() {
|
|
||||||
return this.commonLoanProperties.isInterestRebateAllowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInterestRebateAllowed(final Boolean interestRebateAllowed) {
|
|
||||||
this.commonLoanProperties.setInterestRebateAllowed(interestRebateAllowed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getPrincipal() {
|
public BigDecimal getPrincipal() {
|
||||||
return this.commonLoanProperties.getPrincipal();
|
return principal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPrincipal(final BigDecimal principal) {
|
public void setPrincipal(BigDecimal principal) {
|
||||||
this.commonLoanProperties.setPrincipal(principal);
|
this.principal = principal;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public Boolean getFlexibleRepaymentSchedule() {
|
|
||||||
// return this.commonLoanProperties.getFlexibleRepaymentSchedule();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public Boolean getInterestRebateAllowed() {
|
|
||||||
// return this.commonLoanProperties.getInterestRebateAllowed();
|
|
||||||
// }
|
|
||||||
|
|
||||||
public Integer getInterestRateFrequencyMethod() {
|
|
||||||
return commonLoanProperties.getInterestRateFrequencyMethod();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInterestRateFrequencyMethod(Integer interestRateFrequencyMethod) {
|
|
||||||
this.commonLoanProperties.setInterestRateFrequencyMethod(interestRateFrequencyMethod);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getInterestMethod() {
|
|
||||||
return commonLoanProperties.getInterestMethod();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInterestMethod(Integer interestMethod) {
|
|
||||||
this.commonLoanProperties.setInterestMethod(interestMethod);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getAmortizationMethod() {
|
|
||||||
return commonLoanProperties.getAmortizationMethod();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAmortizationMethod(Integer amortizationMethod) {
|
|
||||||
this.commonLoanProperties.setAmortizationMethod(amortizationMethod);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getNumberOfRepayments() {
|
|
||||||
return commonLoanProperties.getNumberOfRepayments();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNumberOfRepayments(Integer numberOfRepayments) {
|
|
||||||
this.commonLoanProperties.setNumberOfRepayments(numberOfRepayments);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getInterestRatePerPeriod() {
|
|
||||||
return commonLoanProperties.getInterestRatePerPeriod();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInterestRatePerPeriod(BigDecimal interestRatePerPeriod) {
|
|
||||||
this.commonLoanProperties.setInterestRatePerPeriod(interestRatePerPeriod);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getInArrearsToleranceAmount() {
|
public BigDecimal getInArrearsToleranceAmount() {
|
||||||
return this.commonLoanProperties.getInArrearsToleranceAmount();
|
return inArrearsToleranceAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInArrearsToleranceAmount(BigDecimal inArrearsToleranceAmount) {
|
public void setInArrearsToleranceAmount(BigDecimal inArrearsToleranceAmount) {
|
||||||
this.commonLoanProperties.setInArrearsToleranceAmount(inArrearsToleranceAmount);
|
this.inArrearsToleranceAmount = inArrearsToleranceAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getRepaymentEvery() {
|
||||||
|
return repaymentEvery;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepaymentEvery(Integer repaymentEvery) {
|
||||||
|
this.repaymentEvery = repaymentEvery;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getRepaymentFrequency() {
|
||||||
|
return repaymentFrequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepaymentFrequency(Integer repaymentFrequency) {
|
||||||
|
this.repaymentFrequency = repaymentFrequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getNumberOfRepayments() {
|
||||||
|
return numberOfRepayments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNumberOfRepayments(Integer numberOfRepayments) {
|
||||||
|
this.numberOfRepayments = numberOfRepayments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getInterestRatePerPeriod() {
|
||||||
|
return interestRatePerPeriod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInterestRatePerPeriod(BigDecimal interestRatePerPeriod) {
|
||||||
|
this.interestRatePerPeriod = interestRatePerPeriod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getInterestRateFrequencyMethod() {
|
||||||
|
return interestRateFrequencyMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInterestRateFrequencyMethod(Integer interestRateFrequencyMethod) {
|
||||||
|
this.interestRateFrequencyMethod = interestRateFrequencyMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getAmortizationMethod() {
|
||||||
|
return amortizationMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAmortizationMethod(Integer amortizationMethod) {
|
||||||
|
this.amortizationMethod = amortizationMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getInterestMethod() {
|
||||||
|
return interestMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInterestMethod(Integer interestMethod) {
|
||||||
|
this.interestMethod = interestMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getInterestCalculationPeriodMethod() {
|
||||||
|
return interestCalculationPeriodMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInterestCalculationPeriodMethod(
|
||||||
|
Integer interestCalculationPeriodMethod) {
|
||||||
|
this.interestCalculationPeriodMethod = interestCalculationPeriodMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFlexibleRepaymentSchedule() {
|
||||||
|
return flexibleRepaymentSchedule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFlexibleRepaymentSchedule(boolean flexibleRepaymentSchedule) {
|
||||||
|
this.flexibleRepaymentSchedule = flexibleRepaymentSchedule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInterestRebateAllowed() {
|
||||||
|
return interestRebateAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInterestRebateAllowed(boolean interestRebateAllowed) {
|
||||||
|
this.interestRebateAllowed = interestRebateAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalDate getInterestCalculatedFromDate() {
|
public LocalDate getInterestCalculatedFromDate() {
|
||||||
@@ -250,12 +279,73 @@ public class SubmitLoanApplicationCommand {
|
|||||||
public void setInterestCalculatedFromDate(LocalDate interestCalculatedFromDate) {
|
public void setInterestCalculatedFromDate(LocalDate interestCalculatedFromDate) {
|
||||||
this.interestCalculatedFromDate = interestCalculatedFromDate;
|
this.interestCalculatedFromDate = interestCalculatedFromDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getInterestCalculationPeriodMethod() {
|
public String getExpectedDisbursementDateFormatted() {
|
||||||
return this.commonLoanProperties.getInterestCalculationPeriodMethod();
|
return expectedDisbursementDateFormatted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInterestCalculationPeriodMethod(final Integer interestCalculationPeriodMethod) {
|
public void setExpectedDisbursementDateFormatted(
|
||||||
this.commonLoanProperties.setInterestCalculationPeriodMethod(interestCalculationPeriodMethod);
|
String expectedDisbursementDateFormatted) {
|
||||||
|
this.expectedDisbursementDateFormatted = expectedDisbursementDateFormatted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRepaymentsStartingFromDateFormatted() {
|
||||||
|
return repaymentsStartingFromDateFormatted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepaymentsStartingFromDateFormatted(
|
||||||
|
String repaymentsStartingFromDateFormatted) {
|
||||||
|
this.repaymentsStartingFromDateFormatted = repaymentsStartingFromDateFormatted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInterestCalculatedFromDateFormatted() {
|
||||||
|
return interestCalculatedFromDateFormatted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInterestCalculatedFromDateFormatted(
|
||||||
|
String interestCalculatedFromDateFormatted) {
|
||||||
|
this.interestCalculatedFromDateFormatted = interestCalculatedFromDateFormatted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDateFormat() {
|
||||||
|
return dateFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDateFormat(String dateFormat) {
|
||||||
|
this.dateFormat = dateFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSubmittedOnDateFormatted() {
|
||||||
|
return submittedOnDateFormatted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubmittedOnDateFormatted(String submittedOnDateFormatted) {
|
||||||
|
this.submittedOnDateFormatted = submittedOnDateFormatted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrincipalFormatted() {
|
||||||
|
return principalFormatted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrincipalFormatted(String principalFormatted) {
|
||||||
|
this.principalFormatted = principalFormatted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInArrearsToleranceAmountFormatted() {
|
||||||
|
return inArrearsToleranceAmountFormatted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInArrearsToleranceAmountFormatted(
|
||||||
|
String inArrearsToleranceAmountFormatted) {
|
||||||
|
this.inArrearsToleranceAmountFormatted = inArrearsToleranceAmountFormatted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInterestRatePerPeriodFormatted() {
|
||||||
|
return interestRatePerPeriodFormatted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInterestRatePerPeriodFormatted(
|
||||||
|
String interestRatePerPeriodFormatted) {
|
||||||
|
this.interestRatePerPeriodFormatted = interestRatePerPeriodFormatted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,10 @@
|
|||||||
package org.mifosng.ui;
|
package org.mifosng.ui;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import org.mifosng.data.EntityIdentifier;
|
import org.mifosng.data.EntityIdentifier;
|
||||||
import org.mifosng.data.LoanProductData;
|
|
||||||
import org.mifosng.data.LoanRepaymentData;
|
import org.mifosng.data.LoanRepaymentData;
|
||||||
import org.mifosng.data.LoanSchedule;
|
|
||||||
import org.mifosng.data.command.AdjustLoanTransactionCommand;
|
import org.mifosng.data.command.AdjustLoanTransactionCommand;
|
||||||
import org.mifosng.data.command.CalculateLoanScheduleCommand;
|
|
||||||
import org.mifosng.data.command.LoanStateTransitionCommand;
|
import org.mifosng.data.command.LoanStateTransitionCommand;
|
||||||
import org.mifosng.data.command.LoanTransactionCommand;
|
import org.mifosng.data.command.LoanTransactionCommand;
|
||||||
import org.mifosng.data.command.SubmitLoanApplicationCommand;
|
|
||||||
import org.mifosng.data.command.UndoLoanApprovalCommand;
|
import org.mifosng.data.command.UndoLoanApprovalCommand;
|
||||||
import org.mifosng.data.command.UndoLoanDisbursalCommand;
|
import org.mifosng.data.command.UndoLoanDisbursalCommand;
|
||||||
import org.springframework.security.oauth.consumer.ProtectedResourceDetails;
|
import org.springframework.security.oauth.consumer.ProtectedResourceDetails;
|
||||||
@@ -21,12 +15,6 @@ public interface CommonRestOperations {
|
|||||||
|
|
||||||
void updateProtectedResource(ProtectedResourceDetails loadProtectedResourceDetailsById);
|
void updateProtectedResource(ProtectedResourceDetails loadProtectedResourceDetailsById);
|
||||||
|
|
||||||
Collection<LoanProductData> retrieveAllLoanProducts();
|
|
||||||
|
|
||||||
LoanSchedule calculateLoanSchedule(CalculateLoanScheduleCommand command);
|
|
||||||
|
|
||||||
Long submitLoanApplication(SubmitLoanApplicationCommand command);
|
|
||||||
|
|
||||||
EntityIdentifier deleteLoan(Long loanId);
|
EntityIdentifier deleteLoan(Long loanId);
|
||||||
|
|
||||||
EntityIdentifier approveLoan(LoanStateTransitionCommand command);
|
EntityIdentifier approveLoan(LoanStateTransitionCommand command);
|
||||||
|
|||||||
-75
@@ -2,7 +2,6 @@ package org.mifosng.ui;
|
|||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.mifosng.configuration.ApplicationConfigurationService;
|
import org.mifosng.configuration.ApplicationConfigurationService;
|
||||||
@@ -10,15 +9,10 @@ import org.mifosng.data.ClientList;
|
|||||||
import org.mifosng.data.EntityIdentifier;
|
import org.mifosng.data.EntityIdentifier;
|
||||||
import org.mifosng.data.ErrorResponse;
|
import org.mifosng.data.ErrorResponse;
|
||||||
import org.mifosng.data.ErrorResponseList;
|
import org.mifosng.data.ErrorResponseList;
|
||||||
import org.mifosng.data.LoanProductData;
|
|
||||||
import org.mifosng.data.LoanProductList;
|
|
||||||
import org.mifosng.data.LoanRepaymentData;
|
import org.mifosng.data.LoanRepaymentData;
|
||||||
import org.mifosng.data.LoanSchedule;
|
|
||||||
import org.mifosng.data.command.AdjustLoanTransactionCommand;
|
import org.mifosng.data.command.AdjustLoanTransactionCommand;
|
||||||
import org.mifosng.data.command.CalculateLoanScheduleCommand;
|
|
||||||
import org.mifosng.data.command.LoanStateTransitionCommand;
|
import org.mifosng.data.command.LoanStateTransitionCommand;
|
||||||
import org.mifosng.data.command.LoanTransactionCommand;
|
import org.mifosng.data.command.LoanTransactionCommand;
|
||||||
import org.mifosng.data.command.SubmitLoanApplicationCommand;
|
|
||||||
import org.mifosng.data.command.UndoLoanApprovalCommand;
|
import org.mifosng.data.command.UndoLoanApprovalCommand;
|
||||||
import org.mifosng.data.command.UndoLoanDisbursalCommand;
|
import org.mifosng.data.command.UndoLoanDisbursalCommand;
|
||||||
import org.mifosng.ui.loanproduct.ClientValidationException;
|
import org.mifosng.ui.loanproduct.ClientValidationException;
|
||||||
@@ -81,18 +75,6 @@ public class CommonRestOperationsImpl implements CommonRestOperations {
|
|||||||
return requestEntity;
|
return requestEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<LoanProductData> retrieveAllLoanProducts() {
|
|
||||||
URI restUri = URI.create(getBaseServerUrl().concat(
|
|
||||||
"api/protected/product/loan/all"));
|
|
||||||
|
|
||||||
ResponseEntity<LoanProductList> s = this.oauthRestServiceTemplate
|
|
||||||
.exchange(restUri, HttpMethod.GET, emptyRequest(),
|
|
||||||
LoanProductList.class);
|
|
||||||
|
|
||||||
return s.getBody().getProducts();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ErrorResponseList parseErrors(HttpStatusCodeException e) {
|
private ErrorResponseList parseErrors(HttpStatusCodeException e) {
|
||||||
|
|
||||||
XStream xstream = new XStream();
|
XStream xstream = new XStream();
|
||||||
@@ -118,43 +100,6 @@ public class CommonRestOperationsImpl implements CommonRestOperations {
|
|||||||
return errorList;
|
return errorList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public LoanSchedule calculateLoanSchedule(
|
|
||||||
final CalculateLoanScheduleCommand command) {
|
|
||||||
try {
|
|
||||||
URI restUri = URI.create(getBaseServerUrl().concat(
|
|
||||||
"api/protected/loan/calculate"));
|
|
||||||
|
|
||||||
ResponseEntity<LoanSchedule> s = this.oauthRestServiceTemplate
|
|
||||||
.exchange(restUri, HttpMethod.POST,
|
|
||||||
calculateLoanRepaymentScheduleRequest(command),
|
|
||||||
LoanSchedule.class);
|
|
||||||
|
|
||||||
return s.getBody();
|
|
||||||
} catch (HttpStatusCodeException e) {
|
|
||||||
ErrorResponseList errorList = parseErrors(e);
|
|
||||||
throw new ClientValidationException(errorList.getErrors());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Long submitLoanApplication(final SubmitLoanApplicationCommand command) {
|
|
||||||
try {
|
|
||||||
URI restUri = URI.create(getBaseServerUrl().concat(
|
|
||||||
"api/protected/loan/new"));
|
|
||||||
|
|
||||||
ResponseEntity<EntityIdentifier> s = this.oauthRestServiceTemplate
|
|
||||||
.postForEntity(restUri,
|
|
||||||
submitLoanApplicationRequest(command),
|
|
||||||
EntityIdentifier.class);
|
|
||||||
|
|
||||||
return s.getBody().getEntityId();
|
|
||||||
} catch (HttpStatusCodeException e) {
|
|
||||||
ErrorResponseList errorList = parseErrors(e);
|
|
||||||
throw new ClientValidationException(errorList.getErrors());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityIdentifier deleteLoan(Long loanId) {
|
public EntityIdentifier deleteLoan(Long loanId) {
|
||||||
try {
|
try {
|
||||||
@@ -437,24 +382,4 @@ public class CommonRestOperationsImpl implements CommonRestOperations {
|
|||||||
return new HttpEntity<LoanStateTransitionCommand>(command,
|
return new HttpEntity<LoanStateTransitionCommand>(command,
|
||||||
requestHeaders);
|
requestHeaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpEntity<SubmitLoanApplicationCommand> submitLoanApplicationRequest(
|
|
||||||
final SubmitLoanApplicationCommand command) {
|
|
||||||
HttpHeaders requestHeaders = new HttpHeaders();
|
|
||||||
requestHeaders.set("Accept", "application/xml");
|
|
||||||
requestHeaders.set("Content-Type", "application/xml");
|
|
||||||
|
|
||||||
return new HttpEntity<SubmitLoanApplicationCommand>(command,
|
|
||||||
requestHeaders);
|
|
||||||
}
|
|
||||||
|
|
||||||
private HttpEntity<CalculateLoanScheduleCommand> calculateLoanRepaymentScheduleRequest(
|
|
||||||
final CalculateLoanScheduleCommand command) {
|
|
||||||
HttpHeaders requestHeaders = new HttpHeaders();
|
|
||||||
requestHeaders.set("Accept", "application/xml");
|
|
||||||
requestHeaders.set("Content-Type", "application/xml");
|
|
||||||
|
|
||||||
return new HttpEntity<CalculateLoanScheduleCommand>(command,
|
|
||||||
requestHeaders);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+4
@@ -13,6 +13,10 @@ import org.springframework.web.bind.annotation.PathVariable;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated - some initial work around cashflow for CreoCore that can be deleted later.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
@Controller
|
@Controller
|
||||||
public class CashflowController {
|
public class CashflowController {
|
||||||
|
|
||||||
|
|||||||
@@ -1,179 +0,0 @@
|
|||||||
package org.mifosng.ui.loan;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.text.NumberFormat;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.joda.time.LocalDate;
|
|
||||||
import org.joda.time.format.DateTimeFormat;
|
|
||||||
import org.mifosng.data.EntityIdentifier;
|
|
||||||
import org.mifosng.data.ErrorResponse;
|
|
||||||
import org.mifosng.data.LoanSchedule;
|
|
||||||
import org.mifosng.data.command.CalculateLoanScheduleCommand;
|
|
||||||
import org.mifosng.data.command.SubmitLoanApplicationCommand;
|
|
||||||
import org.mifosng.ui.CommonRestOperations;
|
|
||||||
import org.mifosng.ui.loanproduct.ClientValidationException;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
|
||||||
import org.springframework.security.access.AccessDeniedException;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
public class LoanController {
|
|
||||||
|
|
||||||
private final CommonRestOperations commonRestOperations;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public LoanController(final CommonRestOperations commonRestOperations) {
|
|
||||||
this.commonRestOperations = commonRestOperations;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(AccessDeniedException.class)
|
|
||||||
public String accessDeniedException() {
|
|
||||||
return "unAuthorizedAction";
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(ClientValidationException.class)
|
|
||||||
public @ResponseBody Collection<ErrorResponse> validationException(ClientValidationException ex, HttpServletResponse response) {
|
|
||||||
|
|
||||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
|
||||||
response.setContentType("application/json");
|
|
||||||
|
|
||||||
return ex.getValidationErrors();
|
|
||||||
}
|
|
||||||
|
|
||||||
private LocalDate parseStringToLocalDate(String eventDate, String dateFieldIdentifier) {
|
|
||||||
LocalDate eventLocalDate = null;
|
|
||||||
if (StringUtils.isNotBlank(eventDate)) {
|
|
||||||
try {
|
|
||||||
Locale locale = LocaleContextHolder.getLocale();
|
|
||||||
eventLocalDate = DateTimeFormat.forPattern("dd MMMM yyyy").withLocale(locale).parseLocalDate(eventDate.toLowerCase(locale));
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
List<ErrorResponse> validationErrors = new ArrayList<ErrorResponse>();
|
|
||||||
validationErrors.add(new ErrorResponse("validation.msg.invalid.date.format", dateFieldIdentifier, eventDate));
|
|
||||||
throw new ClientValidationException(validationErrors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return eventLocalDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
private BigDecimal parseStringToBigDecimal(String source) {
|
|
||||||
try {
|
|
||||||
BigDecimal number = null;
|
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(source)) {
|
|
||||||
String sourceWithoutSpaces = source.replaceAll(" ", "");
|
|
||||||
Locale locale = LocaleContextHolder.getLocale();
|
|
||||||
NumberFormat format = NumberFormat.getNumberInstance(locale);
|
|
||||||
Number parsedNumber = format.parse(sourceWithoutSpaces);
|
|
||||||
number = BigDecimal.valueOf(Double.valueOf(parsedNumber
|
|
||||||
.doubleValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return number;
|
|
||||||
} catch (ParseException e) {
|
|
||||||
List<ErrorResponse> validationErrors = new ArrayList<ErrorResponse>();
|
|
||||||
validationErrors.add(new ErrorResponse("validation.msg.invalid.number.format", "amount", source));
|
|
||||||
throw new ClientValidationException(validationErrors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping(consumes="application/x-www-form-urlencoded", produces="application/json", value = "/portfolio/client/{clientId}/loan/new", method = RequestMethod.POST)
|
|
||||||
public @ResponseBody EntityIdentifier submitNewLoanApplication(
|
|
||||||
@RequestParam(value="clientId", required=false) Long applicantId,
|
|
||||||
@RequestParam(value="productId", required=false) Long productId,
|
|
||||||
@RequestParam(value="submittedOnDate", required=false) String submittedOnDateStr,
|
|
||||||
@RequestParam(value="submittedOnNote", required=false) String submittedOnNote,
|
|
||||||
@RequestParam(value="currencyCode", required=false) String currencyCode,
|
|
||||||
@RequestParam(value="digitsAfterDecimal", required=false) Integer digitsAfterDecimal,
|
|
||||||
@RequestParam(value="principalMoney", required=false) String principalMoney,
|
|
||||||
@RequestParam(value="repaidEvery", required=false) Integer repaymentEvery,
|
|
||||||
@RequestParam(value="selectedRepaymentFrequencyOption", required=false) Integer repaymentFrequency,
|
|
||||||
@RequestParam(value="numberOfRepayments", required=false) Integer numberOfRepayments,
|
|
||||||
@RequestParam(value="selectedAmortizationMethodOption", required=false) Integer amortizationMethod,
|
|
||||||
@RequestParam(value="inArrearsTolerance", required=false) String inArrearsTolerance,
|
|
||||||
@RequestParam(value="nominalInterestRate", required=false) String nominalInterestRate,
|
|
||||||
@RequestParam(value="selectedInterestFrequencyOption", required=false) Integer interestRateFrequencyMethod,
|
|
||||||
@RequestParam(value="selectedInterestMethodOption", required=false) Integer interestMethod,
|
|
||||||
@RequestParam(value="interestRateCalculatedInPeriod", required=false) Integer interestRateCalculatedInPeriod,
|
|
||||||
@RequestParam(value="expectedDisbursementDate", required=false) String expectedDisbursementDateStr,
|
|
||||||
@RequestParam(value="repaymentsStartingFromDate", required=false) String repaymentsStartingFromDateStr,
|
|
||||||
@RequestParam(value="interestCalculatedFromDate", required=false) String interestCalculatedFromDateStr
|
|
||||||
) {
|
|
||||||
|
|
||||||
final LocalDate submittedOnDate = parseStringToLocalDate(submittedOnDateStr, "submittedOnDate");
|
|
||||||
final Number toleranceAmount = parseStringToBigDecimal(inArrearsTolerance);
|
|
||||||
|
|
||||||
final Number principal = parseStringToBigDecimal(principalMoney);
|
|
||||||
final Number interestRatePerPeriod = parseStringToBigDecimal(nominalInterestRate);
|
|
||||||
final boolean flexibleRepaymentSchedule = false;
|
|
||||||
final boolean interestRebateAllowed = false;
|
|
||||||
|
|
||||||
final LocalDate expectedDisbursementDate = parseStringToLocalDate(expectedDisbursementDateStr, "expectedDisbursementDate");
|
|
||||||
final LocalDate repaymentsStartingFromDate = parseStringToLocalDate(repaymentsStartingFromDateStr, "repaymentsStartingFromDate");
|
|
||||||
final LocalDate interestCalculatedFromDate = parseStringToLocalDate(interestCalculatedFromDateStr, "interestCalculatedFromDate");
|
|
||||||
|
|
||||||
CalculateLoanScheduleCommand calculateLoanScheduleCommand = new CalculateLoanScheduleCommand(currencyCode, digitsAfterDecimal, principal, interestRatePerPeriod,
|
|
||||||
interestRateFrequencyMethod, interestMethod, interestRateCalculatedInPeriod, repaymentEvery, repaymentFrequency, numberOfRepayments, amortizationMethod,
|
|
||||||
flexibleRepaymentSchedule, interestRebateAllowed, expectedDisbursementDate, repaymentsStartingFromDate, interestCalculatedFromDate);
|
|
||||||
|
|
||||||
LoanSchedule loanSchedule = this.commonRestOperations.calculateLoanSchedule(calculateLoanScheduleCommand);
|
|
||||||
|
|
||||||
SubmitLoanApplicationCommand command = new SubmitLoanApplicationCommand(applicantId, productId,
|
|
||||||
submittedOnDate, submittedOnNote, expectedDisbursementDate, repaymentsStartingFromDate, interestCalculatedFromDate,
|
|
||||||
loanSchedule, currencyCode, digitsAfterDecimal, principal,
|
|
||||||
interestRatePerPeriod, interestRateFrequencyMethod, interestMethod, interestRateCalculatedInPeriod,
|
|
||||||
repaymentEvery, repaymentFrequency, numberOfRepayments, amortizationMethod,
|
|
||||||
toleranceAmount, flexibleRepaymentSchedule, interestRebateAllowed);
|
|
||||||
|
|
||||||
Long identifier = this.commonRestOperations.submitLoanApplication(command);
|
|
||||||
|
|
||||||
return new EntityIdentifier(identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping(consumes="application/x-www-form-urlencoded", produces="application/json", value = "/portfolio/loanschedule/calculate", method = RequestMethod.POST)
|
|
||||||
public @ResponseBody LoanSchedule calculateLoanSchedule(
|
|
||||||
@RequestParam(value="currencyCode", required=false) String currencyCode,
|
|
||||||
@RequestParam(value="digitsAfterDecimal", required=false) Integer digitsAfterDecimal,
|
|
||||||
@RequestParam(value="principalMoney", required=false) String principalMoney,
|
|
||||||
@RequestParam(value="repaidEvery", required=false) Integer repaymentEvery,
|
|
||||||
@RequestParam(value="selectedRepaymentFrequencyOption", required=false) Integer repaymentFrequency,
|
|
||||||
@RequestParam(value="numberOfRepayments", required=false) Integer numberOfRepayments,
|
|
||||||
@RequestParam(value="selectedAmortizationMethodOption", required=false) Integer amortizationMethod,
|
|
||||||
@RequestParam(value="nominalInterestRate", required=false) String nominalInterestRate,
|
|
||||||
@RequestParam(value="selectedInterestFrequencyOption", required=false) Integer interestRateFrequencyMethod,
|
|
||||||
@RequestParam(value="selectedInterestMethodOption", required=false) Integer interestMethod,
|
|
||||||
@RequestParam(value="interestRateCalculatedInPeriod", required=false) Integer interestRateCalculatedInPeriod,
|
|
||||||
@RequestParam(value="expectedDisbursementDate", required=false) String expectedDisbursementDateStr,
|
|
||||||
@RequestParam(value="repaymentsStartingFromDate", required=false) String repaymentsStartingFromDateStr,
|
|
||||||
@RequestParam(value="interestCalculatedFromDate", required=false) String interestCalculatedFromDateStr
|
|
||||||
) {
|
|
||||||
|
|
||||||
final Number principal = parseStringToBigDecimal(principalMoney);
|
|
||||||
final Number interestRatePerPeriod = parseStringToBigDecimal(nominalInterestRate);
|
|
||||||
final boolean flexibleRepaymentSchedule = false;
|
|
||||||
final boolean interestRebateAllowed = false;
|
|
||||||
final LocalDate expectedDisbursementDate = parseStringToLocalDate(expectedDisbursementDateStr, "expectedDisbursementDate");
|
|
||||||
final LocalDate repaymentsStartingFromDate = parseStringToLocalDate(repaymentsStartingFromDateStr, "repaymentsStartingFromDate");
|
|
||||||
final LocalDate interestCalculatedFromDate = parseStringToLocalDate(interestCalculatedFromDateStr, "interestCalculatedFromDate");
|
|
||||||
|
|
||||||
CalculateLoanScheduleCommand command = new CalculateLoanScheduleCommand(currencyCode, digitsAfterDecimal, principal, interestRatePerPeriod,
|
|
||||||
interestRateFrequencyMethod, interestMethod, interestRateCalculatedInPeriod, repaymentEvery, repaymentFrequency, numberOfRepayments, amortizationMethod,
|
|
||||||
flexibleRepaymentSchedule, interestRebateAllowed, expectedDisbursementDate, repaymentsStartingFromDate, interestCalculatedFromDate);
|
|
||||||
|
|
||||||
return this.commonRestOperations.calculateLoanSchedule(command);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+91
-88
@@ -206,7 +206,7 @@ $(document).ready(function() {
|
|||||||
return o;
|
return o;
|
||||||
};
|
};
|
||||||
|
|
||||||
function popupConfirmationDialogAndPost(url, titleCode, width, height, tabIndex, redirectUrl) {
|
function popupConfirmationDialogAndPost(url, submitType, titleCode, width, height, tabIndex, redirectUrl) {
|
||||||
var dialogDiv = $("<div id='dialog-form'><div id='formerrors'></div>" + jQuery.i18n.prop('text.confirmation.required') + "</div>");
|
var dialogDiv = $("<div id='dialog-form'><div id='formerrors'></div>" + jQuery.i18n.prop('text.confirmation.required') + "</div>");
|
||||||
|
|
||||||
var confirmButton = jQuery.i18n.prop('dialog.button.confirm');
|
var confirmButton = jQuery.i18n.prop('dialog.button.confirm');
|
||||||
@@ -216,7 +216,9 @@ $(document).ready(function() {
|
|||||||
buttonsOpts[confirmButton] = function() {
|
buttonsOpts[confirmButton] = function() {
|
||||||
var jqxhr = $.ajax({
|
var jqxhr = $.ajax({
|
||||||
url: url,
|
url: url,
|
||||||
type: 'POST',
|
type: submitType,
|
||||||
|
contentType: 'application/json',
|
||||||
|
dataType: 'json',
|
||||||
success: function(data, textStatus, jqXHR) {
|
success: function(data, textStatus, jqXHR) {
|
||||||
dialogDiv.dialog("close");
|
dialogDiv.dialog("close");
|
||||||
if (tabIndex > 0) {
|
if (tabIndex > 0) {
|
||||||
@@ -322,70 +324,70 @@ $(document).ready(function() {
|
|||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
cache: false,
|
cache: false,
|
||||||
success: function(data, textStatus, jqXHR) {
|
success: function(data, textStatus, jqXHR) {
|
||||||
console.log(data);
|
console.log(data);
|
||||||
var formHtml = $(templateSelector).render(data);
|
var formHtml = $(templateSelector).render(data);
|
||||||
|
|
||||||
dialogDiv.append(formHtml);
|
|
||||||
|
|
||||||
var saveButton = jQuery.i18n.prop('dialog.button.save');
|
|
||||||
var cancelButton = jQuery.i18n.prop('dialog.button.cancel');
|
|
||||||
|
|
||||||
var buttonsOpts = {};
|
|
||||||
buttonsOpts[saveButton] = function() {
|
|
||||||
|
|
||||||
$('#notSelectedItems option').each(function(i) {
|
dialogDiv.append(formHtml);
|
||||||
|
|
||||||
|
var saveButton = jQuery.i18n.prop('dialog.button.save');
|
||||||
|
var cancelButton = jQuery.i18n.prop('dialog.button.cancel');
|
||||||
|
|
||||||
|
var buttonsOpts = {};
|
||||||
|
buttonsOpts[saveButton] = function() {
|
||||||
|
|
||||||
|
$('#notSelectedItems option').each(function(i) {
|
||||||
|
$(this).attr("selected", "selected");
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#selectedItems option').each(function(i) {
|
||||||
$(this).attr("selected", "selected");
|
$(this).attr("selected", "selected");
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#selectedItems option').each(function(i) {
|
var newFormData = JSON.stringify($('#entityform').serializeObject());
|
||||||
$(this).attr("selected", "selected");
|
console.log(newFormData);
|
||||||
});
|
|
||||||
|
var jqxhr = $.ajax({
|
||||||
var newFormData = JSON.stringify($('#entityform').serializeObject());
|
url: postUrl,
|
||||||
console.log(newFormData);
|
type: submitType,
|
||||||
|
contentType: 'application/json',
|
||||||
var jqxhr = $.ajax({
|
dataType: 'json',
|
||||||
url: postUrl,
|
data: newFormData,
|
||||||
type: submitType,
|
success: saveSuccessFunction,
|
||||||
contentType: 'application/json',
|
error: function(jqXHR, textStatus, errorThrown) {
|
||||||
dataType: 'json',
|
handleXhrError(jqXHR, textStatus, errorThrown, "#formErrorsTemplate", "#formerrors");
|
||||||
data: newFormData,
|
}
|
||||||
success: saveSuccessFunction,
|
});
|
||||||
error: function(jqXHR, textStatus, errorThrown) {
|
};
|
||||||
handleXhrError(jqXHR, textStatus, errorThrown, "#formErrorsTemplate", "#formerrors");
|
|
||||||
}
|
buttonsOpts[cancelButton] = function() {$(this).dialog( "close" );};
|
||||||
});
|
|
||||||
};
|
dialogDiv.dialog({
|
||||||
|
title: jQuery.i18n.prop(titleCode),
|
||||||
buttonsOpts[cancelButton] = function() {$(this).dialog( "close" );};
|
width: width,
|
||||||
|
height: height,
|
||||||
dialogDiv.dialog({
|
modal: true,
|
||||||
title: jQuery.i18n.prop(titleCode),
|
buttons: buttonsOpts,
|
||||||
width: width,
|
close: function() {
|
||||||
height: height,
|
// if i dont do this, theres a problem with errors being appended to dialog view second time round
|
||||||
modal: true,
|
$(this).remove();
|
||||||
buttons: buttonsOpts,
|
},
|
||||||
close: function() {
|
open: function (event, ui) {
|
||||||
// if i dont do this, theres a problem with errors being appended to dialog view second time round
|
|
||||||
$(this).remove();
|
$('#add').click(function() {
|
||||||
},
|
return !$('#notSelectedItems option:selected').remove().appendTo('#selectedItems');
|
||||||
open: function (event, ui) {
|
});
|
||||||
|
|
||||||
$('#add').click(function() {
|
$('#remove').click(function() {
|
||||||
return !$('#notSelectedItems option:selected').remove().appendTo('#selectedItems');
|
return !$('#selectedItems option:selected').remove().appendTo('#notSelectedItems');
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#remove').click(function() {
|
$('.datepickerfield').datepicker({constrainInput: true, maxDate: 0, dateFormat: 'dd MM yy'});
|
||||||
return !$('#selectedItems option:selected').remove().appendTo('#notSelectedItems');
|
|
||||||
});
|
$("#entityform textarea").first().focus();
|
||||||
|
$('#entityform input').first().focus();
|
||||||
$('.datepickerfield').datepicker({constrainInput: true, maxDate: 0, dateFormat: 'dd MM yy'});
|
}
|
||||||
|
}).dialog('open');
|
||||||
$("#entityform textarea").first().focus();
|
}
|
||||||
$('#entityform input').first().focus();
|
|
||||||
}
|
|
||||||
}).dialog('open');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
jqxhr.error(function(jqXHR, textStatus, errorThrown) {
|
jqxhr.error(function(jqXHR, textStatus, errorThrown) {
|
||||||
@@ -435,19 +437,6 @@ $(document).ready(function() {
|
|||||||
// retrieve accounts summary info
|
// retrieve accounts summary info
|
||||||
refreshLoanSummaryInfo();
|
refreshLoanSummaryInfo();
|
||||||
|
|
||||||
// retrieve additional info
|
|
||||||
var additionalFieldsParams = {
|
|
||||||
url: "http://localhost:8080/mifosng-provider/",
|
|
||||||
datasetType: "portfolio_client",
|
|
||||||
datasetPKValue: data.id,
|
|
||||||
datasetTypeDiv: "clientadditionaldata",
|
|
||||||
headingPrefix: "",
|
|
||||||
headingClass: "",
|
|
||||||
labelClass: "longrowlabel",
|
|
||||||
valueClass: "rowvalue"
|
|
||||||
};
|
|
||||||
jQuery.stretchyData.displayAllExtraData(additionalFieldsParams);
|
|
||||||
|
|
||||||
// bind click listeners to buttons.
|
// bind click listeners to buttons.
|
||||||
$('.casflowbtn').button().click(function(e) {
|
$('.casflowbtn').button().click(function(e) {
|
||||||
var linkId = this.id;
|
var linkId = this.id;
|
||||||
@@ -489,24 +478,25 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
refreshNoteWidget();
|
refreshNoteWidget();
|
||||||
|
|
||||||
} else {
|
// retrieve additional info
|
||||||
|
|
||||||
var tableHtml = $("#loanDataTabTemplate").render(data);
|
|
||||||
|
|
||||||
var currentTab = $("#newtabs").children(".ui-tabs-panel").not(".ui-tabs-hide");
|
|
||||||
currentTab.html(tableHtml);
|
|
||||||
|
|
||||||
var additionalFieldsParams = {
|
var additionalFieldsParams = {
|
||||||
url: "http://localhost:8080/mifosng-provider/",
|
url: "http://localhost:8080/mifosng-provider/",
|
||||||
datasetType: "portfolio_loan",
|
datasetType: "portfolio_client",
|
||||||
datasetPKValue: data.id,
|
datasetPKValue: data.id,
|
||||||
datasetTypeDiv: "loanadditionaldata" + data.id,
|
datasetTypeDiv: "clientadditionaldata",
|
||||||
headingPrefix: "",
|
headingPrefix: "",
|
||||||
headingClass: "",
|
headingClass: "",
|
||||||
labelClass: "longrowlabel",
|
labelClass: "longrowlabel",
|
||||||
valueClass: "rowvalue"
|
valueClass: "rowvalue"
|
||||||
};
|
};
|
||||||
jQuery.stretchyData.displayAllExtraData(additionalFieldsParams);
|
jQuery.stretchyData.displayAllExtraData(additionalFieldsParams);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
var tableHtml = $("#loanDataTabTemplate").render(data);
|
||||||
|
|
||||||
|
var currentTab = $("#newtabs").children(".ui-tabs-panel").not(".ui-tabs-hide");
|
||||||
|
currentTab.html(tableHtml);
|
||||||
|
|
||||||
var curTabID = currentTab.prop("id")
|
var curTabID = currentTab.prop("id")
|
||||||
|
|
||||||
@@ -560,13 +550,13 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
var linkId = this.id;
|
var linkId = this.id;
|
||||||
var loanId = linkId.replace("deletebtn", "");
|
var loanId = linkId.replace("deletebtn", "");
|
||||||
var url = '${rootContext}portfolio/loan/' + loanId + '/delete';
|
var url = 'http://localhost:8080/mifosng-provider/api/v1/loans/' + loanId;
|
||||||
var width = 400;
|
var width = 400;
|
||||||
var height = 225;
|
var height = 225;
|
||||||
|
|
||||||
var redirectUrl = '${clientUrl}';
|
var redirectUrl = '${clientUrl}';
|
||||||
|
|
||||||
popupConfirmationDialogAndPost(url, 'dialog.title.confirmation.required', width, height, 0, redirectUrl);
|
popupConfirmationDialogAndPost(url, 'DELETE', 'dialog.title.confirmation.required', width, height, 0, redirectUrl);
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
});
|
});
|
||||||
$('button.deleteloan span').text(jQuery.i18n.prop('dialog.button.delete.loan'));
|
$('button.deleteloan span').text(jQuery.i18n.prop('dialog.button.delete.loan'));
|
||||||
@@ -660,6 +650,19 @@ $(document).ready(function() {
|
|||||||
var curTabID = curTab.prop("id")
|
var curTabID = curTab.prop("id")
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// additional data
|
||||||
|
var additionalFieldsParams = {
|
||||||
|
url: "http://localhost:8080/mifosng-provider/",
|
||||||
|
datasetType: "portfolio_loan",
|
||||||
|
datasetPKValue: data.id,
|
||||||
|
datasetTypeDiv: "loanadditionaldata" + data.id,
|
||||||
|
headingPrefix: "",
|
||||||
|
headingClass: "",
|
||||||
|
labelClass: "longrowlabel",
|
||||||
|
valueClass: "rowvalue"
|
||||||
|
};
|
||||||
|
jQuery.stretchyData.displayAllExtraData(additionalFieldsParams);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-26
@@ -173,13 +173,13 @@ $.views.registerHelpers({
|
|||||||
};
|
};
|
||||||
|
|
||||||
function calculateAnnualPercentageRate() {
|
function calculateAnnualPercentageRate() {
|
||||||
var periodInterestRate = parseFloat($('#nominalInterestRate').val());
|
var periodInterestRate = parseFloat($('#interestRatePerPeriodFormatted').val());
|
||||||
if (isNaN(periodInterestRate)) {
|
if (isNaN(periodInterestRate)) {
|
||||||
periodInterestRate = 0;
|
periodInterestRate = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var periodsInYear = 12;
|
var periodsInYear = 12;
|
||||||
var periodType = $('#selectedInterestFrequencyOption').val();
|
var periodType = $('#interestRateFrequencyMethod').val();
|
||||||
if (periodType == 3) {
|
if (periodType == 3) {
|
||||||
periodsInYear = 1;
|
periodsInYear = 1;
|
||||||
} else if (periodType == 2) {
|
} else if (periodType == 2) {
|
||||||
@@ -220,15 +220,15 @@ $.views.registerHelpers({
|
|||||||
calculateLoanSchedule();
|
calculateLoanSchedule();
|
||||||
|
|
||||||
// change detection
|
// change detection
|
||||||
$('#principalMoney').change(function() {
|
$('#principalFormatted').change(function() {
|
||||||
calculateLoanSchedule();
|
calculateLoanSchedule();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#repaidEvery').change(function() {
|
$('#repaymentEvery').change(function() {
|
||||||
calculateLoanSchedule();
|
calculateLoanSchedule();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#selectedRepaymentFrequencyOption').change(function() {
|
$('#repaymentFrequency').change(function() {
|
||||||
calculateLoanSchedule();
|
calculateLoanSchedule();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -236,37 +236,37 @@ $.views.registerHelpers({
|
|||||||
calculateLoanSchedule();
|
calculateLoanSchedule();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#expectedDisbursementDate').change(function() {
|
$('#expectedDisbursementDateFormatted').change(function() {
|
||||||
calculateLoanSchedule();
|
calculateLoanSchedule();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#repaymentsStartingFromDate').change(function() {
|
$('#repaymentsStartingFromDateFormatted').change(function() {
|
||||||
calculateLoanSchedule();
|
calculateLoanSchedule();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#nominalInterestRate').change(function() {
|
$('#interestRatePerPeriodFormatted').change(function() {
|
||||||
calculateAnnualPercentageRate();
|
calculateAnnualPercentageRate();
|
||||||
calculateLoanSchedule();
|
calculateLoanSchedule();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#selectedInterestFrequencyOption').change(function() {
|
$('#interestRateFrequencyMethod').change(function() {
|
||||||
calculateAnnualPercentageRate();
|
calculateAnnualPercentageRate();
|
||||||
calculateLoanSchedule();
|
calculateLoanSchedule();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#selectedAmortizationMethodOption').change(function() {
|
$('#amortizationMethod').change(function() {
|
||||||
calculateLoanSchedule();
|
calculateLoanSchedule();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#selectedInterestMethodOption').change(function() {
|
$('#interestMethod').change(function() {
|
||||||
calculateLoanSchedule();
|
calculateLoanSchedule();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#interestRateCalculatedInPeriod').change(function() {
|
$('#interestCalculationPeriodMethod').change(function() {
|
||||||
calculateLoanSchedule();
|
calculateLoanSchedule();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#interestCalculatedFromDate').change(function() {
|
$('#interestCalculatedFromDateFormatted').change(function() {
|
||||||
calculateLoanSchedule();
|
calculateLoanSchedule();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -291,14 +291,17 @@ $.views.registerHelpers({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function calculateLoanSchedule() {
|
function calculateLoanSchedule() {
|
||||||
var calculateLoanScheduleurl = '${rootContext}portfolio/loanschedule/calculate';
|
var calculateLoanScheduleurl = 'http://localhost:8080/mifosng-provider/api/v1/loans?command=calculateLoanSchedule';
|
||||||
|
|
||||||
var form_data = $('#entityform').serialize();
|
var newFormData = JSON.stringify($('#entityform').serializeObject());
|
||||||
|
console.log(newFormData);
|
||||||
|
|
||||||
var jqxhr2 = $.ajax({
|
var jqxhr2 = $.ajax({
|
||||||
url: calculateLoanScheduleurl,
|
url: calculateLoanScheduleurl,
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
data: form_data,
|
contentType: 'application/json',
|
||||||
|
dataType: 'json',
|
||||||
|
data: newFormData,
|
||||||
success: function(data, textStatus, jqXHR) {
|
success: function(data, textStatus, jqXHR) {
|
||||||
removeErrors("#formerrors");
|
removeErrors("#formerrors");
|
||||||
var loanScheduleHtml = $("#newLoanScheduleTemplate").render(data);
|
var loanScheduleHtml = $("#newLoanScheduleTemplate").render(data);
|
||||||
@@ -313,17 +316,20 @@ $.views.registerHelpers({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function submitLoanApplication() {
|
function submitLoanApplication() {
|
||||||
var submitLoanApplicationUrl = '${rootContext}portfolio/client/${clientId}/loan/new';
|
var submitLoanApplicationUrl = 'http://localhost:8080/mifosng-provider/api/v1/loans';
|
||||||
|
|
||||||
var form_data = $('#entityform').serialize();
|
var newFormData = JSON.stringify($('#entityform').serializeObject());
|
||||||
|
console.log(newFormData);
|
||||||
|
|
||||||
var jqxhr2 = $.ajax({
|
var jqxhr2 = $.ajax({
|
||||||
url: submitLoanApplicationUrl,
|
url: submitLoanApplicationUrl,
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
data: form_data,
|
contentType: 'application/json',
|
||||||
|
dataType: 'json',
|
||||||
|
data: newFormData,
|
||||||
success: function(data, textStatus, jqXHR) {
|
success: function(data, textStatus, jqXHR) {
|
||||||
var url = '${rootContext}portfolio/client/${clientId}';
|
var localAppUrlToSwitchToClientPage = '${rootContext}portfolio/client/${clientId}';
|
||||||
window.location.href = url;
|
window.location.href = localAppUrlToSwitchToClientPage;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -331,9 +337,8 @@ $.views.registerHelpers({
|
|||||||
handleXhrError(jqXHR, textStatus, errorThrown, "#formErrorsTemplate", "#formerrors");
|
handleXhrError(jqXHR, textStatus, errorThrown, "#formErrorsTemplate", "#formerrors");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// on page load
|
||||||
|
|
||||||
var jqxhr = $.ajax({
|
var jqxhr = $.ajax({
|
||||||
url: 'http://localhost:8080/mifosng-provider/api/v1/loans/template?clientId=${clientId}',
|
url: 'http://localhost:8080/mifosng-provider/api/v1/loans/template?clientId=${clientId}',
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
<form id="entityform">
|
<form id="entityform">
|
||||||
<div id="formerrors"></div>
|
<div id="formerrors"></div>
|
||||||
|
|
||||||
<input type="hidden" id="clientId" name="clientId" value="{{=clientId}}" />
|
<input type="hidden" id="applicantId" name="applicantId" value="{{=clientId}}" />
|
||||||
<input type="hidden" id="currencyCode" name="currencyCode" value="{{=selectedProduct.principalMoney.currencyCode}}" />
|
<input type="hidden" id="currencyCode" name="currencyCode" value="{{=selectedProduct.principalMoney.currencyCode}}" />
|
||||||
<input type="hidden" id="digitsAfterDecimal" name="digitsAfterDecimal" value="{{=$ctx.number(selectedProduct.principalMoney.currencyDigitsAfterDecimal)}}" />
|
<input type="hidden" id="digitsAfterDecimal" name="digitsAfterDecimal" value="{{=$ctx.number(selectedProduct.principalMoney.currencyDigitsAfterDecimal)}}" />
|
||||||
|
|
||||||
@@ -103,16 +103,16 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td><spring:message code="form.label.loan.product.loan.amount"/></td>
|
<td><spring:message code="form.label.loan.product.loan.amount"/></td>
|
||||||
<td>
|
<td>
|
||||||
<input id="principalMoney" name="principalMoney" title="" type="text" value="{{=$ctx.money(selectedProduct.principalMoney)}}" style="width: 125px;" />
|
<input id="principalFormatted" name="principalFormatted" title="" type="text" value="{{=$ctx.money(selectedProduct.principalMoney)}}" style="width: 125px;" />
|
||||||
<input id="principalMoney.currencyCode" name="principalMoney.currencyCode" title="" type="text" value="{{=selectedProduct.principalMoney.displaySymbol}}" style="width: 40px;" disabled="disabled" />
|
<input id="principalCurrencyCode" name="principalCurrencyCode" title="" type="text" value="{{=selectedProduct.principalMoney.displaySymbol}}" style="width: 40px;" disabled="disabled" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><spring:message code="form.label.loan.product.repaidevery"/></td>
|
<td><spring:message code="form.label.loan.product.repaidevery"/></td>
|
||||||
<td>
|
<td>
|
||||||
<input id="repaidEvery" name="repaidEvery" title="" type="text" value="{{=$ctx.number(selectedProduct.repaidEvery)}}" style="width: 50px;" />
|
<input id="repaymentEvery" name="repaymentEvery" title="" type="text" value="{{=$ctx.number(selectedProduct.repaidEvery)}}" style="width: 50px;" />
|
||||||
|
|
||||||
<select name="selectedRepaymentFrequencyOption" id="selectedRepaymentFrequencyOption" title="" style="width: 121px;">
|
<select name="repaymentFrequency" id="repaymentFrequency" title="" style="width: 121px;">
|
||||||
{{#each selectedProduct.repaymentFrequencyOptions}}
|
{{#each selectedProduct.repaymentFrequencyOptions}}
|
||||||
{{#if $ctx.number($parent.parent.data.selectedProduct.repaymentPeriodFrequency)===$ctx.number(id)}}
|
{{#if $ctx.number($parent.parent.data.selectedProduct.repaymentPeriodFrequency)===$ctx.number(id)}}
|
||||||
<option value="{{=$ctx.number(id)}}" selected="selected">{{=value}}</option>
|
<option value="{{=$ctx.number(id)}}" selected="selected">{{=value}}</option>
|
||||||
@@ -149,9 +149,9 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td><spring:message code="form.label.loan.product.nominal.interestrate"/></td>
|
<td><spring:message code="form.label.loan.product.nominal.interestrate"/></td>
|
||||||
<td>
|
<td>
|
||||||
<input id="nominalInterestRate" name="nominalInterestRate" title="" type="text" value="{{=$ctx.decimal(selectedProduct.interestRatePerPeriod, 4)}}" style="width: 60px;" />
|
<input id="interestRatePerPeriodFormatted" name="interestRatePerPeriodFormatted" title="" type="text" value="{{=$ctx.decimal(selectedProduct.interestRatePerPeriod, 4)}}" style="width: 60px;" />
|
||||||
|
|
||||||
<select name="selectedInterestFrequencyOption" id="selectedInterestFrequencyOption" title="" style="width: 115px;">
|
<select name="interestRateFrequencyMethod" id="interestRateFrequencyMethod" title="" style="width: 115px;">
|
||||||
{{#each selectedProduct.interestFrequencyOptions}}
|
{{#each selectedProduct.interestFrequencyOptions}}
|
||||||
{{#if $ctx.number($parent.parent.data.selectedProduct.interestRatePeriod)===$ctx.number(id)}}
|
{{#if $ctx.number($parent.parent.data.selectedProduct.interestRatePeriod)===$ctx.number(id)}}
|
||||||
<option value="{{=$ctx.number(id)}}" selected="selected">{{=value}}</option>
|
<option value="{{=$ctx.number(id)}}" selected="selected">{{=value}}</option>
|
||||||
@@ -171,7 +171,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td><spring:message code="form.label.loan.product.amortization"/></td>
|
<td><spring:message code="form.label.loan.product.amortization"/></td>
|
||||||
<td>
|
<td>
|
||||||
<select name="selectedAmortizationMethodOption" id="selectedAmortizationMethodOption" title="" style="width: 178px;">
|
<select name="amortizationMethod" id="amortizationMethod" title="" style="width: 178px;">
|
||||||
{{#each selectedProduct.possibleAmortizationOptions}}
|
{{#each selectedProduct.possibleAmortizationOptions}}
|
||||||
{{#if $ctx.number($parent.parent.data.selectedProduct.amortizationMethod)===$ctx.number(id)}}
|
{{#if $ctx.number($parent.parent.data.selectedProduct.amortizationMethod)===$ctx.number(id)}}
|
||||||
<option value="{{=$ctx.number(id)}}" selected="selected">{{=value}}</option>
|
<option value="{{=$ctx.number(id)}}" selected="selected">{{=value}}</option>
|
||||||
@@ -185,7 +185,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td><spring:message code="form.label.loan.product.interest.method"/></td>
|
<td><spring:message code="form.label.loan.product.interest.method"/></td>
|
||||||
<td>
|
<td>
|
||||||
<select name="selectedInterestMethodOption" id="selectedInterestMethodOption" title="" style="width: 180px;">
|
<select name="interestMethod" id="interestMethod" title="" style="width: 180px;">
|
||||||
{{#each selectedProduct.possibleInterestOptions}}
|
{{#each selectedProduct.possibleInterestOptions}}
|
||||||
{{#if $ctx.number($parent.parent.data.selectedProduct.interestMethod)===$ctx.number(id)}}
|
{{#if $ctx.number($parent.parent.data.selectedProduct.interestMethod)===$ctx.number(id)}}
|
||||||
<option value="{{=$ctx.number(id)}}" selected="selected">{{=value}}</option>
|
<option value="{{=$ctx.number(id)}}" selected="selected">{{=value}}</option>
|
||||||
@@ -199,7 +199,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td><spring:message code="form.label.loan.product.interest.rate.calcutated.in.period"/></td>
|
<td><spring:message code="form.label.loan.product.interest.rate.calcutated.in.period"/></td>
|
||||||
<td>
|
<td>
|
||||||
<select id="interestRateCalculatedInPeriod" name="interestRateCalculatedInPeriod" title="" style="width: 220px;">
|
<select id="interestCalculationPeriodMethod" name="interestCalculationPeriodMethod" title="" style="width: 220px;">
|
||||||
{{#each selectedProduct.possibleInterestRateCalculatedInPeriodOptions}}
|
{{#each selectedProduct.possibleInterestRateCalculatedInPeriodOptions}}
|
||||||
{{#if $ctx.number($parent.parent.data.selectedProduct.interestRateCalculatedInPeriod)===$ctx.number(id)}}
|
{{#if $ctx.number($parent.parent.data.selectedProduct.interestRateCalculatedInPeriod)===$ctx.number(id)}}
|
||||||
<option value="{{=$ctx.number(id)}}" selected="selected">{{=value}}</option>
|
<option value="{{=$ctx.number(id)}}" selected="selected">{{=value}}</option>
|
||||||
@@ -213,14 +213,14 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td><spring:message code="form.label.loan.interest.charged.from"/></td>
|
<td><spring:message code="form.label.loan.interest.charged.from"/></td>
|
||||||
<td>
|
<td>
|
||||||
<input id="interestCalculatedFromDate" name="interestCalculatedFromDate" title="" type="text" class="datepickerfield" value="{{=$ctx.globalDate(interestCalculatedFromDate)}}" style="width:172px;"/>
|
<input id="interestCalculatedFromDateFormatted" name="interestCalculatedFromDateFormatted" title="" type="text" class="datepickerfield" value="{{=$ctx.globalDate(interestCalculatedFromDate)}}" style="width:172px;"/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><spring:message code="form.label.loan.product.arrears.tolerance"/></td>
|
<td><spring:message code="form.label.loan.product.arrears.tolerance"/></td>
|
||||||
<td>
|
<td>
|
||||||
<input id="inArrearsTolerance" name="inArrearsTolerance" title="" type="text" value="{{=$ctx.money(selectedProduct.inArrearsTolerance)}}" style="width: 125px;" />
|
<input id="inArrearsToleranceAmountFormatted" name="inArrearsToleranceAmountFormatted" title="" type="text" value="{{=$ctx.money(selectedProduct.inArrearsTolerance)}}" style="width: 125px;" />
|
||||||
<input id="inArrearsTolerance.currencyCode" name="inArrearsTolerance.currencyCode" title="" type="text" value="{{=selectedProduct.inArrearsTolerance.displaySymbol}}" style="width: 40px;" disabled="disabled" />
|
<input id="inArrearsCurrencyCode" name="inArrearsCurrencyCode" title="" type="text" value="{{=selectedProduct.inArrearsTolerance.displaySymbol}}" style="width: 40px;" disabled="disabled" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
-209
@@ -1,209 +0,0 @@
|
|||||||
package org.mifosng.platform;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.mifosng.data.ErrorResponse;
|
|
||||||
import org.mifosng.data.command.CalculateLoanScheduleCommand;
|
|
||||||
import org.mifosng.platform.exceptions.NewDataValidationException;
|
|
||||||
import org.mifosng.platform.loan.domain.AmortizationMethod;
|
|
||||||
import org.mifosng.platform.loan.domain.InterestMethod;
|
|
||||||
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
|
|
||||||
|
|
||||||
public class CalculateLoanScheduleCommandValidator {
|
|
||||||
|
|
||||||
private final CalculateLoanScheduleCommand command;
|
|
||||||
|
|
||||||
public CalculateLoanScheduleCommandValidator(CalculateLoanScheduleCommand command) {
|
|
||||||
this.command = command;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void validate() {
|
|
||||||
List<ErrorResponse> dataValidationErrors = new ArrayList<ErrorResponse>();
|
|
||||||
|
|
||||||
if (StringUtils.isBlank(command.getCurrencyCode())) {
|
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.product.currency.cannot.be.empty", "currencyCode");
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command.getDigitsAfterDecimal() != null) {
|
|
||||||
|
|
||||||
if (command.getDigitsAfterDecimal() < 0 || command.getDigitsAfterDecimal() > 6) {
|
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.product.currency.digitsAfterDecimal.must.be.between.zero.and.six.inclusive", "selectedDigitsAfterDecimal", command.getDigitsAfterDecimal());
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.product.currency.digitsAfterDecimal.cannot.be.empty", "selectedDigitsAfterDecimal");
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command.getPrincipal() != null) {
|
|
||||||
if (command.getPrincipal().doubleValue() <= Double.valueOf("0.0")) {
|
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.product.principal.amount.must.be.greater.than.zero", "principalMoney");
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
// TODO - check number of digits before decimal and after decimal
|
|
||||||
} else {
|
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.product.principal.amount.cannot.be.empty", "principalMoney");
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command.getRepaymentFrequency() != null) {
|
|
||||||
PeriodFrequencyType frequencyType = PeriodFrequencyType.fromInt(command.getRepaymentFrequency());
|
|
||||||
ErrorResponse error = null;
|
|
||||||
switch (frequencyType) {
|
|
||||||
case DAYS:
|
|
||||||
error = validateNumberExistsAndInRange("validation.msg.product.repayment.repaidEvery", "repaidEvery", command.getRepaymentEvery(), 1, 365);
|
|
||||||
break;
|
|
||||||
case WEEKS:
|
|
||||||
error = validateNumberExistsAndInRange("validation.msg.product.repayment.repaidEvery", "repaidEvery", command.getRepaymentEvery(), 1, 52);
|
|
||||||
break;
|
|
||||||
case MONTHS:
|
|
||||||
error = validateNumberExistsAndInRange("validation.msg.product.repayment.repaidEvery", "repaidEvery", command.getRepaymentEvery(), 1, 12);
|
|
||||||
break;
|
|
||||||
case YEARS:
|
|
||||||
error = validateNumberExistsAndInRange("validation.msg.product.repayment.repaidEvery", "repaidEvery", command.getRepaymentEvery(), 1, 2);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error = new ErrorResponse("validation.msg.product.repayment.frequency.invalid", "selectedRepaymentFrequencyOption");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (error != null) {
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.product.repayment.frequency.cannot.be.empty", "selectedRepaymentFrequencyOption");
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command.getNumberOfRepayments() != null) {
|
|
||||||
if (command.getNumberOfRepayments() < 1 || command.getNumberOfRepayments() > 100) {
|
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.product.number.of.repayments.is.out.of.range", "numberOfRepayments");
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.product.number.of.repayments.cannot.be.empty", "numberOfRepayments");
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command.getAmortizationMethod() != null) {
|
|
||||||
AmortizationMethod amortizationMethod = AmortizationMethod.fromInt(command.getAmortizationMethod());
|
|
||||||
ErrorResponse error = null;
|
|
||||||
switch (amortizationMethod) {
|
|
||||||
case EQUAL_PRINCIPAL:
|
|
||||||
break;
|
|
||||||
case EQUAL_INSTALLMENTS:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error = new ErrorResponse("validation.msg.product.amortization.method.invalid", "selectedAmortizationMethodOption");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (error != null) {
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.product.amortization.method.cannot.be.empty", "selectedAmortizationMethodOption");
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (command.getExpectedDisbursementDate() == null) {
|
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.loan.expectedDisbursementDate.method.cannot.be.blank", "expectedDisbursementDate");
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (command.getRepaymentsStartingFromDate() != null
|
|
||||||
&& command.getExpectedDisbursementDate().isAfter(command.getRepaymentsStartingFromDate())) {
|
|
||||||
|
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.loan.expectedDisbursementDate.cannot.be.after.first.repayment.date", "expectedDisbursementDate");
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command.getRepaymentsStartingFromDate() != null && command.getInterestCalculatedFromDate() == null) {
|
|
||||||
|
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.loan.interestCalculatedFromDate.must.be.entered.when.using.repayments.startfrom.field", "interestCalculatedFromDate");
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
} else if (command.getRepaymentsStartingFromDate() == null && command.getInterestCalculatedFromDate() != null) {
|
|
||||||
|
|
||||||
// validate interestCalculatedFromDate is after or on repaymentsStartingFromDate
|
|
||||||
|
|
||||||
if (command.getExpectedDisbursementDate().isAfter(command.getInterestCalculatedFromDate())) {
|
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.loan.interestCalculatedFromDate.cannot.be.before.disbursement.date", "interestCalculatedFromDate");
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command.getInterestRatePerPeriod()!= null) {
|
|
||||||
if (command.getInterestRatePerPeriod().doubleValue() < Double.valueOf("0.0")) {
|
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.product.interest.rate.per.period.amount.cannot.be.negative", "nominalInterestRate");
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.product.interest.rate.per.period.amount.cannot.be.empty", "nominalInterestRate");
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
// interest rate period type
|
|
||||||
if (command.getInterestRateFrequencyMethod() != null) {
|
|
||||||
PeriodFrequencyType frequencyType = PeriodFrequencyType.fromInt(command.getInterestRateFrequencyMethod());
|
|
||||||
ErrorResponse error = null;
|
|
||||||
switch (frequencyType) {
|
|
||||||
case DAYS:
|
|
||||||
break;
|
|
||||||
case WEEKS:
|
|
||||||
break;
|
|
||||||
case MONTHS:
|
|
||||||
break;
|
|
||||||
case YEARS:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error = new ErrorResponse("validation.msg.product.interest.frequency.invalid", "selectedInterestFrequencyOption");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (error != null) {
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.product.interest.frequency.cannot.be.empty", "selectedInterestFrequencyOption");
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command.getInterestMethod() != null) {
|
|
||||||
InterestMethod interestMethod = InterestMethod.fromInt(command.getInterestMethod());
|
|
||||||
ErrorResponse error = null;
|
|
||||||
switch (interestMethod) {
|
|
||||||
case DECLINING_BALANCE:
|
|
||||||
break;
|
|
||||||
case FLAT:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error = new ErrorResponse("validation.msg.product.interest.method.invalid", "selectedInterestMethodOption");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (error != null) {
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.product.interest.method.cannot.be.empty", "selectedInterestMethodOption");
|
|
||||||
dataValidationErrors.add(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dataValidationErrors.isEmpty()) {
|
|
||||||
throw new NewDataValidationException(dataValidationErrors, "Validation errors exist.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ErrorResponse validateNumberExistsAndInRange(String errorCodePreFix, String fieldName, Integer value, int min, int max) {
|
|
||||||
ErrorResponse error = null;
|
|
||||||
if (value == null) {
|
|
||||||
error = new ErrorResponse(errorCodePreFix + ".cannot.be.empty", fieldName);
|
|
||||||
} else {
|
|
||||||
if (value < min || value > max) {
|
|
||||||
error = new ErrorResponse(errorCodePreFix + ".outside.allowed.range", fieldName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -51,6 +51,7 @@ import org.mifosng.platform.loan.domain.LoanStatus;
|
|||||||
import org.mifosng.platform.loan.domain.LoanStatusRepository;
|
import org.mifosng.platform.loan.domain.LoanStatusRepository;
|
||||||
import org.mifosng.platform.loan.domain.LoanTransaction;
|
import org.mifosng.platform.loan.domain.LoanTransaction;
|
||||||
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
|
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
|
||||||
|
import org.mifosng.platform.loan.service.CalculationPlatformService;
|
||||||
import org.mifosng.platform.organisation.domain.Office;
|
import org.mifosng.platform.organisation.domain.Office;
|
||||||
import org.mifosng.platform.organisation.domain.OfficeRepository;
|
import org.mifosng.platform.organisation.domain.OfficeRepository;
|
||||||
import org.mifosng.platform.organisation.domain.Organisation;
|
import org.mifosng.platform.organisation.domain.Organisation;
|
||||||
@@ -452,7 +453,6 @@ public class ImportPlatformServiceImpl implements ImportPlatformService {
|
|||||||
|
|
||||||
String currencyCode = matchingProduct.getCurrency().getCode();
|
String currencyCode = matchingProduct.getCurrency().getCode();
|
||||||
int digitsAfterDecimal = matchingProduct.getCurrency().getDigitsAfterDecimal();
|
int digitsAfterDecimal = matchingProduct.getCurrency().getDigitsAfterDecimal();
|
||||||
boolean flexibleRepaymentSchedule = matchingProduct.isFlexibleRepaymentSchedule();
|
|
||||||
Integer repaymentEvery = matchingProduct.getRepayEvery();
|
Integer repaymentEvery = matchingProduct.getRepayEvery();
|
||||||
Integer repaymentFrequency = matchingProduct.getRepaymentPeriodFrequencyType().getValue();
|
Integer repaymentFrequency = matchingProduct.getRepaymentPeriodFrequencyType().getValue();
|
||||||
Integer amortizationMethod = matchingProduct.getAmortizationMethod().getValue();
|
Integer amortizationMethod = matchingProduct.getAmortizationMethod().getValue();
|
||||||
@@ -469,8 +469,7 @@ public class ImportPlatformServiceImpl implements ImportPlatformService {
|
|||||||
interestRatePeriodFrequency,
|
interestRatePeriodFrequency,
|
||||||
interestMethod, interestCalculationPeriodMethod,
|
interestMethod, interestCalculationPeriodMethod,
|
||||||
repaymentEvery,
|
repaymentEvery,
|
||||||
repaymentFrequency, numberOfRepayments, amortizationMethod, flexibleRepaymentSchedule,
|
repaymentFrequency, numberOfRepayments, amortizationMethod, expectedDisbursementDate, repaymentsStartingFromDate, interestCalculatedFromDate);
|
||||||
matchingProduct.isInterestRebateAllowed(), expectedDisbursementDate, repaymentsStartingFromDate, interestCalculatedFromDate);
|
|
||||||
|
|
||||||
LoanSchedule loanSchedule = this.calculationPlatformService.calculateLoanSchedule(calculateLoanScheduleCommand);
|
LoanSchedule loanSchedule = this.calculationPlatformService.calculateLoanSchedule(calculateLoanScheduleCommand);
|
||||||
|
|
||||||
@@ -478,8 +477,7 @@ public class ImportPlatformServiceImpl implements ImportPlatformService {
|
|||||||
expectedDisbursementDate, repaymentsStartingFromDate, interestCalculatedFromDate, loanSchedule,
|
expectedDisbursementDate, repaymentsStartingFromDate, interestCalculatedFromDate, loanSchedule,
|
||||||
currencyCode, digitsAfterDecimal, principal,
|
currencyCode, digitsAfterDecimal, principal,
|
||||||
interestRatePerPeriod, interestRatePeriodFrequency, interestMethod, interestCalculationPeriodMethod,
|
interestRatePerPeriod, interestRatePeriodFrequency, interestMethod, interestCalculationPeriodMethod,
|
||||||
repaymentEvery, repaymentFrequency, numberOfRepayments, amortizationMethod, toleranceAmount.getAmount(),
|
repaymentEvery, repaymentFrequency, numberOfRepayments, amortizationMethod, toleranceAmount.getAmount());
|
||||||
flexibleRepaymentSchedule, matchingProduct.isInterestRebateAllowed());
|
|
||||||
|
|
||||||
parsedNewLoanDetails.setExternalId(loanExternalId);
|
parsedNewLoanDetails.setExternalId(loanExternalId);
|
||||||
|
|
||||||
|
|||||||
@@ -5,18 +5,14 @@ import static org.mifosng.platform.Specifications.loansThatMatch;
|
|||||||
|
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.mifosng.data.ClientData;
|
|
||||||
import org.mifosng.data.CurrencyData;
|
import org.mifosng.data.CurrencyData;
|
||||||
import org.mifosng.data.LoanProductData;
|
|
||||||
import org.mifosng.data.LoanRepaymentData;
|
import org.mifosng.data.LoanRepaymentData;
|
||||||
import org.mifosng.data.MoneyData;
|
import org.mifosng.data.MoneyData;
|
||||||
import org.mifosng.data.NewLoanWorkflowStepOneData;
|
|
||||||
import org.mifosng.data.OrganisationReadModel;
|
import org.mifosng.data.OrganisationReadModel;
|
||||||
import org.mifosng.platform.client.service.ClientReadPlatformService;
|
import org.mifosng.platform.client.service.ClientReadPlatformService;
|
||||||
import org.mifosng.platform.currency.domain.ApplicationCurrency;
|
import org.mifosng.platform.currency.domain.ApplicationCurrency;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import org.mifosng.data.EntityIdentifier;
|
|||||||
import org.mifosng.data.command.AdjustLoanTransactionCommand;
|
import org.mifosng.data.command.AdjustLoanTransactionCommand;
|
||||||
import org.mifosng.data.command.LoanStateTransitionCommand;
|
import org.mifosng.data.command.LoanStateTransitionCommand;
|
||||||
import org.mifosng.data.command.LoanTransactionCommand;
|
import org.mifosng.data.command.LoanTransactionCommand;
|
||||||
import org.mifosng.data.command.SubmitLoanApplicationCommand;
|
|
||||||
import org.mifosng.data.command.UndoLoanApprovalCommand;
|
import org.mifosng.data.command.UndoLoanApprovalCommand;
|
||||||
import org.mifosng.data.command.UndoLoanDisbursalCommand;
|
import org.mifosng.data.command.UndoLoanDisbursalCommand;
|
||||||
import org.mifosng.data.command.UpdateUsernamePasswordCommand;
|
import org.mifosng.data.command.UpdateUsernamePasswordCommand;
|
||||||
@@ -14,12 +13,6 @@ public interface WritePlatformService {
|
|||||||
|
|
||||||
void updateUsernamePasswordOnFirstTimeLogin(UpdateUsernamePasswordCommand command);
|
void updateUsernamePasswordOnFirstTimeLogin(UpdateUsernamePasswordCommand command);
|
||||||
|
|
||||||
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_DELETE_LOAN_THAT_IS_SUBMITTED_AND_NOT_APPROVED')")
|
|
||||||
EntityIdentifier deleteLoan(Long loanId);
|
|
||||||
|
|
||||||
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_SUBMIT_NEW_LOAN_APPLICATION_ROLE', 'CAN_SUBMIT_HISTORIC_LOAN_APPLICATION_ROLE')")
|
|
||||||
EntityIdentifier submitLoanApplication(SubmitLoanApplicationCommand command);
|
|
||||||
|
|
||||||
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_APPROVE_LOAN_ROLE', 'CAN_APPROVE_LOAN_IN_THE_PAST_ROLE')")
|
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_APPROVE_LOAN_ROLE', 'CAN_APPROVE_LOAN_IN_THE_PAST_ROLE')")
|
||||||
EntityIdentifier approveLoanApplication(LoanStateTransitionCommand command);
|
EntityIdentifier approveLoanApplication(LoanStateTransitionCommand command);
|
||||||
|
|
||||||
|
|||||||
+2
-149
@@ -3,7 +3,6 @@ package org.mifosng.platform;
|
|||||||
import static org.mifosng.platform.Specifications.loansThatMatch;
|
import static org.mifosng.platform.Specifications.loansThatMatch;
|
||||||
import static org.mifosng.platform.Specifications.usersThatMatch;
|
import static org.mifosng.platform.Specifications.usersThatMatch;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -13,39 +12,27 @@ import org.joda.time.LocalDate;
|
|||||||
import org.mifosng.data.EntityIdentifier;
|
import org.mifosng.data.EntityIdentifier;
|
||||||
import org.mifosng.data.ErrorResponse;
|
import org.mifosng.data.ErrorResponse;
|
||||||
import org.mifosng.data.LoanSchedule;
|
import org.mifosng.data.LoanSchedule;
|
||||||
import org.mifosng.data.MoneyData;
|
|
||||||
import org.mifosng.data.ScheduledLoanInstallment;
|
import org.mifosng.data.ScheduledLoanInstallment;
|
||||||
import org.mifosng.data.command.AdjustLoanTransactionCommand;
|
import org.mifosng.data.command.AdjustLoanTransactionCommand;
|
||||||
import org.mifosng.data.command.CalculateLoanScheduleCommand;
|
import org.mifosng.data.command.CalculateLoanScheduleCommand;
|
||||||
import org.mifosng.data.command.LoanStateTransitionCommand;
|
import org.mifosng.data.command.LoanStateTransitionCommand;
|
||||||
import org.mifosng.data.command.LoanTransactionCommand;
|
import org.mifosng.data.command.LoanTransactionCommand;
|
||||||
import org.mifosng.data.command.SubmitLoanApplicationCommand;
|
|
||||||
import org.mifosng.data.command.UndoLoanApprovalCommand;
|
import org.mifosng.data.command.UndoLoanApprovalCommand;
|
||||||
import org.mifosng.data.command.UndoLoanDisbursalCommand;
|
import org.mifosng.data.command.UndoLoanDisbursalCommand;
|
||||||
import org.mifosng.data.command.UpdateUsernamePasswordCommand;
|
import org.mifosng.data.command.UpdateUsernamePasswordCommand;
|
||||||
import org.mifosng.platform.client.domain.Client;
|
|
||||||
import org.mifosng.platform.client.domain.ClientRepository;
|
|
||||||
import org.mifosng.platform.client.domain.Note;
|
import org.mifosng.platform.client.domain.Note;
|
||||||
import org.mifosng.platform.client.domain.NoteRepository;
|
import org.mifosng.platform.client.domain.NoteRepository;
|
||||||
import org.mifosng.platform.currency.domain.MonetaryCurrency;
|
import org.mifosng.platform.currency.domain.MonetaryCurrency;
|
||||||
import org.mifosng.platform.currency.domain.Money;
|
import org.mifosng.platform.currency.domain.Money;
|
||||||
import org.mifosng.platform.exceptions.ApplicationDomainRuleException;
|
import org.mifosng.platform.exceptions.ApplicationDomainRuleException;
|
||||||
import org.mifosng.platform.exceptions.NoAuthorizationException;
|
|
||||||
import org.mifosng.platform.exceptions.UnAuthenticatedUserException;
|
import org.mifosng.platform.exceptions.UnAuthenticatedUserException;
|
||||||
import org.mifosng.platform.infrastructure.BasicPasswordEncodablePlatformUser;
|
import org.mifosng.platform.infrastructure.BasicPasswordEncodablePlatformUser;
|
||||||
import org.mifosng.platform.infrastructure.PlatformPasswordEncoder;
|
import org.mifosng.platform.infrastructure.PlatformPasswordEncoder;
|
||||||
import org.mifosng.platform.infrastructure.PlatformUser;
|
import org.mifosng.platform.infrastructure.PlatformUser;
|
||||||
import org.mifosng.platform.infrastructure.UsernameAlreadyExistsException;
|
import org.mifosng.platform.infrastructure.UsernameAlreadyExistsException;
|
||||||
import org.mifosng.platform.loan.domain.AmortizationMethod;
|
|
||||||
import org.mifosng.platform.loan.domain.DefaultLoanLifecycleStateMachine;
|
import org.mifosng.platform.loan.domain.DefaultLoanLifecycleStateMachine;
|
||||||
import org.mifosng.platform.loan.domain.InterestCalculationPeriodMethod;
|
|
||||||
import org.mifosng.platform.loan.domain.InterestMethod;
|
|
||||||
import org.mifosng.platform.loan.domain.Loan;
|
import org.mifosng.platform.loan.domain.Loan;
|
||||||
import org.mifosng.platform.loan.domain.LoanBuilder;
|
|
||||||
import org.mifosng.platform.loan.domain.LoanLifecycleStateMachine;
|
import org.mifosng.platform.loan.domain.LoanLifecycleStateMachine;
|
||||||
import org.mifosng.platform.loan.domain.LoanProduct;
|
|
||||||
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
|
|
||||||
import org.mifosng.platform.loan.domain.LoanProductRepository;
|
|
||||||
import org.mifosng.platform.loan.domain.LoanRepaymentScheduleInstallment;
|
import org.mifosng.platform.loan.domain.LoanRepaymentScheduleInstallment;
|
||||||
import org.mifosng.platform.loan.domain.LoanRepository;
|
import org.mifosng.platform.loan.domain.LoanRepository;
|
||||||
import org.mifosng.platform.loan.domain.LoanStatus;
|
import org.mifosng.platform.loan.domain.LoanStatus;
|
||||||
@@ -53,6 +40,7 @@ import org.mifosng.platform.loan.domain.LoanStatusRepository;
|
|||||||
import org.mifosng.platform.loan.domain.LoanTransaction;
|
import org.mifosng.platform.loan.domain.LoanTransaction;
|
||||||
import org.mifosng.platform.loan.domain.LoanTransactionRepository;
|
import org.mifosng.platform.loan.domain.LoanTransactionRepository;
|
||||||
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
|
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
|
||||||
|
import org.mifosng.platform.loan.service.CalculationPlatformService;
|
||||||
import org.mifosng.platform.user.domain.AppUser;
|
import org.mifosng.platform.user.domain.AppUser;
|
||||||
import org.mifosng.platform.user.domain.AppUserRepository;
|
import org.mifosng.platform.user.domain.AppUserRepository;
|
||||||
import org.mifosng.platform.user.domain.PlatformUserRepository;
|
import org.mifosng.platform.user.domain.PlatformUserRepository;
|
||||||
@@ -69,8 +57,6 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi
|
|||||||
|
|
||||||
private final PlatformUserRepository platformUserRepository;
|
private final PlatformUserRepository platformUserRepository;
|
||||||
private final PlatformPasswordEncoder platformPasswordEncoder;
|
private final PlatformPasswordEncoder platformPasswordEncoder;
|
||||||
private final ClientRepository clientRepository;
|
|
||||||
private final LoanProductRepository loanProductRepository;
|
|
||||||
private final LoanRepository loanRepository;
|
private final LoanRepository loanRepository;
|
||||||
private final LoanStatusRepository loanStatusRepository;
|
private final LoanStatusRepository loanStatusRepository;
|
||||||
private final CalculationPlatformService calculationPlatformService;
|
private final CalculationPlatformService calculationPlatformService;
|
||||||
@@ -81,9 +67,7 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi
|
|||||||
public WritePlatformServiceJpaRepositoryImpl(
|
public WritePlatformServiceJpaRepositoryImpl(
|
||||||
final PlatformUserRepository platformUserRepository,
|
final PlatformUserRepository platformUserRepository,
|
||||||
final PlatformPasswordEncoder platformPasswordEncoder,
|
final PlatformPasswordEncoder platformPasswordEncoder,
|
||||||
final ClientRepository clientRepository,
|
|
||||||
final NoteRepository noteRepository,
|
final NoteRepository noteRepository,
|
||||||
final LoanProductRepository loanProductRepository,
|
|
||||||
final LoanRepository loanRepository,
|
final LoanRepository loanRepository,
|
||||||
final LoanTransactionRepository loanTransactionRepository,
|
final LoanTransactionRepository loanTransactionRepository,
|
||||||
final LoanStatusRepository loanStatusRepository,
|
final LoanStatusRepository loanStatusRepository,
|
||||||
@@ -91,9 +75,7 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi
|
|||||||
) {
|
) {
|
||||||
this.platformUserRepository = platformUserRepository;
|
this.platformUserRepository = platformUserRepository;
|
||||||
this.platformPasswordEncoder = platformPasswordEncoder;
|
this.platformPasswordEncoder = platformPasswordEncoder;
|
||||||
this.clientRepository = clientRepository;
|
|
||||||
this.noteRepository = noteRepository;
|
this.noteRepository = noteRepository;
|
||||||
this.loanProductRepository = loanProductRepository;
|
|
||||||
this.loanRepository = loanRepository;
|
this.loanRepository = loanRepository;
|
||||||
this.loanTransactionRepository = loanTransactionRepository;
|
this.loanTransactionRepository = loanTransactionRepository;
|
||||||
this.loanStatusRepository = loanStatusRepository;
|
this.loanStatusRepository = loanStatusRepository;
|
||||||
@@ -145,105 +127,6 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi
|
|||||||
return currentUser;
|
return currentUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
|
||||||
@Override
|
|
||||||
public EntityIdentifier submitLoanApplication(final SubmitLoanApplicationCommand command) {
|
|
||||||
|
|
||||||
AppUser currentUser = extractAuthenticatedUser();
|
|
||||||
|
|
||||||
SubmitLoanApplicationCommandValidator validator = new SubmitLoanApplicationCommandValidator(command);
|
|
||||||
validator.validate();
|
|
||||||
|
|
||||||
LocalDate submittedOn = command.getSubmittedOnDate();
|
|
||||||
if (this.isBeforeToday(submittedOn) && currentUser.hasNotPermissionForAnyOf("CAN_SUBMIT_HISTORIC_LOAN_APPLICATION_ROLE", "PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE")) {
|
|
||||||
throw new NoAuthorizationException("Cannot add backdated loan.");
|
|
||||||
}
|
|
||||||
|
|
||||||
LoanProduct loanProduct = this.loanProductRepository.findOne(command.getProductId());
|
|
||||||
Client client = this.clientRepository.findOne(command.getApplicantId());
|
|
||||||
|
|
||||||
MonetaryCurrency currency = new MonetaryCurrency(command.getCurrencyCode(), command.getDigitsAfterDecimal());
|
|
||||||
|
|
||||||
final BigDecimal defaultNominalInterestRatePerPeriod = BigDecimal.valueOf(command
|
|
||||||
.getInterestRatePerPeriod().doubleValue());
|
|
||||||
final PeriodFrequencyType interestPeriodFrequencyType = PeriodFrequencyType.fromInt(command.getInterestRateFrequencyMethod());
|
|
||||||
|
|
||||||
// apr calculator
|
|
||||||
BigDecimal defaultAnnualNominalInterestRate = BigDecimal.ZERO;
|
|
||||||
switch (interestPeriodFrequencyType) {
|
|
||||||
case DAYS:
|
|
||||||
break;
|
|
||||||
case WEEKS:
|
|
||||||
defaultAnnualNominalInterestRate = command
|
|
||||||
.getInterestRatePerPeriod()
|
|
||||||
.multiply(BigDecimal.valueOf(52));
|
|
||||||
break;
|
|
||||||
case MONTHS:
|
|
||||||
defaultAnnualNominalInterestRate = command
|
|
||||||
.getInterestRatePerPeriod()
|
|
||||||
.multiply(BigDecimal.valueOf(12));
|
|
||||||
break;
|
|
||||||
case YEARS:
|
|
||||||
defaultAnnualNominalInterestRate = command
|
|
||||||
.getInterestRatePerPeriod().multiply(BigDecimal.valueOf(1));
|
|
||||||
break;
|
|
||||||
case INVALID:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
final InterestMethod interestMethod = InterestMethod.fromInt(command.getInterestMethod());
|
|
||||||
final InterestCalculationPeriodMethod interestCalculationPeriodMethod = InterestCalculationPeriodMethod.fromInt(command.getInterestCalculationPeriodMethod());
|
|
||||||
|
|
||||||
final Integer repayEvery = command.getRepaymentEvery();
|
|
||||||
final PeriodFrequencyType repaymentFrequencyType = PeriodFrequencyType
|
|
||||||
.fromInt(command.getRepaymentFrequency());
|
|
||||||
final Integer defaultNumberOfInstallments = command.getNumberOfRepayments();
|
|
||||||
final AmortizationMethod amortizationMethod = AmortizationMethod.fromInt(command.getAmortizationMethod());
|
|
||||||
final boolean flexibleRepaymentSchedule = command.isFlexibleRepaymentSchedule();
|
|
||||||
final boolean interestRebateAllowed = command.isInterestRebateAllowed();
|
|
||||||
|
|
||||||
LoanProductRelatedDetail loanRepaymentScheduleDetail = new LoanProductRelatedDetail(currency,
|
|
||||||
command.getPrincipal(), defaultNominalInterestRatePerPeriod, interestPeriodFrequencyType, defaultAnnualNominalInterestRate,
|
|
||||||
interestMethod, interestCalculationPeriodMethod,
|
|
||||||
repayEvery, repaymentFrequencyType, defaultNumberOfInstallments, amortizationMethod, command.getInArrearsToleranceAmount(),
|
|
||||||
flexibleRepaymentSchedule, interestRebateAllowed);
|
|
||||||
|
|
||||||
LoanSchedule loanSchedule = command.getLoanSchedule();
|
|
||||||
List<ScheduledLoanInstallment> loanRepaymentSchedule = loanSchedule.getScheduledLoanInstallments();
|
|
||||||
|
|
||||||
Loan loan = new LoanBuilder()
|
|
||||||
.with(currentUser.getOrganisation())
|
|
||||||
.with(loanProduct).with(client)
|
|
||||||
.with(loanRepaymentScheduleDetail)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
for (ScheduledLoanInstallment scheduledLoanInstallment : loanRepaymentSchedule) {
|
|
||||||
|
|
||||||
MoneyData readPrincipalDue = scheduledLoanInstallment
|
|
||||||
.getPrincipalDue();
|
|
||||||
|
|
||||||
MoneyData readInterestDue = scheduledLoanInstallment
|
|
||||||
.getInterestDue();
|
|
||||||
|
|
||||||
LoanRepaymentScheduleInstallment installment = new LoanRepaymentScheduleInstallment(
|
|
||||||
loan, scheduledLoanInstallment.getInstallmentNumber(),
|
|
||||||
scheduledLoanInstallment.getPeriodStart(),
|
|
||||||
scheduledLoanInstallment.getPeriodEnd(), readPrincipalDue.getAmount(),
|
|
||||||
readInterestDue.getAmount());
|
|
||||||
loan.addRepaymentScheduleInstallment(installment);
|
|
||||||
}
|
|
||||||
|
|
||||||
loan.submitApplication(submittedOn, command.getExpectedDisbursementDate(), command.getRepaymentsStartingFromDate(), command.getInterestCalculatedFromDate(), defaultLoanLifecycleStateMachine());
|
|
||||||
this.loanRepository.save(loan);
|
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(command.getSubmittedOnNote())) {
|
|
||||||
Note note = Note.loanNote(currentUser.getOrganisation(), loan, command.getSubmittedOnNote());
|
|
||||||
this.noteRepository.save(note);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new EntityIdentifier(loan.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isBeforeToday(final LocalDate date) {
|
private boolean isBeforeToday(final LocalDate date) {
|
||||||
return date.isBefore(new LocalDate());
|
return date.isBefore(new LocalDate());
|
||||||
}
|
}
|
||||||
@@ -253,34 +136,6 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi
|
|||||||
return new DefaultLoanLifecycleStateMachine(allowedLoanStatuses);
|
return new DefaultLoanLifecycleStateMachine(allowedLoanStatuses);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
|
||||||
@Override
|
|
||||||
public EntityIdentifier deleteLoan(Long loanId) {
|
|
||||||
|
|
||||||
AppUser currentUser = extractAuthenticatedUser();
|
|
||||||
|
|
||||||
Loan loan = this.loanRepository.findOne(loansThatMatch(
|
|
||||||
currentUser.getOrganisation(), loanId));
|
|
||||||
|
|
||||||
if (loan == null) {
|
|
||||||
throw new ApplicationDomainRuleException(loanIdentifierDoesNotExistError(loanId), "No loan exists with id: " + loanId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loan.isNotSubmittedAndPendingApproval()) {
|
|
||||||
ErrorResponse errorResponse = new ErrorResponse("error.msg.cannot.delete.loan.in.its.present.state", "eventDate");
|
|
||||||
throw new ApplicationDomainRuleException(Arrays.asList(errorResponse), "Loan must be in pending approval state.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Long clientId = loan.getClient().getId();
|
|
||||||
|
|
||||||
List<Note> relatedNotes = this.noteRepository.findByLoanId(loan.getId());
|
|
||||||
this.noteRepository.deleteInBatch(relatedNotes);
|
|
||||||
|
|
||||||
this.loanRepository.delete(loanId);
|
|
||||||
|
|
||||||
return new EntityIdentifier(clientId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ErrorResponse> loanIdentifierDoesNotExistError(Long loanId) {
|
private List<ErrorResponse> loanIdentifierDoesNotExistError(Long loanId) {
|
||||||
ErrorResponse errorResponse = new ErrorResponse("error.msg.no.loan.with.identifier.exists", "id", loanId);
|
ErrorResponse errorResponse = new ErrorResponse("error.msg.no.loan.with.identifier.exists", "id", loanId);
|
||||||
return Arrays.asList(errorResponse);
|
return Arrays.asList(errorResponse);
|
||||||
@@ -444,7 +299,6 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi
|
|||||||
Integer repaidEvery = loan.getLoanRepaymentScheduleDetail().getRepayEvery();
|
Integer repaidEvery = loan.getLoanRepaymentScheduleDetail().getRepayEvery();
|
||||||
Integer selectedRepaymentFrequency = loan.getLoanRepaymentScheduleDetail().getRepaymentPeriodFrequencyType().getValue();
|
Integer selectedRepaymentFrequency = loan.getLoanRepaymentScheduleDetail().getRepaymentPeriodFrequencyType().getValue();
|
||||||
Integer selectedRepaymentSchedule = loan.getLoanRepaymentScheduleDetail().getAmortizationMethod().getValue();
|
Integer selectedRepaymentSchedule = loan.getLoanRepaymentScheduleDetail().getAmortizationMethod().getValue();
|
||||||
boolean flexibleRepaymentSchedule = loan.isFlexibleRepaymentSchedule();
|
|
||||||
|
|
||||||
// use annual percentage rate to re-calculate loan schedule for late disbursement
|
// use annual percentage rate to re-calculate loan schedule for late disbursement
|
||||||
Number interestRatePerPeriod = interestRatePerYear;
|
Number interestRatePerPeriod = interestRatePerYear;
|
||||||
@@ -452,12 +306,11 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi
|
|||||||
|
|
||||||
Integer interestMethod = loan.getLoanRepaymentScheduleDetail().getInterestMethod().getValue();
|
Integer interestMethod = loan.getLoanRepaymentScheduleDetail().getInterestMethod().getValue();
|
||||||
Integer interestCalculationInPeriod = loan.getLoanRepaymentScheduleDetail().getInterestCalculationPeriodMethod().getValue();
|
Integer interestCalculationInPeriod = loan.getLoanRepaymentScheduleDetail().getInterestCalculationPeriodMethod().getValue();
|
||||||
boolean interestRebateAllowed = loan.getLoanRepaymentScheduleDetail().isInterestRebateAllowed();
|
|
||||||
|
|
||||||
CalculateLoanScheduleCommand calculateCommand = new CalculateLoanScheduleCommand(currencyCode, currencyDigits, principalAsDecimal,
|
CalculateLoanScheduleCommand calculateCommand = new CalculateLoanScheduleCommand(currencyCode, currencyDigits, principalAsDecimal,
|
||||||
interestRatePerPeriod, interestRateFrequencyMethod, interestMethod, interestCalculationInPeriod,
|
interestRatePerPeriod, interestRateFrequencyMethod, interestMethod, interestCalculationInPeriod,
|
||||||
repaidEvery, selectedRepaymentFrequency, numberOfInstallments,
|
repaidEvery, selectedRepaymentFrequency, numberOfInstallments,
|
||||||
selectedRepaymentSchedule, flexibleRepaymentSchedule, interestRebateAllowed, actualDisbursementDate, repaymentsStartingFromDate, interestCalculatedFromDate);
|
selectedRepaymentSchedule, actualDisbursementDate, repaymentsStartingFromDate, interestCalculatedFromDate);
|
||||||
|
|
||||||
LoanSchedule loanSchedule = this.calculationPlatformService.calculateLoanSchedule(calculateCommand);
|
LoanSchedule loanSchedule = this.calculationPlatformService.calculateLoanSchedule(calculateCommand);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
package org.mifosng.platform.api;
|
package org.mifosng.platform.api;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
@@ -9,10 +14,20 @@ import javax.ws.rs.QueryParam;
|
|||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.joda.time.LocalDate;
|
||||||
|
import org.mifosng.data.EntityIdentifier;
|
||||||
import org.mifosng.data.LoanAccountData;
|
import org.mifosng.data.LoanAccountData;
|
||||||
|
import org.mifosng.data.LoanSchedule;
|
||||||
import org.mifosng.data.NewLoanWorkflowStepOneData;
|
import org.mifosng.data.NewLoanWorkflowStepOneData;
|
||||||
|
import org.mifosng.data.command.CalculateLoanScheduleCommand;
|
||||||
|
import org.mifosng.data.command.SubmitLoanApplicationCommand;
|
||||||
import org.mifosng.platform.ReadPlatformService;
|
import org.mifosng.platform.ReadPlatformService;
|
||||||
|
import org.mifosng.platform.WritePlatformService;
|
||||||
|
import org.mifosng.platform.api.infrastructure.ApiDataConversionService;
|
||||||
|
import org.mifosng.platform.loan.service.CalculationPlatformService;
|
||||||
import org.mifosng.platform.loan.service.LoanReadPlatformService;
|
import org.mifosng.platform.loan.service.LoanReadPlatformService;
|
||||||
|
import org.mifosng.platform.loan.service.LoanWritePlatformService;
|
||||||
import org.mifosng.platform.user.domain.AppUser;
|
import org.mifosng.platform.user.domain.AppUser;
|
||||||
import org.mifosng.platform.user.domain.AppUserRepository;
|
import org.mifosng.platform.user.domain.AppUserRepository;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -31,9 +46,21 @@ public class LoansApiResource {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private LoanReadPlatformService loanReadPlatformService;
|
private LoanReadPlatformService loanReadPlatformService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private LoanWritePlatformService loanWritePlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ReadPlatformService readPlatformService;
|
private ReadPlatformService readPlatformService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WritePlatformService writePlatformService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CalculationPlatformService calculationPlatformService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApiDataConversionService apiDataConversionService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AppUserRepository appUserRepository;
|
private AppUserRepository appUserRepository;
|
||||||
|
|
||||||
@@ -51,6 +78,8 @@ public class LoansApiResource {
|
|||||||
@Produces({ MediaType.APPLICATION_JSON})
|
@Produces({ MediaType.APPLICATION_JSON})
|
||||||
public Response retrieveDetailsForNewLoanApplicationStepOne(@QueryParam("clientId") final Long clientId, @QueryParam("productId") final Long productId) {
|
public Response retrieveDetailsForNewLoanApplicationStepOne(@QueryParam("clientId") final Long clientId, @QueryParam("productId") final Long productId) {
|
||||||
|
|
||||||
|
hardcodeUserIntoSecurityContext();
|
||||||
|
|
||||||
NewLoanWorkflowStepOneData workflowData = this.loanReadPlatformService.retrieveClientAndProductDetails(clientId, productId);
|
NewLoanWorkflowStepOneData workflowData = this.loanReadPlatformService.retrieveClientAndProductDetails(clientId, productId);
|
||||||
|
|
||||||
return Response.ok().entity(workflowData).build();
|
return Response.ok().entity(workflowData).build();
|
||||||
@@ -68,4 +97,58 @@ public class LoansApiResource {
|
|||||||
|
|
||||||
return Response.ok().entity(loanAccount).build();
|
return Response.ok().entity(loanAccount).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
|
||||||
|
@Produces({MediaType.APPLICATION_JSON})
|
||||||
|
public Response calculateLoanSchedule(@QueryParam("command") final String commandParam, final SubmitLoanApplicationCommand command) {
|
||||||
|
|
||||||
|
hardcodeUserIntoSecurityContext();
|
||||||
|
|
||||||
|
LocalDate expectedDisbursementDate = apiDataConversionService.convertFrom(command.getExpectedDisbursementDateFormatted(), "expectedDisbursementDateFormatted", command.getDateFormat());
|
||||||
|
LocalDate repaymentsStartingFromDate = apiDataConversionService.convertFrom(command.getRepaymentsStartingFromDateFormatted(), "repaymentsStartingFromDateFormatted", command.getDateFormat());
|
||||||
|
LocalDate interestCalculatedFromDate = apiDataConversionService.convertFrom(command.getInterestCalculatedFromDateFormatted(), "interestCalculatedFromDateFormatted", command.getDateFormat());
|
||||||
|
LocalDate submittedOnDate = apiDataConversionService.convertFrom(command.getSubmittedOnDateFormatted(), "submittedOnDateFormatted", command.getDateFormat());
|
||||||
|
command.setExpectedDisbursementDate(expectedDisbursementDate);
|
||||||
|
command.setRepaymentsStartingFromDate(repaymentsStartingFromDate);
|
||||||
|
command.setInterestCalculatedFromDate(interestCalculatedFromDate);
|
||||||
|
command.setSubmittedOnDate(submittedOnDate);
|
||||||
|
|
||||||
|
// FIXME - pass in locale through query string or in 'request body'
|
||||||
|
Locale clientApplicationLocale = Locale.UK;
|
||||||
|
BigDecimal principal = this.apiDataConversionService.convertFrom(command.getPrincipalFormatted(), "principalFormatted", clientApplicationLocale);
|
||||||
|
BigDecimal interestRatePerPeriod = this.apiDataConversionService.convertFrom(command.getInterestRatePerPeriodFormatted(), "interestRatePerPeriodFormatted", clientApplicationLocale);
|
||||||
|
BigDecimal inArrearsToleranceAmount = this.apiDataConversionService.convertFrom(command.getInArrearsToleranceAmountFormatted(), "inArrearsToleranceAmountFormatted", clientApplicationLocale);
|
||||||
|
command.setPrincipal(principal);
|
||||||
|
command.setInterestRatePerPeriod(interestRatePerPeriod);
|
||||||
|
command.setInArrearsToleranceAmount(inArrearsToleranceAmount);
|
||||||
|
|
||||||
|
CalculateLoanScheduleCommand calculateLoanScheduleCommand = command.toCalculateLoanScheduleCommand();
|
||||||
|
LoanSchedule loanSchedule = this.calculationPlatformService.calculateLoanSchedule(calculateLoanScheduleCommand);
|
||||||
|
|
||||||
|
// for now just auto generating the loan schedule and setting support for 'manual' loan schedule creation later.
|
||||||
|
command.setLoanSchedule(loanSchedule);
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase("calculateLoanSchedule")) {
|
||||||
|
|
||||||
|
return Response.ok().entity(loanSchedule).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityIdentifier identifier = this.loanWritePlatformService.submitLoanApplication(command);
|
||||||
|
|
||||||
|
return Response.ok().entity(identifier).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@DELETE
|
||||||
|
@Path("{loanId}")
|
||||||
|
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON})
|
||||||
|
public Response deleteLoanApplication(@PathParam("loanId") final Long loanId) {
|
||||||
|
|
||||||
|
hardcodeUserIntoSecurityContext();
|
||||||
|
|
||||||
|
EntityIdentifier identifier = this.loanWritePlatformService.deleteLoan(loanId);
|
||||||
|
|
||||||
|
return Response.ok().entity(identifier).build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+5
@@ -1,9 +1,14 @@
|
|||||||
package org.mifosng.platform.api.infrastructure;
|
package org.mifosng.platform.api.infrastructure;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
|
|
||||||
public interface ApiDataConversionService {
|
public interface ApiDataConversionService {
|
||||||
|
|
||||||
LocalDate convertFrom(String dateAsString, String parameterName, String dateFormat);
|
LocalDate convertFrom(String dateAsString, String parameterName, String dateFormat);
|
||||||
|
|
||||||
|
BigDecimal convertFrom(String principalFormatted, String parameterName, Locale clientApplicationLocale);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+27
@@ -1,5 +1,8 @@
|
|||||||
package org.mifosng.platform.api.infrastructure;
|
package org.mifosng.platform.api.infrastructure;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@@ -33,4 +36,28 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
|
|||||||
|
|
||||||
return eventLocalDate;
|
return eventLocalDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal convertFrom(String numericalValueFormatted, String parameterName, Locale clientApplicationLocale) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
BigDecimal number = null;
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(numericalValueFormatted)) {
|
||||||
|
String sourceWithoutSpaces = numericalValueFormatted.replaceAll(" ", "");
|
||||||
|
NumberFormat format = NumberFormat.getNumberInstance(clientApplicationLocale);
|
||||||
|
Number parsedNumber = format.parse(sourceWithoutSpaces);
|
||||||
|
number = BigDecimal.valueOf(Double.valueOf(parsedNumber.doubleValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return number;
|
||||||
|
} catch (ParseException e) {
|
||||||
|
|
||||||
|
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.number.format", "The parameter " + parameterName + " is invalid.", parameterName, numericalValueFormatted);
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
|
||||||
|
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
package org.mifosng.platform.exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link RuntimeException} thrown when valid api request end up violating some domain rule.
|
||||||
|
*/
|
||||||
|
public class PlatformDomainRuleException extends RuntimeException {
|
||||||
|
|
||||||
|
private final String globalisationMessageCode;
|
||||||
|
private final String defaultUserMessage;
|
||||||
|
private final Object[] defaultUserMessageArgs;
|
||||||
|
|
||||||
|
public PlatformDomainRuleException(String globalisationMessageCode, String defaultUserMessage, Object... defaultUserMessageArgs) {
|
||||||
|
this.globalisationMessageCode = globalisationMessageCode;
|
||||||
|
this.defaultUserMessage = defaultUserMessage;
|
||||||
|
this.defaultUserMessageArgs = defaultUserMessageArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGlobalisationMessageCode() {
|
||||||
|
return globalisationMessageCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDefaultUserMessage() {
|
||||||
|
return defaultUserMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] getDefaultUserMessageArgs() {
|
||||||
|
return defaultUserMessageArgs;
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -70,6 +70,10 @@ public class DerivedLoanDataProcessor {
|
|||||||
|
|
||||||
Collections.sort(loanRepayments, new LoanRepaymentDataComparator());
|
Collections.sort(loanRepayments, new LoanRepaymentDataComparator());
|
||||||
|
|
||||||
|
if (loanRepayments.isEmpty()) {
|
||||||
|
loanRepayments = null;
|
||||||
|
}
|
||||||
|
|
||||||
return new DerivedLoanData(processRepaymentScheduleData, summaryData, loanRepayments);
|
return new DerivedLoanData(processRepaymentScheduleData, summaryData, loanRepayments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -131,6 +131,12 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
@Transient
|
@Transient
|
||||||
private final InterestRebateCalculatorFactory interestRebateCalculatorFactory = new DailyEquivalentInterestRebateCalculatorFactory();
|
private final InterestRebateCalculatorFactory interestRebateCalculatorFactory = new DailyEquivalentInterestRebateCalculatorFactory();
|
||||||
|
|
||||||
|
public static Loan createNew(Organisation organisation,
|
||||||
|
LoanProduct loanProduct, Client client,
|
||||||
|
LoanProductRelatedDetail loanRepaymentScheduleDetail) {
|
||||||
|
return new Loan(organisation, client, loanProduct, loanRepaymentScheduleDetail, null);
|
||||||
|
}
|
||||||
|
|
||||||
public Loan() {
|
public Loan() {
|
||||||
this.organisation = null;
|
this.organisation = null;
|
||||||
this.client = null;
|
this.client = null;
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ package org.mifosng.platform.loan.domain;
|
|||||||
import org.mifosng.platform.client.domain.Client;
|
import org.mifosng.platform.client.domain.Client;
|
||||||
import org.mifosng.platform.organisation.domain.Organisation;
|
import org.mifosng.platform.organisation.domain.Organisation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove in favour of static factory method on {@link Loan}. No advantage to builder patter in this case?
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public class LoanBuilder {
|
public class LoanBuilder {
|
||||||
|
|
||||||
private Organisation organisation;
|
private Organisation organisation;
|
||||||
|
|||||||
+218
@@ -0,0 +1,218 @@
|
|||||||
|
package org.mifosng.platform.loan.service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.mifosng.data.ApiParameterError;
|
||||||
|
import org.mifosng.data.command.CalculateLoanScheduleCommand;
|
||||||
|
import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
|
||||||
|
import org.mifosng.platform.loan.domain.AmortizationMethod;
|
||||||
|
import org.mifosng.platform.loan.domain.InterestMethod;
|
||||||
|
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
|
||||||
|
|
||||||
|
public class CalculateLoanScheduleCommandValidator {
|
||||||
|
|
||||||
|
private final CalculateLoanScheduleCommand command;
|
||||||
|
|
||||||
|
public CalculateLoanScheduleCommandValidator(CalculateLoanScheduleCommand command) {
|
||||||
|
this.command = command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validate() {
|
||||||
|
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(command.getCurrencyCode())) {
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.product.currency.cannot.be.empty", "The parameter currencyCode cannot be blank.", "currencyCode");
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.getDigitsAfterDecimal() != null) {
|
||||||
|
|
||||||
|
if (command.getDigitsAfterDecimal() < 0 || command.getDigitsAfterDecimal() > 6) {
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.product.currency.digitsAfterDecimal.must.be.between.zero.and.six.inclusive", "The parameter digitsAfterDecimal must be a value between 1 and 6.", "digitsAfterDecimal", command.getDigitsAfterDecimal(), 1, 6);
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.product.currency.digitsAfterDecimal.cannot.be.empty", "The parameter digitsAfterDecimal cannot be blank.", "digitsAfterDecimal");
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME - validate the number of digits before and after decimal provided (before is limited by database field, after is limited by number selected for product (and ultimately by the database field))
|
||||||
|
if (command.getPrincipal() != null) {
|
||||||
|
if (command.getPrincipal().doubleValue() <= Double.valueOf("0.0")) {
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.product.principal.amount.must.be.greater.than.zero", "The parameter principalMoney must be greater than zero.", "principalMoney");
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.product.principal.amount.cannot.be.empty", "The parameter principalMoney cannot be blank.", "principalMoney");
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.getRepaymentFrequency() != null) {
|
||||||
|
PeriodFrequencyType frequencyType = PeriodFrequencyType.fromInt(command.getRepaymentFrequency());
|
||||||
|
ApiParameterError error = null;
|
||||||
|
switch (frequencyType) {
|
||||||
|
case DAYS:
|
||||||
|
error = validateNumberExistsAndInRange("validation.msg.product.repayment.repaidEvery", "repaidEvery", command.getRepaymentEvery(), 1, 365);
|
||||||
|
break;
|
||||||
|
case WEEKS:
|
||||||
|
error = validateNumberExistsAndInRange("validation.msg.product.repayment.repaidEvery", "repaidEvery", command.getRepaymentEvery(), 1, 52);
|
||||||
|
break;
|
||||||
|
case MONTHS:
|
||||||
|
error = validateNumberExistsAndInRange("validation.msg.product.repayment.repaidEvery", "repaidEvery", command.getRepaymentEvery(), 1, 12);
|
||||||
|
break;
|
||||||
|
case YEARS:
|
||||||
|
error = validateNumberExistsAndInRange("validation.msg.product.repayment.repaidEvery", "repaidEvery", command.getRepaymentEvery(), 1, 2);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error = ApiParameterError.parameterError("validation.msg.product.repayment.frequency.invalid", "The parameter repaymentFrequency is invalid.", "repaymentFrequency", command.getRepaymentFrequency());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (error != null) {
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.product.repayment.frequency.cannot.be.empty", "The parameter repaymentFrequency cannot be empty.", "repaymentFrequency");
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.getNumberOfRepayments() != null) {
|
||||||
|
if (command.getNumberOfRepayments() < 1 || command.getNumberOfRepayments() > 100) {
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.product.number.of.repayments.is.out.of.range", "The parameter numberOfRepayments must between {1} and {2}.", "numberOfRepayments", command.getNumberOfRepayments(), 1, 100);
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.product.number.of.repayments.cannot.be.empty", "The parameter numberOfRepayments cannot be empty.", "numberOfRepayments");
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.getAmortizationMethod() != null) {
|
||||||
|
AmortizationMethod amortizationMethod = AmortizationMethod.fromInt(command.getAmortizationMethod());
|
||||||
|
ApiParameterError error = null;
|
||||||
|
switch (amortizationMethod) {
|
||||||
|
case EQUAL_PRINCIPAL:
|
||||||
|
break;
|
||||||
|
case EQUAL_INSTALLMENTS:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error = ApiParameterError.parameterError("validation.msg.product.amortization.method.invalid", "The parameter amortizationMethod is invalid.", "amortizationMethod", command.getAmortizationMethod());
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (error != null) {
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.product.amortization.method.cannot.be.empty", "The parameter amortizationMethod cannot be empty.", "amortizationMethod");
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.getExpectedDisbursementDate() == null) {
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.loan.expectedDisbursementDate.method.cannot.be.blank", "The parameter expectedDisbursementDate cannot be empty.", "expectedDisbursementDate");
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
} else {
|
||||||
|
if (command.getRepaymentsStartingFromDate() != null
|
||||||
|
&& command.getExpectedDisbursementDate().isAfter(command.getRepaymentsStartingFromDate())) {
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.loan.expectedDisbursementDate.cannot.be.after.first.repayment.date",
|
||||||
|
"The parameter expectedDisbursementDate has a date which falls after the given first repayment date.", "expectedDisbursementDate",
|
||||||
|
command.getExpectedDisbursementDate(), command.getRepaymentsStartingFromDate());
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.getRepaymentsStartingFromDate() != null && command.getInterestCalculatedFromDate() == null) {
|
||||||
|
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.loan.interestCalculatedFromDate.must.be.entered.when.using.repayments.startfrom.field",
|
||||||
|
"The parameter interestCalculatedFromDate cannot be empty when first repayment date is provided.", "interestCalculatedFromDate", command.getRepaymentsStartingFromDate());
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
} else if (command.getRepaymentsStartingFromDate() == null && command.getInterestCalculatedFromDate() != null) {
|
||||||
|
|
||||||
|
// validate interestCalculatedFromDate is after or on repaymentsStartingFromDate
|
||||||
|
if (command.getExpectedDisbursementDate().isAfter(command.getInterestCalculatedFromDate())) {
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.loan.interestCalculatedFromDate.cannot.be.before.disbursement.date",
|
||||||
|
"The parameter interestCalculatedFromDate cannot be before the date given for expected disbursement.", "interestCalculatedFromDate", command.getInterestCalculatedFromDate(), command.getExpectedDisbursementDate());
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.getInterestRatePerPeriod()!= null) {
|
||||||
|
if (command.getInterestRatePerPeriod().doubleValue() < Double.valueOf("0.0")) {
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.product.interest.rate.per.period.amount.cannot.be.negative",
|
||||||
|
"The parameter interestRatePerPeriodFormatted cannot be less than zero.", "interestRatePerPeriodFormatted",
|
||||||
|
command.getInterestRatePerPeriod());
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.product.interest.rate.per.period.amount.cannot.be.empty",
|
||||||
|
"The parameter interestRatePerPeriodFormatted cannot be empty.", "interestRatePerPeriodFormatted",
|
||||||
|
command.getInterestRatePerPeriod());
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// interest rate period type
|
||||||
|
if (command.getInterestRateFrequencyMethod() != null) {
|
||||||
|
PeriodFrequencyType frequencyType = PeriodFrequencyType.fromInt(command.getInterestRateFrequencyMethod());
|
||||||
|
ApiParameterError error = null;
|
||||||
|
switch (frequencyType) {
|
||||||
|
case DAYS:
|
||||||
|
break;
|
||||||
|
case WEEKS:
|
||||||
|
break;
|
||||||
|
case MONTHS:
|
||||||
|
break;
|
||||||
|
case YEARS:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error = ApiParameterError.parameterError("validation.msg.product.interest.frequency.invalid",
|
||||||
|
"The parameter interestRateFrequencyMethod cannot be empty.", "interestRateFrequencyMethod", command.getInterestRateFrequencyMethod());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (error != null) {
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.product.interest.frequency.cannot.be.empty",
|
||||||
|
"The parameter interestRateFrequencyMethod cannot be empty.", "interestRateFrequencyMethod");
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.getInterestMethod() != null) {
|
||||||
|
InterestMethod interestMethod = InterestMethod.fromInt(command.getInterestMethod());
|
||||||
|
ApiParameterError error = null;
|
||||||
|
switch (interestMethod) {
|
||||||
|
case DECLINING_BALANCE:
|
||||||
|
break;
|
||||||
|
case FLAT:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error = ApiParameterError.parameterError("validation.msg.product.interest.method.invalid",
|
||||||
|
"The parameter interestMethod is invalid.", "interestMethod", command.getInterestMethod());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (error != null) {
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.product.interest.method.cannot.be.empty",
|
||||||
|
"The parameter interestMethod cannot be empty.", "interestMethod");
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dataValidationErrors.isEmpty()) {
|
||||||
|
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ApiParameterError validateNumberExistsAndInRange(String errorCodePreFix, String fieldName, Integer value, int min, int max) {
|
||||||
|
ApiParameterError error = null;
|
||||||
|
if (value == null) {
|
||||||
|
error = ApiParameterError.parameterError(errorCodePreFix + ".cannot.be.empty", "The parameter " + fieldName + " cannot be blank.", fieldName);
|
||||||
|
} else {
|
||||||
|
if (value < min || value > max) {
|
||||||
|
error = ApiParameterError.parameterError(errorCodePreFix + ".outside.allowed.range", "The parameter " + fieldName + " must be between {0} and {1} inclusive.", fieldName, min, max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package org.mifosng.platform;
|
package org.mifosng.platform.loan.service;
|
||||||
|
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.mifosng.data.LoanPayoffReadModel;
|
import org.mifosng.data.LoanPayoffReadModel;
|
||||||
+1
-2
@@ -1,4 +1,4 @@
|
|||||||
package org.mifosng.platform;
|
package org.mifosng.platform.loan.service;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
@@ -88,7 +88,6 @@ public class CalculationPlatformServiceImpl implements
|
|||||||
@Override
|
@Override
|
||||||
public LoanPayoffReadModel calculatePayoffOn(final Long loanId, final LocalDate payoffDate) {
|
public LoanPayoffReadModel calculatePayoffOn(final Long loanId, final LocalDate payoffDate) {
|
||||||
|
|
||||||
// TODO - use jdbc approach to calculating payoff if possible.
|
|
||||||
final Loan loan = this.loanRepository.findOne(loanId);
|
final Loan loan = this.loanRepository.findOne(loanId);
|
||||||
|
|
||||||
final LoanPayoffSummary payoffSummary = loan.getPayoffSummaryOn(payoffDate);
|
final LoanPayoffSummary payoffSummary = loan.getPayoffSummaryOn(payoffDate);
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
package org.mifosng.platform.loan.service;
|
||||||
|
|
||||||
|
import org.mifosng.data.EntityIdentifier;
|
||||||
|
import org.mifosng.data.command.SubmitLoanApplicationCommand;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
|
||||||
|
public interface LoanWritePlatformService {
|
||||||
|
|
||||||
|
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_SUBMIT_NEW_LOAN_APPLICATION_ROLE', 'CAN_SUBMIT_HISTORIC_LOAN_APPLICATION_ROLE')")
|
||||||
|
EntityIdentifier submitLoanApplication(SubmitLoanApplicationCommand command);
|
||||||
|
|
||||||
|
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_DELETE_LOAN_THAT_IS_SUBMITTED_AND_NOT_APPROVED')")
|
||||||
|
EntityIdentifier deleteLoan(Long loanId);
|
||||||
|
}
|
||||||
+171
@@ -0,0 +1,171 @@
|
|||||||
|
package org.mifosng.platform.loan.service;
|
||||||
|
|
||||||
|
import static org.mifosng.platform.Specifications.loansThatMatch;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.joda.time.LocalDate;
|
||||||
|
import org.mifosng.data.EntityIdentifier;
|
||||||
|
import org.mifosng.data.LoanSchedule;
|
||||||
|
import org.mifosng.data.MoneyData;
|
||||||
|
import org.mifosng.data.ScheduledLoanInstallment;
|
||||||
|
import org.mifosng.data.command.SubmitLoanApplicationCommand;
|
||||||
|
import org.mifosng.platform.client.domain.Client;
|
||||||
|
import org.mifosng.platform.client.domain.ClientRepository;
|
||||||
|
import org.mifosng.platform.client.domain.Note;
|
||||||
|
import org.mifosng.platform.client.domain.NoteRepository;
|
||||||
|
import org.mifosng.platform.currency.domain.MonetaryCurrency;
|
||||||
|
import org.mifosng.platform.exceptions.NoAuthorizationException;
|
||||||
|
import org.mifosng.platform.exceptions.PlatformDomainRuleException;
|
||||||
|
import org.mifosng.platform.exceptions.PlatformResourceNotFoundException;
|
||||||
|
import org.mifosng.platform.loan.domain.AmortizationMethod;
|
||||||
|
import org.mifosng.platform.loan.domain.DefaultLoanLifecycleStateMachine;
|
||||||
|
import org.mifosng.platform.loan.domain.InterestCalculationPeriodMethod;
|
||||||
|
import org.mifosng.platform.loan.domain.InterestMethod;
|
||||||
|
import org.mifosng.platform.loan.domain.Loan;
|
||||||
|
import org.mifosng.platform.loan.domain.LoanLifecycleStateMachine;
|
||||||
|
import org.mifosng.platform.loan.domain.LoanProduct;
|
||||||
|
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
|
||||||
|
import org.mifosng.platform.loan.domain.LoanProductRepository;
|
||||||
|
import org.mifosng.platform.loan.domain.LoanRepaymentScheduleInstallment;
|
||||||
|
import org.mifosng.platform.loan.domain.LoanRepository;
|
||||||
|
import org.mifosng.platform.loan.domain.LoanStatus;
|
||||||
|
import org.mifosng.platform.loan.domain.LoanStatusRepository;
|
||||||
|
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
|
||||||
|
import org.mifosng.platform.loanschedule.domain.AprCalculator;
|
||||||
|
import org.mifosng.platform.security.PlatformSecurityContext;
|
||||||
|
import org.mifosng.platform.user.domain.AppUser;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatformService {
|
||||||
|
|
||||||
|
private final PlatformSecurityContext context;
|
||||||
|
private final LoanRepository loanRepository;
|
||||||
|
private final LoanProductRepository loanProductRepository;
|
||||||
|
private final LoanStatusRepository loanStatusRepository;
|
||||||
|
private final ClientRepository clientRepository;
|
||||||
|
private final NoteRepository noteRepository;
|
||||||
|
|
||||||
|
private final AprCalculator aprCalculator = new AprCalculator();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||||
|
final LoanRepository loanRepository, final LoanStatusRepository loanStatusRepository, final LoanProductRepository loanProductRepository,
|
||||||
|
final ClientRepository clientRepository, final NoteRepository noteRepository) {
|
||||||
|
this.context = context;
|
||||||
|
this.loanRepository = loanRepository;
|
||||||
|
this.loanProductRepository = loanProductRepository;
|
||||||
|
this.clientRepository = clientRepository;
|
||||||
|
this.loanStatusRepository = loanStatusRepository;
|
||||||
|
this.noteRepository = noteRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isBeforeToday(final LocalDate date) {
|
||||||
|
return date.isBefore(new LocalDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
|
||||||
|
List<LoanStatus> allowedLoanStatuses = this.loanStatusRepository.findAll();
|
||||||
|
return new DefaultLoanLifecycleStateMachine(allowedLoanStatuses);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public EntityIdentifier submitLoanApplication(final SubmitLoanApplicationCommand command) {
|
||||||
|
|
||||||
|
AppUser currentUser = context.authenticatedUser();
|
||||||
|
|
||||||
|
SubmitLoanApplicationCommandValidator validator = new SubmitLoanApplicationCommandValidator(command);
|
||||||
|
validator.validate();
|
||||||
|
|
||||||
|
LocalDate submittedOn = command.getSubmittedOnDate();
|
||||||
|
if (this.isBeforeToday(submittedOn) && currentUser.hasNotPermissionForAnyOf("CAN_SUBMIT_HISTORIC_LOAN_APPLICATION_ROLE", "PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE")) {
|
||||||
|
throw new NoAuthorizationException("Cannot add backdated loan.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME - looks like assembly of LoanProductRelatedDetail is common with loan product and calculate loan schedule areas. remove duplication into an assembler.
|
||||||
|
LoanProduct loanProduct = this.loanProductRepository.findOne(command.getProductId());
|
||||||
|
Client client = this.clientRepository.findOne(command.getApplicantId());
|
||||||
|
|
||||||
|
MonetaryCurrency currency = new MonetaryCurrency(command.getCurrencyCode(), command.getDigitsAfterDecimal());
|
||||||
|
|
||||||
|
final BigDecimal defaultNominalInterestRatePerPeriod = BigDecimal.valueOf(command.getInterestRatePerPeriod().doubleValue());
|
||||||
|
final PeriodFrequencyType interestPeriodFrequencyType = PeriodFrequencyType.fromInt(command.getInterestRateFrequencyMethod());
|
||||||
|
|
||||||
|
BigDecimal defaultAnnualNominalInterestRate = aprCalculator.calculateFrom(interestPeriodFrequencyType, command.getInterestRatePerPeriod());
|
||||||
|
|
||||||
|
final InterestMethod interestMethod = InterestMethod.fromInt(command.getInterestMethod());
|
||||||
|
final InterestCalculationPeriodMethod interestCalculationPeriodMethod = InterestCalculationPeriodMethod.fromInt(command.getInterestCalculationPeriodMethod());
|
||||||
|
|
||||||
|
final Integer repayEvery = command.getRepaymentEvery();
|
||||||
|
final PeriodFrequencyType repaymentFrequencyType = PeriodFrequencyType.fromInt(command.getRepaymentFrequency());
|
||||||
|
final Integer defaultNumberOfInstallments = command.getNumberOfRepayments();
|
||||||
|
final AmortizationMethod amortizationMethod = AmortizationMethod.fromInt(command.getAmortizationMethod());
|
||||||
|
final boolean flexibleRepaymentSchedule = command.isFlexibleRepaymentSchedule();
|
||||||
|
final boolean interestRebateAllowed = command.isInterestRebateAllowed();
|
||||||
|
|
||||||
|
LoanProductRelatedDetail loanRepaymentScheduleDetail = new LoanProductRelatedDetail(currency,
|
||||||
|
command.getPrincipal(), defaultNominalInterestRatePerPeriod, interestPeriodFrequencyType, defaultAnnualNominalInterestRate,
|
||||||
|
interestMethod, interestCalculationPeriodMethod,
|
||||||
|
repayEvery, repaymentFrequencyType, defaultNumberOfInstallments, amortizationMethod, command.getInArrearsToleranceAmount(),
|
||||||
|
flexibleRepaymentSchedule, interestRebateAllowed);
|
||||||
|
|
||||||
|
LoanSchedule loanSchedule = command.getLoanSchedule();
|
||||||
|
List<ScheduledLoanInstallment> loanRepaymentSchedule = loanSchedule.getScheduledLoanInstallments();
|
||||||
|
|
||||||
|
Loan loan = Loan.createNew(currentUser.getOrganisation(), loanProduct, client, loanRepaymentScheduleDetail);
|
||||||
|
|
||||||
|
for (ScheduledLoanInstallment scheduledLoanInstallment : loanRepaymentSchedule) {
|
||||||
|
|
||||||
|
MoneyData readPrincipalDue = scheduledLoanInstallment.getPrincipalDue();
|
||||||
|
MoneyData readInterestDue = scheduledLoanInstallment.getInterestDue();
|
||||||
|
|
||||||
|
LoanRepaymentScheduleInstallment installment = new LoanRepaymentScheduleInstallment(
|
||||||
|
loan, scheduledLoanInstallment.getInstallmentNumber(),
|
||||||
|
scheduledLoanInstallment.getPeriodStart(),
|
||||||
|
scheduledLoanInstallment.getPeriodEnd(), readPrincipalDue.getAmount(),
|
||||||
|
readInterestDue.getAmount());
|
||||||
|
loan.addRepaymentScheduleInstallment(installment);
|
||||||
|
}
|
||||||
|
|
||||||
|
loan.submitApplication(submittedOn, command.getExpectedDisbursementDate(), command.getRepaymentsStartingFromDate(), command.getInterestCalculatedFromDate(), defaultLoanLifecycleStateMachine());
|
||||||
|
this.loanRepository.save(loan);
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(command.getSubmittedOnNote())) {
|
||||||
|
Note note = Note.loanNote(currentUser.getOrganisation(), loan, command.getSubmittedOnNote());
|
||||||
|
this.noteRepository.save(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new EntityIdentifier(loan.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public EntityIdentifier deleteLoan(Long loanId) {
|
||||||
|
|
||||||
|
AppUser currentUser = context.authenticatedUser();
|
||||||
|
|
||||||
|
Loan loan = this.loanRepository.findOne(loansThatMatch(currentUser.getOrganisation(), loanId));
|
||||||
|
if (loan == null) {
|
||||||
|
throw new PlatformResourceNotFoundException("error.msg.loan.id.invalid", "Loan with identifier {0} does not exist", loanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loan.isNotSubmittedAndPendingApproval()) {
|
||||||
|
throw new PlatformDomainRuleException("error.msg.cannot.delete.loan.in.its.present.state", "Loan with identifier {0} cannot be deleted in its current state.", loanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Long clientId = loan.getClient().getId();
|
||||||
|
|
||||||
|
List<Note> relatedNotes = this.noteRepository.findByLoanId(loan.getId());
|
||||||
|
this.noteRepository.deleteInBatch(relatedNotes);
|
||||||
|
|
||||||
|
this.loanRepository.delete(loanId);
|
||||||
|
|
||||||
|
return new EntityIdentifier(clientId);
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
-12
@@ -1,12 +1,12 @@
|
|||||||
package org.mifosng.platform;
|
package org.mifosng.platform.loan.service;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.mifosng.data.ErrorResponse;
|
import org.mifosng.data.ApiParameterError;
|
||||||
import org.mifosng.data.command.CalculateLoanScheduleCommand;
|
import org.mifosng.data.command.CalculateLoanScheduleCommand;
|
||||||
import org.mifosng.data.command.SubmitLoanApplicationCommand;
|
import org.mifosng.data.command.SubmitLoanApplicationCommand;
|
||||||
import org.mifosng.platform.exceptions.NewDataValidationException;
|
import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
|
||||||
|
|
||||||
public class SubmitLoanApplicationCommandValidator {
|
public class SubmitLoanApplicationCommandValidator {
|
||||||
|
|
||||||
@@ -17,19 +17,23 @@ public class SubmitLoanApplicationCommandValidator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void validate() {
|
public void validate() {
|
||||||
List<ErrorResponse> dataValidationErrors = new ArrayList<ErrorResponse>();
|
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
|
|
||||||
if (command.getLoanSchedule() == null) {
|
if (command.getLoanSchedule() == null) {
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.submit.loan.loan.schedule.cannot.be.blank", "loanSchedule");
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.submit.loan.loan.schedule.cannot.be.blank",
|
||||||
|
"The parameter loanSchedule cannot be empty.", "loanSchedule");
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.getSubmittedOnDate() == null) {
|
if (command.getSubmittedOnDate() == null) {
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.loan.submitted.on.date.cannot.be.blank", "submittedOnDate");
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.loan.submitted.on.date.cannot.be.blank",
|
||||||
|
"The parameter submittedOnDateFormatted cannot be empty.", "submittedOnDateFormatted");
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
} else {
|
} else {
|
||||||
if (command.getSubmittedOnDate().isAfter(command.getExpectedDisbursementDate())) {
|
if (command.getSubmittedOnDate().isAfter(command.getExpectedDisbursementDate())) {
|
||||||
ErrorResponse error = new ErrorResponse("validation.msg.loan.submitted.on.date.cannot.be.after.expectedDisbursementDate", "submittedOnDate");
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.loan.submitted.on.date.cannot.be.after.expectedDisbursementDate",
|
||||||
|
"The date of parameter submittedOnDateFormatted cannot fall after the date given for expectedDisbursementDateFormatted.", "submittedOnDateFormatted",
|
||||||
|
command.getSubmittedOnDateFormatted(), command.getExpectedDisbursementDateFormatted());
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,8 +49,6 @@ public class SubmitLoanApplicationCommandValidator {
|
|||||||
command.getRepaymentFrequency(),
|
command.getRepaymentFrequency(),
|
||||||
command.getNumberOfRepayments(),
|
command.getNumberOfRepayments(),
|
||||||
command.getAmortizationMethod(),
|
command.getAmortizationMethod(),
|
||||||
command.isFlexibleRepaymentSchedule(),
|
|
||||||
command.isInterestRebateAllowed(),
|
|
||||||
command.getExpectedDisbursementDate(),
|
command.getExpectedDisbursementDate(),
|
||||||
command.getRepaymentsStartingFromDate(),
|
command.getRepaymentsStartingFromDate(),
|
||||||
command.getInterestCalculatedFromDate());
|
command.getInterestCalculatedFromDate());
|
||||||
@@ -54,12 +56,12 @@ public class SubmitLoanApplicationCommandValidator {
|
|||||||
CalculateLoanScheduleCommandValidator validator = new CalculateLoanScheduleCommandValidator(
|
CalculateLoanScheduleCommandValidator validator = new CalculateLoanScheduleCommandValidator(
|
||||||
calculateLoanScheduleCommand);
|
calculateLoanScheduleCommand);
|
||||||
validator.validate();
|
validator.validate();
|
||||||
} catch (NewDataValidationException e) {
|
} catch (PlatformApiDataValidationException e) {
|
||||||
dataValidationErrors.addAll(e.getValidationErrors());
|
dataValidationErrors.addAll(e.getErrors());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dataValidationErrors.isEmpty()) {
|
if (!dataValidationErrors.isEmpty()) {
|
||||||
throw new NewDataValidationException(dataValidationErrors, "Data validation errors exist.");
|
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-1
@@ -11,6 +11,8 @@ import org.mifosng.platform.loan.domain.AmortizationMethod;
|
|||||||
import org.mifosng.platform.loan.domain.InterestMethod;
|
import org.mifosng.platform.loan.domain.InterestMethod;
|
||||||
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
|
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
|
||||||
|
|
||||||
|
// FIXME - There is a lot of common validation across parameters for LoanProduct create/update, loan schedule calculation and submit new loan application flows.
|
||||||
|
// - reduce duplicator across this validators.
|
||||||
public class LoanProductCommandValidator {
|
public class LoanProductCommandValidator {
|
||||||
|
|
||||||
public void validateForUpdate(LoanProductCommand command) {
|
public void validateForUpdate(LoanProductCommand command) {
|
||||||
@@ -67,7 +69,6 @@ public class LoanProductCommandValidator {
|
|||||||
ApiParameterError error = ApiParameterError.parameterError("validation.msg.product.principal.amount.must.be.greater.than.zero", "The parameter amount must be greater than zero.", "amount");
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.product.principal.amount.must.be.greater.than.zero", "The parameter amount must be greater than zero.", "amount");
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
}
|
}
|
||||||
// TODO - check number of digits before decimal and after decimal
|
|
||||||
} else {
|
} else {
|
||||||
ApiParameterError error = ApiParameterError.parameterError("validation.msg.product.principal.amount.cannot.be.empty", "The parameter amount cannot be blank.", "amount");
|
ApiParameterError error = ApiParameterError.parameterError("validation.msg.product.principal.amount.cannot.be.empty", "The parameter amount cannot be blank.", "amount");
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
|
|||||||
@@ -17,13 +17,19 @@ import org.joda.time.format.DateTimeFormatter;
|
|||||||
import org.joda.time.format.ISODateTimeFormat;
|
import org.joda.time.format.ISODateTimeFormat;
|
||||||
import org.mifosng.data.LoanPayoffReadModel;
|
import org.mifosng.data.LoanPayoffReadModel;
|
||||||
import org.mifosng.data.MoneyData;
|
import org.mifosng.data.MoneyData;
|
||||||
import org.mifosng.platform.CalculationPlatformService;
|
import org.mifosng.platform.loan.service.CalculationPlatformService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.sun.jersey.api.json.JSONWithPadding;
|
import com.sun.jersey.api.json.JSONWithPadding;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Payoff functionality was something CreoCore was looking for e.g. if paid in full on date x what should be paid? full minus any rebate or incentive provided.
|
||||||
|
*
|
||||||
|
* NOTE: JSONP functionality not needed now due to use of CORS
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
@Path("/open/loan/{loanId}")
|
@Path("/open/loan/{loanId}")
|
||||||
@Component
|
@Component
|
||||||
@Scope("singleton")
|
@Scope("singleton")
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.DELETE;
|
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.POST;
|
import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
@@ -20,15 +19,11 @@ import org.mifosng.data.EntityIdentifier;
|
|||||||
import org.mifosng.data.ErrorResponse;
|
import org.mifosng.data.ErrorResponse;
|
||||||
import org.mifosng.data.ErrorResponseList;
|
import org.mifosng.data.ErrorResponseList;
|
||||||
import org.mifosng.data.LoanRepaymentData;
|
import org.mifosng.data.LoanRepaymentData;
|
||||||
import org.mifosng.data.LoanSchedule;
|
|
||||||
import org.mifosng.data.command.AdjustLoanTransactionCommand;
|
import org.mifosng.data.command.AdjustLoanTransactionCommand;
|
||||||
import org.mifosng.data.command.CalculateLoanScheduleCommand;
|
|
||||||
import org.mifosng.data.command.LoanStateTransitionCommand;
|
import org.mifosng.data.command.LoanStateTransitionCommand;
|
||||||
import org.mifosng.data.command.LoanTransactionCommand;
|
import org.mifosng.data.command.LoanTransactionCommand;
|
||||||
import org.mifosng.data.command.SubmitLoanApplicationCommand;
|
|
||||||
import org.mifosng.data.command.UndoLoanApprovalCommand;
|
import org.mifosng.data.command.UndoLoanApprovalCommand;
|
||||||
import org.mifosng.data.command.UndoLoanDisbursalCommand;
|
import org.mifosng.data.command.UndoLoanDisbursalCommand;
|
||||||
import org.mifosng.platform.CalculationPlatformService;
|
|
||||||
import org.mifosng.platform.ReadPlatformService;
|
import org.mifosng.platform.ReadPlatformService;
|
||||||
import org.mifosng.platform.ReadPlatformServiceImpl;
|
import org.mifosng.platform.ReadPlatformServiceImpl;
|
||||||
import org.mifosng.platform.WritePlatformService;
|
import org.mifosng.platform.WritePlatformService;
|
||||||
@@ -49,92 +44,12 @@ public class LoanResource {
|
|||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(ReadPlatformServiceImpl.class);
|
private final static Logger logger = LoggerFactory.getLogger(ReadPlatformServiceImpl.class);
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private CalculationPlatformService calculationPlatformService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ReadPlatformService readPlatformService;
|
private ReadPlatformService readPlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private WritePlatformService writePlatformService;
|
private WritePlatformService writePlatformService;
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("calculate")
|
|
||||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
|
||||||
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
|
|
||||||
public Response calculateLoanSchedule(final CalculateLoanScheduleCommand command) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
LoanSchedule loanSchedule = this.calculationPlatformService.calculateLoanSchedule(command);
|
|
||||||
|
|
||||||
return Response.ok().entity(loanSchedule).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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("new")
|
|
||||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
|
||||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
|
||||||
public Response submitLoanApplication(final SubmitLoanApplicationCommand command) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
EntityIdentifier identifier = this.writePlatformService.submitLoanApplication(command);
|
|
||||||
|
|
||||||
return Response.ok().entity(identifier).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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@DELETE
|
|
||||||
@Path("{loanId}")
|
|
||||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
|
||||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
|
||||||
public Response deleteLoanApplication(@PathParam("loanId") final Long loanId) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
EntityIdentifier identifier = this.writePlatformService.deleteLoan(loanId);
|
|
||||||
|
|
||||||
return Response.ok().entity(identifier).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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path("approve")
|
@Path("approve")
|
||||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||||
|
|||||||
Reference in New Issue
Block a user