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 class=alt><td>digitsAfterDecimal</td></tr>
<tr><td class=fielddesc>Override the currency default value for digitsAfterDecimal.</td></tr> <tr><td class=fielddesc>Override the currency default value for digitsAfterDecimal.</td></tr>
<tr class=alt><td>interestRate</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</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 class=alt><td>interestCompoundingPeriodType</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><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 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> <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>
</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-section">
<div class="method-description"> <div class="method-description">
<h4>Retrieve Savings Product Template</h4> <h4>Retrieve Savings Product Template</h4>
@@ -7533,17 +7539,27 @@ Content-Type: application/json
<code class="method-response"> <code class="method-response">
{ {
"currency": { "currency": {
"code": "", "code": "USD",
"name": "", "name": "US Dollar",
"decimalPlaces": 0, "decimalPlaces": 2,
"displaySymbol": "", "displaySymbol": "$",
"nameCode": "", "nameCode": "currency.USD",
"displayLabel": " []" "displayLabel": "US Dollar ($)"
}, },
"interestRatePeriodFrequencyType": { "interestCompoundingPeriodType": {
"id": 3, "id": 1,
"code": "savings.interest.rate.periodFrequencyType.years", "code": "savings.interest.period.savingsCompoundingInterestPeriodType.daily",
"value": "Per year" "value": "Daily"
},
"interestCalculationType": {
"id": 1,
"code": "savingsInterestCalculationType.dailybalance",
"value": "Daily Balance"
},
"interestCalculationDaysInYearType": {
"id": 365,
"code": "savingsInterestCalculationDaysInYearType.days365",
"value": "365 Days"
}, },
"currencyOptions": [ "currencyOptions": [
{ {
@@ -7555,37 +7571,91 @@ Content-Type: application/json
"displayLabel": "US Dollar ($)" "displayLabel": "US Dollar ($)"
} }
], ],
"interestRatePeriodFrequencyTypeOptions": [ "interestCompoundingPeriodTypeOptions": [
{
"id": 1,
"code": "savings.interest.period.savingsCompoundingInterestPeriodType.daily",
"value": "Daily"
},
{ {
"id": 2, "id": 2,
"code": "savings.interest.rate.periodFrequencyType.months", "code": "savings.interest.period.savingsCompoundingInterestPeriodType.weekly",
"value": "Per month" "value": "Weekly"
}, },
{ {
"id": 3, "id": 3,
"code": "savings.interest.rate.periodFrequencyType.years", "code": "savings.interest.period.savingsCompoundingInterestPeriodType.biweekly",
"value": "Per year" "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": [ "lockinPeriodFrequencyTypeOptions": [
{ {
"id": 0, "id": 0,
"code": "savings.lockin.periodFrequencyType.days", "code": "savings.lockin.savingsPeriodFrequencyType.days",
"value": "Days" "value": "Days"
}, },
{ {
"id": 1, "id": 1,
"code": "savings.lockin.periodFrequencyType.weeks", "code": "savings.lockin.savingsPeriodFrequencyType.weeks",
"value": "Weeks" "value": "Weeks"
}, },
{ {
"id": 2, "id": 2,
"code": "savings.lockin.periodFrequencyType.months", "code": "savings.lockin.savingsPeriodFrequencyType.months",
"value": "Months" "value": "Months"
}, },
{ {
"id": 3, "id": 3,
"code": "savings.lockin.periodFrequencyType.years", "code": "savings.lockin.savingsPeriodFrequencyType.years",
"value": "Years" "value": "Years"
} }
] ]
@@ -7600,7 +7670,10 @@ Content-Type: application/json
<h4>Create a Savings Product</h4> <h4>Create a Savings Product</h4>
<table class=matrixHeading> <table class=matrixHeading>
<tr class="matrixHeadingBG"><td><div class="mifosXHeading2">Mandatory Fields</div></td></tr> <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> </table>
<br/> <br/>
<table class=matrixHeading> <table class=matrixHeading>
@@ -7614,13 +7687,15 @@ Content-Type: application/json
Content-Type: application/json Content-Type: application/json
Request Body: Request Body:
{ {
"name": "individual savings", "name": "Passbook Savings",
"description": "An savings product offering for individuals.", "description": "Daily compounding using Daily Balance, 5% per year, 365 days in year",
"currencyCode": "USD", "currencyCode": "USD",
"digitsAfterDecimal": 2, "digitsAfterDecimal": 2,
"locale": "en", "locale": "en",
"interestRate": "5.65", "nominalAnnualInterestRate": "5.0",
"interestRatePeriodFrequencyType": 2 "interestCompoundingPeriodType": 1,
"interestCalculationType": 1,
"interestCalculationDaysInYearType": "365"
} }
</code> </code>
<code class="method-response"> <code class="method-response">
@@ -7647,8 +7722,8 @@ Request Body:
<code class="method-response"> <code class="method-response">
{ {
"id": 1, "id": 1,
"name": "individual savings", "name": "Passbook Savings",
"description": "An savings product offering for individuals. (updated)", "description": "Daily compounding using Daily Balance, 5% per year, 365 days in year",
"currency": { "currency": {
"code": "USD", "code": "USD",
"name": "US Dollar", "name": "US Dollar",
@@ -7657,13 +7732,23 @@ Request Body:
"nameCode": "currency.USD", "nameCode": "currency.USD",
"displayLabel": "US Dollar ($)" "displayLabel": "US Dollar ($)"
}, },
"interestRate": 5.73, "nominalAnnualInterestRate": 5,
"interestRatePeriodFrequencyType": { "interestCompoundingPeriodType": {
"id": 2, "id": 1,
"code": "savings.interest.rate.periodFrequencyType.months", "code": "savings.interest.period.savingsCompoundingInterestPeriodType.daily",
"value": "Per month" "value": "Daily"
},
"interestCalculationType": {
"id": 1,
"code": "savingsInterestCalculationType.dailybalance",
"value": "Daily Balance"
},
"interestCalculationDaysInYearType": {
"id": 365,
"code": "savingsInterestCalculationDaysInYearType.days365",
"value": "365 Days"
} }
} }
</code> </code>
</div> </div>
</div> </div>
@@ -7679,7 +7764,7 @@ Request Body:
Content-Type: application/json Content-Type: application/json
Request Body: Request Body:
{ {
"description": "An savings product offering for individuals. (updated)", "description": "Passbook Savings Lite.",
"locale": "en", "locale": "en",
"interestRate": "5.73" "interestRate": "5.73"
} }
@@ -7688,7 +7773,7 @@ Request Body:
{ {
"resourceId": 1, "resourceId": 1,
"changes": { "changes": {
"description": "An savings product offering for individuals. (updated)", "description": "Passbook Savings Lite.",
"interestRate": 5.73, "interestRate": 5.73,
"locale": "en" "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-declaration">GET https://Domain Name/api/v1/savingsproducts</code>
<code class="method-response"> <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, "id": 1,
"name": "individual savings", "code": "savings.interest.period.savingsCompoundingInterestPeriodType.daily",
"description": "An savings product offering for individuals. (updated)", "value": "Daily"
"currency": { },
"code": "USD", "interestCalculationType": {
"name": "US Dollar", "id": 1,
"decimalPlaces": 2, "code": "savingsInterestCalculationType.dailybalance",
"displaySymbol": "$", "value": "Daily Balance"
"nameCode": "currency.USD", },
"displayLabel": "US Dollar ($)" "interestCalculationDaysInYearType": {
}, "id": 365,
"interestRate": 9.85, "code": "savingsInterestCalculationDaysInYearType.days365",
"interestRatePeriodFrequencyType": { "value": "365 Days"
"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> </code>
</div> </div>
@@ -7793,11 +7881,17 @@ Content-Type: application/json
<tr class=alt><td>activationDate</td></tr> <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><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 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</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 class=alt><td>interestCompoundingPeriodType</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><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 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> <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"> <code class="method-response">
{ {
"clientId": 1, "clientId": 1,
"clientName": "Client A AB", "clientName": "John Doe",
"savingsProductId": 1, "savingsProductId": 3,
"savingsProductName": "First", "savingsProductName": "Passbook Savings",
"currency": { "currency": {
"code": "USD", "code": "USD",
"name": "US Dollar", "name": "US Dollar",
@@ -7867,56 +7961,121 @@ Content-Type: application/json
"nameCode": "currency.USD", "nameCode": "currency.USD",
"displayLabel": "US Dollar ($)" "displayLabel": "US Dollar ($)"
}, },
"interestRate": 12, "nominalAnnualInterestRate": 5,
"interestRatePeriodFrequencyType": { "interestCompoundingPeriodType": {
"id": 3, "id": 1,
"code": "savings.interest.rate.periodFrequencyType.years", "code": "savings.interest.period.savingsCompoundingInterestPeriodType.daily",
"value": "Per year" "value": "Daily"
}, },
"minRequiredOpeningBalance": 1000, "interestCalculationType": {
"lockinPeriodFrequency": 3, "id": 1,
"lockinPeriodFrequencyType": { "code": "savingsInterestCalculationType.dailybalance",
"id": 2, "value": "Daily Balance"
"code": "savings.interest.rate.periodFrequencyType.months", },
"value": "Per month" "interestCalculationDaysInYearType": {
"id": 365,
"code": "savingsInterestCalculationDaysInYearType.days365",
"value": "365 Days"
}, },
"productOptions": [ "productOptions": [
{ {
"id": 1, "id": 1,
"name": "First" "name": "01-Compounding Daily"
} },
],
"interestRatePeriodFrequencyTypeOptions": [
{ {
"id": 2, "id": 2,
"code": "savings.interest.rate.periodFrequencyType.months", "name": "02-Compounding Monthly"
"value": "Per month"
}, },
{ {
"id": 3, "id": 3,
"code": "savings.interest.rate.periodFrequencyType.years", "name": "Passbook Savings"
"value": "Per year" }
],
"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": [ "lockinPeriodFrequencyTypeOptions": [
{ {
"id": 0, "id": 0,
"code": "savings.lockin.periodFrequencyType.days", "code": "savings.lockin.savingsPeriodFrequencyType.days",
"value": "Days" "value": "Days"
}, },
{ {
"id": 1, "id": 1,
"code": "savings.lockin.periodFrequencyType.weeks", "code": "savings.lockin.savingsPeriodFrequencyType.weeks",
"value": "Weeks" "value": "Weeks"
}, },
{ {
"id": 2, "id": 2,
"code": "savings.lockin.periodFrequencyType.months", "code": "savings.lockin.savingsPeriodFrequencyType.months",
"value": "Months" "value": "Months"
}, },
{ {
"id": 3, "id": 3,
"code": "savings.lockin.periodFrequencyType.years", "code": "savings.lockin.savingsPeriodFrequencyType.years",
"value": "Years" "value": "Years"
} }
] ]
@@ -7932,7 +8091,8 @@ Content-Type: application/json
<br/> <br/>
<table class=matrixHeading> <table class=matrixHeading>
<tr class="matrixHeadingBG"><td><div class="mifosXHeading2">Mandatory Fields</div></td></tr> <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> </table>
<br/> <br/>
<table class=matrixHeading> <table class=matrixHeading>
@@ -7942,7 +8102,7 @@ Content-Type: application/json
<br/> <br/>
<table class=matrixHeading> <table class=matrixHeading>
<tr class="matrixHeadingBG"><td><div class="mifosXHeading2">Inherited from Product (if not provided)</div></td></tr> <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> </table>
</div> </div>
<div class="method-example"> <div class="method-example">
@@ -8028,6 +8188,33 @@ Request Body:
</div> </div>
</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> <a id="savingsaccounts_list" name="savingsaccounts_list" class="old-syle-anchor">&nbsp;</a>
<div class="method-section"> <div class="method-section">
<div class="method-description"> <div class="method-description">
@@ -12290,6 +12477,14 @@ GET https://DomainName/api/v1/search?query=000000111
<td></td> <td></td>
</tr> </tr>
<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><a href="#savingsaccounts_transactions">Savings Transactions</a></td>
<td>savingsaccounts/{accountId}/transactions?command=deposit</td> <td>savingsaccounts/{accountId}/transactions?command=deposit</td>
<td><a href="#savingsaccounts_deposit">Make a Deposit</a></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>
<td></td> <td></td>
</tr> </tr>
<tr class="alt"> <tr>
<td></td> <td></td>
<td>savingsaccounts/{accountId}/transactions?command=withdrawal</td> <td>savingsaccounts/{accountId}/transactions?command=withdrawal</td>
<td><a href="#savingsaccounts_withdrawal">Make a Withdrawal</a></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.commands.data.CommandSourceData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport; import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource; import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.RowMapper;
@@ -23,11 +22,9 @@ import org.springframework.stereotype.Service;
public class PortfolioCommandsReadPlatformServiceImpl implements PortfolioCommandsReadPlatformService { public class PortfolioCommandsReadPlatformServiceImpl implements PortfolioCommandsReadPlatformService {
private final JdbcTemplate jdbcTemplate; private final JdbcTemplate jdbcTemplate;
private final PlatformSecurityContext context;
@Autowired @Autowired
public PortfolioCommandsReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource) { public PortfolioCommandsReadPlatformServiceImpl(final TenantAwareRoutingDataSource dataSource) {
this.context = context;
this.jdbcTemplate = new JdbcTemplate(dataSource); this.jdbcTemplate = new JdbcTemplate(dataSource);
} }
@@ -53,7 +50,6 @@ public class PortfolioCommandsReadPlatformServiceImpl implements PortfolioComman
} }
} }
@Override @Override
public CommandSourceData retrieveById(final Long id) { public CommandSourceData retrieveById(final Long id) {
@@ -140,8 +140,7 @@ public class SavingsAccountsApiResource {
Collection<SavingsAccountTransactionData> transactions = null; Collection<SavingsAccountTransactionData> transactions = null;
Collection<SavingsProductData> productOptions = null; Collection<SavingsProductData> productOptions = null;
Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions = null; Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
Collection<EnumOptionData> interestPeriodTypeOptions = null;
Collection<EnumOptionData> interestCalculationTypeOptions = null; Collection<EnumOptionData> interestCalculationTypeOptions = null;
Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null; Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null; Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
@@ -166,15 +165,13 @@ public class SavingsAccountsApiResource {
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
if (settings.isTemplate()) { if (settings.isTemplate()) {
productOptions = this.savingsProductReadPlatformService.retrieveAllForLookup(); productOptions = this.savingsProductReadPlatformService.retrieveAllForLookup();
interestRatePeriodFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveInterestRatePeriodFrequencyTypeOptions(); interestCompoundingPeriodTypeOptions = this.dropdownReadPlatformService.retrieveCompoundingInterestPeriodTypeOptions();
interestPeriodTypeOptions = this.dropdownReadPlatformService.retrieveInterestPeriodTypeOptions();
interestCalculationTypeOptions = this.dropdownReadPlatformService.retrieveInterestCalculationTypeOptions(); interestCalculationTypeOptions = this.dropdownReadPlatformService.retrieveInterestCalculationTypeOptions();
lockinPeriodFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveLockinPeriodFrequencyTypeOptions(); lockinPeriodFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveLockinPeriodFrequencyTypeOptions();
} }
return SavingsAccountData.withTemplateOptions(savingsAccount, productOptions, interestRatePeriodFrequencyTypeOptions, return SavingsAccountData.withTemplateOptions(savingsAccount, productOptions, interestCompoundingPeriodTypeOptions,
interestPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, transactions);
lockinPeriodFrequencyTypeOptions, transactions);
} }
@PUT @PUT
@@ -195,7 +192,7 @@ public class SavingsAccountsApiResource {
@Path("{accountId}") @Path("{accountId}")
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ 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 String apiRequestBodyAsJson) {
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(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 descriptionParamName = "description";
public static final String currencyCodeParamName = "currencyCode"; public static final String currencyCodeParamName = "currencyCode";
public static final String digitsAfterDecimalParamName = "digitsAfterDecimal"; public static final String digitsAfterDecimalParamName = "digitsAfterDecimal";
public static final String interestRateParamName = "interestRate"; public static final String nominalAnnualInterestRateParamName = "nominalAnnualInterestRate";
public static final String interestRatePeriodFrequencyTypeParamName = "interestRatePeriodFrequencyType";
public static final String interestPeriodTypeParamName = "interestPeriodType"; public static final String interestCompoundingPeriodTypeParamName = "interestCompoundingPeriodType";
public static final String interestCalculationTypeParamName = "interestCalculationType"; public static final String interestCalculationTypeParamName = "interestCalculationType";
public static final String interestCalculationDaysInYearTypeParamName = "interestCalculationDaysInYearType"; public static final String interestCalculationDaysInYearTypeParamName = "interestCalculationDaysInYearType";
public static final String minRequiredOpeningBalanceParamName = "minRequiredOpeningBalance"; public static final String minRequiredOpeningBalanceParamName = "minRequiredOpeningBalance";
@@ -45,10 +45,9 @@ public class SavingsApiConstants {
public static final String transactionAmountParamName = "transactionAmount"; public static final String transactionAmountParamName = "transactionAmount";
public static final Set<String> SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName, public static final Set<String> SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
nameParamName, descriptionParamName, currencyCodeParamName, digitsAfterDecimalParamName, interestRateParamName, nameParamName, descriptionParamName, currencyCodeParamName, digitsAfterDecimalParamName, nominalAnnualInterestRateParamName,
interestRatePeriodFrequencyTypeParamName, interestPeriodTypeParamName, interestCalculationTypeParamName, interestCompoundingPeriodTypeParamName, interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName,
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName));
lockinPeriodFrequencyTypeParamName));
/** /**
* These parameters will match the class level parameters of * These parameters will match the class level parameters of
@@ -56,17 +55,16 @@ public class SavingsApiConstants {
* parameters to match those of request parameters. * parameters to match those of request parameters.
*/ */
public static final Set<String> SAVINGS_PRODUCT_RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(idParamName, public static final Set<String> SAVINGS_PRODUCT_RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(idParamName,
nameParamName, descriptionParamName, "currency", digitsAfterDecimalParamName, interestRateParamName, nameParamName, descriptionParamName, "currency", digitsAfterDecimalParamName, nominalAnnualInterestRateParamName,
interestRatePeriodFrequencyTypeParamName, interestPeriodTypeParamName, interestCalculationTypeParamName, interestCompoundingPeriodTypeParamName, interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName,
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName, "currencyOptions",
lockinPeriodFrequencyTypeParamName, "currencyOptions", "interestRatePeriodFrequencyTypeOptions", "interestRatePeriodFrequencyTypeOptions", "lockinPeriodFrequencyTypeOptions"));
"lockinPeriodFrequencyTypeOptions"));
public static final Set<String> SAVINGS_ACCOUNT_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName, public static final Set<String> SAVINGS_ACCOUNT_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
dateFormatParamName, accountNoParamName, externalIdParamName, clientIdParamName, groupIdParamName, productIdParamName, dateFormatParamName, accountNoParamName, externalIdParamName, clientIdParamName, groupIdParamName, productIdParamName,
activeParamName, activationDateParamName, interestRateParamName, interestRatePeriodFrequencyTypeParamName, activeParamName, activationDateParamName, nominalAnnualInterestRateParamName, interestCompoundingPeriodTypeParamName,
interestPeriodTypeParamName, interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName, interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName,
minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName)); lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName));
/** /**
* These parameters will match the class level parameters of * 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, public static final Set<String> SAVINGS_ACCOUNT_RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(idParamName,
accountNoParamName, externalIdParamName, statusParamName, activationDateParamName, clientIdParamName, "clientName", accountNoParamName, externalIdParamName, statusParamName, activationDateParamName, clientIdParamName, "clientName",
groupIdParamName, "groupName", "savingsProductId", "savingsProductName", "currency", interestRateParamName, groupIdParamName, "groupName", "savingsProductId", "savingsProductName", "currency", nominalAnnualInterestRateParamName,
interestRatePeriodFrequencyTypeParamName, "annualInterestRate", interestPeriodTypeParamName, interestCalculationTypeParamName, interestCompoundingPeriodTypeParamName, interestCalculationTypeParamName,
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName,
lockinPeriodFrequencyTypeParamName, "summary", "transactions", "productOptions", "interestRatePeriodFrequencyTypeOptions", lockinPeriodFrequencyTypeParamName, "summary", "transactions", "productOptions", "interestRatePeriodFrequencyTypeOptions",
"lockinPeriodFrequencyTypeOptions")); "lockinPeriodFrequencyTypeOptions"));
@@ -5,6 +5,7 @@
*/ */
package org.mifosplatform.portfolio.savings.api; package org.mifosplatform.portfolio.savings.api;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import javax.ws.rs.Consumes; 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.data.CurrencyData;
import org.mifosplatform.organisation.monetary.service.CurrencyReadPlatformService; import org.mifosplatform.organisation.monetary.service.CurrencyReadPlatformService;
import org.mifosplatform.portfolio.savings.data.SavingsProductData; 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.SavingsInterestCalculationDaysInYearType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationType; 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.SavingsDropdownReadPlatformService;
import org.mifosplatform.portfolio.savings.service.SavingsEnumerations; import org.mifosplatform.portfolio.savings.service.SavingsEnumerations;
import org.mifosplatform.portfolio.savings.service.SavingsProductReadPlatformService; import org.mifosplatform.portfolio.savings.service.SavingsProductReadPlatformService;
@@ -146,22 +146,23 @@ public class SavingsProductsApiResource {
private SavingsProductData handleTemplateRelatedData(final SavingsProductData savingsProduct) { private SavingsProductData handleTemplateRelatedData(final SavingsProductData savingsProduct) {
final EnumOptionData interestRatePeriodFrequencyType = SavingsEnumerations final EnumOptionData interestPeriodType = SavingsEnumerations
.interestRatePeriodFrequencyType(SavingsPeriodFrequencyType.YEARS); .compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.DAILY);
final EnumOptionData interestPeriodType = SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.MONTHLY);
final EnumOptionData interestCalculationType = SavingsEnumerations final EnumOptionData interestCalculationType = SavingsEnumerations
.interestCalculationType(SavingsInterestCalculationType.AVERAGE_DAILY_BALANCE); .interestCalculationType(SavingsInterestCalculationType.DAILY_BALANCE);
final EnumOptionData interestCalculationDaysInYearType = SavingsEnumerations final EnumOptionData interestCalculationDaysInYearType = SavingsEnumerations
.interestCalculationDaysInYearType(SavingsInterestCalculationDaysInYearType.DAYS_365); .interestCalculationDaysInYearType(SavingsInterestCalculationDaysInYearType.DAYS_365);
CurrencyData currency = CurrencyData.blank();
final Collection<CurrencyData> currencyOptions = this.currencyReadPlatformService.retrieveAllowedCurrencies(); final Collection<CurrencyData> currencyOptions = this.currencyReadPlatformService.retrieveAllowedCurrencies();
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions = this.dropdownReadPlatformService if (currencyOptions.size() == 1) {
.retrieveInterestRatePeriodFrequencyTypeOptions(); 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 final Collection<EnumOptionData> interestCalculationTypeOptions = this.dropdownReadPlatformService
.retrieveInterestCalculationTypeOptions(); .retrieveInterestCalculationTypeOptions();
@@ -174,14 +175,12 @@ public class SavingsProductsApiResource {
SavingsProductData savingsProductToReturn = null; SavingsProductData savingsProductToReturn = null;
if (savingsProduct != null) { if (savingsProduct != null) {
savingsProductToReturn = SavingsProductData.withTemplate(savingsProduct, currencyOptions, savingsProductToReturn = SavingsProductData.withTemplate(savingsProduct, currencyOptions, interestPeriodTypeOptions,
interestRatePeriodFrequencyTypeOptions, interestPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions);
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions);
} else { } else {
savingsProductToReturn = SavingsProductData.template(CurrencyData.blank(), interestRatePeriodFrequencyType, interestPeriodType, savingsProductToReturn = SavingsProductData.template(currency, interestPeriodType, interestCalculationType,
interestCalculationType, interestCalculationDaysInYearType, currencyOptions, interestRatePeriodFrequencyTypeOptions, interestCalculationDaysInYearType, currencyOptions, interestPeriodTypeOptions, interestCalculationTypeOptions,
interestPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions);
lockinPeriodFrequencyTypeOptions);
} }
return savingsProductToReturn; return savingsProductToReturn;
@@ -30,10 +30,8 @@ public class SavingsAccountData {
private final Long savingsProductId; private final Long savingsProductId;
private final String savingsProductName; private final String savingsProductName;
private final CurrencyData currency; private final CurrencyData currency;
private final BigDecimal interestRate; private final BigDecimal nominalAnnualInterestRate;
private final EnumOptionData interestRatePeriodFrequencyType; private final EnumOptionData interestCompoundingPeriodType;
private final BigDecimal annualInterestRate;
private final EnumOptionData interestPeriodType;
private final EnumOptionData interestCalculationType; private final EnumOptionData interestCalculationType;
private final EnumOptionData interestCalculationDaysInYearType; private final EnumOptionData interestCalculationDaysInYearType;
private final BigDecimal minRequiredOpeningBalance; private final BigDecimal minRequiredOpeningBalance;
@@ -46,8 +44,7 @@ public class SavingsAccountData {
// template // template
private final Collection<SavingsProductData> productOptions; private final Collection<SavingsProductData> productOptions;
private final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions; private final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions;
private final Collection<EnumOptionData> interestPeriodTypeOptions;
private final Collection<EnumOptionData> interestCalculationTypeOptions; private final Collection<EnumOptionData> interestCalculationTypeOptions;
private final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions; private final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions;
private final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions; 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, 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 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 Long clientId, final String clientName, final Long productId, final String productName, final CurrencyData currency,
final BigDecimal interestRate, final EnumOptionData interestRatePeriodFrequencyType, final BigDecimal annualInterestRate, final BigDecimal interestRate, final EnumOptionData interestCompoundingPeriodType,
final EnumOptionData interestPeriodType, final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType,
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final SavingsAccountSummaryData summary) { final EnumOptionData lockinPeriodFrequencyType, final SavingsAccountSummaryData summary) {
final Collection<SavingsProductData> productOptions = null; final Collection<SavingsProductData> productOptions = null;
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions = null; final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
final Collection<EnumOptionData> interestPeriodTypeOptions = null;
final Collection<EnumOptionData> interestCalculationTypeOptions = null; final Collection<EnumOptionData> interestCalculationTypeOptions = null;
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null; final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null; final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
final Collection<SavingsAccountTransactionData> transactions = null; final Collection<SavingsAccountTransactionData> transactions = null;
return new SavingsAccountData(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName, return new SavingsAccountData(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName,
productId, productName, currency, interestRate, interestRatePeriodFrequencyType, annualInterestRate, interestPeriodType, productId, productName, currency, interestRate, interestCompoundingPeriodType, interestCalculationType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, summary,
lockinPeriodFrequencyType, summary, productOptions, interestRatePeriodFrequencyTypeOptions, interestPeriodTypeOptions, productOptions, interestCompoundingPeriodTypeOptions, interestCalculationTypeOptions,
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, transactions); interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, transactions);
} }
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account, public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
final Collection<SavingsProductData> productOptions, final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions, final Collection<SavingsProductData> productOptions, final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
final Collection<EnumOptionData> interestPeriodTypeOptions, final Collection<EnumOptionData> interestCalculationTypeOptions, final Collection<EnumOptionData> interestCalculationTypeOptions,
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions, final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<SavingsAccountTransactionData> transactions) { final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<SavingsAccountTransactionData> transactions) {
return new SavingsAccountData(account.id, account.accountNo, account.externalId, account.status, account.activationDate, return new SavingsAccountData(account.id, account.accountNo, account.externalId, account.status, account.activationDate,
account.groupId, account.groupName, account.clientId, account.clientName, account.savingsProductId, account.groupId, account.groupName, account.clientId, account.clientName, account.savingsProductId,
account.savingsProductName, account.currency, account.interestRate, account.interestRatePeriodFrequencyType, account.savingsProductName, account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType,
account.annualInterestRate, account.interestPeriodType, account.interestCalculationType, account.interestCalculationType, account.interestCalculationDaysInYearType, account.minRequiredOpeningBalance,
account.interestCalculationDaysInYearType, account.minRequiredOpeningBalance, account.lockinPeriodFrequency, account.lockinPeriodFrequency, account.lockinPeriodFrequencyType, account.summary, productOptions,
account.lockinPeriodFrequencyType, account.summary, productOptions, interestRatePeriodFrequencyTypeOptions, interestCompoundingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
interestPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
lockinPeriodFrequencyTypeOptions, transactions); lockinPeriodFrequencyTypeOptions, transactions);
} }
@@ -102,9 +97,7 @@ public class SavingsAccountData {
final Long productId = null; final Long productId = null;
final String productName = null; final String productName = null;
final CurrencyData currency = null; final CurrencyData currency = null;
final BigDecimal interestRate = null; final BigDecimal nominalAnnualInterestRate = null;
final EnumOptionData interestRatePeriodFrequencyType = null;
final BigDecimal annualInterestRate = null;
final EnumOptionData interestPeriodType = null; final EnumOptionData interestPeriodType = null;
final EnumOptionData interestCalculationType = null; final EnumOptionData interestCalculationType = null;
final EnumOptionData interestCalculationDaysInYearType = null; final EnumOptionData interestCalculationDaysInYearType = null;
@@ -114,29 +107,27 @@ public class SavingsAccountData {
final SavingsAccountSummaryData summary = null; final SavingsAccountSummaryData summary = null;
final Collection<SavingsProductData> productOptions = null; final Collection<SavingsProductData> productOptions = null;
final Collection<CurrencyData> currencyOptions = null; final Collection<CurrencyData> currencyOptions = null;
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions = null; final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
final Collection<EnumOptionData> interestPeriodTypeOptions = null;
final Collection<EnumOptionData> interestCalculationTypeOptions = null; final Collection<EnumOptionData> interestCalculationTypeOptions = null;
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null; final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null; final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
final Collection<SavingsAccountTransactionData> transactions = null; final Collection<SavingsAccountTransactionData> transactions = null;
return new SavingsAccountData(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName, return new SavingsAccountData(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName,
productId, productName, currency, interestRate, interestRatePeriodFrequencyType, annualInterestRate, interestPeriodType, productId, productName, currency, nominalAnnualInterestRate, interestPeriodType, interestCalculationType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, summary,
lockinPeriodFrequencyType, summary, productOptions, interestRatePeriodFrequencyTypeOptions, interestPeriodTypeOptions, productOptions, interestCompoundingPeriodTypeOptions, interestCalculationTypeOptions,
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, transactions); interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, transactions);
} }
private SavingsAccountData(final Long id, final String accountNo, final String externalId, final SavingsAccountStatusEnumData status, 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 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 Long productId, final String productName, final CurrencyData currency, final BigDecimal nominalAnnualInterestRate,
final EnumOptionData interestRatePeriodFrequencyType, final BigDecimal annualInterestRate,
final EnumOptionData interestPeriodType, final EnumOptionData interestCalculationType, final EnumOptionData interestPeriodType, final EnumOptionData interestCalculationType,
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final SavingsAccountSummaryData summary, final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final SavingsAccountSummaryData summary,
final Collection<SavingsProductData> productOptions, final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions, final Collection<SavingsProductData> productOptions, final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
final Collection<EnumOptionData> interestPeriodTypeOptions, final Collection<EnumOptionData> interestCalculationTypeOptions, final Collection<EnumOptionData> interestCalculationTypeOptions,
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions, final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<SavingsAccountTransactionData> transactions) { final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<SavingsAccountTransactionData> transactions) {
this.id = id; this.id = id;
@@ -151,10 +142,8 @@ public class SavingsAccountData {
this.savingsProductId = productId; this.savingsProductId = productId;
this.savingsProductName = productName; this.savingsProductName = productName;
this.currency = currency; this.currency = currency;
this.interestRate = interestRate; this.nominalAnnualInterestRate = nominalAnnualInterestRate;
this.interestRatePeriodFrequencyType = interestRatePeriodFrequencyType; this.interestCompoundingPeriodType = interestPeriodType;
this.annualInterestRate = annualInterestRate;
this.interestPeriodType = interestPeriodType;
this.interestCalculationType = interestCalculationType; this.interestCalculationType = interestCalculationType;
this.interestCalculationDaysInYearType = interestCalculationDaysInYearType; this.interestCalculationDaysInYearType = interestCalculationDaysInYearType;
this.minRequiredOpeningBalance = minRequiredOpeningBalance; this.minRequiredOpeningBalance = minRequiredOpeningBalance;
@@ -163,8 +152,7 @@ public class SavingsAccountData {
this.summary = summary; this.summary = summary;
this.productOptions = productOptions; this.productOptions = productOptions;
this.interestRatePeriodFrequencyTypeOptions = interestRatePeriodFrequencyTypeOptions; this.interestCompoundingPeriodTypeOptions = interestCompoundingPeriodTypeOptions;
this.interestPeriodTypeOptions = interestPeriodTypeOptions;
this.interestCalculationTypeOptions = interestCalculationTypeOptions; this.interestCalculationTypeOptions = interestCalculationTypeOptions;
this.interestCalculationDaysInYearTypeOptions = interestCalculationDaysInYearTypeOptions; this.interestCalculationDaysInYearTypeOptions = interestCalculationDaysInYearTypeOptions;
this.lockinPeriodFrequencyTypeOptions = lockinPeriodFrequencyTypeOptions; 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.groupIdParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationDaysInYearTypeParamName; 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.interestCalculationTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestPeriodTypeParamName; import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
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.lockinPeriodFrequencyParamName; 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.lockinPeriodFrequencyTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName; 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 static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.productIdParamName;
import java.lang.reflect.Type; import java.lang.reflect.Type;
@@ -94,20 +93,13 @@ public class SavingsAccountDataValidator {
baseDataValidator.reset().parameter(externalIdParamName).value(externalId).notExceedingLengthOf(100); baseDataValidator.reset().parameter(externalIdParamName).value(externalId).notExceedingLengthOf(100);
} }
if (fromApiJsonHelper.parameterExists(interestRateParamName, element)) { if (fromApiJsonHelper.parameterExists(nominalAnnualInterestRateParamName, element)) {
final BigDecimal interestRate = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(interestRateParamName, element); final BigDecimal interestRate = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(nominalAnnualInterestRateParamName, element);
baseDataValidator.reset().parameter(interestRateParamName).value(interestRate).notNull().zeroOrPositiveAmount(); baseDataValidator.reset().parameter(nominalAnnualInterestRateParamName).value(interestRate).notNull().zeroOrPositiveAmount();
} }
if (fromApiJsonHelper.parameterExists(interestRatePeriodFrequencyTypeParamName, element)) { final Integer interestPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(interestCompoundingPeriodTypeParamName, element);
final Integer interestRatePeriodFrequencyType = fromApiJsonHelper.extractIntegerSansLocaleNamed( baseDataValidator.reset().parameter(interestCompoundingPeriodTypeParamName).value(interestPeriodType).notNull().inMinMaxRange(1, 7);
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 interestCalculationType = fromApiJsonHelper.extractIntegerSansLocaleNamed(interestCalculationTypeParamName, element); final Integer interestCalculationType = fromApiJsonHelper.extractIntegerSansLocaleNamed(interestCalculationTypeParamName, element);
baseDataValidator.reset().parameter(interestCalculationTypeParamName).value(interestCalculationType).notNull().inMinMaxRange(1, 2); 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); baseDataValidator.reset().parameter(externalIdParamName).value(externalId).notExceedingLengthOf(100);
} }
if (fromApiJsonHelper.parameterExists(interestRateParamName, element)) { if (fromApiJsonHelper.parameterExists(nominalAnnualInterestRateParamName, element)) {
final BigDecimal interestRate = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(interestRateParamName, element); final BigDecimal interestRate = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(nominalAnnualInterestRateParamName, element);
baseDataValidator.reset().parameter(interestRateParamName).value(interestRate).notNull().zeroOrPositiveAmount(); baseDataValidator.reset().parameter(nominalAnnualInterestRateParamName).value(interestRate).notNull().zeroOrPositiveAmount();
} }
if (fromApiJsonHelper.parameterExists(interestRatePeriodFrequencyTypeParamName, element)) { if (this.fromApiJsonHelper.parameterExists(interestCompoundingPeriodTypeParamName, element)) {
final Integer interestRatePeriodFrequencyType = fromApiJsonHelper.extractIntegerSansLocaleNamed( final Integer interestPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(interestCompoundingPeriodTypeParamName, element);
interestRatePeriodFrequencyTypeParamName, element); baseDataValidator.reset().parameter(interestCompoundingPeriodTypeParamName).value(interestPeriodType).notNull().inMinMaxRange(1, 7);
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(interestCalculationTypeParamName, element)) { if (this.fromApiJsonHelper.parameterExists(interestCalculationTypeParamName, element)) {
@@ -20,9 +20,8 @@ public class SavingsProductData {
private final String name; private final String name;
private final String description; private final String description;
private final CurrencyData currency; private final CurrencyData currency;
private final BigDecimal interestRate; private final BigDecimal nominalAnnualInterestRate;
private final EnumOptionData interestRatePeriodFrequencyType; private final EnumOptionData interestCompoundingPeriodType;
private final EnumOptionData interestPeriodType;
private final EnumOptionData interestCalculationType; private final EnumOptionData interestCalculationType;
private final EnumOptionData interestCalculationDaysInYearType; private final EnumOptionData interestCalculationDaysInYearType;
private final BigDecimal minRequiredOpeningBalance; private final BigDecimal minRequiredOpeningBalance;
@@ -33,9 +32,7 @@ public class SavingsProductData {
@SuppressWarnings("unused") @SuppressWarnings("unused")
private final Collection<CurrencyData> currencyOptions; private final Collection<CurrencyData> currencyOptions;
@SuppressWarnings("unused") @SuppressWarnings("unused")
private final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions; private final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions;
@SuppressWarnings("unused")
private final Collection<EnumOptionData> interestPeriodTypeOptions;
@SuppressWarnings("unused") @SuppressWarnings("unused")
private final Collection<EnumOptionData> interestCalculationTypeOptions; private final Collection<EnumOptionData> interestCalculationTypeOptions;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@@ -43,26 +40,25 @@ public class SavingsProductData {
@SuppressWarnings("unused") @SuppressWarnings("unused")
private final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions; private final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions;
public static SavingsProductData template(final CurrencyData currency, final EnumOptionData interestRatePeriodFrequencyType, public static SavingsProductData template(final CurrencyData currency, final EnumOptionData interestCompoundingPeriodType,
final EnumOptionData interestPeriodType, final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType,
final EnumOptionData interestCalculationDaysInYearType, final Collection<CurrencyData> currencyOptions, final Collection<CurrencyData> currencyOptions, final Collection<EnumOptionData> interestPeriodTypeOptions,
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions, final Collection<EnumOptionData> interestCalculationTypeOptions,
final Collection<EnumOptionData> interestPeriodTypeOptions, final Collection<EnumOptionData> interestCalculationTypeOptions,
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions, final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions) { final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions) {
final Long id = null; final Long id = null;
final String name = null; final String name = null;
final String description = null; final String description = null;
final BigDecimal interestRate = null; final BigDecimal nominalAnnualInterestRate = null;
final BigDecimal minRequiredOpeningBalance = null; final BigDecimal minRequiredOpeningBalance = null;
final Integer lockinPeriodFrequency = null; final Integer lockinPeriodFrequency = null;
final EnumOptionData lockinPeriodFrequencyType = 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, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType, currencyOptions, interestRatePeriodFrequencyTypeOptions, interestPeriodTypeOptions, lockinPeriodFrequencyType, currencyOptions, interestPeriodTypeOptions, interestCalculationTypeOptions,
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions); interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions);
} }
/** /**
@@ -70,45 +66,41 @@ public class SavingsProductData {
* {@link SavingsProductData} data with further template data for dropdowns. * {@link SavingsProductData} data with further template data for dropdowns.
*/ */
public static SavingsProductData withTemplate(final SavingsProductData existingProduct, final Collection<CurrencyData> currencyOptions, 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> interestPeriodTypeOptions, final Collection<EnumOptionData> interestCalculationTypeOptions,
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions, final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions) { final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions) {
return new SavingsProductData(existingProduct.id, existingProduct.name, existingProduct.description, existingProduct.currency, 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.interestCalculationType, existingProduct.interestCalculationDaysInYearType,
existingProduct.minRequiredOpeningBalance, existingProduct.lockinPeriodFrequency, existingProduct.minRequiredOpeningBalance, existingProduct.lockinPeriodFrequency,
existingProduct.lockinPeriodFrequencyType, currencyOptions, interestRatePeriodFrequencyTypeOptions, existingProduct.lockinPeriodFrequencyType, currencyOptions, interestPeriodTypeOptions, interestCalculationTypeOptions,
interestPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions);
lockinPeriodFrequencyTypeOptions);
} }
public static SavingsProductData instance(final Long id, final String name, final String description, final CurrencyData currency, 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 EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType,
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType) { final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType) {
final Collection<CurrencyData> currencyOptions = null; final Collection<CurrencyData> currencyOptions = null;
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions = null;
final Collection<EnumOptionData> interestPeriodTypeOptions = null; final Collection<EnumOptionData> interestPeriodTypeOptions = null;
final Collection<EnumOptionData> interestCalculationTypeOptions = null; final Collection<EnumOptionData> interestCalculationTypeOptions = null;
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null; final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = 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, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType, currencyOptions, interestRatePeriodFrequencyTypeOptions, interestPeriodTypeOptions, lockinPeriodFrequencyType, currencyOptions, interestPeriodTypeOptions, interestCalculationTypeOptions,
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions); interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions);
} }
public static SavingsProductData lookup(final Long id, final String name) { public static SavingsProductData lookup(final Long id, final String name) {
final CurrencyData currency = null; final CurrencyData currency = null;
final String description = null; final String description = null;
final BigDecimal interestRate = null; final BigDecimal nominalAnnualInterestRate = null;
final EnumOptionData interestRatePeriodFrequencyType = null; final EnumOptionData interestCompoundingPeriodType = null;
final EnumOptionData interestPeriodType = null;
final EnumOptionData interestCalculationType = null; final EnumOptionData interestCalculationType = null;
final EnumOptionData interestCalculationDaysInYearType = null; final EnumOptionData interestCalculationDaysInYearType = null;
final BigDecimal minRequiredOpeningBalance = null; final BigDecimal minRequiredOpeningBalance = null;
@@ -116,24 +108,22 @@ public class SavingsProductData {
final EnumOptionData lockinPeriodFrequencyType = null; final EnumOptionData lockinPeriodFrequencyType = null;
final Collection<CurrencyData> currencyOptions = null; final Collection<CurrencyData> currencyOptions = null;
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions = null;
final Collection<EnumOptionData> interestPeriodTypeOptions = null; final Collection<EnumOptionData> interestPeriodTypeOptions = null;
final Collection<EnumOptionData> interestCalculationTypeOptions = null; final Collection<EnumOptionData> interestCalculationTypeOptions = null;
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null; final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = 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, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType, currencyOptions, interestRatePeriodFrequencyTypeOptions, interestPeriodTypeOptions, lockinPeriodFrequencyType, currencyOptions, interestPeriodTypeOptions, interestCalculationTypeOptions,
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions); interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions);
} }
private SavingsProductData(final Long id, final String name, final String description, final CurrencyData currency, 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 EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType,
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency, final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
final EnumOptionData lockinPeriodFrequencyType, final Collection<CurrencyData> currencyOptions, final EnumOptionData lockinPeriodFrequencyType, final Collection<CurrencyData> currencyOptions,
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions,
final Collection<EnumOptionData> interestPeriodTypeOptions, final Collection<EnumOptionData> interestCalculationTypeOptions, final Collection<EnumOptionData> interestPeriodTypeOptions, final Collection<EnumOptionData> interestCalculationTypeOptions,
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions, final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions) { final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions) {
@@ -141,9 +131,8 @@ public class SavingsProductData {
this.name = name; this.name = name;
this.description = description; this.description = description;
this.currency = currency; this.currency = currency;
this.interestRate = interestRate; this.nominalAnnualInterestRate = nominalAnnualInterestRate;
this.interestRatePeriodFrequencyType = interestRatePeriodFrequencyType; this.interestCompoundingPeriodType = interestCompoundingPeriodType;
this.interestPeriodType = interestPeriodType;
this.interestCalculationType = interestCalculationType; this.interestCalculationType = interestCalculationType;
this.interestCalculationDaysInYearType = interestCalculationDaysInYearType; this.interestCalculationDaysInYearType = interestCalculationDaysInYearType;
this.minRequiredOpeningBalance = minRequiredOpeningBalance; this.minRequiredOpeningBalance = minRequiredOpeningBalance;
@@ -151,8 +140,7 @@ public class SavingsProductData {
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType; this.lockinPeriodFrequencyType = lockinPeriodFrequencyType;
this.currencyOptions = currencyOptions; this.currencyOptions = currencyOptions;
this.interestRatePeriodFrequencyTypeOptions = interestRatePeriodFrequencyTypeOptions; this.interestCompoundingPeriodTypeOptions = interestPeriodTypeOptions;
this.interestPeriodTypeOptions = interestPeriodTypeOptions;
this.interestCalculationTypeOptions = interestCalculationTypeOptions; this.interestCalculationTypeOptions = interestCalculationTypeOptions;
this.interestCalculationDaysInYearTypeOptions = interestCalculationDaysInYearTypeOptions; this.interestCalculationDaysInYearTypeOptions = interestCalculationDaysInYearTypeOptions;
this.lockinPeriodFrequencyTypeOptions = lockinPeriodFrequencyTypeOptions; 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.digitsAfterDecimalParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationDaysInYearTypeParamName; 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.interestCalculationTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestPeriodTypeParamName; import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
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.lockinPeriodFrequencyParamName; 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.lockinPeriodFrequencyTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName; 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.nameParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.math.BigDecimal; import java.math.BigDecimal;
@@ -67,16 +66,13 @@ public class SavingsProductDataValidator {
final Integer digitsAfterDecimal = fromApiJsonHelper.extractIntegerSansLocaleNamed(digitsAfterDecimalParamName, element); final Integer digitsAfterDecimal = fromApiJsonHelper.extractIntegerSansLocaleNamed(digitsAfterDecimalParamName, element);
baseDataValidator.reset().parameter(digitsAfterDecimalParamName).value(digitsAfterDecimal).notNull().inMinMaxRange(0, 6); baseDataValidator.reset().parameter(digitsAfterDecimalParamName).value(digitsAfterDecimal).notNull().inMinMaxRange(0, 6);
final BigDecimal interestRate = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(interestRateParamName, element); final BigDecimal interestRate = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(nominalAnnualInterestRateParamName, element);
baseDataValidator.reset().parameter(interestRateParamName).value(interestRate).notNull().zeroOrPositiveAmount(); baseDataValidator.reset().parameter(nominalAnnualInterestRateParamName).value(interestRate).notNull().zeroOrPositiveAmount();
final Integer interestRatePeriodFrequencyType = fromApiJsonHelper.extractIntegerSansLocaleNamed( final Integer interestCompoundingPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(
interestRatePeriodFrequencyTypeParamName, element); interestCompoundingPeriodTypeParamName, element);
baseDataValidator.reset().parameter(interestRatePeriodFrequencyTypeParamName).value(interestRatePeriodFrequencyType).notNull() baseDataValidator.reset().parameter(interestCompoundingPeriodTypeParamName).value(interestCompoundingPeriodType).notNull()
.inMinMaxRange(1, 3); .inMinMaxRange(1, 8);
final Integer interestPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(interestPeriodTypeParamName, element);
baseDataValidator.reset().parameter(interestPeriodTypeParamName).value(interestPeriodType).notNull().inMinMaxRange(1, 7);
final Integer interestCalculationType = fromApiJsonHelper.extractIntegerSansLocaleNamed(interestCalculationTypeParamName, element); final Integer interestCalculationType = fromApiJsonHelper.extractIntegerSansLocaleNamed(interestCalculationTypeParamName, element);
baseDataValidator.reset().parameter(interestCalculationTypeParamName).value(interestCalculationType).notNull().inMinMaxRange(1, 2); 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); baseDataValidator.reset().parameter(digitsAfterDecimalParamName).value(digitsAfterDecimal).notNull().inMinMaxRange(0, 6);
} }
if (this.fromApiJsonHelper.parameterExists(interestRateParamName, element)) { if (this.fromApiJsonHelper.parameterExists(nominalAnnualInterestRateParamName, element)) {
final BigDecimal interestRate = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(interestRateParamName, element); final BigDecimal interestRate = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(nominalAnnualInterestRateParamName, element);
baseDataValidator.reset().parameter(interestRateParamName).value(interestRate).notNull().zeroOrPositiveAmount(); baseDataValidator.reset().parameter(nominalAnnualInterestRateParamName).value(interestRate).notNull().zeroOrPositiveAmount();
} }
if (this.fromApiJsonHelper.parameterExists(interestRatePeriodFrequencyTypeParamName, element)) { if (this.fromApiJsonHelper.parameterExists(interestCompoundingPeriodTypeParamName, element)) {
final Integer interestRatePeriodFrequencyType = fromApiJsonHelper.extractIntegerSansLocaleNamed( final Integer interestCompoundingPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(
interestRatePeriodFrequencyTypeParamName, element); interestCompoundingPeriodTypeParamName, element);
baseDataValidator.reset().parameter(interestRatePeriodFrequencyTypeParamName).value(interestRatePeriodFrequencyType).notNull() baseDataValidator.reset().parameter(interestCompoundingPeriodTypeParamName).value(interestCompoundingPeriodType).notNull()
.inMinMaxRange(1, 3); .inMinMaxRange(1, 8);
}
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(interestCalculationTypeParamName, element)) { if (this.fromApiJsonHelper.parameterExists(interestCalculationTypeParamName, element)) {
@@ -201,7 +192,10 @@ public class SavingsProductDataValidator {
} }
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) { private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", if (!dataValidationErrors.isEmpty()) {
"Validation errors exist.", dataValidationErrors); } //
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.Days;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
public class InterestPeriodInterval { public class LocalDateInterval {
private final LocalDate startDate; private final LocalDate startDate;
private final LocalDate endDate; private final LocalDate endDate;
public static InterestPeriodInterval create(final LocalDate startDate, final LocalDate endDate) { public static LocalDateInterval create(final LocalDate startDate, final LocalDate endDate) {
return new InterestPeriodInterval(startDate, 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.startDate = startDate;
this.endDate = endDate; this.endDate = endDate;
} }
@@ -81,20 +81,18 @@ public class SavingsAccount extends AbstractPersistable<Long> {
@Embedded @Embedded
private MonetaryCurrency currency; private MonetaryCurrency currency;
@Column(name = "nominal_interest_rate_per_period", scale = 6, precision = 19, nullable = false) @Column(name = "nominal_annual_interest_rate", scale = 6, precision = 19, nullable = false)
private BigDecimal interestRate; private BigDecimal nominalAnnualInterestRate;
@Column(name = "nominal_interest_rate_period_frequency_enum", nullable = false)
private Integer interestRatePeriodFrequencyType;
/** /**
* The interest period is the span of time at the end of which savings in a * The interest period is the span of time at the end of which savings in a
* client’s account earn interest. * 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) @Column(name = "interest_compounding_period_enum", nullable = false)
private Integer interestPeriodType; private Integer interestCompoundingPeriodType;
/** /**
* A value from the {@link SavingsInterestCalculationType} enumeration. * 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) @Column(name = "interest_calculation_days_in_year_type_enum", nullable = false)
private Integer interestCalculationDaysInYearType; 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) @Column(name = "min_required_opening_balance", scale = 6, precision = 19, nullable = false)
private BigDecimal minRequiredOpeningBalance; 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, public static SavingsAccount createNewAccount(final Client client, final Group group, final SavingsProduct product,
final String accountNo, final String externalId, final BigDecimal interestRate, final String accountNo, final String externalId, final BigDecimal interestRate,
final PeriodFrequencyType interestRatePeriodFrequencyType, final BigDecimal annualInterestRate, final SavingsCompoundingInterestPeriodType interestPeriodType, final SavingsInterestCalculationType interestCalculationType,
final SavingsInterestPeriodType interestPeriodType, final SavingsInterestCalculationType interestCalculationType,
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
final Integer lockinPeriodFrequency, final PeriodFrequencyType lockinPeriodFrequencyType) { final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType) {
final SavingsAccountStatusType status = SavingsAccountStatusType.UNACTIVATED; final SavingsAccountStatusType status = SavingsAccountStatusType.UNACTIVATED;
final LocalDate activationDate = null; final LocalDate activationDate = null;
return new SavingsAccount(client, group, product, accountNo, externalId, status, activationDate, interestRate, return new SavingsAccount(client, group, product, accountNo, externalId, status, activationDate, interestRate, interestPeriodType,
interestRatePeriodFrequencyType, annualInterestRate, interestPeriodType, interestCalculationType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType); lockinPeriodFrequencyType);
} }
private SavingsAccount(final Client client, final Group group, final SavingsProduct product, final String accountNo, 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 String externalId, final SavingsAccountStatusType status, final LocalDate activationDate, final BigDecimal interestRate,
final PeriodFrequencyType interestRatePeriodFrequencyType, final BigDecimal annualInterestRate, final SavingsCompoundingInterestPeriodType interestPeriodType, final SavingsInterestCalculationType interestCalculationType,
final SavingsInterestPeriodType interestPeriodType, final SavingsInterestCalculationType interestCalculationType,
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
final Integer lockinPeriodFrequency, final PeriodFrequencyType lockinPeriodFrequencyType) { final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType) {
this.client = client; this.client = client;
this.group = group; this.group = group;
this.product = product; this.product = product;
@@ -182,10 +175,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
if (activationDate != null) { if (activationDate != null) {
this.activationDate = activationDate.toDate(); this.activationDate = activationDate.toDate();
} }
this.interestRate = interestRate; this.nominalAnnualInterestRate = interestRate;
this.interestRatePeriodFrequencyType = interestRatePeriodFrequencyType.getValue(); this.interestCompoundingPeriodType = interestPeriodType.getValue();
this.annualInterestRate = annualInterestRate;
this.interestPeriodType = interestPeriodType.getValue();
this.interestCalculationType = interestCalculationType.getValue(); this.interestCalculationType = interestCalculationType.getValue();
this.interestCalculationDaysInYearType = interestCalculationDaysInYearType.getValue(); this.interestCalculationDaysInYearType = interestCalculationDaysInYearType.getValue();
this.minRequiredOpeningBalance = minRequiredOpeningBalance; this.minRequiredOpeningBalance = minRequiredOpeningBalance;
@@ -281,47 +272,112 @@ public class SavingsAccount extends AbstractPersistable<Long> {
* Interest calculation is performed on-the-fly over all account * Interest calculation is performed on-the-fly over all account
* transactions. * transactions.
*/ */
/* public void calculateInterest(final LocalDate interestCalculationEndDate) {
* 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() {
// no openingBalance concept supported yet but probably will to all for // no openingBalance concept supported yet but probably will to allow
// migrations. // for migrations.
final Money openingAccountBalance = Money.zero(this.currency); 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. // correct.
recalculateDailyBalances(openingAccountBalance); recalculateDailyBalances(openingAccountBalance);
// 2. determine interest periods
final SavingsInterestPeriodType interestPeriodType = SavingsInterestPeriodType.fromInt(this.interestPeriodType);
final SavingsInterestCalculationDaysInYearType daysInYearType = SavingsInterestCalculationDaysInYearType final SavingsInterestCalculationDaysInYearType daysInYearType = SavingsInterestCalculationDaysInYearType
.fromInt(this.interestCalculationDaysInYearType); .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, // determine opening balance, daily interest rate to apply, interest
this.annualInterestRate, daysInYearType); // 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, private List<InterestCompoundingPeriodSummary> determineInterestCompoundingPeriodSummaries(final Money openingAccountBalance,
final SavingsInterestPeriodType interestPeriodType) { 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 periodStartDate = activationLocalDate;
LocalDate periodEndDate = periodStartDate; 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); 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 // move periodStartDate forward to day after this period
periodStartDate = periodEndDate.plusDays(1); periodStartDate = periodEndDate.plusDays(1);
@@ -330,7 +386,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
return interestPeriods; return interestPeriods;
} }
private LocalDate determineInterestPeriodEndDateFrom(final LocalDate periodStartDate, final SavingsInterestPeriodType interestPeriodType) { private LocalDate determineInterestPeriodEndDateFrom(final LocalDate periodStartDate,
final SavingsCompoundingInterestPeriodType interestPeriodType) {
LocalDate periodEndDate = DateUtils.getLocalDateOfTenant(); LocalDate periodEndDate = DateUtils.getLocalDateOfTenant();
@@ -366,7 +423,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
periodEndDate = new DateTime().withDate(year, 12, 31).toLocalDate(); periodEndDate = new DateTime().withDate(year, 12, 31).toLocalDate();
} }
break; break;
case SEMIANNUAL: case BI_ANNUAL:
// jan 1st to 30, jul 1st to dec 31 // jan 1st to 30, jul 1st to dec 31
year = periodStartDate.getYearOfEra(); year = periodStartDate.getYearOfEra();
monthofYear = periodStartDate.getMonthOfYear(); monthofYear = periodStartDate.getMonthOfYear();
@@ -380,6 +437,10 @@ public class SavingsAccount extends AbstractPersistable<Long> {
periodEndDate = periodStartDate.monthOfYear().withMaximumValue(); periodEndDate = periodStartDate.monthOfYear().withMaximumValue();
periodEndDate = periodStartDate.dayOfMonth().withMaximumValue(); periodEndDate = periodStartDate.dayOfMonth().withMaximumValue();
break; break;
case NO_COMPOUNDING_SIMPLE_INTEREST:
periodEndDate = periodStartDate.monthOfYear().withMaximumValue();
periodEndDate = periodStartDate.dayOfMonth().withMaximumValue();
break;
} }
return periodEndDate; return periodEndDate;
@@ -403,62 +464,6 @@ public class SavingsAccount extends AbstractPersistable<Long> {
return periodsInOneYear; 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) { private void recalculateDailyBalances(final Money openingAccountBalance) {
Money runningBalance = openingAccountBalance.copy(); Money runningBalance = openingAccountBalance.copy();
@@ -537,7 +542,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions); this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
calculateInterest(); final LocalDate today = DateUtils.getLocalDateOfTenant();
calculateInterest(today);
return transaction; return transaction;
} }
@@ -614,7 +620,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions); this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
calculateInterest(); final LocalDate today = DateUtils.getLocalDateOfTenant();
calculateInterest(today);
return transaction; return transaction;
} }
@@ -683,18 +690,12 @@ public class SavingsAccount extends AbstractPersistable<Long> {
actualChanges.put(SavingsApiConstants.productIdParamName, newValue); actualChanges.put(SavingsApiConstants.productIdParamName, newValue);
} }
if (command.isChangeInBigDecimalParameterNamed(SavingsApiConstants.interestRateParamName, this.interestRate)) { if (command.isChangeInBigDecimalParameterNamed(SavingsApiConstants.nominalAnnualInterestRateParamName,
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(SavingsApiConstants.interestRateParamName); this.nominalAnnualInterestRate)) {
actualChanges.put(SavingsApiConstants.interestRateParamName, newValue); final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(SavingsApiConstants.nominalAnnualInterestRateParamName);
actualChanges.put(SavingsApiConstants.nominalAnnualInterestRateParamName, newValue);
actualChanges.put("locale", localeAsInput); actualChanges.put("locale", localeAsInput);
this.interestRate = newValue; this.nominalAnnualInterestRate = 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();
} }
if (command.isChangeInBigDecimalParameterNamed(SavingsApiConstants.minRequiredOpeningBalanceParamName, 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.activeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationDaysInYearTypeParamName; 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.interestCalculationTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestPeriodTypeParamName; import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
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.lockinPeriodFrequencyParamName; 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.lockinPeriodFrequencyTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName; import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Locale; 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.Group;
import org.mifosplatform.portfolio.group.domain.GroupRepository; import org.mifosplatform.portfolio.group.domain.GroupRepository;
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException; 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.mifosplatform.portfolio.savings.exception.SavingsProductNotFoundException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -46,18 +43,15 @@ public class SavingsAccountAssembler {
private final GroupRepository groupRepository; private final GroupRepository groupRepository;
private final SavingsProductRepository savingProductRepository; private final SavingsProductRepository savingProductRepository;
private final FromJsonHelper fromApiJsonHelper; private final FromJsonHelper fromApiJsonHelper;
private final AprCalculator aprCalculator;
@Autowired @Autowired
public SavingsAccountAssembler(final SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper, public SavingsAccountAssembler(final SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper,
final ClientRepository clientRepository, final GroupRepository groupRepository, final ClientRepository clientRepository, final GroupRepository groupRepository,
final SavingsProductRepository savingProductRepository, final AprCalculator aprCalculator, final SavingsProductRepository savingProductRepository, final FromJsonHelper fromApiJsonHelper) {
final FromJsonHelper fromApiJsonHelper) {
this.savingsAccountTransactionSummaryWrapper = savingsAccountTransactionSummaryWrapper; this.savingsAccountTransactionSummaryWrapper = savingsAccountTransactionSummaryWrapper;
this.clientRepository = clientRepository; this.clientRepository = clientRepository;
this.groupRepository = groupRepository; this.groupRepository = groupRepository;
this.savingProductRepository = savingProductRepository; this.savingProductRepository = savingProductRepository;
this.aprCalculator = aprCalculator;
this.fromApiJsonHelper = fromApiJsonHelper; this.fromApiJsonHelper = fromApiJsonHelper;
} }
@@ -93,8 +87,8 @@ public class SavingsAccountAssembler {
} }
BigDecimal interestRate = null; BigDecimal interestRate = null;
if (command.parameterExists(interestRateParamName)) { if (command.parameterExists(nominalAnnualInterestRateParamName)) {
interestRate = command.bigDecimalValueOfParameterNamed(interestRateParamName); interestRate = command.bigDecimalValueOfParameterNamed(nominalAnnualInterestRateParamName);
} else { } else {
interestRate = product.interestRate(); interestRate = product.interestRate();
} }
@@ -102,23 +96,10 @@ public class SavingsAccountAssembler {
final boolean active = fromApiJsonHelper.extractBooleanNamed(activeParamName, element); final boolean active = fromApiJsonHelper.extractBooleanNamed(activeParamName, element);
final LocalDate activationDate = fromApiJsonHelper.extractLocalDateNamed(activationDateParamName, element); final LocalDate activationDate = fromApiJsonHelper.extractLocalDateNamed(activationDateParamName, element);
PeriodFrequencyType interestRatePeriodFrequencyType = null; SavingsCompoundingInterestPeriodType interestPeriodType = null;
Integer interestRatePeriodFrequencyTypeValue = null; final Integer interestPeriodTypeValue = command.integerValueOfParameterNamed(interestCompoundingPeriodTypeParamName);
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);
if (interestPeriodTypeValue != null) { if (interestPeriodTypeValue != null) {
interestPeriodType = SavingsInterestPeriodType.fromInt(interestPeriodTypeValue); interestPeriodType = SavingsCompoundingInterestPeriodType.fromInt(interestPeriodTypeValue);
} }
SavingsInterestCalculationType interestCalculationType = null; SavingsInterestCalculationType interestCalculationType = null;
@@ -148,20 +129,20 @@ public class SavingsAccountAssembler {
lockinPeriodFrequency = product.lockinPeriodFrequency(); lockinPeriodFrequency = product.lockinPeriodFrequency();
} }
PeriodFrequencyType lockinPeriodFrequencyType = null; SavingsPeriodFrequencyType lockinPeriodFrequencyType = null;
Integer lockinPeriodFrequencyTypeValue = null; Integer lockinPeriodFrequencyTypeValue = null;
if (command.parameterExists(lockinPeriodFrequencyTypeParamName)) { if (command.parameterExists(lockinPeriodFrequencyTypeParamName)) {
lockinPeriodFrequencyTypeValue = command.integerValueOfParameterNamed(lockinPeriodFrequencyTypeParamName); lockinPeriodFrequencyTypeValue = command.integerValueOfParameterNamed(lockinPeriodFrequencyTypeParamName);
if (lockinPeriodFrequencyTypeValue != null) { if (lockinPeriodFrequencyTypeValue != null) {
lockinPeriodFrequencyType = PeriodFrequencyType.fromInt(lockinPeriodFrequencyTypeValue); lockinPeriodFrequencyType = SavingsPeriodFrequencyType.fromInt(lockinPeriodFrequencyTypeValue);
} }
} else { } else {
lockinPeriodFrequencyType = product.lockinPeriodFrequencyType(); lockinPeriodFrequencyType = product.lockinPeriodFrequencyType();
} }
final SavingsAccount account = SavingsAccount.createNewAccount(client, group, product, accountNo, externalId, interestRate, final SavingsAccount account = SavingsAccount.createNewAccount(client, group, product, accountNo, externalId, interestRate,
interestRatePeriodFrequencyType, annualInterestRate, interestPeriodType, interestCalculationType, interestPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType); lockinPeriodFrequency, lockinPeriodFrequencyType);
account.setHelpers(this.savingsAccountTransactionSummaryWrapper); account.setHelpers(this.savingsAccountTransactionSummaryWrapper);
if (active) { if (active) {
@@ -9,24 +9,32 @@ import org.mifosplatform.organisation.monetary.domain.Money;
public class SavingsAccountDailyBalance { public class SavingsAccountDailyBalance {
private final InterestPeriodInterval interestPeriodInterval; private final LocalDateInterval interestPeriodInterval;
private final BigDecimal runningBalance; private final BigDecimal endOfDayBalance;
private final BigDecimal cumulativeBalance; private final BigDecimal cumulativeBalance;
private final BigDecimal compoundedInterestToDate;
public static SavingsAccountDailyBalance createFrom(final InterestPeriodInterval interestPeriodInterval, final BigDecimal runningBalance) { public static SavingsAccountDailyBalance createFrom(final LocalDateInterval interestPeriodInterval, final BigDecimal endOfDayBalance,
return new SavingsAccountDailyBalance(interestPeriodInterval, runningBalance); 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.interestPeriodInterval = interestPeriodInterval;
this.runningBalance = runningBalance; this.endOfDayBalance = endOfDayBalance;
this.compoundedInterestToDate = compoundedInterestToDate;
final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN); final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN);
final BigDecimal numberOfDaysBigDecimal = BigDecimal.valueOf(interestPeriodInterval.daysInPeriodInclusiveOfEndDate()); 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) { 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() { public BigDecimal cumulativeBalance() {
@@ -38,12 +46,14 @@ public class SavingsAccountDailyBalance {
} }
public boolean isGreaterThanZero() { 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) { public BigDecimal interestUsingDailyBalanceMethod(final BigDecimal dailyInterestRate, final Integer numberOfDays) {
final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN); final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN);
final BigDecimal numberOfDaysBigDecimal = BigDecimal.valueOf(numberOfDays.longValue()); 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(); .getAmount();
} }
public void updateFromInterestPeriodSummaries(final MonetaryCurrency currency, final List<InterestPeriodSummary> interestPeriodSummaries) { public void updateFromInterestPeriodSummaries(final MonetaryCurrency currency,
Money totalInterestEarned = Money.zero(currency); final List<InterestCompoundingPeriodSummary> compoundingPeriods) {
for (InterestPeriodSummary interestPeriodSummary : interestPeriodSummaries) {
totalInterestEarned = totalInterestEarned.plus(interestPeriodSummary.interest()); // 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) { 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) { public void updateCumulativeBalanceAndDates(final MonetaryCurrency currency, final LocalDate endOfBalanceDate) {
this.balanceEndDate = endOfBalanceDate.toDate(); this.balanceEndDate = endOfBalanceDate.toDate();
this.balanceNumberOfDays = InterestPeriodInterval.create(getTransactionLocalDate(), endOfBalanceDate) this.balanceNumberOfDays = LocalDateInterval.create(getTransactionLocalDate(), endOfBalanceDate)
.daysInPeriodInclusiveOfEndDate(); .daysInPeriodInclusiveOfEndDate();
this.cumulativeBalance = Money.of(currency, this.runningBalance).multipliedBy(this.balanceNumberOfDays).getAmount(); this.cumulativeBalance = Money.of(currency, this.runningBalance).multipliedBy(this.balanceNumberOfDays).getAmount();
} }
@@ -147,7 +147,7 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
return endDate; return endDate;
} }
public boolean isAcceptableForDailyBalance(final InterestPeriodInterval interestPeriodInterval) { public boolean isAcceptableForDailyBalance(final LocalDateInterval interestPeriodInterval) {
return isNotReversed() && interestPeriodInterval.contains(getTransactionLocalDate()) && isABalanceForAtLeastOneDay(); return isNotReversed() && interestPeriodInterval.contains(getTransactionLocalDate()) && isABalanceForAtLeastOneDay();
} }
@@ -162,7 +162,17 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
balanceValidTo = periodEnd; balanceValidTo = periodEnd;
} }
final InterestPeriodInterval interestPeriodInterval = InterestPeriodInterval.create(getTransactionLocalDate(), balanceValidTo); final LocalDateInterval interestPeriodInterval = LocalDateInterval.create(getTransactionLocalDate(), balanceValidTo);
return SavingsAccountDailyBalance.createFrom(interestPeriodInterval, this.runningBalance); 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.math.BigDecimal;
import java.util.List; import java.util.List;
public interface SavingsInterestCalculator { public interface SavingsCompoundInterestCalculator {
BigDecimal calculate(List<SavingsAccountDailyBalance> dailyBalances, Integer numberOfDays); 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> * Calculates interest on a savings account using the <b>Average Balance</b>
* method. * method.
*/ */
public class SavingsInterestCalculatorForAverageBalance implements SavingsInterestCalculator { public class SavingsCompoundInterestCalculatorForAverageBalance implements SavingsCompoundInterestCalculator {
private final BigDecimal periodsInOneYearAsFraction; private final BigDecimal periodsInOneYearAsFraction;
private final BigDecimal annualInterestRateAsFraction; private final BigDecimal annualInterestRateAsFraction;
public SavingsInterestCalculatorForAverageBalance(final BigDecimal periodsInOneYearAsFraction, public SavingsCompoundInterestCalculatorForAverageBalance(final BigDecimal periodsInOneYearAsFraction,
final BigDecimal annualInterestRateAsFraction) { final BigDecimal annualInterestRateAsFraction) {
this.periodsInOneYearAsFraction = periodsInOneYearAsFraction; this.periodsInOneYearAsFraction = periodsInOneYearAsFraction;
this.annualInterestRateAsFraction = annualInterestRateAsFraction; this.annualInterestRateAsFraction = annualInterestRateAsFraction;
@@ -9,12 +9,12 @@ import java.util.List;
* Calculates interest on a savings account using the <b>Daily Balance</b> * Calculates interest on a savings account using the <b>Daily Balance</b>
* method. * method.
*/ */
public class SavingsInterestCalculatorForDailyBalance implements SavingsInterestCalculator { public class SavingsCompoundInterestCalculatorForDailyBalance implements SavingsCompoundInterestCalculator {
private final BigDecimal periodsInOneYearAsFraction; private final BigDecimal periodsInOneYearAsFraction;
private final BigDecimal annualInterestRateAsFraction; private final BigDecimal annualInterestRateAsFraction;
public SavingsInterestCalculatorForDailyBalance(final BigDecimal periodsInOneYearAsFraction, public SavingsCompoundInterestCalculatorForDailyBalance(final BigDecimal periodsInOneYearAsFraction,
final BigDecimal annualInterestRateAsFraction) { final BigDecimal annualInterestRateAsFraction) {
this.periodsInOneYearAsFraction = periodsInOneYearAsFraction; this.periodsInOneYearAsFraction = periodsInOneYearAsFraction;
this.annualInterestRateAsFraction = annualInterestRateAsFraction; this.annualInterestRateAsFraction = annualInterestRateAsFraction;
@@ -29,7 +29,7 @@ public class SavingsInterestCalculatorForDailyBalance implements SavingsInterest
for (SavingsAccountDailyBalance balance : dailyBalances) { for (SavingsAccountDailyBalance balance : dailyBalances) {
if (balance.isGreaterThanZero()) { if (balance.isGreaterThanZero()) {
final BigDecimal interestForBalance = balance.interestUsingDailyBalanceMethod(dailyInterestRate, numberOfDays); final BigDecimal interestForBalance = balance.interestUsingDailyBalanceMethod(dailyInterestRate, balance.numberOfDays());
interestCalculated = interestCalculated.add(interestForBalance, mc); 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 class SavingsInterestCalculatorFactory {
public SavingsInterestCalculator createFrom(final SavingsInterestCalculationType interestCalculationType, public SavingsCompoundInterestCalculator createFrom(final SavingsInterestCalculationType interestCalculationType,
final BigDecimal periodsInOneYearAsFraction, final BigDecimal annualInterestRateAsFraction) { final BigDecimal periodsInOneYearAsFraction, final BigDecimal annualInterestRateAsFraction) {
SavingsInterestCalculator savingsInterestCalculator = new SavingsInterestCalculatorForDailyBalance(periodsInOneYearAsFraction, SavingsCompoundInterestCalculator savingsInterestCalculator = new SavingsCompoundInterestCalculatorForDailyBalance(periodsInOneYearAsFraction,
annualInterestRateAsFraction); annualInterestRateAsFraction);
switch (interestCalculationType) { switch (interestCalculationType) {
case AVERAGE_DAILY_BALANCE: case AVERAGE_DAILY_BALANCE:
savingsInterestCalculator = new SavingsInterestCalculatorForAverageBalance(periodsInOneYearAsFraction, savingsInterestCalculator = new SavingsCompoundInterestCalculatorForAverageBalance(periodsInOneYearAsFraction,
annualInterestRateAsFraction); annualInterestRateAsFraction);
break; break;
case DAILY_BALANCE: case DAILY_BALANCE:
savingsInterestCalculator = new SavingsInterestCalculatorForDailyBalance(periodsInOneYearAsFraction, savingsInterestCalculator = new SavingsCompoundInterestCalculatorForDailyBalance(periodsInOneYearAsFraction,
annualInterestRateAsFraction); annualInterestRateAsFraction);
break; break;
case INVALID: 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.digitsAfterDecimalParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationDaysInYearTypeParamName; 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.interestCalculationTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestPeriodTypeParamName; import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
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.localeParamName; 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.lockinPeriodFrequencyParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyTypeParamName; 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.minRequiredOpeningBalanceParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nameParamName; import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nameParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@@ -31,7 +30,6 @@ import javax.persistence.Table;
import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money; import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.savings.exception.InvalidSavingsProductSettingsException; import org.mifosplatform.portfolio.savings.exception.InvalidSavingsProductSettingsException;
import org.springframework.data.jpa.domain.AbstractPersistable; import org.springframework.data.jpa.domain.AbstractPersistable;
@@ -48,20 +46,17 @@ public class SavingsProduct extends AbstractPersistable<Long> {
@Embedded @Embedded
private MonetaryCurrency currency; private MonetaryCurrency currency;
@Column(name = "nominal_interest_rate_per_period", scale = 6, precision = 19, nullable = false) @Column(name = "nominal_annual_interest_rate", scale = 6, precision = 19, nullable = false)
private BigDecimal interestRate; private BigDecimal nominalAnnualInterestRate;
@Column(name = "nominal_interest_rate_period_frequency_enum", nullable = false)
private Integer interestRatePeriodFrequencyType;
/** /**
* The interest period is the span of time at the end of which savings in a * The interest period is the span of time at the end of which savings in a
* client’s account earn interest. * 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) @Column(name = "interest_compounding_period_enum", nullable = false)
private Integer interestPeriodType; private Integer interestCompoundingPeriodType;
/** /**
* A value from the {@link SavingsInterestCalculationType} enumeration. * A value from the {@link SavingsInterestCalculationType} enumeration.
@@ -86,15 +81,13 @@ public class SavingsProduct extends AbstractPersistable<Long> {
private Integer lockinPeriodFrequencyType; private Integer lockinPeriodFrequencyType;
public static SavingsProduct createNew(final String name, final String description, final MonetaryCurrency currency, public static SavingsProduct createNew(final String name, final String description, final MonetaryCurrency currency,
final BigDecimal interestRate, final SavingsPeriodFrequencyType interestRatePeriodFrequencyType, final BigDecimal interestRate, final SavingsCompoundingInterestPeriodType interestPeriodType,
final SavingsInterestPeriodType interestPeriodType, final SavingsInterestCalculationType interestCalculationType, final SavingsInterestCalculationType interestCalculationType,
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
final Integer lockinPeriodFrequency, final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType) {
final PeriodFrequencyType lockinPeriodFrequencyType) {
return new SavingsProduct(name, description, currency, interestRate, interestRatePeriodFrequencyType, interestPeriodType, return new SavingsProduct(name, description, currency, interestRate, interestPeriodType, interestCalculationType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType);
lockinPeriodFrequencyType);
} }
protected SavingsProduct() { 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, private SavingsProduct(final String name, final String description, final MonetaryCurrency currency, final BigDecimal interestRate,
final SavingsPeriodFrequencyType interestRatePeriodFrequencyType, final SavingsInterestPeriodType interestPeriodType, final SavingsCompoundingInterestPeriodType interestPeriodType, final SavingsInterestCalculationType interestCalculationType,
final SavingsInterestCalculationType interestCalculationType,
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
final Integer lockinPeriodFrequency, final PeriodFrequencyType lockinPeriodFrequencyType) { final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType) {
this.name = name; this.name = name;
this.description = description; this.description = description;
this.currency = currency; this.currency = currency;
this.interestRate = interestRate; this.nominalAnnualInterestRate = interestRate;
this.interestRatePeriodFrequencyType = interestRatePeriodFrequencyType.getValue(); this.interestCompoundingPeriodType = interestPeriodType.getValue();
this.interestPeriodType = interestPeriodType.getValue();
this.interestCalculationType = interestCalculationType.getValue(); this.interestCalculationType = interestCalculationType.getValue();
this.interestCalculationDaysInYearType = interestCalculationDaysInYearType.getValue(); this.interestCalculationDaysInYearType = interestCalculationDaysInYearType.getValue();
@@ -135,15 +126,7 @@ public class SavingsProduct extends AbstractPersistable<Long> {
} }
public BigDecimal interestRate() { public BigDecimal interestRate() {
return Money.of(this.currency, this.interestRate).getAmount(); return Money.of(this.currency, this.nominalAnnualInterestRate).getAmount();
}
public PeriodFrequencyType interestRatePeriodFrequencyType() {
PeriodFrequencyType type = null;
if (this.interestRatePeriodFrequencyType != null) {
type = PeriodFrequencyType.fromInt(this.interestRatePeriodFrequencyType);
}
return type;
} }
public BigDecimal minRequiredOpeningBalance() { public BigDecimal minRequiredOpeningBalance() {
@@ -154,10 +137,10 @@ public class SavingsProduct extends AbstractPersistable<Long> {
return this.lockinPeriodFrequency; return this.lockinPeriodFrequency;
} }
public PeriodFrequencyType lockinPeriodFrequencyType() { public SavingsPeriodFrequencyType lockinPeriodFrequencyType() {
PeriodFrequencyType type = null; SavingsPeriodFrequencyType type = null;
if (this.lockinPeriodFrequencyType != null) { if (this.lockinPeriodFrequencyType != null) {
type = PeriodFrequencyType.fromInt(this.lockinPeriodFrequencyType); type = SavingsPeriodFrequencyType.fromInt(this.lockinPeriodFrequencyType);
} }
return type; return type;
} }
@@ -197,23 +180,17 @@ public class SavingsProduct extends AbstractPersistable<Long> {
this.currency = new MonetaryCurrency(currencyCode, this.currency.getDigitsAfterDecimal()); this.currency = new MonetaryCurrency(currencyCode, this.currency.getDigitsAfterDecimal());
} }
if (command.isChangeInBigDecimalParameterNamed(interestRateParamName, this.interestRate)) { if (command.isChangeInBigDecimalParameterNamed(nominalAnnualInterestRateParamName, this.nominalAnnualInterestRate)) {
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(interestRateParamName); final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(nominalAnnualInterestRateParamName);
actualChanges.put(interestRateParamName, newValue); actualChanges.put(nominalAnnualInterestRateParamName, newValue);
actualChanges.put(localeParamName, localeAsInput); actualChanges.put(localeParamName, localeAsInput);
this.interestRate = newValue; this.nominalAnnualInterestRate = newValue;
} }
if (command.isChangeInIntegerParameterNamed(interestRatePeriodFrequencyTypeParamName, this.interestRatePeriodFrequencyType)) { if (command.isChangeInIntegerParameterNamed(interestCompoundingPeriodTypeParamName, this.interestCompoundingPeriodType)) {
final Integer newValue = command.integerValueOfParameterNamed(interestRatePeriodFrequencyTypeParamName); final Integer newValue = command.integerValueOfParameterNamed(interestCompoundingPeriodTypeParamName);
actualChanges.put(interestRatePeriodFrequencyTypeParamName, newValue); actualChanges.put(interestCompoundingPeriodTypeParamName, newValue);
this.interestRatePeriodFrequencyType = SavingsPeriodFrequencyType.fromInt(newValue).getValue(); this.interestCompoundingPeriodType = SavingsCompoundingInterestPeriodType.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(interestCalculationTypeParamName, this.interestCalculationType)) { 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.digitsAfterDecimalParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationDaysInYearTypeParamName; 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.interestCalculationTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestPeriodTypeParamName; import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
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.lockinPeriodFrequencyParamName; 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.lockinPeriodFrequencyTypeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName; 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.nameParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
import java.math.BigDecimal; import java.math.BigDecimal;
import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@Component @Component
@@ -32,17 +30,12 @@ public class SavingsProductAssembler {
final Integer digitsAfterDecimal = command.integerValueOfParameterNamed(digitsAfterDecimalParamName); final Integer digitsAfterDecimal = command.integerValueOfParameterNamed(digitsAfterDecimalParamName);
MonetaryCurrency currency = new MonetaryCurrency(currencyCode, digitsAfterDecimal); MonetaryCurrency currency = new MonetaryCurrency(currencyCode, digitsAfterDecimal);
final BigDecimal interestRate = command.bigDecimalValueOfParameterNamed(interestRateParamName); final BigDecimal interestRate = command.bigDecimalValueOfParameterNamed(nominalAnnualInterestRateParamName);
SavingsPeriodFrequencyType interestRatePeriodFrequencyType = null;
final Integer interestRatePeriodFrequencyTypeValue = command.integerValueOfParameterNamed(interestRatePeriodFrequencyTypeParamName);
if (interestRatePeriodFrequencyTypeValue != null) {
interestRatePeriodFrequencyType = SavingsPeriodFrequencyType.fromInt(interestRatePeriodFrequencyTypeValue);
}
SavingsInterestPeriodType interestPeriodType = null; SavingsCompoundingInterestPeriodType interestPeriodType = null;
final Integer interestPeriodTypeValue = command.integerValueOfParameterNamed(interestPeriodTypeParamName); final Integer interestPeriodTypeValue = command.integerValueOfParameterNamed(interestCompoundingPeriodTypeParamName);
if (interestPeriodTypeValue != null) { if (interestPeriodTypeValue != null) {
interestPeriodType = SavingsInterestPeriodType.fromInt(interestPeriodTypeValue); interestPeriodType = SavingsCompoundingInterestPeriodType.fromInt(interestPeriodTypeValue);
} }
SavingsInterestCalculationType interestCalculationType = null; SavingsInterestCalculationType interestCalculationType = null;
@@ -61,14 +54,13 @@ public class SavingsProductAssembler {
final BigDecimal minRequiredOpeningBalance = command.bigDecimalValueOfParameterNamed(minRequiredOpeningBalanceParamName); final BigDecimal minRequiredOpeningBalance = command.bigDecimalValueOfParameterNamed(minRequiredOpeningBalanceParamName);
final Integer lockinPeriodFrequency = command.integerValueOfParameterNamed(lockinPeriodFrequencyParamName); final Integer lockinPeriodFrequency = command.integerValueOfParameterNamed(lockinPeriodFrequencyParamName);
PeriodFrequencyType lockinPeriodFrequencyType = null; SavingsPeriodFrequencyType lockinPeriodFrequencyType = null;
final Integer lockinPeriodFrequencyTypeValue = command.integerValueOfParameterNamed(lockinPeriodFrequencyTypeParamName); final Integer lockinPeriodFrequencyTypeValue = command.integerValueOfParameterNamed(lockinPeriodFrequencyTypeParamName);
if (lockinPeriodFrequencyTypeValue != null) { if (lockinPeriodFrequencyTypeValue != null) {
lockinPeriodFrequencyType = PeriodFrequencyType.fromInt(lockinPeriodFrequencyTypeValue); lockinPeriodFrequencyType = SavingsPeriodFrequencyType.fromInt(lockinPeriodFrequencyTypeValue);
} }
return SavingsProduct.createNew(name, description, currency, interestRate, interestRatePeriodFrequencyType, interestPeriodType, return SavingsProduct.createNew(name, description, currency, interestRate, interestPeriodType, interestCalculationType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType);
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.SavingsAccountTransactionData;
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionEnumData; import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionEnumData;
import org.mifosplatform.portfolio.savings.data.SavingsProductData; 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.SavingsInterestCalculationDaysInYearType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationType; 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.domain.SavingsPeriodFrequencyType;
import org.mifosplatform.portfolio.savings.exception.SavingsAccountNotFoundException; import org.mifosplatform.portfolio.savings.exception.SavingsAccountNotFoundException;
import org.springframework.beans.factory.annotation.Autowired; 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("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.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, "); sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, ");
sqlBuilder.append("sa.nominal_interest_rate_per_period as interestRate, "); sqlBuilder.append("sa.nominal_annual_interest_rate as nominalAnnualInterestRate, ");
sqlBuilder.append("sa.nominal_interest_rate_period_frequency_enum as interestRatePeriodFrequencyType, "); sqlBuilder.append("sa.interest_compounding_period_enum as interestCompoundingPeriodType, ");
sqlBuilder.append("sa.annual_nominal_interest_rate as annualInterestRate, ");
sqlBuilder.append("sa.interest_period_enum as interestPeriodType, ");
sqlBuilder.append("sa.interest_calculation_type_enum as interestCalculationType, "); sqlBuilder.append("sa.interest_calculation_type_enum as interestCalculationType, ");
sqlBuilder.append("sa.interest_calculation_days_in_year_type_enum as interestCalculationDaysInYearType, "); sqlBuilder.append("sa.interest_calculation_days_in_year_type_enum as interestCalculationDaysInYearType, ");
sqlBuilder.append("sa.min_required_opening_balance as minRequiredOpeningBalance, "); 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, final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, currencyDisplaySymbol,
currencyNameCode); currencyNameCode);
final BigDecimal interestRate = rs.getBigDecimal("interestRate"); final BigDecimal nominalAnnualInterestRate = rs.getBigDecimal("nominalAnnualInterestRate");
final SavingsPeriodFrequencyType interestRatePeriodType = SavingsPeriodFrequencyType.fromInt(JdbcSupport.getInteger(rs,
"interestRatePeriodFrequencyType"));
final EnumOptionData interestRatePeriodFrequencyType = SavingsEnumerations
.interestRatePeriodFrequencyType(interestRatePeriodType);
final BigDecimal annualInterestRate = rs.getBigDecimal("annualInterestRate");
EnumOptionData interestPeriodType = SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.fromInt(JdbcSupport final EnumOptionData interestCompoundingPeriodType = SavingsEnumerations
.getInteger(rs, "interestPeriodType"))); .compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.fromInt(JdbcSupport.getInteger(rs,
"interestCompoundingPeriodType")));
EnumOptionData interestCalculationType = SavingsEnumerations.interestCalculationType(SavingsInterestCalculationType final EnumOptionData interestCalculationType = SavingsEnumerations.interestCalculationType(SavingsInterestCalculationType
.fromInt(JdbcSupport.getInteger(rs, "interestCalculationType"))); .fromInt(JdbcSupport.getInteger(rs, "interestCalculationType")));
EnumOptionData interestCalculationDaysInYearType = SavingsEnumerations final EnumOptionData interestCalculationDaysInYearType = SavingsEnumerations
.interestCalculationDaysInYearType(SavingsInterestCalculationDaysInYearType.fromInt(JdbcSupport.getInteger(rs, .interestCalculationDaysInYearType(SavingsInterestCalculationDaysInYearType.fromInt(JdbcSupport.getInteger(rs,
"interestCalculationDaysInYearType"))); "interestCalculationDaysInYearType")));
@@ -194,10 +188,11 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
final SavingsAccountSummaryData summary = new SavingsAccountSummaryData(currency, totalDeposits, totalWithdrawals, final SavingsAccountSummaryData summary = new SavingsAccountSummaryData(currency, totalDeposits, totalWithdrawals,
totalInterestEarned, totalInterestPosted, accountBalance); totalInterestEarned, totalInterestPosted, accountBalance);
return SavingsAccountData.instance(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName, return SavingsAccountData
productId, productName, currency, interestRate, interestRatePeriodFrequencyType, annualInterestRate, .instance(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName, productId,
interestPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, productName, currency, nominalAnnualInterestRate, interestCompoundingPeriodType, interestCalculationType,
lockinPeriodFrequency, lockinPeriodFrequencyType, summary); interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
summary);
} }
} }
@@ -225,11 +220,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
final String sql = "select " + mapper.schema() + " where sp.id = ?"; final String sql = "select " + mapper.schema() + " where sp.id = ?";
template = this.jdbcTemplate.queryForObject(sql, mapper, new Object[] { productId }); template = this.jdbcTemplate.queryForObject(sql, mapper, new Object[] { productId });
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions = this.dropdownReadPlatformService final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = this.dropdownReadPlatformService
.retrieveInterestRatePeriodFrequencyTypeOptions(); .retrieveCompoundingInterestPeriodTypeOptions();
final Collection<EnumOptionData> interestPeriodTypeOptions = this.dropdownReadPlatformService
.retrieveInterestPeriodTypeOptions();
final Collection<EnumOptionData> interestCalculationTypeOptions = this.dropdownReadPlatformService final Collection<EnumOptionData> interestCalculationTypeOptions = this.dropdownReadPlatformService
.retrieveInterestCalculationTypeOptions(); .retrieveInterestCalculationTypeOptions();
@@ -241,9 +233,9 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
.retrieveLockinPeriodFrequencyTypeOptions(); .retrieveLockinPeriodFrequencyTypeOptions();
final Collection<SavingsAccountTransactionData> transactions = null; final Collection<SavingsAccountTransactionData> transactions = null;
template = SavingsAccountData.withTemplateOptions(template, productOptions, interestRatePeriodFrequencyTypeOptions, template = SavingsAccountData.withTemplateOptions(template, productOptions, interestCompoundingPeriodTypeOptions,
interestPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
lockinPeriodFrequencyTypeOptions, transactions); transactions);
} else { } else {
String clientName = null; String clientName = null;
@@ -258,16 +250,15 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
template = SavingsAccountData.withClientTemplate(clientId, clientName, groupId, groupName); template = SavingsAccountData.withClientTemplate(clientId, clientName, groupId, groupName);
final Collection<EnumOptionData> interestRatePeriodFrequencyTypeOptions = null; final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
final Collection<EnumOptionData> interestPeriodTypeOptions = null;
final Collection<EnumOptionData> interestCalculationTypeOptions = null; final Collection<EnumOptionData> interestCalculationTypeOptions = null;
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null; final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null; final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
final Collection<SavingsAccountTransactionData> transactions = null; final Collection<SavingsAccountTransactionData> transactions = null;
template = SavingsAccountData.withTemplateOptions(template, productOptions, interestRatePeriodFrequencyTypeOptions, template = SavingsAccountData.withTemplateOptions(template, productOptions, interestCompoundingPeriodTypeOptions,
interestPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
lockinPeriodFrequencyTypeOptions, transactions); transactions);
} }
return template; 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("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.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, "); sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, ");
sqlBuilder.append("sp.nominal_interest_rate_per_period as interestRate, "); sqlBuilder.append("sp.nominal_annual_interest_rate as nominalAnnualIterestRate, ");
sqlBuilder.append("sp.nominal_interest_rate_period_frequency_enum as interestRatePeriodFrequencyType, "); sqlBuilder.append("sp.interest_compounding_period_enum as interestCompoundingPeriodType, ");
sqlBuilder.append("sp.interest_period_enum as interestPeriodType, ");
sqlBuilder.append("sp.interest_calculation_type_enum as interestCalculationType, "); sqlBuilder.append("sp.interest_calculation_type_enum as interestCalculationType, ");
sqlBuilder.append("sp.interest_calculation_days_in_year_type_enum as interestCalculationDaysInYearType, "); sqlBuilder.append("sp.interest_calculation_days_in_year_type_enum as interestCalculationDaysInYearType, ");
sqlBuilder.append("sp.min_required_opening_balance as minRequiredOpeningBalance, "); 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, final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, currencyDisplaySymbol,
currencyNameCode); currencyNameCode);
final BigDecimal interestRate = rs.getBigDecimal("interestRate"); final BigDecimal nominalAnnualIterestRate = rs.getBigDecimal("nominalAnnualIterestRate");
final SavingsPeriodFrequencyType interestRatePeriodType = SavingsPeriodFrequencyType.fromInt(JdbcSupport.getInteger(rs,
"interestRatePeriodFrequencyType"));
final EnumOptionData interestRatePeriodFrequencyType = SavingsEnumerations
.interestRatePeriodFrequencyType(interestRatePeriodType);
final BigDecimal annualInterestRate = null;
EnumOptionData interestPeriodType = SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.fromInt(JdbcSupport EnumOptionData interestPeriodType = SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType
.getInteger(rs, "interestPeriodType"))); .fromInt(JdbcSupport.getInteger(rs, "interestCompoundingPeriodType")));
EnumOptionData interestCalculationType = SavingsEnumerations.interestCalculationType(SavingsInterestCalculationType EnumOptionData interestCalculationType = SavingsEnumerations.interestCalculationType(SavingsInterestCalculationType
.fromInt(JdbcSupport.getInteger(rs, "interestCalculationType"))); .fromInt(JdbcSupport.getInteger(rs, "interestCalculationType")));
@@ -474,10 +459,11 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
final SavingsAccountStatusEnumData status = null; final SavingsAccountStatusEnumData status = null;
final LocalDate activationDate = null; final LocalDate activationDate = null;
final SavingsAccountSummaryData summary = null; final SavingsAccountSummaryData summary = null;
return SavingsAccountData.instance(null, null, null, status, activationDate, groupId, groupName, clientId, clientName, return SavingsAccountData
productId, productName, currency, interestRate, interestRatePeriodFrequencyType, annualInterestRate, .instance(null, null, null, status, activationDate, groupId, groupName, clientId, clientName, productId, productName,
interestPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, currency, nominalAnnualIterestRate, interestPeriodType, interestCalculationType,
lockinPeriodFrequency, lockinPeriodFrequencyType, summary); 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.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException; import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.core.service.DateUtils;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator; import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator;
import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory; import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory;
@@ -321,7 +322,8 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
final SavingsAccount account = this.savingAccountRepository.findOneWithNotFoundDetection(savingsId); final SavingsAccount account = this.savingAccountRepository.findOneWithNotFoundDetection(savingsId);
account.calculateInterest(); final LocalDate today = DateUtils.getLocalDateOfTenant();
account.calculateInterest(today);
this.savingAccountRepository.save(account); this.savingAccountRepository.save(account);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
@@ -6,11 +6,9 @@ import org.mifosplatform.infrastructure.core.data.EnumOptionData;
public interface SavingsDropdownReadPlatformService { public interface SavingsDropdownReadPlatformService {
Collection<EnumOptionData> retrieveInterestRatePeriodFrequencyTypeOptions();
Collection<EnumOptionData> retrieveLockinPeriodFrequencyTypeOptions(); Collection<EnumOptionData> retrieveLockinPeriodFrequencyTypeOptions();
Collection<EnumOptionData> retrieveInterestPeriodTypeOptions(); Collection<EnumOptionData> retrieveCompoundingInterestPeriodTypeOptions();
Collection<EnumOptionData> retrieveInterestCalculationTypeOptions(); Collection<EnumOptionData> retrieveInterestCalculationTypeOptions();
@@ -5,25 +5,15 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import org.mifosplatform.infrastructure.core.data.EnumOptionData; 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.SavingsInterestCalculationDaysInYearType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationType; 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.domain.SavingsPeriodFrequencyType;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service @Service
public class SavingsDropdownReadPlatformServiceImpl implements SavingsDropdownReadPlatformService { 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 @Override
public List<EnumOptionData> retrieveLockinPeriodFrequencyTypeOptions() { public List<EnumOptionData> retrieveLockinPeriodFrequencyTypeOptions() {
List<EnumOptionData> allowedLockinPeriodFrequencyTypeOptions = Arrays.asList( // List<EnumOptionData> allowedLockinPeriodFrequencyTypeOptions = Arrays.asList( //
@@ -37,15 +27,16 @@ public class SavingsDropdownReadPlatformServiceImpl implements SavingsDropdownRe
} }
@Override @Override
public Collection<EnumOptionData> retrieveInterestPeriodTypeOptions() { public Collection<EnumOptionData> retrieveCompoundingInterestPeriodTypeOptions() {
List<EnumOptionData> allowedOptions = Arrays.asList( // List<EnumOptionData> allowedOptions = Arrays.asList( //
SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.DAILY), // SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.DAILY), //
SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.WEEKLY), // SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.WEEKLY), //
SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.BIWEEKLY), // SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.BIWEEKLY), //
SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.MONTHLY), // SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.MONTHLY), //
SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.QUATERLY), // SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.QUATERLY), //
SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.SEMIANNUAL), // SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.BI_ANNUAL), //
SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.ANNUAL) // SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.ANNUAL), //
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.NO_COMPOUNDING_SIMPLE_INTEREST) //
); );
return allowedOptions; 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.data.SavingsAccountTransactionEnumData;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountStatusType; import org.mifosplatform.portfolio.savings.domain.SavingsAccountStatusType;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransactionType; 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.SavingsInterestCalculationDaysInYearType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationType; 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.domain.SavingsPeriodFrequencyType;
public class SavingsEnumerations { 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) { public static EnumOptionData lockinPeriodFrequencyType(final int id) {
return lockinPeriodFrequencyType(SavingsPeriodFrequencyType.fromInt(id)); return lockinPeriodFrequencyType(SavingsPeriodFrequencyType.fromInt(id));
} }
@@ -141,45 +110,50 @@ public class SavingsEnumerations {
} }
public static EnumOptionData interestPeriodType(final Integer type) { 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."; final String codePrefix = "savings.interest.period.";
EnumOptionData optionData = new EnumOptionData(SavingsInterestPeriodType.INVALID.getValue().longValue(), EnumOptionData optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.INVALID.getValue().longValue(),
SavingsInterestPeriodType.INVALID.getCode(), "Invalid"); SavingsCompoundingInterestPeriodType.INVALID.getCode(), "Invalid");
switch (type) { switch (type) {
case INVALID: case INVALID:
break; break;
case DAILY: case DAILY:
optionData = new EnumOptionData(SavingsInterestPeriodType.DAILY.getValue().longValue(), codePrefix optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.DAILY.getValue().longValue(), codePrefix
+ SavingsInterestPeriodType.DAILY.getCode(), "Daily"); + SavingsCompoundingInterestPeriodType.DAILY.getCode(), "Daily");
break; break;
case WEEKLY: case WEEKLY:
optionData = new EnumOptionData(SavingsInterestPeriodType.WEEKLY.getValue().longValue(), codePrefix optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.WEEKLY.getValue().longValue(), codePrefix
+ SavingsInterestPeriodType.WEEKLY.getCode(), "Weekly"); + SavingsCompoundingInterestPeriodType.WEEKLY.getCode(), "Weekly");
break; break;
case BIWEEKLY: case BIWEEKLY:
optionData = new EnumOptionData(SavingsInterestPeriodType.BIWEEKLY.getValue().longValue(), codePrefix optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.BIWEEKLY.getValue().longValue(), codePrefix
+ SavingsInterestPeriodType.BIWEEKLY.getCode(), "Bi-Weekly"); + SavingsCompoundingInterestPeriodType.BIWEEKLY.getCode(), "Bi-Weekly");
break; break;
case MONTHLY: case MONTHLY:
optionData = new EnumOptionData(SavingsInterestPeriodType.MONTHLY.getValue().longValue(), codePrefix optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.MONTHLY.getValue().longValue(), codePrefix
+ SavingsInterestPeriodType.MONTHLY.getCode(), "Monthly"); + SavingsCompoundingInterestPeriodType.MONTHLY.getCode(), "Monthly");
break; break;
case QUATERLY: case QUATERLY:
optionData = new EnumOptionData(SavingsInterestPeriodType.QUATERLY.getValue().longValue(), codePrefix optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.QUATERLY.getValue().longValue(), codePrefix
+ SavingsInterestPeriodType.QUATERLY.getCode(), "Quarterly"); + SavingsCompoundingInterestPeriodType.QUATERLY.getCode(), "Quarterly");
break; break;
case SEMIANNUAL: case BI_ANNUAL:
optionData = new EnumOptionData(SavingsInterestPeriodType.SEMIANNUAL.getValue().longValue(), codePrefix optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.BI_ANNUAL.getValue().longValue(), codePrefix
+ SavingsInterestPeriodType.SEMIANNUAL.getCode(), "Semi-Annual"); + SavingsCompoundingInterestPeriodType.BI_ANNUAL.getCode(), "Semi-Annual");
break; break;
case ANNUAL: case ANNUAL:
optionData = new EnumOptionData(SavingsInterestPeriodType.ANNUAL.getValue().longValue(), codePrefix optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.ANNUAL.getValue().longValue(), codePrefix
+ SavingsInterestPeriodType.ANNUAL.getCode(), "Annually"); + 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; break;
} }
@@ -16,9 +16,9 @@ import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSourc
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.monetary.data.CurrencyData; import org.mifosplatform.organisation.monetary.data.CurrencyData;
import org.mifosplatform.portfolio.savings.data.SavingsProductData; 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.SavingsInterestCalculationDaysInYearType;
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationType; 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.domain.SavingsPeriodFrequencyType;
import org.mifosplatform.portfolio.savings.exception.SavingsProductNotFoundException; import org.mifosplatform.portfolio.savings.exception.SavingsProductNotFoundException;
import org.springframework.beans.factory.annotation.Autowired; 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("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.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, "); sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, ");
sqlBuilder.append("sp.nominal_interest_rate_per_period as interestRate, "); sqlBuilder.append("sp.nominal_annual_interest_rate as nominalAnnualInterestRate, ");
sqlBuilder.append("sp.nominal_interest_rate_period_frequency_enum as interestRatePeriodFrequencyType, "); sqlBuilder.append("sp.interest_compounding_period_enum as compoundingInterestPeriodType, ");
sqlBuilder.append("sp.interest_period_enum as interestPeriodType, ");
sqlBuilder.append("sp.interest_calculation_type_enum as interestCalculationType, "); sqlBuilder.append("sp.interest_calculation_type_enum as interestCalculationType, ");
sqlBuilder.append("sp.interest_calculation_days_in_year_type_enum as interestCalculationDaysInYearType, "); sqlBuilder.append("sp.interest_calculation_days_in_year_type_enum as interestCalculationDaysInYearType, ");
sqlBuilder.append("sp.min_required_opening_balance as minRequiredOpeningBalance, "); 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, final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, currencyDisplaySymbol,
currencyNameCode); currencyNameCode);
BigDecimal interestRate = rs.getBigDecimal("interestRate"); final BigDecimal nominalAnnualInterestRate = rs.getBigDecimal("nominalAnnualInterestRate");
EnumOptionData interestRatePeriodFrequencyType = SavingsEnumerations.interestRatePeriodFrequencyType(SavingsPeriodFrequencyType EnumOptionData compoundingInterestPeriodType = SavingsEnumerations
.fromInt(JdbcSupport.getInteger(rs, "interestRatePeriodFrequencyType"))); .compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.fromInt(JdbcSupport.getInteger(rs,
"compoundingInterestPeriodType")));
EnumOptionData interestPeriodType = SavingsEnumerations.interestPeriodType(SavingsInterestPeriodType.fromInt(JdbcSupport
.getInteger(rs, "interestPeriodType")));
EnumOptionData interestCalculationType = SavingsEnumerations.interestCalculationType(SavingsInterestCalculationType EnumOptionData interestCalculationType = SavingsEnumerations.interestCalculationType(SavingsInterestCalculationType
.fromInt(JdbcSupport.getInteger(rs, "interestCalculationType"))); .fromInt(JdbcSupport.getInteger(rs, "interestCalculationType")));
@@ -142,9 +139,9 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
.fromInt(lockinPeriodFrequencyTypeValue)); .fromInt(lockinPeriodFrequencyTypeValue));
} }
return SavingsProductData.instance(id, name, description, currency, interestRate, interestRatePeriodFrequencyType, return SavingsProductData.instance(id, name, description, currency, nominalAnnualInterestRate, compoundingInterestPeriodType,
interestPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequency, lockinPeriodFrequencyType); lockinPeriodFrequencyType);
} }
} }