MIFOSX-250: interest calculation change for compounding with api docs updates.

This commit is contained in:
Keith Woodlock
2013-04-02 17:12:03 +01:00
parent 41b31ded07
commit ec810d9485
32 changed files with 866 additions and 799 deletions
+291 -96
View File
@@ -7496,11 +7496,17 @@ Content-Type: application/json
<tr class=alt><td>digitsAfterDecimal</td></tr>
<tr><td class=fielddesc>Override the currency default value for digitsAfterDecimal.</td></tr>
<tr class=alt><td>interestRate</td></tr>
<tr><td class=fielddesc>The default interest rate set when creating savings accounts of this type of product. e.g. <b>5</b>% Per year</td></tr>
<tr class=alt><td>nominalAnnualInterestRate</td></tr>
<tr><td class=fielddesc>The default interest rate set when creating savings accounts of this type of product. e.g. <b>5</b>% Per year - It number here is always expressed as the Nominal APR.</td></tr>
<tr class=alt><td>interestRatePeriodFrequencyType</td></tr>
<tr><td class=fielddesc>The default interest rate period type. 2=Per month, 3=Per year e.g. 5% <b>Per year</b></td></tr>
<tr class=alt><td>interestCompoundingPeriodType</td></tr>
<tr><td class=fielddesc>The period at which interest rate is compounded. 1=Daily, 2=Weekly (at end of week, sunday), 3=Every two weeks (at end of two weeks, sunday), 4=Monthly (at end of month), 5=Quarterly (at end of quarter, 31st Mar, 30th Jun, 30th Sep, 31st Dec), 6=Bi-Annually (30th June, 31st Dec), 7=Annually (31st Dec), 8=No Compounding - Simple Interest</td></tr>
<tr class=alt><td>interestCalculationType</td></tr>
<tr><td class=fielddesc>The interest calculation method used: 1=Daily Balance or 2=Average Daily Balance</td></tr>
<tr class=alt><td>interestCalculationDaysInYearType</td></tr>
<tr><td class=fielddesc>The setting for number of days in year to use: 360=360 Days, 365=365 Days</td></tr>
<tr class=alt><td>minRequiredOpeningBalance</td></tr>
<tr><td class=fielddesc><b>Optional</b>: If provided, sets the minimum deposit amount required to open a savings account e.g. <b>2,000</b></td></tr>
@@ -7515,7 +7521,7 @@ Content-Type: application/json
</div>
</div>
<a id="savingsproducts_template" name="savingsproducts_template" class="old-syle-anchor">&nbsp;</a>
<a id="savingsproducts_template" name="savingsproducts_template" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Retrieve Savings Product Template</h4>
@@ -7533,17 +7539,27 @@ Content-Type: application/json
<code class="method-response">
{
"currency": {
"code": "",
"name": "",
"decimalPlaces": 0,
"displaySymbol": "",
"nameCode": "",
"displayLabel": " []"
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$",
"nameCode": "currency.USD",
"displayLabel": "US Dollar ($)"
},
"interestRatePeriodFrequencyType": {
"id": 3,
"code": "savings.interest.rate.periodFrequencyType.years",
"value": "Per year"
"interestCompoundingPeriodType": {
"id": 1,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.daily",
"value": "Daily"
},
"interestCalculationType": {
"id": 1,
"code": "savingsInterestCalculationType.dailybalance",
"value": "Daily Balance"
},
"interestCalculationDaysInYearType": {
"id": 365,
"code": "savingsInterestCalculationDaysInYearType.days365",
"value": "365 Days"
},
"currencyOptions": [
{
@@ -7555,37 +7571,91 @@ Content-Type: application/json
"displayLabel": "US Dollar ($)"
}
],
"interestRatePeriodFrequencyTypeOptions": [
"interestCompoundingPeriodTypeOptions": [
{
"id": 1,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.daily",
"value": "Daily"
},
{
"id": 2,
"code": "savings.interest.rate.periodFrequencyType.months",
"value": "Per month"
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.weekly",
"value": "Weekly"
},
{
"id": 3,
"code": "savings.interest.rate.periodFrequencyType.years",
"value": "Per year"
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.biweekly",
"value": "Bi-Weekly"
},
{
"id": 4,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.monthly",
"value": "Monthly"
},
{
"id": 5,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.quarterly",
"value": "Quarterly"
},
{
"id": 6,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.biannual",
"value": "Semi-Annual"
},
{
"id": 7,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.annual",
"value": "Annually"
},
{
"id": 8,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.nocompounding",
"value": "No Compounding - Simple Interest"
}
],
"interestCalculationTypeOptions": [
{
"id": 1,
"code": "savingsInterestCalculationType.dailybalance",
"value": "Daily Balance"
},
{
"id": 2,
"code": "savingsInterestCalculationType.averagedailybalance",
"value": "Average Daily Balance"
}
],
"interestCalculationDaysInYearTypeOptions": [
{
"id": 360,
"code": "savingsInterestCalculationDaysInYearType.days360",
"value": "360 Days"
},
{
"id": 365,
"code": "savingsInterestCalculationDaysInYearType.days365",
"value": "365 Days"
}
],
"lockinPeriodFrequencyTypeOptions": [
{
"id": 0,
"code": "savings.lockin.periodFrequencyType.days",
"code": "savings.lockin.savingsPeriodFrequencyType.days",
"value": "Days"
},
{
"id": 1,
"code": "savings.lockin.periodFrequencyType.weeks",
"code": "savings.lockin.savingsPeriodFrequencyType.weeks",
"value": "Weeks"
},
{
"id": 2,
"code": "savings.lockin.periodFrequencyType.months",
"code": "savings.lockin.savingsPeriodFrequencyType.months",
"value": "Months"
},
{
"id": 3,
"code": "savings.lockin.periodFrequencyType.years",
"code": "savings.lockin.savingsPeriodFrequencyType.years",
"value": "Years"
}
]
@@ -7600,7 +7670,10 @@ Content-Type: application/json
<h4>Create a Savings Product</h4>
<table class=matrixHeading>
<tr class="matrixHeadingBG"><td><div class="mifosXHeading2">Mandatory Fields</div></td></tr>
<tr class=alt><td>name, description, currencyCode, digitsAfterDecimal, interestRate, interestRatePeriodFrequencyType</tr>
<tr class=alt>
<td>name, description, currencyCode, digitsAfterDecimal, nominalAnnualInterestRate,
interestCompoundingPeriodType, interestCalculationType, interestCalculationDaysInYearType</td>
</tr>
</table>
<br/>
<table class=matrixHeading>
@@ -7614,13 +7687,15 @@ Content-Type: application/json
Content-Type: application/json
Request Body:
{
"name": "individual savings",
"description": "An savings product offering for individuals.",
"name": "Passbook Savings",
"description": "Daily compounding using Daily Balance, 5% per year, 365 days in year",
"currencyCode": "USD",
"digitsAfterDecimal": 2,
"locale": "en",
"interestRate": "5.65",
"interestRatePeriodFrequencyType": 2
"nominalAnnualInterestRate": "5.0",
"interestCompoundingPeriodType": 1,
"interestCalculationType": 1,
"interestCalculationDaysInYearType": "365"
}
</code>
<code class="method-response">
@@ -7647,8 +7722,8 @@ Request Body:
<code class="method-response">
{
"id": 1,
"name": "individual savings",
"description": "An savings product offering for individuals. (updated)",
"name": "Passbook Savings",
"description": "Daily compounding using Daily Balance, 5% per year, 365 days in year",
"currency": {
"code": "USD",
"name": "US Dollar",
@@ -7657,13 +7732,23 @@ Request Body:
"nameCode": "currency.USD",
"displayLabel": "US Dollar ($)"
},
"interestRate": 5.73,
"interestRatePeriodFrequencyType": {
"id": 2,
"code": "savings.interest.rate.periodFrequencyType.months",
"value": "Per month"
"nominalAnnualInterestRate": 5,
"interestCompoundingPeriodType": {
"id": 1,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.daily",
"value": "Daily"
},
"interestCalculationType": {
"id": 1,
"code": "savingsInterestCalculationType.dailybalance",
"value": "Daily Balance"
},
"interestCalculationDaysInYearType": {
"id": 365,
"code": "savingsInterestCalculationDaysInYearType.days365",
"value": "365 Days"
}
}
}
</code>
</div>
</div>
@@ -7679,7 +7764,7 @@ Request Body:
Content-Type: application/json
Request Body:
{
"description": "An savings product offering for individuals. (updated)",
"description": "Passbook Savings Lite.",
"locale": "en",
"interestRate": "5.73"
}
@@ -7688,7 +7773,7 @@ Request Body:
{
"resourceId": 1,
"changes": {
"description": "An savings product offering for individuals. (updated)",
"description": "Passbook Savings Lite.",
"interestRate": 5.73,
"locale": "en"
}
@@ -7731,32 +7816,35 @@ Content-Type: application/json
<code class="method-declaration">GET https://Domain Name/api/v1/savingsproducts</code>
<code class="method-response">
[
{
{
"id": 1,
"name": "Passbook Savings",
"description": "Daily compounding using Daily Balance, 5% per year, 365 days in year",
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$",
"nameCode": "currency.USD",
"displayLabel": "US Dollar ($)"
},
"nominalAnnualInterestRate": 5,
"interestCompoundingPeriodType": {
"id": 1,
"name": "individual savings",
"description": "An savings product offering for individuals. (updated)",
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$",
"nameCode": "currency.USD",
"displayLabel": "US Dollar ($)"
},
"interestRate": 9.85,
"interestRatePeriodFrequencyType": {
"id": 3,
"code": "savings.interest.rate.periodFrequencyType.years",
"value": "Per year"
},
"minRequiredOpeningBalance": 1000,
"lockinPeriodFrequency": 3,
"lockinPeriodFrequencyType": {
"id": 2,
"code": "savings.interest.rate.periodFrequencyType.months",
"value": "Per month"
}
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.daily",
"value": "Daily"
},
"interestCalculationType": {
"id": 1,
"code": "savingsInterestCalculationType.dailybalance",
"value": "Daily Balance"
},
"interestCalculationDaysInYearType": {
"id": 365,
"code": "savingsInterestCalculationDaysInYearType.days365",
"value": "365 Days"
}
}
]
</code>
</div>
@@ -7793,11 +7881,17 @@ Content-Type: application/json
<tr class=alt><td>activationDate</td></tr>
<tr><td class=fielddesc>If <b>active</b> is true the <i>activationDate</i> must be provided. If the savings account has an entry for <i>minRequiredOpeningBalance</i> then a deposit for that amount with <i>activationDate</i> as the date is automatically entered.</td></tr>
<tr class=alt><td>interestRate</td></tr>
<tr><td class=fielddesc>The default interest rate set when creating savings accounts of this type of product. e.g. <b>5</b>% Per year</td></tr>
<tr class=alt><td>nominalAnnualInterestRate</td></tr>
<tr><td class=fielddesc>The interest rate set for savings account e.g. <b>5</b>% Per year - It is always expressed as the Nominal APR.</td></tr>
<tr class=alt><td>interestRatePeriodFrequencyType</td></tr>
<tr><td class=fielddesc>The default interest rate period type. 2=Per month, 3=Per year e.g. 5% <b>Per year</b></td></tr>
<tr class=alt><td>interestCompoundingPeriodType</td></tr>
<tr><td class=fielddesc>The period at which interest rate is compounded. 1=Daily, 2=Weekly (at end of week, sunday), 3=Every two weeks (at end of two weeks, sunday), 4=Monthly (at end of month), 5=Quarterly (at end of quarter, 31st Mar, 30th Jun, 30th Sep, 31st Dec), 6=Bi-Annually (30th June, 31st Dec), 7=Annually (31st Dec), 8=No Compounding - Simple Interest</td></tr>
<tr class=alt><td>interestCalculationType</td></tr>
<tr><td class=fielddesc>The interest calculation method used: 1=Daily Balance or 2=Average Daily Balance</td></tr>
<tr class=alt><td>interestCalculationDaysInYearType</td></tr>
<tr><td class=fielddesc>The setting for number of days in year to use: 360=360 Days, 365=365 Days</td></tr>
<tr class=alt><td>minRequiredOpeningBalance</td></tr>
<tr><td class=fielddesc><b>Optional</b>: If provided, sets the minimum deposit amount required to open a savings account e.g. <b>2,000</b></td></tr>
@@ -7856,9 +7950,9 @@ Content-Type: application/json
<code class="method-response">
{
"clientId": 1,
"clientName": "Client A AB",
"savingsProductId": 1,
"savingsProductName": "First",
"clientName": "John Doe",
"savingsProductId": 3,
"savingsProductName": "Passbook Savings",
"currency": {
"code": "USD",
"name": "US Dollar",
@@ -7867,56 +7961,121 @@ Content-Type: application/json
"nameCode": "currency.USD",
"displayLabel": "US Dollar ($)"
},
"interestRate": 12,
"interestRatePeriodFrequencyType": {
"id": 3,
"code": "savings.interest.rate.periodFrequencyType.years",
"value": "Per year"
"nominalAnnualInterestRate": 5,
"interestCompoundingPeriodType": {
"id": 1,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.daily",
"value": "Daily"
},
"minRequiredOpeningBalance": 1000,
"lockinPeriodFrequency": 3,
"lockinPeriodFrequencyType": {
"id": 2,
"code": "savings.interest.rate.periodFrequencyType.months",
"value": "Per month"
"interestCalculationType": {
"id": 1,
"code": "savingsInterestCalculationType.dailybalance",
"value": "Daily Balance"
},
"interestCalculationDaysInYearType": {
"id": 365,
"code": "savingsInterestCalculationDaysInYearType.days365",
"value": "365 Days"
},
"productOptions": [
{
"id": 1,
"name": "First"
}
],
"interestRatePeriodFrequencyTypeOptions": [
"name": "01-Compounding Daily"
},
{
"id": 2,
"code": "savings.interest.rate.periodFrequencyType.months",
"value": "Per month"
"name": "02-Compounding Monthly"
},
{
"id": 3,
"code": "savings.interest.rate.periodFrequencyType.years",
"value": "Per year"
"name": "Passbook Savings"
}
],
"interestCompoundingPeriodTypeOptions": [
{
"id": 1,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.daily",
"value": "Daily"
},
{
"id": 2,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.weekly",
"value": "Weekly"
},
{
"id": 3,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.biweekly",
"value": "Bi-Weekly"
},
{
"id": 4,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.monthly",
"value": "Monthly"
},
{
"id": 5,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.quarterly",
"value": "Quarterly"
},
{
"id": 6,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.biannual",
"value": "Semi-Annual"
},
{
"id": 7,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.annual",
"value": "Annually"
},
{
"id": 8,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.nocompounding",
"value": "No Compounding - Simple Interest"
}
],
"interestCalculationTypeOptions": [
{
"id": 1,
"code": "savingsInterestCalculationType.dailybalance",
"value": "Daily Balance"
},
{
"id": 2,
"code": "savingsInterestCalculationType.averagedailybalance",
"value": "Average Daily Balance"
}
],
"interestCalculationDaysInYearTypeOptions": [
{
"id": 360,
"code": "savingsInterestCalculationDaysInYearType.days360",
"value": "360 Days"
},
{
"id": 365,
"code": "savingsInterestCalculationDaysInYearType.days365",
"value": "365 Days"
}
],
"lockinPeriodFrequencyTypeOptions": [
{
"id": 0,
"code": "savings.lockin.periodFrequencyType.days",
"code": "savings.lockin.savingsPeriodFrequencyType.days",
"value": "Days"
},
{
"id": 1,
"code": "savings.lockin.periodFrequencyType.weeks",
"code": "savings.lockin.savingsPeriodFrequencyType.weeks",
"value": "Weeks"
},
{
"id": 2,
"code": "savings.lockin.periodFrequencyType.months",
"code": "savings.lockin.savingsPeriodFrequencyType.months",
"value": "Months"
},
{
"id": 3,
"code": "savings.lockin.periodFrequencyType.years",
"code": "savings.lockin.savingsPeriodFrequencyType.years",
"value": "Years"
}
]
@@ -7932,7 +8091,8 @@ Content-Type: application/json
<br/>
<table class=matrixHeading>
<tr class="matrixHeadingBG"><td><div class="mifosXHeading2">Mandatory Fields</div></td></tr>
<tr class=alt><td>clientId or groupId, productId, accountNo, externalId, active, (activationDate if active is true)</td></tr>
<tr class=alt><td>clientId or groupId, productId, accountNo, externalId,
active, (activationDate if active is true)</td></tr>
</table>
<br/>
<table class=matrixHeading>
@@ -7942,7 +8102,7 @@ Content-Type: application/json
<br/>
<table class=matrixHeading>
<tr class="matrixHeadingBG"><td><div class="mifosXHeading2">Inherited from Product (if not provided)</div></td></tr>
<tr class=alt><td>interestRate, interestRatePeriodFrequencyType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType</td></tr>
<tr class=alt><td>nominalAnnualInterestRate, interestCompoundingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType</td></tr>
</table>
</div>
<div class="method-example">
@@ -8028,6 +8188,33 @@ Request Body:
</div>
</div>
<a id="savingsaccounts_calculate_interest" name="savingsaccounts_calculate_interest" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h2>Calculate Interest on Savings Account</h2>
<p>
Calculates interest earned on a savings account based on todays date. It does not attempt to <b>post or credit</b> the interest on the account. That is responsibility of another API that will be called by overnight process.
</p>
</div>
<div class="method-example">
<code class="method-declaration">POST https://Domain Name/api/v1/savingsaccounts/{savingsId}?command=calculateInterest</code>
<code class="method-request">POST savingsaccount/1?command=calculateInterest
Content-Type: application/json
Request Body:
{
}
</code>
<code class="method-response">
{
"officeId": 1,
"clientId": 1,
"savingsId": 1,
"resourceId": 1
}
</code>
</div>
</div>
<a id="savingsaccounts_list" name="savingsaccounts_list" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
@@ -12290,6 +12477,14 @@ GET https://DomainName/api/v1/search?query=000000111
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}?command=calculateInterest</td>
<td><a href="#savingsaccounts_calculate_interest">Calculate Interest on a Savings Account</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class="alt">
<td><a href="#savingsaccounts_transactions">Savings Transactions</a></td>
<td>savingsaccounts/{accountId}/transactions?command=deposit</td>
<td><a href="#savingsaccounts_deposit">Make a Deposit</a></td>
@@ -12297,7 +12492,7 @@ GET https://DomainName/api/v1/search?query=000000111
<td></td>
<td></td>
</tr>
<tr class="alt">
<tr>
<td></td>
<td>savingsaccounts/{accountId}/transactions?command=withdrawal</td>
<td><a href="#savingsaccounts_withdrawal">Make a Withdrawal</a></td>
@@ -0,0 +1,11 @@
ALTER TABLE `m_savings_product`
DROP COLUMN `nominal_interest_rate_period_frequency_enum`,
CHANGE COLUMN `nominal_interest_rate_per_period` `nominal_annual_interest_rate` DECIMAL(19,6) NOT NULL,
CHANGE COLUMN `interest_period_enum` `interest_compounding_period_enum` SMALLINT(5) NOT NULL;
ALTER TABLE `m_savings_account`
DROP COLUMN `annual_nominal_interest_rate`,
DROP COLUMN `nominal_interest_rate_period_frequency_enum`,
CHANGE COLUMN `nominal_interest_rate_per_period` `nominal_annual_interest_rate` DECIMAL(19,6) NOT NULL,
CHANGE COLUMN `interest_period_enum` `interest_compounding_period_enum` SMALLINT(5) NOT NULL;
@@ -13,7 +13,6 @@ import org.joda.time.LocalDate;
import org.mifosplatform.commands.data.CommandSourceData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
@@ -23,11 +22,9 @@ import org.springframework.stereotype.Service;
public class PortfolioCommandsReadPlatformServiceImpl implements PortfolioCommandsReadPlatformService {
private final JdbcTemplate jdbcTemplate;
private final PlatformSecurityContext context;
@Autowired
public PortfolioCommandsReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource) {
this.context = context;
public PortfolioCommandsReadPlatformServiceImpl(final TenantAwareRoutingDataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@@ -53,7 +50,6 @@ public class PortfolioCommandsReadPlatformServiceImpl implements PortfolioComman
}
}
@Override
public CommandSourceData retrieveById(final Long id) {
@@ -140,8 +140,7 @@ public class SavingsAccountsApiResource {
Collection<SavingsAccountTransactionData> transactions = null;
Collection<SavingsProductData> productOptions = null;
Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions = null;
Collection<EnumOptionData> interestPeriodTypeOptions = null;
Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
Collection<EnumOptionData> interestCalculationTypeOptions = null;
Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
@@ -166,15 +165,13 @@ public class SavingsAccountsApiResource {
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
if (settings.isTemplate()) {
productOptions = this.savingsProductReadPlatformService.retrieveAllForLookup();
interestRatePeriodFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveInterestRatePeriodFrequencyTypeOptions();
interestPeriodTypeOptions = this.dropdownReadPlatformService.retrieveInterestPeriodTypeOptions();
interestCompoundingPeriodTypeOptions = this.dropdownReadPlatformService.retrieveCompoundingInterestPeriodTypeOptions();
interestCalculationTypeOptions = this.dropdownReadPlatformService.retrieveInterestCalculationTypeOptions();
lockinPeriodFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveLockinPeriodFrequencyTypeOptions();
}
return SavingsAccountData.withTemplateOptions(savingsAccount, productOptions, interestRatePeriodFrequencyTypeOptions,
interestPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
lockinPeriodFrequencyTypeOptions, transactions);
return SavingsAccountData.withTemplateOptions(savingsAccount, productOptions, interestCompoundingPeriodTypeOptions,
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, transactions);
}
@PUT
@@ -195,7 +192,7 @@ public class SavingsAccountsApiResource {
@Path("{accountId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String activate(@PathParam("accountId") final Long accountId, @QueryParam("command") final String commandParam,
public String handleCommands(@PathParam("accountId") final Long accountId, @QueryParam("command") final String commandParam,
final String apiRequestBodyAsJson) {
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
@@ -31,9 +31,9 @@ public class SavingsApiConstants {
public static final String descriptionParamName = "description";
public static final String currencyCodeParamName = "currencyCode";
public static final String digitsAfterDecimalParamName = "digitsAfterDecimal";
public static final String interestRateParamName = "interestRate";
public static final String interestRatePeriodFrequencyTypeParamName = "interestRatePeriodFrequencyType";
public static final String interestPeriodTypeParamName = "interestPeriodType";
public static final String nominalAnnualInterestRateParamName = "nominalAnnualInterestRate";
public static final String interestCompoundingPeriodTypeParamName = "interestCompoundingPeriodType";
public static final String interestCalculationTypeParamName = "interestCalculationType";
public static final String interestCalculationDaysInYearTypeParamName = "interestCalculationDaysInYearType";
public static final String minRequiredOpeningBalanceParamName = "minRequiredOpeningBalance";
@@ -45,10 +45,9 @@ public class SavingsApiConstants {
public static final String transactionAmountParamName = "transactionAmount";
public static final Set<String> SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
nameParamName, descriptionParamName, currencyCodeParamName, digitsAfterDecimalParamName, interestRateParamName,
interestRatePeriodFrequencyTypeParamName, interestPeriodTypeParamName, interestCalculationTypeParamName,
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName,
lockinPeriodFrequencyTypeParamName));
nameParamName, descriptionParamName, currencyCodeParamName, digitsAfterDecimalParamName, nominalAnnualInterestRateParamName,
interestCompoundingPeriodTypeParamName, interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName,
minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName));
/**
* These parameters will match the class level parameters of
@@ -56,17 +55,16 @@ 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, interestRateParamName,
interestRatePeriodFrequencyTypeParamName, interestPeriodTypeParamName, interestCalculationTypeParamName,
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName,
lockinPeriodFrequencyTypeParamName, "currencyOptions", "interestRatePeriodFrequencyTypeOptions",
"lockinPeriodFrequencyTypeOptions"));
nameParamName, descriptionParamName, "currency", digitsAfterDecimalParamName, nominalAnnualInterestRateParamName,
interestCompoundingPeriodTypeParamName, interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName,
minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName, "currencyOptions",
"interestRatePeriodFrequencyTypeOptions", "lockinPeriodFrequencyTypeOptions"));
public static final Set<String> SAVINGS_ACCOUNT_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
dateFormatParamName, accountNoParamName, externalIdParamName, clientIdParamName, groupIdParamName, productIdParamName,
activeParamName, activationDateParamName, interestRateParamName, interestRatePeriodFrequencyTypeParamName,
interestPeriodTypeParamName, interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName,
minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName));
activeParamName, activationDateParamName, nominalAnnualInterestRateParamName, interestCompoundingPeriodTypeParamName,
interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName,
lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName));
/**
* These parameters will match the class level parameters of
@@ -75,8 +73,8 @@ public class SavingsApiConstants {
*/
public static final Set<String> SAVINGS_ACCOUNT_RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(idParamName,
accountNoParamName, externalIdParamName, statusParamName, activationDateParamName, clientIdParamName, "clientName",
groupIdParamName, "groupName", "savingsProductId", "savingsProductName", "currency", interestRateParamName,
interestRatePeriodFrequencyTypeParamName, "annualInterestRate", interestPeriodTypeParamName, interestCalculationTypeParamName,
groupIdParamName, "groupName", "savingsProductId", "savingsProductName", "currency", nominalAnnualInterestRateParamName,
interestCompoundingPeriodTypeParamName, interestCalculationTypeParamName,
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName,
lockinPeriodFrequencyTypeParamName, "summary", "transactions", "productOptions", "interestRatePeriodFrequencyTypeOptions",
"lockinPeriodFrequencyTypeOptions"));
@@ -5,6 +5,7 @@
*/
package org.mifosplatform.portfolio.savings.api;
import java.util.ArrayList;
import java.util.Collection;
import javax.ws.rs.Consumes;
@@ -31,10 +32,9 @@ import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext
import org.mifosplatform.organisation.monetary.data.CurrencyData;
import org.mifosplatform.organisation.monetary.service.CurrencyReadPlatformService;
import org.mifosplatform.portfolio.savings.data.SavingsProductData;
import org.mifosplatform.portfolio.savings.domain.SavingsCompoundingInterestPeriodType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationDaysInYearType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestPeriodType;
import org.mifosplatform.portfolio.savings.domain.SavingsPeriodFrequencyType;
import org.mifosplatform.portfolio.savings.service.SavingsDropdownReadPlatformService;
import org.mifosplatform.portfolio.savings.service.SavingsEnumerations;
import org.mifosplatform.portfolio.savings.service.SavingsProductReadPlatformService;
@@ -146,22 +146,23 @@ public class SavingsProductsApiResource {
private SavingsProductData handleTemplateRelatedData(final SavingsProductData savingsProduct) {
final EnumOptionData interestRatePeriodFrequencyType = SavingsEnumerations
.interestRatePeriodFrequencyType(SavingsPeriodFrequencyType.YEARS);
final EnumOptionData interestPeriodType = SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.MONTHLY);
final EnumOptionData interestPeriodType = SavingsEnumerations
.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.DAILY);
final EnumOptionData interestCalculationType = SavingsEnumerations
.interestCalculationType(SavingsInterestCalculationType.AVERAGE_DAILY_BALANCE);
.interestCalculationType(SavingsInterestCalculationType.DAILY_BALANCE);
final EnumOptionData interestCalculationDaysInYearType = SavingsEnumerations
.interestCalculationDaysInYearType(SavingsInterestCalculationDaysInYearType.DAYS_365);
CurrencyData currency = CurrencyData.blank();
final Collection<CurrencyData> currencyOptions = this.currencyReadPlatformService.retrieveAllowedCurrencies();
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions = this.dropdownReadPlatformService
.retrieveInterestRatePeriodFrequencyTypeOptions();
if (currencyOptions.size() == 1) {
currency = new ArrayList<CurrencyData>(currencyOptions).get(0);
}
final Collection<EnumOptionData> interestPeriodTypeOptions = this.dropdownReadPlatformService.retrieveInterestPeriodTypeOptions();
final Collection<EnumOptionData> interestPeriodTypeOptions = this.dropdownReadPlatformService
.retrieveCompoundingInterestPeriodTypeOptions();
final Collection<EnumOptionData> interestCalculationTypeOptions = this.dropdownReadPlatformService
.retrieveInterestCalculationTypeOptions();
@@ -174,14 +175,12 @@ public class SavingsProductsApiResource {
SavingsProductData savingsProductToReturn = null;
if (savingsProduct != null) {
savingsProductToReturn = SavingsProductData.withTemplate(savingsProduct, currencyOptions,
interestRatePeriodFrequencyTypeOptions, interestPeriodTypeOptions, interestCalculationTypeOptions,
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions);
savingsProductToReturn = SavingsProductData.withTemplate(savingsProduct, currencyOptions, interestPeriodTypeOptions,
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions);
} else {
savingsProductToReturn = SavingsProductData.template(CurrencyData.blank(), interestRatePeriodFrequencyType, interestPeriodType,
interestCalculationType, interestCalculationDaysInYearType, currencyOptions, interestRatePeriodFrequencyTypeOptions,
interestPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
lockinPeriodFrequencyTypeOptions);
savingsProductToReturn = SavingsProductData.template(currency, interestPeriodType, interestCalculationType,
interestCalculationDaysInYearType, currencyOptions, interestPeriodTypeOptions, interestCalculationTypeOptions,
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions);
}
return savingsProductToReturn;
@@ -30,10 +30,8 @@ public class SavingsAccountData {
private final Long savingsProductId;
private final String savingsProductName;
private final CurrencyData currency;
private final BigDecimal interestRate;
private final EnumOptionData interestRatePeriodFrequencyType;
private final BigDecimal annualInterestRate;
private final EnumOptionData interestPeriodType;
private final BigDecimal nominalAnnualInterestRate;
private final EnumOptionData interestCompoundingPeriodType;
private final EnumOptionData interestCalculationType;
private final EnumOptionData interestCalculationDaysInYearType;
private final BigDecimal minRequiredOpeningBalance;
@@ -46,8 +44,7 @@ public class SavingsAccountData {
// template
private final Collection<SavingsProductData> productOptions;
private final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions;
private final Collection<EnumOptionData> interestPeriodTypeOptions;
private final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions;
private final Collection<EnumOptionData> interestCalculationTypeOptions;
private final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions;
private final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions;
@@ -55,39 +52,37 @@ public class SavingsAccountData {
public static SavingsAccountData instance(final Long id, final String accountNo, final String externalId,
final SavingsAccountStatusEnumData status, final LocalDate activationDate, final Long groupId, final String groupName,
final Long clientId, final String clientName, final Long productId, final String productName, final CurrencyData currency,
final BigDecimal interestRate, final EnumOptionData interestRatePeriodFrequencyType, final BigDecimal annualInterestRate,
final EnumOptionData interestPeriodType, final EnumOptionData interestCalculationType,
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final SavingsAccountSummaryData summary) {
final BigDecimal interestRate, final EnumOptionData interestCompoundingPeriodType,
final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType,
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
final EnumOptionData lockinPeriodFrequencyType, final SavingsAccountSummaryData summary) {
final Collection<SavingsProductData> productOptions = null;
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions = null;
final Collection<EnumOptionData> interestPeriodTypeOptions = null;
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
final Collection<SavingsAccountTransactionData> transactions = null;
return new SavingsAccountData(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName,
productId, productName, currency, interestRate, interestRatePeriodFrequencyType, annualInterestRate, interestPeriodType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType, summary, productOptions, interestRatePeriodFrequencyTypeOptions, interestPeriodTypeOptions,
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, transactions);
productId, productName, currency, interestRate, interestCompoundingPeriodType, interestCalculationType,
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, summary,
productOptions, interestCompoundingPeriodTypeOptions, interestCalculationTypeOptions,
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, transactions);
}
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
final Collection<SavingsProductData> productOptions, final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions,
final Collection<EnumOptionData> interestPeriodTypeOptions, final Collection<EnumOptionData> interestCalculationTypeOptions,
final Collection<SavingsProductData> productOptions, final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
final Collection<EnumOptionData> interestCalculationTypeOptions,
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<SavingsAccountTransactionData> transactions) {
return new SavingsAccountData(account.id, account.accountNo, account.externalId, account.status, account.activationDate,
account.groupId, account.groupName, account.clientId, account.clientName, account.savingsProductId,
account.savingsProductName, account.currency, account.interestRate, account.interestRatePeriodFrequencyType,
account.annualInterestRate, account.interestPeriodType, account.interestCalculationType,
account.interestCalculationDaysInYearType, account.minRequiredOpeningBalance, account.lockinPeriodFrequency,
account.lockinPeriodFrequencyType, account.summary, productOptions, interestRatePeriodFrequencyTypeOptions,
interestPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
account.savingsProductName, account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType,
account.interestCalculationType, account.interestCalculationDaysInYearType, account.minRequiredOpeningBalance,
account.lockinPeriodFrequency, account.lockinPeriodFrequencyType, account.summary, productOptions,
interestCompoundingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
lockinPeriodFrequencyTypeOptions, transactions);
}
@@ -102,9 +97,7 @@ public class SavingsAccountData {
final Long productId = null;
final String productName = null;
final CurrencyData currency = null;
final BigDecimal interestRate = null;
final EnumOptionData interestRatePeriodFrequencyType = null;
final BigDecimal annualInterestRate = null;
final BigDecimal nominalAnnualInterestRate = null;
final EnumOptionData interestPeriodType = null;
final EnumOptionData interestCalculationType = null;
final EnumOptionData interestCalculationDaysInYearType = null;
@@ -114,29 +107,27 @@ public class SavingsAccountData {
final SavingsAccountSummaryData summary = null;
final Collection<SavingsProductData> productOptions = null;
final Collection<CurrencyData> currencyOptions = null;
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions = null;
final Collection<EnumOptionData> interestPeriodTypeOptions = null;
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
final Collection<SavingsAccountTransactionData> transactions = null;
return new SavingsAccountData(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName,
productId, productName, currency, interestRate, interestRatePeriodFrequencyType, annualInterestRate, interestPeriodType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType, summary, productOptions, interestRatePeriodFrequencyTypeOptions, interestPeriodTypeOptions,
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, transactions);
productId, productName, currency, nominalAnnualInterestRate, interestPeriodType, interestCalculationType,
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, summary,
productOptions, interestCompoundingPeriodTypeOptions, interestCalculationTypeOptions,
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, transactions);
}
private SavingsAccountData(final Long id, final String accountNo, final String externalId, final SavingsAccountStatusEnumData status,
final LocalDate activationDate, final Long groupId, final String groupName, final Long clientId, final String clientName,
final Long productId, final String productName, final CurrencyData currency, final BigDecimal interestRate,
final EnumOptionData interestRatePeriodFrequencyType, final BigDecimal annualInterestRate,
final Long productId, final String productName, final CurrencyData currency, final BigDecimal nominalAnnualInterestRate,
final EnumOptionData interestPeriodType, final EnumOptionData interestCalculationType,
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final SavingsAccountSummaryData summary,
final Collection<SavingsProductData> productOptions, final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions,
final Collection<EnumOptionData> interestPeriodTypeOptions, final Collection<EnumOptionData> interestCalculationTypeOptions,
final Collection<SavingsProductData> productOptions, final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
final Collection<EnumOptionData> interestCalculationTypeOptions,
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<SavingsAccountTransactionData> transactions) {
this.id = id;
@@ -151,10 +142,8 @@ public class SavingsAccountData {
this.savingsProductId = productId;
this.savingsProductName = productName;
this.currency = currency;
this.interestRate = interestRate;
this.interestRatePeriodFrequencyType = interestRatePeriodFrequencyType;
this.annualInterestRate = annualInterestRate;
this.interestPeriodType = interestPeriodType;
this.nominalAnnualInterestRate = nominalAnnualInterestRate;
this.interestCompoundingPeriodType = interestPeriodType;
this.interestCalculationType = interestCalculationType;
this.interestCalculationDaysInYearType = interestCalculationDaysInYearType;
this.minRequiredOpeningBalance = minRequiredOpeningBalance;
@@ -163,8 +152,7 @@ public class SavingsAccountData {
this.summary = summary;
this.productOptions = productOptions;
this.interestRatePeriodFrequencyTypeOptions = interestRatePeriodFrequencyTypeOptions;
this.interestPeriodTypeOptions = interestPeriodTypeOptions;
this.interestCompoundingPeriodTypeOptions = interestCompoundingPeriodTypeOptions;
this.interestCalculationTypeOptions = interestCalculationTypeOptions;
this.interestCalculationDaysInYearTypeOptions = interestCalculationDaysInYearTypeOptions;
this.lockinPeriodFrequencyTypeOptions = lockinPeriodFrequencyTypeOptions;
@@ -8,12 +8,11 @@ import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.extern
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.groupIdParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestPeriodTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestRateParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestRatePeriodFrequencyTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.productIdParamName;
import java.lang.reflect.Type;
@@ -94,20 +93,13 @@ public class SavingsAccountDataValidator {
baseDataValidator.reset().parameter(externalIdParamName).value(externalId).notExceedingLengthOf(100);
}
if (fromApiJsonHelper.parameterExists(interestRateParamName, element)) {
final BigDecimal interestRate = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(interestRateParamName, element);
baseDataValidator.reset().parameter(interestRateParamName).value(interestRate).notNull().zeroOrPositiveAmount();
if (fromApiJsonHelper.parameterExists(nominalAnnualInterestRateParamName, element)) {
final BigDecimal interestRate = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(nominalAnnualInterestRateParamName, element);
baseDataValidator.reset().parameter(nominalAnnualInterestRateParamName).value(interestRate).notNull().zeroOrPositiveAmount();
}
if (fromApiJsonHelper.parameterExists(interestRatePeriodFrequencyTypeParamName, element)) {
final Integer interestRatePeriodFrequencyType = fromApiJsonHelper.extractIntegerSansLocaleNamed(
interestRatePeriodFrequencyTypeParamName, element);
baseDataValidator.reset().parameter(interestRatePeriodFrequencyTypeParamName).value(interestRatePeriodFrequencyType).notNull()
.inMinMaxRange(1, 3);
}
final Integer interestPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(interestPeriodTypeParamName, element);
baseDataValidator.reset().parameter(interestPeriodTypeParamName).value(interestPeriodType).notNull().inMinMaxRange(1, 7);
final Integer interestPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(interestCompoundingPeriodTypeParamName, element);
baseDataValidator.reset().parameter(interestCompoundingPeriodTypeParamName).value(interestPeriodType).notNull().inMinMaxRange(1, 7);
final Integer interestCalculationType = fromApiJsonHelper.extractIntegerSansLocaleNamed(interestCalculationTypeParamName, element);
baseDataValidator.reset().parameter(interestCalculationTypeParamName).value(interestCalculationType).notNull().inMinMaxRange(1, 2);
@@ -215,21 +207,14 @@ public class SavingsAccountDataValidator {
baseDataValidator.reset().parameter(externalIdParamName).value(externalId).notExceedingLengthOf(100);
}
if (fromApiJsonHelper.parameterExists(interestRateParamName, element)) {
final BigDecimal interestRate = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(interestRateParamName, element);
baseDataValidator.reset().parameter(interestRateParamName).value(interestRate).notNull().zeroOrPositiveAmount();
if (fromApiJsonHelper.parameterExists(nominalAnnualInterestRateParamName, element)) {
final BigDecimal interestRate = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(nominalAnnualInterestRateParamName, element);
baseDataValidator.reset().parameter(nominalAnnualInterestRateParamName).value(interestRate).notNull().zeroOrPositiveAmount();
}
if (fromApiJsonHelper.parameterExists(interestRatePeriodFrequencyTypeParamName, element)) {
final Integer interestRatePeriodFrequencyType = fromApiJsonHelper.extractIntegerSansLocaleNamed(
interestRatePeriodFrequencyTypeParamName, element);
baseDataValidator.reset().parameter(interestRatePeriodFrequencyTypeParamName).value(interestRatePeriodFrequencyType).notNull()
.inMinMaxRange(1, 3);
}
if (this.fromApiJsonHelper.parameterExists(interestPeriodTypeParamName, element)) {
final Integer interestPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(interestPeriodTypeParamName, element);
baseDataValidator.reset().parameter(interestPeriodTypeParamName).value(interestPeriodType).notNull().inMinMaxRange(1, 7);
if (this.fromApiJsonHelper.parameterExists(interestCompoundingPeriodTypeParamName, element)) {
final Integer interestPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(interestCompoundingPeriodTypeParamName, element);
baseDataValidator.reset().parameter(interestCompoundingPeriodTypeParamName).value(interestPeriodType).notNull().inMinMaxRange(1, 7);
}
if (this.fromApiJsonHelper.parameterExists(interestCalculationTypeParamName, element)) {
@@ -20,9 +20,8 @@ public class SavingsProductData {
private final String name;
private final String description;
private final CurrencyData currency;
private final BigDecimal interestRate;
private final EnumOptionData interestRatePeriodFrequencyType;
private final EnumOptionData interestPeriodType;
private final BigDecimal nominalAnnualInterestRate;
private final EnumOptionData interestCompoundingPeriodType;
private final EnumOptionData interestCalculationType;
private final EnumOptionData interestCalculationDaysInYearType;
private final BigDecimal minRequiredOpeningBalance;
@@ -33,9 +32,7 @@ public class SavingsProductData {
@SuppressWarnings("unused")
private final Collection<CurrencyData> currencyOptions;
@SuppressWarnings("unused")
private final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions;
@SuppressWarnings("unused")
private final Collection<EnumOptionData> interestPeriodTypeOptions;
private final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions;
@SuppressWarnings("unused")
private final Collection<EnumOptionData> interestCalculationTypeOptions;
@SuppressWarnings("unused")
@@ -43,26 +40,25 @@ public class SavingsProductData {
@SuppressWarnings("unused")
private final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions;
public static SavingsProductData template(final CurrencyData currency, final EnumOptionData interestRatePeriodFrequencyType,
final EnumOptionData interestPeriodType, final EnumOptionData interestCalculationType,
final EnumOptionData interestCalculationDaysInYearType, final Collection<CurrencyData> currencyOptions,
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions,
final Collection<EnumOptionData> interestPeriodTypeOptions, final Collection<EnumOptionData> interestCalculationTypeOptions,
public static SavingsProductData template(final CurrencyData currency, final EnumOptionData interestCompoundingPeriodType,
final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType,
final Collection<CurrencyData> currencyOptions, final Collection<EnumOptionData> interestPeriodTypeOptions,
final Collection<EnumOptionData> interestCalculationTypeOptions,
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions) {
final Long id = null;
final String name = null;
final String description = null;
final BigDecimal interestRate = null;
final BigDecimal nominalAnnualInterestRate = null;
final BigDecimal minRequiredOpeningBalance = null;
final Integer lockinPeriodFrequency = null;
final EnumOptionData lockinPeriodFrequencyType = null;
return new SavingsProductData(id, name, description, currency, interestRate, interestRatePeriodFrequencyType, interestPeriodType,
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType, currencyOptions, interestRatePeriodFrequencyTypeOptions, interestPeriodTypeOptions,
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions);
lockinPeriodFrequencyType, currencyOptions, interestPeriodTypeOptions, interestCalculationTypeOptions,
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions);
}
/**
@@ -70,45 +66,41 @@ public class SavingsProductData {
* {@link SavingsProductData} data with further template data for dropdowns.
*/
public static SavingsProductData withTemplate(final SavingsProductData existingProduct, final Collection<CurrencyData> currencyOptions,
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions,
final Collection<EnumOptionData> interestPeriodTypeOptions, final Collection<EnumOptionData> interestCalculationTypeOptions,
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions) {
return new SavingsProductData(existingProduct.id, existingProduct.name, existingProduct.description, existingProduct.currency,
existingProduct.interestRate, existingProduct.interestRatePeriodFrequencyType, existingProduct.interestPeriodType,
existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType,
existingProduct.interestCalculationType, existingProduct.interestCalculationDaysInYearType,
existingProduct.minRequiredOpeningBalance, existingProduct.lockinPeriodFrequency,
existingProduct.lockinPeriodFrequencyType, currencyOptions, interestRatePeriodFrequencyTypeOptions,
interestPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
lockinPeriodFrequencyTypeOptions);
existingProduct.lockinPeriodFrequencyType, currencyOptions, interestPeriodTypeOptions, interestCalculationTypeOptions,
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions);
}
public static SavingsProductData instance(final Long id, final String name, final String description, final CurrencyData currency,
final BigDecimal interestRate, final EnumOptionData interestRatePeriodFrequencyType, final EnumOptionData interestPeriodType,
final BigDecimal nominalAnnualInterestRate, final EnumOptionData interestCompoundingPeriodType,
final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType,
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType) {
final Collection<CurrencyData> currencyOptions = null;
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions = null;
final Collection<EnumOptionData> interestPeriodTypeOptions = null;
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
return new SavingsProductData(id, name, description, currency, interestRate, interestRatePeriodFrequencyType, interestPeriodType,
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType, currencyOptions, interestRatePeriodFrequencyTypeOptions, interestPeriodTypeOptions,
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions);
lockinPeriodFrequencyType, currencyOptions, interestPeriodTypeOptions, interestCalculationTypeOptions,
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions);
}
public static SavingsProductData lookup(final Long id, final String name) {
final CurrencyData currency = null;
final String description = null;
final BigDecimal interestRate = null;
final EnumOptionData interestRatePeriodFrequencyType = null;
final EnumOptionData interestPeriodType = null;
final BigDecimal nominalAnnualInterestRate = null;
final EnumOptionData interestCompoundingPeriodType = null;
final EnumOptionData interestCalculationType = null;
final EnumOptionData interestCalculationDaysInYearType = null;
final BigDecimal minRequiredOpeningBalance = null;
@@ -116,24 +108,22 @@ public class SavingsProductData {
final EnumOptionData lockinPeriodFrequencyType = null;
final Collection<CurrencyData> currencyOptions = null;
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions = null;
final Collection<EnumOptionData> interestPeriodTypeOptions = null;
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
return new SavingsProductData(id, name, description, currency, interestRate, interestRatePeriodFrequencyType, interestPeriodType,
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType, currencyOptions, interestRatePeriodFrequencyTypeOptions, interestPeriodTypeOptions,
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions);
lockinPeriodFrequencyType, currencyOptions, interestPeriodTypeOptions, interestCalculationTypeOptions,
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions);
}
private SavingsProductData(final Long id, final String name, final String description, final CurrencyData currency,
final BigDecimal interestRate, final EnumOptionData interestRatePeriodFrequencyType, final EnumOptionData interestPeriodType,
final BigDecimal nominalAnnualInterestRate, final EnumOptionData interestCompoundingPeriodType,
final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType,
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
final EnumOptionData lockinPeriodFrequencyType, final Collection<CurrencyData> currencyOptions,
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions,
final Collection<EnumOptionData> interestPeriodTypeOptions, final Collection<EnumOptionData> interestCalculationTypeOptions,
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions) {
@@ -141,9 +131,8 @@ public class SavingsProductData {
this.name = name;
this.description = description;
this.currency = currency;
this.interestRate = interestRate;
this.interestRatePeriodFrequencyType = interestRatePeriodFrequencyType;
this.interestPeriodType = interestPeriodType;
this.nominalAnnualInterestRate = nominalAnnualInterestRate;
this.interestCompoundingPeriodType = interestCompoundingPeriodType;
this.interestCalculationType = interestCalculationType;
this.interestCalculationDaysInYearType = interestCalculationDaysInYearType;
this.minRequiredOpeningBalance = minRequiredOpeningBalance;
@@ -151,8 +140,7 @@ public class SavingsProductData {
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType;
this.currencyOptions = currencyOptions;
this.interestRatePeriodFrequencyTypeOptions = interestRatePeriodFrequencyTypeOptions;
this.interestPeriodTypeOptions = interestPeriodTypeOptions;
this.interestCompoundingPeriodTypeOptions = interestPeriodTypeOptions;
this.interestCalculationTypeOptions = interestCalculationTypeOptions;
this.interestCalculationDaysInYearTypeOptions = interestCalculationDaysInYearTypeOptions;
this.lockinPeriodFrequencyTypeOptions = lockinPeriodFrequencyTypeOptions;
@@ -7,13 +7,12 @@ import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.descri
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.digitsAfterDecimalParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestPeriodTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestRateParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestRatePeriodFrequencyTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nameParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
import java.lang.reflect.Type;
import java.math.BigDecimal;
@@ -67,16 +66,13 @@ public class SavingsProductDataValidator {
final Integer digitsAfterDecimal = fromApiJsonHelper.extractIntegerSansLocaleNamed(digitsAfterDecimalParamName, element);
baseDataValidator.reset().parameter(digitsAfterDecimalParamName).value(digitsAfterDecimal).notNull().inMinMaxRange(0, 6);
final BigDecimal interestRate = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(interestRateParamName, element);
baseDataValidator.reset().parameter(interestRateParamName).value(interestRate).notNull().zeroOrPositiveAmount();
final BigDecimal interestRate = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(nominalAnnualInterestRateParamName, element);
baseDataValidator.reset().parameter(nominalAnnualInterestRateParamName).value(interestRate).notNull().zeroOrPositiveAmount();
final Integer interestRatePeriodFrequencyType = fromApiJsonHelper.extractIntegerSansLocaleNamed(
interestRatePeriodFrequencyTypeParamName, element);
baseDataValidator.reset().parameter(interestRatePeriodFrequencyTypeParamName).value(interestRatePeriodFrequencyType).notNull()
.inMinMaxRange(1, 3);
final Integer interestPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(interestPeriodTypeParamName, element);
baseDataValidator.reset().parameter(interestPeriodTypeParamName).value(interestPeriodType).notNull().inMinMaxRange(1, 7);
final Integer interestCompoundingPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(
interestCompoundingPeriodTypeParamName, element);
baseDataValidator.reset().parameter(interestCompoundingPeriodTypeParamName).value(interestCompoundingPeriodType).notNull()
.inMinMaxRange(1, 8);
final Integer interestCalculationType = fromApiJsonHelper.extractIntegerSansLocaleNamed(interestCalculationTypeParamName, element);
baseDataValidator.reset().parameter(interestCalculationTypeParamName).value(interestCalculationType).notNull().inMinMaxRange(1, 2);
@@ -153,21 +149,16 @@ public class SavingsProductDataValidator {
baseDataValidator.reset().parameter(digitsAfterDecimalParamName).value(digitsAfterDecimal).notNull().inMinMaxRange(0, 6);
}
if (this.fromApiJsonHelper.parameterExists(interestRateParamName, element)) {
final BigDecimal interestRate = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(interestRateParamName, element);
baseDataValidator.reset().parameter(interestRateParamName).value(interestRate).notNull().zeroOrPositiveAmount();
if (this.fromApiJsonHelper.parameterExists(nominalAnnualInterestRateParamName, element)) {
final BigDecimal interestRate = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(nominalAnnualInterestRateParamName, element);
baseDataValidator.reset().parameter(nominalAnnualInterestRateParamName).value(interestRate).notNull().zeroOrPositiveAmount();
}
if (this.fromApiJsonHelper.parameterExists(interestRatePeriodFrequencyTypeParamName, element)) {
final Integer interestRatePeriodFrequencyType = fromApiJsonHelper.extractIntegerSansLocaleNamed(
interestRatePeriodFrequencyTypeParamName, element);
baseDataValidator.reset().parameter(interestRatePeriodFrequencyTypeParamName).value(interestRatePeriodFrequencyType).notNull()
.inMinMaxRange(1, 3);
}
if (this.fromApiJsonHelper.parameterExists(interestPeriodTypeParamName, element)) {
final Integer interestPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(interestPeriodTypeParamName, element);
baseDataValidator.reset().parameter(interestPeriodTypeParamName).value(interestPeriodType).notNull().inMinMaxRange(1, 7);
if (this.fromApiJsonHelper.parameterExists(interestCompoundingPeriodTypeParamName, element)) {
final Integer interestCompoundingPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(
interestCompoundingPeriodTypeParamName, element);
baseDataValidator.reset().parameter(interestCompoundingPeriodTypeParamName).value(interestCompoundingPeriodType).notNull()
.inMinMaxRange(1, 8);
}
if (this.fromApiJsonHelper.parameterExists(interestCalculationTypeParamName, element)) {
@@ -201,7 +192,10 @@ public class SavingsProductDataValidator {
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
if (!dataValidationErrors.isEmpty()) {
//
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
dataValidationErrors);
}
}
}
@@ -0,0 +1,53 @@
package org.mifosplatform.portfolio.savings.domain;
import java.math.BigDecimal;
import java.math.MathContext;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
public class InterestCompoundingPeriodSummary {
@SuppressWarnings("unused")
private final LocalDateInterval periodInterval;
@SuppressWarnings("unused")
private final BigDecimal openingBalance;
private final BigDecimal closingBalance;
private final BigDecimal interestEarnedUnrounded;
private final BigDecimal cumulativeCompoundedInterestToDate;
public static InterestCompoundingPeriodSummary create(final LocalDateInterval periodInterval, final BigDecimal openingBalance,
final BigDecimal closingBalance, final BigDecimal interestEarnedUnrounded, final BigDecimal cumulativeCompoundedInterestToDate) {
return new InterestCompoundingPeriodSummary(periodInterval, openingBalance, closingBalance, interestEarnedUnrounded,
cumulativeCompoundedInterestToDate);
}
public InterestCompoundingPeriodSummary(final LocalDateInterval periodInterval, final BigDecimal openingBalance,
final BigDecimal closingBalance, final BigDecimal interestEarnedUnrounded, final BigDecimal cumulativeCompoundedInterestToDate) {
this.periodInterval = periodInterval;
this.openingBalance = openingBalance;
this.closingBalance = closingBalance;
this.interestEarnedUnrounded = interestEarnedUnrounded;
this.cumulativeCompoundedInterestToDate = cumulativeCompoundedInterestToDate;
}
public Money closingBalance(final MonetaryCurrency currency) {
return Money.of(currency, this.closingBalance);
}
public BigDecimal closingBalance() {
return this.closingBalance;
}
public BigDecimal closingBalanceWithUnroundedInterest(final MathContext mc) {
return this.closingBalance.add(interestEarnedUnrounded, mc);
}
public BigDecimal compoundedInterest() {
return cumulativeCompoundedInterestToDate;
}
public BigDecimal interestUnrounded() {
return this.interestEarnedUnrounded;
}
}
@@ -1,61 +0,0 @@
package org.mifosplatform.portfolio.savings.domain;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
public class InterestPeriodSummary {
@SuppressWarnings("unused")
private final Date startDate;
@SuppressWarnings("unused")
private final Date endDate;
@SuppressWarnings("unused")
private final Integer numberOfDays;
@SuppressWarnings("unused")
private final BigDecimal startingBalance;
private final BigDecimal closingBalance;
private final BigDecimal interestEarnedUnrounded;
private final BigDecimal interestEarned;
@SuppressWarnings("unused")
private final List<SavingsAccountDailyBalance> dailyBalances;
public static InterestPeriodSummary from(final InterestPeriodInterval interestPeriodInterval, final Money startingBalance,
final List<SavingsAccountDailyBalance> dailyBalances, final BigDecimal totalInterestEarnedUnrounded) {
return new InterestPeriodSummary(interestPeriodInterval, startingBalance, dailyBalances, totalInterestEarnedUnrounded);
}
private InterestPeriodSummary(final InterestPeriodInterval interestPeriodInterval, final Money startingBalance,
final List<SavingsAccountDailyBalance> dailyBalances, final BigDecimal totalInterestEarnedUnrounded) {
this.startDate = interestPeriodInterval.startDate().toDate();
this.endDate = interestPeriodInterval.endDate().toDate();
this.numberOfDays = interestPeriodInterval.daysInPeriodInclusiveOfEndDate();
this.startingBalance = startingBalance.getAmount();
final MonetaryCurrency currency = startingBalance.getCurrency();
this.interestEarnedUnrounded = totalInterestEarnedUnrounded;
this.interestEarned = Money.of(currency, this.interestEarnedUnrounded).getAmount();
Money closingBalanceForPeriod = startingBalance.copy();
for (SavingsAccountDailyBalance balance : dailyBalances) {
closingBalanceForPeriod = balance.dailyRunningBalance(currency);
}
this.closingBalance = closingBalanceForPeriod.getAmount();
this.dailyBalances = dailyBalances;
}
public Money closingBalance(final MonetaryCurrency currency) {
return Money.of(currency, this.closingBalance);
}
public BigDecimal interest() {
return this.interestEarned;
}
}
@@ -3,16 +3,16 @@ package org.mifosplatform.portfolio.savings.domain;
import org.joda.time.Days;
import org.joda.time.LocalDate;
public class InterestPeriodInterval {
public class LocalDateInterval {
private final LocalDate startDate;
private final LocalDate endDate;
public static InterestPeriodInterval create(final LocalDate startDate, final LocalDate endDate) {
return new InterestPeriodInterval(startDate, endDate);
public static LocalDateInterval create(final LocalDate startDate, final LocalDate endDate) {
return new LocalDateInterval(startDate, endDate);
}
public InterestPeriodInterval(final LocalDate startDate, final LocalDate endDate) {
public LocalDateInterval(final LocalDate startDate, final LocalDate endDate) {
this.startDate = startDate;
this.endDate = endDate;
}
@@ -81,20 +81,18 @@ public class SavingsAccount extends AbstractPersistable<Long> {
@Embedded
private MonetaryCurrency currency;
@Column(name = "nominal_interest_rate_per_period", scale = 6, precision = 19, nullable = false)
private BigDecimal interestRate;
@Column(name = "nominal_interest_rate_period_frequency_enum", nullable = false)
private Integer interestRatePeriodFrequencyType;
@Column(name = "nominal_annual_interest_rate", scale = 6, precision = 19, nullable = false)
private BigDecimal nominalAnnualInterestRate;
/**
* The interest period is the span of time at the end of which savings in a
* client’s account earn interest.
*
* A value from the {@link SavingsInterestPeriodType} enumeration.
* A value from the {@link SavingsCompoundingInterestPeriodType}
* enumeration.
*/
@Column(name = "interest_period_enum", nullable = false)
private Integer interestPeriodType;
@Column(name = "interest_compounding_period_enum", nullable = false)
private Integer interestCompoundingPeriodType;
/**
* A value from the {@link SavingsInterestCalculationType} enumeration.
@@ -109,9 +107,6 @@ public class SavingsAccount extends AbstractPersistable<Long> {
@Column(name = "interest_calculation_days_in_year_type_enum", nullable = false)
private Integer interestCalculationDaysInYearType;
@Column(name = "annual_nominal_interest_rate", scale = 6, precision = 19, nullable = false)
private BigDecimal annualInterestRate;
@Column(name = "min_required_opening_balance", scale = 6, precision = 19, nullable = false)
private BigDecimal minRequiredOpeningBalance;
@@ -149,24 +144,22 @@ public class SavingsAccount extends AbstractPersistable<Long> {
public static SavingsAccount createNewAccount(final Client client, final Group group, final SavingsProduct product,
final String accountNo, final String externalId, final BigDecimal interestRate,
final PeriodFrequencyType interestRatePeriodFrequencyType, final BigDecimal annualInterestRate,
final SavingsInterestPeriodType interestPeriodType, final SavingsInterestCalculationType interestCalculationType,
final SavingsCompoundingInterestPeriodType interestPeriodType, final SavingsInterestCalculationType interestCalculationType,
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
final Integer lockinPeriodFrequency, final PeriodFrequencyType lockinPeriodFrequencyType) {
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType) {
final SavingsAccountStatusType status = SavingsAccountStatusType.UNACTIVATED;
final LocalDate activationDate = null;
return new SavingsAccount(client, group, product, accountNo, externalId, status, activationDate, interestRate,
interestRatePeriodFrequencyType, annualInterestRate, interestPeriodType, interestCalculationType,
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType);
return new SavingsAccount(client, group, product, accountNo, externalId, status, activationDate, interestRate, interestPeriodType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType);
}
private SavingsAccount(final Client client, final Group group, final SavingsProduct product, final String accountNo,
final String externalId, final SavingsAccountStatusType status, final LocalDate activationDate, final BigDecimal interestRate,
final PeriodFrequencyType interestRatePeriodFrequencyType, final BigDecimal annualInterestRate,
final SavingsInterestPeriodType interestPeriodType, final SavingsInterestCalculationType interestCalculationType,
final SavingsCompoundingInterestPeriodType interestPeriodType, final SavingsInterestCalculationType interestCalculationType,
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
final Integer lockinPeriodFrequency, final PeriodFrequencyType lockinPeriodFrequencyType) {
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType) {
this.client = client;
this.group = group;
this.product = product;
@@ -182,10 +175,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
if (activationDate != null) {
this.activationDate = activationDate.toDate();
}
this.interestRate = interestRate;
this.interestRatePeriodFrequencyType = interestRatePeriodFrequencyType.getValue();
this.annualInterestRate = annualInterestRate;
this.interestPeriodType = interestPeriodType.getValue();
this.nominalAnnualInterestRate = interestRate;
this.interestCompoundingPeriodType = interestPeriodType.getValue();
this.interestCalculationType = interestCalculationType.getValue();
this.interestCalculationDaysInYearType = interestCalculationDaysInYearType.getValue();
this.minRequiredOpeningBalance = minRequiredOpeningBalance;
@@ -281,47 +272,112 @@ public class SavingsAccount extends AbstractPersistable<Long> {
* Interest calculation is performed on-the-fly over all account
* transactions.
*/
/*
* The daily balance method is the application of a daily interest rate to
* the full amount of principal in the account each day. For the days the
* account is overdrawn, a zero balance is used to calculate the interest
* for those days.
*/
public void calculateInterest() {
public void calculateInterest(final LocalDate interestCalculationEndDate) {
// no openingBalance concept supported yet but probably will to all for
// migrations.
// no openingBalance concept supported yet but probably will to allow
// for migrations.
final Money openingAccountBalance = Money.zero(this.currency);
// 1. update existing transactions so derived balance fields are
// update existing transactions so derived balance fields are
// correct.
recalculateDailyBalances(openingAccountBalance);
// 2. determine interest periods
final SavingsInterestPeriodType interestPeriodType = SavingsInterestPeriodType.fromInt(this.interestPeriodType);
final SavingsInterestCalculationDaysInYearType daysInYearType = SavingsInterestCalculationDaysInYearType
.fromInt(this.interestCalculationDaysInYearType);
final List<InterestPeriodInterval> interestPeriods = determineInterestPeriods(getActivationLocalDate(), interestPeriodType);
final SavingsCompoundingInterestPeriodType compoundingPeriodType = SavingsCompoundingInterestPeriodType
.fromInt(this.interestCompoundingPeriodType);
final List<LocalDateInterval> interestCompoundingPeriods = determineInterestCompoundingPeriods(getActivationLocalDate(),
interestCalculationEndDate, compoundingPeriodType);
final List<InterestPeriodSummary> interestPeriodSummaries = deriveInterestPeriodSummaries(openingAccountBalance, interestPeriods,
this.annualInterestRate, daysInYearType);
// determine opening balance, daily interest rate to apply, interest
// due, interest to compound for each period
final List<InterestCompoundingPeriodSummary> compoundingPeriods = determineInterestCompoundingPeriodSummaries(
openingAccountBalance, this.nominalAnnualInterestRate, daysInYearType, interestCompoundingPeriods);
this.summary.updateFromInterestPeriodSummaries(currency, interestPeriodSummaries);
this.summary.updateFromInterestPeriodSummaries(currency, compoundingPeriods);
}
private List<InterestPeriodInterval> determineInterestPeriods(final LocalDate activationLocalDate,
final SavingsInterestPeriodType interestPeriodType) {
private List<InterestCompoundingPeriodSummary> determineInterestCompoundingPeriodSummaries(final Money openingAccountBalance,
final BigDecimal annualInterestRate, final SavingsInterestCalculationDaysInYearType daysInYearType,
final List<LocalDateInterval> interestCompoundingPeriods) {
LocalDate today = DateUtils.getLocalDateOfTenant();
List<InterestCompoundingPeriodSummary> summaries = new ArrayList<InterestCompoundingPeriodSummary>();
final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN);
final BigDecimal percentageDivisor = BigDecimal.valueOf(100l);
final BigDecimal periodsInOneYear = determinePeriodsInOneYear(daysInYearType);
final BigDecimal periodsInOneYearAsFraction = BigDecimal.ONE.divide(periodsInOneYear, mc);
final BigDecimal annualInterestRateAsFraction = annualInterestRate.divide(percentageDivisor, mc);
final SavingsInterestCalculationType interestCalculationType = SavingsInterestCalculationType.fromInt(this.interestCalculationType);
final SavingsInterestCalculatorFactory interestCalculatorFactory = new SavingsInterestCalculatorFactory();
final SavingsCompoundInterestCalculator interestCalculator = interestCalculatorFactory.createFrom(interestCalculationType,
periodsInOneYearAsFraction, annualInterestRateAsFraction);
BigDecimal periodOpeningBalance = openingAccountBalance.copy().getAmount();
BigDecimal compoundedInterestToDate = BigDecimal.ZERO;
for (LocalDateInterval periodInterval : interestCompoundingPeriods) {
InterestCompoundingPeriodSummary compoundingSummary = calculateInterestCompoundingPeriodSummary(periodInterval,
periodOpeningBalance, compoundedInterestToDate, interestCalculator);
periodOpeningBalance = compoundingSummary.closingBalance();
compoundedInterestToDate = compoundingSummary.compoundedInterest();
summaries.add(compoundingSummary);
}
return summaries;
}
private InterestCompoundingPeriodSummary calculateInterestCompoundingPeriodSummary(final LocalDateInterval periodInterval,
final BigDecimal periodOpeningBalance, final BigDecimal compoundedInterestToDate,
final SavingsCompoundInterestCalculator interestCalculator) {
BigDecimal periodClosingBalance = periodOpeningBalance;
List<SavingsAccountDailyBalance> dailyBalances = new ArrayList<SavingsAccountDailyBalance>();
for (SavingsAccountTransaction transaction : this.transactions) {
if (transaction.isAcceptableForDailyBalance(periodInterval)) {
SavingsAccountDailyBalance dailyBalance = transaction.toCompoundedDailyBalance(periodInterval.endDate(),
compoundedInterestToDate);
dailyBalances.add(dailyBalance);
periodClosingBalance = dailyBalance.endOfDayBalance();
}
}
if (dailyBalances.isEmpty()) {
SavingsAccountDailyBalance dailyBalance = SavingsAccountDailyBalance.createFrom(periodInterval, periodOpeningBalance,
compoundedInterestToDate);
dailyBalances.add(dailyBalance);
}
final BigDecimal totalInterestEarnedUnrounded = interestCalculator.calculate(dailyBalances,
periodInterval.daysInPeriodInclusiveOfEndDate());
final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN);
final BigDecimal cumulativeCompoundedInterestToDate = compoundedInterestToDate.add(totalInterestEarnedUnrounded, mc);
return InterestCompoundingPeriodSummary.create(periodInterval, periodOpeningBalance, periodClosingBalance,
totalInterestEarnedUnrounded, cumulativeCompoundedInterestToDate);
}
private List<LocalDateInterval> determineInterestCompoundingPeriods(final LocalDate activationLocalDate,
final LocalDate interestCalculationEndDate, final SavingsCompoundingInterestPeriodType interestPeriodType) {
LocalDate periodStartDate = activationLocalDate;
LocalDate periodEndDate = periodStartDate;
final List<InterestPeriodInterval> interestPeriods = new ArrayList<InterestPeriodInterval>();
final List<LocalDateInterval> interestPeriods = new ArrayList<LocalDateInterval>();
while (!periodStartDate.isAfter(today) && !periodEndDate.isAfter(today)) {
while (!periodStartDate.isAfter(interestCalculationEndDate) && !periodEndDate.isAfter(interestCalculationEndDate)) {
periodEndDate = determineInterestPeriodEndDateFrom(periodStartDate, interestPeriodType);
interestPeriods.add(InterestPeriodInterval.create(periodStartDate, periodEndDate));
if (periodEndDate.isAfter(interestCalculationEndDate)) {
periodEndDate = interestCalculationEndDate;
}
interestPeriods.add(LocalDateInterval.create(periodStartDate, periodEndDate));
// move periodStartDate forward to day after this period
periodStartDate = periodEndDate.plusDays(1);
@@ -330,7 +386,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
return interestPeriods;
}
private LocalDate determineInterestPeriodEndDateFrom(final LocalDate periodStartDate, final SavingsInterestPeriodType interestPeriodType) {
private LocalDate determineInterestPeriodEndDateFrom(final LocalDate periodStartDate,
final SavingsCompoundingInterestPeriodType interestPeriodType) {
LocalDate periodEndDate = DateUtils.getLocalDateOfTenant();
@@ -366,7 +423,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
periodEndDate = new DateTime().withDate(year, 12, 31).toLocalDate();
}
break;
case SEMIANNUAL:
case BI_ANNUAL:
// jan 1st to 30, jul 1st to dec 31
year = periodStartDate.getYearOfEra();
monthofYear = periodStartDate.getMonthOfYear();
@@ -380,6 +437,10 @@ public class SavingsAccount extends AbstractPersistable<Long> {
periodEndDate = periodStartDate.monthOfYear().withMaximumValue();
periodEndDate = periodStartDate.dayOfMonth().withMaximumValue();
break;
case NO_COMPOUNDING_SIMPLE_INTEREST:
periodEndDate = periodStartDate.monthOfYear().withMaximumValue();
periodEndDate = periodStartDate.dayOfMonth().withMaximumValue();
break;
}
return periodEndDate;
@@ -403,62 +464,6 @@ public class SavingsAccount extends AbstractPersistable<Long> {
return periodsInOneYear;
}
private List<InterestPeriodSummary> deriveInterestPeriodSummaries(final Money openingAccountBalance,
final List<InterestPeriodInterval> interestPeriods, final BigDecimal annualInterestRate,
final SavingsInterestCalculationDaysInYearType daysInYearType) {
final List<InterestPeriodSummary> summaries = new ArrayList<InterestPeriodSummary>();
final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN);
final BigDecimal percentageDivisor = BigDecimal.valueOf(100l);
final BigDecimal periodsInOneYear = determinePeriodsInOneYear(daysInYearType);
final BigDecimal periodsInOneYearAsFraction = BigDecimal.ONE.divide(periodsInOneYear, mc);
final BigDecimal annualInterestRateAsFraction = annualInterestRate.divide(percentageDivisor, mc);
final SavingsInterestCalculationType interestCalculationType = SavingsInterestCalculationType.fromInt(this.interestCalculationType);
final SavingsInterestCalculatorFactory interestCalculatorFactory = new SavingsInterestCalculatorFactory();
final SavingsInterestCalculator interestCalculator = interestCalculatorFactory.createFrom(interestCalculationType,
periodsInOneYearAsFraction, annualInterestRateAsFraction);
Money periodOpeningBalance = openingAccountBalance.copy();
for (InterestPeriodInterval interestPeriodInterval : interestPeriods) {
InterestPeriodSummary interestPeriodSummary = calculateInterestPeriodSummaryFor(interestPeriodInterval, periodOpeningBalance,
interestCalculator);
periodOpeningBalance = interestPeriodSummary.closingBalance(this.currency);
summaries.add(interestPeriodSummary);
}
return summaries;
}
private InterestPeriodSummary calculateInterestPeriodSummaryFor(final InterestPeriodInterval interestPeriodInterval,
final Money startingBalanceForPeriod, final SavingsInterestCalculator interestCalculator) {
List<SavingsAccountDailyBalance> dailyBalances = new ArrayList<SavingsAccountDailyBalance>();
for (SavingsAccountTransaction transaction : this.transactions) {
if (transaction.isAcceptableForDailyBalance(interestPeriodInterval)) {
SavingsAccountDailyBalance dailyBalance = transaction.toDailyBalance(interestPeriodInterval.endDate());
dailyBalances.add(dailyBalance);
}
}
if (dailyBalances.isEmpty()) {
SavingsAccountDailyBalance dailyBalance = SavingsAccountDailyBalance.createFrom(interestPeriodInterval,
startingBalanceForPeriod.getAmount());
dailyBalances.add(dailyBalance);
}
final BigDecimal totalInterestEarnedUnrounded = interestCalculator.calculate(dailyBalances,
interestPeriodInterval.daysInPeriodInclusiveOfEndDate());
return InterestPeriodSummary.from(interestPeriodInterval, startingBalanceForPeriod, dailyBalances, totalInterestEarnedUnrounded);
}
private void recalculateDailyBalances(final Money openingAccountBalance) {
Money runningBalance = openingAccountBalance.copy();
@@ -537,7 +542,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
calculateInterest();
final LocalDate today = DateUtils.getLocalDateOfTenant();
calculateInterest(today);
return transaction;
}
@@ -614,7 +620,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
calculateInterest();
final LocalDate today = DateUtils.getLocalDateOfTenant();
calculateInterest(today);
return transaction;
}
@@ -683,18 +690,12 @@ public class SavingsAccount extends AbstractPersistable<Long> {
actualChanges.put(SavingsApiConstants.productIdParamName, newValue);
}
if (command.isChangeInBigDecimalParameterNamed(SavingsApiConstants.interestRateParamName, this.interestRate)) {
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(SavingsApiConstants.interestRateParamName);
actualChanges.put(SavingsApiConstants.interestRateParamName, newValue);
if (command.isChangeInBigDecimalParameterNamed(SavingsApiConstants.nominalAnnualInterestRateParamName,
this.nominalAnnualInterestRate)) {
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(SavingsApiConstants.nominalAnnualInterestRateParamName);
actualChanges.put(SavingsApiConstants.nominalAnnualInterestRateParamName, newValue);
actualChanges.put("locale", localeAsInput);
this.interestRate = newValue;
}
if (command.isChangeInIntegerParameterNamed(SavingsApiConstants.interestRatePeriodFrequencyTypeParamName,
this.interestRatePeriodFrequencyType)) {
final Integer newValue = command.integerValueOfParameterNamed(SavingsApiConstants.interestRatePeriodFrequencyTypeParamName);
actualChanges.put(SavingsApiConstants.interestRatePeriodFrequencyTypeParamName, newValue);
this.interestRatePeriodFrequencyType = PeriodFrequencyType.fromInt(newValue).getValue();
this.nominalAnnualInterestRate = newValue;
}
if (command.isChangeInBigDecimalParameterNamed(SavingsApiConstants.minRequiredOpeningBalanceParamName,
@@ -9,12 +9,11 @@ import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activa
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestPeriodTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestRateParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestRatePeriodFrequencyTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
import java.math.BigDecimal;
import java.util.Locale;
@@ -30,8 +29,6 @@ import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
import org.mifosplatform.portfolio.group.domain.Group;
import org.mifosplatform.portfolio.group.domain.GroupRepository;
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.AprCalculator;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.savings.exception.SavingsProductNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -46,18 +43,15 @@ public class SavingsAccountAssembler {
private final GroupRepository groupRepository;
private final SavingsProductRepository savingProductRepository;
private final FromJsonHelper fromApiJsonHelper;
private final AprCalculator aprCalculator;
@Autowired
public SavingsAccountAssembler(final SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper,
final ClientRepository clientRepository, final GroupRepository groupRepository,
final SavingsProductRepository savingProductRepository, final AprCalculator aprCalculator,
final FromJsonHelper fromApiJsonHelper) {
final SavingsProductRepository savingProductRepository, final FromJsonHelper fromApiJsonHelper) {
this.savingsAccountTransactionSummaryWrapper = savingsAccountTransactionSummaryWrapper;
this.clientRepository = clientRepository;
this.groupRepository = groupRepository;
this.savingProductRepository = savingProductRepository;
this.aprCalculator = aprCalculator;
this.fromApiJsonHelper = fromApiJsonHelper;
}
@@ -93,8 +87,8 @@ public class SavingsAccountAssembler {
}
BigDecimal interestRate = null;
if (command.parameterExists(interestRateParamName)) {
interestRate = command.bigDecimalValueOfParameterNamed(interestRateParamName);
if (command.parameterExists(nominalAnnualInterestRateParamName)) {
interestRate = command.bigDecimalValueOfParameterNamed(nominalAnnualInterestRateParamName);
} else {
interestRate = product.interestRate();
}
@@ -102,23 +96,10 @@ public class SavingsAccountAssembler {
final boolean active = fromApiJsonHelper.extractBooleanNamed(activeParamName, element);
final LocalDate activationDate = fromApiJsonHelper.extractLocalDateNamed(activationDateParamName, element);
PeriodFrequencyType interestRatePeriodFrequencyType = null;
Integer interestRatePeriodFrequencyTypeValue = null;
if (command.parameterExists(interestRatePeriodFrequencyTypeParamName)) {
interestRatePeriodFrequencyTypeValue = command.integerValueOfParameterNamed(interestRatePeriodFrequencyTypeParamName);
if (interestRatePeriodFrequencyTypeValue != null) {
interestRatePeriodFrequencyType = PeriodFrequencyType.fromInt(interestRatePeriodFrequencyTypeValue);
}
} else {
interestRatePeriodFrequencyType = product.interestRatePeriodFrequencyType();
}
final BigDecimal annualInterestRate = this.aprCalculator.calculateFrom(interestRatePeriodFrequencyType, interestRate);
SavingsInterestPeriodType interestPeriodType = null;
final Integer interestPeriodTypeValue = command.integerValueOfParameterNamed(interestPeriodTypeParamName);
SavingsCompoundingInterestPeriodType interestPeriodType = null;
final Integer interestPeriodTypeValue = command.integerValueOfParameterNamed(interestCompoundingPeriodTypeParamName);
if (interestPeriodTypeValue != null) {
interestPeriodType = SavingsInterestPeriodType.fromInt(interestPeriodTypeValue);
interestPeriodType = SavingsCompoundingInterestPeriodType.fromInt(interestPeriodTypeValue);
}
SavingsInterestCalculationType interestCalculationType = null;
@@ -148,20 +129,20 @@ public class SavingsAccountAssembler {
lockinPeriodFrequency = product.lockinPeriodFrequency();
}
PeriodFrequencyType lockinPeriodFrequencyType = null;
SavingsPeriodFrequencyType lockinPeriodFrequencyType = null;
Integer lockinPeriodFrequencyTypeValue = null;
if (command.parameterExists(lockinPeriodFrequencyTypeParamName)) {
lockinPeriodFrequencyTypeValue = command.integerValueOfParameterNamed(lockinPeriodFrequencyTypeParamName);
if (lockinPeriodFrequencyTypeValue != null) {
lockinPeriodFrequencyType = PeriodFrequencyType.fromInt(lockinPeriodFrequencyTypeValue);
lockinPeriodFrequencyType = SavingsPeriodFrequencyType.fromInt(lockinPeriodFrequencyTypeValue);
}
} else {
lockinPeriodFrequencyType = product.lockinPeriodFrequencyType();
}
final SavingsAccount account = SavingsAccount.createNewAccount(client, group, product, accountNo, externalId, interestRate,
interestRatePeriodFrequencyType, annualInterestRate, interestPeriodType, interestCalculationType,
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType);
interestPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
lockinPeriodFrequency, lockinPeriodFrequencyType);
account.setHelpers(this.savingsAccountTransactionSummaryWrapper);
if (active) {
@@ -9,24 +9,32 @@ import org.mifosplatform.organisation.monetary.domain.Money;
public class SavingsAccountDailyBalance {
private final InterestPeriodInterval interestPeriodInterval;
private final BigDecimal runningBalance;
private final LocalDateInterval interestPeriodInterval;
private final BigDecimal endOfDayBalance;
private final BigDecimal cumulativeBalance;
private final BigDecimal compoundedInterestToDate;
public static SavingsAccountDailyBalance createFrom(final InterestPeriodInterval interestPeriodInterval, final BigDecimal runningBalance) {
return new SavingsAccountDailyBalance(interestPeriodInterval, runningBalance);
public static SavingsAccountDailyBalance createFrom(final LocalDateInterval interestPeriodInterval, final BigDecimal endOfDayBalance,
final BigDecimal compoundedInterestToDate) {
return new SavingsAccountDailyBalance(interestPeriodInterval, endOfDayBalance, compoundedInterestToDate);
}
private SavingsAccountDailyBalance(final InterestPeriodInterval interestPeriodInterval, final BigDecimal runningBalance) {
private SavingsAccountDailyBalance(final LocalDateInterval interestPeriodInterval, final BigDecimal endOfDayBalance,
final BigDecimal compoundedInterestToDate) {
this.interestPeriodInterval = interestPeriodInterval;
this.runningBalance = runningBalance;
this.endOfDayBalance = endOfDayBalance;
this.compoundedInterestToDate = compoundedInterestToDate;
final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN);
final BigDecimal numberOfDaysBigDecimal = BigDecimal.valueOf(interestPeriodInterval.daysInPeriodInclusiveOfEndDate());
this.cumulativeBalance = runningBalance.multiply(numberOfDaysBigDecimal, mc);
this.cumulativeBalance = endOfDayBalance.multiply(numberOfDaysBigDecimal, mc);
}
public Money dailyRunningBalance(final MonetaryCurrency currency) {
return Money.of(currency, runningBalance);
return Money.of(currency, endOfDayBalance);
}
public BigDecimal endOfDayBalance() {
return this.endOfDayBalance;
}
public BigDecimal cumulativeBalance() {
@@ -38,12 +46,14 @@ public class SavingsAccountDailyBalance {
}
public boolean isGreaterThanZero() {
return this.runningBalance.compareTo(BigDecimal.ZERO) > 0;
return this.endOfDayBalance.compareTo(BigDecimal.ZERO) > 0;
}
public BigDecimal interestUsingDailyBalanceMethod(final BigDecimal dailyInterestRate, final Integer numberOfDays) {
final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN);
final BigDecimal numberOfDaysBigDecimal = BigDecimal.valueOf(numberOfDays.longValue());
return this.runningBalance.multiply(dailyInterestRate, mc).multiply(numberOfDaysBigDecimal, mc);
final BigDecimal compoundedEndOfDayBalance = this.endOfDayBalance.add(this.compoundedInterestToDate, mc);
return compoundedEndOfDayBalance.multiply(dailyInterestRate, mc).multiply(numberOfDaysBigDecimal, mc);
}
}
@@ -47,13 +47,19 @@ public final class SavingsAccountSummary {
.getAmount();
}
public void updateFromInterestPeriodSummaries(final MonetaryCurrency currency, final List<InterestPeriodSummary> interestPeriodSummaries) {
Money totalInterestEarned = Money.zero(currency);
for (InterestPeriodSummary interestPeriodSummary : interestPeriodSummaries) {
totalInterestEarned = totalInterestEarned.plus(interestPeriodSummary.interest());
public void updateFromInterestPeriodSummaries(final MonetaryCurrency currency,
final List<InterestCompoundingPeriodSummary> compoundingPeriods) {
// get the max compounded interest
final BigDecimal compoundedInterestToDate = compoundingPeriods.get(compoundingPeriods.size() - 1).compoundedInterest();
final Money maxIntrestCompoundedToDate = Money.of(currency, compoundedInterestToDate);
BigDecimal totalInterestUnrounded = BigDecimal.ZERO;
for (InterestCompoundingPeriodSummary interestPeriodSummary : compoundingPeriods) {
totalInterestUnrounded = totalInterestUnrounded.add(interestPeriodSummary.interestUnrounded());
}
this.totalInterestEarned = totalInterestEarned.getAmountDefaultedToNullIfZero();
this.totalInterestEarned = maxIntrestCompoundedToDate.getAmountDefaultedToNullIfZero();
}
public boolean isLessThanOrEqualToAccountBalance(final Money amount) {
@@ -130,7 +130,7 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
public void updateCumulativeBalanceAndDates(final MonetaryCurrency currency, final LocalDate endOfBalanceDate) {
this.balanceEndDate = endOfBalanceDate.toDate();
this.balanceNumberOfDays = InterestPeriodInterval.create(getTransactionLocalDate(), endOfBalanceDate)
this.balanceNumberOfDays = LocalDateInterval.create(getTransactionLocalDate(), endOfBalanceDate)
.daysInPeriodInclusiveOfEndDate();
this.cumulativeBalance = Money.of(currency, this.runningBalance).multipliedBy(this.balanceNumberOfDays).getAmount();
}
@@ -147,7 +147,7 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
return endDate;
}
public boolean isAcceptableForDailyBalance(final InterestPeriodInterval interestPeriodInterval) {
public boolean isAcceptableForDailyBalance(final LocalDateInterval interestPeriodInterval) {
return isNotReversed() && interestPeriodInterval.contains(getTransactionLocalDate()) && isABalanceForAtLeastOneDay();
}
@@ -162,7 +162,17 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
balanceValidTo = periodEnd;
}
final InterestPeriodInterval interestPeriodInterval = InterestPeriodInterval.create(getTransactionLocalDate(), balanceValidTo);
return SavingsAccountDailyBalance.createFrom(interestPeriodInterval, this.runningBalance);
final LocalDateInterval interestPeriodInterval = LocalDateInterval.create(getTransactionLocalDate(), balanceValidTo);
return SavingsAccountDailyBalance.createFrom(interestPeriodInterval, this.runningBalance, BigDecimal.ZERO);
}
public SavingsAccountDailyBalance toCompoundedDailyBalance(final LocalDate periodEnd, final BigDecimal compoundedInterestToDate) {
LocalDate balanceValidTo = getEndOfBalanceLocalDate();
if (periodEnd.isBefore(getEndOfBalanceLocalDate())) {
balanceValidTo = periodEnd;
}
final LocalDateInterval interestPeriodInterval = LocalDateInterval.create(getTransactionLocalDate(), balanceValidTo);
return SavingsAccountDailyBalance.createFrom(interestPeriodInterval, this.runningBalance, compoundedInterestToDate);
}
}
@@ -3,7 +3,7 @@ package org.mifosplatform.portfolio.savings.domain;
import java.math.BigDecimal;
import java.util.List;
public interface SavingsInterestCalculator {
public interface SavingsCompoundInterestCalculator {
BigDecimal calculate(List<SavingsAccountDailyBalance> dailyBalances, Integer numberOfDays);
@@ -9,12 +9,12 @@ import java.util.List;
* Calculates interest on a savings account using the <b>Average Balance</b>
* method.
*/
public class SavingsInterestCalculatorForAverageBalance implements SavingsInterestCalculator {
public class SavingsCompoundInterestCalculatorForAverageBalance implements SavingsCompoundInterestCalculator {
private final BigDecimal periodsInOneYearAsFraction;
private final BigDecimal annualInterestRateAsFraction;
public SavingsInterestCalculatorForAverageBalance(final BigDecimal periodsInOneYearAsFraction,
public SavingsCompoundInterestCalculatorForAverageBalance(final BigDecimal periodsInOneYearAsFraction,
final BigDecimal annualInterestRateAsFraction) {
this.periodsInOneYearAsFraction = periodsInOneYearAsFraction;
this.annualInterestRateAsFraction = annualInterestRateAsFraction;
@@ -9,12 +9,12 @@ import java.util.List;
* Calculates interest on a savings account using the <b>Daily Balance</b>
* method.
*/
public class SavingsInterestCalculatorForDailyBalance implements SavingsInterestCalculator {
public class SavingsCompoundInterestCalculatorForDailyBalance implements SavingsCompoundInterestCalculator {
private final BigDecimal periodsInOneYearAsFraction;
private final BigDecimal annualInterestRateAsFraction;
public SavingsInterestCalculatorForDailyBalance(final BigDecimal periodsInOneYearAsFraction,
public SavingsCompoundInterestCalculatorForDailyBalance(final BigDecimal periodsInOneYearAsFraction,
final BigDecimal annualInterestRateAsFraction) {
this.periodsInOneYearAsFraction = periodsInOneYearAsFraction;
this.annualInterestRateAsFraction = annualInterestRateAsFraction;
@@ -29,7 +29,7 @@ public class SavingsInterestCalculatorForDailyBalance implements SavingsInterest
for (SavingsAccountDailyBalance balance : dailyBalances) {
if (balance.isGreaterThanZero()) {
final BigDecimal interestForBalance = balance.interestUsingDailyBalanceMethod(dailyInterestRate, numberOfDays);
final BigDecimal interestForBalance = balance.interestUsingDailyBalanceMethod(dailyInterestRate, balance.numberOfDays());
interestCalculated = interestCalculated.add(interestForBalance, mc);
}
}
@@ -0,0 +1,74 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.savings.domain;
/**
* <p>
* The compounding interest period is the span of time at the end of which
* savings in a client’s account earn interest.
* </p>
*/
public enum SavingsCompoundingInterestPeriodType {
INVALID(0, "savingsCompoundingInterestPeriodType.invalid"), //
DAILY(1, "savingsCompoundingInterestPeriodType.daily"), //
WEEKLY(2, "savingsCompoundingInterestPeriodType.weekly"), //
BIWEEKLY(3, "savingsCompoundingInterestPeriodType.biweekly"), //
MONTHLY(4, "savingsCompoundingInterestPeriodType.monthly"), //
QUATERLY(5, "savingsCompoundingInterestPeriodType.quarterly"), //
BI_ANNUAL(6, "savingsCompoundingInterestPeriodType.biannual"), //
ANNUAL(7, "savingsCompoundingInterestPeriodType.annual"), //
NO_COMPOUNDING_SIMPLE_INTEREST(8, "savingsCompoundingInterestPeriodType.nocompounding");
private final Integer value;
private final String code;
private SavingsCompoundingInterestPeriodType(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 SavingsCompoundingInterestPeriodType fromInt(final Integer type) {
SavingsCompoundingInterestPeriodType repaymentFrequencyType = SavingsCompoundingInterestPeriodType.INVALID;
if (type != null) {
switch (type) {
case 1:
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.DAILY;
break;
case 2:
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.WEEKLY;
break;
case 3:
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.BIWEEKLY;
break;
case 4:
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.MONTHLY;
break;
case 5:
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.QUATERLY;
break;
case 6:
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.BI_ANNUAL;
break;
case 7:
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.ANNUAL;
break;
case 8:
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.NO_COMPOUNDING_SIMPLE_INTEREST;
break;
}
}
return repaymentFrequencyType;
}
}
@@ -4,18 +4,18 @@ import java.math.BigDecimal;
public class SavingsInterestCalculatorFactory {
public SavingsInterestCalculator createFrom(final SavingsInterestCalculationType interestCalculationType,
public SavingsCompoundInterestCalculator createFrom(final SavingsInterestCalculationType interestCalculationType,
final BigDecimal periodsInOneYearAsFraction, final BigDecimal annualInterestRateAsFraction) {
SavingsInterestCalculator savingsInterestCalculator = new SavingsInterestCalculatorForDailyBalance(periodsInOneYearAsFraction,
SavingsCompoundInterestCalculator savingsInterestCalculator = new SavingsCompoundInterestCalculatorForDailyBalance(periodsInOneYearAsFraction,
annualInterestRateAsFraction);
switch (interestCalculationType) {
case AVERAGE_DAILY_BALANCE:
savingsInterestCalculator = new SavingsInterestCalculatorForAverageBalance(periodsInOneYearAsFraction,
savingsInterestCalculator = new SavingsCompoundInterestCalculatorForAverageBalance(periodsInOneYearAsFraction,
annualInterestRateAsFraction);
break;
case DAILY_BALANCE:
savingsInterestCalculator = new SavingsInterestCalculatorForDailyBalance(periodsInOneYearAsFraction,
savingsInterestCalculator = new SavingsCompoundInterestCalculatorForDailyBalance(periodsInOneYearAsFraction,
annualInterestRateAsFraction);
break;
case INVALID:
@@ -1,75 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.savings.domain;
/**
* <p>
* The interest period is the span of time at the end of which savings in a
* client’s account earn interest.
* </p>
*
* <p>
* Interest periods may differ for different types of savings products. In all
* cases, savings accounts must have established and published interest periods.
* </p>
*/
public enum SavingsInterestPeriodType {
INVALID(0, "savingsCalculationPeriodType.invalid"), //
DAILY(1, "savingsCalculationPeriodType.daily"), //
WEEKLY(2, "savingsCalculationPeriodType.weekly"), //
BIWEEKLY(3, "savingsCalculationPeriodType.biweekly"), //
MONTHLY(4, "savingsCalculationPeriodType.monthly"), //
QUATERLY(5, "savingsCalculationPeriodType.quarterly"), //
SEMIANNUAL(6, "savingsCalculationPeriodType.semiannual"), //
ANNUAL(7, "savingsCalculationPeriodType.annual");
private final Integer value;
private final String code;
private SavingsInterestPeriodType(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 SavingsInterestPeriodType fromInt(final Integer type) {
SavingsInterestPeriodType repaymentFrequencyType = SavingsInterestPeriodType.INVALID;
if (type != null) {
switch (type) {
case 1:
repaymentFrequencyType = SavingsInterestPeriodType.DAILY;
break;
case 2:
repaymentFrequencyType = SavingsInterestPeriodType.WEEKLY;
break;
case 3:
repaymentFrequencyType = SavingsInterestPeriodType.BIWEEKLY;
break;
case 4:
repaymentFrequencyType = SavingsInterestPeriodType.MONTHLY;
break;
case 5:
repaymentFrequencyType = SavingsInterestPeriodType.QUATERLY;
break;
case 6:
repaymentFrequencyType = SavingsInterestPeriodType.SEMIANNUAL;
break;
case 7:
repaymentFrequencyType = SavingsInterestPeriodType.ANNUAL;
break;
}
}
return repaymentFrequencyType;
}
}
@@ -10,14 +10,13 @@ import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.descri
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.digitsAfterDecimalParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestPeriodTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestRateParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestRatePeriodFrequencyTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.localeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nameParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
import java.math.BigDecimal;
import java.util.LinkedHashMap;
@@ -31,7 +30,6 @@ import javax.persistence.Table;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.savings.exception.InvalidSavingsProductSettingsException;
import org.springframework.data.jpa.domain.AbstractPersistable;
@@ -48,20 +46,17 @@ public class SavingsProduct extends AbstractPersistable<Long> {
@Embedded
private MonetaryCurrency currency;
@Column(name = "nominal_interest_rate_per_period", scale = 6, precision = 19, nullable = false)
private BigDecimal interestRate;
@Column(name = "nominal_interest_rate_period_frequency_enum", nullable = false)
private Integer interestRatePeriodFrequencyType;
@Column(name = "nominal_annual_interest_rate", scale = 6, precision = 19, nullable = false)
private BigDecimal nominalAnnualInterestRate;
/**
* The interest period is the span of time at the end of which savings in a
* client’s account earn interest.
*
* A value from the {@link SavingsInterestPeriodType} enumeration.
* A value from the {@link SavingsCompoundingInterestPeriodType} enumeration.
*/
@Column(name = "interest_period_enum", nullable = false)
private Integer interestPeriodType;
@Column(name = "interest_compounding_period_enum", nullable = false)
private Integer interestCompoundingPeriodType;
/**
* A value from the {@link SavingsInterestCalculationType} enumeration.
@@ -86,15 +81,13 @@ public class SavingsProduct extends AbstractPersistable<Long> {
private Integer lockinPeriodFrequencyType;
public static SavingsProduct createNew(final String name, final String description, final MonetaryCurrency currency,
final BigDecimal interestRate, final SavingsPeriodFrequencyType interestRatePeriodFrequencyType,
final SavingsInterestPeriodType interestPeriodType, final SavingsInterestCalculationType interestCalculationType,
final BigDecimal interestRate, final SavingsCompoundingInterestPeriodType interestPeriodType,
final SavingsInterestCalculationType interestCalculationType,
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
final Integer lockinPeriodFrequency,
final PeriodFrequencyType lockinPeriodFrequencyType) {
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType) {
return new SavingsProduct(name, description, currency, interestRate, interestRatePeriodFrequencyType, interestPeriodType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType);
return new SavingsProduct(name, description, currency, interestRate, interestPeriodType, interestCalculationType,
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType);
}
protected SavingsProduct() {
@@ -103,18 +96,16 @@ public class SavingsProduct extends AbstractPersistable<Long> {
}
private SavingsProduct(final String name, final String description, final MonetaryCurrency currency, final BigDecimal interestRate,
final SavingsPeriodFrequencyType interestRatePeriodFrequencyType, final SavingsInterestPeriodType interestPeriodType,
final SavingsInterestCalculationType interestCalculationType,
final SavingsCompoundingInterestPeriodType interestPeriodType, final SavingsInterestCalculationType interestCalculationType,
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
final Integer lockinPeriodFrequency, final PeriodFrequencyType lockinPeriodFrequencyType) {
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType) {
this.name = name;
this.description = description;
this.currency = currency;
this.interestRate = interestRate;
this.interestRatePeriodFrequencyType = interestRatePeriodFrequencyType.getValue();
this.interestPeriodType = interestPeriodType.getValue();
this.nominalAnnualInterestRate = interestRate;
this.interestCompoundingPeriodType = interestPeriodType.getValue();
this.interestCalculationType = interestCalculationType.getValue();
this.interestCalculationDaysInYearType = interestCalculationDaysInYearType.getValue();
@@ -135,15 +126,7 @@ public class SavingsProduct extends AbstractPersistable<Long> {
}
public BigDecimal interestRate() {
return Money.of(this.currency, this.interestRate).getAmount();
}
public PeriodFrequencyType interestRatePeriodFrequencyType() {
PeriodFrequencyType type = null;
if (this.interestRatePeriodFrequencyType != null) {
type = PeriodFrequencyType.fromInt(this.interestRatePeriodFrequencyType);
}
return type;
return Money.of(this.currency, this.nominalAnnualInterestRate).getAmount();
}
public BigDecimal minRequiredOpeningBalance() {
@@ -154,10 +137,10 @@ public class SavingsProduct extends AbstractPersistable<Long> {
return this.lockinPeriodFrequency;
}
public PeriodFrequencyType lockinPeriodFrequencyType() {
PeriodFrequencyType type = null;
public SavingsPeriodFrequencyType lockinPeriodFrequencyType() {
SavingsPeriodFrequencyType type = null;
if (this.lockinPeriodFrequencyType != null) {
type = PeriodFrequencyType.fromInt(this.lockinPeriodFrequencyType);
type = SavingsPeriodFrequencyType.fromInt(this.lockinPeriodFrequencyType);
}
return type;
}
@@ -197,23 +180,17 @@ public class SavingsProduct extends AbstractPersistable<Long> {
this.currency = new MonetaryCurrency(currencyCode, this.currency.getDigitsAfterDecimal());
}
if (command.isChangeInBigDecimalParameterNamed(interestRateParamName, this.interestRate)) {
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(interestRateParamName);
actualChanges.put(interestRateParamName, newValue);
if (command.isChangeInBigDecimalParameterNamed(nominalAnnualInterestRateParamName, this.nominalAnnualInterestRate)) {
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(nominalAnnualInterestRateParamName);
actualChanges.put(nominalAnnualInterestRateParamName, newValue);
actualChanges.put(localeParamName, localeAsInput);
this.interestRate = newValue;
this.nominalAnnualInterestRate = newValue;
}
if (command.isChangeInIntegerParameterNamed(interestRatePeriodFrequencyTypeParamName, this.interestRatePeriodFrequencyType)) {
final Integer newValue = command.integerValueOfParameterNamed(interestRatePeriodFrequencyTypeParamName);
actualChanges.put(interestRatePeriodFrequencyTypeParamName, newValue);
this.interestRatePeriodFrequencyType = SavingsPeriodFrequencyType.fromInt(newValue).getValue();
}
if (command.isChangeInIntegerParameterNamed(interestPeriodTypeParamName, this.interestPeriodType)) {
final Integer newValue = command.integerValueOfParameterNamed(interestPeriodTypeParamName);
actualChanges.put(interestPeriodTypeParamName, newValue);
this.interestPeriodType = SavingsInterestPeriodType.fromInt(newValue).getValue();
if (command.isChangeInIntegerParameterNamed(interestCompoundingPeriodTypeParamName, this.interestCompoundingPeriodType)) {
final Integer newValue = command.integerValueOfParameterNamed(interestCompoundingPeriodTypeParamName);
actualChanges.put(interestCompoundingPeriodTypeParamName, newValue);
this.interestCompoundingPeriodType = SavingsCompoundingInterestPeriodType.fromInt(newValue).getValue();
}
if (command.isChangeInIntegerParameterNamed(interestCalculationTypeParamName, this.interestCalculationType)) {
@@ -5,19 +5,17 @@ import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.descri
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.digitsAfterDecimalParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestPeriodTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestRateParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestRatePeriodFrequencyTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nameParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
import java.math.BigDecimal;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.stereotype.Component;
@Component
@@ -32,17 +30,12 @@ public class SavingsProductAssembler {
final Integer digitsAfterDecimal = command.integerValueOfParameterNamed(digitsAfterDecimalParamName);
MonetaryCurrency currency = new MonetaryCurrency(currencyCode, digitsAfterDecimal);
final BigDecimal interestRate = command.bigDecimalValueOfParameterNamed(interestRateParamName);
SavingsPeriodFrequencyType interestRatePeriodFrequencyType = null;
final Integer interestRatePeriodFrequencyTypeValue = command.integerValueOfParameterNamed(interestRatePeriodFrequencyTypeParamName);
if (interestRatePeriodFrequencyTypeValue != null) {
interestRatePeriodFrequencyType = SavingsPeriodFrequencyType.fromInt(interestRatePeriodFrequencyTypeValue);
}
final BigDecimal interestRate = command.bigDecimalValueOfParameterNamed(nominalAnnualInterestRateParamName);
SavingsInterestPeriodType interestPeriodType = null;
final Integer interestPeriodTypeValue = command.integerValueOfParameterNamed(interestPeriodTypeParamName);
SavingsCompoundingInterestPeriodType interestPeriodType = null;
final Integer interestPeriodTypeValue = command.integerValueOfParameterNamed(interestCompoundingPeriodTypeParamName);
if (interestPeriodTypeValue != null) {
interestPeriodType = SavingsInterestPeriodType.fromInt(interestPeriodTypeValue);
interestPeriodType = SavingsCompoundingInterestPeriodType.fromInt(interestPeriodTypeValue);
}
SavingsInterestCalculationType interestCalculationType = null;
@@ -61,14 +54,13 @@ public class SavingsProductAssembler {
final BigDecimal minRequiredOpeningBalance = command.bigDecimalValueOfParameterNamed(minRequiredOpeningBalanceParamName);
final Integer lockinPeriodFrequency = command.integerValueOfParameterNamed(lockinPeriodFrequencyParamName);
PeriodFrequencyType lockinPeriodFrequencyType = null;
SavingsPeriodFrequencyType lockinPeriodFrequencyType = null;
final Integer lockinPeriodFrequencyTypeValue = command.integerValueOfParameterNamed(lockinPeriodFrequencyTypeParamName);
if (lockinPeriodFrequencyTypeValue != null) {
lockinPeriodFrequencyType = PeriodFrequencyType.fromInt(lockinPeriodFrequencyTypeValue);
lockinPeriodFrequencyType = SavingsPeriodFrequencyType.fromInt(lockinPeriodFrequencyTypeValue);
}
return SavingsProduct.createNew(name, description, currency, interestRate, interestRatePeriodFrequencyType, interestPeriodType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType);
return SavingsProduct.createNew(name, description, currency, interestRate, interestPeriodType, interestCalculationType,
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType);
}
}
@@ -27,9 +27,9 @@ import org.mifosplatform.portfolio.savings.data.SavingsAccountSummaryData;
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionData;
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionEnumData;
import org.mifosplatform.portfolio.savings.data.SavingsProductData;
import org.mifosplatform.portfolio.savings.domain.SavingsCompoundingInterestPeriodType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationDaysInYearType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestPeriodType;
import org.mifosplatform.portfolio.savings.domain.SavingsPeriodFrequencyType;
import org.mifosplatform.portfolio.savings.exception.SavingsAccountNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
@@ -103,10 +103,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
sqlBuilder.append("sa.currency_code as currencyCode, sa.currency_digits as currencyDigits, ");
sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, ");
sqlBuilder.append("sa.nominal_interest_rate_per_period as interestRate, ");
sqlBuilder.append("sa.nominal_interest_rate_period_frequency_enum as interestRatePeriodFrequencyType, ");
sqlBuilder.append("sa.annual_nominal_interest_rate as annualInterestRate, ");
sqlBuilder.append("sa.interest_period_enum as interestPeriodType, ");
sqlBuilder.append("sa.nominal_annual_interest_rate as nominalAnnualInterestRate, ");
sqlBuilder.append("sa.interest_compounding_period_enum as interestCompoundingPeriodType, ");
sqlBuilder.append("sa.interest_calculation_type_enum as interestCalculationType, ");
sqlBuilder.append("sa.interest_calculation_days_in_year_type_enum as interestCalculationDaysInYearType, ");
sqlBuilder.append("sa.min_required_opening_balance as minRequiredOpeningBalance, ");
@@ -158,20 +156,16 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, currencyDisplaySymbol,
currencyNameCode);
final BigDecimal interestRate = rs.getBigDecimal("interestRate");
final SavingsPeriodFrequencyType interestRatePeriodType = SavingsPeriodFrequencyType.fromInt(JdbcSupport.getInteger(rs,
"interestRatePeriodFrequencyType"));
final EnumOptionData interestRatePeriodFrequencyType = SavingsEnumerations
.interestRatePeriodFrequencyType(interestRatePeriodType);
final BigDecimal annualInterestRate = rs.getBigDecimal("annualInterestRate");
final BigDecimal nominalAnnualInterestRate = rs.getBigDecimal("nominalAnnualInterestRate");
EnumOptionData interestPeriodType = SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.fromInt(JdbcSupport
.getInteger(rs, "interestPeriodType")));
final EnumOptionData interestCompoundingPeriodType = SavingsEnumerations
.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.fromInt(JdbcSupport.getInteger(rs,
"interestCompoundingPeriodType")));
EnumOptionData interestCalculationType = SavingsEnumerations.interestCalculationType(SavingsInterestCalculationType
final EnumOptionData interestCalculationType = SavingsEnumerations.interestCalculationType(SavingsInterestCalculationType
.fromInt(JdbcSupport.getInteger(rs, "interestCalculationType")));
EnumOptionData interestCalculationDaysInYearType = SavingsEnumerations
final EnumOptionData interestCalculationDaysInYearType = SavingsEnumerations
.interestCalculationDaysInYearType(SavingsInterestCalculationDaysInYearType.fromInt(JdbcSupport.getInteger(rs,
"interestCalculationDaysInYearType")));
@@ -194,10 +188,11 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
final SavingsAccountSummaryData summary = new SavingsAccountSummaryData(currency, totalDeposits, totalWithdrawals,
totalInterestEarned, totalInterestPosted, accountBalance);
return SavingsAccountData.instance(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName,
productId, productName, currency, interestRate, interestRatePeriodFrequencyType, annualInterestRate,
interestPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
lockinPeriodFrequency, lockinPeriodFrequencyType, summary);
return SavingsAccountData
.instance(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName, productId,
productName, currency, nominalAnnualInterestRate, interestCompoundingPeriodType, interestCalculationType,
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
summary);
}
}
@@ -225,11 +220,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
final String sql = "select " + mapper.schema() + " where sp.id = ?";
template = this.jdbcTemplate.queryForObject(sql, mapper, new Object[] { productId });
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions = this.dropdownReadPlatformService
.retrieveInterestRatePeriodFrequencyTypeOptions();
final Collection<EnumOptionData> interestPeriodTypeOptions = this.dropdownReadPlatformService
.retrieveInterestPeriodTypeOptions();
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = this.dropdownReadPlatformService
.retrieveCompoundingInterestPeriodTypeOptions();
final Collection<EnumOptionData> interestCalculationTypeOptions = this.dropdownReadPlatformService
.retrieveInterestCalculationTypeOptions();
@@ -241,9 +233,9 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
.retrieveLockinPeriodFrequencyTypeOptions();
final Collection<SavingsAccountTransactionData> transactions = null;
template = SavingsAccountData.withTemplateOptions(template, productOptions, interestRatePeriodFrequencyTypeOptions,
interestPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
lockinPeriodFrequencyTypeOptions, transactions);
template = SavingsAccountData.withTemplateOptions(template, productOptions, interestCompoundingPeriodTypeOptions,
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
transactions);
} else {
String clientName = null;
@@ -258,16 +250,15 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
template = SavingsAccountData.withClientTemplate(clientId, clientName, groupId, groupName);
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions = null;
final Collection<EnumOptionData> interestPeriodTypeOptions = null;
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
final Collection<SavingsAccountTransactionData> transactions = null;
template = SavingsAccountData.withTemplateOptions(template, productOptions, interestRatePeriodFrequencyTypeOptions,
interestPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
lockinPeriodFrequencyTypeOptions, transactions);
template = SavingsAccountData.withTemplateOptions(template, productOptions, interestCompoundingPeriodTypeOptions,
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
transactions);
}
return template;
@@ -398,9 +389,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
sqlBuilder.append("sp.currency_code as currencyCode, sp.currency_digits as currencyDigits, ");
sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, ");
sqlBuilder.append("sp.nominal_interest_rate_per_period as interestRate, ");
sqlBuilder.append("sp.nominal_interest_rate_period_frequency_enum as interestRatePeriodFrequencyType, ");
sqlBuilder.append("sp.interest_period_enum as interestPeriodType, ");
sqlBuilder.append("sp.nominal_annual_interest_rate as nominalAnnualIterestRate, ");
sqlBuilder.append("sp.interest_compounding_period_enum as interestCompoundingPeriodType, ");
sqlBuilder.append("sp.interest_calculation_type_enum as interestCalculationType, ");
sqlBuilder.append("sp.interest_calculation_days_in_year_type_enum as interestCalculationDaysInYearType, ");
sqlBuilder.append("sp.min_required_opening_balance as minRequiredOpeningBalance, ");
@@ -430,15 +420,10 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, currencyDisplaySymbol,
currencyNameCode);
final BigDecimal interestRate = rs.getBigDecimal("interestRate");
final SavingsPeriodFrequencyType interestRatePeriodType = SavingsPeriodFrequencyType.fromInt(JdbcSupport.getInteger(rs,
"interestRatePeriodFrequencyType"));
final EnumOptionData interestRatePeriodFrequencyType = SavingsEnumerations
.interestRatePeriodFrequencyType(interestRatePeriodType);
final BigDecimal annualInterestRate = null;
final BigDecimal nominalAnnualIterestRate = rs.getBigDecimal("nominalAnnualIterestRate");
EnumOptionData interestPeriodType = SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.fromInt(JdbcSupport
.getInteger(rs, "interestPeriodType")));
EnumOptionData interestPeriodType = SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType
.fromInt(JdbcSupport.getInteger(rs, "interestCompoundingPeriodType")));
EnumOptionData interestCalculationType = SavingsEnumerations.interestCalculationType(SavingsInterestCalculationType
.fromInt(JdbcSupport.getInteger(rs, "interestCalculationType")));
@@ -474,10 +459,11 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
final SavingsAccountStatusEnumData status = null;
final LocalDate activationDate = null;
final SavingsAccountSummaryData summary = null;
return SavingsAccountData.instance(null, null, null, status, activationDate, groupId, groupName, clientId, clientName,
productId, productName, currency, interestRate, interestRatePeriodFrequencyType, annualInterestRate,
interestPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
lockinPeriodFrequency, lockinPeriodFrequencyType, summary);
return SavingsAccountData
.instance(null, null, null, status, activationDate, groupId, groupName, clientId, clientName, productId, productName,
currency, nominalAnnualIterestRate, interestPeriodType, interestCalculationType,
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
summary);
}
}
}
@@ -17,6 +17,7 @@ import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.core.service.DateUtils;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator;
import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory;
@@ -321,7 +322,8 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
final SavingsAccount account = this.savingAccountRepository.findOneWithNotFoundDetection(savingsId);
account.calculateInterest();
final LocalDate today = DateUtils.getLocalDateOfTenant();
account.calculateInterest(today);
this.savingAccountRepository.save(account);
return new CommandProcessingResultBuilder() //
@@ -6,11 +6,9 @@ import org.mifosplatform.infrastructure.core.data.EnumOptionData;
public interface SavingsDropdownReadPlatformService {
Collection<EnumOptionData> retrieveInterestRatePeriodFrequencyTypeOptions();
Collection<EnumOptionData> retrieveLockinPeriodFrequencyTypeOptions();
Collection<EnumOptionData> retrieveInterestPeriodTypeOptions();
Collection<EnumOptionData> retrieveCompoundingInterestPeriodTypeOptions();
Collection<EnumOptionData> retrieveInterestCalculationTypeOptions();
@@ -5,25 +5,15 @@ import java.util.Collection;
import java.util.List;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.portfolio.savings.domain.SavingsCompoundingInterestPeriodType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationDaysInYearType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestPeriodType;
import org.mifosplatform.portfolio.savings.domain.SavingsPeriodFrequencyType;
import org.springframework.stereotype.Service;
@Service
public class SavingsDropdownReadPlatformServiceImpl implements SavingsDropdownReadPlatformService {
@Override
public List<EnumOptionData> retrieveInterestRatePeriodFrequencyTypeOptions() {
List<EnumOptionData> allowedInterestRatePeriodFrequencyTypeOptions = Arrays.asList( //
SavingsEnumerations.interestRatePeriodFrequencyType(SavingsPeriodFrequencyType.MONTHS), //
SavingsEnumerations.interestRatePeriodFrequencyType(SavingsPeriodFrequencyType.YEARS) //
);
return allowedInterestRatePeriodFrequencyTypeOptions;
}
@Override
public List<EnumOptionData> retrieveLockinPeriodFrequencyTypeOptions() {
List<EnumOptionData> allowedLockinPeriodFrequencyTypeOptions = Arrays.asList( //
@@ -37,15 +27,16 @@ public class SavingsDropdownReadPlatformServiceImpl implements SavingsDropdownRe
}
@Override
public Collection<EnumOptionData> retrieveInterestPeriodTypeOptions() {
public Collection<EnumOptionData> retrieveCompoundingInterestPeriodTypeOptions() {
List<EnumOptionData> allowedOptions = Arrays.asList( //
SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.DAILY), //
SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.WEEKLY), //
SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.BIWEEKLY), //
SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.MONTHLY), //
SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.QUATERLY), //
SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.SEMIANNUAL), //
SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.ANNUAL) //
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.DAILY), //
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.WEEKLY), //
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.BIWEEKLY), //
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.MONTHLY), //
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.QUATERLY), //
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.BI_ANNUAL), //
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.ANNUAL), //
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.NO_COMPOUNDING_SIMPLE_INTEREST) //
);
return allowedOptions;
@@ -10,44 +10,13 @@ import org.mifosplatform.portfolio.savings.data.SavingsAccountStatusEnumData;
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionEnumData;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountStatusType;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransactionType;
import org.mifosplatform.portfolio.savings.domain.SavingsCompoundingInterestPeriodType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationDaysInYearType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestPeriodType;
import org.mifosplatform.portfolio.savings.domain.SavingsPeriodFrequencyType;
public class SavingsEnumerations {
public static EnumOptionData interestRatePeriodFrequencyType(final int id) {
return interestRatePeriodFrequencyType(SavingsPeriodFrequencyType.fromInt(id));
}
public static EnumOptionData interestRatePeriodFrequencyType(final SavingsPeriodFrequencyType type) {
final String codePrefix = "savings.interest.rate.";
EnumOptionData optionData = new EnumOptionData(SavingsPeriodFrequencyType.INVALID.getValue().longValue(),
SavingsPeriodFrequencyType.INVALID.getCode(), "Invalid");
switch (type) {
case INVALID:
break;
case DAYS:
optionData = new EnumOptionData(SavingsPeriodFrequencyType.DAYS.getValue().longValue(), codePrefix
+ SavingsPeriodFrequencyType.DAYS.getCode(), "Per day");
break;
case WEEKS:
optionData = new EnumOptionData(SavingsPeriodFrequencyType.WEEKS.getValue().longValue(), codePrefix
+ SavingsPeriodFrequencyType.WEEKS.getCode(), "Per week");
break;
case MONTHS:
optionData = new EnumOptionData(SavingsPeriodFrequencyType.MONTHS.getValue().longValue(), codePrefix
+ SavingsPeriodFrequencyType.MONTHS.getCode(), "Per month");
break;
case YEARS:
optionData = new EnumOptionData(SavingsPeriodFrequencyType.YEARS.getValue().longValue(), codePrefix
+ SavingsPeriodFrequencyType.YEARS.getCode(), "Per year");
break;
}
return optionData;
}
public static EnumOptionData lockinPeriodFrequencyType(final int id) {
return lockinPeriodFrequencyType(SavingsPeriodFrequencyType.fromInt(id));
}
@@ -141,45 +110,50 @@ public class SavingsEnumerations {
}
public static EnumOptionData interestPeriodType(final Integer type) {
return interestPeriodType(SavingsInterestPeriodType.fromInt(type));
return compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.fromInt(type));
}
public static EnumOptionData interestPeriodType(final SavingsInterestPeriodType type) {
public static EnumOptionData compoundingInterestPeriodType(final SavingsCompoundingInterestPeriodType type) {
final String codePrefix = "savings.interest.period.";
EnumOptionData optionData = new EnumOptionData(SavingsInterestPeriodType.INVALID.getValue().longValue(),
SavingsInterestPeriodType.INVALID.getCode(), "Invalid");
EnumOptionData optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.INVALID.getValue().longValue(),
SavingsCompoundingInterestPeriodType.INVALID.getCode(), "Invalid");
switch (type) {
case INVALID:
break;
case DAILY:
optionData = new EnumOptionData(SavingsInterestPeriodType.DAILY.getValue().longValue(), codePrefix
+ SavingsInterestPeriodType.DAILY.getCode(), "Daily");
optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.DAILY.getValue().longValue(), codePrefix
+ SavingsCompoundingInterestPeriodType.DAILY.getCode(), "Daily");
break;
case WEEKLY:
optionData = new EnumOptionData(SavingsInterestPeriodType.WEEKLY.getValue().longValue(), codePrefix
+ SavingsInterestPeriodType.WEEKLY.getCode(), "Weekly");
optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.WEEKLY.getValue().longValue(), codePrefix
+ SavingsCompoundingInterestPeriodType.WEEKLY.getCode(), "Weekly");
break;
case BIWEEKLY:
optionData = new EnumOptionData(SavingsInterestPeriodType.BIWEEKLY.getValue().longValue(), codePrefix
+ SavingsInterestPeriodType.BIWEEKLY.getCode(), "Bi-Weekly");
optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.BIWEEKLY.getValue().longValue(), codePrefix
+ SavingsCompoundingInterestPeriodType.BIWEEKLY.getCode(), "Bi-Weekly");
break;
case MONTHLY:
optionData = new EnumOptionData(SavingsInterestPeriodType.MONTHLY.getValue().longValue(), codePrefix
+ SavingsInterestPeriodType.MONTHLY.getCode(), "Monthly");
optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.MONTHLY.getValue().longValue(), codePrefix
+ SavingsCompoundingInterestPeriodType.MONTHLY.getCode(), "Monthly");
break;
case QUATERLY:
optionData = new EnumOptionData(SavingsInterestPeriodType.QUATERLY.getValue().longValue(), codePrefix
+ SavingsInterestPeriodType.QUATERLY.getCode(), "Quarterly");
optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.QUATERLY.getValue().longValue(), codePrefix
+ SavingsCompoundingInterestPeriodType.QUATERLY.getCode(), "Quarterly");
break;
case SEMIANNUAL:
optionData = new EnumOptionData(SavingsInterestPeriodType.SEMIANNUAL.getValue().longValue(), codePrefix
+ SavingsInterestPeriodType.SEMIANNUAL.getCode(), "Semi-Annual");
case BI_ANNUAL:
optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.BI_ANNUAL.getValue().longValue(), codePrefix
+ SavingsCompoundingInterestPeriodType.BI_ANNUAL.getCode(), "Semi-Annual");
break;
case ANNUAL:
optionData = new EnumOptionData(SavingsInterestPeriodType.ANNUAL.getValue().longValue(), codePrefix
+ SavingsInterestPeriodType.ANNUAL.getCode(), "Annually");
optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.ANNUAL.getValue().longValue(), codePrefix
+ SavingsCompoundingInterestPeriodType.ANNUAL.getCode(), "Annually");
break;
case NO_COMPOUNDING_SIMPLE_INTEREST:
optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.NO_COMPOUNDING_SIMPLE_INTEREST.getValue().longValue(),
codePrefix + SavingsCompoundingInterestPeriodType.NO_COMPOUNDING_SIMPLE_INTEREST.getCode(),
"No Compounding - Simple Interest");
break;
}
@@ -16,9 +16,9 @@ import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSourc
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.monetary.data.CurrencyData;
import org.mifosplatform.portfolio.savings.data.SavingsProductData;
import org.mifosplatform.portfolio.savings.domain.SavingsCompoundingInterestPeriodType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationDaysInYearType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestPeriodType;
import org.mifosplatform.portfolio.savings.domain.SavingsPeriodFrequencyType;
import org.mifosplatform.portfolio.savings.exception.SavingsProductNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
@@ -80,9 +80,8 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
sqlBuilder.append("sp.currency_code as currencyCode, sp.currency_digits as currencyDigits, ");
sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, ");
sqlBuilder.append("sp.nominal_interest_rate_per_period as interestRate, ");
sqlBuilder.append("sp.nominal_interest_rate_period_frequency_enum as interestRatePeriodFrequencyType, ");
sqlBuilder.append("sp.interest_period_enum as interestPeriodType, ");
sqlBuilder.append("sp.nominal_annual_interest_rate as nominalAnnualInterestRate, ");
sqlBuilder.append("sp.interest_compounding_period_enum as compoundingInterestPeriodType, ");
sqlBuilder.append("sp.interest_calculation_type_enum as interestCalculationType, ");
sqlBuilder.append("sp.interest_calculation_days_in_year_type_enum as interestCalculationDaysInYearType, ");
sqlBuilder.append("sp.min_required_opening_balance as minRequiredOpeningBalance, ");
@@ -113,13 +112,11 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, currencyDisplaySymbol,
currencyNameCode);
BigDecimal interestRate = rs.getBigDecimal("interestRate");
final BigDecimal nominalAnnualInterestRate = rs.getBigDecimal("nominalAnnualInterestRate");
EnumOptionData interestRatePeriodFrequencyType = SavingsEnumerations.interestRatePeriodFrequencyType(SavingsPeriodFrequencyType
.fromInt(JdbcSupport.getInteger(rs, "interestRatePeriodFrequencyType")));
EnumOptionData interestPeriodType = SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.fromInt(JdbcSupport
.getInteger(rs, "interestPeriodType")));
EnumOptionData compoundingInterestPeriodType = SavingsEnumerations
.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.fromInt(JdbcSupport.getInteger(rs,
"compoundingInterestPeriodType")));
EnumOptionData interestCalculationType = SavingsEnumerations.interestCalculationType(SavingsInterestCalculationType
.fromInt(JdbcSupport.getInteger(rs, "interestCalculationType")));
@@ -142,9 +139,9 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
.fromInt(lockinPeriodFrequencyTypeValue));
}
return SavingsProductData.instance(id, name, description, currency, interestRate, interestRatePeriodFrequencyType,
interestPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
lockinPeriodFrequency, lockinPeriodFrequencyType);
return SavingsProductData.instance(id, name, description, currency, nominalAnnualInterestRate, compoundingInterestPeriodType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType);
}
}