add relationship between loan product and the loan transaction processing strategy. its optional by default for loan product and loans. If no value selected it will default to the the 'Mifos style' repayment strategy which is pay off interest, then principal in all cases.

This commit is contained in:
Keith Woodlock
2012-07-30 13:01:13 +01:00
parent 864df5eeef
commit 97bf8e2f93
15 changed files with 268 additions and 50 deletions
@@ -63,6 +63,18 @@ CREATE TABLE `ref_loan_status` (
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `ref_loan_transaction_processing_strategy` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`code` varchar(100) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`createdby_id` bigint(20) DEFAULT NULL,
`created_date` datetime DEFAULT NULL,
`lastmodifiedby_id` bigint(20) DEFAULT NULL,
`lastmodified_date` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ltp_strategy_code` (`code`)
) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8;
-- DDL for organisation wide related concepts
CREATE TABLE `org_fund` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
@@ -216,6 +228,7 @@ CREATE TABLE `portfolio_client` (
CONSTRAINT `FKCE00CAB3E0DD567A` FOREIGN KEY (`office_id`) REFERENCES `org_office` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
CREATE TABLE `portfolio_product_loan` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`currency_code` varchar(3) NOT NULL,
@@ -225,6 +238,7 @@ CREATE TABLE `portfolio_product_loan` (
`name` varchar(100) NOT NULL,
`description` varchar(500) DEFAULT NULL,
`fund_id` bigint(20) DEFAULT NULL,
`loan_transaction_strategy_id` bigint(20) DEFAULT NULL,
`nominal_interest_rate_per_period` decimal(19,6) NOT NULL,
`interest_period_frequency_enum` smallint(5) NOT NULL,
`annual_nominal_interest_rate` decimal(19,6) NOT NULL,
@@ -244,6 +258,8 @@ CREATE TABLE `portfolio_product_loan` (
KEY `FKAUD0000000000003` (`createdby_id`),
KEY `FKAUD0000000000004` (`lastmodifiedby_id`),
KEY `FKA6A8A7D77240145` (`fund_id`),
KEY `FK_ltp_strategy` (`loan_transaction_strategy_id`),
CONSTRAINT `FK_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`),
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `org_fund` (`id`),
CONSTRAINT `FKAUD0000000000003` FOREIGN KEY (`createdby_id`) REFERENCES `admin_appuser` (`id`),
CONSTRAINT `FKAUD0000000000004` FOREIGN KEY (`lastmodifiedby_id`) REFERENCES `admin_appuser` (`id`)
@@ -0,0 +1,21 @@
-- add loan transactions processing table
CREATE TABLE `ref_loan_transaction_processing_strategy` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`code` varchar(100) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`createdby_id` bigint(20) DEFAULT NULL,
`created_date` datetime DEFAULT NULL,
`lastmodifiedby_id` bigint(20) DEFAULT NULL,
`lastmodified_date` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ltp_strategy_code` (`code`)
) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8;
ALTER TABLE `portfolio_product_loan`
ADD COLUMN `loan_transaction_strategy_id` bigint(20) DEFAULT NULL,
ADD KEY `FK_ltp_strategy` (`loan_transaction_strategy_id`),
ADD CONSTRAINT `FK_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`);
-- update ref table with out-of-the-box strategies
@@ -88,12 +88,14 @@ public class LoanProductsApiResource {
@Produces({MediaType.APPLICATION_JSON})
public String retrieveNewLoanProductDetails(@Context final UriInfo uriInfo) {
// TODO - KW - every addition of a parameter here requires same additon in supported params used in 'apiDataConversionService' method.
Set<String> typicalResponseParameters = new HashSet<String>(
Arrays.asList("id", "name", "description", "fundId", "fundName", "principal", "inArrearsTolerance", "numberOfRepayments",
Arrays.asList("id", "name", "description", "fundId", "fundName", "transactionProcessingStrategyId", "transactionProcessingStrategyName",
"principal", "inArrearsTolerance", "numberOfRepayments",
"repaymentEvery", "interestRatePerPeriod", "annualInterestRate",
"repaymentFrequencyType", "interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType",
"createdOn", "lastModifedOn","currencyOptions", "amortizationTypeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions",
"repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "fundOptions")
"repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "fundOptions", "transactionProcessingStrategyOptions")
);
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
@@ -114,7 +116,9 @@ public class LoanProductsApiResource {
public String retrieveLoanProductDetails(@PathParam("productId") final Long productId, @Context final UriInfo uriInfo) {
Set<String> typicalResponseParameters = new HashSet<String>(
Arrays.asList("id", "name", "description", "fundId", "fundName", "principal", "inArrearsTolerance", "numberOfRepayments",
Arrays.asList("id", "name", "description", "fundId", "fundName",
"transactionProcessingStrategyId", "transactionProcessingStrategyName",
"principal", "inArrearsTolerance", "numberOfRepayments",
"repaymentEvery", "interestRatePerPeriod", "annualInterestRate",
"repaymentFrequencyType", "interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType",
"createdOn", "lastModifedOn")
@@ -130,7 +134,7 @@ public class LoanProductsApiResource {
LoanProductData loanProduct = this.loanProductReadPlatformService.retrieveLoanProduct(productId);
if (template) {
responseParameters.addAll(Arrays.asList("currencyOptions", "amortizationTypeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions",
"repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "fundOptions"));
"repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "fundOptions", "transactionProcessingStrategyOptions"));
}
return this.apiDataConversionService.convertLoanProductDataToJson(prettyPrint, responseParameters, loanProduct);
@@ -13,6 +13,7 @@ public class LoanProductCommand {
private final String description;
private final Long fundId;
private final Long transactionProcessingStrategyId;
private final String currencyCode;
private final Integer digitsAfterDecimal;
@@ -33,7 +34,7 @@ public class LoanProductCommand {
private final Set<String> modifiedParameters;
public LoanProductCommand(final Set<String> modifiedParameters, final Long id, final String name, final String description,
final Long fundId,
final Long fundId, final Long transactionProcessingStrategyId,
final String currencyCode, final Integer digitsAfterDecimal,
final BigDecimal principal, final BigDecimal inArrearsTolerance, final Integer numberOfRepayments,
final Integer repaymentEvery, final BigDecimal interestRatePerPeriod,
@@ -44,6 +45,7 @@ public class LoanProductCommand {
this.name = name;
this.description = description;
this.fundId = fundId;
this.transactionProcessingStrategyId = transactionProcessingStrategyId;
this.currencyCode = currencyCode;
this.digitsAfterDecimal = digitsAfterDecimal;
this.principal = principal;
@@ -73,6 +75,10 @@ public class LoanProductCommand {
public Long getFundId() {
return fundId;
}
public Long getTransactionProcessingStrategyId() {
return transactionProcessingStrategyId;
}
public String getCurrencyCode() {
return currencyCode;
@@ -133,6 +139,10 @@ public class LoanProductCommand {
public boolean isFundChanged() {
return this.modifiedParameters.contains("fundId");
}
public boolean isTransactionProcessingStrategyChanged() {
return this.modifiedParameters.contains("transactionProcessingStrategyId");
}
public boolean isCurrencyCodeChanged() {
return this.modifiedParameters.contains("currencyCode");
@@ -1,6 +1,5 @@
package org.mifosng.platform.api.data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
@@ -8,7 +7,7 @@ import java.util.List;
import org.joda.time.DateTime;
public class LoanProductData implements Serializable {
public class LoanProductData {
private Long id;
private String name;
@@ -16,6 +15,9 @@ public class LoanProductData implements Serializable {
private Long fundId;
private String fundName;
private Long transactionProcessingStrategyId;
private String transactionProcessingStrategyName;
private MoneyData principal;
private MoneyData inArrearsTolerance;
@@ -36,6 +38,7 @@ public class LoanProductData implements Serializable {
private List<CurrencyData> currencyOptions = new ArrayList<CurrencyData>();
private Collection<FundData> fundOptions = new ArrayList<FundData>();
private Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions = new ArrayList<TransactionProcessingStrategyData>();
private List<EnumOptionData> amortizationTypeOptions = new ArrayList<EnumOptionData>();
private List<EnumOptionData> interestTypeOptions = new ArrayList<EnumOptionData>();
private List<EnumOptionData> interestCalculationPeriodTypeOptions = new ArrayList<EnumOptionData>();
@@ -55,7 +58,7 @@ public class LoanProductData implements Serializable {
EnumOptionData interestRateFrequencyType,
EnumOptionData amortizationType, EnumOptionData interestType,
EnumOptionData interestCalculationPeriodType, Long fundId,
String fundName) {
String fundName, Long transactionProcessingStrategyId, String transactionProcessingStrategyName) {
this.createdOn = createdOn;
this.lastModifedOn = lastModifedOn;
this.id = id;
@@ -74,6 +77,8 @@ public class LoanProductData implements Serializable {
this.interestCalculationPeriodType = interestCalculationPeriodType;
this.fundId = fundId;
this.fundName = fundName;
this.transactionProcessingStrategyId = transactionProcessingStrategyId;
this.transactionProcessingStrategyName = transactionProcessingStrategyName;
}
public Long getId() {
@@ -115,6 +120,23 @@ public class LoanProductData implements Serializable {
public void setFundName(String fundName) {
this.fundName = fundName;
}
public Long getTransactionProcessingStrategyId() {
return transactionProcessingStrategyId;
}
public void setTransactionProcessingStrategyId(Long transactionProcessingStrategyId) {
this.transactionProcessingStrategyId = transactionProcessingStrategyId;
}
public String getTransactionProcessingStrategyName() {
return transactionProcessingStrategyName;
}
public void setTransactionProcessingStrategyName(
String transactionProcessingStrategyName) {
this.transactionProcessingStrategyName = transactionProcessingStrategyName;
}
public MoneyData getPrincipal() {
return principal;
@@ -255,6 +277,15 @@ public class LoanProductData implements Serializable {
public void setFundOptions(Collection<FundData> fundOptions) {
this.fundOptions = fundOptions;
}
public Collection<TransactionProcessingStrategyData> getTransactionProcessingStrategyOptions() {
return transactionProcessingStrategyOptions;
}
public void setTransactionProcessingStrategyOptions(
Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions) {
this.transactionProcessingStrategyOptions = transactionProcessingStrategyOptions;
}
public List<EnumOptionData> getAmortizationTypeOptions() {
return amortizationTypeOptions;
@@ -0,0 +1,27 @@
package org.mifosng.platform.api.data;
public final class TransactionProcessingStrategyData {
private final Long id;
private final String code;
private final String name;
public TransactionProcessingStrategyData(final Long id, final String code, final String name) {
this.id = id;
this.code = code;
this.name = name;
}
public Long getId() {
return id;
}
public String getCode() {
return code;
}
public String getName() {
return name;
}
}
@@ -226,12 +226,13 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
@Override
public String convertLoanProductDataToJson(final boolean prettyPrint, final Set<String> responseParameters, final LoanProductData... products) {
Set<String> supportedParameters = new HashSet<String>(
Arrays.asList("id", "name", "description", "fundId", "fundName", "principal", "inArrearsTolerance", "numberOfRepayments",
Arrays.asList("id", "name", "description", "fundId", "fundName", "transactionProcessingStrategyId", "transactionProcessingStrategyName",
"principal", "inArrearsTolerance", "numberOfRepayments",
"repaymentEvery", "interestRatePerPeriod", "annualInterestRate",
"repaymentFrequencyType", "interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType",
"createdOn", "lastModifedOn",
"currencyOptions", "amortizationTypeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions",
"repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "fundOptions")
"repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "fundOptions", "transactionProcessingStrategyOptions")
);
final Set<String> parameterNamesToSkip = new HashSet<String>();
@@ -827,7 +828,7 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
Map<String, String> requestMap = gsonConverter.fromJson(json, typeOfMap);
Set<String> supportedParams = new HashSet<String>(
Arrays.asList("name", "description", "fundId", "currencyCode", "digitsAfterDecimal",
Arrays.asList("name", "description", "fundId", "transactionProcessingStrategyId", "currencyCode", "digitsAfterDecimal",
"principal", "inArrearsTolerance", "interestRatePerPeriod", "repaymentEvery", "numberOfRepayments",
"repaymentFrequencyType", "interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType", "locale")
);
@@ -839,6 +840,7 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
String name = extractStringParameter("name", requestMap, modifiedParameters);
String description = extractStringParameter("description", requestMap, modifiedParameters);
Long fundId = extractLongParameter("fundId", requestMap, modifiedParameters);
Long transactionProcessingStrategyId = extractLongParameter("transactionProcessingStrategyId", requestMap, modifiedParameters);
String currencyCode = extractStringParameter("currencyCode", requestMap, modifiedParameters);
Integer digitsAfterDecimalValue = extractIntegerParameter("digitsAfterDecimal", requestMap, modifiedParameters);
BigDecimal principalValue = extractBigDecimalParameter("principal", requestMap, modifiedParameters);
@@ -854,7 +856,7 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
Integer interestTypeValue = extractIntegerParameter("interestType", requestMap, modifiedParameters);
Integer interestCalculationPeriodTypeValue = extractIntegerParameter("interestCalculationPeriodType", requestMap, modifiedParameters);
return new LoanProductCommand(modifiedParameters, resourceIdentifier, name, description, fundId,
return new LoanProductCommand(modifiedParameters, resourceIdentifier, name, description, fundId, transactionProcessingStrategyId,
currencyCode, digitsAfterDecimalValue, principalValue, inArrearsToleranceValue, numberOfRepaymentsValue, repaymentEveryValue, interestRatePerPeriodValue,
repaymentFrequencyTypeValue, interestRateFrequencyTypeValue, amortizationTypeValue, interestTypeValue, interestCalculationPeriodTypeValue);
}
@@ -0,0 +1,11 @@
package org.mifosng.platform.exceptions;
/**
* A {@link RuntimeException} thrown when loan transactions processing strategy resources are not found.
*/
public class LoanTransactionProcessingStrategyNotFoundException extends AbstractPlatformResourceNotFoundException {
public LoanTransactionProcessingStrategyNotFoundException(final Long id) {
super("error.msg.transactions.processing.strategy.id.invalid", "Loan transaction processing strategy with identifier " + id + " does not exist", id);
}
}
@@ -32,6 +32,10 @@ public class LoanProduct extends AbstractAuditableCustom<AppUser, Long> {
@ManyToOne
@JoinColumn(name = "fund_id", nullable = true)
private Fund fund;
@ManyToOne
@JoinColumn(name = "loan_transaction_strategy_id", nullable = true)
private LoanTransactionProcessingStrategy transactionProcessingStrategy;
@Column(name = "name", nullable = false)
private String name;
@@ -49,12 +53,14 @@ public class LoanProduct extends AbstractAuditableCustom<AppUser, Long> {
this.loanProductRelatedDetail = null;
}
public LoanProduct(final Fund fund, final String name, final String description, final MonetaryCurrency currency, final BigDecimal defaultPrincipal,
public LoanProduct(final Fund fund, final LoanTransactionProcessingStrategy transactionProcessingStrategy,
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.fund = fund;
this.transactionProcessingStrategy = transactionProcessingStrategy;
this.name = name.trim();
if (StringUtils.isNotBlank(description)) {
this.description = description.trim();
@@ -96,10 +102,6 @@ public class LoanProduct extends AbstractAuditableCustom<AppUser, Long> {
return this.loanProductRelatedDetail.isInterestRebateAllowed();
}
public boolean identifiedBy(final String identifier) {
return identifier.equalsIgnoreCase(this.name);
}
public BigDecimal getDefaultNominalInterestRatePerPeriod() {
return this.loanProductRelatedDetail.getNominalInterestRatePerPeriod();
}
@@ -131,8 +133,12 @@ public class LoanProduct extends AbstractAuditableCustom<AppUser, Long> {
public Fund getFund() {
return fund;
}
public LoanTransactionProcessingStrategy getTransactionProcessingStrategy() {
return transactionProcessingStrategy;
}
public void update(final LoanProductCommand command, final Fund fund) {
public void update(final LoanProductCommand command, final Fund fund, final LoanTransactionProcessingStrategy strategy) {
if (command.isNameChanged()) {
this.name = command.getName();
@@ -146,6 +152,10 @@ public class LoanProduct extends AbstractAuditableCustom<AppUser, Long> {
this.fund = fund;
}
if (command.isTransactionProcessingStrategyChanged()) {
this.transactionProcessingStrategy = strategy;
}
this.loanProductRelatedDetail.update(command);
}
}
@@ -0,0 +1,35 @@
package org.mifosng.platform.loan.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import org.mifosng.platform.api.data.TransactionProcessingStrategyData;
import org.mifosng.platform.infrastructure.AbstractAuditableCustom;
import org.mifosng.platform.user.domain.AppUser;
/**
*
*/
@Entity
@Table(name = "ref_loan_transaction_processing_strategy")
public class LoanTransactionProcessingStrategy extends AbstractAuditableCustom<AppUser, Long> {
@Column(name = "code", unique=true)
private String code;
@Column(name = "name")
private String name;
protected LoanTransactionProcessingStrategy() {
//
}
public String code() {
return this.code;
}
public TransactionProcessingStrategyData toData() {
return new TransactionProcessingStrategyData(this.getId(), this.code, this.name);
}
}
@@ -0,0 +1,9 @@
package org.mifosng.platform.loan.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface LoanTransactionProcessingStrategyRepository extends JpaRepository<LoanTransactionProcessingStrategy, Long>,
JpaSpecificationExecutor<LoanTransactionProcessingStrategy> {
// no added behaviour
}
@@ -1,8 +1,10 @@
package org.mifosng.platform.loanproduct.service;
import java.util.Collection;
import java.util.List;
import org.mifosng.platform.api.data.EnumOptionData;
import org.mifosng.platform.api.data.TransactionProcessingStrategyData;
public interface LoanDropdownReadPlatformService {
@@ -15,4 +17,6 @@ public interface LoanDropdownReadPlatformService {
List<EnumOptionData> retrieveRepaymentFrequencyTypeOptions();
List<EnumOptionData> retrieveInterestRateFrequencyTypeOptions();
Collection<TransactionProcessingStrategyData> retreiveTransactionProcessingStrategies();
}
@@ -6,20 +6,32 @@ import static org.mifosng.platform.loanproduct.service.LoanEnumerations.interest
import static org.mifosng.platform.loanproduct.service.LoanEnumerations.interestType;
import static org.mifosng.platform.loanproduct.service.LoanEnumerations.repaymentFrequencyType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.mifosng.platform.api.data.EnumOptionData;
import org.mifosng.platform.api.data.TransactionProcessingStrategyData;
import org.mifosng.platform.loan.domain.AmortizationMethod;
import org.mifosng.platform.loan.domain.InterestCalculationPeriodMethod;
import org.mifosng.platform.loan.domain.InterestMethod;
import org.mifosng.platform.loan.domain.LoanTransactionProcessingStrategy;
import org.mifosng.platform.loan.domain.LoanTransactionProcessingStrategyRepository;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class LoanDropdownReadPlatformServiceImpl implements
LoanDropdownReadPlatformService {
public class LoanDropdownReadPlatformServiceImpl implements LoanDropdownReadPlatformService {
private final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository;
@Autowired
public LoanDropdownReadPlatformServiceImpl(final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository) {
this.loanTransactionProcessingStrategyRepository = loanTransactionProcessingStrategyRepository;
}
@Override
public List<EnumOptionData> retrieveLoanAmortizationTypeOptions() {
@@ -67,4 +79,17 @@ public class LoanDropdownReadPlatformServiceImpl implements
interestRateFrequencyType(PeriodFrequencyType.YEARS));
return interestRateFrequencyTypeOptions;
}
@Override
public Collection<TransactionProcessingStrategyData> retreiveTransactionProcessingStrategies() {
Collection<TransactionProcessingStrategyData> strategyOptions = new ArrayList<TransactionProcessingStrategyData>();
List<LoanTransactionProcessingStrategy> strategies = this.loanTransactionProcessingStrategyRepository.findAll();
for (LoanTransactionProcessingStrategy strategy : strategies) {
strategyOptions.add(strategy.toData());
}
return strategyOptions;
}
}
@@ -13,6 +13,7 @@ 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.api.data.TransactionProcessingStrategyData;
import org.mifosng.platform.currency.service.CurrencyReadPlatformService;
import org.mifosng.platform.exceptions.LoanProductNotFoundException;
import org.mifosng.platform.fund.service.FundReadPlatformService;
@@ -128,14 +129,12 @@ public class LoanProductReadPlatformServiceImpl implements
private static final class LoanProductMapper implements
RowMapper<LoanProductData> {
// private final List<CurrencyData> allowedCurrencies;
// private final Collection<FundData> allFunds;
public LoanProductMapper() {
}
public String loanProductSchema() {
return "lp.id as id, lp.fund_id as fundId, f.name as fundName, 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, f.name as fundName, lp.loan_transaction_strategy_id as transactionStrategyId, ltps.name as transactionStrategyName, "
+ "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,"
@@ -145,6 +144,7 @@ public class LoanProductReadPlatformServiceImpl implements
+ "curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, curr.display_symbol as currencyDisplaySymbol "
+ " from portfolio_product_loan lp "
+ " left join org_fund f on f.id = lp.fund_id"
+ " left join ref_loan_transaction_processing_strategy ltps on ltps.id = lp.loan_transaction_strategy_id"
+ " join ref_currency curr on curr.code = lp.currency_code";
}
@@ -158,6 +158,9 @@ public class LoanProductReadPlatformServiceImpl implements
Long fundId = JdbcSupport.getLong(rs, "fundId");
String fundName = rs.getString("fundName");
Long transactionStrategyId = JdbcSupport.getLong(rs, "transactionStrategyId");
String transactionStrategyName = rs.getString("transactionStrategyName");
String currencyCode = rs.getString("currencyCode");
String currencyName = rs.getString("currencyName");
@@ -217,7 +220,7 @@ public class LoanProductReadPlatformServiceImpl implements
numberOfRepayments, repaymentEvery, interestRatePerPeriod,
annualInterestRate, repaymentFrequencyType,
interestRateFrequencyType, amortizationType, interestType,
interestCalculationPeriodType, fundId, fundName);
interestCalculationPeriodType, fundId, fundName, transactionStrategyId, transactionStrategyName);
}
}
@@ -241,35 +244,26 @@ public class LoanProductReadPlatformServiceImpl implements
}
private void populateProductDataWithDropdownOptions(
LoanProductData productData) {
private void populateProductDataWithDropdownOptions(final LoanProductData productData) {
List<CurrencyData> currencyOptions = currencyReadPlatformService
.retrieveAllowedCurrencies();
List<EnumOptionData> amortizationTypeOptions = dropdownReadPlatformService
.retrieveLoanAmortizationTypeOptions();
List<EnumOptionData> interestTypeOptions = dropdownReadPlatformService
.retrieveLoanInterestTypeOptions();
List<EnumOptionData> interestCalculationPeriodTypeOptions = dropdownReadPlatformService
.retrieveLoanInterestRateCalculatedInPeriodOptions();
List<EnumOptionData> repaymentFrequencyTypeOptions = dropdownReadPlatformService
.retrieveRepaymentFrequencyTypeOptions();
List<EnumOptionData> interestRateFrequencyTypeOptions = dropdownReadPlatformService
.retrieveInterestRateFrequencyTypeOptions();
List<CurrencyData> currencyOptions = currencyReadPlatformService.retrieveAllowedCurrencies();
List<EnumOptionData> amortizationTypeOptions = dropdownReadPlatformService.retrieveLoanAmortizationTypeOptions();
List<EnumOptionData> interestTypeOptions = dropdownReadPlatformService.retrieveLoanInterestTypeOptions();
List<EnumOptionData> interestCalculationPeriodTypeOptions = dropdownReadPlatformService.retrieveLoanInterestRateCalculatedInPeriodOptions();
List<EnumOptionData> repaymentFrequencyTypeOptions = dropdownReadPlatformService.retrieveRepaymentFrequencyTypeOptions();
List<EnumOptionData> interestRateFrequencyTypeOptions = dropdownReadPlatformService.retrieveInterestRateFrequencyTypeOptions();
Collection<FundData> fundOptions = this.fundReadPlatformService
.retrieveAllFunds();
Collection<FundData> fundOptions = this.fundReadPlatformService.retrieveAllFunds();
Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions = this.dropdownReadPlatformService.retreiveTransactionProcessingStrategies();
productData.setCurrencyOptions(currencyOptions);
productData.setAmortizationTypeOptions(amortizationTypeOptions);
productData.setInterestTypeOptions(interestTypeOptions);
productData
.setInterestCalculationPeriodTypeOptions(interestCalculationPeriodTypeOptions);
productData
.setRepaymentFrequencyTypeOptions(repaymentFrequencyTypeOptions);
productData
.setInterestRateFrequencyTypeOptions(interestRateFrequencyTypeOptions);
productData.setInterestCalculationPeriodTypeOptions(interestCalculationPeriodTypeOptions);
productData.setRepaymentFrequencyTypeOptions(repaymentFrequencyTypeOptions);
productData.setInterestRateFrequencyTypeOptions(interestRateFrequencyTypeOptions);
productData.setFundOptions(fundOptions);
productData.setTransactionProcessingStrategyOptions(transactionProcessingStrategyOptions);
}
}
@@ -7,6 +7,7 @@ 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.exceptions.LoanTransactionProcessingStrategyNotFoundException;
import org.mifosng.platform.fund.domain.Fund;
import org.mifosng.platform.fund.domain.FundRepository;
import org.mifosng.platform.loan.domain.AmortizationMethod;
@@ -14,6 +15,8 @@ import org.mifosng.platform.loan.domain.InterestCalculationPeriodMethod;
import org.mifosng.platform.loan.domain.InterestMethod;
import org.mifosng.platform.loan.domain.LoanProduct;
import org.mifosng.platform.loan.domain.LoanProductRepository;
import org.mifosng.platform.loan.domain.LoanTransactionProcessingStrategy;
import org.mifosng.platform.loan.domain.LoanTransactionProcessingStrategyRepository;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosng.platform.loanschedule.domain.AprCalculator;
import org.mifosng.platform.security.PlatformSecurityContext;
@@ -28,14 +31,16 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
private final LoanProductRepository loanProductRepository;
private final AprCalculator aprCalculator;
private final FundRepository fundRepository;
private final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository;
@Autowired
public LoanProductWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final LoanProductRepository loanProductRepository,
final AprCalculator aprCalculator, final FundRepository fundRepository) {
final AprCalculator aprCalculator, final FundRepository fundRepository, final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository) {
this.context = context;
this.loanProductRepository = loanProductRepository;
this.aprCalculator = aprCalculator;
this.fundRepository = fundRepository;
this.loanTransactionProcessingStrategyRepository = loanTransactionProcessingStrategyRepository;
}
@Transactional
@@ -65,8 +70,10 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
// associating fund with loan product at creation is optional for now.
Fund fund = findFundByIdIfProvided(command.getFundId());
LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(command.getTransactionProcessingStrategyId());
LoanProduct loanproduct = new LoanProduct(fund, command.getName(), command.getDescription(),
LoanProduct loanproduct = new LoanProduct(fund, loanTransactionProcessingStrategy,
command.getName(), command.getDescription(),
currency, command.getPrincipal(),
command.getInterestRatePerPeriod(), interestFrequencyType, annualInterestRate, interestMethod, interestCalculationPeriodMethod,
command.getRepaymentEvery(), repaymentFrequencyType, command.getNumberOfRepayments(),
@@ -77,6 +84,17 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
return new EntityIdentifier(loanproduct.getId());
}
private LoanTransactionProcessingStrategy findStrategyByIdIfProvided(final Long transactionProcessingStrategyId) {
LoanTransactionProcessingStrategy fund = null;
if (transactionProcessingStrategyId != null) {
fund = this.loanTransactionProcessingStrategyRepository.findOne(transactionProcessingStrategyId);
if (fund == null) {
throw new LoanTransactionProcessingStrategyNotFoundException(transactionProcessingStrategyId);
}
}
return fund;
}
private Fund findFundByIdIfProvided(final Long fundId) {
Fund fund = null;
if (fundId != null) {
@@ -104,8 +122,9 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
// associating fund with loan product at creation is optional for now.
Fund fund = findFundByIdIfProvided(command.getFundId());
LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(command.getTransactionProcessingStrategyId());
product.update(command, fund);
product.update(command, fund, loanTransactionProcessingStrategy);
this.loanProductRepository.save(product);