Adding short names for loan and saving products

This commit is contained in:
Madhukar
2013-12-24 17:38:24 +05:30
parent 570296d10a
commit f32225e275
17 changed files with 145 additions and 37 deletions
+24 -2
View File
@@ -7873,6 +7873,14 @@ Request Body:
<tr>
<td class=fielddesc>Name associated with loan product on system.</td>
</tr>
<tr class=alt>
<td>shortName</td>
</tr>
<tr>
<td class=fielddesc>Shortname associated with a loan product. <br>
An abbreviated version of the name, used in reports or menus where space is limited, such as Collection Sheets.
</td>
</tr>
<tr class=alt>
<td>description</td>
</tr>
@@ -8090,6 +8098,7 @@ GET https://DomainName/api/v1/loanproducts
{
"id": 1,
"name": "personal loan product",
"shortName": "pe1",
"includeInBorrowerCycle": false,
"useBorrowerCycle": false,
"startDate": [
@@ -8937,6 +8946,7 @@ GET https://DomainName/api/v1/loanproducts/{productId}
{
"id": 11,
"name": "advanced accounting",
"shortName": "ad11",
"includeInBorrowerCycle": true,
"useBorrowerCycle": true,
"status": "loanProduct.active",
@@ -9148,7 +9158,7 @@ GET https://DomainName/api/v1/loanproducts/{productId}
<td><div class="mifosXHeading2">Mandatory Fields</div></td>
</tr>
<tr class=alt>
<td>name, currencyCode, digitsAfterDecimal, inMultiplesOf, principal,
<td>name, shortName, currencyCode, digitsAfterDecimal, inMultiplesOf, principal,
numberOfRepayments, repaymentEvery, repaymentFrequencyType,
interestRatePerPeriod, interestRateFrequencyType, amortizationType, interestType,
interestCalculationPeriodType, transactionProcessingStrategyId,
@@ -9222,6 +9232,7 @@ Request Body:
],
"accountingRule":"2",
"name":"product 5",
"shortName":"prd5",
"principal":"5000",
"numberOfRepayments":"7",
"repaymentEvery":"7",
@@ -9253,6 +9264,7 @@ Content-Type: application/json
Request Body:
{
"name": "LP Cash Accounting",
"shortName": "LPCA",
"currencyCode": "USD",
"locale": "en_GB",
"digitsAfterDecimal": "2",
@@ -9312,6 +9324,7 @@ Content-Type: application/json
Request Body:
{
"name": "LP Accrual Accounting",
"shortName": "LPAA",
"currencyCode": "USD",
"locale": "en_GB",
"digitsAfterDecimal": "2",
@@ -12934,6 +12947,11 @@ Content-Type: application/json
<tr class=alt><td>name</td></tr>
<tr><td class=fielddesc>The name of the product offering.</td></tr>
<tr class=alt><td>shortName</td></tr>
<tr><td class=fielddesc>Shortname associated with a saving product. <br>
An abbreviated version of the name, used in reports or menus where space is limited.
</td></tr>
<tr class=alt><td>description</td></tr>
<tr><td class=fielddesc>A description of the product offering.</td></tr>
@@ -13537,7 +13555,7 @@ Content-Type: application/json
<table class=matrixHeading>
<tr class="matrixHeadingBG"><td><div class="mifosXHeading2">Mandatory Fields</div></td></tr>
<tr class=alt>
<td>name, description, currencyCode, digitsAfterDecimal,inMultiplesOf, nominalAnnualInterestRate,
<td>name, shortName, description, currencyCode, digitsAfterDecimal,inMultiplesOf, nominalAnnualInterestRate,
interestCompoundingPeriodType, interestCalculationType, interestCalculationDaysInYearType,accountingRule</td>
</tr>
</table>
@@ -13561,6 +13579,7 @@ Content-Type: application/json
Request Body:
{
"name": "Passbook Savings",
"shortName": "PBSV",
"description": "Daily compounding using Daily Balance, 5% per year, 365 days in year",
"currencyCode": "USD",
"digitsAfterDecimal": 2,
@@ -13586,6 +13605,7 @@ Request Body:
{
"locale": "en",
"name": "New Passbook Savings ",
"shortName": "NPBS",
"description": "A savings product",
"currencyCode": "USD",
"digitsAfterDecimal": "2",
@@ -13652,6 +13672,7 @@ Request Body:
{
"id": 1,
"name": "savings product",
"shortName": "sa1",
"description": "gtasga",
"currency": {
"code": "USD",
@@ -13835,6 +13856,7 @@ Content-Type: application/json
{
"id": 1,
"name": "Savings product",
"shortName": "sa1",
"description": "gtasga",
"currency": {
"code": "USD",
@@ -0,0 +1,18 @@
ALTER TABLE `m_product_loan`
ADD COLUMN `short_name` VARCHAR(4) NULL DEFAULT NULL AFTER `id`;
update m_product_loan set short_name=concat(LEFT(name,2), RIGHT(id,2)) where short_name is null;
ALTER TABLE `m_product_loan`
ALTER `short_name` DROP DEFAULT;
ALTER TABLE `m_product_loan`
CHANGE COLUMN `short_name` `short_name` VARCHAR(4) NOT NULL AFTER `id`;
ALTER TABLE `m_product_loan`
ADD UNIQUE INDEX `unq_short_name` (`short_name`);
ALTER TABLE `m_savings_product`
ADD COLUMN `short_name` VARCHAR(4) NULL DEFAULT NULL AFTER `name`;
update m_savings_product set short_name=concat(LEFT(name,2), RIGHT(id,2)) where short_name is null;
ALTER TABLE `m_savings_product`
ALTER `short_name` DROP DEFAULT;
ALTER TABLE `m_savings_product`
CHANGE COLUMN `short_name` `short_name` VARCHAR(4) NOT NULL AFTER `name`,
ADD UNIQUE INDEX `sp_unq_short_name` (`short_name`);
@@ -215,7 +215,7 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
+ "ln.id As loanId, "
+ "ln.account_no As accountId, "
+ "ln.loan_status_id As accountStatusId, "
+ "pl.name As productShortName, "
+ "pl.short_name As productShortName, "
+ "ln.product_id As productId, "
+ "ln.currency_code as currencyCode, ln.currency_digits as currencyDigits, ln.currency_multiplesof as inMultiplesOf, rc.`name` as currencyName, rc.display_symbol as currencyDisplaySymbol, rc.internationalized_name_code as currencyNameCode, "
+ "if(ln.loan_status_id = 200 , ln.principal_amount , null) As disbursementAmount, "
@@ -49,4 +49,5 @@ public interface LoanProductConstants {
public static final String VALUE_CONDITION_END_WITH_ERROR = "condition.type.must.end.with.greterthan";
public static final String VALUE_CONDITION_START_WITH_ERROR = "condition.type.must.start.with.equal";
public static final String shortName = "shortName";
}
@@ -63,7 +63,7 @@ import org.springframework.stereotype.Component;
@Scope("singleton")
public class LoanProductsApiResource {
private final Set<String> LOAN_PRODUCT_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "name", "description", "fundId",
private final Set<String> LOAN_PRODUCT_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "name", "shortName", "description", "fundId",
"fundName", "includeInBorrowerCycle", "currency", "principal", "minPrincipal", "maxPrincipal", "numberOfRepayments",
"minNumberOfRepayments", "maxNumberOfRepayments", "repaymentEvery", "repaymentFrequencyType", "graceOnPrincipalPayment",
"graceOnInterestPayment", "graceOnInterestCharged", "interestRatePerPeriod", "minInterestRatePerPeriod",
@@ -35,6 +35,7 @@ public class LoanProductData {
private final Long id;
private final String name;
private final String shortName;
private final String description;
private final Long fundId;
private final String fundName;
@@ -109,6 +110,7 @@ public class LoanProductData {
* Used when returning lookup information about loan product for dropdowns.
*/
public static LoanProductData lookup(final Long id, final String name) {
final String shortName = null;
final String description = null;
final CurrencyData currency = null;
final BigDecimal principal = null;
@@ -146,7 +148,7 @@ public class LoanProductData {
final LocalDate closeDate = null;
final String status = null;
final String externalId = null;
return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments,
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments,
minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod, minInterestRatePerPeriod,
maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType,
interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId,
@@ -156,6 +158,7 @@ public class LoanProductData {
}
public static LoanProductData lookupWithCurrency(final Long id, final String name, final CurrencyData currency) {
final String shortName = null;
final String description = null;
final BigDecimal principal = null;
final BigDecimal minPrincipal = null;
@@ -195,7 +198,7 @@ public class LoanProductData {
final Collection<LoanProductBorrowerCycleVariationData> interestRateVariations = new ArrayList<LoanProductBorrowerCycleVariationData>(1);
final Collection<LoanProductBorrowerCycleVariationData> numberOfRepaymentVariations = new ArrayList<LoanProductBorrowerCycleVariationData>(1);
return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments,
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments,
minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod, minInterestRatePerPeriod,
maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType,
interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId,
@@ -207,6 +210,7 @@ public class LoanProductData {
public static LoanProductData sensibleDefaultsForNewLoanProductCreation() {
final Long id = null;
final String name = null;
final String shortName = null;
final String description = null;
final CurrencyData currency = CurrencyData.blank();
final BigDecimal principal = null;
@@ -250,7 +254,7 @@ public class LoanProductData {
final String status = null;
final String externalId = null;
return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments,
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments,
minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod, minInterestRatePerPeriod,
maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType,
interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId,
@@ -270,7 +274,7 @@ public class LoanProductData {
return productData;
}
public LoanProductData(final Long id, final String name, final String description, final CurrencyData currency,
public LoanProductData(final Long id, final String name, final String shortName, final String description, final CurrencyData currency,
final BigDecimal principal, final BigDecimal minPrincipal, final BigDecimal maxPrincipal, final BigDecimal tolerance,
final Integer numberOfRepayments, final Integer minNumberOfRepayments, final Integer maxNumberOfRepayments,
final Integer repaymentEvery, final BigDecimal interestRatePerPeriod, final BigDecimal minInterestRatePerPeriod,
@@ -285,6 +289,7 @@ public class LoanProductData {
Collection<LoanProductBorrowerCycleVariationData> numberOfRepaymentVariations) {
this.id = id;
this.name = name;
this.shortName = shortName;
this.description = description;
this.currency = currency;
this.principal = principal;
@@ -354,6 +359,7 @@ public class LoanProductData {
final List<EnumOptionData> valueConditionTypeOptions) {
this.id = productData.id;
this.name = productData.name;
this.shortName = productData.shortName;
this.description = productData.description;
this.fundId = productData.fundId;
this.fundName = productData.fundName;
@@ -57,7 +57,8 @@ import com.google.gson.JsonObject;
*/
@Entity
@Table(name = "m_product_loan", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "unq_name"),
@UniqueConstraint(columnNames = { "external_id" }, name = "external_id_UNIQUE") })
@UniqueConstraint(columnNames = { "external_id" }, name = "external_id_UNIQUE"),
@UniqueConstraint(columnNames = { "short_name" }, name = "unq_short_name")})
public class LoanProduct extends AbstractPersistable<Long> {
@ManyToOne
@@ -70,6 +71,9 @@ public class LoanProduct extends AbstractPersistable<Long> {
@Column(name = "name", nullable = false, unique = true)
private String name;
@Column(name = "short_name", nullable = false, unique = true)
private String shortName;
@Column(name = "description")
private String description;
@@ -112,6 +116,7 @@ public class LoanProduct extends AbstractPersistable<Long> {
final List<Charge> productCharges, final JsonCommand command, final AprCalculator aprCalculator) {
final String name = command.stringValueOfParameterNamed("name");
final String shortName = command.stringValueOfParameterNamed(LoanProductConstants.shortName);
final String description = command.stringValueOfParameterNamed("description");
final String currencyCode = command.stringValueOfParameterNamed("currencyCode");
final Integer digitsAfterDecimal = command.integerValueOfParameterNamed("digitsAfterDecimal");
@@ -160,7 +165,7 @@ public class LoanProduct extends AbstractPersistable<Long> {
populateBorrowerCyclevariations(command, loanProductBorrowerCycleVariations);
}
return new LoanProduct(fund, loanTransactionProcessingStrategy, name, description, currency, principal, minPrincipal, maxPrincipal,
return new LoanProduct(fund, loanTransactionProcessingStrategy, name, shortName, description, currency, principal, minPrincipal, maxPrincipal,
interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod, interestFrequencyType, annualInterestRate,
interestMethod, interestCalculationPeriodMethod, repaymentEvery, repaymentFrequencyType, numberOfRepayments,
minNumberOfRepayments, maxNumberOfRepayments, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged,
@@ -362,7 +367,7 @@ public class LoanProduct extends AbstractPersistable<Long> {
}
public LoanProduct(final Fund fund, final LoanTransactionProcessingStrategy transactionProcessingStrategy, final String name,
final String description, final MonetaryCurrency currency, final BigDecimal defaultPrincipal,
final String shortName, final String description, final MonetaryCurrency currency, final BigDecimal defaultPrincipal,
final BigDecimal defaultMinPrincipal, final BigDecimal defaultMaxPrincipal,
final BigDecimal defaultNominalInterestRatePerPeriod, final BigDecimal defaultMinNominalInterestRatePerPeriod,
final BigDecimal defaultMaxNominalInterestRatePerPeriod, final PeriodFrequencyType interestPeriodFrequencyType,
@@ -378,6 +383,7 @@ public class LoanProduct extends AbstractPersistable<Long> {
this.fund = fund;
this.transactionProcessingStrategy = transactionProcessingStrategy;
this.name = name.trim();
this.shortName = shortName.trim();
if (StringUtils.isNotBlank(description)) {
this.description = description.trim();
} else {
@@ -477,6 +483,13 @@ public class LoanProduct extends AbstractPersistable<Long> {
actualChanges.put(nameParamName, newValue);
this.name = newValue;
}
final String shortNameParamName = LoanProductConstants.shortName;
if (command.isChangeInStringParameterNamed(shortNameParamName, this.shortName)) {
final String newValue = command.stringValueOfParameterNamed(shortNameParamName);
actualChanges.put(shortNameParamName, newValue);
this.shortName = newValue;
}
final String descriptionParamName = "description";
if (command.isChangeInStringParameterNamed(descriptionParamName, this.description)) {
@@ -56,7 +56,7 @@ public final class LoanProductDataValidator {
LOAN_PRODUCT_ACCOUNTING_PARAMS.FEE_INCOME_ACCOUNT_MAPPING.getValue(),
LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTY_INCOME_ACCOUNT_MAPPING.getValue(),LoanProductConstants.useBorrowerCycleParameterName,
LoanProductConstants.principalVariationsForBorrowerCycleParameterName,LoanProductConstants.interestRateVariationsForBorrowerCycleParameterName,
LoanProductConstants.numberOfRepaymentVariationsForBorrowerCycleParameterName));
LoanProductConstants.numberOfRepaymentVariationsForBorrowerCycleParameterName, LoanProductConstants.shortName));
private final FromJsonHelper fromApiJsonHelper;
@@ -78,6 +78,9 @@ public final class LoanProductDataValidator {
final String name = this.fromApiJsonHelper.extractStringNamed("name", element);
baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(100);
final String shortName = this.fromApiJsonHelper.extractStringNamed(LoanProductConstants.shortName, element);
baseDataValidator.reset().parameter(LoanProductConstants.shortName).value(shortName).notBlank().notExceedingLengthOf(4);
final String description = this.fromApiJsonHelper.extractStringNamed("description", element);
baseDataValidator.reset().parameter("description").value(description).notExceedingLengthOf(500);
@@ -340,6 +343,11 @@ public final class LoanProductDataValidator {
final String name = this.fromApiJsonHelper.extractStringNamed("name", element);
baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(100);
}
if (this.fromApiJsonHelper.parameterExists(LoanProductConstants.shortName, element)) {
final String shortName = this.fromApiJsonHelper.extractStringNamed(LoanProductConstants.shortName, element);
baseDataValidator.reset().parameter(LoanProductConstants.shortName).value(shortName).notBlank().notExceedingLengthOf(4);
}
if (this.fromApiJsonHelper.parameterExists("description", element)) {
final String description = this.fromApiJsonHelper.extractStringNamed("description", element);
@@ -112,7 +112,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
public String loanProductSchema() {
return "lp.id as id, lp.fund_id as fundId, f.name as fundName, lp.loan_transaction_strategy_id as transactionStrategyId, ltps.name as transactionStrategyName, "
+ "lp.name as name, lp.description as description, "
+ "lp.name as name, lp.short_name as shortName, lp.description as description, "
+ "lp.principal_amount as principal, lp.min_principal_amount as minPrincipal, lp.max_principal_amount as maxPrincipal, lp.currency_code as currencyCode, lp.currency_digits as currencyDigits, lp.currency_multiplesof as inMultiplesOf, "
+ "lp.nominal_interest_rate_per_period as interestRatePerPeriod, lp.min_nominal_interest_rate_per_period as minInterestRatePerPeriod, lp.max_nominal_interest_rate_per_period as maxInterestRatePerPeriod, lp.interest_period_frequency_enum as interestRatePerPeriodFreq, "
+ "lp.annual_nominal_interest_rate as annualInterestRate, lp.interest_method_enum as interestMethod, lp.interest_calculated_in_period_enum as interestCalculationInPeriodMethod,"
@@ -132,6 +132,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
final Long id = rs.getLong("id");
final String name = rs.getString("name");
final String shortName = rs.getString("shortName");
final String description = rs.getString("description");
final Long fundId = JdbcSupport.getLong(rs, "fundId");
final String fundName = rs.getString("fundName");
@@ -213,7 +214,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
}
}
return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType,
interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, fundId, fundName,
@@ -237,6 +237,11 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
final String name = command.stringValueOfParameterNamed("name");
throw new PlatformDataIntegrityException("error.msg.product.loan.duplicate.name", "Loan product with name `" + name
+ "` already exists", "name", name);
} else if (realCause.getMessage().contains("unq_short_name")) {
final String shortName = command.stringValueOfParameterNamed("shortName");
throw new PlatformDataIntegrityException("error.msg.product.loan.duplicate.short.name", "Loan product with short name `" + shortName
+ "` already exists", "shortName", shortName);
} else if (realCause.getMessage().contains("Duplicate entry")) {
final Object[] args = null;
throw new PlatformDataIntegrityException("error.msg.product.loan.duplicate.charge",
@@ -66,6 +66,7 @@ public class SavingsApiConstants {
public static final String activeParamName = "active";
public static final String nameParamName = "name";
public static final String shortNameParamName = "shortName";
public static final String descriptionParamName = "description";
public static final String currencyCodeParamName = "currencyCode";
public static final String digitsAfterDecimalParamName = "digitsAfterDecimal";
@@ -129,7 +130,7 @@ public class SavingsApiConstants {
public static final Set<String> SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
monthDayFormatParamName, nameParamName, descriptionParamName, currencyCodeParamName, digitsAfterDecimalParamName,
monthDayFormatParamName, nameParamName, shortNameParamName, descriptionParamName, currencyCodeParamName, digitsAfterDecimalParamName,
inMultiplesOfParamName, nominalAnnualInterestRateParamName, interestCompoundingPeriodTypeParamName,
interestPostingPeriodTypeParamName, interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName,
minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName,
@@ -150,7 +151,7 @@ public class SavingsApiConstants {
* parameters to match those of request parameters.
*/
public static final Set<String> SAVINGS_PRODUCT_RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(idParamName,
nameParamName, descriptionParamName, "currency", digitsAfterDecimalParamName, inMultiplesOfParamName,
nameParamName, shortNameParamName, descriptionParamName, "currency", digitsAfterDecimalParamName, inMultiplesOfParamName,
nominalAnnualInterestRateParamName, interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName,
interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName,
lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName,
@@ -26,6 +26,7 @@ public class SavingsProductData {
private final Long id;
private final String name;
private final String shortName;
private final String description;
private final CurrencyData currency;
private final BigDecimal nominalAnnualInterestRate;
@@ -76,6 +77,7 @@ public class SavingsProductData {
final Long id = null;
final String name = null;
final String shortName = null;
final String description = null;
final BigDecimal nominalAnnualInterestRate = null;
final BigDecimal minRequiredOpeningBalance = null;
@@ -88,7 +90,7 @@ public class SavingsProductData {
final Collection<ChargeToGLAccountMapper> feeToIncomeAccountMappings = null;
final Collection<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = null;
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
return new SavingsProductData(id, name, shortName, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, accountingRule, accountingMappings,
paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions,
@@ -99,7 +101,7 @@ public class SavingsProductData {
}
public static SavingsProductData withCharges(final SavingsProductData product, final Collection<ChargeData> charges) {
return new SavingsProductData(product.id, product.name, product.description, product.currency, product.nominalAnnualInterestRate,
return new SavingsProductData(product.id, product.name, product.shortName, product.description, product.currency, product.nominalAnnualInterestRate,
product.interestCompoundingPeriodType, product.interestPostingPeriodType, product.interestCalculationType,
product.interestCalculationDaysInYearType, product.minRequiredOpeningBalance, product.lockinPeriodFrequency,
product.lockinPeriodFrequencyType, product.withdrawalFeeForTransfers, product.accountingRule, product.accountingMappings,
@@ -125,8 +127,8 @@ public class SavingsProductData {
final Map<String, List<GLAccountData>> accountingMappingOptions, final Collection<ChargeData> chargeOptions,
final Collection<ChargeData> penaltyOptions) {
return new SavingsProductData(existingProduct.id, existingProduct.name, existingProduct.description, existingProduct.currency,
existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType,
return new SavingsProductData(existingProduct.id, existingProduct.name, existingProduct.shortName, existingProduct.description,
existingProduct.currency, existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType,
existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType,
existingProduct.interestCalculationDaysInYearType, existingProduct.minRequiredOpeningBalance,
existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType,
@@ -157,8 +159,8 @@ public class SavingsProductData {
final Collection<ChargeData> chargeOptions = null;
final Collection<ChargeData> penaltyOptions = null;
return new SavingsProductData(existingProduct.id, existingProduct.name, existingProduct.description, existingProduct.currency,
existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType,
return new SavingsProductData(existingProduct.id, existingProduct.name, existingProduct.shortName, existingProduct.description,
existingProduct.currency, existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType,
existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType,
existingProduct.interestCalculationDaysInYearType, existingProduct.minRequiredOpeningBalance,
existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType,
@@ -170,8 +172,8 @@ public class SavingsProductData {
penaltyToIncomeAccountMappings);
}
public static SavingsProductData instance(final Long id, final String name, final String description, final CurrencyData currency,
final BigDecimal nominalAnnualInterestRate, final EnumOptionData interestCompoundingPeriodType,
public static SavingsProductData instance(final Long id, final String name, final String shortName, final String description,
final CurrencyData currency, final BigDecimal nominalAnnualInterestRate, final EnumOptionData interestCompoundingPeriodType,
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers,
@@ -196,7 +198,7 @@ public class SavingsProductData {
final Collection<ChargeToGLAccountMapper> feeToIncomeAccountMappings = null;
final Collection<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = null;
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
return new SavingsProductData(id, name, shortName, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, accountingType, accountingMappings,
paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions,
@@ -208,6 +210,7 @@ public class SavingsProductData {
public static SavingsProductData lookup(final Long id, final String name) {
final String shortName = null;
final CurrencyData currency = null;
final String description = null;
final BigDecimal nominalAnnualInterestRate = null;
@@ -239,7 +242,7 @@ public class SavingsProductData {
final Collection<ChargeToGLAccountMapper> feeToIncomeAccountMappings = null;
final Collection<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = null;
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
return new SavingsProductData(id, name, shortName, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers,
accountingType, accountingMappings, paymentChannelToFundSourceMappings,
@@ -249,7 +252,7 @@ public class SavingsProductData {
penaltyToIncomeAccountMappings);
}
private SavingsProductData(final Long id, final String name, final String description, final CurrencyData currency,
private SavingsProductData(final Long id, final String name, final String shortName, final String description, final CurrencyData currency,
final BigDecimal nominalAnnualInterestRate, final EnumOptionData interestCompoundingPeriodType,
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
@@ -268,6 +271,7 @@ public class SavingsProductData {
final Collection<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings) {
this.id = id;
this.name = name;
this.shortName = shortName;
this.description = description;
this.currency = currency;
this.nominalAnnualInterestRate = nominalAnnualInterestRate;
@@ -23,6 +23,7 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequire
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nameParamName;
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.shortNameParamName;
import java.lang.reflect.Type;
import java.math.BigDecimal;
@@ -76,6 +77,9 @@ public class SavingsProductDataValidator {
final String name = this.fromApiJsonHelper.extractStringNamed(nameParamName, element);
baseDataValidator.reset().parameter(nameParamName).value(name).notBlank().notExceedingLengthOf(100);
final String shortName = this.fromApiJsonHelper.extractStringNamed(shortNameParamName, element);
baseDataValidator.reset().parameter(shortNameParamName).value(shortName).notBlank().notExceedingLengthOf(4);
final String description = this.fromApiJsonHelper.extractStringNamed(descriptionParamName, element);
baseDataValidator.reset().parameter(descriptionParamName).value(description).notBlank().notExceedingLengthOf(500);
@@ -260,6 +264,11 @@ public class SavingsProductDataValidator {
final String name = this.fromApiJsonHelper.extractStringNamed(nameParamName, element);
baseDataValidator.reset().parameter(nameParamName).value(name).notBlank().notExceedingLengthOf(100);
}
if (this.fromApiJsonHelper.parameterExists(shortNameParamName, element)) {
final String shortName = this.fromApiJsonHelper.extractStringNamed(shortNameParamName, element);
baseDataValidator.reset().parameter(shortNameParamName).value(shortName).notBlank().notExceedingLengthOf(4);
}
if (this.fromApiJsonHelper.parameterExists(descriptionParamName, element)) {
final String description = this.fromApiJsonHelper.extractStringNamed(descriptionParamName, element);
@@ -23,6 +23,7 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequire
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nameParamName;
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.shortNameParamName;
import java.math.BigDecimal;
import java.util.ArrayList;
@@ -39,6 +40,7 @@ import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.mifosplatform.accounting.common.AccountingRuleType;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
@@ -58,11 +60,15 @@ import org.springframework.data.jpa.domain.AbstractPersistable;
import com.google.gson.JsonArray;
@Entity
@Table(name = "m_savings_product")
@Table(name = "m_savings_product", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "sp_unq_name"),
@UniqueConstraint(columnNames = { "short_name" }, name = "sp_unq_short_name")})
public class SavingsProduct extends AbstractPersistable<Long> {
@Column(name = "name", nullable = false)
@Column(name = "name", nullable = false, unique = true)
private String name;
@Column(name = "short_name", nullable = false, unique = true)
private String shortName;
@Column(name = "description", length = 500, nullable = false)
private String description;
@@ -124,14 +130,14 @@ public class SavingsProduct extends AbstractPersistable<Long> {
@JoinTable(name = "m_savings_product_charge", joinColumns = @JoinColumn(name = "savings_product_id"), inverseJoinColumns = @JoinColumn(name = "charge_id"))
private Set<Charge> charges;
public static SavingsProduct createNew(final String name, final String description, final MonetaryCurrency currency,
public static SavingsProduct createNew(final String name, final String shortName, final String description, final MonetaryCurrency currency,
final BigDecimal interestRate, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set<Charge> charges) {
return new SavingsProduct(name, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
return new SavingsProduct(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges);
}
@@ -141,7 +147,7 @@ public class SavingsProduct extends AbstractPersistable<Long> {
this.description = null;
}
private SavingsProduct(final String name, final String description, final MonetaryCurrency currency, final BigDecimal interestRate,
private SavingsProduct(final String name, final String shortName, final String description, final MonetaryCurrency currency, final BigDecimal interestRate,
final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
@@ -149,6 +155,7 @@ public class SavingsProduct extends AbstractPersistable<Long> {
final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set<Charge> charges) {
this.name = name;
this.shortName = shortName;
this.description = description;
this.currency = currency;
@@ -238,6 +245,12 @@ public class SavingsProduct extends AbstractPersistable<Long> {
actualChanges.put(nameParamName, newValue);
this.name = newValue;
}
if (command.isChangeInStringParameterNamed(shortNameParamName, this.name)) {
final String newValue = command.stringValueOfParameterNamed(shortNameParamName);
actualChanges.put(shortNameParamName, newValue);
this.shortName = newValue;
}
if (command.isChangeInStringParameterNamed(descriptionParamName, this.description)) {
final String newValue = command.stringValueOfParameterNamed(descriptionParamName);
@@ -21,6 +21,7 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequire
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nameParamName;
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.shortNameParamName;
import java.math.BigDecimal;
import java.util.HashSet;
@@ -57,6 +58,7 @@ public class SavingsProductAssembler {
public SavingsProduct assemble(final JsonCommand command) {
final String name = command.stringValueOfParameterNamed(nameParamName);
final String shortName = command.stringValueOfParameterNamed(shortNameParamName);
final String description = command.stringValueOfParameterNamed(descriptionParamName);
final String currencyCode = command.stringValueOfParameterNamed(currencyCodeParamName);
@@ -111,7 +113,7 @@ public class SavingsProductAssembler {
// Savings product charges
final Set<Charge> charges = assembleListOfSavingsProductCharges(command, currencyCode);
return SavingsProduct.createNew(name, description, currency, interestRate, interestCompoundingPeriodType,
return SavingsProduct.createNew(name, shortName, description, currency, interestRate, interestCompoundingPeriodType,
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
lockinPeriodFrequency, lockinPeriodFrequencyType, iswithdrawalFeeApplicableForTransfer, accountingRuleType, charges);
}
@@ -73,9 +73,8 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
public SavingProductMapper() {
final StringBuilder sqlBuilder = new StringBuilder(400);
sqlBuilder.append("sp.id as id, sp.name as name, sp.description as description, ");
sqlBuilder
.append("sp.currency_code as currencyCode, sp.currency_digits as currencyDigits, sp.currency_multiplesof as inMultiplesOf, ");
sqlBuilder.append("sp.id as id, sp.name as name, sp.short_name as shortName, sp.description as description, ");
sqlBuilder.append("sp.currency_code as currencyCode, sp.currency_digits as currencyDigits, sp.currency_multiplesof as inMultiplesOf, ");
sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, ");
sqlBuilder.append("sp.nominal_annual_interest_rate as nominalAnnualInterestRate, ");
@@ -108,6 +107,7 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
final Long id = rs.getLong("id");
final String name = rs.getString("name");
final String shortName = rs.getString("shortName");
final String description = rs.getString("description");
final String currencyCode = rs.getString("currencyCode");
@@ -168,7 +168,7 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
annualFeeOnMonthDay = new MonthDay(annualFeeOnMonth, annualFeeOnDay);
}
*/
return SavingsProductData.instance(id, name, description, currency, nominalAnnualInterestRate, compoundingInterestPeriodType,
return SavingsProductData.instance(id, name, shortName, description, currency, nominalAnnualInterestRate, compoundingInterestPeriodType,
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, accountingRuleType);
}
@@ -65,6 +65,11 @@ public class SavingsProductWritePlatformServiceJpaRepositoryImpl implements Savi
final String name = command.stringValueOfParameterNamed("name");
throw new PlatformDataIntegrityException("error.msg.product.savings.duplicate.name", "Savings product with name `" + name
+ "` already exists", "name", name);
} else if (realCause.getMessage().contains("sp_unq_short_name")) {
final String shortName = command.stringValueOfParameterNamed("shortName");
throw new PlatformDataIntegrityException("error.msg.product.savings.duplicate.short.name", "Savings product with short name `"
+ shortName + "` already exists", "shortName", shortName);
}
logAsErrorUnexpectedDataIntegrityException(dae);