MIFOSX-97: move loan products to command handler support.

This commit is contained in:
Keith Woodlock
2012-11-30 16:35:01 +00:00
parent a3970af6c2
commit 7ac55812d6
94 changed files with 1884 additions and 1724 deletions
@@ -36,12 +36,12 @@ import org.mifosng.platform.api.infrastructure.PortfolioApiDataConversionService
import org.mifosng.platform.api.infrastructure.PortfolioApiJsonSerializerService;
import org.mifosng.platform.exceptions.UnrecognizedQueryParamException;
import org.mifosng.platform.infrastructure.api.ApiParameterHelper;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosng.platform.saving.service.DepositAccountReadPlatformService;
import org.mifosng.platform.saving.service.DepositAccountWritePlatformService;
import org.mifosng.platform.savingproduct.service.DepositProductReadPlatformService;
import org.mifosng.platform.savingproduct.service.SavingsDepositEnumerations;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@@ -26,13 +26,13 @@ import org.mifosng.platform.api.data.EnumOptionData;
import org.mifosng.platform.api.infrastructure.PortfolioApiDataConversionService;
import org.mifosng.platform.api.infrastructure.PortfolioApiJsonSerializerService;
import org.mifosng.platform.infrastructure.api.ApiParameterHelper;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosng.platform.savingproduct.service.DepositProductReadPlatformService;
import org.mifosng.platform.savingproduct.service.DepositProductWritePlatformService;
import org.mifosng.platform.savingproduct.service.SavingsDepositEnumerations;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.configuration.service.CurrencyReadPlatformService;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@@ -1,170 +0,0 @@
package org.mifosng.platform.api;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import org.mifosng.platform.api.commands.LoanProductCommand;
import org.mifosng.platform.api.data.EntityIdentifier;
import org.mifosng.platform.api.data.EnumOptionData;
import org.mifosng.platform.api.data.LoanProductData;
import org.mifosng.platform.api.data.TransactionProcessingStrategyData;
import org.mifosng.platform.api.infrastructure.PortfolioApiDataConversionService;
import org.mifosng.platform.api.infrastructure.PortfolioApiJsonSerializerService;
import org.mifosng.platform.infrastructure.api.ApiParameterHelper;
import org.mifosng.platform.loanproduct.service.LoanDropdownReadPlatformService;
import org.mifosng.platform.loanproduct.service.LoanProductReadPlatformService;
import org.mifosng.platform.loanproduct.service.LoanProductWritePlatformService;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.configuration.service.CurrencyReadPlatformService;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.charge.data.ChargeData;
import org.mifosplatform.portfolio.charge.service.ChargeReadPlatformService;
import org.mifosplatform.portfolio.fund.data.FundData;
import org.mifosplatform.portfolio.fund.service.FundReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/loanproducts")
@Component
@Scope("singleton")
public class LoanProductsApiResource {
@Autowired
private LoanProductReadPlatformService loanProductReadPlatformService;
@Autowired
private LoanProductWritePlatformService loanProductWritePlatformService;
@Autowired
private ChargeReadPlatformService chargeReadPlatformService;
@Autowired
private PortfolioApiDataConversionService apiDataConversionService;
@Autowired
private PortfolioApiJsonSerializerService apiJsonSerializerService;
@Autowired
private CurrencyReadPlatformService currencyReadPlatformService;
@Autowired
private FundReadPlatformService fundReadPlatformService;
@Autowired
private LoanDropdownReadPlatformService dropdownReadPlatformService;
private final String entityType = "LOANPRODUCT";
@Autowired
private PlatformSecurityContext context;
@POST
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String createLoanProduct(final String jsonRequestBody) {
final LoanProductCommand command = this.apiDataConversionService.convertJsonToLoanProductCommand(null, jsonRequestBody);
final EntityIdentifier identifier = this.loanProductWritePlatformService.createLoanProduct(command);
return apiJsonSerializerService.serializeEntityIdentifier(identifier);
}
@GET
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String retrieveAllLoanProducts(@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
final Collection<LoanProductData> products = this.loanProductReadPlatformService.retrieveAllLoanProducts();
return this.apiJsonSerializerService.serializeLoanProductDataToJson(prettyPrint, responseParameters, products);
}
@GET
@Path("template")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String retrieveNewLoanProductDetails(@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
LoanProductData loanProduct = this.loanProductReadPlatformService.retrieveNewLoanProductDetails();
loanProduct = handleTemplate(loanProduct);
return this.apiJsonSerializerService.serializeLoanProductDataToJson(prettyPrint, responseParameters, loanProduct);
}
@GET
@Path("{productId}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String retrieveLoanProductDetails(@PathParam("productId") final Long productId, @Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
final boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters());
LoanProductData loanProduct = this.loanProductReadPlatformService.retrieveLoanProduct(productId);
if (template) {
loanProduct = handleTemplate(loanProduct);
}
return this.apiJsonSerializerService.serializeLoanProductDataToJson(prettyPrint, responseParameters, loanProduct);
}
@PUT
@Path("{productId}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String updateLoanProduct(@PathParam("productId") final Long productId, final String jsonRequestBody) {
final LoanProductCommand command = this.apiDataConversionService.convertJsonToLoanProductCommand(productId, jsonRequestBody);
final EntityIdentifier identifier = this.loanProductWritePlatformService.updateLoanProduct(command);
return apiJsonSerializerService.serializeEntityIdentifier(identifier);
}
private LoanProductData handleTemplate(final LoanProductData productData) {
final boolean feeChargesOnly = true;
Collection<ChargeData> chargeOptions = this.chargeReadPlatformService.retrieveLoanApplicableCharges(feeChargesOnly);
chargeOptions.removeAll(productData.charges());
final List<CurrencyData> currencyOptions = currencyReadPlatformService.retrieveAllowedCurrencies();
final List<EnumOptionData> amortizationTypeOptions = dropdownReadPlatformService.retrieveLoanAmortizationTypeOptions();
final List<EnumOptionData> interestTypeOptions = dropdownReadPlatformService.retrieveLoanInterestTypeOptions();
final List<EnumOptionData> interestCalculationPeriodTypeOptions = dropdownReadPlatformService.retrieveLoanInterestRateCalculatedInPeriodOptions();
final List<EnumOptionData> loanTermFrequencyTypeOptions = dropdownReadPlatformService.retrieveLoanTermFrequencyTypeOptions();
final List<EnumOptionData> repaymentFrequencyTypeOptions = dropdownReadPlatformService.retrieveRepaymentFrequencyTypeOptions();
final List<EnumOptionData> interestRateFrequencyTypeOptions = dropdownReadPlatformService.retrieveInterestRateFrequencyTypeOptions();
final Collection<FundData> fundOptions = this.fundReadPlatformService.retrieveAllFunds();
final Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions = this.dropdownReadPlatformService.retreiveTransactionProcessingStrategies();
return new LoanProductData(productData, chargeOptions, currencyOptions, amortizationTypeOptions, interestTypeOptions,
interestCalculationPeriodTypeOptions, loanTermFrequencyTypeOptions, repaymentFrequencyTypeOptions, interestRateFrequencyTypeOptions, fundOptions, transactionProcessingStrategyOptions);
}
}
@@ -35,11 +35,9 @@ import org.mifosng.platform.api.data.LoanAccountData;
import org.mifosng.platform.api.data.LoanBasicDetailsData;
import org.mifosng.platform.api.data.LoanChargeData;
import org.mifosng.platform.api.data.LoanPermissionData;
import org.mifosng.platform.api.data.LoanProductData;
import org.mifosng.platform.api.data.LoanScheduleData;
import org.mifosng.platform.api.data.LoanTransactionData;
import org.mifosng.platform.api.data.StaffAccountSummaryCollectionData;
import org.mifosng.platform.api.data.TransactionProcessingStrategyData;
import org.mifosng.platform.api.infrastructure.PortfolioApiDataConversionService;
import org.mifosng.platform.api.infrastructure.PortfolioApiJsonSerializerService;
import org.mifosng.platform.exceptions.UnrecognizedQueryParamException;
@@ -48,8 +46,6 @@ import org.mifosng.platform.infrastructure.api.ApiParameterHelper;
import org.mifosng.platform.loan.service.CalculationPlatformService;
import org.mifosng.platform.loan.service.LoanReadPlatformService;
import org.mifosng.platform.loan.service.LoanWritePlatformService;
import org.mifosng.platform.loanproduct.service.LoanDropdownReadPlatformService;
import org.mifosng.platform.loanproduct.service.LoanProductReadPlatformService;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.infrastructure.office.data.OfficeLookup;
@@ -63,6 +59,10 @@ import org.mifosplatform.portfolio.charge.data.ChargeData;
import org.mifosplatform.portfolio.charge.service.ChargeReadPlatformService;
import org.mifosplatform.portfolio.fund.data.FundData;
import org.mifosplatform.portfolio.fund.service.FundReadPlatformService;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
import org.mifosplatform.portfolio.loanproduct.data.TransactionProcessingStrategyData;
import org.mifosplatform.portfolio.loanproduct.service.LoanDropdownReadPlatformService;
import org.mifosplatform.portfolio.loanproduct.service.LoanProductReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@@ -4,6 +4,7 @@ import java.math.BigDecimal;
import java.util.Set;
import org.joda.time.LocalDate;
import org.mifosplatform.portfolio.loanproduct.command.LoanProductCommand;
/**
* Immutable command for submitting new loan application.
@@ -209,7 +210,7 @@ public class LoanApplicationCommand {
public LoanProductCommand toLoanProductCommand() {
// FIXME - KW - CHARGE - FIX UP FOR CHARGES - take look at loan product charges also and align usage with other loan areas.
return new LoanProductCommand(modifiedParameters, this.productId, null, null,
return new LoanProductCommand(modifiedParameters, false, this.productId, null, null,
this.fundId, this.transactionProcessingStrategyId,
null, null,
this.principal, this.inArrearsTolerance,
@@ -1,211 +0,0 @@
package org.mifosng.platform.api.commands;
import java.math.BigDecimal;
import java.util.Set;
/**
* Immutable command for creating or updating details of a loan product.
*/
public class LoanProductCommand {
private final Long id;
private final String name;
private final String description;
private final Long fundId;
private final Long transactionProcessingStrategyId;
private final String currencyCode;
private final Integer digitsAfterDecimal;
private final BigDecimal principal;
private final BigDecimal inArrearsTolerance;
private final Integer numberOfRepayments;
private final Integer repaymentEvery;
private final BigDecimal interestRatePerPeriod;
private final Integer repaymentFrequencyType;
private final Integer interestRateFrequencyType;
private final Integer amortizationType;
private final Integer interestType;
private final Integer interestCalculationPeriodType;
private final String[] charges;
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 transactionProcessingStrategyId,
final String currencyCode, final Integer digitsAfterDecimal,
final BigDecimal principal, final BigDecimal inArrearsTolerance, final Integer numberOfRepayments,
final Integer repaymentEvery, final BigDecimal interestRatePerPeriod,
final Integer repaymentFrequencyType, final Integer interestRateFrequencyType, final Integer amortizationType, final Integer interestType,
final Integer interestCalculationPeriodType, final String[] charges) {
this.modifiedParameters = modifiedParameters;
this.id = id;
this.name = name;
this.description = description;
this.fundId = fundId;
this.transactionProcessingStrategyId = transactionProcessingStrategyId;
this.currencyCode = currencyCode;
this.digitsAfterDecimal = digitsAfterDecimal;
this.principal = principal;
if (inArrearsTolerance != null && BigDecimal.ZERO.compareTo(inArrearsTolerance) == 0) {
this.inArrearsTolerance = null;
} else {
this.inArrearsTolerance = inArrearsTolerance;
}
this.numberOfRepayments = numberOfRepayments;
this.repaymentEvery = repaymentEvery;
this.interestRatePerPeriod = interestRatePerPeriod;
this.repaymentFrequencyType = repaymentFrequencyType;
this.interestRateFrequencyType = interestRateFrequencyType;
this.amortizationType = amortizationType;
this.interestType = interestType;
this.interestCalculationPeriodType = interestCalculationPeriodType;
this.charges = charges;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public Long getFundId() {
return fundId;
}
public Long getTransactionProcessingStrategyId() {
return transactionProcessingStrategyId;
}
public String getCurrencyCode() {
return currencyCode;
}
public Integer getDigitsAfterDecimal() {
return digitsAfterDecimal;
}
public BigDecimal getPrincipal() {
return principal;
}
public BigDecimal getInArrearsTolerance() {
return inArrearsTolerance;
}
public Integer getNumberOfRepayments() {
return numberOfRepayments;
}
public Integer getRepaymentEvery() {
return repaymentEvery;
}
public BigDecimal getInterestRatePerPeriod() {
return interestRatePerPeriod;
}
public Integer getRepaymentFrequencyType() {
return repaymentFrequencyType;
}
public Integer getInterestRateFrequencyType() {
return interestRateFrequencyType;
}
public Integer getAmortizationType() {
return amortizationType;
}
public Integer getInterestType() {
return interestType;
}
public Integer getInterestCalculationPeriodType() {
return interestCalculationPeriodType;
}
public String[] getCharges() {
return charges;
}
public boolean isNameChanged() {
return this.modifiedParameters.contains("name");
}
public boolean isDescriptionChanged() {
return this.modifiedParameters.contains("description");
}
public boolean isFundChanged() {
return this.modifiedParameters.contains("fundId");
}
public boolean isTransactionProcessingStrategyChanged() {
return this.modifiedParameters.contains("transactionProcessingStrategyId");
}
public boolean isCurrencyCodeChanged() {
return this.modifiedParameters.contains("currencyCode");
}
public boolean isDigitsAfterDecimalChanged() {
return this.modifiedParameters.contains("digitsAfterDecimal");
}
public boolean isPrincipalChanged() {
return this.modifiedParameters.contains("principal");
}
public boolean isInArrearsToleranceChanged() {
return this.modifiedParameters.contains("inArrearsTolerance");
}
public boolean isNumberOfRepaymentsChanged() {
return this.modifiedParameters.contains("numberOfRepayments");
}
public boolean isRepaymentEveryChanged() {
return this.modifiedParameters.contains("repaymentEvery");
}
public boolean isRepaymentFrequencyTypeChanged() {
return this.modifiedParameters.contains("repaymentFrequencyType");
}
public boolean isAmortizationTypeChanged() {
return this.modifiedParameters.contains("amortizationType");
}
public boolean isInterestTypeChanged() {
return this.modifiedParameters.contains("interestType");
}
public boolean isInterestRatePerPeriodChanged() {
return this.modifiedParameters.contains("interestRatePerPeriod");
}
public boolean isInterestRateFrequencyTypeChanged() {
return this.modifiedParameters.contains("interestRateFrequencyType");
}
public boolean isInterestCalculationPeriodTypeChanged() {
return this.modifiedParameters.contains("interestCalculationPeriodType");
}
public boolean isChargesChanged() {
return this.modifiedParameters.contains("charges");
}
}
@@ -2,25 +2,25 @@ package org.mifosng.platform.api.data;
public class EnumOptionData {
private final Long id;
private final String code;
private final String value;
private final Long id;
private final String code;
private final String value;
public EnumOptionData(final Long id, final String code, final String value) {
this.id = id;
this.code = code;
this.value = value;
}
public EnumOptionData(final Long id, final String code, final String value) {
this.id = id;
this.code = code;
this.value = value;
}
public Long getId() {
return id;
}
public Long getId() {
return id;
}
public String getCode() {
return code;
}
public String getCode() {
return code;
}
public String getValue() {
return value;
}
public String getValue() {
return value;
}
}
@@ -8,6 +8,8 @@ import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.staff.data.StaffData;
import org.mifosplatform.portfolio.charge.data.ChargeData;
import org.mifosplatform.portfolio.fund.data.FundData;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
import org.mifosplatform.portfolio.loanproduct.data.TransactionProcessingStrategyData;
/**
* Immutable data object representing loan account data.
@@ -10,6 +10,7 @@ import org.joda.time.LocalDate;
import org.joda.time.Months;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.portfolio.charge.data.ChargeData;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
/**
* Immutable data object for core details of loan to be combined with {@link LoanAccountData} usage.
@@ -1,388 +0,0 @@
package org.mifosng.platform.api.data;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.joda.time.DateTime;
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.PeriodFrequencyType;
import org.mifosng.platform.loanproduct.service.LoanEnumerations;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.portfolio.charge.data.ChargeData;
import org.mifosplatform.portfolio.fund.data.FundData;
/**
* Immutable data object to represent loan products.
*/
public class LoanProductData {
private final Long id;
private final String name;
private final String description;
private final Long fundId;
private final String fundName;
private final Long transactionProcessingStrategyId;
private final String transactionProcessingStrategyName;
private final CurrencyData currency;
private final BigDecimal principal;
private final BigDecimal inArrearsTolerance;
private final Integer numberOfRepayments;
private final Integer loanTermFrequency;
private final Integer repaymentEvery;
private final BigDecimal interestRatePerPeriod;
private final BigDecimal annualInterestRate;
private final EnumOptionData loanTermFrequencyType;
private final EnumOptionData repaymentFrequencyType;
private final EnumOptionData interestRateFrequencyType;
private final EnumOptionData amortizationType;
private final EnumOptionData interestType;
private final EnumOptionData interestCalculationPeriodType;
private final Collection<ChargeData> charges;
private final DateTime createdOn;
private final DateTime lastModifedOn;
private final List<CurrencyData> currencyOptions;
private final Collection<FundData> fundOptions;
private final Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions;
private final List<EnumOptionData> amortizationTypeOptions;
private final List<EnumOptionData> interestTypeOptions;
private final List<EnumOptionData> interestCalculationPeriodTypeOptions;
private final List<EnumOptionData> repaymentFrequencyTypeOptions;
private final List<EnumOptionData> interestRateFrequencyTypeOptions;
private final List<EnumOptionData> loanTermFrequencyTypeOptions;
private final Collection<ChargeData> chargeOptions;
/**
* Used when returning lookup information about loan product for dropdowns.
*/
public static LoanProductData lookup(final Long id, final String name) {
final DateTime createdOn = null;
final DateTime lastModifedOn = null;
final String description = null;
final CurrencyData currency = null;
final BigDecimal principal = null;
final BigDecimal tolerance = null;
final Integer numberOfRepayments = null;
final Integer loanTermFrequency = null;
final Integer repaymentEvery = null;
final BigDecimal interestRatePerPeriod = null;
final BigDecimal annualInterestRate = null;
final EnumOptionData loanTermFrequencyType = null;
final EnumOptionData repaymentFrequencyType = null;
final EnumOptionData interestRateFrequencyType = null;
final EnumOptionData amortizationType = null;
final EnumOptionData interestType = null;
final EnumOptionData interestCalculationPeriodType = null;
final Long fundId = null;
final String fundName = null;
final Long transactionProcessingStrategyId = null;
final String transactionProcessingStrategyName = null;
final Collection<ChargeData> charges = null;
return new LoanProductData(createdOn, lastModifedOn, id, name, description, currency, principal, tolerance,
numberOfRepayments, loanTermFrequency, repaymentEvery, interestRatePerPeriod, annualInterestRate,
loanTermFrequencyType, repaymentFrequencyType, interestRateFrequencyType,
amortizationType, interestType, interestCalculationPeriodType,
fundId, fundName, transactionProcessingStrategyId, transactionProcessingStrategyName, charges);
}
public static LoanProductData sensibleDefaultsForNewLoanProductCreation() {
final DateTime createdOn = null;
final DateTime lastModifedOn = null;
final Long id = null;
final String name = null;
final String description = null;
final CurrencyData currency = CurrencyData.blank();
final BigDecimal principal = null;
final BigDecimal tolerance = null;
final Integer numberOfRepayments = null;
final Integer loanTermFrequency = null;
final Integer repaymentEvery = null;
final BigDecimal interestRatePerPeriod = null;
final BigDecimal annualInterestRate = null;
final EnumOptionData loanTermFrequencyType = LoanEnumerations.loanTermFrequencyType(PeriodFrequencyType.MONTHS);
final EnumOptionData repaymentFrequencyType = LoanEnumerations.repaymentFrequencyType(PeriodFrequencyType.MONTHS);
final EnumOptionData interestRateFrequencyType = LoanEnumerations.interestRateFrequencyType(PeriodFrequencyType.MONTHS);
final EnumOptionData amortizationType = LoanEnumerations.amortizationType(AmortizationMethod.EQUAL_INSTALLMENTS);
final EnumOptionData interestType = LoanEnumerations.interestType(InterestMethod.DECLINING_BALANCE);
final EnumOptionData interestCalculationPeriodType = LoanEnumerations.interestCalculationPeriodType(InterestCalculationPeriodMethod.SAME_AS_REPAYMENT_PERIOD);
final Long fundId = null;
final String fundName = null;
final Long transactionProcessingStrategyId = null;
final String transactionProcessingStrategyName = null;
final Collection<ChargeData> charges = null;
return new LoanProductData(createdOn, lastModifedOn, id, name, description, currency, principal, tolerance,
numberOfRepayments, loanTermFrequency, repaymentEvery, interestRatePerPeriod, annualInterestRate,
loanTermFrequencyType, repaymentFrequencyType, interestRateFrequencyType,
amortizationType, interestType, interestCalculationPeriodType,
fundId, fundName, transactionProcessingStrategyId, transactionProcessingStrategyName, charges);
}
public LoanProductData(
final DateTime createdOn,
final DateTime lastModifedOn,
final Long id,
final String name,
final String description,
final CurrencyData currency,
final BigDecimal principal,
final BigDecimal tolerance,
final Integer numberOfRepayments,
final Integer loanTermFrequency,
final Integer repaymentEvery,
final BigDecimal interestRatePerPeriod,
final BigDecimal annualInterestRate,
final EnumOptionData loanTermFrequencyType,
final EnumOptionData repaymentFrequencyType,
final EnumOptionData interestRateFrequencyType,
final EnumOptionData amortizationType,
final EnumOptionData interestType,
final EnumOptionData interestCalculationPeriodType,
final Long fundId,
final String fundName,
final Long transactionProcessingStrategyId,
final String transactionProcessingStrategyName,
final Collection<ChargeData> charges) {
this.createdOn = createdOn;
this.lastModifedOn = lastModifedOn;
this.id = id;
this.name = name;
this.description = description;
this.currency = currency;
this.principal = principal;
this.inArrearsTolerance = tolerance;
this.numberOfRepayments = numberOfRepayments;
this.loanTermFrequency = loanTermFrequency;
this.repaymentEvery = repaymentEvery;
this.interestRatePerPeriod = interestRatePerPeriod;
this.annualInterestRate = annualInterestRate;
this.loanTermFrequencyType = loanTermFrequencyType;
this.repaymentFrequencyType = repaymentFrequencyType;
this.interestRateFrequencyType = interestRateFrequencyType;
this.amortizationType = amortizationType;
this.interestType = interestType;
this.interestCalculationPeriodType = interestCalculationPeriodType;
this.fundId = fundId;
this.fundName = fundName;
this.transactionProcessingStrategyId = transactionProcessingStrategyId;
this.transactionProcessingStrategyName = transactionProcessingStrategyName;
this.charges = charges;
this.chargeOptions = null;
this.currencyOptions = null;
this.fundOptions = null;
this.transactionProcessingStrategyOptions = null;
this.amortizationTypeOptions = null;
this.interestTypeOptions = null;
this.interestCalculationPeriodTypeOptions = null;
this.loanTermFrequencyTypeOptions = null;
this.repaymentFrequencyTypeOptions = null;
this.interestRateFrequencyTypeOptions = null;
}
public LoanProductData(
final LoanProductData productData,
final Collection<ChargeData> chargeOptions,
final List<CurrencyData> currencyOptions,
final List<EnumOptionData> amortizationTypeOptions,
final List<EnumOptionData> interestTypeOptions,
final List<EnumOptionData> interestCalculationPeriodTypeOptions,
final List<EnumOptionData> loanTermFrequencyTypeOptions,
final List<EnumOptionData> repaymentFrequencyTypeOptions,
final List<EnumOptionData> interestRateFrequencyTypeOptions,
final Collection<FundData> fundOptions,
final Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions) {
this.createdOn = productData.createdOn;
this.lastModifedOn = productData.lastModifedOn;
this.id = productData.id;
this.name = productData.name;
this.description = productData.description;
this.principal = productData.principal;
this.inArrearsTolerance = productData.inArrearsTolerance;
this.numberOfRepayments = productData.numberOfRepayments;
this.loanTermFrequency = productData.loanTermFrequency;
this.repaymentEvery = productData.repaymentEvery;
this.interestRatePerPeriod = productData.interestRatePerPeriod;
this.annualInterestRate = productData.annualInterestRate;
this.loanTermFrequencyType = productData.loanTermFrequencyType;
this.repaymentFrequencyType = productData.repaymentFrequencyType;
this.interestRateFrequencyType = productData.interestRateFrequencyType;
this.amortizationType = productData.amortizationType;
this.interestType = productData.interestType;
this.interestCalculationPeriodType = productData.interestCalculationPeriodType;
this.fundId = productData.fundId;
this.fundName = productData.fundName;
this.transactionProcessingStrategyId = productData.transactionProcessingStrategyId;
this.transactionProcessingStrategyName = productData.transactionProcessingStrategyName;
this.charges = productData.charges();
this.chargeOptions = chargeOptions;
this.currencyOptions = currencyOptions;
if (this.currencyOptions.size() == 1) {
this.currency = this.currencyOptions.get(0);
} else {
this.currency = productData.currency;
}
this.fundOptions = fundOptions;
this.transactionProcessingStrategyOptions = transactionProcessingStrategyOptions;
this.amortizationTypeOptions = amortizationTypeOptions;
this.interestTypeOptions = interestTypeOptions;
this.interestCalculationPeriodTypeOptions = interestCalculationPeriodTypeOptions;
this.loanTermFrequencyTypeOptions = loanTermFrequencyTypeOptions;
this.repaymentFrequencyTypeOptions = repaymentFrequencyTypeOptions;
this.interestRateFrequencyTypeOptions = interestRateFrequencyTypeOptions;
}
public Collection<ChargeData> charges() {
Collection<ChargeData> chargesLocal = new ArrayList<ChargeData>();
if (this.charges != null) {
chargesLocal = this.charges;
}
return chargesLocal;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public Long getFundId() {
return fundId;
}
public String getFundName() {
return fundName;
}
public Long getTransactionProcessingStrategyId() {
return transactionProcessingStrategyId;
}
public String getTransactionProcessingStrategyName() {
return transactionProcessingStrategyName;
}
public CurrencyData getCurrency() {
return currency;
}
public BigDecimal getPrincipal() {
return principal;
}
public BigDecimal getInArrearsTolerance() {
return inArrearsTolerance;
}
public Integer getNumberOfRepayments() {
return numberOfRepayments;
}
public Integer getLoanTermFrequency() {
return loanTermFrequency;
}
public Integer getRepaymentEvery() {
return repaymentEvery;
}
public BigDecimal getInterestRatePerPeriod() {
return interestRatePerPeriod;
}
public BigDecimal getAnnualInterestRate() {
return annualInterestRate;
}
public EnumOptionData getLoanTermFrequencyType() {
return loanTermFrequencyType;
}
public EnumOptionData getRepaymentFrequencyType() {
return repaymentFrequencyType;
}
public EnumOptionData getInterestRateFrequencyType() {
return interestRateFrequencyType;
}
public EnumOptionData getAmortizationType() {
return amortizationType;
}
public EnumOptionData getInterestType() {
return interestType;
}
public EnumOptionData getInterestCalculationPeriodType() {
return interestCalculationPeriodType;
}
public DateTime getCreatedOn() {
return createdOn;
}
public DateTime getLastModifedOn() {
return lastModifedOn;
}
public List<CurrencyData> getCurrencyOptions() {
return currencyOptions;
}
public Collection<FundData> getFundOptions() {
return fundOptions;
}
public Collection<TransactionProcessingStrategyData> getTransactionProcessingStrategyOptions() {
return transactionProcessingStrategyOptions;
}
public List<EnumOptionData> getAmortizationTypeOptions() {
return amortizationTypeOptions;
}
public List<EnumOptionData> getInterestTypeOptions() {
return interestTypeOptions;
}
public List<EnumOptionData> getInterestCalculationPeriodTypeOptions() {
return interestCalculationPeriodTypeOptions;
}
public List<EnumOptionData> getRepaymentFrequencyTypeOptions() {
return repaymentFrequencyTypeOptions;
}
public List<EnumOptionData> getInterestRateFrequencyTypeOptions() {
return interestRateFrequencyTypeOptions;
}
public List<EnumOptionData> getLoanTermFrequencyTypeOptions() {
return loanTermFrequencyTypeOptions;
}
public Collection<ChargeData> getChargeOptions() {
return chargeOptions;
}
}
@@ -17,7 +17,6 @@ import org.mifosng.platform.api.data.GroupData;
import org.mifosng.platform.api.data.GuarantorData;
import org.mifosng.platform.api.data.LoanAccountData;
import org.mifosng.platform.api.data.LoanChargeData;
import org.mifosng.platform.api.data.LoanProductData;
import org.mifosng.platform.api.data.LoanScheduleData;
import org.mifosng.platform.api.data.LoanTransactionData;
import org.mifosng.platform.api.data.NoteData;
@@ -40,6 +39,7 @@ import org.mifosplatform.infrastructure.user.api.data.RoleData;
import org.mifosplatform.infrastructure.user.api.data.RolePermissionsData;
import org.mifosplatform.portfolio.charge.data.ChargeData;
import org.mifosplatform.portfolio.fund.data.FundData;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -13,7 +13,6 @@ import org.mifosng.platform.api.commands.GroupCommand;
import org.mifosng.platform.api.commands.GuarantorCommand;
import org.mifosng.platform.api.commands.LoanApplicationCommand;
import org.mifosng.platform.api.commands.LoanChargeCommand;
import org.mifosng.platform.api.commands.LoanProductCommand;
import org.mifosng.platform.api.commands.LoanStateTransitionCommand;
import org.mifosng.platform.api.commands.LoanTransactionCommand;
import org.mifosng.platform.api.commands.NoteCommand;
@@ -32,6 +31,7 @@ import org.mifosplatform.infrastructure.user.command.RolePermissionCommand;
import org.mifosplatform.infrastructure.user.command.UserCommand;
import org.mifosplatform.portfolio.charge.command.ChargeDefinitionCommand;
import org.mifosplatform.portfolio.fund.command.FundCommand;
import org.mifosplatform.portfolio.loanproduct.command.LoanProductCommand;
public interface PortfolioApiDataConversionService {
@@ -51,7 +51,7 @@ public interface PortfolioApiDataConversionService {
BranchMoneyTransferCommand convertApiRequestJsonToBranchMoneyTransferCommand(String json);
LoanProductCommand convertJsonToLoanProductCommand(Long resourceIdentifier, String json);
LoanProductCommand convertApiRequestJsonToLoanProductCommand(Long resourceIdentifier, String json);
SavingProductCommand convertJsonToSavingProductCommand(Long resourceIdentifier, String json);
@@ -30,7 +30,6 @@ import org.mifosng.platform.api.commands.GroupCommand;
import org.mifosng.platform.api.commands.GuarantorCommand;
import org.mifosng.platform.api.commands.LoanApplicationCommand;
import org.mifosng.platform.api.commands.LoanChargeCommand;
import org.mifosng.platform.api.commands.LoanProductCommand;
import org.mifosng.platform.api.commands.LoanStateTransitionCommand;
import org.mifosng.platform.api.commands.LoanTransactionCommand;
import org.mifosng.platform.api.commands.NoteCommand;
@@ -54,6 +53,7 @@ import org.mifosplatform.infrastructure.user.command.RolePermissionCommand;
import org.mifosplatform.infrastructure.user.command.UserCommand;
import org.mifosplatform.portfolio.charge.command.ChargeDefinitionCommand;
import org.mifosplatform.portfolio.fund.command.FundCommand;
import org.mifosplatform.portfolio.loanproduct.command.LoanProductCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.number.NumberFormatter;
import org.springframework.stereotype.Service;
@@ -518,7 +518,7 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo
}
@Override
public LoanProductCommand convertJsonToLoanProductCommand(final Long resourceIdentifier, final String json) {
public LoanProductCommand convertApiRequestJsonToLoanProductCommand(final Long resourceIdentifier, final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
@@ -581,7 +581,7 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo
}
}
return new LoanProductCommand(modifiedParameters, resourceIdentifier, name, description, fundId, transactionProcessingStrategyId,
return new LoanProductCommand(modifiedParameters, false, resourceIdentifier, name, description, fundId, transactionProcessingStrategyId,
currencyCode, digitsAfterDecimal, principal, inArrearsTolerance, numberOfRepayments, repaymentEvery, interestRatePerPeriod,
repaymentFrequencyType, interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, charges);
}
@@ -15,7 +15,6 @@ import org.mifosng.platform.api.data.GroupData;
import org.mifosng.platform.api.data.GuarantorData;
import org.mifosng.platform.api.data.LoanAccountData;
import org.mifosng.platform.api.data.LoanChargeData;
import org.mifosng.platform.api.data.LoanProductData;
import org.mifosng.platform.api.data.LoanScheduleData;
import org.mifosng.platform.api.data.LoanTransactionData;
import org.mifosng.platform.api.data.NoteData;
@@ -37,6 +36,7 @@ import org.mifosplatform.infrastructure.user.api.data.RoleData;
import org.mifosplatform.infrastructure.user.api.data.RolePermissionsData;
import org.mifosplatform.portfolio.charge.data.ChargeData;
import org.mifosplatform.portfolio.fund.data.FundData;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
public interface PortfolioApiJsonSerializerService {
@@ -21,6 +21,7 @@ import org.mifosplatform.infrastructure.user.command.RolePermissionCommand;
import org.mifosplatform.infrastructure.user.command.UserCommand;
import org.mifosplatform.portfolio.charge.command.ChargeDefinitionCommand;
import org.mifosplatform.portfolio.fund.command.FundCommand;
import org.mifosplatform.portfolio.loanproduct.command.LoanProductCommand;
import org.springframework.stereotype.Service;
import com.google.gson.Gson;
@@ -268,6 +269,55 @@ public class PortfolioCommandDeerializerServiceGoogleGson implements PortfolioCo
return new ClientCommand(parametersPassedInRequest, clientId, externalId, firstname, lastname, clientOrBusinessName,
officeId, joiningDate, makerCheckerApproval);
}
@Override
public LoanProductCommand deserializeLoanProductCommand(final Long loanProductId, final String commandAsJson, final boolean makerCheckerApproval) {
if (StringUtils.isBlank(commandAsJson)) { throw new InvalidJsonException(); }
final JsonParserHelper helper = new JsonParserHelper();
final JsonElement element = parser.parse(commandAsJson);
final Set<String> parametersPassedInRequest = new HashSet<String>();
final String name = helper.extractStringNamed("name", element, parametersPassedInRequest);
final String description = helper.extractStringNamed("description", element, parametersPassedInRequest);
final Long fundId = helper.extractLongNamed("fundId", element, parametersPassedInRequest);
final Long transactionProcessingStrategyId = helper
.extractLongNamed("transactionProcessingStrategyId", element, parametersPassedInRequest);
final String currencyCode = helper.extractStringNamed("currencyCode", element, parametersPassedInRequest);
final Integer digitsAfterDecimal = helper.extractIntegerNamed("digitsAfterDecimal", element, Locale.US, parametersPassedInRequest);
final BigDecimal principal = helper.extractBigDecimalNamed("principal", element.getAsJsonObject(), Locale.US, parametersPassedInRequest);
final BigDecimal inArrearsTolerance = helper.extractBigDecimalNamed("inArrearsTolerance", element.getAsJsonObject(), Locale.US, parametersPassedInRequest);
final BigDecimal interestRatePerPeriod = helper.extractBigDecimalNamed("interestRatePerPeriod", element.getAsJsonObject(), Locale.US, parametersPassedInRequest);
final Integer repaymentEvery = helper.extractIntegerNamed("repaymentEvery", element, Locale.US, parametersPassedInRequest);
final Integer numberOfRepayments = helper.extractIntegerNamed("numberOfRepayments", element, Locale.US, parametersPassedInRequest);
final Integer repaymentFrequencyType = helper.extractIntegerNamed("repaymentFrequencyType", element, Locale.US, parametersPassedInRequest);
final Integer interestRateFrequencyType = helper.extractIntegerNamed("interestRateFrequencyType", element, Locale.US, parametersPassedInRequest);
final Integer amortizationType = helper.extractIntegerNamed("amortizationType", element, Locale.US, parametersPassedInRequest);
final Integer interestType = helper.extractIntegerNamed("interestType", element, Locale.US, parametersPassedInRequest);
final Integer interestCalculationPeriodType = helper.extractIntegerNamed("interestCalculationPeriodType", element, Locale.US,
parametersPassedInRequest);
String[] charges = null;
if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
if (object.has("charges")) {
parametersPassedInRequest.add("charges");
JsonArray array = object.get("charges").getAsJsonArray();
charges = new String[array.size()];
for (int i = 0; i < array.size(); i++) {
charges[i] = array.get(i).getAsString();
}
}
}
return new LoanProductCommand(parametersPassedInRequest, makerCheckerApproval, loanProductId, name, description, fundId, transactionProcessingStrategyId,
currencyCode, digitsAfterDecimal, principal, inArrearsTolerance, numberOfRepayments, repaymentEvery, interestRatePerPeriod,
repaymentFrequencyType, interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, charges);
}
}
@@ -12,6 +12,7 @@ import org.mifosplatform.infrastructure.user.command.RolePermissionCommand;
import org.mifosplatform.infrastructure.user.command.UserCommand;
import org.mifosplatform.portfolio.charge.command.ChargeDefinitionCommand;
import org.mifosplatform.portfolio.fund.command.FundCommand;
import org.mifosplatform.portfolio.loanproduct.command.LoanProductCommand;
/**
* Service for de-serializing JSON for a command into the platforms internal
@@ -48,4 +49,6 @@ public interface PortfolioCommandDeserializerService {
ChargeDefinitionCommand deserializeChargeDefinitionCommand(Long chargeDefinitionId, String commandAsJson, boolean makerCheckerApproval);
ClientCommand deserializeClientCommand(Long clientId, String commandAsJson, boolean makerCheckerApproval);
LoanProductCommand deserializeLoanProductCommand(Long resourceId, String json, boolean b);
}
@@ -1,42 +0,0 @@
package org.mifosng.platform.loan.domain;
public enum AmortizationMethod {
EQUAL_PRINCIPAL(0, "amortizationType.equal.principal"), EQUAL_INSTALLMENTS(1, "amortizationType.equal.installments"), INVALID(2, "amortizationType.invalid");
private final Integer value;
private final String code;
private AmortizationMethod(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return code;
}
public static AmortizationMethod fromInt(final Integer selectedMethod) {
if (selectedMethod == null) {
return null;
}
AmortizationMethod repaymentMethod = null;
switch (selectedMethod) {
case 0:
repaymentMethod = AmortizationMethod.EQUAL_PRINCIPAL;
break;
case 1:
repaymentMethod = AmortizationMethod.EQUAL_INSTALLMENTS;
break;
default:
repaymentMethod = AmortizationMethod.INVALID;
break;
}
return repaymentMethod;
}
}
@@ -1,38 +0,0 @@
package org.mifosng.platform.loan.domain;
public enum InterestCalculationPeriodMethod {
DAILY(0, "interestCalculationPeriodType.daily"), SAME_AS_REPAYMENT_PERIOD(1, "interestCalculationPeriodType.same.as.repayment.period"), INVALID(2, "interestCalculationPeriodType.invalid");
private final Integer value;
private final String code;
private InterestCalculationPeriodMethod(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return code;
}
public static InterestCalculationPeriodMethod fromInt(final Integer selectedMethod) {
InterestCalculationPeriodMethod repaymentMethod = null;
switch (selectedMethod) {
case 0:
repaymentMethod = InterestCalculationPeriodMethod.DAILY;
break;
case 1:
repaymentMethod = InterestCalculationPeriodMethod.SAME_AS_REPAYMENT_PERIOD;
break;
default:
repaymentMethod = InterestCalculationPeriodMethod.INVALID;
break;
}
return repaymentMethod;
}
}
@@ -1,38 +0,0 @@
package org.mifosng.platform.loan.domain;
public enum InterestMethod {
DECLINING_BALANCE(0, "interestType.declining.balance"), FLAT(1, "interestType.flat"), INVALID(2, "interestType.invalid");
private final Integer value;
private final String code;
private InterestMethod(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return code;
}
public static InterestMethod fromInt(final Integer selectedMethod) {
InterestMethod repaymentMethod = null;
switch (selectedMethod) {
case 0:
repaymentMethod = InterestMethod.DECLINING_BALANCE;
break;
case 1:
repaymentMethod = InterestMethod.FLAT;
break;
default:
repaymentMethod = InterestMethod.INVALID;
break;
}
return repaymentMethod;
}
}
@@ -42,6 +42,10 @@ import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.infrastructure.staff.domain.Staff;
import org.mifosplatform.infrastructure.user.domain.AppUser;
import org.mifosplatform.portfolio.fund.domain.Fund;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
import org.mifosplatform.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
@Entity
@Table(name = "m_loan", uniqueConstraints = @UniqueConstraint(columnNames = { "external_id" }))
@@ -1,139 +0,0 @@
package org.mifosng.platform.loan.domain;
import java.math.BigDecimal;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.apache.commons.lang.StringUtils;
import org.mifosng.platform.api.commands.LoanProductCommand;
import org.mifosng.platform.infrastructure.AbstractAuditableCustom;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.user.domain.AppUser;
import org.mifosplatform.portfolio.charge.domain.Charge;
import org.mifosplatform.portfolio.fund.domain.Fund;
/**
* Loan products allow for categorisation of an organisations loans into something meaningful to them.
*
* They provide a means of simplifying creation/maintenance of loans.
* They can also allow for product comparison to take place when reporting.
*
* They allow for constraints to be added at product level.
*/
@Entity
@Table(name = "m_product_loan")
public class LoanProduct extends AbstractAuditableCustom<AppUser, Long> {
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "fund_id", nullable = true)
private Fund fund;
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "loan_transaction_strategy_id", nullable = true)
private LoanTransactionProcessingStrategy transactionProcessingStrategy;
@SuppressWarnings("unused")
@Column(name = "name", nullable = false)
private String name;
@SuppressWarnings("unused")
@Column(name = "description")
private String description;
@ManyToMany
@JoinTable(name = "m_product_loan_charge",
joinColumns = @JoinColumn(name = "product_loan_id"),
inverseJoinColumns = @JoinColumn(name = "charge_id"))
private Set<Charge> charges;
@Embedded
private final LoanProductRelatedDetail loanProductRelatedDetail;
protected LoanProduct() {
this.loanProductRelatedDetail = null;
}
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,
final Set<Charge> charges) {
this.fund = fund;
this.transactionProcessingStrategy = transactionProcessingStrategy;
this.name = name.trim();
if (StringUtils.isNotBlank(description)) {
this.description = description.trim();
} else {
this.description = null;
}
if (charges != null){
this.charges = charges;
}
this.loanProductRelatedDetail = new LoanProductRelatedDetail(currency,
defaultPrincipal, defaultNominalInterestRatePerPeriod, interestPeriodFrequencyType, defaultAnnualNominalInterestRate,
interestMethod, interestCalculationPeriodMethod,
repayEvery, repaymentFrequencyType, defaultNumberOfInstallments, amortizationMethod, inArrearsTolerance);
}
public MonetaryCurrency getCurrency() {
return this.loanProductRelatedDetail.getCurrency();
}
public Set<Charge> getCharges() {
return charges;
}
public void update(
final LoanProductCommand command,
final Fund fund,
final LoanTransactionProcessingStrategy strategy,
final Set<Charge> charges) {
if (command.isNameChanged()) {
this.name = command.getName();
}
if (command.isDescriptionChanged()) {
this.description = command.getDescription();
}
if (command.isFundChanged()) {
this.fund = fund;
}
if (command.isTransactionProcessingStrategyChanged()) {
this.transactionProcessingStrategy = strategy;
}
if (command.isChargesChanged()){
this.charges = charges;
}
this.loanProductRelatedDetail.update(command);
}
}
@@ -1,195 +0,0 @@
package org.mifosng.platform.loan.domain;
import java.math.BigDecimal;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import org.mifosng.platform.api.commands.LoanProductCommand;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.domain.Money;
/**
* LoanRepaymentScheduleDetail encapsulates all the details of a
* {@link LoanProduct} that are also used and persisted by a {@link Loan}.
*/
@Embeddable
public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentScheduleRelatedDetail {
@Embedded
private MonetaryCurrency currency;
@Column(name = "principal_amount", scale = 6, precision = 19, nullable = false)
private BigDecimal principal;
@Column(name = "nominal_interest_rate_per_period", scale = 6, precision = 19, nullable = false)
private BigDecimal nominalInterestRatePerPeriod;
@Enumerated(EnumType.ORDINAL)
@Column(name = "interest_period_frequency_enum", nullable = false)
private PeriodFrequencyType interestPeriodFrequencyType;
@Column(name = "annual_nominal_interest_rate", scale = 6, precision = 19, nullable = false)
private BigDecimal annualNominalInterestRate;
@Enumerated(EnumType.ORDINAL)
@Column(name = "interest_method_enum", nullable = false)
private InterestMethod interestMethod;
@Enumerated(EnumType.ORDINAL)
@Column(name = "interest_calculated_in_period_enum", nullable = false)
private InterestCalculationPeriodMethod interestCalculationPeriodMethod;
@Column(name = "repay_every", nullable = false)
private Integer repayEvery;
@Enumerated(EnumType.ORDINAL)
@Column(name = "repayment_period_frequency_enum", nullable = false)
private PeriodFrequencyType repaymentPeriodFrequencyType;
@Column(name = "number_of_repayments", nullable = false)
private Integer numberOfRepayments;
@Enumerated(EnumType.ORDINAL)
@Column(name = "amortization_method_enum", nullable = false)
private AmortizationMethod amortizationMethod;
@Column(name = "arrearstolerance_amount", scale = 6, precision = 19, nullable = true)
private BigDecimal inArrearsTolerance;
protected LoanProductRelatedDetail() {
//
}
public LoanProductRelatedDetail(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 defaultNumberOfRepayments,
final AmortizationMethod amortizationMethod,
final BigDecimal inArrearsTolerance) {
this.currency = currency;
this.principal = defaultPrincipal;
this.nominalInterestRatePerPeriod = defaultNominalInterestRatePerPeriod;
this.interestPeriodFrequencyType = interestPeriodFrequencyType;
this.annualNominalInterestRate = defaultAnnualNominalInterestRate;
this.interestMethod = interestMethod;
this.interestCalculationPeriodMethod = interestCalculationPeriodMethod;
this.repayEvery = repayEvery;
this.repaymentPeriodFrequencyType = repaymentFrequencyType;
this.numberOfRepayments = defaultNumberOfRepayments;
this.amortizationMethod = amortizationMethod;
if (inArrearsTolerance != null && BigDecimal.ZERO.compareTo(inArrearsTolerance) == 0) {
this.inArrearsTolerance = null;
} else {
this.inArrearsTolerance = inArrearsTolerance;
}
}
public MonetaryCurrency getCurrency() {
return this.currency.copy();
}
public Money getPrincipal() {
return Money.of(this.currency, this.principal);
}
public Money getInArrearsTolerance() {
return Money.of(this.currency, this.inArrearsTolerance);
}
public BigDecimal getNominalInterestRatePerPeriod() {
return BigDecimal.valueOf(Double.valueOf(this.nominalInterestRatePerPeriod.stripTrailingZeros().toString())) ;
}
public PeriodFrequencyType getInterestPeriodFrequencyType() {
return interestPeriodFrequencyType;
}
public BigDecimal getAnnualNominalInterestRate() {
return BigDecimal.valueOf(Double.valueOf(this.annualNominalInterestRate.stripTrailingZeros().toString())) ;
}
public InterestMethod getInterestMethod() {
return interestMethod;
}
public InterestCalculationPeriodMethod getInterestCalculationPeriodMethod() {
return interestCalculationPeriodMethod;
}
@Override
public Integer getRepayEvery() {
return repayEvery;
}
@Override
public PeriodFrequencyType getRepaymentPeriodFrequencyType() {
return repaymentPeriodFrequencyType;
}
@Override
public Integer getNumberOfRepayments() {
return numberOfRepayments;
}
public AmortizationMethod getAmortizationMethod() {
return amortizationMethod;
}
public void update(final LoanProductCommand command) {
Integer digitsAfterDecimalChanged = this.currency.getDigitsAfterDecimal();
if (command.isDigitsAfterDecimalChanged()) {
digitsAfterDecimalChanged = command.getDigitsAfterDecimal();
}
String currencyCodeChanged = this.currency.getCode();
if (command.isCurrencyCodeChanged()) {
currencyCodeChanged = command.getCurrencyCode();
}
if (command.isDigitsAfterDecimalChanged() || command.isCurrencyCodeChanged()) {
this.currency = new MonetaryCurrency(currencyCodeChanged, digitsAfterDecimalChanged);
}
if (command.isPrincipalChanged()) {
this.principal = command.getPrincipal();
}
if (command.isRepaymentEveryChanged()) {
this.repayEvery = command.getRepaymentEvery();
}
if (command.isRepaymentFrequencyTypeChanged()) {
this.repaymentPeriodFrequencyType = PeriodFrequencyType.fromInt(command.getRepaymentFrequencyType());
}
if (command.isNumberOfRepaymentsChanged()) {
this.numberOfRepayments = command.getNumberOfRepayments();
}
if (command.isAmortizationTypeChanged()) {
this.amortizationMethod = AmortizationMethod.fromInt(command.getAmortizationType());
}
if (command.isInArrearsToleranceChanged()) {
this.inArrearsTolerance = command.getInArrearsTolerance();
}
if (command.isInterestRatePerPeriodChanged()) {
this.nominalInterestRatePerPeriod = command.getInterestRatePerPeriod();
}
if (command.isInterestRateFrequencyTypeChanged()) {
this.interestPeriodFrequencyType = PeriodFrequencyType.fromInt(command.getInterestRateFrequencyType());
}
if (command.isInterestTypeChanged()) {
this.interestMethod = InterestMethod.fromInt(command.getInterestType());
}
if (command.isInterestCalculationPeriodTypeChanged()) {
this.interestCalculationPeriodMethod = InterestCalculationPeriodMethod.fromInt(command.getInterestCalculationPeriodType());
}
}
}
@@ -1,9 +0,0 @@
package org.mifosng.platform.loan.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface LoanProductRepository extends
JpaRepository<LoanProduct, Long>, JpaSpecificationExecutor<LoanProduct> {
// no behaviour added
}
@@ -1,5 +1,7 @@
package org.mifosng.platform.loan.domain;
import org.mifosplatform.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
/**
*
@@ -19,11 +19,11 @@ import org.joda.time.LocalDate;
import org.mifosng.platform.api.data.EnumOptionData;
import org.mifosng.platform.api.data.LoanTransactionData;
import org.mifosng.platform.infrastructure.AbstractAuditableCustom;
import org.mifosng.platform.loanproduct.service.LoanEnumerations;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.infrastructure.user.domain.AppUser;
import org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations;
import org.springframework.format.annotation.DateTimeFormat;
/**
@@ -1,47 +0,0 @@
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.mifosplatform.infrastructure.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 TransactionProcessingStrategyData toData() {
return new TransactionProcessingStrategyData(this.getId(), this.code, this.name);
}
public boolean isStandardMifosStrategy() {
return "mifos-standard-strategy".equalsIgnoreCase(this.code);
}
public boolean isHeavensfamilyStrategy() {
return "heavensfamily-strategy".equalsIgnoreCase(this.code);
}
public boolean isCreocoreStrategy() {
return "creocore-strategy".equalsIgnoreCase(this.code);
}
public boolean isIndianRBIStrategy() {
return "rbi-india-strategy".equalsIgnoreCase(this.code);
}
}
@@ -1,5 +1,6 @@
package org.mifosng.platform.loan.domain;
import org.mifosplatform.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -1,48 +0,0 @@
package org.mifosng.platform.loan.domain;
public enum PeriodFrequencyType {
DAYS(0, "periodFrequencyType.days"), //
WEEKS(1, "periodFrequencyType.weeks"), //
MONTHS(2, "periodFrequencyType.months"), //
YEARS(3, "periodFrequencyType.years"), //
INVALID(4, "periodFrequencyType.invalid");
private final Integer value;
private final String code;
private PeriodFrequencyType(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return code;
}
public static PeriodFrequencyType fromInt(final Integer frequency) {
PeriodFrequencyType repaymentFrequencyType = PeriodFrequencyType.INVALID;
switch (frequency) {
case 0:
repaymentFrequencyType = PeriodFrequencyType.DAYS;
break;
case 1:
repaymentFrequencyType = PeriodFrequencyType.WEEKS;
break;
case 2:
repaymentFrequencyType = PeriodFrequencyType.MONTHS;
break;
case 3:
repaymentFrequencyType = PeriodFrequencyType.YEARS;
break;
default:
repaymentFrequencyType = PeriodFrequencyType.INVALID;
break;
}
return repaymentFrequencyType;
}
}
@@ -4,16 +4,16 @@ import java.util.Set;
import org.mifosng.platform.api.commands.CalculateLoanScheduleCommand;
import org.mifosng.platform.api.data.LoanScheduleData;
import org.mifosng.platform.loan.domain.InterestMethod;
import org.mifosng.platform.loan.domain.LoanCharge;
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosng.platform.loanschedule.domain.DefaultLoanScheduleGeneratorFactory;
import org.mifosng.platform.loanschedule.domain.LoanScheduleGenerator;
import org.mifosng.platform.loanschedule.domain.LoanScheduleGeneratorFactory;
import org.mifosplatform.infrastructure.configuration.domain.ApplicationCurrency;
import org.mifosplatform.infrastructure.configuration.domain.ApplicationCurrencyRepository;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.loanproduct.domain.InterestMethod;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -19,27 +19,27 @@ import org.mifosng.platform.exceptions.StaffNotFoundException;
import org.mifosng.platform.exceptions.StaffRoleException;
import org.mifosng.platform.group.domain.Group;
import org.mifosng.platform.group.domain.GroupRepository;
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.LoanCharge;
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.LoanStatus;
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.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.staff.domain.Staff;
import org.mifosplatform.infrastructure.staff.domain.StaffRepository;
import org.mifosplatform.portfolio.fund.domain.Fund;
import org.mifosplatform.portfolio.fund.domain.FundRepository;
import org.mifosplatform.portfolio.loanproduct.domain.AmortizationMethod;
import org.mifosplatform.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
import org.mifosplatform.portfolio.loanproduct.domain.InterestMethod;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRepository;
import org.mifosplatform.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -4,15 +4,15 @@ import java.math.BigDecimal;
import org.mifosng.platform.api.commands.CalculateLoanScheduleCommand;
import org.mifosng.platform.exceptions.LoanProductNotFoundException;
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.LoanProduct;
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
import org.mifosng.platform.loan.domain.LoanProductRepository;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosng.platform.loanschedule.domain.AprCalculator;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.portfolio.loanproduct.domain.AmortizationMethod;
import org.mifosplatform.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
import org.mifosplatform.portfolio.loanproduct.domain.InterestMethod;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRepository;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -14,7 +14,6 @@ import org.mifosng.platform.api.data.GroupData;
import org.mifosng.platform.api.data.LoanBasicDetailsData;
import org.mifosng.platform.api.data.LoanChargeData;
import org.mifosng.platform.api.data.LoanPermissionData;
import org.mifosng.platform.api.data.LoanProductData;
import org.mifosng.platform.api.data.LoanScheduleData;
import org.mifosng.platform.api.data.LoanSchedulePeriodData;
import org.mifosng.platform.api.data.LoanTransactionData;
@@ -30,14 +29,15 @@ import org.mifosng.platform.loan.domain.LoanRepository;
import org.mifosng.platform.loan.domain.LoanTransaction;
import org.mifosng.platform.loan.domain.LoanTransactionRepository;
import org.mifosng.platform.loan.domain.LoanTransactionType;
import org.mifosng.platform.loanproduct.service.LoanEnumerations;
import org.mifosng.platform.loanproduct.service.LoanProductReadPlatformService;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.configuration.domain.ApplicationCurrency;
import org.mifosplatform.infrastructure.configuration.domain.ApplicationCurrencyRepository;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
import org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations;
import org.mifosplatform.portfolio.loanproduct.service.LoanProductReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
@@ -38,15 +38,11 @@ import org.mifosng.platform.loan.domain.Loan;
import org.mifosng.platform.loan.domain.LoanCharge;
import org.mifosng.platform.loan.domain.LoanChargeRepository;
import org.mifosng.platform.loan.domain.LoanLifecycleStateMachine;
import org.mifosng.platform.loan.domain.LoanProduct;
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.LoanTransaction;
import org.mifosng.platform.loan.domain.LoanTransactionProcessingStrategy;
import org.mifosng.platform.loan.domain.LoanTransactionRepository;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
@@ -57,6 +53,10 @@ import org.mifosplatform.infrastructure.user.domain.AppUser;
import org.mifosplatform.portfolio.charge.domain.Charge;
import org.mifosplatform.portfolio.charge.domain.ChargeRepository;
import org.mifosplatform.portfolio.fund.domain.Fund;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRepository;
import org.mifosplatform.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
@@ -1,14 +0,0 @@
package org.mifosng.platform.loanproduct.service;
import org.mifosng.platform.api.commands.LoanProductCommand;
import org.mifosng.platform.api.data.EntityIdentifier;
import org.springframework.security.access.prepost.PreAuthorize;
public interface LoanProductWritePlatformService {
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'ORGANISATION_ADMINISTRATION_SUPER_USER', 'CREATE_LOANPRODUCT')")
EntityIdentifier createLoanProduct(LoanProductCommand command);
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'ORGANISATION_ADMINISTRATION_SUPER_USER', 'UPDATE_LOANPRODUCT')")
EntityIdentifier updateLoanProduct(LoanProductCommand command);
}
@@ -1,187 +0,0 @@
package org.mifosng.platform.loanproduct.service;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.Set;
import org.mifosng.platform.api.commands.LoanProductCommand;
import org.mifosng.platform.api.data.EntityIdentifier;
import org.mifosng.platform.exceptions.ChargeIsNotActiveException;
import org.mifosng.platform.exceptions.ChargeNotFoundException;
import org.mifosng.platform.exceptions.FundNotFoundException;
import org.mifosng.platform.exceptions.InvalidCurrencyException;
import org.mifosng.platform.exceptions.LoanProductNotFoundException;
import org.mifosng.platform.exceptions.LoanTransactionProcessingStrategyNotFoundException;
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.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.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.charge.domain.Charge;
import org.mifosplatform.portfolio.charge.domain.ChargeRepository;
import org.mifosplatform.portfolio.fund.domain.Fund;
import org.mifosplatform.portfolio.fund.domain.FundRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
@Service
public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanProductWritePlatformService {
private final PlatformSecurityContext context;
private final LoanProductRepository loanProductRepository;
private final AprCalculator aprCalculator;
private final FundRepository fundRepository;
private final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository;
private final ChargeRepository chargeRepository;
@Autowired
public LoanProductWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final LoanProductRepository loanProductRepository,
final AprCalculator aprCalculator, final FundRepository fundRepository, final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository,
final ChargeRepository chargeRepository) {
this.context = context;
this.loanProductRepository = loanProductRepository;
this.aprCalculator = aprCalculator;
this.fundRepository = fundRepository;
this.loanTransactionProcessingStrategyRepository = loanTransactionProcessingStrategyRepository;
this.chargeRepository = chargeRepository;
}
@Transactional
@Override
public EntityIdentifier createLoanProduct(final LoanProductCommand command) {
this.context.authenticatedUser();
LoanProductCommandValidator validator = new LoanProductCommandValidator(command);
validator.validateForCreate();
// assemble LoanProduct from data
InterestMethod interestMethod = InterestMethod.fromInt(command.getInterestType());
InterestCalculationPeriodMethod interestCalculationPeriodMethod = InterestCalculationPeriodMethod.fromInt(command.getInterestCalculationPeriodType());
AmortizationMethod amortizationMethod = AmortizationMethod.fromInt(command.getAmortizationType());
PeriodFrequencyType repaymentFrequencyType = PeriodFrequencyType
.fromInt(command.getRepaymentFrequencyType());
PeriodFrequencyType interestFrequencyType = PeriodFrequencyType
.fromInt(command.getInterestRateFrequencyType());
MonetaryCurrency currency = new MonetaryCurrency(command.getCurrencyCode(), command.getDigitsAfterDecimal());
BigDecimal annualInterestRate = this.aprCalculator.calculateFrom(interestFrequencyType, command.getInterestRatePerPeriod());
// associating fund with loan product at creation is optional for now.
Fund fund = findFundByIdIfProvided(command.getFundId());
LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(command.getTransactionProcessingStrategyId());
final Set<Charge> charges = this.assembleSetOfCharges(command, null);
LoanProduct loanproduct = new LoanProduct(fund, loanTransactionProcessingStrategy,
command.getName(), command.getDescription(),
currency, command.getPrincipal(),
command.getInterestRatePerPeriod(), interestFrequencyType, annualInterestRate, interestMethod, interestCalculationPeriodMethod,
command.getRepaymentEvery(), repaymentFrequencyType, command.getNumberOfRepayments(),
amortizationMethod, command.getInArrearsTolerance(), charges);
this.loanProductRepository.save(loanproduct);
return new EntityIdentifier(loanproduct.getId());
}
private LoanTransactionProcessingStrategy findStrategyByIdIfProvided(final Long transactionProcessingStrategyId) {
LoanTransactionProcessingStrategy strategy = null;
if (transactionProcessingStrategyId != null) {
strategy = this.loanTransactionProcessingStrategyRepository.findOne(transactionProcessingStrategyId);
if (strategy == null) {
throw new LoanTransactionProcessingStrategyNotFoundException(transactionProcessingStrategyId);
}
}
return strategy;
}
private Fund findFundByIdIfProvided(final Long fundId) {
Fund fund = null;
if (fundId != null) {
fund = this.fundRepository.findOne(fundId);
if (fund == null) {
throw new FundNotFoundException(fundId);
}
}
return fund;
}
@Transactional
@Override
public EntityIdentifier updateLoanProduct(final LoanProductCommand command) {
this.context.authenticatedUser();
LoanProductCommandValidator validator = new LoanProductCommandValidator(command);
validator.validateForUpdate();
LoanProduct product = this.loanProductRepository.findOne(command.getId());
if (product == null) {
throw new LoanProductNotFoundException(command.getId());
}
// associating fund with loan product at creation is optional for now.
Fund fund = null;
if (command.isFundChanged()) {
fund = findFundByIdIfProvided(command.getFundId());
}
LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = null;
if (command.isTransactionProcessingStrategyChanged()) {
loanTransactionProcessingStrategy = findStrategyByIdIfProvided(command.getTransactionProcessingStrategyId());
}
final Set<Charge> charges = this.assembleSetOfCharges(command, product.getCurrency().getCode());
product.update(command, fund, loanTransactionProcessingStrategy, charges);
this.loanProductRepository.save(product);
return new EntityIdentifier(Long.valueOf(product.getId()));
}
private Set<Charge> assembleSetOfCharges(final LoanProductCommand command, final String currencyCode) {
Set<Charge> charges = new HashSet<Charge>();
String[] chargesArray = command.getCharges();
String loanProductCurrencyCode = command.getCurrencyCode();
if (loanProductCurrencyCode == null){
loanProductCurrencyCode = currencyCode;
}
if (command.isChargesChanged() && !ObjectUtils.isEmpty(chargesArray)) {
for (String chargeId : chargesArray) {
Long id = Long.valueOf(chargeId);
Charge charge = this.chargeRepository.findOne(id);
if (charge == null || charge.isDeleted()) {
throw new ChargeNotFoundException(id);
}
if (!charge.isActive()){
throw new ChargeIsNotActiveException(id, charge.getName());
}
if (!loanProductCurrencyCode.equals(charge.getCurrencyCode())){
String errorMessage = "Charge and Loan Product must have the same currency.";
throw new InvalidCurrencyException("charge", "attach.to.loan.product", errorMessage);
}
charges.add(charge);
}
}
return charges;
}
}
@@ -7,8 +7,8 @@ import java.util.Set;
import org.joda.time.LocalDate;
import org.mifosng.platform.api.data.LoanScheduleData;
import org.mifosng.platform.loan.domain.LoanCharge;
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
import org.mifosplatform.infrastructure.configuration.domain.ApplicationCurrency;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
public interface AmortizationLoanScheduleGenerator {
@@ -1,6 +1,6 @@
package org.mifosng.platform.loanschedule.domain;
import org.mifosng.platform.loan.domain.AmortizationMethod;
import org.mifosplatform.portfolio.loanproduct.domain.AmortizationMethod;
public class AmortizationLoanScheduleGeneratorFactory {
@@ -2,7 +2,7 @@ package org.mifosng.platform.loanschedule.domain;
import java.math.BigDecimal;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.stereotype.Component;
@Component
@@ -6,11 +6,11 @@ import java.util.Set;
import org.joda.time.LocalDate;
import org.mifosng.platform.api.data.LoanScheduleData;
import org.mifosng.platform.loan.domain.AmortizationMethod;
import org.mifosng.platform.loan.domain.LoanCharge;
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosplatform.infrastructure.configuration.domain.ApplicationCurrency;
import org.mifosplatform.portfolio.loanproduct.domain.AmortizationMethod;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
/**
* <p>
@@ -1,6 +1,6 @@
package org.mifosng.platform.loanschedule.domain;
import org.mifosng.platform.loan.domain.InterestMethod;
import org.mifosplatform.portfolio.loanproduct.domain.InterestMethod;
public class DefaultLoanScheduleGeneratorFactory implements
LoanScheduleGeneratorFactory {
@@ -4,7 +4,7 @@ import java.util.List;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
public class DefaultPaymentPeriodsInOneYearCalculator implements
PaymentPeriodsInOneYearCalculator {
@@ -4,8 +4,8 @@ import java.util.ArrayList;
import java.util.List;
import org.joda.time.LocalDate;
import org.mifosng.platform.loan.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
@@ -11,11 +11,11 @@ import org.joda.time.LocalDate;
import org.mifosng.platform.api.data.LoanScheduleData;
import org.mifosng.platform.api.data.LoanSchedulePeriodData;
import org.mifosng.platform.loan.domain.LoanCharge;
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.configuration.domain.ApplicationCurrency;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
/**
* Irregular payments for declining balance not supported
@@ -11,11 +11,11 @@ import org.joda.time.LocalDate;
import org.mifosng.platform.api.data.LoanScheduleData;
import org.mifosng.platform.api.data.LoanSchedulePeriodData;
import org.mifosng.platform.loan.domain.LoanCharge;
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.configuration.domain.ApplicationCurrency;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
public class EqualPrincipalAmortizationLoanScheduleGenerator implements AmortizationLoanScheduleGenerator {
@@ -13,12 +13,12 @@ import org.joda.time.LocalDate;
import org.mifosng.platform.api.data.LoanScheduleData;
import org.mifosng.platform.api.data.LoanSchedulePeriodData;
import org.mifosng.platform.loan.domain.LoanCharge;
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.configuration.domain.ApplicationCurrency;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
public class FlatMethodLoanScheduleGenerator implements LoanScheduleGenerator {
@@ -5,9 +5,9 @@ import java.util.Set;
import org.joda.time.LocalDate;
import org.mifosng.platform.api.data.LoanScheduleData;
import org.mifosng.platform.loan.domain.LoanCharge;
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosplatform.infrastructure.configuration.domain.ApplicationCurrency;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
public interface LoanScheduleGenerator {
@@ -1,6 +1,6 @@
package org.mifosng.platform.loanschedule.domain;
import org.mifosng.platform.loan.domain.InterestMethod;
import org.mifosplatform.portfolio.loanproduct.domain.InterestMethod;
public interface LoanScheduleGeneratorFactory {
@@ -3,7 +3,7 @@ package org.mifosng.platform.loanschedule.domain;
import java.util.List;
import org.joda.time.LocalDate;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
public interface PaymentPeriodsInOneYearCalculator {
@@ -4,9 +4,9 @@ import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
public class PeriodicInterestRateCalculator {
@@ -2,9 +2,9 @@ package org.mifosng.platform.loanschedule.domain;
import java.math.BigDecimal;
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
public class PmtCalculator {
@@ -3,8 +3,8 @@ package org.mifosng.platform.loanschedule.domain;
import java.util.List;
import org.joda.time.LocalDate;
import org.mifosng.platform.loan.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
public interface ScheduledDateGenerator {
@@ -29,11 +29,11 @@ import org.mifosng.platform.api.commands.DepositStateTransitionApprovalCommand;
import org.mifosng.platform.client.domain.Client;
import org.mifosng.platform.exceptions.InvalidDepositStateTransitionException;
import org.mifosng.platform.infrastructure.AbstractAuditableCustom;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosng.platform.savingproduct.domain.DepositProduct;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.infrastructure.user.domain.AppUser;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
@Entity
@Table(name = "m_deposit_account", uniqueConstraints = @UniqueConstraint(name="deposit_acc_external_id", columnNames = { "external_id" }))
@@ -4,8 +4,8 @@ import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.stereotype.Service;
@Service
@@ -16,7 +16,6 @@ import javax.persistence.UniqueConstraint;
import org.joda.time.LocalDate;
import org.mifosng.platform.client.domain.Client;
import org.mifosng.platform.infrastructure.AbstractAuditableCustom;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosng.platform.savingproduct.domain.SavingFrequencyType;
import org.mifosng.platform.savingproduct.domain.SavingInterestCalculationMethod;
import org.mifosng.platform.savingproduct.domain.SavingProduct;
@@ -26,6 +25,7 @@ import org.mifosng.platform.savingproduct.domain.TenureTypeEnum;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.infrastructure.user.domain.AppUser;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
@Entity
@Table(name = "m_saving_account", uniqueConstraints = @UniqueConstraint(name="saving_acc_external_id", columnNames = { "external_id" }))
@@ -11,7 +11,6 @@ import org.mifosng.platform.client.domain.ClientRepository;
import org.mifosng.platform.exceptions.ClientNotFoundException;
import org.mifosng.platform.exceptions.DepositAccounDataValidationtException;
import org.mifosng.platform.exceptions.DepositProductNotFoundException;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosng.platform.saving.domain.DepositAccount;
import org.mifosng.platform.saving.domain.DepositAccountStatus;
import org.mifosng.platform.saving.domain.DepositLifecycleStateMachine;
@@ -20,6 +19,7 @@ import org.mifosng.platform.saving.domain.FixedTermDepositInterestCalculator;
import org.mifosng.platform.savingproduct.domain.DepositProduct;
import org.mifosng.platform.savingproduct.domain.DepositProductRepository;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -10,7 +10,6 @@ import org.mifosng.platform.client.domain.Client;
import org.mifosng.platform.client.domain.ClientRepository;
import org.mifosng.platform.exceptions.ClientNotFoundException;
import org.mifosng.platform.exceptions.ProductNotFoundException;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosng.platform.saving.domain.DepositAccountStatus;
import org.mifosng.platform.saving.domain.DepositLifecycleStateMachine;
import org.mifosng.platform.saving.domain.DepositLifecycleStateMachineImpl;
@@ -25,6 +24,7 @@ import org.mifosng.platform.savingproduct.domain.SavingsInterestType;
import org.mifosng.platform.savingproduct.domain.TenureTypeEnum;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -12,9 +12,9 @@ import org.apache.commons.lang.StringUtils;
import org.mifosng.platform.api.commands.DepositProductCommand;
import org.mifosng.platform.exceptions.ValueOutsideRangeException;
import org.mifosng.platform.infrastructure.AbstractAuditableCustom;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.user.domain.AppUser;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
@Entity
@Table(name = "m_product_deposit", uniqueConstraints={
@@ -10,9 +10,9 @@ import javax.persistence.Table;
import org.apache.commons.lang.StringUtils;
import org.mifosng.platform.api.commands.SavingProductCommand;
import org.mifosng.platform.infrastructure.AbstractAuditableCustom;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.user.domain.AppUser;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
@Entity
@Table(name = "m_product_savings")
@@ -7,8 +7,8 @@ import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import org.mifosng.platform.api.commands.SavingProductCommand;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
@Embeddable
public class SavingProductRelatedDetail {
@@ -12,9 +12,9 @@ import org.mifosng.platform.api.data.DepositProductLookup;
import org.mifosng.platform.api.data.EnumOptionData;
import org.mifosng.platform.infrastructure.JdbcSupport;
import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
@@ -4,11 +4,11 @@ import org.mifosng.platform.api.commands.DepositProductCommand;
import org.mifosng.platform.api.data.EntityIdentifier;
import org.mifosng.platform.exceptions.DepositProductNotFoundException;
import org.mifosng.platform.exceptions.PlatformDataIntegrityException;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosng.platform.savingproduct.domain.DepositProduct;
import org.mifosng.platform.savingproduct.domain.DepositProductRepository;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -13,11 +13,11 @@ import org.mifosng.platform.api.data.SavingProductLookup;
import org.mifosng.platform.exceptions.LoanProductNotFoundException;
import org.mifosng.platform.infrastructure.JdbcSupport;
import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosng.platform.savingproduct.domain.SavingProductType;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.configuration.service.CurrencyReadPlatformService;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
@@ -4,7 +4,6 @@ import org.mifosng.platform.api.commands.SavingProductCommand;
import org.mifosng.platform.api.data.EntityIdentifier;
import org.mifosng.platform.exceptions.ProductNotFoundException;
import org.mifosng.platform.exceptions.SavingProductNotFoundException;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosng.platform.savingproduct.domain.SavingFrequencyType;
import org.mifosng.platform.savingproduct.domain.SavingInterestCalculationMethod;
import org.mifosng.platform.savingproduct.domain.SavingProduct;
@@ -14,6 +13,7 @@ import org.mifosng.platform.savingproduct.domain.SavingsInterestType;
import org.mifosng.platform.savingproduct.domain.TenureTypeEnum;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -1,7 +1,7 @@
package org.mifosng.platform.savingproduct.service;
import org.mifosng.platform.api.data.EnumOptionData;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
public class SavingsDepositEnumerations {
@@ -171,8 +171,11 @@ public class CommandSource extends AbstractPersistable<Long> {
return this.resource.equalsIgnoreCase("CHARGES");
}
public boolean isLoanProductResource() {
return this.resource.equalsIgnoreCase("LOANPRODUCTS");
}
public boolean isClientResource() {
return this.resource.equalsIgnoreCase("CLIENTS");
}
}
@@ -22,11 +22,10 @@ public class ChargeDefinitionCommandHandler implements CommandSourceHandler {
private final ChangeDetectionService changeDetectionService;
private final PortfolioCommandDeserializerService commandDeserializerService;
private final ChargeWritePlatformService writePlatformService;
@Autowired
public ChargeDefinitionCommandHandler(final PlatformSecurityContext context, final ChangeDetectionService changeDetectionService,
final PortfolioCommandDeserializerService commandDeserializerService,
final ChargeWritePlatformService writePlatformService) {
final PortfolioCommandDeserializerService commandDeserializerService, final ChargeWritePlatformService writePlatformService) {
this.context = context;
this.changeDetectionService = changeDetectionService;
this.commandDeserializerService = commandDeserializerService;
@@ -42,8 +41,9 @@ public class ChargeDefinitionCommandHandler implements CommandSourceHandler {
CommandSource commandSourceResult = commandSource.copy();
final Long resourceId = commandSource.resourceId();
final ChargeDefinitionCommand command = this.commandDeserializerService.deserializeChargeDefinitionCommand(resourceId, commandSourceResult.json(), true);
final ChargeDefinitionCommand command = this.commandDeserializerService.deserializeChargeDefinitionCommand(resourceId,
commandSourceResult.json(), false);
if (commandSource.isCreate()) {
try {
Long newResourceId = this.writePlatformService.createCharge(command);
@@ -54,13 +54,15 @@ public class ChargeDefinitionCommandHandler implements CommandSourceHandler {
}
} else if (commandSource.isUpdate()) {
try {
final String jsonOfChangesOnly = this.changeDetectionService.detectChangesOnUpdate(commandSource.resourceName(), commandSource.resourceId(), commandSource.json());
final String jsonOfChangesOnly = this.changeDetectionService.detectChangesOnUpdate(commandSource.resourceName(),
commandSource.resourceId(), commandSource.json());
commandSourceResult.updateJsonTo(jsonOfChangesOnly);
final ChargeDefinitionCommand changesOnly = this.commandDeserializerService.deserializeChargeDefinitionCommand(resourceId, jsonOfChangesOnly, false);
final ChargeDefinitionCommand changesOnly = this.commandDeserializerService.deserializeChargeDefinitionCommand(resourceId,
jsonOfChangesOnly, false);
this.writePlatformService.updateCharge(changesOnly);
commandSourceResult.markAsChecked(maker, asToday);
} catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) {
// swallow this rollback transaction by design
@@ -81,32 +83,34 @@ public class ChargeDefinitionCommandHandler implements CommandSourceHandler {
public CommandSource handleCommandForCheckerApproval(final CommandSource commandSourceResult) {
final AppUser checker = context.authenticatedUser();
Long resourceId = commandSourceResult.resourceId();
final ChargeDefinitionCommand command = this.commandDeserializerService.deserializeChargeDefinitionCommand(resourceId, commandSourceResult.json(), true);
if (commandSourceResult.isUserResource()) {
if (commandSourceResult.isCreate()) {
final List<String> allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "ORGANISATION_ADMINISTRATION_SUPER_USER", "CREATE_CHARGE_MAKER");
context.authenticatedUser().validateHasPermissionTo("CREATE_CHARGE_MAKER", allowedPermissions);
resourceId = this.writePlatformService.createCharge(command);
commandSourceResult.updateResourceId(resourceId);
commandSourceResult.markAsChecked(checker, new LocalDate());
} else if (commandSourceResult.isUpdate()) {
final List<String> allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "ORGANISATION_ADMINISTRATION_SUPER_USER", "UPDATE_CHARGE_MAKER");
context.authenticatedUser().validateHasPermissionTo("UPDATE_CHARGE_MAKER", allowedPermissions);
this.writePlatformService.updateCharge(command);
commandSourceResult.markAsChecked(checker, new LocalDate());
} else if (commandSourceResult.isDelete()) {
final List<String> allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "ORGANISATION_ADMINISTRATION_SUPER_USER", "DELETE_CHARGE_MAKER");
context.authenticatedUser().validateHasPermissionTo("DELETE_CHARGE_MAKER", allowedPermissions);
this.writePlatformService.deleteCharge(command);
commandSourceResult.markAsChecked(checker, new LocalDate());
}
final ChargeDefinitionCommand command = this.commandDeserializerService.deserializeChargeDefinitionCommand(resourceId,
commandSourceResult.json(), true);
if (commandSourceResult.isCreate()) {
final List<String> allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "ORGANISATION_ADMINISTRATION_SUPER_USER",
"CREATE_CHARGE_MAKER");
context.authenticatedUser().validateHasPermissionTo("CREATE_CHARGE_MAKER", allowedPermissions);
resourceId = this.writePlatformService.createCharge(command);
commandSourceResult.updateResourceId(resourceId);
commandSourceResult.markAsChecked(checker, new LocalDate());
} else if (commandSourceResult.isUpdate()) {
final List<String> allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "ORGANISATION_ADMINISTRATION_SUPER_USER",
"UPDATE_CHARGE_MAKER");
context.authenticatedUser().validateHasPermissionTo("UPDATE_CHARGE_MAKER", allowedPermissions);
this.writePlatformService.updateCharge(command);
commandSourceResult.markAsChecked(checker, new LocalDate());
} else if (commandSourceResult.isDelete()) {
final List<String> allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "ORGANISATION_ADMINISTRATION_SUPER_USER",
"DELETE_CHARGE_MAKER");
context.authenticatedUser().validateHasPermissionTo("DELETE_CHARGE_MAKER", allowedPermissions);
this.writePlatformService.deleteCharge(command);
commandSourceResult.markAsChecked(checker, new LocalDate());
}
return commandSourceResult;
@@ -24,6 +24,7 @@ public class CommandSourceHandlerDelegator {
private final OfficeTransactionCommandHandler officeTransactionCommandHandler;
private final CurrencyCommandHandler currencyCommandHandler;
private final ChargeDefinitionCommandHandler chargeDefinitionCommandHandler;
private final LoanProductCommandHandler loanProductCommandHandler;
@Autowired
public CommandSourceHandlerDelegator(final PlatformSecurityContext context,
@@ -37,7 +38,8 @@ public class CommandSourceHandlerDelegator {
final OfficeCommandHandler officeCommandHandler,
final OfficeTransactionCommandHandler officeTransactionCommandHandler,
final CurrencyCommandHandler currencyCommandHandler,
final ChargeDefinitionCommandHandler chargeDefinitionCommandHandler) {
final ChargeDefinitionCommandHandler chargeDefinitionCommandHandler,
final LoanProductCommandHandler loanProductCommandHandler) {
this.context = context;
this.clientCommandHandler = clientCommandHandler;
this.roleCommandHandler = roleCommandHandler;
@@ -50,6 +52,7 @@ public class CommandSourceHandlerDelegator {
this.officeTransactionCommandHandler = officeTransactionCommandHandler;
this.currencyCommandHandler = currencyCommandHandler;
this.chargeDefinitionCommandHandler = chargeDefinitionCommandHandler;
this.loanProductCommandHandler = loanProductCommandHandler;
}
public CommandSource handleCommandWithSupportForRollback(final CommandSource commandSource) {
@@ -78,6 +81,8 @@ public class CommandSourceHandlerDelegator {
commandSourceResult = currencyCommandHandler.handleCommandWithSupportForRollback(commandSource);
} else if (commandSource.isChargeDefinitionResource()) {
commandSourceResult = chargeDefinitionCommandHandler.handleCommandWithSupportForRollback(commandSource);
} else if (commandSource.isLoanProductResource()) {
commandSourceResult = loanProductCommandHandler.handleCommandWithSupportForRollback(commandSource);
} else {
throw new UnsupportedCommandException(commandSource.commandName());
}
@@ -110,6 +115,8 @@ public class CommandSourceHandlerDelegator {
commandSourceResult = currencyCommandHandler.handleCommandForCheckerApproval(existingCommandSource);
} else if (existingCommandSource.isChargeDefinitionResource()) {
commandSourceResult = chargeDefinitionCommandHandler.handleCommandForCheckerApproval(existingCommandSource);
} else if (existingCommandSource.isLoanProductResource()) {
commandSourceResult = loanProductCommandHandler.handleCommandForCheckerApproval(existingCommandSource);
} else {
throw new UnsupportedCommandException(existingCommandSource.commandName());
}
@@ -0,0 +1,106 @@
package org.mifosplatform.commands.handler;
import java.util.Arrays;
import java.util.List;
import org.joda.time.LocalDate;
import org.mifosng.platform.api.data.EntityIdentifier;
import org.mifosng.platform.api.infrastructure.PortfolioCommandDeserializerService;
import org.mifosng.platform.client.service.RollbackTransactionAsCommandIsNotApprovedByCheckerException;
import org.mifosng.platform.infrastructure.errorhandling.UnsupportedCommandException;
import org.mifosplatform.commands.domain.CommandSource;
import org.mifosplatform.commands.service.ChangeDetectionService;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.infrastructure.user.domain.AppUser;
import org.mifosplatform.portfolio.loanproduct.command.LoanProductCommand;
import org.mifosplatform.portfolio.loanproduct.service.LoanProductWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class LoanProductCommandHandler implements CommandSourceHandler {
private final PlatformSecurityContext context;
private final ChangeDetectionService changeDetectionService;
private final PortfolioCommandDeserializerService commandDeserializerService;
private final LoanProductWritePlatformService writePlatformService;
@Autowired
public LoanProductCommandHandler(final PlatformSecurityContext context, final ChangeDetectionService changeDetectionService,
final PortfolioCommandDeserializerService commandDeserializerService, final LoanProductWritePlatformService writePlatformService) {
this.context = context;
this.changeDetectionService = changeDetectionService;
this.commandDeserializerService = commandDeserializerService;
this.writePlatformService = writePlatformService;
}
@Override
public CommandSource handleCommandWithSupportForRollback(final CommandSource commandSource) {
final AppUser maker = context.authenticatedUser();
final LocalDate asToday = new LocalDate();
final Long resourceId = commandSource.resourceId();
final LoanProductCommand command = this.commandDeserializerService.deserializeLoanProductCommand(resourceId, commandSource.json(),
false);
CommandSource commandSourceResult = commandSource.copy();
if (commandSource.isCreate()) {
try {
EntityIdentifier result = this.writePlatformService.createLoanProduct(command);
commandSourceResult.markAsChecked(maker, asToday);
commandSourceResult.updateResourceId(result.getEntityId());
} catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) {
// swallow this rollback transaction by design
}
} else if (commandSource.isUpdate()) {
try {
final String jsonOfChangesOnly = this.changeDetectionService.detectChangesOnUpdate(commandSource.resourceName(),
commandSource.resourceId(), commandSource.json());
commandSourceResult.updateJsonTo(jsonOfChangesOnly);
final LoanProductCommand changesOnly = this.commandDeserializerService.deserializeLoanProductCommand(resourceId,
jsonOfChangesOnly, false);
this.writePlatformService.updateLoanProduct(changesOnly);
commandSourceResult.markAsChecked(maker, asToday);
} catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) {
// swallow this rollback transaction by design
}
} else if (commandSource.isDelete()) { throw new UnsupportedCommandException(commandSource.commandName()); }
return commandSourceResult;
}
@Override
public CommandSource handleCommandForCheckerApproval(final CommandSource commandSourceResult) {
final AppUser checker = context.authenticatedUser();
Long resourceId = commandSourceResult.resourceId();
final LoanProductCommand command = this.commandDeserializerService.deserializeLoanProductCommand(resourceId,
commandSourceResult.json(), true);
if (commandSourceResult.isCreate()) {
final List<String> allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "ORGANISATION_ADMINISTRATION_SUPER_USER",
"CREATE_LOANPRODUCT_MAKER");
context.authenticatedUser().validateHasPermissionTo("CREATE_LOANPRODUCT_MAKER", allowedPermissions);
EntityIdentifier result = this.writePlatformService.createLoanProduct(command);
commandSourceResult.updateResourceId(result.getEntityId());
commandSourceResult.markAsChecked(checker, new LocalDate());
} else if (commandSourceResult.isUpdate()) {
final List<String> allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "ORGANISATION_ADMINISTRATION_SUPER_USER",
"UPDATE_LOANPRODUCT_MAKER");
context.authenticatedUser().validateHasPermissionTo("UPDATE_LOANPRODUCT_MAKER", allowedPermissions);
this.writePlatformService.updateLoanProduct(command);
commandSourceResult.markAsChecked(checker, new LocalDate());
} else if (commandSourceResult.isDelete()) { throw new UnsupportedCommandException(commandSourceResult.commandName()); }
return commandSourceResult;
}
}
@@ -8,31 +8,31 @@ import javax.persistence.Embeddable;
@Embeddable
public class MonetaryCurrency implements Serializable {
@Column(name = "currency_code", length = 3, nullable=false)
private final String code;
@Column(name = "currency_code", length = 3, nullable = false)
private final String code;
@Column(name = "currency_digits", nullable=false)
private final int digitsAfterDecimal;
@Column(name = "currency_digits", nullable = false)
private final int digitsAfterDecimal;
protected MonetaryCurrency() {
this.code = null;
this.digitsAfterDecimal = 0;
}
protected MonetaryCurrency() {
this.code = null;
this.digitsAfterDecimal = 0;
}
public MonetaryCurrency(final String code, final int digitsAfterDecimal) {
this.code = code;
this.digitsAfterDecimal = digitsAfterDecimal;
}
public MonetaryCurrency copy() {
return new MonetaryCurrency(this.code, this.digitsAfterDecimal);
}
public MonetaryCurrency(final String code, final int digitsAfterDecimal) {
this.code = code;
this.digitsAfterDecimal = digitsAfterDecimal;
}
public String getCode() {
return code;
}
public MonetaryCurrency copy() {
return new MonetaryCurrency(this.code, this.digitsAfterDecimal);
}
public int getDigitsAfterDecimal() {
return digitsAfterDecimal;
}
public String getCode() {
return code;
}
public int getDigitsAfterDecimal() {
return digitsAfterDecimal;
}
}
@@ -5,6 +5,7 @@ import java.util.Collection;
import org.mifosng.platform.api.data.LoanChargeData;
import org.mifosplatform.portfolio.charge.data.ChargeData;
// FIXME - KW - break out methods that belong to product charges and loan charges
public interface ChargeReadPlatformService {
Collection<ChargeData> retrieveAllCharges();
@@ -0,0 +1,195 @@
package org.mifosplatform.portfolio.loanproduct.api;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import org.mifosng.platform.api.data.EntityIdentifier;
import org.mifosng.platform.api.data.EnumOptionData;
import org.mifosng.platform.api.infrastructure.PortfolioApiDataConversionService;
import org.mifosng.platform.api.infrastructure.PortfolioApiJsonSerializerService;
import org.mifosng.platform.api.infrastructure.PortfolioCommandSerializerService;
import org.mifosng.platform.infrastructure.api.ApiParameterHelper;
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.configuration.service.CurrencyReadPlatformService;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.charge.data.ChargeData;
import org.mifosplatform.portfolio.charge.service.ChargeReadPlatformService;
import org.mifosplatform.portfolio.fund.data.FundData;
import org.mifosplatform.portfolio.fund.service.FundReadPlatformService;
import org.mifosplatform.portfolio.loanproduct.command.LoanProductCommand;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
import org.mifosplatform.portfolio.loanproduct.data.TransactionProcessingStrategyData;
import org.mifosplatform.portfolio.loanproduct.service.LoanDropdownReadPlatformService;
import org.mifosplatform.portfolio.loanproduct.service.LoanProductReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/loanproducts")
@Component
@Scope("singleton")
public class LoanProductsApiResource {
private final String resourceNameForPermissions = "LOANPRODUCT";
private final PlatformSecurityContext context;
private final LoanProductReadPlatformService loanProductReadPlatformService;
private final ChargeReadPlatformService chargeReadPlatformService;
private final CurrencyReadPlatformService currencyReadPlatformService;
private final FundReadPlatformService fundReadPlatformService;
private final LoanDropdownReadPlatformService dropdownReadPlatformService;
private final PortfolioApiJsonSerializerService apiJsonSerializerService;
private final PortfolioApiDataConversionService apiDataConversionService;
private final PortfolioCommandSerializerService commandSerializerService;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
@Autowired
public LoanProductsApiResource(final PlatformSecurityContext context, final LoanProductReadPlatformService readPlatformService,
final ChargeReadPlatformService chargeReadPlatformService, final CurrencyReadPlatformService currencyReadPlatformService,
final FundReadPlatformService fundReadPlatformService, final LoanDropdownReadPlatformService dropdownReadPlatformService,
final PortfolioApiJsonSerializerService apiJsonSerializerService,
final PortfolioApiDataConversionService apiDataConversionService,
final PortfolioCommandSerializerService commandSerializerService,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
this.context = context;
this.loanProductReadPlatformService = readPlatformService;
this.chargeReadPlatformService = chargeReadPlatformService;
this.currencyReadPlatformService = currencyReadPlatformService;
this.fundReadPlatformService = fundReadPlatformService;
this.dropdownReadPlatformService = dropdownReadPlatformService;
this.apiJsonSerializerService = apiJsonSerializerService;
this.apiDataConversionService = apiDataConversionService;
this.commandSerializerService = commandSerializerService;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
}
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createLoanProduct(final String apiRequestBodyAsJson) {
final List<String> allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "ORGANISATION_ADMINISTRATION_SUPER_USER",
"CREATE_LOANPRODUCT");
context.authenticatedUser().validateHasPermissionTo("CREATE_LOANPRODUCT", allowedPermissions);
final LoanProductCommand command = this.apiDataConversionService.convertApiRequestJsonToLoanProductCommand(null,
apiRequestBodyAsJson);
final String commandSerializedAsJson = this.commandSerializerService.serializeCommandToJson(command);
final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("CREATE", "loanproducts", null,
commandSerializedAsJson);
return this.apiJsonSerializerService.serializeEntityIdentifier(result);
}
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllLoanProducts(@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions);
final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
final Collection<LoanProductData> products = this.loanProductReadPlatformService.retrieveAllLoanProducts();
return this.apiJsonSerializerService.serializeLoanProductDataToJson(prettyPrint, responseParameters, products);
}
@GET
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveNewLoanProductDetails(@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions);
final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
LoanProductData loanProduct = this.loanProductReadPlatformService.retrieveNewLoanProductDetails();
loanProduct = handleTemplate(loanProduct);
return this.apiJsonSerializerService.serializeLoanProductDataToJson(prettyPrint, responseParameters, loanProduct);
}
@GET
@Path("{productId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveLoanProductDetails(@PathParam("productId") final Long productId, @Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions);
final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
final boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters());
LoanProductData loanProduct = this.loanProductReadPlatformService.retrieveLoanProduct(productId);
if (template) {
loanProduct = handleTemplate(loanProduct);
}
return this.apiJsonSerializerService.serializeLoanProductDataToJson(prettyPrint, responseParameters, loanProduct);
}
@PUT
@Path("{productId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateLoanProduct(@PathParam("productId") final Long productId, final String apiRequestBodyAsJson) {
final List<String> allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "ORGANISATION_ADMINISTRATION_SUPER_USER",
"UPDATE_LOANPRODUCT");
context.authenticatedUser().validateHasPermissionTo("UPDATE_LOANPRODUCT", allowedPermissions);
final LoanProductCommand command = this.apiDataConversionService.convertApiRequestJsonToLoanProductCommand(productId,
apiRequestBodyAsJson);
final String commandSerializedAsJson = this.commandSerializerService.serializeCommandToJson(command);
final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("UPDATE", "loanproducts", null,
commandSerializedAsJson);
return this.apiJsonSerializerService.serializeEntityIdentifier(result);
}
private LoanProductData handleTemplate(final LoanProductData productData) {
final boolean feeChargesOnly = true;
Collection<ChargeData> chargeOptions = this.chargeReadPlatformService.retrieveLoanApplicableCharges(feeChargesOnly);
chargeOptions.removeAll(productData.charges());
final List<CurrencyData> currencyOptions = currencyReadPlatformService.retrieveAllowedCurrencies();
final List<EnumOptionData> amortizationTypeOptions = dropdownReadPlatformService.retrieveLoanAmortizationTypeOptions();
final List<EnumOptionData> interestTypeOptions = dropdownReadPlatformService.retrieveLoanInterestTypeOptions();
final List<EnumOptionData> interestCalculationPeriodTypeOptions = dropdownReadPlatformService
.retrieveLoanInterestRateCalculatedInPeriodOptions();
final List<EnumOptionData> loanTermFrequencyTypeOptions = dropdownReadPlatformService.retrieveLoanTermFrequencyTypeOptions();
final List<EnumOptionData> repaymentFrequencyTypeOptions = dropdownReadPlatformService.retrieveRepaymentFrequencyTypeOptions();
final List<EnumOptionData> interestRateFrequencyTypeOptions = dropdownReadPlatformService
.retrieveInterestRateFrequencyTypeOptions();
final Collection<FundData> fundOptions = this.fundReadPlatformService.retrieveAllFunds();
final Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions = this.dropdownReadPlatformService
.retreiveTransactionProcessingStrategies();
return new LoanProductData(productData, chargeOptions, currencyOptions, amortizationTypeOptions, interestTypeOptions,
interestCalculationPeriodTypeOptions, loanTermFrequencyTypeOptions, repaymentFrequencyTypeOptions,
interestRateFrequencyTypeOptions, fundOptions, transactionProcessingStrategyOptions);
}
}
@@ -0,0 +1,216 @@
package org.mifosplatform.portfolio.loanproduct.command;
import java.math.BigDecimal;
import java.util.Set;
/**
* Immutable command for creating or updating details of a loan product.
*/
public class LoanProductCommand {
private final String name;
private final String description;
private final Long fundId;
private final Long transactionProcessingStrategyId;
private final String currencyCode;
private final Integer digitsAfterDecimal;
private final BigDecimal principal;
private final BigDecimal inArrearsTolerance;
private final Integer numberOfRepayments;
private final Integer repaymentEvery;
private final BigDecimal interestRatePerPeriod;
private final Integer repaymentFrequencyType;
private final Integer interestRateFrequencyType;
private final Integer amortizationType;
private final Integer interestType;
private final Integer interestCalculationPeriodType;
private final String[] charges;
private final transient Set<String> modifiedParameters;
private final transient boolean makerCheckerApproval;
private final transient Long id;
public LoanProductCommand(final Set<String> modifiedParameters,
final boolean makerCheckerApproval, final Long id, final String name, final String description,
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, final Integer repaymentFrequencyType,
final Integer interestRateFrequencyType, final Integer amortizationType, final Integer interestType,
final Integer interestCalculationPeriodType, final String[] charges) {
this.modifiedParameters = modifiedParameters;
this.makerCheckerApproval = makerCheckerApproval;
this.id = id;
this.name = name;
this.description = description;
this.fundId = fundId;
this.transactionProcessingStrategyId = transactionProcessingStrategyId;
this.currencyCode = currencyCode;
this.digitsAfterDecimal = digitsAfterDecimal;
this.principal = principal;
if (inArrearsTolerance != null && BigDecimal.ZERO.compareTo(inArrearsTolerance) == 0) {
this.inArrearsTolerance = null;
} else {
this.inArrearsTolerance = inArrearsTolerance;
}
this.numberOfRepayments = numberOfRepayments;
this.repaymentEvery = repaymentEvery;
this.interestRatePerPeriod = interestRatePerPeriod;
this.repaymentFrequencyType = repaymentFrequencyType;
this.interestRateFrequencyType = interestRateFrequencyType;
this.amortizationType = amortizationType;
this.interestType = interestType;
this.interestCalculationPeriodType = interestCalculationPeriodType;
this.charges = charges;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public Long getFundId() {
return fundId;
}
public Long getTransactionProcessingStrategyId() {
return transactionProcessingStrategyId;
}
public String getCurrencyCode() {
return currencyCode;
}
public Integer getDigitsAfterDecimal() {
return digitsAfterDecimal;
}
public BigDecimal getPrincipal() {
return principal;
}
public BigDecimal getInArrearsTolerance() {
return inArrearsTolerance;
}
public Integer getNumberOfRepayments() {
return numberOfRepayments;
}
public Integer getRepaymentEvery() {
return repaymentEvery;
}
public BigDecimal getInterestRatePerPeriod() {
return interestRatePerPeriod;
}
public Integer getRepaymentFrequencyType() {
return repaymentFrequencyType;
}
public Integer getInterestRateFrequencyType() {
return interestRateFrequencyType;
}
public Integer getAmortizationType() {
return amortizationType;
}
public Integer getInterestType() {
return interestType;
}
public Integer getInterestCalculationPeriodType() {
return interestCalculationPeriodType;
}
public String[] getCharges() {
return charges;
}
public boolean isNameChanged() {
return this.modifiedParameters.contains("name");
}
public boolean isDescriptionChanged() {
return this.modifiedParameters.contains("description");
}
public boolean isFundChanged() {
return this.modifiedParameters.contains("fundId");
}
public boolean isTransactionProcessingStrategyChanged() {
return this.modifiedParameters.contains("transactionProcessingStrategyId");
}
public boolean isCurrencyCodeChanged() {
return this.modifiedParameters.contains("currencyCode");
}
public boolean isDigitsAfterDecimalChanged() {
return this.modifiedParameters.contains("digitsAfterDecimal");
}
public boolean isPrincipalChanged() {
return this.modifiedParameters.contains("principal");
}
public boolean isInArrearsToleranceChanged() {
return this.modifiedParameters.contains("inArrearsTolerance");
}
public boolean isNumberOfRepaymentsChanged() {
return this.modifiedParameters.contains("numberOfRepayments");
}
public boolean isRepaymentEveryChanged() {
return this.modifiedParameters.contains("repaymentEvery");
}
public boolean isRepaymentFrequencyTypeChanged() {
return this.modifiedParameters.contains("repaymentFrequencyType");
}
public boolean isAmortizationTypeChanged() {
return this.modifiedParameters.contains("amortizationType");
}
public boolean isInterestTypeChanged() {
return this.modifiedParameters.contains("interestType");
}
public boolean isInterestRatePerPeriodChanged() {
return this.modifiedParameters.contains("interestRatePerPeriod");
}
public boolean isInterestRateFrequencyTypeChanged() {
return this.modifiedParameters.contains("interestRateFrequencyType");
}
public boolean isInterestCalculationPeriodTypeChanged() {
return this.modifiedParameters.contains("interestCalculationPeriodType");
}
public boolean isChargesChanged() {
return this.modifiedParameters.contains("charges");
}
public boolean isApprovedByChecker() {
return this.makerCheckerApproval;
}
}
@@ -0,0 +1,365 @@
package org.mifosplatform.portfolio.loanproduct.data;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.joda.time.DateTime;
import org.mifosng.platform.api.data.EnumOptionData;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.portfolio.charge.data.ChargeData;
import org.mifosplatform.portfolio.fund.data.FundData;
import org.mifosplatform.portfolio.loanproduct.domain.AmortizationMethod;
import org.mifosplatform.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
import org.mifosplatform.portfolio.loanproduct.domain.InterestMethod;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations;
/**
* Immutable data object to represent loan products.
*/
public class LoanProductData {
private final Long id;
private final String name;
private final String description;
private final Long fundId;
private final String fundName;
private final Long transactionProcessingStrategyId;
private final String transactionProcessingStrategyName;
private final CurrencyData currency;
private final BigDecimal principal;
private final BigDecimal inArrearsTolerance;
private final Integer numberOfRepayments;
private final Integer loanTermFrequency;
private final Integer repaymentEvery;
private final BigDecimal interestRatePerPeriod;
private final BigDecimal annualInterestRate;
private final EnumOptionData loanTermFrequencyType;
private final EnumOptionData repaymentFrequencyType;
private final EnumOptionData interestRateFrequencyType;
private final EnumOptionData amortizationType;
private final EnumOptionData interestType;
private final EnumOptionData interestCalculationPeriodType;
private final Collection<ChargeData> charges;
private final DateTime createdOn;
private final DateTime lastModifedOn;
private final List<CurrencyData> currencyOptions;
private final Collection<FundData> fundOptions;
private final Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions;
private final List<EnumOptionData> amortizationTypeOptions;
private final List<EnumOptionData> interestTypeOptions;
private final List<EnumOptionData> interestCalculationPeriodTypeOptions;
private final List<EnumOptionData> repaymentFrequencyTypeOptions;
private final List<EnumOptionData> interestRateFrequencyTypeOptions;
private final List<EnumOptionData> loanTermFrequencyTypeOptions;
private final Collection<ChargeData> chargeOptions;
/**
* Used when returning lookup information about loan product for dropdowns.
*/
public static LoanProductData lookup(final Long id, final String name) {
final DateTime createdOn = null;
final DateTime lastModifedOn = null;
final String description = null;
final CurrencyData currency = null;
final BigDecimal principal = null;
final BigDecimal tolerance = null;
final Integer numberOfRepayments = null;
final Integer loanTermFrequency = null;
final Integer repaymentEvery = null;
final BigDecimal interestRatePerPeriod = null;
final BigDecimal annualInterestRate = null;
final EnumOptionData loanTermFrequencyType = null;
final EnumOptionData repaymentFrequencyType = null;
final EnumOptionData interestRateFrequencyType = null;
final EnumOptionData amortizationType = null;
final EnumOptionData interestType = null;
final EnumOptionData interestCalculationPeriodType = null;
final Long fundId = null;
final String fundName = null;
final Long transactionProcessingStrategyId = null;
final String transactionProcessingStrategyName = null;
final Collection<ChargeData> charges = null;
return new LoanProductData(createdOn, lastModifedOn, id, name, description, currency, principal, tolerance, numberOfRepayments,
loanTermFrequency, repaymentEvery, interestRatePerPeriod, annualInterestRate, loanTermFrequencyType,
repaymentFrequencyType, interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, fundId,
fundName, transactionProcessingStrategyId, transactionProcessingStrategyName, charges);
}
public static LoanProductData sensibleDefaultsForNewLoanProductCreation() {
final DateTime createdOn = null;
final DateTime lastModifedOn = null;
final Long id = null;
final String name = null;
final String description = null;
final CurrencyData currency = CurrencyData.blank();
final BigDecimal principal = null;
final BigDecimal tolerance = null;
final Integer numberOfRepayments = null;
final Integer loanTermFrequency = null;
final Integer repaymentEvery = null;
final BigDecimal interestRatePerPeriod = null;
final BigDecimal annualInterestRate = null;
final EnumOptionData loanTermFrequencyType = LoanEnumerations.loanTermFrequencyType(PeriodFrequencyType.MONTHS);
final EnumOptionData repaymentFrequencyType = LoanEnumerations.repaymentFrequencyType(PeriodFrequencyType.MONTHS);
final EnumOptionData interestRateFrequencyType = LoanEnumerations.interestRateFrequencyType(PeriodFrequencyType.MONTHS);
final EnumOptionData amortizationType = LoanEnumerations.amortizationType(AmortizationMethod.EQUAL_INSTALLMENTS);
final EnumOptionData interestType = LoanEnumerations.interestType(InterestMethod.DECLINING_BALANCE);
final EnumOptionData interestCalculationPeriodType = LoanEnumerations
.interestCalculationPeriodType(InterestCalculationPeriodMethod.SAME_AS_REPAYMENT_PERIOD);
final Long fundId = null;
final String fundName = null;
final Long transactionProcessingStrategyId = null;
final String transactionProcessingStrategyName = null;
final Collection<ChargeData> charges = null;
return new LoanProductData(createdOn, lastModifedOn, id, name, description, currency, principal, tolerance, numberOfRepayments,
loanTermFrequency, repaymentEvery, interestRatePerPeriod, annualInterestRate, loanTermFrequencyType,
repaymentFrequencyType, interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, fundId,
fundName, transactionProcessingStrategyId, transactionProcessingStrategyName, charges);
}
public LoanProductData(final DateTime createdOn, final DateTime lastModifedOn, final Long id, final String name,
final String description, final CurrencyData currency, final BigDecimal principal, final BigDecimal tolerance,
final Integer numberOfRepayments, final Integer loanTermFrequency, final Integer repaymentEvery,
final BigDecimal interestRatePerPeriod, final BigDecimal annualInterestRate, final EnumOptionData loanTermFrequencyType,
final EnumOptionData repaymentFrequencyType, final EnumOptionData interestRateFrequencyType,
final EnumOptionData amortizationType, final EnumOptionData interestType, final EnumOptionData interestCalculationPeriodType,
final Long fundId, final String fundName, final Long transactionProcessingStrategyId,
final String transactionProcessingStrategyName, final Collection<ChargeData> charges) {
this.createdOn = createdOn;
this.lastModifedOn = lastModifedOn;
this.id = id;
this.name = name;
this.description = description;
this.currency = currency;
this.principal = principal;
this.inArrearsTolerance = tolerance;
this.numberOfRepayments = numberOfRepayments;
this.loanTermFrequency = loanTermFrequency;
this.repaymentEvery = repaymentEvery;
this.interestRatePerPeriod = interestRatePerPeriod;
this.annualInterestRate = annualInterestRate;
this.loanTermFrequencyType = loanTermFrequencyType;
this.repaymentFrequencyType = repaymentFrequencyType;
this.interestRateFrequencyType = interestRateFrequencyType;
this.amortizationType = amortizationType;
this.interestType = interestType;
this.interestCalculationPeriodType = interestCalculationPeriodType;
this.fundId = fundId;
this.fundName = fundName;
this.transactionProcessingStrategyId = transactionProcessingStrategyId;
this.transactionProcessingStrategyName = transactionProcessingStrategyName;
this.charges = charges;
this.chargeOptions = null;
this.currencyOptions = null;
this.fundOptions = null;
this.transactionProcessingStrategyOptions = null;
this.amortizationTypeOptions = null;
this.interestTypeOptions = null;
this.interestCalculationPeriodTypeOptions = null;
this.loanTermFrequencyTypeOptions = null;
this.repaymentFrequencyTypeOptions = null;
this.interestRateFrequencyTypeOptions = null;
}
public LoanProductData(final LoanProductData productData, final Collection<ChargeData> chargeOptions,
final List<CurrencyData> currencyOptions, final List<EnumOptionData> amortizationTypeOptions,
final List<EnumOptionData> interestTypeOptions, final List<EnumOptionData> interestCalculationPeriodTypeOptions,
final List<EnumOptionData> loanTermFrequencyTypeOptions, final List<EnumOptionData> repaymentFrequencyTypeOptions,
final List<EnumOptionData> interestRateFrequencyTypeOptions, final Collection<FundData> fundOptions,
final Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions) {
this.createdOn = productData.createdOn;
this.lastModifedOn = productData.lastModifedOn;
this.id = productData.id;
this.name = productData.name;
this.description = productData.description;
this.principal = productData.principal;
this.inArrearsTolerance = productData.inArrearsTolerance;
this.numberOfRepayments = productData.numberOfRepayments;
this.loanTermFrequency = productData.loanTermFrequency;
this.repaymentEvery = productData.repaymentEvery;
this.interestRatePerPeriod = productData.interestRatePerPeriod;
this.annualInterestRate = productData.annualInterestRate;
this.loanTermFrequencyType = productData.loanTermFrequencyType;
this.repaymentFrequencyType = productData.repaymentFrequencyType;
this.interestRateFrequencyType = productData.interestRateFrequencyType;
this.amortizationType = productData.amortizationType;
this.interestType = productData.interestType;
this.interestCalculationPeriodType = productData.interestCalculationPeriodType;
this.fundId = productData.fundId;
this.fundName = productData.fundName;
this.transactionProcessingStrategyId = productData.transactionProcessingStrategyId;
this.transactionProcessingStrategyName = productData.transactionProcessingStrategyName;
this.charges = productData.charges();
this.chargeOptions = chargeOptions;
this.currencyOptions = currencyOptions;
if (this.currencyOptions.size() == 1) {
this.currency = this.currencyOptions.get(0);
} else {
this.currency = productData.currency;
}
this.fundOptions = fundOptions;
this.transactionProcessingStrategyOptions = transactionProcessingStrategyOptions;
this.amortizationTypeOptions = amortizationTypeOptions;
this.interestTypeOptions = interestTypeOptions;
this.interestCalculationPeriodTypeOptions = interestCalculationPeriodTypeOptions;
this.loanTermFrequencyTypeOptions = loanTermFrequencyTypeOptions;
this.repaymentFrequencyTypeOptions = repaymentFrequencyTypeOptions;
this.interestRateFrequencyTypeOptions = interestRateFrequencyTypeOptions;
}
public Collection<ChargeData> charges() {
Collection<ChargeData> chargesLocal = new ArrayList<ChargeData>();
if (this.charges != null) {
chargesLocal = this.charges;
}
return chargesLocal;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public Long getFundId() {
return fundId;
}
public String getFundName() {
return fundName;
}
public Long getTransactionProcessingStrategyId() {
return transactionProcessingStrategyId;
}
public String getTransactionProcessingStrategyName() {
return transactionProcessingStrategyName;
}
public CurrencyData getCurrency() {
return currency;
}
public BigDecimal getPrincipal() {
return principal;
}
public BigDecimal getInArrearsTolerance() {
return inArrearsTolerance;
}
public Integer getNumberOfRepayments() {
return numberOfRepayments;
}
public Integer getLoanTermFrequency() {
return loanTermFrequency;
}
public Integer getRepaymentEvery() {
return repaymentEvery;
}
public BigDecimal getInterestRatePerPeriod() {
return interestRatePerPeriod;
}
public BigDecimal getAnnualInterestRate() {
return annualInterestRate;
}
public EnumOptionData getLoanTermFrequencyType() {
return loanTermFrequencyType;
}
public EnumOptionData getRepaymentFrequencyType() {
return repaymentFrequencyType;
}
public EnumOptionData getInterestRateFrequencyType() {
return interestRateFrequencyType;
}
public EnumOptionData getAmortizationType() {
return amortizationType;
}
public EnumOptionData getInterestType() {
return interestType;
}
public EnumOptionData getInterestCalculationPeriodType() {
return interestCalculationPeriodType;
}
public DateTime getCreatedOn() {
return createdOn;
}
public DateTime getLastModifedOn() {
return lastModifedOn;
}
public List<CurrencyData> getCurrencyOptions() {
return currencyOptions;
}
public Collection<FundData> getFundOptions() {
return fundOptions;
}
public Collection<TransactionProcessingStrategyData> getTransactionProcessingStrategyOptions() {
return transactionProcessingStrategyOptions;
}
public List<EnumOptionData> getAmortizationTypeOptions() {
return amortizationTypeOptions;
}
public List<EnumOptionData> getInterestTypeOptions() {
return interestTypeOptions;
}
public List<EnumOptionData> getInterestCalculationPeriodTypeOptions() {
return interestCalculationPeriodTypeOptions;
}
public List<EnumOptionData> getRepaymentFrequencyTypeOptions() {
return repaymentFrequencyTypeOptions;
}
public List<EnumOptionData> getInterestRateFrequencyTypeOptions() {
return interestRateFrequencyTypeOptions;
}
public List<EnumOptionData> getLoanTermFrequencyTypeOptions() {
return loanTermFrequencyTypeOptions;
}
public Collection<ChargeData> getChargeOptions() {
return chargeOptions;
}
}
@@ -1,9 +1,12 @@
package org.mifosng.platform.api.data;
package org.mifosplatform.portfolio.loanproduct.data;
public final class TransactionProcessingStrategyData {
@SuppressWarnings("unused")
private final Long id;
@SuppressWarnings("unused")
private final String code;
@SuppressWarnings("unused")
private final String name;
public TransactionProcessingStrategyData(final Long id, final String code, final String name) {
@@ -11,16 +14,4 @@ public final class TransactionProcessingStrategyData {
this.code = code;
this.name = name;
}
public Long getId() {
return id;
}
public String getCode() {
return code;
}
public String getName() {
return name;
}
}
@@ -0,0 +1,42 @@
package org.mifosplatform.portfolio.loanproduct.domain;
public enum AmortizationMethod {
EQUAL_PRINCIPAL(0, "amortizationType.equal.principal"), //
EQUAL_INSTALLMENTS(1, "amortizationType.equal.installments"), //
INVALID(2, "amortizationType.invalid");
private final Integer value;
private final String code;
private AmortizationMethod(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return code;
}
public static AmortizationMethod fromInt(final Integer selectedMethod) {
if (selectedMethod == null) { return null; }
AmortizationMethod repaymentMethod = null;
switch (selectedMethod) {
case 0:
repaymentMethod = AmortizationMethod.EQUAL_PRINCIPAL;
break;
case 1:
repaymentMethod = AmortizationMethod.EQUAL_INSTALLMENTS;
break;
default:
repaymentMethod = AmortizationMethod.INVALID;
break;
}
return repaymentMethod;
}
}
@@ -0,0 +1,40 @@
package org.mifosplatform.portfolio.loanproduct.domain;
public enum InterestCalculationPeriodMethod {
DAILY(0, "interestCalculationPeriodType.daily"), //
SAME_AS_REPAYMENT_PERIOD(1, "interestCalculationPeriodType.same.as.repayment.period"), //
INVALID(2, "interestCalculationPeriodType.invalid");
private final Integer value;
private final String code;
private InterestCalculationPeriodMethod(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return code;
}
public static InterestCalculationPeriodMethod fromInt(final Integer selectedMethod) {
InterestCalculationPeriodMethod repaymentMethod = null;
switch (selectedMethod) {
case 0:
repaymentMethod = InterestCalculationPeriodMethod.DAILY;
break;
case 1:
repaymentMethod = InterestCalculationPeriodMethod.SAME_AS_REPAYMENT_PERIOD;
break;
default:
repaymentMethod = InterestCalculationPeriodMethod.INVALID;
break;
}
return repaymentMethod;
}
}
@@ -0,0 +1,38 @@
package org.mifosplatform.portfolio.loanproduct.domain;
public enum InterestMethod {
DECLINING_BALANCE(0, "interestType.declining.balance"), FLAT(1, "interestType.flat"), INVALID(2, "interestType.invalid");
private final Integer value;
private final String code;
private InterestMethod(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return code;
}
public static InterestMethod fromInt(final Integer selectedMethod) {
InterestMethod repaymentMethod = null;
switch (selectedMethod) {
case 0:
repaymentMethod = InterestMethod.DECLINING_BALANCE;
break;
case 1:
repaymentMethod = InterestMethod.FLAT;
break;
default:
repaymentMethod = InterestMethod.INVALID;
break;
}
return repaymentMethod;
}
}
@@ -0,0 +1,123 @@
package org.mifosplatform.portfolio.loanproduct.domain;
import java.math.BigDecimal;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.apache.commons.lang.StringUtils;
import org.mifosng.platform.infrastructure.AbstractAuditableCustom;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.user.domain.AppUser;
import org.mifosplatform.portfolio.charge.domain.Charge;
import org.mifosplatform.portfolio.fund.domain.Fund;
import org.mifosplatform.portfolio.loanproduct.command.LoanProductCommand;
/**
* Loan products allow for categorisation of an organisations loans into
* something meaningful to them.
*
* They provide a means of simplifying creation/maintenance of loans. They can
* also allow for product comparison to take place when reporting.
*
* They allow for constraints to be added at product level.
*/
@Entity
@Table(name = "m_product_loan")
public class LoanProduct extends AbstractAuditableCustom<AppUser, Long> {
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "fund_id", nullable = true)
private Fund fund;
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "loan_transaction_strategy_id", nullable = true)
private LoanTransactionProcessingStrategy transactionProcessingStrategy;
@SuppressWarnings("unused")
@Column(name = "name", nullable = false)
private String name;
@SuppressWarnings("unused")
@Column(name = "description")
private String description;
@ManyToMany
@JoinTable(name = "m_product_loan_charge", joinColumns = @JoinColumn(name = "product_loan_id"), inverseJoinColumns = @JoinColumn(name = "charge_id"))
private Set<Charge> charges;
@Embedded
private final LoanProductRelatedDetail loanProductRelatedDetail;
protected LoanProduct() {
this.loanProductRelatedDetail = null;
}
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, final Set<Charge> charges) {
this.fund = fund;
this.transactionProcessingStrategy = transactionProcessingStrategy;
this.name = name.trim();
if (StringUtils.isNotBlank(description)) {
this.description = description.trim();
} else {
this.description = null;
}
if (charges != null) {
this.charges = charges;
}
this.loanProductRelatedDetail = new LoanProductRelatedDetail(currency, defaultPrincipal, defaultNominalInterestRatePerPeriod,
interestPeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod, repayEvery,
repaymentFrequencyType, defaultNumberOfInstallments, amortizationMethod, inArrearsTolerance);
}
public MonetaryCurrency getCurrency() {
return this.loanProductRelatedDetail.getCurrency();
}
public Set<Charge> getCharges() {
return charges;
}
public void update(final LoanProductCommand command, final Fund fund, final LoanTransactionProcessingStrategy strategy,
final Set<Charge> charges) {
if (command.isNameChanged()) {
this.name = command.getName();
}
if (command.isDescriptionChanged()) {
this.description = command.getDescription();
}
if (command.isFundChanged()) {
this.fund = fund;
}
if (command.isTransactionProcessingStrategyChanged()) {
this.transactionProcessingStrategy = strategy;
}
if (command.isChargesChanged()) {
this.charges = charges;
}
this.loanProductRelatedDetail.update(command);
}
}
@@ -1,9 +1,11 @@
package org.mifosng.platform.loan.domain;
package org.mifosplatform.portfolio.loanproduct.domain;
import java.io.Serializable;
/**
* Represents the bare minimum repayment details needed for activities related to generating repayment schedules.
* Represents the bare minimum repayment details needed for activities related
* to generating repayment schedules.
*/
public interface LoanProductMinimumRepaymentScheduleRelatedDetail extends Serializable {
@@ -0,0 +1,190 @@
package org.mifosplatform.portfolio.loanproduct.domain;
import java.math.BigDecimal;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import org.mifosng.platform.loan.domain.Loan;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.portfolio.loanproduct.command.LoanProductCommand;
/**
* LoanRepaymentScheduleDetail encapsulates all the details of a
* {@link LoanProduct} that are also used and persisted by a {@link Loan}.
*/
@Embeddable
public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentScheduleRelatedDetail {
@Embedded
private MonetaryCurrency currency;
@Column(name = "principal_amount", scale = 6, precision = 19, nullable = false)
private BigDecimal principal;
@Column(name = "nominal_interest_rate_per_period", scale = 6, precision = 19, nullable = false)
private BigDecimal nominalInterestRatePerPeriod;
@Enumerated(EnumType.ORDINAL)
@Column(name = "interest_period_frequency_enum", nullable = false)
private PeriodFrequencyType interestPeriodFrequencyType;
@Column(name = "annual_nominal_interest_rate", scale = 6, precision = 19, nullable = false)
private BigDecimal annualNominalInterestRate;
@Enumerated(EnumType.ORDINAL)
@Column(name = "interest_method_enum", nullable = false)
private InterestMethod interestMethod;
@Enumerated(EnumType.ORDINAL)
@Column(name = "interest_calculated_in_period_enum", nullable = false)
private InterestCalculationPeriodMethod interestCalculationPeriodMethod;
@Column(name = "repay_every", nullable = false)
private Integer repayEvery;
@Enumerated(EnumType.ORDINAL)
@Column(name = "repayment_period_frequency_enum", nullable = false)
private PeriodFrequencyType repaymentPeriodFrequencyType;
@Column(name = "number_of_repayments", nullable = false)
private Integer numberOfRepayments;
@Enumerated(EnumType.ORDINAL)
@Column(name = "amortization_method_enum", nullable = false)
private AmortizationMethod amortizationMethod;
@Column(name = "arrearstolerance_amount", scale = 6, precision = 19, nullable = true)
private BigDecimal inArrearsTolerance;
protected LoanProductRelatedDetail() {
//
}
public LoanProductRelatedDetail(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 defaultNumberOfRepayments,
final AmortizationMethod amortizationMethod, final BigDecimal inArrearsTolerance) {
this.currency = currency;
this.principal = defaultPrincipal;
this.nominalInterestRatePerPeriod = defaultNominalInterestRatePerPeriod;
this.interestPeriodFrequencyType = interestPeriodFrequencyType;
this.annualNominalInterestRate = defaultAnnualNominalInterestRate;
this.interestMethod = interestMethod;
this.interestCalculationPeriodMethod = interestCalculationPeriodMethod;
this.repayEvery = repayEvery;
this.repaymentPeriodFrequencyType = repaymentFrequencyType;
this.numberOfRepayments = defaultNumberOfRepayments;
this.amortizationMethod = amortizationMethod;
if (inArrearsTolerance != null && BigDecimal.ZERO.compareTo(inArrearsTolerance) == 0) {
this.inArrearsTolerance = null;
} else {
this.inArrearsTolerance = inArrearsTolerance;
}
}
public MonetaryCurrency getCurrency() {
return this.currency.copy();
}
public Money getPrincipal() {
return Money.of(this.currency, this.principal);
}
public Money getInArrearsTolerance() {
return Money.of(this.currency, this.inArrearsTolerance);
}
public BigDecimal getNominalInterestRatePerPeriod() {
return BigDecimal.valueOf(Double.valueOf(this.nominalInterestRatePerPeriod.stripTrailingZeros().toString()));
}
public PeriodFrequencyType getInterestPeriodFrequencyType() {
return interestPeriodFrequencyType;
}
public BigDecimal getAnnualNominalInterestRate() {
return BigDecimal.valueOf(Double.valueOf(this.annualNominalInterestRate.stripTrailingZeros().toString()));
}
public InterestMethod getInterestMethod() {
return interestMethod;
}
public InterestCalculationPeriodMethod getInterestCalculationPeriodMethod() {
return interestCalculationPeriodMethod;
}
@Override
public Integer getRepayEvery() {
return repayEvery;
}
@Override
public PeriodFrequencyType getRepaymentPeriodFrequencyType() {
return repaymentPeriodFrequencyType;
}
@Override
public Integer getNumberOfRepayments() {
return numberOfRepayments;
}
public AmortizationMethod getAmortizationMethod() {
return amortizationMethod;
}
public void update(final LoanProductCommand command) {
Integer digitsAfterDecimalChanged = this.currency.getDigitsAfterDecimal();
if (command.isDigitsAfterDecimalChanged()) {
digitsAfterDecimalChanged = command.getDigitsAfterDecimal();
}
String currencyCodeChanged = this.currency.getCode();
if (command.isCurrencyCodeChanged()) {
currencyCodeChanged = command.getCurrencyCode();
}
if (command.isDigitsAfterDecimalChanged() || command.isCurrencyCodeChanged()) {
this.currency = new MonetaryCurrency(currencyCodeChanged, digitsAfterDecimalChanged);
}
if (command.isPrincipalChanged()) {
this.principal = command.getPrincipal();
}
if (command.isRepaymentEveryChanged()) {
this.repayEvery = command.getRepaymentEvery();
}
if (command.isRepaymentFrequencyTypeChanged()) {
this.repaymentPeriodFrequencyType = PeriodFrequencyType.fromInt(command.getRepaymentFrequencyType());
}
if (command.isNumberOfRepaymentsChanged()) {
this.numberOfRepayments = command.getNumberOfRepayments();
}
if (command.isAmortizationTypeChanged()) {
this.amortizationMethod = AmortizationMethod.fromInt(command.getAmortizationType());
}
if (command.isInArrearsToleranceChanged()) {
this.inArrearsTolerance = command.getInArrearsTolerance();
}
if (command.isInterestRatePerPeriodChanged()) {
this.nominalInterestRatePerPeriod = command.getInterestRatePerPeriod();
}
if (command.isInterestRateFrequencyTypeChanged()) {
this.interestPeriodFrequencyType = PeriodFrequencyType.fromInt(command.getInterestRateFrequencyType());
}
if (command.isInterestTypeChanged()) {
this.interestMethod = InterestMethod.fromInt(command.getInterestType());
}
if (command.isInterestCalculationPeriodTypeChanged()) {
this.interestCalculationPeriodMethod = InterestCalculationPeriodMethod.fromInt(command.getInterestCalculationPeriodType());
}
}
}
@@ -0,0 +1,8 @@
package org.mifosplatform.portfolio.loanproduct.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface LoanProductRepository extends JpaRepository<LoanProduct, Long>, JpaSpecificationExecutor<LoanProduct> {
// no behaviour added
}
@@ -0,0 +1,47 @@
package org.mifosplatform.portfolio.loanproduct.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import org.mifosng.platform.infrastructure.AbstractAuditableCustom;
import org.mifosplatform.infrastructure.user.domain.AppUser;
import org.mifosplatform.portfolio.loanproduct.data.TransactionProcessingStrategyData;
/**
*
*/
@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 TransactionProcessingStrategyData toData() {
return new TransactionProcessingStrategyData(this.getId(), this.code, this.name);
}
public boolean isStandardMifosStrategy() {
return "mifos-standard-strategy".equalsIgnoreCase(this.code);
}
public boolean isHeavensfamilyStrategy() {
return "heavensfamily-strategy".equalsIgnoreCase(this.code);
}
public boolean isCreocoreStrategy() {
return "creocore-strategy".equalsIgnoreCase(this.code);
}
public boolean isIndianRBIStrategy() {
return "rbi-india-strategy".equalsIgnoreCase(this.code);
}
}
@@ -0,0 +1,48 @@
package org.mifosplatform.portfolio.loanproduct.domain;
public enum PeriodFrequencyType {
DAYS(0, "periodFrequencyType.days"), //
WEEKS(1, "periodFrequencyType.weeks"), //
MONTHS(2, "periodFrequencyType.months"), //
YEARS(3, "periodFrequencyType.years"), //
INVALID(4, "periodFrequencyType.invalid");
private final Integer value;
private final String code;
private PeriodFrequencyType(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return code;
}
public static PeriodFrequencyType fromInt(final Integer frequency) {
PeriodFrequencyType repaymentFrequencyType = PeriodFrequencyType.INVALID;
switch (frequency) {
case 0:
repaymentFrequencyType = PeriodFrequencyType.DAYS;
break;
case 1:
repaymentFrequencyType = PeriodFrequencyType.WEEKS;
break;
case 2:
repaymentFrequencyType = PeriodFrequencyType.MONTHS;
break;
case 3:
repaymentFrequencyType = PeriodFrequencyType.YEARS;
break;
default:
repaymentFrequencyType = PeriodFrequencyType.INVALID;
break;
}
return repaymentFrequencyType;
}
}
@@ -1,10 +1,10 @@
package org.mifosng.platform.loanproduct.service;
package org.mifosplatform.portfolio.loanproduct.service;
import java.util.Collection;
import java.util.List;
import org.mifosng.platform.api.data.EnumOptionData;
import org.mifosng.platform.api.data.TransactionProcessingStrategyData;
import org.mifosplatform.portfolio.loanproduct.data.TransactionProcessingStrategyData;
public interface LoanDropdownReadPlatformService {
@@ -1,11 +1,11 @@
package org.mifosng.platform.loanproduct.service;
package org.mifosplatform.portfolio.loanproduct.service;
import static org.mifosng.platform.loanproduct.service.LoanEnumerations.amortizationType;
import static org.mifosng.platform.loanproduct.service.LoanEnumerations.interestCalculationPeriodType;
import static org.mifosng.platform.loanproduct.service.LoanEnumerations.interestRateFrequencyType;
import static org.mifosng.platform.loanproduct.service.LoanEnumerations.interestType;
import static org.mifosng.platform.loanproduct.service.LoanEnumerations.loanTermFrequencyType;
import static org.mifosng.platform.loanproduct.service.LoanEnumerations.repaymentFrequencyType;
import static org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations.amortizationType;
import static org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations.interestCalculationPeriodType;
import static org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations.interestRateFrequencyType;
import static org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations.interestType;
import static org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations.loanTermFrequencyType;
import static org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations.repaymentFrequencyType;
import java.util.ArrayList;
import java.util.Arrays;
@@ -13,13 +13,13 @@ 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.mifosplatform.portfolio.loanproduct.data.TransactionProcessingStrategyData;
import org.mifosplatform.portfolio.loanproduct.domain.AmortizationMethod;
import org.mifosplatform.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
import org.mifosplatform.portfolio.loanproduct.domain.InterestMethod;
import org.mifosplatform.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -1,12 +1,12 @@
package org.mifosng.platform.loanproduct.service;
package org.mifosplatform.portfolio.loanproduct.service;
import org.mifosng.platform.api.data.EnumOptionData;
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.LoanStatus;
import org.mifosng.platform.loan.domain.LoanTransactionType;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.loanproduct.domain.AmortizationMethod;
import org.mifosplatform.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
import org.mifosplatform.portfolio.loanproduct.domain.InterestMethod;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
public class LoanEnumerations {
@@ -1,12 +1,12 @@
package org.mifosng.platform.loanproduct.service;
package org.mifosplatform.portfolio.loanproduct.service;
import java.util.ArrayList;
import java.util.List;
import org.mifosng.platform.DataValidatorBuilder;
import org.mifosng.platform.api.commands.LoanProductCommand;
import org.mifosng.platform.api.data.ApiParameterError;
import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
import org.mifosplatform.portfolio.loanproduct.command.LoanProductCommand;
public class LoanProductCommandValidator {
@@ -1,8 +1,8 @@
package org.mifosng.platform.loanproduct.service;
package org.mifosplatform.portfolio.loanproduct.service;
import java.util.Collection;
import org.mifosng.platform.api.data.LoanProductData;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
public interface LoanProductReadPlatformService {
@@ -1,4 +1,4 @@
package org.mifosng.platform.loanproduct.service;
package org.mifosplatform.portfolio.loanproduct.service;
import java.math.BigDecimal;
import java.sql.ResultSet;
@@ -7,7 +7,6 @@ import java.util.Collection;
import org.joda.time.DateTime;
import org.mifosng.platform.api.data.EnumOptionData;
import org.mifosng.platform.api.data.LoanProductData;
import org.mifosng.platform.exceptions.LoanProductNotFoundException;
import org.mifosng.platform.infrastructure.JdbcSupport;
import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource;
@@ -15,6 +14,7 @@ import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.charge.data.ChargeData;
import org.mifosplatform.portfolio.charge.service.ChargeReadPlatformService;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
@@ -0,0 +1,11 @@
package org.mifosplatform.portfolio.loanproduct.service;
import org.mifosng.platform.api.data.EntityIdentifier;
import org.mifosplatform.portfolio.loanproduct.command.LoanProductCommand;
public interface LoanProductWritePlatformService {
EntityIdentifier createLoanProduct(LoanProductCommand command);
EntityIdentifier updateLoanProduct(LoanProductCommand command);
}
@@ -0,0 +1,185 @@
package org.mifosplatform.portfolio.loanproduct.service;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.Set;
import org.mifosng.platform.api.data.EntityIdentifier;
import org.mifosng.platform.client.service.RollbackTransactionAsCommandIsNotApprovedByCheckerException;
import org.mifosng.platform.exceptions.ChargeIsNotActiveException;
import org.mifosng.platform.exceptions.ChargeNotFoundException;
import org.mifosng.platform.exceptions.FundNotFoundException;
import org.mifosng.platform.exceptions.InvalidCurrencyException;
import org.mifosng.platform.exceptions.LoanProductNotFoundException;
import org.mifosng.platform.exceptions.LoanTransactionProcessingStrategyNotFoundException;
import org.mifosng.platform.loan.domain.LoanTransactionProcessingStrategyRepository;
import org.mifosng.platform.loanschedule.domain.AprCalculator;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.service.ConfigurationDomainService;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.charge.domain.Charge;
import org.mifosplatform.portfolio.charge.domain.ChargeRepository;
import org.mifosplatform.portfolio.fund.domain.Fund;
import org.mifosplatform.portfolio.fund.domain.FundRepository;
import org.mifosplatform.portfolio.loanproduct.command.LoanProductCommand;
import org.mifosplatform.portfolio.loanproduct.domain.AmortizationMethod;
import org.mifosplatform.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
import org.mifosplatform.portfolio.loanproduct.domain.InterestMethod;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRepository;
import org.mifosplatform.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
@Service
public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanProductWritePlatformService {
private final PlatformSecurityContext context;
private final LoanProductRepository loanProductRepository;
private final AprCalculator aprCalculator;
private final FundRepository fundRepository;
private final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository;
private final ChargeRepository chargeRepository;
private final ConfigurationDomainService configurationDomainService;
@Autowired
public LoanProductWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
final LoanProductRepository loanProductRepository, final AprCalculator aprCalculator, final FundRepository fundRepository,
final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository,
final ChargeRepository chargeRepository,
final ConfigurationDomainService configurationDomainService) {
this.context = context;
this.loanProductRepository = loanProductRepository;
this.aprCalculator = aprCalculator;
this.fundRepository = fundRepository;
this.loanTransactionProcessingStrategyRepository = loanTransactionProcessingStrategyRepository;
this.chargeRepository = chargeRepository;
this.configurationDomainService = configurationDomainService;
}
@Transactional
@Override
public EntityIdentifier createLoanProduct(final LoanProductCommand command) {
this.context.authenticatedUser();
LoanProductCommandValidator validator = new LoanProductCommandValidator(command);
validator.validateForCreate();
// assemble LoanProduct from data
InterestMethod interestMethod = InterestMethod.fromInt(command.getInterestType());
InterestCalculationPeriodMethod interestCalculationPeriodMethod = InterestCalculationPeriodMethod.fromInt(command
.getInterestCalculationPeriodType());
AmortizationMethod amortizationMethod = AmortizationMethod.fromInt(command.getAmortizationType());
PeriodFrequencyType repaymentFrequencyType = PeriodFrequencyType.fromInt(command.getRepaymentFrequencyType());
PeriodFrequencyType interestFrequencyType = PeriodFrequencyType.fromInt(command.getInterestRateFrequencyType());
MonetaryCurrency currency = new MonetaryCurrency(command.getCurrencyCode(), command.getDigitsAfterDecimal());
BigDecimal annualInterestRate = this.aprCalculator.calculateFrom(interestFrequencyType, command.getInterestRatePerPeriod());
// associating fund with loan product at creation is optional for now.
Fund fund = findFundByIdIfProvided(command.getFundId());
LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(command
.getTransactionProcessingStrategyId());
final Set<Charge> charges = this.assembleSetOfCharges(command, null);
LoanProduct loanproduct = new LoanProduct(fund, loanTransactionProcessingStrategy, command.getName(), command.getDescription(),
currency, command.getPrincipal(), command.getInterestRatePerPeriod(), interestFrequencyType, annualInterestRate,
interestMethod, interestCalculationPeriodMethod, command.getRepaymentEvery(), repaymentFrequencyType,
command.getNumberOfRepayments(), amortizationMethod, command.getInArrearsTolerance(), charges);
this.loanProductRepository.save(loanproduct);
if (this.configurationDomainService.isMakerCheckerEnabledForTask("CREATE_LOANPRODUCT") && !command.isApprovedByChecker()) { throw new RollbackTransactionAsCommandIsNotApprovedByCheckerException(); }
return new EntityIdentifier(loanproduct.getId());
}
private LoanTransactionProcessingStrategy findStrategyByIdIfProvided(final Long transactionProcessingStrategyId) {
LoanTransactionProcessingStrategy strategy = null;
if (transactionProcessingStrategyId != null) {
strategy = this.loanTransactionProcessingStrategyRepository.findOne(transactionProcessingStrategyId);
if (strategy == null) { throw new LoanTransactionProcessingStrategyNotFoundException(transactionProcessingStrategyId); }
}
return strategy;
}
private Fund findFundByIdIfProvided(final Long fundId) {
Fund fund = null;
if (fundId != null) {
fund = this.fundRepository.findOne(fundId);
if (fund == null) { throw new FundNotFoundException(fundId); }
}
return fund;
}
@Transactional
@Override
public EntityIdentifier updateLoanProduct(final LoanProductCommand command) {
this.context.authenticatedUser();
LoanProductCommandValidator validator = new LoanProductCommandValidator(command);
validator.validateForUpdate();
LoanProduct product = this.loanProductRepository.findOne(command.getId());
if (product == null) { throw new LoanProductNotFoundException(command.getId()); }
// associating fund with loan product at creation is optional for now.
Fund fund = null;
if (command.isFundChanged()) {
fund = findFundByIdIfProvided(command.getFundId());
}
LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = null;
if (command.isTransactionProcessingStrategyChanged()) {
loanTransactionProcessingStrategy = findStrategyByIdIfProvided(command.getTransactionProcessingStrategyId());
}
final Set<Charge> charges = this.assembleSetOfCharges(command, product.getCurrency().getCode());
product.update(command, fund, loanTransactionProcessingStrategy, charges);
this.loanProductRepository.save(product);
if (this.configurationDomainService.isMakerCheckerEnabledForTask("UPDATE_LOANPRODUCT") && !command.isApprovedByChecker()) { throw new RollbackTransactionAsCommandIsNotApprovedByCheckerException(); }
return new EntityIdentifier(Long.valueOf(product.getId()));
}
private Set<Charge> assembleSetOfCharges(final LoanProductCommand command, final String currencyCode) {
Set<Charge> charges = new HashSet<Charge>();
String[] chargesArray = command.getCharges();
String loanProductCurrencyCode = command.getCurrencyCode();
if (loanProductCurrencyCode == null) {
loanProductCurrencyCode = currencyCode;
}
if (command.isChargesChanged() && !ObjectUtils.isEmpty(chargesArray)) {
for (String chargeId : chargesArray) {
Long id = Long.valueOf(chargeId);
Charge charge = this.chargeRepository.findOne(id);
if (charge == null || charge.isDeleted()) { throw new ChargeNotFoundException(id); }
if (!charge.isActive()) { throw new ChargeIsNotActiveException(id, charge.getName()); }
if (!loanProductCurrencyCode.equals(charge.getCurrencyCode())) {
String errorMessage = "Charge and Loan Product must have the same currency.";
throw new InvalidCurrencyException("charge", "attach.to.loan.product", errorMessage);
}
charges.add(charge);
}
}
return charges;
}
}
@@ -6,8 +6,8 @@ package org.mifosng.platform.loanschedule.domain;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
import org.mockito.runners.MockitoJUnitRunner;
@SuppressWarnings("unused")
@@ -6,8 +6,8 @@ package org.mifosng.platform.loanschedule.domain;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
import org.mockito.runners.MockitoJUnitRunner;
@SuppressWarnings("unused")
@@ -2,13 +2,13 @@ package org.mifosng.platform.loanschedule.domain;
import java.math.BigDecimal;
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.LoanProductRelatedDetail;
import org.mifosng.platform.loan.domain.MonetaryCurrencyBuilder;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.portfolio.loanproduct.domain.AmortizationMethod;
import org.mifosplatform.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
import org.mifosplatform.portfolio.loanproduct.domain.InterestMethod;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
/**
* This class is used to keep in one place configurations for setting up {@link LoanProductRelatedDetail} object used in {@link LoanScheduleGenerator}'s