support basic operations on fund concept and associating as optional with loan product.

This commit is contained in:
Keith Woodlock
2012-07-11 09:37:34 +01:00
parent 21d5a4cc1a
commit 855adc27ef
12 changed files with 142 additions and 140 deletions
@@ -9,7 +9,6 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@@ -18,7 +17,6 @@ import javax.ws.rs.core.UriInfo;
import org.mifosng.platform.api.commands.FundCommand;
import org.mifosng.platform.api.data.EntityIdentifier;
import org.mifosng.platform.api.data.FundData;
import org.mifosng.platform.api.infrastructure.ApiDataConversionService;
import org.mifosng.platform.api.infrastructure.ApiJSONFormattingService;
import org.mifosng.platform.fund.service.FundReadPlatformService;
import org.mifosng.platform.fund.service.FundWritePlatformService;
@@ -31,7 +29,6 @@ import org.springframework.stereotype.Component;
@Scope("singleton")
public class FundsApiResource {
private String defaultFieldList = "openingDate";
private String allowedFieldList = "allowedParents";
private String filterName = "myFilter";
@@ -41,9 +38,6 @@ public class FundsApiResource {
@Autowired
private FundWritePlatformService writePlatformService;
@Autowired
private ApiDataConversionService apiDataConversionService;
@Autowired
private ApiJSONFormattingService jsonFormattingService;
@@ -63,11 +57,6 @@ public class FundsApiResource {
@Produces({ MediaType.APPLICATION_JSON })
public Response createFund(final FundCommand command) {
// LocalDate openingLocalDate = apiDataConversionService.convertFrom(
// command.getOpeningDate(), "openingDate",
// command.getDateFormat());
// command.setOpeningLocalDate(openingLocalDate);
Long fundId = this.writePlatformService.createFund(command);
return Response.ok().entity(new EntityIdentifier(fundId)).build();
@@ -77,14 +66,9 @@ public class FundsApiResource {
@Path("{fundId}")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON })
public String retreiveOffice(@PathParam("fundId") final Long fundId,
@QueryParam("template") String template, @Context UriInfo uriInfo) {
public String retreiveOffice(@PathParam("fundId") final Long fundId, @Context UriInfo uriInfo) {
FundData fund = this.readPlatformService.retrieveFund(fundId);
// if (template != null && template.equalsIgnoreCase("true")) {
// office.setAllowedParents(this.readPlatformService
// .retrieveAllowedParents(officeId));
// }
String selectedFields = "";
return this.jsonFormattingService.convertRequest(fund, filterName,
@@ -95,13 +79,8 @@ public class FundsApiResource {
@Path("{fundId}")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON })
public Response updateOffice(@PathParam("fundId") final Long fundId,
final FundCommand command) {
public Response updateFund(@PathParam("fundId") final Long fundId, final FundCommand command) {
// LocalDate openingLocalDate = apiDataConversionService.convertFrom(
// command.getOpeningDate(), "openingDate",
// command.getDateFormat());
// command.setOpeningLocalDate(openingLocalDate);
command.setId(fundId);
Long entityId = this.writePlatformService.updateFund(command);
@@ -2,8 +2,6 @@ package org.mifosng.platform.api.commands;
import javax.xml.bind.annotation.XmlRootElement;
import org.joda.time.LocalDate;
/**
* Command used for create and update fund operations.
*/
@@ -14,13 +12,6 @@ public class FundCommand {
private String name;
private String externalId;
private String dateFormat;
private String activatedOnDate;
private LocalDate activatedOnLocalDate;
private String deactivatedOnDate;
private LocalDate deactivatedOnLocalDate;
protected FundCommand() {
//
}
@@ -53,44 +44,4 @@ public class FundCommand {
public void setExternalId(String externalId) {
this.externalId = externalId;
}
public String getDateFormat() {
return dateFormat;
}
public void setDateFormat(String dateFormat) {
this.dateFormat = dateFormat;
}
public String getActivatedOnDate() {
return activatedOnDate;
}
public void setActivatedOnDate(String activatedOnDate) {
this.activatedOnDate = activatedOnDate;
}
public LocalDate getActivatedOnLocalDate() {
return activatedOnLocalDate;
}
public void setActivatedOnLocalDate(LocalDate activatedOnLocalDate) {
this.activatedOnLocalDate = activatedOnLocalDate;
}
public String getDeactivatedOnDate() {
return deactivatedOnDate;
}
public void setDeactivatedOnDate(String deactivatedOnDate) {
this.deactivatedOnDate = deactivatedOnDate;
}
public LocalDate getDeactivatedOnLocalDate() {
return deactivatedOnLocalDate;
}
public void setDeactivatedOnLocalDate(LocalDate deactivatedOnLocalDate) {
this.deactivatedOnLocalDate = deactivatedOnLocalDate;
}
}
@@ -12,6 +12,8 @@ public class LoanProductCommand {
private String description;
private String externalId;
private Long fundId;
private String locale;
private String currencyCode;
private String digitsAfterDecimal;
@@ -223,4 +225,12 @@ public class LoanProductCommand {
Integer interestCalculationPeriodType) {
this.interestCalculationPeriodType = interestCalculationPeriodType;
}
public Long getFundId() {
return fundId;
}
public void setFundId(Long fundId) {
this.fundId = fundId;
}
}
@@ -3,6 +3,7 @@ package org.mifosng.platform.api.data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.codehaus.jackson.map.annotate.JsonFilter;
@@ -15,6 +16,8 @@ public class LoanProductData implements Serializable {
private String name;
private String description;
private FundData fund;
private MoneyData principal;
private MoneyData inArrearsTolerance;
@@ -33,12 +36,14 @@ public class LoanProductData implements Serializable {
private DateTime lastModifedOn;
private List<CurrencyData> currencyOptions = new ArrayList<CurrencyData>();
private Collection<FundData> fundOptions = new ArrayList<FundData>();
private List<EnumOptionData> amortizationTypeOptions = new ArrayList<EnumOptionData>();
private List<EnumOptionData> interestTypeOptions = new ArrayList<EnumOptionData>();
private List<EnumOptionData> interestCalculationPeriodTypeOptions = new ArrayList<EnumOptionData>();
private List<EnumOptionData> repaymentFrequencyTypeOptions = new ArrayList<EnumOptionData>();
private List<EnumOptionData> interestRateFrequencyTypeOptions = new ArrayList<EnumOptionData>();
public LoanProductData() {
//
}
@@ -52,7 +57,7 @@ public class LoanProductData implements Serializable {
EnumOptionData interestRateFrequencyType,
EnumOptionData amortizationType,
EnumOptionData interestType,
EnumOptionData interestCalculationPeriodType) {
EnumOptionData interestCalculationPeriodType, FundData fund) {
this.createdOn = createdOn;
this.lastModifedOn = lastModifedOn;
this.id = id;
@@ -69,6 +74,7 @@ public class LoanProductData implements Serializable {
this.amortizationType = amortizationType;
this.interestType = interestType;
this.interestCalculationPeriodType = interestCalculationPeriodType;
this.fund = fund;
}
public Long getId() {
@@ -94,6 +100,14 @@ public class LoanProductData implements Serializable {
public void setDescription(String description) {
this.description = description;
}
public FundData getFund() {
return fund;
}
public void setFund(FundData fund) {
this.fund = fund;
}
public MoneyData getPrincipal() {
return principal;
@@ -226,6 +240,14 @@ public class LoanProductData implements Serializable {
public void setCurrencyOptions(List<CurrencyData> currencyOptions) {
this.currencyOptions = currencyOptions;
}
public Collection<FundData> getFundOptions() {
return fundOptions;
}
public void setFundOptions(Collection<FundData> fundOptions) {
this.fundOptions = fundOptions;
}
public List<EnumOptionData> getAmortizationTypeOptions() {
return amortizationTypeOptions;
@@ -1,15 +1,11 @@
package org.mifosng.platform.fund.domain;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;
import org.mifosng.platform.api.commands.FundCommand;
import org.mifosng.platform.infrastructure.AbstractAuditableCustom;
@@ -17,7 +13,10 @@ import org.mifosng.platform.organisation.domain.Organisation;
import org.mifosng.platform.user.domain.AppUser;
@Entity
@Table(name = "org_fund")
@Table(name = "org_fund", uniqueConstraints={
@UniqueConstraint(columnNames = {"org_id", "name"}, name="fund_name_org"),
@UniqueConstraint(columnNames = {"org_id", "external_id"}, name="fund_externalid_org")
})
public class Fund extends AbstractAuditableCustom<AppUser, Long> {
@ManyToOne
@@ -30,17 +29,6 @@ public class Fund extends AbstractAuditableCustom<AppUser, Long> {
@Column(name = "external_id", length=100)
private String externalId;
@Temporal(TemporalType.DATE)
@Column(name = "activatedon_date")
private Date activatedOnDate;
@Temporal(TemporalType.DATE)
@Column(name = "deactivatedon_date")
private Date deactivatedOnDate;
@Column(name = "initial_balance", scale = 6, precision = 19)
private BigDecimal initialBalance;
public static Fund createNew(final Organisation organisation, final String fundName) {
return new Fund(organisation, fundName);
}
@@ -52,7 +40,6 @@ public class Fund extends AbstractAuditableCustom<AppUser, Long> {
private Fund(final Organisation organisation, final String fundName) {
this.organisation = organisation;
this.name = fundName;
this.initialBalance = BigDecimal.ZERO;
}
public void update(FundCommand command) {
@@ -22,11 +22,9 @@ public class FundCommandValidator {
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("fund");
// baseDataValidator.reset().parameter("name").value(command.getName()).notBlank();
// baseDataValidator.reset().parameter("openingDate").value(command.getOpeningDate()).notBlank();
// baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).notExceedingLengthOf(100);
// baseDataValidator.reset().parameter("parentId").value(command.getParentId()).notNull().greaterThanZero();
//
baseDataValidator.reset().parameter("name").value(command.getName()).notBlank();
baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).notExceedingLengthOf(100);
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
}
@@ -36,15 +34,13 @@ public class FundCommandValidator {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("fund");
//
// baseDataValidator.reset().parameter("id").value(command.getId()).notNull();
// baseDataValidator.reset().parameter("name").value(command.getName()).ignoreIfNull().notBlank();
// baseDataValidator.reset().parameter("openingDate").value(command.getOpeningDate()).ignoreIfNull().notBlank();
// baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100);
// baseDataValidator.reset().parameter("parentId").value(command.getParentId()).ignoreIfNull().notNull().greaterThanZero();
//
// baseDataValidator.reset().anyOfNotNull(command.getName(), command.getOpeningDate(), command.getExternalId(), command.getParentId());
//
baseDataValidator.reset().parameter("id").value(command.getId()).notNull();
baseDataValidator.reset().parameter("name").value(command.getName()).ignoreIfNull().notBlank();
baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100);
baseDataValidator.reset().anyOfNotNull(command.getName(), command.getExternalId());
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
}
@@ -42,7 +42,6 @@ public class FundReadPlatformServiceImpl implements FundReadPlatformService {
Long id = rs.getLong("id");
String name = rs.getString("name");
String externalId = rs.getString("externalId");
// LocalDate openingDate = JdbcSupport.getLocalDate(rs, "openingDate");
return new FundData(id, name, externalId);
}
@@ -83,13 +83,13 @@ public class FundWritePlatformServiceJpaRepositoryImpl implements FundWritePlatf
private void handleFundDataIntegrityIssues(final FundCommand command, DataIntegrityViolationException dve) {
Throwable realCause = dve.getMostSpecificCause();
if (realCause.getMessage().contains("externalid_org")) {
throw new PlatformDataIntegrityException("error.msg.office.duplicate.externalId", "Office with externalId {0} already exists", "externalId", command.getExternalId());
} else if (realCause.getMessage().contains("name_org")) {
throw new PlatformDataIntegrityException("error.msg.office.duplicate.name", "Office with name {0} already exists", "name", command.getName());
if (realCause.getMessage().contains("fund_externalid_org")) {
throw new PlatformDataIntegrityException("error.msg.fund.duplicate.externalId", "Fund with externalId {0} already exists", "externalId", command.getExternalId());
} else if (realCause.getMessage().contains("fund_name_org")) {
throw new PlatformDataIntegrityException("error.msg.fund.duplicate.name", "Fund with name {0} already exists", "name", command.getName());
}
logger.error(dve.getMessage(), dve);
throw new PlatformDataIntegrityException("error.msg.office.unknown.data.integrity.issue", "Unknown data integrity issue with resource.");
throw new PlatformDataIntegrityException("error.msg.fund.unknown.data.integrity.issue", "Unknown data integrity issue with resource: " + realCause.getMessage());
}
}
@@ -13,6 +13,7 @@ import org.apache.commons.lang.StringUtils;
import org.mifosng.platform.api.commands.LoanProductCommand;
import org.mifosng.platform.currency.domain.MonetaryCurrency;
import org.mifosng.platform.currency.domain.Money;
import org.mifosng.platform.fund.domain.Fund;
import org.mifosng.platform.infrastructure.AbstractAuditableCustom;
import org.mifosng.platform.organisation.domain.Organisation;
import org.mifosng.platform.user.domain.AppUser;
@@ -29,32 +30,38 @@ import org.mifosng.platform.user.domain.AppUser;
@Table(name = "portfolio_product_loan")
public class LoanProduct extends AbstractAuditableCustom<AppUser, Long> {
@ManyToOne
@JoinColumn(name = "org_id", nullable = false)
private final Organisation organisation;
@ManyToOne
@JoinColumn(name = "org_id", nullable = false)
private final Organisation organisation;
@Column(name = "name", nullable = false)
private String name;
@ManyToOne
@JoinColumn(name = "fund_id", nullable = true)
private Fund fund;
@Column(name = "description")
private String description;
@Column(name = "name", nullable = false)
private String name;
@Embedded
private final LoanProductRelatedDetail loanProductRelatedDetail;
@Column(name = "description")
private String description;
@Embedded
private final LoanProductRelatedDetail loanProductRelatedDetail;
public LoanProduct() {
this.organisation = null;
this.fund = null;
this.name = null;
this.description = null;
this.loanProductRelatedDetail = null;
}
public LoanProduct(final Organisation organisation, final String name, final String description, final MonetaryCurrency currency, final BigDecimal defaultPrincipal,
public LoanProduct(final Organisation organisation, Fund fund, final String name, final String description, final MonetaryCurrency currency, final BigDecimal defaultPrincipal,
final BigDecimal defaultNominalInterestRatePerPeriod, final PeriodFrequencyType interestPeriodFrequencyType, final BigDecimal defaultAnnualNominalInterestRate,
final InterestMethod interestMethod, final InterestCalculationPeriodMethod interestCalculationPeriodMethod,
final Integer repayEvery, final PeriodFrequencyType repaymentFrequencyType, final Integer defaultNumberOfInstallments, final AmortizationMethod amortizationMethod,
final BigDecimal inArrearsTolerance) {
this.organisation = organisation;
this.fund = fund;
this.name = name.trim();
if (StringUtils.isNotBlank(description)) {
this.description = description.trim();
@@ -132,13 +139,17 @@ public class LoanProduct extends AbstractAuditableCustom<AppUser, Long> {
return this.loanProductRelatedDetail.getAmortizationMethod();
}
public void update(LoanProductCommand command) {
public void update(final LoanProductCommand command, final Fund fund) {
if (command.getName() != null) {
this.name = command.getName();
}
if (command.getDescription() != null) {
this.description = command.getDescription();
}
if (fund != null) {
this.fund = fund;
}
this.loanProductRelatedDetail.update(command);
}
}
@@ -44,7 +44,7 @@ public class LoanProductCommandValidator {
baseDataValidator.reset().parameter("interestType").value(command.getInterestType()).ignoreIfNull().notNull().inMinMaxRange(0, 1);
baseDataValidator.reset().parameter("interestCalculationPeriodType").value(command.getInterestCalculationPeriodType()).ignoreIfNull().notNull().inMinMaxRange(0, 1);
baseDataValidator.reset().anyOfNotNull(command.getName(), command.getDescription(), command.getExternalId(), command.getCurrencyCode(), command.getDigitsAfterDecimal(),
baseDataValidator.reset().anyOfNotNull(command.getFundId(), command.getName(), command.getDescription(), command.getExternalId(), command.getCurrencyCode(), command.getDigitsAfterDecimal(),
command.getPrincipal(), command.getInArrearsTolerance(), command.getRepaymentFrequencyType(), command.getRepaymentEvery(), command.getNumberOfRepayments(),
command.getInterestRatePerPeriod(), command.getInterestRateFrequencyType(), command.getAmortizationType(), command.getInterestType(), command.getInterestCalculationPeriodType());
@@ -11,11 +11,13 @@ import javax.sql.DataSource;
import org.joda.time.DateTime;
import org.mifosng.platform.api.data.CurrencyData;
import org.mifosng.platform.api.data.EnumOptionData;
import org.mifosng.platform.api.data.FundData;
import org.mifosng.platform.api.data.LoanProductData;
import org.mifosng.platform.api.data.LoanProductLookup;
import org.mifosng.platform.api.data.MoneyData;
import org.mifosng.platform.currency.service.CurrencyReadPlatformService;
import org.mifosng.platform.exceptions.LoanProductNotFoundException;
import org.mifosng.platform.fund.service.FundReadPlatformService;
import org.mifosng.platform.infrastructure.JdbcSupport;
import org.mifosng.platform.loan.domain.AmortizationMethod;
import org.mifosng.platform.loan.domain.InterestCalculationPeriodMethod;
@@ -37,15 +39,18 @@ public class LoanProductReadPlatformServiceImpl implements
private final CurrencyReadPlatformService currencyReadPlatformService;
private final SimpleJdbcTemplate jdbcTemplate;
private final LoanDropdownReadPlatformService dropdownReadPlatformService;
private final FundReadPlatformService fundReadPlatformService;
@Autowired
public LoanProductReadPlatformServiceImpl(
final PlatformSecurityContext context,
final CurrencyReadPlatformService currencyReadPlatformService,
final FundReadPlatformService fundReadPlatformService,
final LoanDropdownReadPlatformService dropdownReadPlatformService,
final DataSource dataSource) {
this.context = context;
this.currencyReadPlatformService = currencyReadPlatformService;
this.fundReadPlatformService = fundReadPlatformService;
this.dropdownReadPlatformService = dropdownReadPlatformService;
this.jdbcTemplate = new SimpleJdbcTemplate(dataSource);
}
@@ -56,8 +61,10 @@ public class LoanProductReadPlatformServiceImpl implements
try {
List<CurrencyData> allowedCurrencies = currencyReadPlatformService
.retrieveAllPlatformCurrencies();
Collection<FundData> allFunds = this.fundReadPlatformService.retrieveAllFunds();
LoanProductMapper rm = new LoanProductMapper(allowedCurrencies);
LoanProductMapper rm = new LoanProductMapper(allowedCurrencies, allFunds);
String sql = "select " + rm.loanProductSchema()
+ " where lp.id = ?";
@@ -76,11 +83,12 @@ public class LoanProductReadPlatformServiceImpl implements
public Collection<LoanProductData> retrieveAllLoanProducts() {
AppUser currentUser = this.context.authenticatedUser();
// TODO - include currency read in the sql
List<CurrencyData> allowedCurrencies = currencyReadPlatformService
.retrieveAllPlatformCurrencies();
List<CurrencyData> allowedCurrencies = currencyReadPlatformService.retrieveAllPlatformCurrencies();
Collection<FundData> allFunds = this.fundReadPlatformService.retrieveAllFunds();
LoanProductMapper rm = new LoanProductMapper(allowedCurrencies);
LoanProductMapper rm = new LoanProductMapper(allowedCurrencies, allFunds);
String sql = "select " + rm.loanProductSchema()
+ " where lp.org_id = ?";
@@ -132,17 +140,18 @@ public class LoanProductReadPlatformServiceImpl implements
return productData;
}
private static final class LoanProductMapper implements
RowMapper<LoanProductData> {
private static final class LoanProductMapper implements RowMapper<LoanProductData> {
private final List<CurrencyData> allowedCurrencies;
private final Collection<FundData> allFunds;
public LoanProductMapper(List<CurrencyData> allowedCurrencies) {
public LoanProductMapper(List<CurrencyData> allowedCurrencies, Collection<FundData> allFunds) {
this.allowedCurrencies = allowedCurrencies;
this.allFunds = allFunds;
}
public String loanProductSchema() {
return "lp.id as id, lp.name as name, lp.description as description, lp.flexible_repayment_schedule as isFlexible, lp.interest_rebate as isInterestRebateAllowed, "
return "lp.id as id, lp.fund_id as fundId, lp.name as name, lp.description as description, lp.flexible_repayment_schedule as isFlexible, lp.interest_rebate as isInterestRebateAllowed, "
+ "lp.principal_amount as principal, lp.currency_code as currencyCode, lp.currency_digits as currencyDigits, "
+ "lp.nominal_interest_rate_per_period as interestRatePerPeriod, lp.interest_period_frequency_enum as interestRatePerPeriodFreq, "
+ "lp.annual_nominal_interest_rate as annualInterestRate, lp.interest_method_enum as interestMethod, lp.interest_calculated_in_period_enum as interestCalculationInPeriodMethod,"
@@ -160,6 +169,9 @@ public class LoanProductReadPlatformServiceImpl implements
String name = rs.getString("name");
String description = rs.getString("description");
Long fundId = rs.getLong("fundId");
FundData fund = findFundDataById(fundId, allFunds);
String currencyCode = rs.getString("currencyCode");
Integer currencyDigits = JdbcSupport.getInteger(rs,
"currencyDigits");
@@ -216,11 +228,20 @@ public class LoanProductReadPlatformServiceImpl implements
numberOfRepayments, repaymentEvery, interestRatePerPeriod,
annualInterestRate, repaymentFrequencyType,
interestRateFrequencyType, amortizationType, interestType,
interestCalculationPeriodType);
interestCalculationPeriodType, fund);
}
private CurrencyData findCurrencyByCode(String currencyCode,
List<CurrencyData> allowedCurrencies) {
private FundData findFundDataById(Long fundId, Collection<FundData> allFunds) {
FundData match = null;
for (FundData fundData : allFunds) {
if (fundData.getId().equals(fundId)) {
match = fundData;
}
}
return match;
}
private CurrencyData findCurrencyByCode(String currencyCode, List<CurrencyData> allowedCurrencies) {
CurrencyData match = null;
for (CurrencyData currencyData : allowedCurrencies) {
if (currencyData.getCode().equalsIgnoreCase(currencyCode)) {
@@ -251,8 +272,7 @@ public class LoanProductReadPlatformServiceImpl implements
}
private void populateProductDataWithDropdownOptions(
LoanProductData productData) {
private void populateProductDataWithDropdownOptions(LoanProductData productData) {
List<CurrencyData> currencyOptions = currencyReadPlatformService
.retrieveAllowedCurrencies();
@@ -266,6 +286,8 @@ public class LoanProductReadPlatformServiceImpl implements
.retrieveRepaymentFrequencyTypeOptions();
List<EnumOptionData> interestRateFrequencyTypeOptions = dropdownReadPlatformService
.retrieveInterestRateFrequencyTypeOptions();
Collection<FundData> fundOptions = this.fundReadPlatformService.retrieveAllFunds();
productData.setCurrencyOptions(currencyOptions);
productData.setAmortizationTypeOptions(amortizationTypeOptions);
@@ -276,6 +298,7 @@ public class LoanProductReadPlatformServiceImpl implements
.setRepaymentFrequencyTypeOptions(repaymentFrequencyTypeOptions);
productData
.setInterestRateFrequencyTypeOptions(interestRateFrequencyTypeOptions);
productData.setFundOptions(fundOptions);
}
}
@@ -1,13 +1,16 @@
package org.mifosng.platform.loanproduct.service;
import static org.mifosng.platform.Specifications.productThatMatches;
import static org.mifosng.platform.Specifications.*;
import java.math.BigDecimal;
import org.mifosng.platform.api.commands.LoanProductCommand;
import org.mifosng.platform.api.data.EntityIdentifier;
import org.mifosng.platform.currency.domain.MonetaryCurrency;
import org.mifosng.platform.exceptions.FundNotFoundException;
import org.mifosng.platform.exceptions.LoanProductNotFoundException;
import org.mifosng.platform.fund.domain.Fund;
import org.mifosng.platform.fund.domain.FundRepository;
import org.mifosng.platform.loan.domain.AmortizationMethod;
import org.mifosng.platform.loan.domain.InterestCalculationPeriodMethod;
import org.mifosng.platform.loan.domain.InterestMethod;
@@ -15,6 +18,7 @@ import org.mifosng.platform.loan.domain.LoanProduct;
import org.mifosng.platform.loan.domain.LoanProductRepository;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosng.platform.loanschedule.domain.AprCalculator;
import org.mifosng.platform.organisation.domain.Organisation;
import org.mifosng.platform.security.PlatformSecurityContext;
import org.mifosng.platform.user.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired;
@@ -27,12 +31,15 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
private final PlatformSecurityContext context;
private final LoanProductRepository loanProductRepository;
private final AprCalculator aprCalculator;
private final FundRepository fundRepository;
@Autowired
public LoanProductWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final LoanProductRepository loanProductRepository, final AprCalculator aprCalculator) {
public LoanProductWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final LoanProductRepository loanProductRepository,
final AprCalculator aprCalculator, final FundRepository fundRepository) {
this.context = context;
this.loanProductRepository = loanProductRepository;
this.aprCalculator = aprCalculator;
this.fundRepository = fundRepository;
}
@Transactional
@@ -60,7 +67,10 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
BigDecimal annualInterestRate = this.aprCalculator.calculateFrom(interestFrequencyType, command.getInterestRatePerPeriodValue());
LoanProduct loanproduct = new LoanProduct(currentUser.getOrganisation(), command.getName(), command.getDescription(),
// associating fund with loan product at creation is optional for now.
Fund fund = findFundByIdIfProvided(currentUser.getOrganisation(), command.getFundId());
LoanProduct loanproduct = new LoanProduct(currentUser.getOrganisation(), fund, command.getName(), command.getDescription(),
currency, command.getPrincipalValue(),
command.getInterestRatePerPeriodValue(), interestFrequencyType, annualInterestRate, interestMethod, interestCalculationPeriodMethod,
command.getRepaymentEveryValue(), repaymentFrequencyType, command.getNumberOfRepaymentsValue(),
@@ -71,6 +81,17 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
return new EntityIdentifier(loanproduct.getId());
}
private Fund findFundByIdIfProvided(final Organisation organisation, final Long fundId) {
Fund fund = null;
if (fundId != null) {
fund = this.fundRepository.findOne(fundsThatMatch(organisation, fundId));
if (fund == null) {
throw new FundNotFoundException(fundId);
}
}
return fund;
}
@Transactional
@Override
public EntityIdentifier updateLoanProduct(LoanProductCommand command) {
@@ -85,7 +106,10 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
throw new LoanProductNotFoundException(command.getId());
}
product.update(command);
// associating fund with loan product at creation is optional for now.
Fund fund = findFundByIdIfProvided(currentUser.getOrganisation(), command.getFundId());
product.update(command, fund);
this.loanProductRepository.save(product);