MIFOSX-232: WIP - split out terms and settings related fields on loan product along with charges and accounting related inputs.
This commit is contained in:
+395
-396
@@ -5466,7 +5466,7 @@ Request Body:
|
||||
<td class=fielddesc>Used like: numberOfRepayments Every
|
||||
repaymentEvery repaymentFrequencyType<br> e.g. 10
|
||||
(repayments) Every 12 <b>Weeks</b> <br>
|
||||
<span>Example Values:</span> Days, Weeks, Months
|
||||
<span>Example Values:</span> 0=Days, 1=Weeks, 2=Months
|
||||
</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
@@ -5476,15 +5476,15 @@ Request Body:
|
||||
<td class=fielddesc>Used like: interestRatePerPeriod%
|
||||
interestRateFrequencyType - interestType<br> e.g. 12.0000%
|
||||
<b>Per year</b> - Declining Balance <br>
|
||||
<span>Example Values:</span> Per month, Per year
|
||||
<span>Example Values:</span> 2=Per month, 3=Per year
|
||||
</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>amortizationType</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc><span>Example Values:</span> Equal
|
||||
principle payments, Equal installments</td>
|
||||
<td class=fielddesc><span>Example Values:</span> 0=Equal
|
||||
principle payments, 1=Equal installments</td>
|
||||
</tr>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -5495,7 +5495,7 @@ Request Body:
|
||||
<td class=fielddesc>Used like: interestRatePerPeriod%
|
||||
interestRateFrequencyType - interestType<br> e.g. 12.0000%
|
||||
Per year - <b>Declining Balance</b> <br>
|
||||
<span>Example Values:</span> Declining Balance, Flat
|
||||
<span>Example Values:</span> 0=Declining Balance, 1=Flat
|
||||
</td>
|
||||
</tr>
|
||||
</td>
|
||||
@@ -5504,8 +5504,8 @@ Request Body:
|
||||
<td>interestCalculationPeriodType</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc><span>Example Values:</span> Same as
|
||||
repayment period, Daily</td>
|
||||
<td class=fielddesc><span>Example Values:</span> 0=Daily,
|
||||
1=Same as repayment period</td>
|
||||
</tr>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -5514,8 +5514,8 @@ Request Body:
|
||||
<td>accountingRule</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc><span>Example Values:</span>NONE(1),
|
||||
CASH_BASED(2), ACCRUAL_BASED(3)</td>
|
||||
<td class=fielddesc><span>Example Values:</span>1=NONE,
|
||||
2=CASH_BASED, 3=ACCRUAL_BASED</td>
|
||||
</tr>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -5541,61 +5541,55 @@ GET https://DomainName/api/v1/loanproducts
|
||||
</code>
|
||||
<code class="method-response">
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"name": "A new loan product for me",
|
||||
"currency": {
|
||||
"code": "USD",
|
||||
"name": "US Dollar",
|
||||
"decimalPlaces": 2,
|
||||
"displaySymbol": "$",
|
||||
"nameCode": "currency.USD",
|
||||
"displayLabel": "US Dollar ($)"
|
||||
},
|
||||
"principal": 100000,
|
||||
"numberOfRepayments": 12,
|
||||
"loanTermFrequency": 12,
|
||||
"repaymentEvery": 1,
|
||||
"loanTermFrequencyType": {
|
||||
"id": 2,
|
||||
"code": "loanTermFrequency.periodFrequencyType.months",
|
||||
"value": "Months"
|
||||
},
|
||||
"repaymentFrequencyType": {
|
||||
"id": 2,
|
||||
"code": "repaymentFrequency.periodFrequencyType.months",
|
||||
"value": "Months"
|
||||
},
|
||||
"transactionProcessingStrategyId": 1,
|
||||
"transactionProcessingStrategyName": "Mifos style",
|
||||
"interestRatePerPeriod": 1.75,
|
||||
"interestRateFrequencyType": {
|
||||
"id": 2,
|
||||
"code": "interestRateFrequency.periodFrequencyType.months",
|
||||
"value": "Per month"
|
||||
},
|
||||
"annualInterestRate": 21,
|
||||
"amortizationType": {
|
||||
"id": 1,
|
||||
"code": "amortizationType.equal.installments",
|
||||
"value": "Equal installments"
|
||||
},
|
||||
"interestType": {
|
||||
"id": 0,
|
||||
"code": "interestType.declining.balance",
|
||||
"value": "Declining Balance"
|
||||
},
|
||||
"interestCalculationPeriodType": {
|
||||
"id": 1,
|
||||
"code": "interestCalculationPeriodType.same.as.repayment.period",
|
||||
"value": "Same as repayment period"
|
||||
},
|
||||
"accountingRule": {
|
||||
"id": 1,
|
||||
"code": "accountingRuleType.none",
|
||||
"value": "NONE"
|
||||
}
|
||||
{
|
||||
"id": 1,
|
||||
"name": "LP with Charges but no accounting)",
|
||||
"currency": {
|
||||
"code": "USD",
|
||||
"name": "US Dollar",
|
||||
"decimalPlaces": 2,
|
||||
"displaySymbol": "$",
|
||||
"nameCode": "currency.USD",
|
||||
"displayLabel": "US Dollar ($)"
|
||||
},
|
||||
"principal": 100000,
|
||||
"numberOfRepayments": 12,
|
||||
"repaymentEvery": 1,
|
||||
"repaymentFrequencyType": {
|
||||
"id": 2,
|
||||
"code": "repaymentFrequency.periodFrequencyType.months",
|
||||
"value": "Months"
|
||||
},
|
||||
"interestRatePerPeriod": 1.75,
|
||||
"interestRateFrequencyType": {
|
||||
"id": 2,
|
||||
"code": "interestRateFrequency.periodFrequencyType.months",
|
||||
"value": "Per month"
|
||||
},
|
||||
"annualInterestRate": 21,
|
||||
"amortizationType": {
|
||||
"id": 1,
|
||||
"code": "amortizationType.equal.installments",
|
||||
"value": "Equal installments"
|
||||
},
|
||||
"interestType": {
|
||||
"id": 0,
|
||||
"code": "interestType.declining.balance",
|
||||
"value": "Declining Balance"
|
||||
},
|
||||
"interestCalculationPeriodType": {
|
||||
"id": 1,
|
||||
"code": "interestCalculationPeriodType.same.as.repayment.period",
|
||||
"value": "Same as repayment period"
|
||||
},
|
||||
"transactionProcessingStrategyId": 1,
|
||||
"transactionProcessingStrategyName": "Mifos style",
|
||||
"accountingRule": {
|
||||
"id": 1,
|
||||
"code": "accountingRuleType.none",
|
||||
"value": "NONE"
|
||||
}
|
||||
}
|
||||
]
|
||||
</code>
|
||||
</div>
|
||||
@@ -5625,17 +5619,12 @@ GET https://DomainName/api/v1/loanproducts/template
|
||||
<code class="method-response">
|
||||
{
|
||||
"currency": {
|
||||
"code": "USD",
|
||||
"name": "US Dollar",
|
||||
"code": "UGX",
|
||||
"name": "Uganda Shilling",
|
||||
"decimalPlaces": 2,
|
||||
"displaySymbol": "$",
|
||||
"nameCode": "currency.USD",
|
||||
"displayLabel": "US Dollar ($)"
|
||||
},
|
||||
"loanTermFrequencyType": {
|
||||
"id": 2,
|
||||
"code": "loanTermFrequency.periodFrequencyType.months",
|
||||
"value": "Months"
|
||||
"displaySymbol": "USh",
|
||||
"nameCode": "currency.UGX",
|
||||
"displayLabel": "Uganda Shilling (USh)"
|
||||
},
|
||||
"repaymentFrequencyType": {
|
||||
"id": 2,
|
||||
@@ -5662,43 +5651,51 @@ GET https://DomainName/api/v1/loanproducts/template
|
||||
"code": "interestCalculationPeriodType.same.as.repayment.period",
|
||||
"value": "Same as repayment period"
|
||||
},
|
||||
"accountingRule": 1,
|
||||
"transactionProcessingStrategyId": 2,
|
||||
"transactionProcessingStrategyName": "Heavensfamily",
|
||||
"accountingRule": {
|
||||
"id": 1,
|
||||
"code": "accountingRuleType.none",
|
||||
"value": "NONE"
|
||||
},
|
||||
"accountingMappings": {},
|
||||
"currencyOptions": [
|
||||
{
|
||||
"code": "USD",
|
||||
"name": "US Dollar",
|
||||
"code": "UGX",
|
||||
"name": "Uganda Shilling",
|
||||
"decimalPlaces": 2,
|
||||
"displaySymbol": "$",
|
||||
"nameCode": "currency.USD",
|
||||
"displayLabel": "US Dollar ($)"
|
||||
"displaySymbol": "USh",
|
||||
"nameCode": "currency.UGX",
|
||||
"displayLabel": "Uganda Shilling (USh)"
|
||||
}
|
||||
],
|
||||
"fundOptions": [
|
||||
"repaymentFrequencyTypeOptions": [
|
||||
{
|
||||
"id": 0,
|
||||
"code": "repaymentFrequency.periodFrequencyType.days",
|
||||
"value": "Days"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "EU Agri Fund"
|
||||
}
|
||||
],
|
||||
"transactionProcessingStrategyOptions": [
|
||||
{
|
||||
"id": 1,
|
||||
"code": "mifos-standard-strategy",
|
||||
"name": "Mifos style"
|
||||
"code": "repaymentFrequency.periodFrequencyType.weeks",
|
||||
"value": "Weeks"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"code": "heavensfamily-strategy",
|
||||
"name": "Heavensfamily"
|
||||
"code": "repaymentFrequency.periodFrequencyType.months",
|
||||
"value": "Months"
|
||||
}
|
||||
],
|
||||
"interestRateFrequencyTypeOptions": [
|
||||
{
|
||||
"id": 2,
|
||||
"code": "interestRateFrequency.periodFrequencyType.months",
|
||||
"value": "Per month"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"code": "creocore-strategy",
|
||||
"name": "Creocore"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"code": "rbi-india-strategy",
|
||||
"name": "RBI (India)"
|
||||
"code": "interestRateFrequency.periodFrequencyType.years",
|
||||
"value": "Per year"
|
||||
}
|
||||
],
|
||||
"amortizationTypeOptions": [
|
||||
@@ -5737,58 +5734,274 @@ GET https://DomainName/api/v1/loanproducts/template
|
||||
"value": "Same as repayment period"
|
||||
}
|
||||
],
|
||||
"repaymentFrequencyTypeOptions": [
|
||||
{
|
||||
"id": 0,
|
||||
"code": "repaymentFrequency.periodFrequencyType.days",
|
||||
"value": "Days"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"code": "repaymentFrequency.periodFrequencyType.weeks",
|
||||
"value": "Weeks"
|
||||
},
|
||||
"transactionProcessingStrategyOptions": [
|
||||
{
|
||||
"id": 2,
|
||||
"code": "repaymentFrequency.periodFrequencyType.months",
|
||||
"value": "Months"
|
||||
}
|
||||
],
|
||||
"interestRateFrequencyTypeOptions": [
|
||||
{
|
||||
"id": 2,
|
||||
"code": "interestRateFrequency.periodFrequencyType.months",
|
||||
"value": "Per month"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"code": "interestRateFrequency.periodFrequencyType.years",
|
||||
"value": "Per year"
|
||||
}
|
||||
],
|
||||
"loanTermFrequencyTypeOptions": [
|
||||
{
|
||||
"id": 0,
|
||||
"code": "loanTermFrequency.periodFrequencyType.days",
|
||||
"value": "Days"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"code": "loanTermFrequency.periodFrequencyType.weeks",
|
||||
"value": "Weeks"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"code": "loanTermFrequency.periodFrequencyType.months",
|
||||
"value": "Months"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"code": "loanTermFrequency.periodFrequencyType.years",
|
||||
"value": "Years"
|
||||
"code": "heavensfamily-strategy",
|
||||
"name": "Heavensfamily"
|
||||
}
|
||||
],
|
||||
"chargeOptions": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Bank Fee (per installment)",
|
||||
"active": true,
|
||||
"penalty": false,
|
||||
"currency": {
|
||||
"code": "UGX",
|
||||
"name": "Uganda Shilling",
|
||||
"decimalPlaces": 2,
|
||||
"displaySymbol": "USh",
|
||||
"nameCode": "currency.UGX",
|
||||
"displayLabel": "Uganda Shilling (USh)"
|
||||
},
|
||||
"amount": 1500,
|
||||
"chargeTimeType": {
|
||||
"id": 2,
|
||||
"code": "chargeTimeType.specifiedDueDate",
|
||||
"value": "Specified due date"
|
||||
},
|
||||
"chargeAppliesTo": {
|
||||
"id": 1,
|
||||
"code": "chargeAppliesTo.loan",
|
||||
"value": "Loan"
|
||||
},
|
||||
"chargeCalculationType": {
|
||||
"id": 1,
|
||||
"code": "chargeCalculationType.flat",
|
||||
"value": "Flat"
|
||||
}
|
||||
}
|
||||
],
|
||||
"accountingRuleOptions": [
|
||||
{
|
||||
"id": 1,
|
||||
"code": "accountingRuleType.none",
|
||||
"value": "NONE"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"code": "accountingRuleType.cash",
|
||||
"value": "CASH BASED"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"code": "accountingRuleType.accrual",
|
||||
"value": "ACCRUAL BASED"
|
||||
}
|
||||
],
|
||||
"accountingMappingOptions": {
|
||||
"assetAccountOptions": [
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Cash in Valut 1",
|
||||
"glCode": "11101",
|
||||
"disabled": false,
|
||||
"manualEntriesAllowed": true,
|
||||
"type": {
|
||||
"id": 1,
|
||||
"code": "accountType.asset",
|
||||
"value": "ASSET"
|
||||
},
|
||||
"usage": {
|
||||
"id": 1,
|
||||
"code": "accountUsage.detail",
|
||||
"value": "DETAIL"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Centenary Opening Account",
|
||||
"glCode": "11201",
|
||||
"disabled": false,
|
||||
"manualEntriesAllowed": true,
|
||||
"type": {
|
||||
"id": 1,
|
||||
"code": "accountType.asset",
|
||||
"value": "ASSET"
|
||||
},
|
||||
"usage": {
|
||||
"id": 1,
|
||||
"code": "accountUsage.detail",
|
||||
"value": "DETAIL"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expenseAccountOptions": [
|
||||
{
|
||||
"id": 41,
|
||||
"name": "Water Charges",
|
||||
"glCode": "42102",
|
||||
"disabled": false,
|
||||
"manualEntriesAllowed": true,
|
||||
"type": {
|
||||
"id": 5,
|
||||
"code": "accountType.expense",
|
||||
"value": "EXPENSE"
|
||||
},
|
||||
"usage": {
|
||||
"id": 1,
|
||||
"code": "accountUsage.detail",
|
||||
"value": "DETAIL"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 42,
|
||||
"name": "Electricity Charges",
|
||||
"glCode": "42103",
|
||||
"disabled": false,
|
||||
"manualEntriesAllowed": true,
|
||||
"type": {
|
||||
"id": 5,
|
||||
"code": "accountType.expense",
|
||||
"value": "EXPENSE"
|
||||
},
|
||||
"usage": {
|
||||
"id": 1,
|
||||
"code": "accountUsage.detail",
|
||||
"value": "DETAIL"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 97,
|
||||
"name": "Miscellaneous",
|
||||
"glCode": "42905",
|
||||
"disabled": false,
|
||||
"manualEntriesAllowed": true,
|
||||
"type": {
|
||||
"id": 5,
|
||||
"code": "accountType.expense",
|
||||
"value": "EXPENSE"
|
||||
},
|
||||
"usage": {
|
||||
"id": 1,
|
||||
"code": "accountUsage.detail",
|
||||
"value": "DETAIL"
|
||||
}
|
||||
}
|
||||
],
|
||||
"incomeAccountOptions": [
|
||||
{
|
||||
"id": 34,
|
||||
"name": "Interest on Loans",
|
||||
"glCode": "31101",
|
||||
"disabled": false,
|
||||
"manualEntriesAllowed": true,
|
||||
"type": {
|
||||
"id": 4,
|
||||
"code": "accountType.income",
|
||||
"value": "INCOME"
|
||||
},
|
||||
"usage": {
|
||||
"id": 1,
|
||||
"code": "accountUsage.detail",
|
||||
"value": "DETAIL"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 35,
|
||||
"name": "Late Payment Interest",
|
||||
"glCode": "31102",
|
||||
"disabled": false,
|
||||
"manualEntriesAllowed": true,
|
||||
"type": {
|
||||
"id": 4,
|
||||
"code": "accountType.income",
|
||||
"value": "INCOME"
|
||||
},
|
||||
"usage": {
|
||||
"id": 1,
|
||||
"code": "accountUsage.detail",
|
||||
"value": "DETAIL"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 37,
|
||||
"name": "Collected Bank Fees Receivable",
|
||||
"glCode": "6201",
|
||||
"disabled": false,
|
||||
"manualEntriesAllowed": true,
|
||||
"type": {
|
||||
"id": 4,
|
||||
"code": "accountType.income",
|
||||
"value": "INCOME"
|
||||
},
|
||||
"usage": {
|
||||
"id": 1,
|
||||
"code": "accountUsage.detail",
|
||||
"value": "DETAIL"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
</code>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a id="loanproducts_retrieve" name="loanproducts_retrieve"
|
||||
class="old-syle-anchor"> </a>
|
||||
<div class="method-section">
|
||||
<div class="method-description">
|
||||
<h4>Retrieve a Loan Product</h4>
|
||||
<p>Example Requests:</p>
|
||||
<div class=apiClick>loanproducts/1</div>
|
||||
<br>
|
||||
<br>
|
||||
<div class=apiClick>loanproducts/1?template=true</div>
|
||||
<br>
|
||||
<br>
|
||||
<div class=apiClick>loanproducts/1?fields=name,description,numberOfRepayments</div>
|
||||
</div>
|
||||
<div class="method-example">
|
||||
<code class="method-declaration">
|
||||
GET https://DomainName/api/v1/loanproducts/{productId}
|
||||
</code>
|
||||
<code class="method-response">
|
||||
{
|
||||
"id": 1,
|
||||
"name": "LP with Charges but no accounting)",
|
||||
"currency": {
|
||||
"code": "USD",
|
||||
"name": "US Dollar",
|
||||
"decimalPlaces": 2,
|
||||
"displaySymbol": "$",
|
||||
"nameCode": "currency.USD",
|
||||
"displayLabel": "US Dollar ($)"
|
||||
},
|
||||
"principal": 100000,
|
||||
"numberOfRepayments": 12,
|
||||
"repaymentEvery": 1,
|
||||
"repaymentFrequencyType": {
|
||||
"id": 2,
|
||||
"code": "repaymentFrequency.periodFrequencyType.months",
|
||||
"value": "Months"
|
||||
},
|
||||
"interestRatePerPeriod": 1.75,
|
||||
"interestRateFrequencyType": {
|
||||
"id": 2,
|
||||
"code": "interestRateFrequency.periodFrequencyType.months",
|
||||
"value": "Per month"
|
||||
},
|
||||
"annualInterestRate": 21,
|
||||
"amortizationType": {
|
||||
"id": 1,
|
||||
"code": "amortizationType.equal.installments",
|
||||
"value": "Equal installments"
|
||||
},
|
||||
"interestType": {
|
||||
"id": 0,
|
||||
"code": "interestType.declining.balance",
|
||||
"value": "Declining Balance"
|
||||
},
|
||||
"interestCalculationPeriodType": {
|
||||
"id": 1,
|
||||
"code": "interestCalculationPeriodType.same.as.repayment.period",
|
||||
"value": "Same as repayment period"
|
||||
},
|
||||
"transactionProcessingStrategyId": 1,
|
||||
"transactionProcessingStrategyName": "Mifos style",
|
||||
"charges": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Loan service fee",
|
||||
@@ -5820,234 +6033,11 @@ GET https://DomainName/api/v1/loanproducts/template
|
||||
}
|
||||
}
|
||||
],
|
||||
"accountingOptions": {
|
||||
"assetAccountOptions": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Fund Source For Loans",
|
||||
"glCode": "100001",
|
||||
"disabled": false,
|
||||
"manualEntriesAllowed": true,
|
||||
"type": {
|
||||
"id": 1,
|
||||
"code": "accountType.asset",
|
||||
"value": "ASSET"
|
||||
},
|
||||
"usage": {
|
||||
"id": 1,
|
||||
"code": "accountUsage.detail",
|
||||
"value": "DETAIL"
|
||||
},
|
||||
"description": "Desc"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Interest Receivable",
|
||||
"glCode": "100002",
|
||||
"disabled": false,
|
||||
"manualEntriesAllowed": true,
|
||||
"type": {
|
||||
"id": 1,
|
||||
"code": "accountType.asset",
|
||||
"value": "ASSET"
|
||||
},
|
||||
"usage": {
|
||||
"id": 1,
|
||||
"code": "accountUsage.detail",
|
||||
"value": "DETAIL"
|
||||
},
|
||||
"description": "Desc"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Fees Receivable",
|
||||
"glCode": "100003",
|
||||
"disabled": false,
|
||||
"manualEntriesAllowed": true,
|
||||
"type": {
|
||||
"id": 1,
|
||||
"code": "accountType.asset",
|
||||
"value": "ASSET"
|
||||
},
|
||||
"usage": {
|
||||
"id": 1,
|
||||
"code": "accountUsage.detail",
|
||||
"value": "DETAIL"
|
||||
},
|
||||
"description": "Desc"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Penalties Receivable",
|
||||
"glCode": "100004",
|
||||
"disabled": false,
|
||||
"manualEntriesAllowed": true,
|
||||
"type": {
|
||||
"id": 1,
|
||||
"code": "accountType.asset",
|
||||
"value": "ASSET"
|
||||
},
|
||||
"usage": {
|
||||
"id": 1,
|
||||
"code": "accountUsage.detail",
|
||||
"value": "DETAIL"
|
||||
},
|
||||
"description": "better duddette"
|
||||
}
|
||||
],
|
||||
"expenseAccountOptions": [
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Written Off Losses",
|
||||
"glCode": "500005",
|
||||
"disabled": false,
|
||||
"manualEntriesAllowed": true,
|
||||
"type": {
|
||||
"id": 5,
|
||||
"code": "accountType.expense",
|
||||
"value": "EXPENSE"
|
||||
},
|
||||
"usage": {
|
||||
"id": 1,
|
||||
"code": "accountUsage.detail",
|
||||
"value": "DETAIL"
|
||||
},
|
||||
"description": "Desc"
|
||||
}
|
||||
],
|
||||
"incomeAccountOptions": [
|
||||
{
|
||||
"id": 6,
|
||||
"name": "Income from Interest",
|
||||
"glCode": "400001",
|
||||
"disabled": false,
|
||||
"manualEntriesAllowed": true,
|
||||
"type": {
|
||||
"id": 4,
|
||||
"code": "accountType.income",
|
||||
"value": "INCOME"
|
||||
},
|
||||
"usage": {
|
||||
"id": 1,
|
||||
"code": "accountUsage.detail",
|
||||
"value": "DETAIL"
|
||||
},
|
||||
"description": "Desc"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Income from Fees",
|
||||
"glCode": "400002",
|
||||
"disabled": false,
|
||||
"manualEntriesAllowed": true,
|
||||
"type": {
|
||||
"id": 4,
|
||||
"code": "accountType.income",
|
||||
"value": "INCOME"
|
||||
},
|
||||
"usage": {
|
||||
"id": 1,
|
||||
"code": "accountUsage.detail",
|
||||
"value": "DETAIL"
|
||||
},
|
||||
"description": "Desc"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Income from Penalties",
|
||||
"glCode": "400003",
|
||||
"disabled": false,
|
||||
"manualEntriesAllowed": true,
|
||||
"type": {
|
||||
"id": 4,
|
||||
"code": "accountType.income",
|
||||
"value": "INCOME"
|
||||
},
|
||||
"usage": {
|
||||
"id": 1,
|
||||
"code": "accountUsage.detail",
|
||||
"value": "DETAIL"
|
||||
},
|
||||
"description": "Desc"
|
||||
}
|
||||
]
|
||||
},
|
||||
"accountingMappings": {}
|
||||
}
|
||||
</code>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a id="loanproducts_retrieve" name="loanproducts_retrieve"
|
||||
class="old-syle-anchor"> </a>
|
||||
<div class="method-section">
|
||||
<div class="method-description">
|
||||
<h4>Retrieve a Loan Product</h4>
|
||||
<p>Example Requests:</p>
|
||||
<div class=apiClick>loanproducts/1</div>
|
||||
<br>
|
||||
<br>
|
||||
<div class=apiClick>loanproducts/1?template=true</div>
|
||||
<br>
|
||||
<br>
|
||||
<div class=apiClick>loanproducts/1?fields=name,description,numberOfRepayments</div>
|
||||
</div>
|
||||
<div class="method-example">
|
||||
<code class="method-declaration">
|
||||
GET https://DomainName/api/v1/loanproducts/{productId}
|
||||
</code>
|
||||
<code class="method-response">
|
||||
{
|
||||
"accountingRule": {
|
||||
"id": 1,
|
||||
"name": "A new loan product for me",
|
||||
"currency": {
|
||||
"code": "USD",
|
||||
"name": "US Dollar",
|
||||
"decimalPlaces": 2,
|
||||
"displaySymbol": "$",
|
||||
"nameCode": "currency.USD",
|
||||
"displayLabel": "US Dollar ($)"
|
||||
},
|
||||
"principal": 100000,
|
||||
"numberOfRepayments": 12,
|
||||
"loanTermFrequency": 12,
|
||||
"repaymentEvery": 1,
|
||||
"loanTermFrequencyType": {
|
||||
"id": 2,
|
||||
"code": "loanTermFrequency.periodFrequencyType.months",
|
||||
"value": "Months"
|
||||
},
|
||||
"repaymentFrequencyType": {
|
||||
"id": 2,
|
||||
"code": "repaymentFrequency.periodFrequencyType.months",
|
||||
"value": "Months"
|
||||
},
|
||||
"transactionProcessingStrategyId": 1,
|
||||
"transactionProcessingStrategyName": "Mifos style",
|
||||
"interestRatePerPeriod": 1.75,
|
||||
"interestRateFrequencyType": {
|
||||
"id": 2,
|
||||
"code": "interestRateFrequency.periodFrequencyType.months",
|
||||
"value": "Per month"
|
||||
},
|
||||
"annualInterestRate": 21,
|
||||
"amortizationType": {
|
||||
"id": 1,
|
||||
"code": "amortizationType.equal.installments",
|
||||
"value": "Equal installments"
|
||||
},
|
||||
"interestType": {
|
||||
"id": 0,
|
||||
"code": "interestType.declining.balance",
|
||||
"value": "Declining Balance"
|
||||
},
|
||||
"interestCalculationPeriodType": {
|
||||
"id": 1,
|
||||
"code": "interestCalculationPeriodType.same.as.repayment.period",
|
||||
"value": "Same as repayment period"
|
||||
},
|
||||
"accountingRule": 1,
|
||||
"charges": []
|
||||
"code": "accountingRuleType.none",
|
||||
"value": "NONE"
|
||||
}
|
||||
}
|
||||
</code>
|
||||
</div>
|
||||
@@ -6074,11 +6064,17 @@ GET https://DomainName/api/v1/loanproducts/{productId}
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>name, currencyCode, digitsAfterDecimal, principal,
|
||||
inArrearsTolerance, repaymentFrequencyType, repaymentEvery,
|
||||
numberOfRepayments, interestRatePerPeriod,
|
||||
interestRateFrequencyType, amortizationType, interestType,
|
||||
interestCalculationPeriodType, accountingRule</td>
|
||||
numberOfRepayments, repaymentEvery, repaymentFrequencyType,
|
||||
interestRatePerPeriod, interestRateFrequencyType, amortizationType, interestType,
|
||||
interestCalculationPeriodType, transactionProcessingStrategyId, accountingRule</td>
|
||||
</tr>
|
||||
<tr class="matrixHeadingBG">
|
||||
<td><div class="mifosXHeading2">Optional Fields</div></td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>inArrearsTolerance, charges</td>
|
||||
</tr>
|
||||
|
||||
<tr class="matrixHeadingBG">
|
||||
<td><div class="mifosXHeading2">Additional Mandatory Fields for Cash(2) based accounting</div></td>
|
||||
</tr>
|
||||
@@ -6107,7 +6103,7 @@ POST loanproducts
|
||||
Content-Type: application/json
|
||||
Request Body:
|
||||
{
|
||||
"name": "A new loan product for me",
|
||||
"name": "LP with Charges but no accounting)",
|
||||
"currencyCode": "USD",
|
||||
"locale": "en_GB",
|
||||
"digitsAfterDecimal": "2",
|
||||
@@ -6115,12 +6111,14 @@ Request Body:
|
||||
"numberOfRepayments": "12",
|
||||
"repaymentEvery": "1",
|
||||
"repaymentFrequencyType": 2,
|
||||
"transactionProcessingStrategyId": 1,
|
||||
"interestRatePerPeriod": "1.75",
|
||||
"interestRateFrequencyType": 2,
|
||||
"amortizationType": 1,
|
||||
"interestType": 0,
|
||||
"interestCalculationPeriodType": 1,
|
||||
"inArrearsTolerance": "0",
|
||||
"transactionProcessingStrategyId": 1,
|
||||
"charges":[{"id":"1"},{"id":"1"}],
|
||||
"accountingRule": 1
|
||||
}
|
||||
</code>
|
||||
@@ -6134,7 +6132,7 @@ POST loanproducts
|
||||
Content-Type: application/json
|
||||
Request Body:
|
||||
{
|
||||
"name": "A new loan product for me",
|
||||
"name": "LP Cash Accounting",
|
||||
"currencyCode": "USD",
|
||||
"locale": "en_GB",
|
||||
"digitsAfterDecimal": "2",
|
||||
@@ -6148,13 +6146,13 @@ Request Body:
|
||||
"amortizationType": 1,
|
||||
"interestType": 0,
|
||||
"interestCalculationPeriodType": 1,
|
||||
"accountingRule":"3",
|
||||
"fundSourceAccountId":"15",
|
||||
"loanPortfolioAccountId":"16",
|
||||
"interestOnLoanAccountId":"14",
|
||||
"incomeFromFeeAccountId":"13",
|
||||
"incomeFromPenaltyAccountId":"12",
|
||||
"writeOffAccountId":"11"
|
||||
"accountingRule":"2",
|
||||
"fundSourceAccountId":"4",
|
||||
"loanPortfolioAccountId":"8",
|
||||
"interestOnLoanAccountId":"34",
|
||||
"incomeFromFeeAccountId":"37",
|
||||
"incomeFromPenaltyAccountId":"35",
|
||||
"writeOffAccountId":"41"
|
||||
}
|
||||
</code>
|
||||
<code class="method-response">
|
||||
@@ -6167,7 +6165,7 @@ POST loanproducts
|
||||
Content-Type: application/json
|
||||
Request Body:
|
||||
{
|
||||
"name": "A new loan product for me",
|
||||
"name": "LP Accrual Accounting",
|
||||
"currencyCode": "USD",
|
||||
"locale": "en_GB",
|
||||
"digitsAfterDecimal": "2",
|
||||
@@ -6182,15 +6180,15 @@ Request Body:
|
||||
"interestType": 0,
|
||||
"interestCalculationPeriodType": 1,
|
||||
"accountingRule":"3",
|
||||
"fundSourceAccountId":"15",
|
||||
"loanPortfolioAccountId":"16",
|
||||
"receivableInterestAccountId":"10",
|
||||
"receivableFeeAccountId":"9",
|
||||
"receivablePenaltyAccountId":"8",
|
||||
"interestOnLoanAccountId":"14",
|
||||
"incomeFromFeeAccountId":"13",
|
||||
"incomeFromPenaltyAccountId":"12",
|
||||
"writeOffAccountId":"11"
|
||||
"fundSourceAccountId":"4",
|
||||
"loanPortfolioAccountId":"8",
|
||||
"receivableInterestAccountId":"9",
|
||||
"receivableFeeAccountId":"11",
|
||||
"receivablePenaltyAccountId":"10",
|
||||
"interestOnLoanAccountId":"34",
|
||||
"incomeFromFeeAccountId":"37",
|
||||
"incomeFromPenaltyAccountId":"35",
|
||||
"writeOffAccountId":"41"
|
||||
}
|
||||
</code>
|
||||
<code class="method-response">
|
||||
@@ -6823,7 +6821,8 @@ Request Body:
|
||||
"locale": "en",
|
||||
"amount": "230.56",
|
||||
"chargeTimeType": "1",
|
||||
"chargeCalculationType": "1"
|
||||
"chargeCalculationType": "1",
|
||||
"active": true
|
||||
}
|
||||
</code>
|
||||
<code class="method-response">{ "resourceId": 1 }</code>
|
||||
|
||||
+103
-1
@@ -116,4 +116,106 @@ from x_registered_table r;
|
||||
|
||||
insert into m_permission(grouping, `code`, entity_name, action_name)
|
||||
select 'datatable', concat('DELETE_', r.registered_table_name), r.registered_table_name, 'DELETE'
|
||||
from x_registered_table r;
|
||||
from x_registered_table r;
|
||||
|
||||
|
||||
|
||||
-- ==== Chart of Accounts =====
|
||||
truncate `acc_gl_account`;
|
||||
INSERT INTO `acc_gl_account` VALUES
|
||||
(1,'Petty Cash Balances',NULL,'11100',0,1,2,1,NULL),
|
||||
(2,'Cash in Valut 1',NULL,'11101',0,1,1,1,NULL),
|
||||
(3,'Bank Balances',NULL,'11200',0,1,2,1,NULL),
|
||||
(4,'Centenary Opening Account',NULL,'11201',0,1,1,1,NULL),
|
||||
(5,'Centenary Expense Account',NULL,'11202',0,1,1,1,NULL),
|
||||
(6,'Centenary USD Account',NULL,'11203',0,1,1,1,NULL),
|
||||
(7,'Loans and Advances',NULL,'13100',0,1,2,1,NULL),
|
||||
(8,'Loans to Clients',NULL,'13101',0,1,1,1,NULL),
|
||||
(9,'Outstanding Interest',NULL,'13102',0,1,1,1,NULL),
|
||||
(10,'Outstanding Late Payment Interest',NULL,'13103',0,1,1,1,NULL),
|
||||
(11,'Outstanding Bank Fees to be collected',NULL,'13104',0,1,1,1,NULL),
|
||||
(12,'WriteOff Accounts',NULL,'13200',0,1,2,1,NULL),
|
||||
(13,'Write-offs (use for funds coming in)',NULL,'13201',0,1,1,1,NULL),
|
||||
(14,'Write-offs outstanding principal',NULL,'13202',0,1,1,1,NULL),
|
||||
(15,'Write-offs outstanding interest',NULL,'13203',0,1,1,1,NULL),
|
||||
(16,'Write-offs collected bank fees',NULL,'13204',0,1,1,1,NULL),
|
||||
(17,'Write-offs hardware/furniture',NULL,'13205',0,1,1,1,NULL),
|
||||
(18,'Fixed Assets',NULL,'14100',0,1,2,1,NULL),
|
||||
(19,'Office Equipment',NULL,'14101',0,1,1,1,NULL),
|
||||
(20,'Suspense Items (unidentified deposits)',NULL,'15000',0,1,2,1,NULL),
|
||||
(21,'Assets',NULL,'10000',0,1,2,1,NULL),
|
||||
(22,'Liabilities',NULL,'20000',0,1,2,2,NULL),
|
||||
(23,'Shares Account',NULL,'26100',0,1,2,2,NULL),
|
||||
(24,'Shares Captial',NULL,'26101',0,1,1,2,NULL),
|
||||
(25,'Donated Equity',NULL,'26300',0,1,2,2,NULL),
|
||||
(26,'Donated Equity Ameropa Foundation',NULL,'26301',0,1,1,2,NULL),
|
||||
(27,'Donated Equity e.h',NULL,'26302',0,1,1,2,NULL),
|
||||
(28,'Overpaid Amounts',NULL,'27000',0,1,2,2,NULL),
|
||||
(29,'Loss Provision',NULL,'28000',0,1,2,2,NULL),
|
||||
(30,'Provision Outstanding Principal',NULL,'28001',0,1,1,2,NULL),
|
||||
(31,'Provision Oustanding Interest',NULL,'28002',0,1,1,2,NULL),(32,'Income',NULL,'30000',0,1,2,4,NULL),
|
||||
(33,'Interest Income from Loans',NULL,'31100',0,1,2,4,NULL),
|
||||
(34,'Interest on Loans',NULL,'31101',0,1,1,4,NULL),
|
||||
(35,'Late Payment Interest',NULL,'31102',0,1,1,4,NULL),
|
||||
(36,'Income from Micro credit & Lending Activities',NULL,'31300',0,1,2,4,NULL),
|
||||
(37,'Collected Bank Fees Receivable',NULL,'6201',0,1,1,4,NULL),
|
||||
(38,'Deposits from Loans Write Off',NULL,'31400',0,1,2,4,NULL),
|
||||
(39,'Expenditure',NULL,'40000',0,1,2,5,NULL),
|
||||
(40,'Office Expenditure Account',NULL,'42100',0,1,2,5,NULL),
|
||||
(41,'Water Charges',NULL,'42102',0,1,1,5,NULL),
|
||||
(42,'Electricity Charges',NULL,'42103',0,1,1,5,NULL),
|
||||
(43,'Printing and Stationary',NULL,'42105',0,1,1,5,NULL),
|
||||
(44,'Office Rent',NULL,'42107',0,1,1,5,NULL),
|
||||
(45,'Marketing Expense',NULL,'42109',0,1,1,5,NULL),
|
||||
(46,'Office utilities',NULL,'42112',0,1,1,5,'(supplies, toiletries, kitchen)'),
|
||||
(47,'Furniture',NULL,'42113',0,1,1,5,NULL),
|
||||
(48,'CEDA Meeting Expense',NULL,'42114',0,1,1,5,NULL),
|
||||
(49,'Employee Personal Expsense Account',NULL,'42200',0,1,2,5,NULL),
|
||||
(50,'Salary Alice',NULL,'42201',0,1,1,5,NULL),
|
||||
(51,'Salary Irene',NULL,'42202',0,1,1,5,NULL),
|
||||
(52,'Salary Richard',NULL,'42203',0,1,1,5,NULL),
|
||||
(53,'Salary Loan Officer TBA',NULL,'42204',0,1,1,5,NULL),
|
||||
(54,'Medical Insurance Alice & Family',NULL,'42205',0,1,1,5,NULL),
|
||||
(55,'Medical Insurance Irene',NULL,'42206',0,1,1,5,NULL),
|
||||
(56,'Medical Insurance Richard',NULL,'42207',0,1,1,5,NULL),
|
||||
(57,'Medical Insurance Loan Officer TBA',NULL,'42208',0,1,1,5,NULL),
|
||||
(58,'PAYE all employees',NULL,'42209',0,1,1,5,NULL),
|
||||
(59,'NSSF all employees',NULL,'42210',0,1,1,5,NULL),
|
||||
(60,'Lunch Allowances all employees',NULL,'42211',0,1,1,5,NULL),
|
||||
(61,'IT software and maintenance',NULL,'42300',0,1,2,5,NULL),
|
||||
(62,'Mifos maintenance contract 12 months',NULL,'42301',0,1,1,5,NULL),
|
||||
(63,'VPS Contract 12 months',NULL,'42302',0,1,1,5,NULL),
|
||||
(64,'Bulk SMS Service',NULL,'42303',0,1,1,5,NULL),
|
||||
(65,'Support Accounting Software',NULL,'42304',0,1,1,5,NULL),
|
||||
(66,'Mifos Instance Setup',NULL,'42305',0,1,1,5,NULL),
|
||||
(67,'Misc support expense',NULL,'42306',0,1,1,5,NULL),
|
||||
(68,'Warid Mobile Line',NULL,'42307',0,1,1,5,NULL),
|
||||
(69,'Landline',NULL,'42308',0,1,1,5,NULL),
|
||||
(70,'Modem Alice',NULL,'42309',0,1,1,5,NULL),
|
||||
(71,'Modem Irene',NULL,'42310',0,1,1,5,NULL),
|
||||
(72,'Modem Richard',NULL,'42311',0,1,1,5,NULL),
|
||||
(73,'Repairs',NULL,'42312',0,1,1,5,NULL),
|
||||
(74,'Airtime Expenses',NULL,'42400',0,1,2,5,NULL),
|
||||
(75,'Airtime Alice',NULL,'42401',0,1,1,5,NULL),
|
||||
(76,'Airtime Richard',NULL,'42402',0,1,1,5,NULL),
|
||||
(77,'Airtime Loan Office TBA',NULL,'42403',0,1,1,5,NULL),
|
||||
(78,'Special Airtime Alice',NULL,'42404',0,1,1,5,NULL),
|
||||
(79,'Transportation',NULL,'42500',0,1,2,5,NULL),
|
||||
(80,'Flat monthly transportation cost',NULL,'42501',0,1,1,5,NULL),
|
||||
(81,'Faciliation cost for Richard',NULL,'42502',0,1,1,5,NULL),
|
||||
(82,'Faciliation cost for Loan Officer TBA',NULL,'42503',0,1,1,5,NULL),
|
||||
(83,'Consultancy Expenses',NULL,'42600',0,1,2,5,NULL),
|
||||
(84,'Audit Fees',NULL,'42601',0,1,1,5,NULL),
|
||||
(85,'Legal Fees',NULL,'42602',0,1,1,5,NULL),
|
||||
(86,'Miscellaneous Expenses Account',NULL,'42700',0,1,2,5,NULL),
|
||||
(87,'MFI License',NULL,'42703',0,1,1,5,NULL),
|
||||
(88,'Sundy Expenses',NULL,'42704',0,1,1,5,NULL),
|
||||
(89,'Bank Fees',NULL,'42800',0,1,2,5,NULL),
|
||||
(90,'Bank Charges Operating Account',NULL,'42801',0,1,1,5,NULL),
|
||||
(91,'Bank Charges Expense Account',NULL,'42802',0,1,1,5,NULL),
|
||||
(92,'E.H Account',NULL,'42900',0,1,2,5,NULL),
|
||||
(93,'Airtime',NULL,'42901',0,1,1,5,NULL),
|
||||
(94,'Modem',NULL,'42902',0,1,1,5,NULL),
|
||||
(95,'Meals',NULL,'42903',0,1,1,5,NULL),
|
||||
(96,'Transportation',NULL,'42904',0,1,1,5,NULL),
|
||||
(97,'Miscellaneous',NULL,'42905',0,1,1,5,NULL);
|
||||
+16
-2
@@ -17,6 +17,7 @@ import org.mifosplatform.infrastructure.security.domain.BasicPasswordEncodablePl
|
||||
import org.mifosplatform.infrastructure.security.domain.PlatformUser;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformPasswordEncoder;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
/**
|
||||
@@ -39,8 +40,8 @@ public final class JsonCommand {
|
||||
private final Long apptableId;
|
||||
private final Long datatableId;
|
||||
private final Long codeId;
|
||||
private String supportedEntityType;
|
||||
private Long supportedEntityId;
|
||||
private final String supportedEntityType;
|
||||
private final Long supportedEntityId;
|
||||
private final String transactionId;
|
||||
|
||||
public static JsonCommand from(final String jsonCommand, final JsonElement parsedCommand, final FromJsonHelper fromApiJsonHelper,
|
||||
@@ -86,6 +87,15 @@ public final class JsonCommand {
|
||||
return this.parsedCommand;
|
||||
}
|
||||
|
||||
public String jsonFragment(final String paramName) {
|
||||
String jsonFragment = null;
|
||||
if (this.parsedCommand.getAsJsonObject().has(paramName)) {
|
||||
JsonElement fragment = this.parsedCommand.getAsJsonObject().get(paramName);
|
||||
jsonFragment = this.fromApiJsonHelper.toJson(fragment);
|
||||
}
|
||||
return jsonFragment;
|
||||
}
|
||||
|
||||
public Long commandId() {
|
||||
return this.commandId;
|
||||
}
|
||||
@@ -347,6 +357,10 @@ public final class JsonCommand {
|
||||
return this.fromApiJsonHelper.extractArrayNamed(parameterName, parsedCommand);
|
||||
}
|
||||
|
||||
public JsonArray arrayOfParameterNamed(final String parameterName) {
|
||||
return this.fromApiJsonHelper.extractJsonArrayNamed(parameterName, parsedCommand);
|
||||
}
|
||||
|
||||
public boolean isChangeInPasswordParameterNamed(final String parameterName, final String existingValue,
|
||||
final PlatformPasswordEncoder platformPasswordEncoder, final Long saltValue) {
|
||||
boolean isChanged = false;
|
||||
|
||||
+7
-2
@@ -21,6 +21,7 @@ import org.mifosplatform.infrastructure.core.exception.UnsupportedParameterExcep
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
@@ -46,7 +47,7 @@ public class FromJsonHelper {
|
||||
return this.gsonConverter.fromJson(json, typeOfMap);
|
||||
}
|
||||
|
||||
public <T> T fromJson(final String json, Class<T> classOfT) {
|
||||
public <T> T fromJson(final String json, final Class<T> classOfT) {
|
||||
return this.gsonConverter.fromJson(json, classOfT);
|
||||
}
|
||||
|
||||
@@ -93,6 +94,10 @@ public class FromJsonHelper {
|
||||
return helperDelegator.extractLongNamed(parameterName, element, parametersPassedInRequest);
|
||||
}
|
||||
|
||||
public JsonArray extractJsonArrayNamed(final String parameterName, final JsonElement element) {
|
||||
return helperDelegator.extractJsonArrayNamed(parameterName, element);
|
||||
}
|
||||
|
||||
public String[] extractArrayNamed(final String parameterName, final JsonElement element) {
|
||||
return helperDelegator.extractArrayNamed(parameterName, element, new HashSet<String>());
|
||||
}
|
||||
@@ -109,7 +114,7 @@ public class FromJsonHelper {
|
||||
return helperDelegator.extractBooleanNamed(parameterName, element, parametersPassedInRequest);
|
||||
}
|
||||
|
||||
public LocalDate extractLocalDateNamed(final String parameterName, JsonElement element) {
|
||||
public LocalDate extractLocalDateNamed(final String parameterName, final JsonElement element) {
|
||||
return helperDelegator.extractLocalDateNamed(parameterName, element, new HashSet<String>());
|
||||
}
|
||||
|
||||
|
||||
+24
-10
@@ -32,7 +32,7 @@ import com.google.gson.JsonPrimitive;
|
||||
* Helper class to extract values of json named attributes.
|
||||
*/
|
||||
public class JsonParserHelper {
|
||||
|
||||
|
||||
public boolean parameterExists(final String parameterName, final JsonElement element) {
|
||||
return element.getAsJsonObject().has(parameterName);
|
||||
}
|
||||
@@ -137,19 +137,21 @@ public class JsonParserHelper {
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/** Method used to extract integers from unformatted strings.
|
||||
* Ex: "1" , "100002" etc
|
||||
|
||||
/**
|
||||
* Method used to extract integers from unformatted strings. Ex: "1" ,
|
||||
* "100002" etc
|
||||
*
|
||||
* Please note that this method does not support extracting Integers from locale
|
||||
* specific formatted strings Ex "1,000" etc
|
||||
* Please note that this method does not support extracting Integers from
|
||||
* locale specific formatted strings Ex "1,000" etc
|
||||
*
|
||||
* @param parameterName
|
||||
* @param element
|
||||
* @param parametersPassedInRequest
|
||||
* @return
|
||||
*/
|
||||
public Integer extractIntegerSansLocaleNamed(final String parameterName, final JsonElement element, final Set<String> parametersPassedInRequest) {
|
||||
public Integer extractIntegerSansLocaleNamed(final String parameterName, final JsonElement element,
|
||||
final Set<String> parametersPassedInRequest) {
|
||||
Integer intValue = null;
|
||||
if (element.isJsonObject()) {
|
||||
JsonObject object = element.getAsJsonObject();
|
||||
@@ -211,6 +213,19 @@ public class JsonParserHelper {
|
||||
return arrayValue;
|
||||
}
|
||||
|
||||
public JsonArray extractJsonArrayNamed(final String parameterName, final JsonElement element) {
|
||||
JsonArray jsonArray = null;
|
||||
|
||||
if (element.isJsonObject()) {
|
||||
JsonObject object = element.getAsJsonObject();
|
||||
if (object.has(parameterName)) {
|
||||
jsonArray = object.get(parameterName).getAsJsonArray();
|
||||
}
|
||||
}
|
||||
|
||||
return jsonArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used with the local date is in array format
|
||||
*/
|
||||
@@ -391,8 +406,8 @@ public class JsonParserHelper {
|
||||
} catch (NumberFormatException e) {
|
||||
|
||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.integer", "The parameter "
|
||||
+ parameterName + " has value: " + numericalValueFormatted + " which is invalid integer.", parameterName, numericalValueFormatted);
|
||||
ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.integer", "The parameter " + parameterName
|
||||
+ " has value: " + numericalValueFormatted + " which is invalid integer.", parameterName, numericalValueFormatted);
|
||||
dataValidationErrors.add(error);
|
||||
|
||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||
@@ -400,7 +415,6 @@ public class JsonParserHelper {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public BigDecimal convertFrom(final String numericalValueFormatted, final String parameterName, final Locale clientApplicationLocale) {
|
||||
|
||||
if (clientApplicationLocale == null) {
|
||||
|
||||
+15
-30
@@ -11,11 +11,12 @@ import java.util.List;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData;
|
||||
|
||||
/**
|
||||
* Immutable data object for charge data.
|
||||
*/
|
||||
public class ChargeData {
|
||||
public class ChargeData implements Comparable<ChargeData> {
|
||||
|
||||
private final Long id;
|
||||
private final String name;
|
||||
@@ -72,36 +73,8 @@ public class ChargeData {
|
||||
this.chargeTimeTypeOptions = chargeTimeTypeOptions;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isPenalty() {
|
||||
return this.penalty;
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public CurrencyData getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
public EnumOptionData getChargeTimeType() {
|
||||
return chargeTimeType;
|
||||
}
|
||||
|
||||
public EnumOptionData getChargeCalculationType() {
|
||||
return chargeCalculationType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean equals(final Object obj) {
|
||||
ChargeData chargeData = (ChargeData) obj;
|
||||
return this.id.equals(chargeData.id);
|
||||
}
|
||||
@@ -110,4 +83,16 @@ public class ChargeData {
|
||||
public int hashCode() {
|
||||
return this.id.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final ChargeData obj) {
|
||||
if (obj == null) { return -1; }
|
||||
|
||||
return obj.id.compareTo(this.id);
|
||||
}
|
||||
|
||||
public LoanChargeData toLoanChargeData() {
|
||||
return LoanChargeData.newLoanChargeDetails(this.id, this.name, this.currency, this.amount, this.chargeTimeType,
|
||||
this.chargeCalculationType, this.penalty);
|
||||
}
|
||||
}
|
||||
+40
-3
@@ -14,8 +14,15 @@ import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
import org.mifosplatform.portfolio.charge.data.ChargeData;
|
||||
import org.mifosplatform.portfolio.charge.exception.ChargeDueAtDisbursementCannotBePenaltyException;
|
||||
import org.mifosplatform.portfolio.charge.service.ChargeEnumerations;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@Entity
|
||||
@@ -71,7 +78,7 @@ public class Charge extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
private Charge(final String name, final BigDecimal amount, final String currencyCode, final ChargeAppliesTo chargeAppliesTo,
|
||||
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculationType, final boolean penalty, boolean active) {
|
||||
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculationType, final boolean penalty, final boolean active) {
|
||||
this.name = name;
|
||||
this.amount = amount;
|
||||
this.currencyCode = currencyCode;
|
||||
@@ -83,6 +90,24 @@ public class Charge extends AbstractPersistable<Long> {
|
||||
if (penalty && chargeTime.isTimeOfDisbursement()) { throw new ChargeDueAtDisbursementCannotBePenaltyException(name); }
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (obj == null) { return false; }
|
||||
if (obj == this) { return true; }
|
||||
if (obj.getClass() != getClass()) { return false; }
|
||||
LoanCharge rhs = (LoanCharge) obj;
|
||||
return new EqualsBuilder().appendSuper(super.equals(obj)) //
|
||||
.append(this.getId(), rhs.getId()) //
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(3, 5) //
|
||||
.append(this.getId()) //
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -180,8 +205,9 @@ public class Charge extends AbstractPersistable<Long> {
|
||||
actualChanges.put(activeParamName, newValue);
|
||||
this.active = newValue;
|
||||
}
|
||||
|
||||
if (this.penalty && ChargeTimeType.fromInt(this.chargeTime).isTimeOfDisbursement()) { throw new ChargeDueAtDisbursementCannotBePenaltyException(name); }
|
||||
|
||||
if (this.penalty && ChargeTimeType.fromInt(this.chargeTime).isTimeOfDisbursement()) { throw new ChargeDueAtDisbursementCannotBePenaltyException(
|
||||
name); }
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
@@ -196,4 +222,15 @@ public class Charge extends AbstractPersistable<Long> {
|
||||
this.deleted = true;
|
||||
this.name = this.getId() + "_" + this.name;
|
||||
}
|
||||
|
||||
public ChargeData toData() {
|
||||
|
||||
EnumOptionData chargeTimeType = ChargeEnumerations.chargeTimeType(this.chargeTime);
|
||||
EnumOptionData chargeAppliesTo = ChargeEnumerations.chargeAppliesTo(this.chargeAppliesTo);
|
||||
EnumOptionData chargeCalculationType = ChargeEnumerations.chargeCalculationType(this.chargeCalculation);
|
||||
|
||||
CurrencyData currency = new CurrencyData(this.currencyCode, null, 0, null, null);
|
||||
return ChargeData.instance(this.getId(), this.name, this.amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType,
|
||||
penalty, active);
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -353,8 +353,7 @@ public class LoanAccountData {
|
||||
|
||||
final Collection<LoanChargeData> charges = new ArrayList<LoanChargeData>();
|
||||
for (ChargeData charge : product.charges()) {
|
||||
charges.add(LoanChargeData.newLoanChargeDetails(charge.getId(), charge.getName(), charge.getCurrency(), charge.getAmount(),
|
||||
charge.getChargeTimeType(), charge.getChargeCalculationType(), charge.isPenalty()));
|
||||
charges.add(charge.toLoanChargeData());
|
||||
}
|
||||
|
||||
return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId,
|
||||
|
||||
+16
-16
@@ -57,12 +57,13 @@ import org.springframework.stereotype.Component;
|
||||
public class LoanProductsApiResource {
|
||||
|
||||
private final Set<String> LOAN_PRODUCT_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "name", "description", "fundId",
|
||||
"fundName", "transactionProcessingStrategyId", "transactionProcessingStrategyName", "principal", "inArrearsTolerance",
|
||||
"numberOfRepayments", "repaymentEvery", "interestRatePerPeriod", "annualInterestRate", "repaymentFrequencyType",
|
||||
"interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType", "charges", "createdOn",
|
||||
"lastModifedOn", "currencyOptions", "amortizationTypeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions",
|
||||
"repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "fundOptions", "transactionProcessingStrategyOptions",
|
||||
"chargeOptions", "accountingOptions", "accountingRule","accountingRuleOptions","accountingMappings","accountingMappingOptions"));
|
||||
"fundName", "currency", "principal", "numberOfRepayments", "repaymentEvery", "repaymentFrequencyType", "interestRatePerPeriod",
|
||||
"interestRateFrequencyType", "annualInterestRate", "amortizationType", "interestType", "interestCalculationPeriodType",
|
||||
"inArrearsTolerance", "transactionProcessingStrategyId", "transactionProcessingStrategyName", "charges", "accountingRule",
|
||||
"accountingMappings", "fundOptions", "currencyOptions", "repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions",
|
||||
"amortizationTypeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions",
|
||||
"transactionProcessingStrategyOptions", "chargeOptions", "accountingOptions", "accountingRuleOptions",
|
||||
"accountingMappingOptions"));
|
||||
|
||||
private final String resourceNameForPermissions = "LOANPRODUCT";
|
||||
|
||||
@@ -129,7 +130,7 @@ public class LoanProductsApiResource {
|
||||
@Path("template")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retrieveNewLoanProductDetails(@Context final UriInfo uriInfo) {
|
||||
public String retrieveTemplate(@Context final UriInfo uriInfo) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions);
|
||||
|
||||
@@ -154,7 +155,8 @@ public class LoanProductsApiResource {
|
||||
|
||||
Map<String, Object> accountingMappings = null;
|
||||
if (loanProduct.hasAccountingEnabled()) {
|
||||
accountingMappings = accountMappingReadPlatformService.fetchAccountMappingDetailsForLoanProduct(productId, loanProduct.accountingRuleType().getId().intValue());
|
||||
accountingMappings = accountMappingReadPlatformService.fetchAccountMappingDetailsForLoanProduct(productId, loanProduct
|
||||
.accountingRuleType().getId().intValue());
|
||||
loanProduct = LoanProductData.withAccountingMappings(loanProduct, accountingMappings);
|
||||
}
|
||||
|
||||
@@ -182,7 +184,6 @@ public class LoanProductsApiResource {
|
||||
|
||||
final boolean feeChargesOnly = true;
|
||||
Collection<ChargeData> chargeOptions = this.chargeReadPlatformService.retrieveLoanApplicableCharges(feeChargesOnly);
|
||||
chargeOptions.removeAll(productData.charges());
|
||||
if (chargeOptions.isEmpty()) {
|
||||
chargeOptions = null;
|
||||
}
|
||||
@@ -192,7 +193,6 @@ public class LoanProductsApiResource {
|
||||
final List<EnumOptionData> interestTypeOptions = dropdownReadPlatformService.retrieveLoanInterestTypeOptions();
|
||||
final List<EnumOptionData> interestCalculationPeriodTypeOptions = dropdownReadPlatformService
|
||||
.retrieveLoanInterestRateCalculatedInPeriodOptions();
|
||||
final List<EnumOptionData> loanTermFrequencyTypeOptions = dropdownReadPlatformService.retrieveLoanTermFrequencyTypeOptions();
|
||||
final List<EnumOptionData> repaymentFrequencyTypeOptions = dropdownReadPlatformService.retrieveRepaymentFrequencyTypeOptions();
|
||||
final List<EnumOptionData> interestRateFrequencyTypeOptions = dropdownReadPlatformService
|
||||
.retrieveInterestRateFrequencyTypeOptions();
|
||||
@@ -204,29 +204,29 @@ public class LoanProductsApiResource {
|
||||
final Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions = this.dropdownReadPlatformService
|
||||
.retreiveTransactionProcessingStrategies();
|
||||
|
||||
Map<String, List<GLAccountData>> accountOptions= new HashMap<String, List<GLAccountData>>();
|
||||
Map<String, List<GLAccountData>> accountOptions = new HashMap<String, List<GLAccountData>>();
|
||||
List<GLAccountData> assetAccountOptions = accountReadPlatformService.retrieveAllEnabledDetailGLAccounts(GLAccountType.ASSET);
|
||||
if (assetAccountOptions.isEmpty()) {
|
||||
assetAccountOptions = null;
|
||||
}
|
||||
accountOptions.put("assetAccountOptions", assetAccountOptions);
|
||||
|
||||
|
||||
List<GLAccountData> incomeAccountOptions = accountReadPlatformService.retrieveAllEnabledDetailGLAccounts(GLAccountType.INCOME);
|
||||
if (incomeAccountOptions.isEmpty()) {
|
||||
incomeAccountOptions = null;
|
||||
}
|
||||
accountOptions.put("incomeAccountOptions", incomeAccountOptions);
|
||||
|
||||
|
||||
List<GLAccountData> expenseAccountOptions = accountReadPlatformService.retrieveAllEnabledDetailGLAccounts(GLAccountType.EXPENSE);
|
||||
if (expenseAccountOptions.isEmpty()) {
|
||||
expenseAccountOptions = null;
|
||||
}
|
||||
accountOptions.put("expenseAccountOptions", expenseAccountOptions);
|
||||
|
||||
|
||||
List<EnumOptionData> accountingRuleTypeOptions = dropdownReadPlatformService.retrieveAccountingRuleTypeOptions();
|
||||
|
||||
return new LoanProductData(productData, chargeOptions, currencyOptions, amortizationTypeOptions, interestTypeOptions,
|
||||
interestCalculationPeriodTypeOptions, loanTermFrequencyTypeOptions, repaymentFrequencyTypeOptions,
|
||||
interestRateFrequencyTypeOptions, fundOptions, transactionProcessingStrategyOptions, accountOptions, accountingRuleTypeOptions,accountingMappings);
|
||||
interestCalculationPeriodTypeOptions, repaymentFrequencyTypeOptions, interestRateFrequencyTypeOptions, fundOptions,
|
||||
transactionProcessingStrategyOptions, accountOptions, accountingRuleTypeOptions, accountingMappings);
|
||||
}
|
||||
}
|
||||
+57
-66
@@ -33,47 +33,46 @@ public class LoanProductData {
|
||||
private final String description;
|
||||
private final Long fundId;
|
||||
private final String fundName;
|
||||
|
||||
// terms
|
||||
private final CurrencyData currency;
|
||||
private final BigDecimal principal;
|
||||
private final Integer numberOfRepayments;
|
||||
private final Integer loanTermFrequency;
|
||||
private final Integer repaymentEvery;
|
||||
private final EnumOptionData loanTermFrequencyType;
|
||||
private final EnumOptionData repaymentFrequencyType;
|
||||
private final Long transactionProcessingStrategyId;
|
||||
private final String transactionProcessingStrategyName;
|
||||
private final BigDecimal interestRatePerPeriod;
|
||||
private final EnumOptionData interestRateFrequencyType;
|
||||
private final BigDecimal annualInterestRate;
|
||||
|
||||
// settings
|
||||
private final EnumOptionData amortizationType;
|
||||
private final EnumOptionData interestType;
|
||||
private final EnumOptionData interestCalculationPeriodType;
|
||||
private final BigDecimal inArrearsTolerance;
|
||||
private final Long transactionProcessingStrategyId;
|
||||
private final String transactionProcessingStrategyName;
|
||||
|
||||
private final EnumOptionData accountingRule;
|
||||
|
||||
// charges
|
||||
private final Collection<ChargeData> charges;
|
||||
|
||||
// accounting
|
||||
private final EnumOptionData accountingRule;
|
||||
@SuppressWarnings("unused")
|
||||
private final Map<String, Object> accountingMappings;
|
||||
|
||||
// template related
|
||||
private final Collection<CurrencyData> currencyOptions;
|
||||
private final Collection<FundData> fundOptions;
|
||||
private final Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions;
|
||||
private final Collection<CurrencyData> currencyOptions;
|
||||
private final List<EnumOptionData> repaymentFrequencyTypeOptions;
|
||||
private final List<EnumOptionData> interestRateFrequencyTypeOptions;
|
||||
private final List<EnumOptionData> amortizationTypeOptions;
|
||||
private final List<EnumOptionData> interestTypeOptions;
|
||||
private final List<EnumOptionData> interestCalculationPeriodTypeOptions;
|
||||
private final List<EnumOptionData> repaymentFrequencyTypeOptions;
|
||||
private final List<EnumOptionData> interestRateFrequencyTypeOptions;
|
||||
private final List<EnumOptionData> loanTermFrequencyTypeOptions;
|
||||
private final Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions;
|
||||
private final Collection<ChargeData> chargeOptions;
|
||||
|
||||
// accounting related template fields
|
||||
private final List<EnumOptionData> accountingRuleOptions;
|
||||
private final Map<String, List<GLAccountData>> accountingMappingOptions;
|
||||
|
||||
// accounting related mapping fields
|
||||
@SuppressWarnings("unused")
|
||||
private final Map<String, Object> accountingMappings;
|
||||
|
||||
/**
|
||||
* Used when returning lookup information about loan product for dropdowns.
|
||||
*/
|
||||
@@ -83,11 +82,9 @@ public class LoanProductData {
|
||||
final BigDecimal principal = null;
|
||||
final BigDecimal tolerance = null;
|
||||
final Integer numberOfRepayments = null;
|
||||
final Integer loanTermFrequency = null;
|
||||
final Integer repaymentEvery = null;
|
||||
final BigDecimal interestRatePerPeriod = null;
|
||||
final BigDecimal annualInterestRate = null;
|
||||
final EnumOptionData loanTermFrequencyType = null;
|
||||
final EnumOptionData repaymentFrequencyType = null;
|
||||
final EnumOptionData interestRateFrequencyType = null;
|
||||
final EnumOptionData amortizationType = null;
|
||||
@@ -100,10 +97,10 @@ public class LoanProductData {
|
||||
final Collection<ChargeData> charges = null;
|
||||
final EnumOptionData accountingType = null;
|
||||
|
||||
return new LoanProductData(id, name, description, currency, principal, tolerance, numberOfRepayments, loanTermFrequency,
|
||||
repaymentEvery, interestRatePerPeriod, annualInterestRate, loanTermFrequencyType, repaymentFrequencyType,
|
||||
interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, fundId, fundName,
|
||||
transactionProcessingStrategyId, transactionProcessingStrategyName, charges, accountingType);
|
||||
return new LoanProductData(id, name, description, currency, principal, tolerance, numberOfRepayments, repaymentEvery,
|
||||
interestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType,
|
||||
interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId,
|
||||
transactionProcessingStrategyName, charges, accountingType);
|
||||
}
|
||||
|
||||
public static LoanProductData sensibleDefaultsForNewLoanProductCreation() {
|
||||
@@ -114,11 +111,9 @@ public class LoanProductData {
|
||||
final BigDecimal principal = null;
|
||||
final BigDecimal tolerance = null;
|
||||
final Integer numberOfRepayments = null;
|
||||
final Integer loanTermFrequency = null;
|
||||
final Integer repaymentEvery = null;
|
||||
final BigDecimal interestRatePerPeriod = null;
|
||||
final BigDecimal annualInterestRate = null;
|
||||
final EnumOptionData loanTermFrequencyType = LoanEnumerations.loanTermFrequencyType(PeriodFrequencyType.MONTHS);
|
||||
final EnumOptionData repaymentFrequencyType = LoanEnumerations.repaymentFrequencyType(PeriodFrequencyType.MONTHS);
|
||||
final EnumOptionData interestRateFrequencyType = LoanEnumerations.interestRateFrequencyType(PeriodFrequencyType.MONTHS);
|
||||
final EnumOptionData amortizationType = LoanEnumerations.amortizationType(AmortizationMethod.EQUAL_INSTALLMENTS);
|
||||
@@ -132,25 +127,24 @@ public class LoanProductData {
|
||||
final Collection<ChargeData> charges = null;
|
||||
final EnumOptionData accountingType = LoanEnumerations.accountingRuleType(AccountingRuleType.NONE);
|
||||
|
||||
return new LoanProductData(id, name, description, currency, principal, tolerance, numberOfRepayments, loanTermFrequency,
|
||||
repaymentEvery, interestRatePerPeriod, annualInterestRate, loanTermFrequencyType, repaymentFrequencyType,
|
||||
interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, fundId, fundName,
|
||||
transactionProcessingStrategyId, transactionProcessingStrategyName, charges, accountingType);
|
||||
return new LoanProductData(id, name, description, currency, principal, tolerance, numberOfRepayments, repaymentEvery,
|
||||
interestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType,
|
||||
interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId,
|
||||
transactionProcessingStrategyName, charges, accountingType);
|
||||
}
|
||||
|
||||
public static LoanProductData withAccountingMappings(final LoanProductData productData, final Map<String, Object> accountingMappings) {
|
||||
|
||||
return new LoanProductData(productData, productData.chargeOptions, productData.currencyOptions,
|
||||
productData.amortizationTypeOptions, productData.interestTypeOptions, productData.interestCalculationPeriodTypeOptions,
|
||||
productData.loanTermFrequencyTypeOptions, productData.repaymentFrequencyTypeOptions,
|
||||
productData.interestRateFrequencyTypeOptions, productData.fundOptions, productData.transactionProcessingStrategyOptions,
|
||||
productData.accountingMappingOptions, productData.accountingRuleOptions, accountingMappings);
|
||||
productData.repaymentFrequencyTypeOptions, productData.interestRateFrequencyTypeOptions, productData.fundOptions,
|
||||
productData.transactionProcessingStrategyOptions, productData.accountingMappingOptions, productData.accountingRuleOptions,
|
||||
accountingMappings);
|
||||
}
|
||||
|
||||
public LoanProductData(final Long id, final String name, final String description, final CurrencyData currency,
|
||||
final BigDecimal principal, final BigDecimal tolerance, final Integer numberOfRepayments, final Integer loanTermFrequency,
|
||||
final Integer repaymentEvery, final BigDecimal interestRatePerPeriod, final BigDecimal annualInterestRate,
|
||||
final EnumOptionData loanTermFrequencyType, final EnumOptionData repaymentFrequencyType,
|
||||
final BigDecimal principal, final BigDecimal tolerance, final Integer numberOfRepayments, final Integer repaymentEvery,
|
||||
final BigDecimal interestRatePerPeriod, final BigDecimal annualInterestRate, final EnumOptionData repaymentFrequencyType,
|
||||
final EnumOptionData interestRateFrequencyType, final EnumOptionData amortizationType, final EnumOptionData interestType,
|
||||
final EnumOptionData interestCalculationPeriodType, final Long fundId, final String fundName,
|
||||
final Long transactionProcessingStrategyId, final String transactionProcessingStrategyName,
|
||||
@@ -162,11 +156,11 @@ public class LoanProductData {
|
||||
this.principal = principal;
|
||||
this.inArrearsTolerance = tolerance;
|
||||
this.numberOfRepayments = numberOfRepayments;
|
||||
this.loanTermFrequency = loanTermFrequency;
|
||||
// this.loanTermFrequency = loanTermFrequency;
|
||||
this.repaymentEvery = repaymentEvery;
|
||||
this.interestRatePerPeriod = interestRatePerPeriod;
|
||||
this.annualInterestRate = annualInterestRate;
|
||||
this.loanTermFrequencyType = loanTermFrequencyType;
|
||||
// this.loanTermFrequencyType = loanTermFrequencyType;
|
||||
this.repaymentFrequencyType = repaymentFrequencyType;
|
||||
this.interestRateFrequencyType = interestRateFrequencyType;
|
||||
this.amortizationType = amortizationType;
|
||||
@@ -186,7 +180,7 @@ public class LoanProductData {
|
||||
this.amortizationTypeOptions = null;
|
||||
this.interestTypeOptions = null;
|
||||
this.interestCalculationPeriodTypeOptions = null;
|
||||
this.loanTermFrequencyTypeOptions = null;
|
||||
// this.loanTermFrequencyTypeOptions = null;
|
||||
this.repaymentFrequencyTypeOptions = null;
|
||||
this.interestRateFrequencyTypeOptions = null;
|
||||
|
||||
@@ -198,31 +192,29 @@ public class LoanProductData {
|
||||
public LoanProductData(final LoanProductData productData, final Collection<ChargeData> chargeOptions,
|
||||
final Collection<CurrencyData> currencyOptions, final List<EnumOptionData> amortizationTypeOptions,
|
||||
final List<EnumOptionData> interestTypeOptions, final List<EnumOptionData> interestCalculationPeriodTypeOptions,
|
||||
final List<EnumOptionData> loanTermFrequencyTypeOptions, final List<EnumOptionData> repaymentFrequencyTypeOptions,
|
||||
final List<EnumOptionData> interestRateFrequencyTypeOptions, final Collection<FundData> fundOptions,
|
||||
final Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions,
|
||||
final List<EnumOptionData> repaymentFrequencyTypeOptions, final List<EnumOptionData> interestRateFrequencyTypeOptions,
|
||||
final Collection<FundData> fundOptions,
|
||||
final Collection<TransactionProcessingStrategyData> transactionStrategyOptions,
|
||||
final Map<String, List<GLAccountData>> accountingMappingOptions, final List<EnumOptionData> accountingRuleOptions,
|
||||
final Map<String, Object> accountingMappings) {
|
||||
this.id = productData.id;
|
||||
this.name = productData.name;
|
||||
this.description = productData.description;
|
||||
this.fundId = productData.fundId;
|
||||
this.fundName = productData.fundName;
|
||||
|
||||
this.principal = productData.principal;
|
||||
this.inArrearsTolerance = productData.inArrearsTolerance;
|
||||
this.numberOfRepayments = productData.numberOfRepayments;
|
||||
this.loanTermFrequency = productData.loanTermFrequency;
|
||||
this.repaymentEvery = productData.repaymentEvery;
|
||||
this.interestRatePerPeriod = productData.interestRatePerPeriod;
|
||||
this.annualInterestRate = productData.annualInterestRate;
|
||||
this.loanTermFrequencyType = productData.loanTermFrequencyType;
|
||||
this.repaymentFrequencyType = productData.repaymentFrequencyType;
|
||||
this.interestRateFrequencyType = productData.interestRateFrequencyType;
|
||||
this.amortizationType = productData.amortizationType;
|
||||
this.interestType = productData.interestType;
|
||||
this.interestCalculationPeriodType = productData.interestCalculationPeriodType;
|
||||
this.fundId = productData.fundId;
|
||||
this.fundName = productData.fundName;
|
||||
this.transactionProcessingStrategyId = productData.transactionProcessingStrategyId;
|
||||
this.transactionProcessingStrategyName = productData.transactionProcessingStrategyName;
|
||||
|
||||
this.charges = nullIfEmpty(productData.charges());
|
||||
this.accountingRule = productData.accountingRule;
|
||||
|
||||
@@ -234,17 +226,32 @@ public class LoanProductData {
|
||||
this.currency = productData.currency;
|
||||
}
|
||||
this.fundOptions = fundOptions;
|
||||
this.transactionProcessingStrategyOptions = transactionProcessingStrategyOptions;
|
||||
this.transactionProcessingStrategyOptions = transactionStrategyOptions;
|
||||
if (this.transactionProcessingStrategyOptions != null && this.transactionProcessingStrategyOptions.size() == 1) {
|
||||
final List<TransactionProcessingStrategyData> listOfOptions = new ArrayList<TransactionProcessingStrategyData>(
|
||||
this.transactionProcessingStrategyOptions);
|
||||
|
||||
this.transactionProcessingStrategyId = listOfOptions.get(0).id();
|
||||
this.transactionProcessingStrategyName = listOfOptions.get(0).name();
|
||||
} else {
|
||||
this.transactionProcessingStrategyId = productData.transactionProcessingStrategyId;
|
||||
this.transactionProcessingStrategyName = productData.transactionProcessingStrategyName;
|
||||
}
|
||||
|
||||
this.amortizationTypeOptions = amortizationTypeOptions;
|
||||
this.interestTypeOptions = interestTypeOptions;
|
||||
this.interestCalculationPeriodTypeOptions = interestCalculationPeriodTypeOptions;
|
||||
this.loanTermFrequencyTypeOptions = loanTermFrequencyTypeOptions;
|
||||
this.repaymentFrequencyTypeOptions = repaymentFrequencyTypeOptions;
|
||||
this.interestRateFrequencyTypeOptions = interestRateFrequencyTypeOptions;
|
||||
|
||||
this.accountingMappingOptions = accountingMappingOptions;
|
||||
this.accountingRuleOptions = accountingRuleOptions;
|
||||
this.accountingMappings = accountingMappings;
|
||||
|
||||
if (accountingMappings == null || accountingMappings.isEmpty()) {
|
||||
this.accountingMappings = null;
|
||||
} else {
|
||||
this.accountingMappings = accountingMappings;
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<ChargeData> nullIfEmpty(final Collection<ChargeData> charges) {
|
||||
@@ -315,10 +322,6 @@ public class LoanProductData {
|
||||
return numberOfRepayments;
|
||||
}
|
||||
|
||||
public Integer getLoanTermFrequency() {
|
||||
return loanTermFrequency;
|
||||
}
|
||||
|
||||
public Integer getRepaymentEvery() {
|
||||
return repaymentEvery;
|
||||
}
|
||||
@@ -331,10 +334,6 @@ public class LoanProductData {
|
||||
return annualInterestRate;
|
||||
}
|
||||
|
||||
public EnumOptionData getLoanTermFrequencyType() {
|
||||
return loanTermFrequencyType;
|
||||
}
|
||||
|
||||
public EnumOptionData getRepaymentFrequencyType() {
|
||||
return repaymentFrequencyType;
|
||||
}
|
||||
@@ -359,10 +358,6 @@ public class LoanProductData {
|
||||
return fundOptions;
|
||||
}
|
||||
|
||||
public Collection<TransactionProcessingStrategyData> getTransactionProcessingStrategyOptions() {
|
||||
return transactionProcessingStrategyOptions;
|
||||
}
|
||||
|
||||
public List<EnumOptionData> getAmortizationTypeOptions() {
|
||||
return amortizationTypeOptions;
|
||||
}
|
||||
@@ -383,10 +378,6 @@ public class LoanProductData {
|
||||
return interestRateFrequencyTypeOptions;
|
||||
}
|
||||
|
||||
public List<EnumOptionData> getLoanTermFrequencyTypeOptions() {
|
||||
return loanTermFrequencyTypeOptions;
|
||||
}
|
||||
|
||||
public Collection<ChargeData> getChargeOptions() {
|
||||
return chargeOptions;
|
||||
}
|
||||
|
||||
+11
-2
@@ -5,13 +5,14 @@
|
||||
*/
|
||||
package org.mifosplatform.portfolio.loanproduct.data;
|
||||
|
||||
/**
|
||||
* Immutable data object representing a transaction strategy option for a loan.
|
||||
*/
|
||||
public final class TransactionProcessingStrategyData {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final Long id;
|
||||
@SuppressWarnings("unused")
|
||||
private final String code;
|
||||
@SuppressWarnings("unused")
|
||||
private final String name;
|
||||
|
||||
public TransactionProcessingStrategyData(final Long id, final String code, final String name) {
|
||||
@@ -19,4 +20,12 @@ public final class TransactionProcessingStrategyData {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long id() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
+25
-31
@@ -6,7 +6,7 @@
|
||||
package org.mifosplatform.portfolio.loanproduct.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -29,6 +29,8 @@ import org.mifosplatform.portfolio.fund.domain.Fund;
|
||||
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.AprCalculator;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
|
||||
/**
|
||||
* Loan products allow for categorisation of an organisations loans into
|
||||
* something meaningful to them.
|
||||
@@ -39,7 +41,7 @@ import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
* They allow for constraints to be added at product level.
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "m_product_loan" , uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "unq_name")})
|
||||
@Table(name = "m_product_loan", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "unq_name") })
|
||||
public class LoanProduct extends AbstractPersistable<Long> {
|
||||
|
||||
@ManyToOne
|
||||
@@ -50,7 +52,7 @@ public class LoanProduct extends AbstractPersistable<Long> {
|
||||
@JoinColumn(name = "loan_transaction_strategy_id", nullable = true)
|
||||
private LoanTransactionProcessingStrategy transactionProcessingStrategy;
|
||||
|
||||
@Column(name = "name", nullable = false , unique = true)
|
||||
@Column(name = "name", nullable = false, unique = true)
|
||||
private String name;
|
||||
|
||||
@Column(name = "description")
|
||||
@@ -58,7 +60,7 @@ public class LoanProduct extends AbstractPersistable<Long> {
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(name = "m_product_loan_charge", joinColumns = @JoinColumn(name = "product_loan_id"), inverseJoinColumns = @JoinColumn(name = "charge_id"))
|
||||
private Set<Charge> charges;
|
||||
private List<Charge> charges;
|
||||
|
||||
@Embedded
|
||||
private final LoanProductRelatedDetail loanProductRelatedDetail;
|
||||
@@ -67,7 +69,7 @@ public class LoanProduct extends AbstractPersistable<Long> {
|
||||
private Integer accountingRule;
|
||||
|
||||
public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy,
|
||||
final Set<Charge> productCharges, final JsonCommand command, final AprCalculator aprCalculator) {
|
||||
final List<Charge> productCharges, final JsonCommand command, final AprCalculator aprCalculator) {
|
||||
|
||||
final String name = command.stringValueOfParameterNamed("name");
|
||||
final String description = command.stringValueOfParameterNamed("description");
|
||||
@@ -108,7 +110,7 @@ public class LoanProduct extends AbstractPersistable<Long> {
|
||||
final BigDecimal defaultAnnualNominalInterestRate, final InterestMethod interestMethod,
|
||||
final InterestCalculationPeriodMethod interestCalculationPeriodMethod, final Integer repayEvery,
|
||||
final PeriodFrequencyType repaymentFrequencyType, final Integer defaultNumberOfInstallments,
|
||||
final AmortizationMethod amortizationMethod, final BigDecimal inArrearsTolerance, final Set<Charge> charges,
|
||||
final AmortizationMethod amortizationMethod, final BigDecimal inArrearsTolerance, final List<Charge> charges,
|
||||
final AccountingRuleType accountingRuleType) {
|
||||
this.fund = fund;
|
||||
this.transactionProcessingStrategy = transactionProcessingStrategy;
|
||||
@@ -136,10 +138,6 @@ public class LoanProduct extends AbstractPersistable<Long> {
|
||||
return this.loanProductRelatedDetail.getCurrency();
|
||||
}
|
||||
|
||||
public Set<Charge> getCharges() {
|
||||
return charges;
|
||||
}
|
||||
|
||||
public void update(final Fund fund) {
|
||||
this.fund = fund;
|
||||
}
|
||||
@@ -148,8 +146,17 @@ public class LoanProduct extends AbstractPersistable<Long> {
|
||||
this.transactionProcessingStrategy = strategy;
|
||||
}
|
||||
|
||||
public void update(final Set<Charge> charges) {
|
||||
this.charges = charges;
|
||||
public boolean update(final List<Charge> newProductCharges) {
|
||||
boolean updated = false;
|
||||
if (this.charges != null) {
|
||||
final Set<Charge> setOfCharges = new HashSet<Charge>(this.charges);
|
||||
|
||||
updated = setOfCharges.addAll(newProductCharges);
|
||||
if (updated) {
|
||||
this.charges = newProductCharges;
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
public Integer getAccountingType() {
|
||||
@@ -202,30 +209,17 @@ public class LoanProduct extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
final String chargesParamName = "charges";
|
||||
if (command.isChangeInArrayParameterNamed(chargesParamName, getChargesIds())) {
|
||||
final String[] newValue = command.arrayValueOfParameterNamed(chargesParamName);
|
||||
actualChanges.put(chargesParamName, newValue);
|
||||
if (command.hasParameter(chargesParamName)) {
|
||||
JsonArray jsonArray = command.arrayOfParameterNamed(chargesParamName);
|
||||
if (jsonArray != null) {
|
||||
|
||||
}
|
||||
actualChanges.put(chargesParamName, command.jsonFragment(chargesParamName));
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private String[] getChargesIds() {
|
||||
final List<String> chargeIds = new ArrayList<String>();
|
||||
|
||||
if (this.charges != null) {
|
||||
for (Charge charge : this.charges) {
|
||||
chargeIds.add(charge.getId().toString());
|
||||
}
|
||||
}
|
||||
|
||||
return chargeIds.toArray(new String[chargeIds.size()]);
|
||||
}
|
||||
|
||||
public boolean isAccountingEnabled() {
|
||||
return !AccountingRuleType.NONE.getValue().equals(this.accountingRule);
|
||||
}
|
||||
|
||||
public boolean isCashBasedAccountingEnabled() {
|
||||
return AccountingRuleType.CASH_BASED.getValue().equals(this.accountingRule);
|
||||
}
|
||||
|
||||
+16
-14
@@ -35,10 +35,10 @@ public final class LoanProductCommandFromApiJsonDeserializer {
|
||||
/**
|
||||
* The parameters supported for this command.
|
||||
*/
|
||||
private final Set<String> supportedParameters = new HashSet<String>(Arrays.asList("name", "description", "fundId",
|
||||
"transactionProcessingStrategyId", "currencyCode", "digitsAfterDecimal", "principal", "inArrearsTolerance",
|
||||
"interestRatePerPeriod", "repaymentEvery", "numberOfRepayments", "repaymentFrequencyType", "interestRateFrequencyType",
|
||||
"amortizationType", "interestType", "interestCalculationPeriodType", "charges", "locale", "accountingRule",
|
||||
private final Set<String> supportedParameters = new HashSet<String>(Arrays.asList("locale", "name", "description", "fundId",
|
||||
"currencyCode", "digitsAfterDecimal", "principal", "repaymentEvery", "numberOfRepayments", "repaymentFrequencyType",
|
||||
"interestRatePerPeriod", "interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType",
|
||||
"inArrearsTolerance", "transactionProcessingStrategyId", "charges", "accountingRule",
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(),
|
||||
@@ -74,6 +74,7 @@ public final class LoanProductCommandFromApiJsonDeserializer {
|
||||
baseDataValidator.reset().parameter("fundId").value(fundId).ignoreIfNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
// terms
|
||||
final String currencyCode = fromApiJsonHelper.extractStringNamed("currencyCode", element);
|
||||
baseDataValidator.reset().parameter("currencyCode").value(currencyCode).notBlank().notExceedingLengthOf(3);
|
||||
|
||||
@@ -83,12 +84,6 @@ public final class LoanProductCommandFromApiJsonDeserializer {
|
||||
final BigDecimal principal = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("principal", element);
|
||||
baseDataValidator.reset().parameter("principal").value(principal).notNull().positiveAmount();
|
||||
|
||||
final BigDecimal inArrearsTolerance = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("inArrearsTolerance", element);
|
||||
baseDataValidator.reset().parameter("inArrearsTolerance").value(inArrearsTolerance).ignoreIfNull().zeroOrPositiveAmount();
|
||||
|
||||
final BigDecimal interestRatePerPeriod = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("interestRatePerPeriod", element);
|
||||
baseDataValidator.reset().parameter("interestRatePerPeriod").value(interestRatePerPeriod).notNull().zeroOrPositiveAmount();
|
||||
|
||||
final Integer numberOfRepayments = fromApiJsonHelper.extractIntegerWithLocaleNamed("numberOfRepayments", element);
|
||||
baseDataValidator.reset().parameter("numberOfRepayments").value(numberOfRepayments).notNull().integerGreaterThanZero();
|
||||
|
||||
@@ -99,14 +94,14 @@ public final class LoanProductCommandFromApiJsonDeserializer {
|
||||
.extractIntegerNamed("repaymentFrequencyType", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("repaymentFrequencyType").value(repaymentFrequencyType).notNull().inMinMaxRange(0, 3);
|
||||
|
||||
final Long transactionProcessingStrategyId = fromApiJsonHelper.extractLongNamed("transactionProcessingStrategyId", element);
|
||||
baseDataValidator.reset().parameter("transactionProcessingStrategyId").value(transactionProcessingStrategyId).notNull()
|
||||
.integerGreaterThanZero();
|
||||
final BigDecimal interestRatePerPeriod = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("interestRatePerPeriod", element);
|
||||
baseDataValidator.reset().parameter("interestRatePerPeriod").value(interestRatePerPeriod).notNull().zeroOrPositiveAmount();
|
||||
|
||||
final Integer interestRateFrequencyType = fromApiJsonHelper.extractIntegerNamed("interestRateFrequencyType", element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("interestRateFrequencyType").value(interestRateFrequencyType).notNull().inMinMaxRange(0, 3);
|
||||
|
||||
// settings
|
||||
final Integer amortizationType = fromApiJsonHelper.extractIntegerNamed("amortizationType", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("amortizationType").value(amortizationType).notNull().inMinMaxRange(0, 1);
|
||||
|
||||
@@ -118,6 +113,13 @@ public final class LoanProductCommandFromApiJsonDeserializer {
|
||||
baseDataValidator.reset().parameter("interestCalculationPeriodType").value(interestCalculationPeriodType).notNull()
|
||||
.inMinMaxRange(0, 1);
|
||||
|
||||
final BigDecimal inArrearsTolerance = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("inArrearsTolerance", element);
|
||||
baseDataValidator.reset().parameter("inArrearsTolerance").value(inArrearsTolerance).ignoreIfNull().zeroOrPositiveAmount();
|
||||
|
||||
final Long transactionProcessingStrategyId = fromApiJsonHelper.extractLongNamed("transactionProcessingStrategyId", element);
|
||||
baseDataValidator.reset().parameter("transactionProcessingStrategyId").value(transactionProcessingStrategyId).notNull()
|
||||
.integerGreaterThanZero();
|
||||
|
||||
// accounting related data validation
|
||||
final Integer accountingRuleType = fromApiJsonHelper.extractIntegerNamed("accountingRule", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("accountingRule").value(accountingRuleType).notNull().inMinMaxRange(1, 3);
|
||||
@@ -176,7 +178,7 @@ public final class LoanProductCommandFromApiJsonDeserializer {
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
public void validateForUpdate(String json) {
|
||||
public void validateForUpdate(final String json) {
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
|
||||
+8
-11
@@ -134,19 +134,16 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
|
||||
final Integer numberOfRepayments = JdbcSupport.getInteger(rs, "numberOfRepayments");
|
||||
final Integer repaymentEvery = JdbcSupport.getInteger(rs, "repaidEvery");
|
||||
|
||||
final Integer accountingTypeId = JdbcSupport.getInteger(rs, "accountingType");
|
||||
final EnumOptionData accountingRuleType = LoanEnumerations.accountingRuleType(accountingTypeId);
|
||||
|
||||
final Integer loanTermFrequency = repaymentEvery * numberOfRepayments;
|
||||
|
||||
final Integer accountingRuleId = JdbcSupport.getInteger(rs, "accountingType");
|
||||
final EnumOptionData accountingRuleType = LoanEnumerations.accountingRuleType(accountingRuleId);
|
||||
|
||||
final BigDecimal interestRatePerPeriod = rs.getBigDecimal("interestRatePerPeriod");
|
||||
final BigDecimal annualInterestRate = rs.getBigDecimal("annualInterestRate");
|
||||
|
||||
final int repaymentFrequencyTypeId = JdbcSupport.getInteger(rs, "repaymentPeriodFrequency");
|
||||
final EnumOptionData repaymentFrequencyType = LoanEnumerations.repaymentFrequencyType(repaymentFrequencyTypeId);
|
||||
|
||||
final EnumOptionData loanTermFrequencyType = LoanEnumerations.loanTermFrequencyType(repaymentFrequencyTypeId);
|
||||
|
||||
final int amortizationTypeId = JdbcSupport.getInteger(rs, "amortizationMethod");
|
||||
final EnumOptionData amortizationType = LoanEnumerations.amortizationType(amortizationTypeId);
|
||||
|
||||
@@ -160,10 +157,10 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
final EnumOptionData interestCalculationPeriodType = LoanEnumerations
|
||||
.interestCalculationPeriodType(interestCalculationPeriodTypeId);
|
||||
|
||||
return new LoanProductData(id, name, description, currency, principal, tolerance, numberOfRepayments, loanTermFrequency,
|
||||
repaymentEvery, interestRatePerPeriod, annualInterestRate, loanTermFrequencyType, repaymentFrequencyType,
|
||||
interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, fundId, fundName,
|
||||
transactionStrategyId, transactionStrategyName, this.charges, accountingRuleType);
|
||||
return new LoanProductData(id, name, description, currency, principal, tolerance, numberOfRepayments, repaymentEvery,
|
||||
interestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType,
|
||||
interestType, interestCalculationPeriodType, fundId, fundName, transactionStrategyId, transactionStrategyName,
|
||||
this.charges, accountingRuleType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+39
-33
@@ -5,9 +5,9 @@
|
||||
*/
|
||||
package org.mifosplatform.portfolio.loanproduct.service;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mifosplatform.accounting.producttoaccountmapping.service.ProductToGLAccountMappingWritePlatformService;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
@@ -16,9 +16,7 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.mifosplatform.portfolio.charge.domain.Charge;
|
||||
import org.mifosplatform.portfolio.charge.domain.ChargeRepository;
|
||||
import org.mifosplatform.portfolio.charge.exception.ChargeIsNotActiveException;
|
||||
import org.mifosplatform.portfolio.charge.exception.ChargeNotFoundException;
|
||||
import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper;
|
||||
import org.mifosplatform.portfolio.fund.domain.Fund;
|
||||
import org.mifosplatform.portfolio.fund.domain.FundRepository;
|
||||
import org.mifosplatform.portfolio.fund.exception.FundNotFoundException;
|
||||
@@ -31,13 +29,15 @@ import org.mifosplatform.portfolio.loanproduct.domain.LoanTransactionProcessingS
|
||||
import org.mifosplatform.portfolio.loanproduct.exception.InvalidCurrencyException;
|
||||
import org.mifosplatform.portfolio.loanproduct.exception.LoanProductNotFoundException;
|
||||
import org.mifosplatform.portfolio.loanproduct.serialization.LoanProductCommandFromApiJsonDeserializer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
@Service
|
||||
public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanProductWritePlatformService {
|
||||
@@ -49,7 +49,7 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
private final AprCalculator aprCalculator;
|
||||
private final FundRepository fundRepository;
|
||||
private final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository;
|
||||
private final ChargeRepository chargeRepository;
|
||||
private final ChargeRepositoryWrapper chargeRepository;
|
||||
private final ProductToGLAccountMappingWritePlatformService accountMappingWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
@@ -57,7 +57,8 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
final LoanProductCommandFromApiJsonDeserializer fromApiJsonDeserializer, final LoanProductRepository loanProductRepository,
|
||||
final AprCalculator aprCalculator, final FundRepository fundRepository,
|
||||
final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository,
|
||||
final ChargeRepository chargeRepository, final ProductToGLAccountMappingWritePlatformService accountMappingWritePlatformService) {
|
||||
final ChargeRepositoryWrapper chargeRepository,
|
||||
final ProductToGLAccountMappingWritePlatformService accountMappingWritePlatformService) {
|
||||
this.context = context;
|
||||
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
||||
this.loanProductRepository = loanProductRepository;
|
||||
@@ -78,15 +79,13 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
|
||||
this.fromApiJsonDeserializer.validateForCreate(command.json());
|
||||
|
||||
// associating fund with loan product at creation is optional for
|
||||
// now.
|
||||
final Fund fund = findFundByIdIfProvided(command.longValueOfParameterNamed("fundId"));
|
||||
|
||||
final Long transactionProcessingStrategyId = command.longValueOfParameterNamed("transactionProcessingStrategyId");
|
||||
final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(transactionProcessingStrategyId);
|
||||
|
||||
final String currencyCode = command.stringValueOfParameterNamed("currencyCode");
|
||||
final Set<Charge> charges = this.assembleSetOfCharges(command, currencyCode);
|
||||
final List<Charge> charges = this.assembleListOfProductCharges(command, currencyCode);
|
||||
|
||||
final LoanProduct loanproduct = LoanProduct.assembleFromJson(fund, loanTransactionProcessingStrategy, charges, command,
|
||||
this.aprCalculator);
|
||||
@@ -131,7 +130,6 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
public CommandProcessingResult updateLoanProduct(final Long loanProductId, final JsonCommand command) {
|
||||
|
||||
try {
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
this.fromApiJsonDeserializer.validateForUpdate(command.json());
|
||||
@@ -141,8 +139,6 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
|
||||
final Map<String, Object> changes = product.update(command, this.aprCalculator);
|
||||
|
||||
// associating fund with loan product at creation is optional for
|
||||
// now.
|
||||
if (changes.containsKey("fundId")) {
|
||||
final Long fundId = (Long) changes.get("fundId");
|
||||
final Fund fund = findFundByIdIfProvided(fundId);
|
||||
@@ -156,10 +152,13 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
}
|
||||
|
||||
if (changes.containsKey("charges")) {
|
||||
final Set<Charge> charges = this.assembleSetOfCharges(command, product.getCurrency().getCode());
|
||||
product.update(charges);
|
||||
final List<Charge> productCharges = this.assembleListOfProductCharges(command, product.getCurrency().getCode());
|
||||
boolean updated = product.update(productCharges);
|
||||
if (!updated) {
|
||||
changes.remove("charges");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// accounting related changes
|
||||
boolean accountingTypeChanged = changes.containsKey("accountingRule");
|
||||
final Map<String, Object> accountingMappingChanges = accountMappingWritePlatformService.updateLoanProductToGLAccountMapping(
|
||||
@@ -183,29 +182,33 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
|
||||
}
|
||||
|
||||
private Set<Charge> assembleSetOfCharges(final JsonCommand command, final String currencyCode) {
|
||||
private List<Charge> assembleListOfProductCharges(final JsonCommand command, final String currencyCode) {
|
||||
|
||||
final Set<Charge> charges = new HashSet<Charge>();
|
||||
final String[] chargesArray = command.arrayValueOfParameterNamed("charges");
|
||||
final List<Charge> charges = new ArrayList<Charge>();
|
||||
|
||||
String loanProductCurrencyCode = command.stringValueOfParameterNamed("currencyCode");
|
||||
if (loanProductCurrencyCode == null) {
|
||||
loanProductCurrencyCode = currencyCode;
|
||||
}
|
||||
|
||||
if (!ObjectUtils.isEmpty(chargesArray)) {
|
||||
for (final String chargeId : chargesArray) {
|
||||
if (command.parameterExists("charges")) {
|
||||
JsonArray chargesArray = command.arrayOfParameterNamed("charges");
|
||||
if (chargesArray != null) {
|
||||
for (int i = 0; i < chargesArray.size(); i++) {
|
||||
|
||||
final Long id = Long.valueOf(chargeId);
|
||||
final Charge charge = this.chargeRepository.findOne(id);
|
||||
if (charge == null || charge.isDeleted()) { throw new ChargeNotFoundException(id); }
|
||||
if (!charge.isActive()) { throw new ChargeIsNotActiveException(id, charge.getName()); }
|
||||
final JsonObject jsonObject = chargesArray.get(i).getAsJsonObject();
|
||||
if (jsonObject.has("id")) {
|
||||
final Long id = jsonObject.get("id").getAsLong();
|
||||
|
||||
if (!loanProductCurrencyCode.equals(charge.getCurrencyCode())) {
|
||||
String errorMessage = "Charge and Loan Product must have the same currency.";
|
||||
throw new InvalidCurrencyException("charge", "attach.to.loan.product", errorMessage);
|
||||
final Charge charge = this.chargeRepository.findOneWithNotFoundDetection(id);
|
||||
|
||||
if (!loanProductCurrencyCode.equals(charge.getCurrencyCode())) {
|
||||
String errorMessage = "Charge and Loan Product must have the same currency.";
|
||||
throw new InvalidCurrencyException("charge", "attach.to.loan.product", errorMessage);
|
||||
}
|
||||
charges.add(charge);
|
||||
}
|
||||
}
|
||||
charges.add(charge);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +227,10 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
final String name = command.stringValueOfParameterNamed("name");
|
||||
throw new PlatformDataIntegrityException("error.msg.product.loan.duplicate.name", "Loan product with name `" + name
|
||||
+ "` already exists", "name", name);
|
||||
} else if (realCause.getMessage().contains("Duplicate entry")) {
|
||||
Object[] args = null;
|
||||
throw new PlatformDataIntegrityException("error.msg.product.loan.duplicate.charge",
|
||||
"Loan product may only have one charge of each type.`", "charges", args);
|
||||
}
|
||||
|
||||
logAsErrorUnexpectedDataIntegrityException(dve);
|
||||
@@ -234,5 +241,4 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
private void logAsErrorUnexpectedDataIntegrityException(final DataIntegrityViolationException dve) {
|
||||
logger.error(dve.getMessage(), dve);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user