Merge branch 'develop'
This commit is contained in:
@@ -6,6 +6,7 @@ See VERSIONING (https://github.com/openMF/mifosx/blob/master/VERSIONING.md) for
|
||||
Releases
|
||||
===============
|
||||
|
||||
1. 20 Jun 2013 - 1.4.0.RELEASE
|
||||
1. 10 Jun 2013 - 1.3.0.RELEASE
|
||||
1. 06 Jun 2013 - 1.2.1.RELEASE
|
||||
1. 27 May 2013 - 1.2.0.RELEASE
|
||||
@@ -24,6 +25,47 @@ Releases
|
||||
1. 05 April 2013 - 0.11.1.beta
|
||||
1. 05 April 2013 - 0.11.0.beta
|
||||
|
||||
|
||||
1.4.0.RELEASE
|
||||
=============
|
||||
Feature Release
|
||||
|
||||
This feature release focussed on moving groups functionality from BETA to public API.
|
||||
|
||||
Along with Group releated work, key improvements was the addition of a UI and API for adding 'additional data' and staff relationship to clients.
|
||||
|
||||
Platform & API
|
||||
|
||||
Bug
|
||||
- [MIFOSX-420] - In "Change loan application" not able to save the modifications made because of error message getting displayed on charges.
|
||||
- [MIFOSX-424] - In new loan application, loan is getting approved for the Principal amount beyond the range (Minimum and Maximum) defined in the loan product.
|
||||
- [MIFOSX-429] - App user of one branch can edit client of another branch
|
||||
- [MIFOSX-446] - New loan application is not validating Min-Max Principal defined in the product defination
|
||||
- [MIFOSX-447] - New loan application is not validating Min-Max for "# Of Repayments" defined in the product defination
|
||||
- [MIFOSX-448] - New loan application is not validating Min-Max "Nominal interest rate %" defined in the product defination
|
||||
- [MIFOSX-468] - In "Change loan application" error message is displaying for the second charge which was applied before.
|
||||
- [MIFOSX-474] - Adjusting an existing loan transaction fails when 'note' information is passed
|
||||
|
||||
New Features & Improvements
|
||||
- [MIFOSX-365] - Simplify "Data Tables" functionality
|
||||
- [MIFOSX-421] - Ability to create and associate Group Roles
|
||||
- [MIFOSX-434] - Allow linking of staff to Clients
|
||||
- [MIFOSX-445] - Show loanofficers at higher hierarchical level in product template
|
||||
- [MIFOSX-449] - Group and JLG loans repayment schedule should match group meeting dates if loan repayment is synched with group meeting
|
||||
- [MIFOSX-457] - Update API param names for accounting rules to be consistent with rest of the accounting services
|
||||
- [MIFOSX-458] - Unable to create accounting rules with Tag Id, multiple debits/credits etc
|
||||
|
||||
Reference App
|
||||
- [MIFOSX-378] - TEVI: Produce 'role-based' dashboards as entry/landing page for users that login
|
||||
- [MIFOSX-455] - CodeValues functionality broken on the reference Client app
|
||||
- [MIFOSX-469] - In Groups unable to activate the created group
|
||||
- [MIFOSX-464] - Unable to edit the created charge in "charge details" page
|
||||
|
||||
BETA (functionality related to BETA functionality
|
||||
- [MIFOSX-456] - CRUD services and UI for creating Holidays
|
||||
- [MIFOSX-411] - While creating new savings account, If "Interest posting period" is defined Annually, it is getting posted monthly.
|
||||
|
||||
|
||||
1.3.0.RELEASE
|
||||
=============
|
||||
Feature Release
|
||||
|
||||
@@ -26,7 +26,7 @@ The mifos-platform (project named 'Mifos X') has reached <b>public release versi
|
||||
|
||||
That means there is a published and stable API. This API is documented in the api-docs under <b>Full API Matrix</b>.
|
||||
|
||||
Latest stable release: <a target="_blank" href="https://github.com/openMF/mifosx/tree/mifosplatform-1.3.0" title="mifosplatform-1.3.0">mifosplatform-1.3.0</a>
|
||||
Latest stable release: <a target="_blank" href="https://github.com/openMF/mifosx/tree/mifosplatform-1.4.0" title="mifosplatform-1.4.0">mifosplatform-1.4.0</a>
|
||||
|
||||
License
|
||||
=============
|
||||
|
||||
+521
-98
@@ -90,7 +90,7 @@
|
||||
<body>
|
||||
<div id="page-wrapper">
|
||||
<div id="flybar">
|
||||
<div id="nav-logo">1.3.0.RELEASE API</div>
|
||||
<div id="nav-logo">1.4.0.RELEASE API</div>
|
||||
<div class="flybar-nav">
|
||||
<h2 class="flybar-button">Overview</h2>
|
||||
<div class="flybar-menu-overview">
|
||||
@@ -449,6 +449,106 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flybar-nav">
|
||||
<h2 class="flybar-button">Group</h2>
|
||||
<div id="toc-menu-loan" class="flybar-menu">
|
||||
<div class="tocMatrix">
|
||||
<table class=matrixHeading>
|
||||
<tr class="matrixHeadingBG">
|
||||
<td colspan=2 valign="top"><div class="matrixHeadingVerbs">
|
||||
<table>
|
||||
<tr>
|
||||
<td>RESOURCES</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></td>
|
||||
<td><table>
|
||||
<tr>
|
||||
<td><div class="matrixHeadingVerbs">POST</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><div class=matrixHeadingCommands>create/complex
|
||||
update</div></td>
|
||||
</tr>
|
||||
</table></td>
|
||||
<td><table>
|
||||
<tr>
|
||||
<td><div class="matrixHeadingVerbs">GET</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><div class=matrixHeadingCommands>read</div></td>
|
||||
</tr>
|
||||
</table></td>
|
||||
<td><table>
|
||||
<tr>
|
||||
<td><div class="matrixHeadingVerbs">PUT</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><div class=matrixHeadingCommands>update</div></td>
|
||||
</tr>
|
||||
</table></td>
|
||||
<td><table>
|
||||
<tr>
|
||||
<td><div class="matrixHeadingVerbs">DELETE</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><div class=matrixHeadingCommands>delete</div></td>
|
||||
</tr>
|
||||
</table></td>
|
||||
</tr>
|
||||
<tr class="alt">
|
||||
<td><a href="#groups">Group</a></td>
|
||||
<td>groups</td>
|
||||
<td><a href="#groups_create">Create a Group</a></td>
|
||||
<td><a href="#groups_list">List Groups</a></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>groups/template</td>
|
||||
<td></td>
|
||||
<td><a href="#groups_template">Retrieve Group Template</a></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr class="alt">
|
||||
<td></td>
|
||||
<td>groups/{groupId}</td>
|
||||
<td></td>
|
||||
<td><a href="#groups_retrieve">Retrieve a Group</a></td>
|
||||
<td><a href="#groups_update">Update a Group</a></td>
|
||||
<td><a href="#groups_delete">Delete a Group</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>groups/{groupId}?command=activate</td>
|
||||
<td><a href="#groups_activate">Activate a Group</a></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>groups/{groupId}?command=associateClients</td>
|
||||
<td><a href="#groups_associate_clients">Associate Clients</a></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>groups/{groupId}?command=disassociateClients</td>
|
||||
<td><a href="#groups_disassociate_clients">Disassociate Clients</a></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- disabled Groupings API for release 1.0.0 as its beta -->
|
||||
<!--
|
||||
<div class="flybar-nav">
|
||||
@@ -1272,6 +1372,10 @@
|
||||
<td>clients/template</td>
|
||||
<td><a href="#clients_template">Retrieve Client Template</a></td>
|
||||
</tr>
|
||||
<tr class="alt">
|
||||
<td>groups/template</td>
|
||||
<td><a href="#groups_template">Retrieve Group Template</a></td>
|
||||
</tr>
|
||||
<tr >
|
||||
<td>loanproducts/template</td>
|
||||
<td><a href="#loanproducts_template">Retrieve Loan Product Template</a></td>
|
||||
@@ -3253,6 +3357,33 @@ GET https://DomainName/mifosng-provider/api/v1/centers
|
||||
<div class="method-section">
|
||||
<div class="method-description">
|
||||
<h4>Retrieve Group Template</h4>
|
||||
<p>This is a convenience resource. It can be useful when
|
||||
building maintenance user interface screens for client
|
||||
applications. The template data returned consists of any or all
|
||||
of:
|
||||
<ul>
|
||||
<li class=normalli>Field Defaults</li>
|
||||
<li class=normalli>Allowed Value Lists</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h5>Arguments</h5>
|
||||
<dl class="argument-list">
|
||||
<dt>officeId</dt>
|
||||
<dd>
|
||||
Integer <span>optional</span>
|
||||
</dd>
|
||||
<dt>centerId</dt>
|
||||
<dd>
|
||||
Integer <span>optional</span>
|
||||
</dd>
|
||||
<dt>staffInSelectedOfficeOnly</dt>
|
||||
<dd>
|
||||
Boolean <span>optional</span>
|
||||
</dd>
|
||||
<dd>Defaults to false if not provided. If <strong>staffInSelectedOfficeOnly=true</strong> only staff
|
||||
who are associated with the selected branch are returned.</dd>
|
||||
</dl>
|
||||
|
||||
<p>Example Requests:</p>
|
||||
<div class=apiClick>groups/template</div>
|
||||
<br/>
|
||||
@@ -3260,7 +3391,8 @@ GET https://DomainName/mifosng-provider/api/v1/centers
|
||||
<br/>
|
||||
<div class=apiClick>groups/template?centerId=1</div>
|
||||
<br/>
|
||||
|
||||
<div class=apiClick>groups/template?centerId=1&staffInSelectedOfficeOnly=true</div>
|
||||
<br/>
|
||||
</div>
|
||||
<div class="method-example">
|
||||
<p>Template to create a standard group</p>
|
||||
@@ -3901,12 +4033,14 @@ GET https://DomainName/mifosng-provider/api/v1/groups
|
||||
<td class=fielddesc>The type of transaction processing strategy to be used.<br>
|
||||
At present some MFI specific ones exist. This is an important point of change for many MFIs.
|
||||
<br>Responsible for things like payment order and how early or late repayments should be processed.<br>
|
||||
Out of the box, four available:
|
||||
Out of the box options available are:
|
||||
<ol>
|
||||
<li>id=1, code=mifos-standard-strategy, name=Mifos style</li>
|
||||
<li>id=2, code=heavensfamily-strategy, name=Heavensfamily</li>
|
||||
<li>id=3, code=creocore-strategy, name=Creocore</li>
|
||||
<li>id=4, code=rbi-india-strategy, name=RBI (India)</li>
|
||||
<li>id=5, code=principal-interest-penalties-fees-order-strategy, name=Principal Interest Penalties Fees Order</li>
|
||||
<li>id=6, code=interest-principal-penalties-fees-order-strategy, name=Interest Principal Penalties Fees Order</li>
|
||||
</ol>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -3973,6 +4107,13 @@ GET https://DomainName/mifosng-provider/api/v1/groups
|
||||
</dd>
|
||||
<dd>If entered, productId, productName and selectedProduct
|
||||
fields are returned.</dd>
|
||||
|
||||
<dt>staffInSelectedOfficeOnly</dt>
|
||||
<dd>
|
||||
Boolean <span>optional</span>
|
||||
</dd>
|
||||
<dd>Defaults to false if not provided. If <strong>staffInSelectedOfficeOnly=true</strong> only loan officers
|
||||
who are associated with the selected branch are returned.</dd>
|
||||
</dl>
|
||||
<p>Example Requests:</p>
|
||||
<div class=apiClick>loans/template?templateType=individual&clientId=1</div>
|
||||
@@ -4900,21 +5041,20 @@ Request Body:
|
||||
"locale": "en_GB",
|
||||
"clientId": 1,
|
||||
"productId": 1,
|
||||
"principal": "100,000.00",
|
||||
"principal": "10,000.00",
|
||||
"loanTermFrequency": 12,
|
||||
"loanTermFrequencyType": 2,
|
||||
"loanType": "individual"
|
||||
"numberOfRepayments": 12,
|
||||
"loanType": "individual",
|
||||
"numberOfRepayments": 10,
|
||||
"repaymentEvery": 1,
|
||||
"repaymentFrequencyType": 2,
|
||||
"interestRatePerPeriod": 2,
|
||||
"interestRatePerPeriod": 10,
|
||||
"amortizationType": 1,
|
||||
"interestType": 0,
|
||||
"interestCalculationPeriodType": 1,
|
||||
"transactionProcessingStrategyId": 1,
|
||||
"expectedDisbursementDate": "20 September 2011",
|
||||
"submittedOnDate": "20 September 2011",
|
||||
"loanType": "individual"
|
||||
"expectedDisbursementDate": "10 Jun 2013",
|
||||
"submittedOnDate": "10 Jun 2013"
|
||||
}
|
||||
</code>
|
||||
<code class="method-response">
|
||||
@@ -6995,12 +7135,14 @@ Request Body:
|
||||
<td class=fielddesc>The type of transaction processing strategy to be used.<br>
|
||||
At present some MFI specific ones exist. This is an important point of change for many MFIs.
|
||||
<br>Responsible for things like payment order and how early or late repayments should be processed.<br>
|
||||
Out of the box, four available:
|
||||
Out of the box options available are:
|
||||
<ol>
|
||||
<li>id=1, code=mifos-standard-strategy, name=Mifos style</li>
|
||||
<li>id=2, code=heavensfamily-strategy, name=Heavensfamily</li>
|
||||
<li>id=3, code=creocore-strategy, name=Creocore</li>
|
||||
<li>id=4, code=rbi-india-strategy, name=RBI (India)</li>
|
||||
<li>id=5, code=principal-interest-penalties-fees-order-strategy, name=Principal Interest Penalties Fees Order</li>
|
||||
<li>id=6, code=interest-principal-penalties-fees-order-strategy, name=Interest Principal Penalties Fees Order</li>
|
||||
</ol>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -7590,7 +7732,7 @@ GET https://DomainName/api/v1/loanproducts/{productId}
|
||||
<td><div class="mifosXHeading2">Optional Fields</div></td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>inArrearsTolerance, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, charges, paymentChannelToFundSourceMappings</td>
|
||||
<td>inArrearsTolerance, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, charges, paymentChannelToFundSourceMappings, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings</td>
|
||||
</tr>
|
||||
|
||||
<tr class="matrixHeadingBG">
|
||||
@@ -7673,14 +7815,27 @@ Request Body:
|
||||
"writeOffAccountId":"41",
|
||||
"paymentChannelToFundSourceMappings": [
|
||||
{
|
||||
"paymentTypeId": "14",
|
||||
"fundSourceAccountId": "2"
|
||||
"paymentTypeId": "11",
|
||||
"fundSourceAccountId": "11"
|
||||
}
|
||||
],
|
||||
"feeToIncomeAccountMappings": [
|
||||
{
|
||||
"chargeId": "1",
|
||||
"incomeAccountId": "5"
|
||||
},
|
||||
{
|
||||
"paymentTypeId": "14",
|
||||
"fundSourceAccountId": "2"
|
||||
"chargeId": "2",
|
||||
"incomeAccountId": "8"
|
||||
}
|
||||
],
|
||||
"penaltyToIncomeAccountMappings": [
|
||||
{
|
||||
"chargeId": "6",
|
||||
"incomeAccountId": "9"
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
</code>
|
||||
<code class="method-response">
|
||||
@@ -9455,11 +9610,30 @@ Content-Type: application/json
|
||||
<div class="method-description">
|
||||
<h3>Accounting Rules</h3>
|
||||
<p>
|
||||
Its additional option for MFIs to define their own accounting rules.
|
||||
Its typically used to perform daily accounting postings of journal entries.
|
||||
It is typical scenario in MFI's that non accountants pass journal entries on a regular basis.
|
||||
For Ex: A branch office might deposit their entire cash at hand to their Bank account at the end of a
|
||||
working day. The branch office users might not understand enough of accounting to figure out which
|
||||
account needs to get credited and which account needs to be debited to represent this transaction.
|
||||
</p>
|
||||
<p>For an accounting rule debit account and credit account is fixed, so that we can avoid
|
||||
the selection of credit and debit accounts every time for default journal entries</p>
|
||||
<p>Enter accounting rules, an abstraction on top of manual Journal entires for enabling
|
||||
simpler data entry.
|
||||
An accounting rule can define any of the following abstractions
|
||||
<ul>
|
||||
<li>A Simple journal entry where both the credit and debit account have been preselected</li>
|
||||
<li>A Simple journal entry where either credit or debit accounts have been limited to a
|
||||
pre-selected list of accounts (Ex: Debit account should be one of "Bank of America" of "JP Morgan"
|
||||
and credit account should be "Cash")
|
||||
</li>
|
||||
<li>A Compound journal entry where multiple debits and / or multiple credits may be made
|
||||
amongst a set of preselected list of accounts (Ex: Credit account should be either "Bank Of America"
|
||||
or "Cash" and debit account can be "Employee Salary" and/or "Miscellenous Expenses")
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</p>
|
||||
|
||||
<p>An accounting rule can also be optionally associated with a branch, so that only a particular Branch's
|
||||
users have access to the rule</p>
|
||||
<table class=matrixHeading>
|
||||
<tr class="matrixHeadingBG">
|
||||
<td><div class="mifosXHeading2">Field Descriptions</div></td>
|
||||
@@ -9474,49 +9648,51 @@ Content-Type: application/json
|
||||
<td>description</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>The description about the accounting rule.</td>
|
||||
<td class=fielddesc>A description of the accounting rule.</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>officeId</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>The officeId of the office/branch for this accounting rule is applicable.</td>
|
||||
<td class=fielddesc>An Optional Office for this accounting rule is applicable.</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>debitAccountHead</td>
|
||||
<td>accountToDebit</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Debit account for creating accounting rule</td>
|
||||
<td class=fielddesc>ID of the target account to be Debited</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>creditAccountHead</td>
|
||||
<td>accountToCredit</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Credit account for creating accounting rule</td>
|
||||
<td class=fielddesc>ID of the target account to be Credited</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>debitTags</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Debit tags for creating accounting rule, These tags fetches the all chart of accounts that are tagged with these tagIds</td>
|
||||
<td class=fielddesc>A list of accounting Tags. Any Ledger account with this tag can serve as the
|
||||
account to be debited.<br> This parameter is optional, if <b>accountToDebit</b> present in the request params</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>creditTags</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Credit tags for creating accounting rule, These tags fetches the all chart of accounts that are tagged with these tagIds</td>
|
||||
<td class=fielddesc>A list of accounting Tags. Any Ledger account with this tag can serve as the
|
||||
account to be credited.<br> This parameter is optional, if <b>accountToCredit</b> present in the request params</td></td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>allowMultipleDebitEntries</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Allows to add multiple debits if the value is true, while creating journal entries with this rule</td>
|
||||
<td class=fielddesc>Allows passing multiple debit entries for the accounting rule</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>allowMultipleCreditEntries</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Allows to add multiple credits if the value is true, while creating journal entries with this rule</td>
|
||||
<td class=fielddesc>Allows passing multiple credit entries for the accounting rule</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@@ -9608,6 +9784,24 @@ GET https://DomainName/api/v1/accountingrules/template
|
||||
<div class="method-description">
|
||||
<h4>Create/Define a Accounting rule</h4>
|
||||
<p>Define a new Accounting rule.</p>
|
||||
<table class=matrixHeading>
|
||||
<tr class="matrixHeadingBG">
|
||||
<td><div class="mifosXHeading2">Mandatory Fields</div></td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>name, officeId,<br> accountToDebit OR debitTags,<br> accountToCredit OR creditTags.<br>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br />
|
||||
<table class=matrixHeading>
|
||||
<tr class="matrixHeadingBG">
|
||||
<td><div class="mifosXHeading2">Optional Fields</div></td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>description</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="method-example">
|
||||
<code class="method-declaration">
|
||||
@@ -9620,8 +9814,8 @@ Request Body:
|
||||
{
|
||||
"name": "test",
|
||||
"officeId": "1",
|
||||
"debitAccountHead": "21",
|
||||
"creditAccountHead": "9",
|
||||
"accountToDebit": "21",
|
||||
"accountToCredit": "9",
|
||||
"description": "Employee salary"
|
||||
}
|
||||
</code>
|
||||
@@ -9658,7 +9852,7 @@ Request Body:
|
||||
{
|
||||
"name": "test123",
|
||||
"officeId": "1",
|
||||
"debitAccountHead": "21",
|
||||
"accountToDebit": "21",
|
||||
"creditTags": ["12", "13"],
|
||||
"allowMultipleCreditEntries": "false",
|
||||
"description": "Employee salary"
|
||||
@@ -9677,9 +9871,9 @@ Request Body:
|
||||
{
|
||||
"name": "fordocstest",
|
||||
"officeId": "1",
|
||||
"debitTags": ["10", "11"],
|
||||
"debitTags": ["10","11"],
|
||||
"allowMultipleDebitEntries": "false",
|
||||
"creditAccountHead": "9",
|
||||
"accountToCredit": "9",
|
||||
"description": "for api docs"
|
||||
}
|
||||
</code>
|
||||
@@ -11433,6 +11627,83 @@ No Request Body:
|
||||
<h4>Create Data Table</h4>
|
||||
<p>Create a new data table and registers it with the Mifos X Core application
|
||||
table.</p>
|
||||
<table class=matrixHeading>
|
||||
<tr class="matrixHeadingBG">
|
||||
<td><div class="mifosXHeading2">Field Descriptions</div></td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><strong>Mandatory - </strong> datatableName</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>The name of the Data Table.</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><strong>Mandatory - </strong> apptableName</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>
|
||||
Application table name. Must be one of the following:
|
||||
<ul class="field">
|
||||
<li>m_client</li>
|
||||
<li>m_group</li>
|
||||
<li>m_loan</li>
|
||||
<li>m_office</li>
|
||||
<li>m_saving_account</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><strong>Mandatory - </strong>columns</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>An array of columns in the new Data Table.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class=matrixHeading>
|
||||
<tr class="matrixHeadingBG">
|
||||
<td><div class="mifosXHeading2">Field Descriptions - columns</div></td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><strong>Mandatory - </strong>name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Name of the created column. Can contain only alphanumeric characters, underscores and spaces, but cannot start with a number. Cannot start or end with an underscore or space.</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><strong>Mandatory - </strong>type</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>
|
||||
Column type. Must be one of the following:
|
||||
<ul class="field">
|
||||
<li>Date</li>
|
||||
<li>Decimal</li>
|
||||
<li>Dropdown</li>
|
||||
<li>Number</li>
|
||||
<li>String</li>
|
||||
<li>Text</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><strong>Mandatory [type = Dropdown] - </strong>code</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Used in Code Value fields. Column name becomes: <tt>code_cd_name</tt>. Mandatory if using type Dropdown, otherwise an error is returned.</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><em>Optional - </em>mandatory</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Determines whether this column must have a value in every entry. Optional, defaults to <tt>false</tt>.</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><strong>Mandatory [type = String] - </strong>length</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Length of the text field. Mandatory if type String is used, otherwise an error is returned.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="method-example">
|
||||
<code class="method-declaration">
|
||||
@@ -11619,6 +11890,153 @@ GET https://DomainName/api/v1/datatables/{datatable}
|
||||
<h4>Update Data Table</h4>
|
||||
<p>Modifies fields of a data table. If the apptableName parameter is passed,
|
||||
data table is deregistered and registered with the new application table.</p>
|
||||
<table class=matrixHeading>
|
||||
<tr class="matrixHeadingBG">
|
||||
<td><div class="mifosXHeading2">Field Descriptions</div></td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><em>Optional - </em> apptableName</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>
|
||||
Application table name. Only necessary if changing the application table this Data Table is registered to. Must be one of the following:
|
||||
<ul class="field">
|
||||
<li>m_client</li>
|
||||
<li>m_group</li>
|
||||
<li>m_loan</li>
|
||||
<li>m_office</li>
|
||||
<li>m_saving_account</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><em>Optional - </em>dropColumns</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>An array of columns to be deleted from the Data Table.</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><em>Optional - </em>addColumns</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>An array of columns to be added to the Data Table.</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><em>Optional - </em>changeColumns</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>An array of columns to be changed in the Data Table.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class=matrixHeading>
|
||||
<tr class="matrixHeadingBG">
|
||||
<td><div class="mifosXHeading2">Field Descriptions - dropColumns</div></td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><strong>Mandatory - </strong>name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Requires a full name of the deleted column to be provided.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class=matrixHeading>
|
||||
<tr class="matrixHeadingBG">
|
||||
<td><div class="mifosXHeading2">Field Descriptions - addColumns</div></td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><strong>Mandatory - </strong>name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Name of the created column. Can contain only alphanumeric characters, underscores and spaces, but cannot start with a number. Cannot start or end with an underscore or space.</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><strong>Mandatory - </strong>type</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>
|
||||
Column type. Must be one of the following:
|
||||
<ul class="field">
|
||||
<li>Date</li>
|
||||
<li>Decimal</li>
|
||||
<li>Dropdown</li>
|
||||
<li>Number</li>
|
||||
<li>String</li>
|
||||
<li>Text</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><strong>Mandatory [type = Dropdown] - </strong>code</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Used in Code Value fields. Column name becomes: <tt>code_cd_name</tt>. Mandatory if using type Dropdown, otherwise an error is returned.</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><em>Optional - </em>mandatory</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Determines whether this column must have a value in every entry. Optional, defaults to <tt>false</tt>.</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><strong>Mandatory [type = String] - </strong>length</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Length of the text field. Mandatory if type String is used, otherwise an error is returned.</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><em>Optional - </em>after</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Only used when re-ordering Data Table columns. Requires a full column name to be provided.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class=matrixHeading>
|
||||
<tr class="matrixHeadingBG">
|
||||
<td><div class="mifosXHeading2">Field Descriptions - changeColumns</div></td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><strong>Mandatory - </strong>name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Name of the created column. Can contain only alphanumeric characters, underscores and spaces, but cannot start with a number. Cannot start or end with an underscore or space.</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><em>Optional - </em>newName</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>New name of the created column. Can contain only alphanumeric characters, underscores and spaces, but cannot start with a number. Cannot start or end with an underscore or space.</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><strong>Mandatory [type = Dropdown] - </strong>code</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Used in Code Value fields. Column name becomes: <tt>code_cd_name</tt>. Mandatory if using type Dropdown, otherwise an error is returned.</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><em>Optional [type = Dropdown] - </em>newCode</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Used in Code Value fields. Column name becomes: <tt>code_cd_name</tt>. Optional if using type Dropdown, otherwise an error is returned.</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><em>Optional - </em>mandatory</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Determines whether this column must have a value in every entry. Optional, defaults to <tt>false</tt>.</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><strong>Mandatory [type = String] - </strong>length</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Length of the text field. Mandatory if type String is used, otherwise an error is returned.</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td><em>Optional - </em>after</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>Only used when re-ordering Data Table columns. Requires a full column name to be provided.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="method-example">
|
||||
<code class="method-declaration">
|
||||
@@ -11631,26 +12049,31 @@ Content-Type: application/json
|
||||
Request Body:
|
||||
{
|
||||
"apptableName": "m_client",
|
||||
"columns": [
|
||||
"dropColumns": [
|
||||
{
|
||||
"name": "Gender",
|
||||
"name": "Gender_cd_Question"
|
||||
}
|
||||
],
|
||||
"addColumns": [
|
||||
{
|
||||
"name": "Question",
|
||||
"type": "Dropdown",
|
||||
"code": "Gender"
|
||||
},
|
||||
{
|
||||
"name": "Some Decimal",
|
||||
"type": "Decimal",
|
||||
"code": "Gender",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"name": "Birth Date",
|
||||
"type": "Date"
|
||||
},
|
||||
"name": "Some Number",
|
||||
"type": "Number",
|
||||
"after": "Some Field"
|
||||
}
|
||||
],
|
||||
"changeColumns": [
|
||||
{
|
||||
"name": "Question 2",
|
||||
"type": "String",
|
||||
"length": 100,
|
||||
"mandatory": false
|
||||
"name": "Question",
|
||||
"newName": "Question 2",
|
||||
"mandatory": true,
|
||||
"code": "Gender",
|
||||
"newCode": "Gender2"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -11668,7 +12091,7 @@ Request Body:
|
||||
<div class="method-section">
|
||||
<div class="method-description">
|
||||
<h4>Delete Data Table</h4>
|
||||
<p>Deletes a data table and unregisters it from the Mifos X Core
|
||||
<p>Deletes a data table and deregisters it from the Mifos X Core
|
||||
application table.</p>
|
||||
</div>
|
||||
<div class="method-example">
|
||||
@@ -15386,6 +15809,54 @@ GET https://DomainName/api/v1/search?query=000000111
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr class="alt">
|
||||
<td><a href="#groups">Group</a></td>
|
||||
<td>groups</td>
|
||||
<td><a href="#groups_create">Create a Group</a></td>
|
||||
<td><a href="#groups_list">List Groups</a></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>groups/template</td>
|
||||
<td></td>
|
||||
<td><a href="#groups_template">Retrieve Group Template</a></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr class="alt">
|
||||
<td></td>
|
||||
<td>groups/{groupId}</td>
|
||||
<td></td>
|
||||
<td><a href="#groups_retrieve">Retrieve a Group</a></td>
|
||||
<td><a href="#groups_update">Update a Group</a></td>
|
||||
<td><a href="#groups_delete">Delete a Group</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>groups/{groupId}?command=activate</td>
|
||||
<td><a href="#groups_activate">Activate a Group</a></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>groups/{groupId}?command=associateClients</td>
|
||||
<td><a href="#groups_associate_clients">Associate Clients</a></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>groups/{groupId}?command=disassociateClients</td>
|
||||
<td><a href="#groups_disassociate_clients">Disassociate Clients</a></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr class="alt">
|
||||
<td><a href="#loanproducts">Loan Product</a></td>
|
||||
<td>loanproducts</td>
|
||||
@@ -16128,54 +16599,6 @@ GET https://DomainName/api/v1/search?query=000000111
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr class="alt">
|
||||
<td><a href="#groups">Group</a></td>
|
||||
<td>groups</td>
|
||||
<td><a href="#groups_create">Create a Group</a></td>
|
||||
<td><a href="#groups_list">List Groups</a></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>groups/template</td>
|
||||
<td></td>
|
||||
<td><a href="#groups_template">Retrieve Group Template</a></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr class="alt">
|
||||
<td></td>
|
||||
<td>groups/{groupId}</td>
|
||||
<td></td>
|
||||
<td><a href="#groups_retrieve">Retrieve a Group</a></td>
|
||||
<td><a href="#groups_update">Update a Group</a></td>
|
||||
<td><a href="#groups_delete">Delete a Group</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>groups/{groupId}?command=activate</td>
|
||||
<td><a href="#groups_activate">Activate a Group</a></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>groups/{groupId}?command=associateClients</td>
|
||||
<td><a href="#groups_associate_clients">Associate Clients</a></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>groups/{groupId}?command=disassociateClients</td>
|
||||
<td><a href="#groups_disassociate_clients">Disassociate Clients</a></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr class="alt">
|
||||
<td><a href="#savingsproducts">Savings Product</a></td>
|
||||
<td>savingsproducts</td>
|
||||
|
||||
@@ -724,3 +724,16 @@ strong { font-weight: bold; }
|
||||
.stripe-version {
|
||||
float: left;
|
||||
}
|
||||
|
||||
ul.field {
|
||||
margin: 5px 10px;
|
||||
}
|
||||
|
||||
ul.field li {
|
||||
list-style: square inside none;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
tt {
|
||||
font-size: 9.5pt;
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE `acc_accounting_rule`
|
||||
CHANGE COLUMN `debit_account_id` `debit_account_id` BIGINT(20) NULL DEFAULT NULL AFTER `office_id`,
|
||||
CHANGE COLUMN `credit_account_id` `credit_account_id` BIGINT(20) NULL DEFAULT NULL AFTER `allow_multiple_debits`;
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
create table `m_holiday`(
|
||||
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(100) NOT NULL,
|
||||
`from_date` DATETIME NOT NULL,
|
||||
`to_date` DATETIME NOT NULL,
|
||||
`description` varchar(100) NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `holiday_name` (`name`)
|
||||
);
|
||||
|
||||
CREATE TABLE `m_holiday_office` (
|
||||
`holiday_id` BIGINT(20) NOT NULL,
|
||||
`office_id` BIGINT(20) NOT NULL,
|
||||
PRIMARY KEY (`holiday_id`, `office_id`),
|
||||
INDEX `m_holiday_id_ibfk_1` (`holiday_id`),
|
||||
INDEX `m_office_id_ibfk_2` (`office_id`),
|
||||
CONSTRAINT `m_holiday_id_ibfk_1` FOREIGN KEY (`holiday_id`) REFERENCES `m_holiday` (`id`),
|
||||
CONSTRAINT `m_office_id_ibfk_2` FOREIGN KEY (`office_id`) REFERENCES `m_office` (`id`)
|
||||
);
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('organisation', 'CREATE_HOLIDAY', 'HOLIDAY', 'CREATE', 0);
|
||||
@@ -0,0 +1,22 @@
|
||||
INSERT INTO `m_code` (`code_name`, `is_system_defined`) VALUES ('GROUPROLE', 1);
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'ASSIGNROLE_GROUP', 'GROUP', 'ASSIGNROLE', 0);
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'UNASSIGNROLE_GROUP', 'GROUP', 'UNASSIGNROLE', 0);
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'UPDATEROLE_GROUP', 'GROUP', 'UPDATEROLE', 0);
|
||||
|
||||
CREATE TABLE `m_group_roles` (
|
||||
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
`client_id` BIGINT(20) NULL DEFAULT NULL,
|
||||
`group_id` BIGINT(20) NULL DEFAULT NULL,
|
||||
`role_cv_id` INT(11) NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `FKGroupRoleClientId` (`client_id`),
|
||||
INDEX `FKGroupRoleGroupId` (`group_id`),
|
||||
INDEX `FK_grouprole_m_codevalue` (`role_cv_id`),
|
||||
UNIQUE INDEX `UNIQUE_GROUP_ROLES` (`client_id`, `group_id`, `role_cv_id`),
|
||||
CONSTRAINT `FKGroupRoleClientId` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`),
|
||||
CONSTRAINT `FKGroupRoleGroupId` FOREIGN KEY (`group_id`) REFERENCES `m_group` (`id`),
|
||||
CONSTRAINT `FK_grouprole_m_codevalue` FOREIGN KEY (`role_cv_id`) REFERENCES `m_code_value` (`id`)
|
||||
)
|
||||
COLLATE='utf8_general_ci'
|
||||
ENGINE=InnoDB;
|
||||
@@ -0,0 +1,320 @@
|
||||
/* Leaving as out-of-box (but non-core reports) for now
|
||||
could be removed later if people think too many non-generic
|
||||
reports are being added
|
||||
used in quipo TEVI dashboard (landing pages) */
|
||||
|
||||
DELETE FROM `stretchy_report` where report_name = 'FieldAgentStats';
|
||||
DELETE FROM `stretchy_report` where report_name = 'FieldAgentPrograms';
|
||||
DELETE FROM `stretchy_report` where report_name = 'ProgramDetails';
|
||||
DELETE FROM `stretchy_report` where report_name = 'ChildrenStaffList';
|
||||
DELETE FROM `stretchy_report` where report_name = 'CoordinatorStats';
|
||||
DELETE FROM `stretchy_report` where report_name = 'BranchManagerStats';
|
||||
DELETE FROM `stretchy_report` where report_name = 'ProgramDirectorStats';
|
||||
DELETE FROM `stretchy_report` where report_name = 'ProgramStats';
|
||||
|
||||
DELETE FROM `m_permission` where entity_name = 'FieldAgentStats';
|
||||
DELETE FROM `m_permission` where entity_name = 'FieldAgentPrograms';
|
||||
DELETE FROM `m_permission` where entity_name = 'ProgramDetails';
|
||||
DELETE FROM `m_permission` where entity_name = 'ChildrenStaffList';
|
||||
DELETE FROM `m_permission` where entity_name = 'CoordinatorStats';
|
||||
DELETE FROM `m_permission` where entity_name = 'BranchManagerStats';
|
||||
DELETE FROM `m_permission` where entity_name = 'ProgramDirectorStats';
|
||||
DELETE FROM `m_permission` where entity_name = 'ProgramStats';
|
||||
|
||||
|
||||
INSERT INTO `stretchy_report` (`report_name`, `report_type`, `report_category`, `core_report`, `use_report`, `description`, `report_sql`)
|
||||
VALUES ('FieldAgentStats', 'Table', 'Quipo', false, false, 'Field Agent Statistics',
|
||||
|
||||
"
|
||||
select ifnull(cur.display_symbol, l.currency_code) as Currency,
|
||||
/*This query will return more than one entry if more than one currency is used */
|
||||
count(distinct(c.id)) as activeClients, count(*) as activeLoans,
|
||||
sum(l.principal_disbursed_derived) as disbursedAmount,
|
||||
sum(l.principal_outstanding_derived) as loanOutstandingAmount,
|
||||
round((sum(l.principal_outstanding_derived) * 100) / sum(l.principal_disbursed_derived),2) as loanOutstandingPC,
|
||||
'???' as loanOverPaymentAmount,
|
||||
sum(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
l.principal_outstanding_derived,0)) as portfolioAtRisk,
|
||||
|
||||
round((sum(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
l.principal_outstanding_derived,0)) * 100) / sum(l.principal_outstanding_derived), 2) as portfolioAtRiskPC,
|
||||
|
||||
count(distinct(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
c.id,null))) as clientsInDefault,
|
||||
round((count(distinct(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
c.id,null))) * 100) / count(distinct(c.id)),2) as clientsInDefaultPC,
|
||||
(sum(l.principal_disbursed_derived) / count(*)) as averageLoanAmount
|
||||
from m_staff fa
|
||||
join m_office o on o.id = fa.office_id
|
||||
and o.hierarchy like concat('${currentUserHierarchy}', '%')
|
||||
join m_group pgm on pgm.staff_id = fa.id
|
||||
join m_loan l on l.group_id = pgm.id and l.client_id is not null
|
||||
left join m_currency cur on cur.code = l.currency_code
|
||||
left join m_loan_arrears_aging laa on laa.loan_id = l.id
|
||||
join m_client c on c.id = l.client_id
|
||||
where fa.id = ${staffId}
|
||||
and l.loan_status_id = 300
|
||||
group by l.currency_code
|
||||
");
|
||||
|
||||
|
||||
INSERT INTO `stretchy_report` (`report_name`, `report_type`, `report_category`, `core_report`, `use_report`, `description`, `report_sql`)
|
||||
VALUES ('FieldAgentPrograms', 'Table', 'Quipo', false, false, 'List of Field Agent Programs',
|
||||
|
||||
"
|
||||
select pgm.id, pgm.display_name as `name`, sts.enum_message_property as status
|
||||
from m_group pgm
|
||||
join m_office o on o.id = pgm.office_id
|
||||
and o.hierarchy like concat('${currentUserHierarchy}', '%')
|
||||
left join r_enum_value sts on sts.enum_name = 'status_enum' and sts.enum_id = pgm.status_enum
|
||||
where pgm.staff_id = ${staffId}
|
||||
");
|
||||
|
||||
|
||||
INSERT INTO `stretchy_report` (`report_name`, `report_type`, `report_category`, `core_report`, `use_report`, `description`, `report_sql`)
|
||||
VALUES ('ProgramDetails', 'Table', 'Quipo', false, false, 'List of Loans in a Program',
|
||||
|
||||
"
|
||||
select l.id as loanId, l.account_no as loanAccountNo, c.id as clientId, c.account_no as clientAccountNo,
|
||||
pgm.display_name as programName,
|
||||
|
||||
(select count(*)
|
||||
from m_loan cy
|
||||
where cy.group_id = pgm.id and cy.client_id =c.id
|
||||
and cy.disbursedon_date <= l.disbursedon_date) as loanCycleNo,
|
||||
|
||||
c.display_name as clientDisplayName,
|
||||
ifnull(cur.display_symbol, l.currency_code) as Currency,
|
||||
ifnull(l.principal_repaid_derived,0.0) as loanRepaidAmount,
|
||||
ifnull(l.principal_outstanding_derived, 0.0) as loanOutstandingAmount,
|
||||
'???' as loanInAdvanceAmount,
|
||||
|
||||
ifnull(laa.principal_overdue_derived, 0.0) as loanInArrearsAmount,
|
||||
if(ifnull(laa.principal_overdue_derived, 0.00) > 0, 'Yes', 'No') as inDefault,
|
||||
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
l.principal_outstanding_derived,0) as portfolioAtRisk
|
||||
|
||||
from m_group pgm
|
||||
join m_office o on o.id = pgm.office_id
|
||||
and o.hierarchy like concat('${currentUserHierarchy}', '%')
|
||||
join m_loan l on l.group_id = pgm.id and l.client_id is not null
|
||||
left join m_currency cur on cur.code = l.currency_code
|
||||
join m_client c on c.id = l.client_id
|
||||
left join m_loan_arrears_aging laa on laa.loan_id = l.id
|
||||
where pgm.id = ${programId}
|
||||
and l.loan_status_id = 300
|
||||
order by c.display_name, l.account_no
|
||||
|
||||
");
|
||||
|
||||
|
||||
INSERT INTO `stretchy_report` (`report_name`, `report_type`, `report_category`, `core_report`, `use_report`, `description`, `report_sql`)
|
||||
VALUES ('ChildrenStaffList', 'Table', 'Quipo', false, false, 'Get Next Level Down Staff',
|
||||
|
||||
"
|
||||
select s.id, s.display_name,
|
||||
s.firstname, s.lastname, s.organisational_role_enum,
|
||||
s.organisational_role_parent_staff_id,
|
||||
sp.display_name as `organisational_role_parent_staff_display_name`
|
||||
from m_staff s
|
||||
join m_staff sp on s.organisational_role_parent_staff_id = sp.id
|
||||
where s.organisational_role_parent_staff_id = ${staffId}
|
||||
");
|
||||
|
||||
|
||||
INSERT INTO `stretchy_report` (`report_name`, `report_type`, `report_category`, `core_report`, `use_report`, `description`, `report_sql`)
|
||||
VALUES ('CoordinatorStats', 'Table', 'Quipo', false, false, 'Coordinator Statistics',
|
||||
|
||||
"
|
||||
select ifnull(cur.display_symbol, l.currency_code) as Currency,
|
||||
/*This query will return more than one entry if more than one currency is used */
|
||||
count(distinct(c.id)) as activeClients, count(*) as activeLoans,
|
||||
sum(l.principal_disbursed_derived) as disbursedAmount,
|
||||
sum(l.principal_outstanding_derived) as loanOutstandingAmount,
|
||||
round((sum(l.principal_outstanding_derived) * 100) / sum(l.principal_disbursed_derived),2) as loanOutstandingPC,
|
||||
'???' as loanOverPaymentAmount,
|
||||
sum(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
l.principal_outstanding_derived,0)) as portfolioAtRisk,
|
||||
|
||||
round((sum(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
l.principal_outstanding_derived,0)) * 100) / sum(l.principal_outstanding_derived), 2) as portfolioAtRiskPC,
|
||||
|
||||
count(distinct(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
c.id,null))) as clientsInDefault,
|
||||
round((count(distinct(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
c.id,null))) * 100) / count(distinct(c.id)),2) as clientsInDefaultPC,
|
||||
(sum(l.principal_disbursed_derived) / count(*)) as averageLoanAmount
|
||||
from m_staff coord
|
||||
join m_staff fa on fa.organisational_role_parent_staff_id = coord.id
|
||||
join m_office o on o.id = fa.office_id
|
||||
and o.hierarchy like concat('${currentUserHierarchy}', '%')
|
||||
join m_group pgm on pgm.staff_id = fa.id
|
||||
join m_loan l on l.group_id = pgm.id and l.client_id is not null
|
||||
left join m_currency cur on cur.code = l.currency_code
|
||||
left join m_loan_arrears_aging laa on laa.loan_id = l.id
|
||||
join m_client c on c.id = l.client_id
|
||||
where coord.id = ${staffId}
|
||||
and l.loan_status_id = 300
|
||||
group by l.currency_code
|
||||
");
|
||||
|
||||
|
||||
INSERT INTO `stretchy_report` (`report_name`, `report_type`, `report_category`, `core_report`, `use_report`, `description`, `report_sql`)
|
||||
VALUES ('BranchManagerStats', 'Table', 'Quipo', false, false, 'Branch Manager Statistics',
|
||||
|
||||
"
|
||||
select ifnull(cur.display_symbol, l.currency_code) as Currency,
|
||||
/*This query will return more than one entry if more than one currency is used */
|
||||
count(distinct(c.id)) as activeClients, count(*) as activeLoans,
|
||||
sum(l.principal_disbursed_derived) as disbursedAmount,
|
||||
sum(l.principal_outstanding_derived) as loanOutstandingAmount,
|
||||
round((sum(l.principal_outstanding_derived) * 100) / sum(l.principal_disbursed_derived),2) as loanOutstandingPC,
|
||||
'???' as loanOverPaymentAmount,
|
||||
sum(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
l.principal_outstanding_derived,0)) as portfolioAtRisk,
|
||||
|
||||
round((sum(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
l.principal_outstanding_derived,0)) * 100) / sum(l.principal_outstanding_derived), 2) as portfolioAtRiskPC,
|
||||
|
||||
count(distinct(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
c.id,null))) as clientsInDefault,
|
||||
round((count(distinct(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
c.id,null))) * 100) / count(distinct(c.id)),2) as clientsInDefaultPC,
|
||||
(sum(l.principal_disbursed_derived) / count(*)) as averageLoanAmount
|
||||
from m_staff bm
|
||||
join m_staff coord on coord.organisational_role_parent_staff_id = bm.id
|
||||
join m_staff fa on fa.organisational_role_parent_staff_id = coord.id
|
||||
join m_office o on o.id = fa.office_id
|
||||
and o.hierarchy like concat('${currentUserHierarchy}', '%')
|
||||
join m_group pgm on pgm.staff_id = fa.id
|
||||
join m_loan l on l.group_id = pgm.id and l.client_id is not null
|
||||
left join m_currency cur on cur.code = l.currency_code
|
||||
left join m_loan_arrears_aging laa on laa.loan_id = l.id
|
||||
join m_client c on c.id = l.client_id
|
||||
where bm.id = ${staffId}
|
||||
and l.loan_status_id = 300
|
||||
group by l.currency_code
|
||||
");
|
||||
|
||||
|
||||
INSERT INTO `stretchy_report` (`report_name`, `report_type`, `report_category`, `core_report`, `use_report`, `description`, `report_sql`)
|
||||
VALUES ('ProgramDirectorStats', 'Table', 'Quipo', false, false, 'Program DirectorStatistics',
|
||||
|
||||
"
|
||||
select ifnull(cur.display_symbol, l.currency_code) as Currency,
|
||||
/*This query will return more than one entry if more than one currency is used */
|
||||
count(distinct(c.id)) as activeClients, count(*) as activeLoans,
|
||||
sum(l.principal_disbursed_derived) as disbursedAmount,
|
||||
sum(l.principal_outstanding_derived) as loanOutstandingAmount,
|
||||
round((sum(l.principal_outstanding_derived) * 100) / sum(l.principal_disbursed_derived),2) as loanOutstandingPC,
|
||||
'???' as loanOverPaymentAmount,
|
||||
sum(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
l.principal_outstanding_derived,0)) as portfolioAtRisk,
|
||||
|
||||
round((sum(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
l.principal_outstanding_derived,0)) * 100) / sum(l.principal_outstanding_derived), 2) as portfolioAtRiskPC,
|
||||
|
||||
count(distinct(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
c.id,null))) as clientsInDefault,
|
||||
round((count(distinct(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
c.id,null))) * 100) / count(distinct(c.id)),2) as clientsInDefaultPC,
|
||||
(sum(l.principal_disbursed_derived) / count(*)) as averageLoanAmount
|
||||
from m_staff pd
|
||||
join m_staff bm on bm.organisational_role_parent_staff_id = pd.id
|
||||
join m_staff coord on coord.organisational_role_parent_staff_id = bm.id
|
||||
join m_staff fa on fa.organisational_role_parent_staff_id = coord.id
|
||||
join m_office o on o.id = fa.office_id
|
||||
and o.hierarchy like concat('${currentUserHierarchy}', '%')
|
||||
join m_group pgm on pgm.staff_id = fa.id
|
||||
join m_loan l on l.group_id = pgm.id and l.client_id is not null
|
||||
left join m_currency cur on cur.code = l.currency_code
|
||||
left join m_loan_arrears_aging laa on laa.loan_id = l.id
|
||||
join m_client c on c.id = l.client_id
|
||||
where pd.id = ${staffId}
|
||||
and l.loan_status_id = 300
|
||||
group by l.currency_code
|
||||
");
|
||||
|
||||
|
||||
INSERT INTO `stretchy_report` (`report_name`, `report_type`, `report_category`, `core_report`, `use_report`, `description`, `report_sql`)
|
||||
VALUES ('ProgramStats', 'Table', 'Quipo', false, false, 'Program Statistics',
|
||||
|
||||
"
|
||||
select ifnull(cur.display_symbol, l.currency_code) as Currency,
|
||||
/*This query will return more than one entry if more than one currency is used */
|
||||
count(distinct(c.id)) as activeClients, count(*) as activeLoans,
|
||||
sum(l.principal_disbursed_derived) as disbursedAmount,
|
||||
sum(l.principal_outstanding_derived) as loanOutstandingAmount,
|
||||
round((sum(l.principal_outstanding_derived) * 100) / sum(l.principal_disbursed_derived),2) as loanOutstandingPC,
|
||||
'???' as loanOverPaymentAmount,
|
||||
sum(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
l.principal_outstanding_derived,0)) as portfolioAtRisk,
|
||||
|
||||
round((sum(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
l.principal_outstanding_derived,0)) * 100) / sum(l.principal_outstanding_derived), 2) as portfolioAtRiskPC,
|
||||
|
||||
count(distinct(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
c.id,null))) as clientsInDefault,
|
||||
round((count(distinct(
|
||||
if(date_sub(curdate(), interval 28 day) > ifnull(laa.overdue_since_date_derived, curdate()),
|
||||
c.id,null))) * 100) / count(distinct(c.id)),2) as clientsInDefaultPC,
|
||||
(sum(l.principal_disbursed_derived) / count(*)) as averageLoanAmount
|
||||
from m_group pgm
|
||||
join m_office o on o.id = pgm.office_id
|
||||
and o.hierarchy like concat('${currentUserHierarchy}', '%')
|
||||
join m_loan l on l.group_id = pgm.id and l.client_id is not null
|
||||
left join m_currency cur on cur.code = l.currency_code
|
||||
left join m_loan_arrears_aging laa on laa.loan_id = l.id
|
||||
join m_client c on c.id = l.client_id
|
||||
where pgm.id = ${programId}
|
||||
and l.loan_status_id = 300
|
||||
group by l.currency_code
|
||||
");
|
||||
|
||||
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
|
||||
VALUES ('report', 'READ_FieldAgentStats', 'FieldAgentStats', 'READ', 0);
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
|
||||
VALUES ('report', 'READ_FieldAgentPrograms', 'FieldAgentPrograms', 'READ', 0);
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
|
||||
VALUES ('report', 'READ_ProgramDetails', 'ProgramDetails', 'READ', 0);
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
|
||||
VALUES ('report', 'READ_ChildrenStaffList', 'ChildrenStaffList', 'READ', 0);
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
|
||||
VALUES ('report', 'READ_CoordinatorStats', 'CoordinatorStats', 'READ', 0);
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
|
||||
VALUES ('report', 'READ_BranchManagerStats', 'BranchManagerStats', 'READ', 0);
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
|
||||
VALUES ('report', 'READ_ProgramDirectorStats', 'ProgramDirectorStats', 'READ', 0);
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
|
||||
VALUES ('report', 'READ_ProgramStats', 'ProgramStats', 'READ', 0);
|
||||
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
|
||||
/* Leaving as out-of-box (but non-core report) for now
|
||||
could be removed later if people think too many non-generic
|
||||
reports are being added
|
||||
similar example used in small MFI Elevate Africa */
|
||||
|
||||
|
||||
delete from stretchy_report_parameter
|
||||
where report_id = (select r.id from stretchy_report r where r.report_name = 'TxnRunningBalances');
|
||||
|
||||
DELETE FROM `stretchy_report` where report_name = 'TxnRunningBalances';
|
||||
|
||||
DELETE FROM `m_permission` where entity_name = 'TxnRunningBalances';
|
||||
|
||||
|
||||
INSERT INTO `stretchy_report` (`report_name`, `report_type`, `report_category`, `core_report`, `use_report`, `description`, `report_sql`)
|
||||
VALUES ('TxnRunningBalances', 'Table', 'Transaction', false, false,
|
||||
"Running Balance Txn report for Individual Lending.
|
||||
Suitable for small MFI's. Larger could use it using the branch or other parameters.
|
||||
Basically, suck it and see if its quick enough for you out-of-te box or whether it needs performance work in your situation.
|
||||
",
|
||||
|
||||
"
|
||||
select date('${startDate}') as 'Transaction Date', 'Opening Balance' as `Transaction Type`, null as Office,
|
||||
null as 'Loan Officer', null as `Loan Account No`, null as `Loan Product`, null as `Currency`,
|
||||
null as `Client Account No`, null as Client,
|
||||
null as Amount, null as Principal, null as Interest,
|
||||
@totalOutstandingPrincipal :=
|
||||
ifnull(round(sum(
|
||||
if (txn.transaction_type_enum = 1 /* disbursement */,
|
||||
ifnull(txn.amount,0.00),
|
||||
ifnull(txn.principal_portion_derived,0.00) * -1))
|
||||
,2),0.00) as 'Outstanding Principal',
|
||||
|
||||
@totalInterestIncome :=
|
||||
ifnull(round(sum(
|
||||
if (txn.transaction_type_enum in (2,5,8) /* repayment, repayment at disbursal, recovery repayment */,
|
||||
ifnull(txn.interest_portion_derived,0.00),
|
||||
0))
|
||||
,2),0.00) as 'Interest Income',
|
||||
|
||||
@totalWriteOff :=
|
||||
ifnull(round(sum(
|
||||
if (txn.transaction_type_enum = 6 /* write-off */,
|
||||
ifnull(txn.principal_portion_derived,0.00),
|
||||
0))
|
||||
,2),0.00) as 'Principal Write Off'
|
||||
from m_office o
|
||||
join m_office ounder on ounder.hierarchy like concat(o.hierarchy, '%')
|
||||
and ounder.hierarchy like concat('${currentUserHierarchy}', '%')
|
||||
join m_client c on c.office_id = ounder.id
|
||||
join m_loan l on l.client_id = c.id
|
||||
join m_product_loan lp on lp.id = l.product_id
|
||||
join m_loan_transaction txn on txn.loan_id = l.id
|
||||
left join m_currency cur on cur.code = l.currency_code
|
||||
where txn.is_reversed = false
|
||||
and txn.transaction_type_enum not in (10,11)
|
||||
and o.id = ${officeId}
|
||||
and txn.transaction_date < date('${startDate}')
|
||||
|
||||
union all
|
||||
|
||||
select x.`Transaction Date`, x.`Transaction Type`, x.Office, x.`Loan Officer`, x.`Loan Account No`, x.`Loan Product`, x.`Currency`,
|
||||
x.`Client Account No`, x.Client, x.Amount, x.Principal, x.Interest,
|
||||
cast(round(
|
||||
if (x.transaction_type_enum = 1 /* disbursement */,
|
||||
@totalOutstandingPrincipal := @totalOutstandingPrincipal + x.`Amount`,
|
||||
@totalOutstandingPrincipal := @totalOutstandingPrincipal - x.`Principal`)
|
||||
,2) as decimal(19,2)) as 'Outstanding Principal',
|
||||
cast(round(
|
||||
if (x.transaction_type_enum in (2,5,8) /* repayment, repayment at disbursal, recovery repayment */,
|
||||
@totalInterestIncome := @totalInterestIncome + x.`Interest`,
|
||||
@totalInterestIncome)
|
||||
,2) as decimal(19,2)) as 'Interest Income',
|
||||
cast(round(
|
||||
if (x.transaction_type_enum = 6 /* write-off */,
|
||||
@totalWriteOff := @totalWriteOff + x.`Principal`,
|
||||
@totalWriteOff)
|
||||
,2) as decimal(19,2)) as 'Principal Write Off'
|
||||
from
|
||||
(select txn.transaction_type_enum, txn.id as txn_id, txn.transaction_date as 'Transaction Date',
|
||||
cast(
|
||||
ifnull(re.enum_message_property, concat('Unknown Transaction Type Value: ' , txn.transaction_type_enum))
|
||||
as char) as 'Transaction Type',
|
||||
ounder.`name` as Office, lo.display_name as 'Loan Officer',
|
||||
l.account_no as 'Loan Account No', lp.`name` as 'Loan Product',
|
||||
ifnull(cur.display_symbol, l.currency_code) as Currency,
|
||||
c.account_no as 'Client Account No', c.display_name as 'Client',
|
||||
ifnull(txn.amount,0.00) as Amount,
|
||||
ifnull(txn.principal_portion_derived,0.00) as Principal,
|
||||
ifnull(txn.interest_portion_derived,0.00) as Interest
|
||||
from m_office o
|
||||
join m_office ounder on ounder.hierarchy like concat(o.hierarchy, '%')
|
||||
and ounder.hierarchy like concat('${currentUserHierarchy}', '%')
|
||||
join m_client c on c.office_id = ounder.id
|
||||
join m_loan l on l.client_id = c.id
|
||||
left join m_staff lo on lo.id = l.loan_officer_id
|
||||
join m_product_loan lp on lp.id = l.product_id
|
||||
join m_loan_transaction txn on txn.loan_id = l.id
|
||||
left join m_currency cur on cur.code = l.currency_code
|
||||
left join r_enum_value re on re.enum_name = 'transaction_type_enum'
|
||||
and re.enum_id = txn.transaction_type_enum
|
||||
where txn.is_reversed = false
|
||||
and txn.transaction_type_enum not in (10,11)
|
||||
and (ifnull(l.loan_officer_id, -10) = '${loanOfficerId}' or '-1' = '${loanOfficerId}')
|
||||
and o.id = ${officeId}
|
||||
and txn.transaction_date >= date('${startDate}')
|
||||
and txn.transaction_date <= date('${endDate}')
|
||||
order by txn.transaction_date, txn.id) x
|
||||
");
|
||||
|
||||
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
|
||||
VALUES ('report', 'READ_TxnRunningBalances', 'TxnRunningBalances', 'READ', 0);
|
||||
|
||||
|
||||
insert into stretchy_report_parameter (report_id, parameter_id)
|
||||
select r.id, p.id
|
||||
from stretchy_report r,
|
||||
stretchy_parameter p
|
||||
where r.report_name = 'TxnRunningBalances'
|
||||
and p.parameter_name in ('startDateSelect', 'endDateSelect', 'OfficeIdSelectOne',
|
||||
'loanOfficerIdSelectAll');
|
||||
@@ -0,0 +1,5 @@
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'UNASSIGNSTAFF_CLIENT', 'CLIENT', 'UNASSIGNSTAFF', 0);
|
||||
ALTER TABLE m_client
|
||||
ADD COLUMN `staff_id` BIGINT(20) NULL DEFAULT NULL AFTER `office_id`,
|
||||
ADD INDEX `client_staff_id` (`staff_id`),
|
||||
ADD CONSTRAINT `FK_m_client_m_staff` FOREIGN KEY (`staff_id`) REFERENCES `m_staff` (`id`);
|
||||
@@ -1 +1 @@
|
||||
releaseVersion=1.3.0.RELEASE
|
||||
releaseVersion=1.4.0.RELEASE
|
||||
+1
-1
@@ -12,7 +12,7 @@ import java.util.Set;
|
||||
* Enum of all parameters passed in while creating/updating a loan product
|
||||
***/
|
||||
public enum AccountingRuleJsonInputParams {
|
||||
ID("id"), OFFICE_ID("officeId"), ACCOUNT_TO_DEBIT("debitAccountHead"), ACCOUNT_TO_CREDIT("creditAccountHead"), NAME("name"), DESCRIPTION(
|
||||
ID("id"), OFFICE_ID("officeId"), ACCOUNT_TO_DEBIT("accountToDebit"), ACCOUNT_TO_CREDIT("accountToCredit"), NAME("name"), DESCRIPTION(
|
||||
"description"), SYSTEM_DEFINED("systemDefined"), DEBIT_ACCOUNT_TAGS("debitTags"), CREDIT_ACCOUNT_TAGS("creditTags"), ALLOW_MULTIPLE_CREDIT_ENTRIES(
|
||||
"allowMultipleCreditEntries"), ALLOW_MULTIPLE_DEBIT_ENTRIES("allowMultipleDebitEntries");
|
||||
|
||||
|
||||
+32
-14
@@ -109,18 +109,15 @@ public class CommandWrapper {
|
||||
}
|
||||
|
||||
public boolean isCreateDatatable() {
|
||||
return (this.actionName.equalsIgnoreCase("CREATE") && this.href.startsWith("/datatables/")
|
||||
&& this.entityId == null);
|
||||
return (this.actionName.equalsIgnoreCase("CREATE") && this.href.startsWith("/datatables/") && this.entityId == null);
|
||||
}
|
||||
|
||||
public boolean isDeleteDatatable() {
|
||||
return (this.actionName.equalsIgnoreCase("DELETE") && this.href.startsWith("/datatables/")
|
||||
&& this.entityId == null);
|
||||
return (this.actionName.equalsIgnoreCase("DELETE") && this.href.startsWith("/datatables/") && this.entityId == null);
|
||||
}
|
||||
|
||||
public boolean isUpdateDatatable() {
|
||||
return (this.actionName.equalsIgnoreCase("UPDATE") && this.href.startsWith("/datatables/")
|
||||
&& this.entityId == null);
|
||||
return (this.actionName.equalsIgnoreCase("UPDATE") && this.href.startsWith("/datatables/") && this.entityId == null);
|
||||
}
|
||||
|
||||
public String getTaskPermissionName() {
|
||||
@@ -415,7 +412,7 @@ public class CommandWrapper {
|
||||
}
|
||||
|
||||
public boolean isUpdateOfOwnUserDetails(final Long loggedInUserId) {
|
||||
return this.isUserResource() && isUpdate() && loggedInUserId.equals(this.entityId);
|
||||
return isUserResource() && isUpdate() && loggedInUserId.equals(this.entityId);
|
||||
}
|
||||
|
||||
public boolean isDepositProductResource() {
|
||||
@@ -499,8 +496,8 @@ public class CommandWrapper {
|
||||
public boolean isGroupResource() {
|
||||
return this.entityName.equalsIgnoreCase("GROUP");
|
||||
}
|
||||
|
||||
public boolean isSaveGroupCollectionSheet(){
|
||||
|
||||
public boolean isSaveGroupCollectionSheet() {
|
||||
return this.entityName.equalsIgnoreCase("GROUP") && this.actionName.equalsIgnoreCase("SAVECOLLECTIONSHEET");
|
||||
}
|
||||
|
||||
@@ -512,10 +509,10 @@ public class CommandWrapper {
|
||||
return this.entityName.equalsIgnoreCase("CENTER");
|
||||
}
|
||||
|
||||
public boolean isSaveCenterCollectionSheet(){
|
||||
public boolean isSaveCenterCollectionSheet() {
|
||||
return this.entityName.equalsIgnoreCase("CENTER") && this.actionName.equalsIgnoreCase("SAVECOLLECTIONSHEET");
|
||||
}
|
||||
|
||||
|
||||
public boolean isReportResource() {
|
||||
return this.entityName.equalsIgnoreCase("REPORT");
|
||||
}
|
||||
@@ -528,7 +525,28 @@ public class CommandWrapper {
|
||||
return this.actionName.equalsIgnoreCase("DISASSOCIATECLIENTS");
|
||||
}
|
||||
|
||||
public boolean isAccountingRuleResource() {
|
||||
return this.entityName.equalsIgnoreCase("ACCOUNTINGRULE");
|
||||
}
|
||||
public boolean isHolidayResource() {
|
||||
return this.entityName.equalsIgnoreCase("HOLIDAY");
|
||||
}
|
||||
|
||||
public boolean isAccountingRuleResource() {
|
||||
return this.entityName.equalsIgnoreCase("ACCOUNTINGRULE");
|
||||
}
|
||||
|
||||
public boolean isClientUnassignStaff() {
|
||||
return this.actionName.equalsIgnoreCase("UNASSIGNSTAFF") && this.entityName.equalsIgnoreCase("CLIENT");
|
||||
}
|
||||
|
||||
public boolean isAssignRole() {
|
||||
return this.entityName.equalsIgnoreCase("GROUP") && this.actionName.equalsIgnoreCase("ASSIGNROLE");
|
||||
}
|
||||
|
||||
public boolean isUnAssignRole() {
|
||||
return this.entityName.equalsIgnoreCase("GROUP") && this.actionName.equalsIgnoreCase("UNASSIGNROLE");
|
||||
}
|
||||
|
||||
public boolean isUpdateRole() {
|
||||
return this.entityName.equalsIgnoreCase("GROUP") && this.actionName.equalsIgnoreCase("UPDATEROLE");
|
||||
}
|
||||
|
||||
}
|
||||
+44
@@ -1018,4 +1018,48 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/accountingrules/" + accountingRuleId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder createHoliday() {
|
||||
this.actionName = "CREATE";
|
||||
this.entityName = "HOLIDAY";
|
||||
this.entityId = null;
|
||||
this.href = "/holidays/template";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder assignRole(Long groupId) {
|
||||
this.actionName = "ASSIGNROLE";
|
||||
this.entityName = "GROUP";
|
||||
this.groupId = groupId;
|
||||
this.entityId = null;
|
||||
this.href = "/groups/"+groupId+"?command=assignRole";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder unassignRole(Long groupId, Long roleId) {
|
||||
this.actionName = "UNASSIGNROLE";
|
||||
this.entityName = "GROUP";
|
||||
this.groupId = groupId;
|
||||
this.entityId = roleId;
|
||||
this.href = "/groups/"+groupId+"?command=unassignRole";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updateRole(Long groupId, Long roleId) {
|
||||
this.actionName = "UPDATEROLE";
|
||||
this.entityName = "GROUP";
|
||||
this.groupId = groupId;
|
||||
this.entityId = roleId;
|
||||
this.href = "/groups/"+groupId+"?command=updateRole";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder unassignClientStaff(Long clientId) {
|
||||
this.actionName = "UNASSIGNSTAFF";
|
||||
this.entityName = "CLIENT";
|
||||
this.entityId = clientId;
|
||||
this.clientId = clientId;
|
||||
this.href = "/clients/" + clientId + "?command=unassignStaff";
|
||||
return this;
|
||||
}
|
||||
}
|
||||
+138
-124
@@ -59,7 +59,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
final NewCommandSourceHandler handler = findCommandHandler(wrapper);
|
||||
final CommandProcessingResult result = handler.processCommand(command);
|
||||
|
||||
final AppUser maker = context.authenticatedUser();
|
||||
final AppUser maker = this.context.authenticatedUser();
|
||||
|
||||
CommandSource commandSourceResult = null;
|
||||
if (command.commandId() != null) {
|
||||
@@ -83,7 +83,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
}
|
||||
|
||||
if (commandSourceResult.hasJson()) {
|
||||
commandSourceRepository.save(commandSourceResult);
|
||||
this.commandSourceRepository.save(commandSourceResult);
|
||||
}
|
||||
|
||||
if (rollbackTransaction) { throw new RollbackTransactionAsCommandIsNotApprovedByCheckerException(commandSourceResult); }
|
||||
@@ -96,7 +96,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
public CommandProcessingResult logCommand(final CommandSource commandSourceResult) {
|
||||
|
||||
commandSourceResult.markAsAwaitingApproval();
|
||||
commandSourceRepository.save(commandSourceResult);
|
||||
this.commandSourceRepository.save(commandSourceResult);
|
||||
|
||||
return new CommandProcessingResultBuilder().withCommandId(commandSourceResult.getId())
|
||||
.withEntityId(commandSourceResult.getResourceId()).build();
|
||||
@@ -106,333 +106,342 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
NewCommandSourceHandler handler = null;
|
||||
|
||||
if (wrapper.isConfigurationResource()) {
|
||||
handler = applicationContext.getBean("updateGlobalConfigurationCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateGlobalConfigurationCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDatatableResource()) {
|
||||
if (wrapper.isCreateDatatable()) {
|
||||
handler = applicationContext.getBean("createDatatableCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDeleteDatatable()) {
|
||||
handler = applicationContext.getBean("deleteDatatableCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdateDatatable()) {
|
||||
handler = applicationContext.getBean("updateDatatableCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createDatatableEntryCommandHandler", NewCommandSourceHandler.class);
|
||||
if (wrapper.isCreateDatatable()) {
|
||||
handler = this.applicationContext.getBean("createDatatableCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDeleteDatatable()) {
|
||||
handler = this.applicationContext.getBean("deleteDatatableCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdateDatatable()) {
|
||||
handler = this.applicationContext.getBean("updateDatatableCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isCreate()) {
|
||||
handler = this.applicationContext.getBean("createDatatableEntryCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdateMultiple()) {
|
||||
handler = applicationContext.getBean("updateOneToManyDatatableEntryCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateOneToManyDatatableEntryCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdateOneToOne()) {
|
||||
handler = applicationContext.getBean("updateOneToOneDatatableEntryCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateOneToOneDatatableEntryCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDeleteMultiple()) {
|
||||
handler = applicationContext.getBean("deleteOneToManyDatatableEntryCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteOneToManyDatatableEntryCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDeleteOneToOne()) {
|
||||
handler = applicationContext.getBean("deleteOneToOneDatatableEntryCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteOneToOneDatatableEntryCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isNoteResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createNoteCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createNoteCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateNoteCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateNoteCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteNoteCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteNoteCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isClientIdentifierResource()) {
|
||||
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createClientIdentifierCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createClientIdentifierCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateClientIdentifierCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateClientIdentifierCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteClientIdentifierCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteClientIdentifierCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isClientResource() && !wrapper.isClientNoteResource() && !wrapper.isClientIdentifierResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createClientCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createClientCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateClientCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateClientCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteClientCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteClientCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isClientActivation()) {
|
||||
handler = applicationContext.getBean("activateClientCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("activateClientCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isClientUnassignStaff()) {
|
||||
handler = applicationContext.getBean("unassignClientStaffCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
// end of client
|
||||
} else if (wrapper.isUpdateRolePermissions()) {
|
||||
handler = applicationContext.getBean("updateRolePermissionsCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateRolePermissionsCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isPermissionResource()) {
|
||||
handler = applicationContext.getBean("updateMakerCheckerPermissionsCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateMakerCheckerPermissionsCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isRoleResource()) {
|
||||
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createRoleCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createRoleCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateRoleCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateRoleCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
|
||||
} else if (wrapper.isUserResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createUserCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createUserCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateUserCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateUserCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteUserCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteUserCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isStaffResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createStaffCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createStaffCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateStaffCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateStaffCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isGuarantorResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createGuarantorCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createGuarantorCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateGuarantorCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateGuarantorCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteGuarantorCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteGuarantorCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isCollateralResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createCollateralCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createCollateralCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateCollateralCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateCollateralCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteCollateralCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteCollateralCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isCodeResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createCodeCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createCodeCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateCodeCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateCodeCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteCodeCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteCodeCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isCodeValueResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createCodeValueCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createCodeValueCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateCodeValueCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateCodeValueCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteCodeValueCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteCodeValueCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isCurrencyResource()) {
|
||||
handler = applicationContext.getBean("updateCurrencyCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateCurrencyCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isFundResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createFundCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createFundCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateFundCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateFundCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isOfficeResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createOfficeCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createOfficeCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateOfficeCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateOfficeCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isOfficeTransactionResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createOfficeTransactionCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createOfficeTransactionCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteOfficeTransactionCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteOfficeTransactionCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isChargeDefinitionResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createChargeDefinitionCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createChargeDefinitionCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateChargeDefinitionCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateChargeDefinitionCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteChargeDefinitionCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteChargeDefinitionCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isLoanProductResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createLoanProductCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createLoanProductCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateLoanProductCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateLoanProductCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isLoanResource()) {
|
||||
if (wrapper.isApproveLoanApplication()) {
|
||||
handler = applicationContext.getBean("loanApplicationApprovalCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("loanApplicationApprovalCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUndoApprovalOfLoanApplication()) {
|
||||
handler = applicationContext.getBean("loanApplicationApprovalUndoCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("loanApplicationApprovalUndoCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isApplicantWithdrawalFromLoanApplication()) {
|
||||
handler = applicationContext.getBean("loanApplicationWithdrawnByApplicantCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("loanApplicationWithdrawnByApplicantCommandHandler",
|
||||
NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isRejectionOfLoanApplication()) {
|
||||
handler = applicationContext.getBean("loanApplicationRejectedCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("loanApplicationRejectedCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDisbursementOfLoan()) {
|
||||
handler = applicationContext.getBean("disburseLoanCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("disburseLoanCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUndoDisbursementOfLoan()) {
|
||||
handler = applicationContext.getBean("undoDisbursalLoanCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("undoDisbursalLoanCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isLoanRepayment()) {
|
||||
handler = applicationContext.getBean("loanRepaymentCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("loanRepaymentCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isLoanRepaymentAdjustment()) {
|
||||
handler = applicationContext.getBean("loanRepaymentAdjustmentCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("loanRepaymentAdjustmentCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isWaiveInterestPortionOnLoan()) {
|
||||
handler = applicationContext.getBean("waiveInterestPortionOnLoanCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("waiveInterestPortionOnLoanCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isLoanWriteOff()) {
|
||||
handler = applicationContext.getBean("writeOffLoanCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("writeOffLoanCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isCloseLoanAsObligationsMet()) {
|
||||
handler = applicationContext.getBean("closeLoanCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("closeLoanCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isCloseLoanAsRescheduled()) {
|
||||
handler = applicationContext.getBean("closeLoanAsRescheduledCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("closeLoanAsRescheduledCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdateLoanOfficer()) {
|
||||
handler = applicationContext.getBean("updateLoanOfficerCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateLoanOfficerCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isRemoveLoanOfficer()) {
|
||||
handler = applicationContext.getBean("removeLoanOfficerCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("removeLoanOfficerCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isBulkUpdateLoanOfficer()) {
|
||||
handler = applicationContext.getBean("bulkUpdateLoanOfficerCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("bulkUpdateLoanOfficerCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("loanApplicationSubmittalCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("loanApplicationSubmittalCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("loanApplicationModificationCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("loanApplicationModificationCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("loanApplicationDeletionCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("loanApplicationDeletionCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isLoanChargeResource()) {
|
||||
if (wrapper.isAddLoanCharge()) {
|
||||
handler = applicationContext.getBean("addLoanChargeCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("addLoanChargeCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDeleteLoanCharge()) {
|
||||
handler = applicationContext.getBean("deleteLoanChargeCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteLoanChargeCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdateLoanCharge()) {
|
||||
handler = applicationContext.getBean("updateLoanChargeCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateLoanChargeCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isWaiveLoanCharge()) {
|
||||
handler = applicationContext.getBean("waiveLoanChargeCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("waiveLoanChargeCommandHandler", NewCommandSourceHandler.class);
|
||||
}
|
||||
} else if (wrapper.isGLAccountResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createGLAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createGLAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateGLAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateGLAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteGLAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteGLAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isGLClosureResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createGLClosureCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createGLClosureCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateGLClosureCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateGLClosureCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteGLClosureCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteGLClosureCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isJournalEntryResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createJournalEntryCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createJournalEntryCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isRevertJournalEntry()) {
|
||||
handler = applicationContext.getBean("reverseJournalEntryCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("reverseJournalEntryCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isSavingsProductResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createSavingsProductCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createSavingsProductCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateSavingsProductCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateSavingsProductCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteSavingsProductCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteSavingsProductCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isSavingsAccountResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isSavingsAccountDeposit()) {
|
||||
handler = applicationContext.getBean("depositSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("depositSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isSavingsAccountWithdrawal()) {
|
||||
handler = applicationContext.getBean("withdrawSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("withdrawSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isSavingsAccountActivation()) {
|
||||
handler = applicationContext.getBean("activateSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("activateSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isSavingsAccountInterestCalculation()) {
|
||||
handler = applicationContext.getBean("calculateInterestSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("calculateInterestSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isSavingsAccountInterestPosting()) {
|
||||
handler = applicationContext.getBean("postInterestSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("postInterestSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isCalendarResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createCalendarCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createCalendarCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateCalendarCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateCalendarCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteCalendarCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteCalendarCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isGroupResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createGroupCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createGroupCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateGroupCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateGroupCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUnassignStaff()) {
|
||||
handler = applicationContext.getBean("unassignGroupStaffCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("unassignGroupStaffCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteGroupCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteGroupCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isGroupActivation()) {
|
||||
handler = applicationContext.getBean("activateGroupCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("activateGroupCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isAssociateClients()) {
|
||||
handler = applicationContext.getBean("associateClientsToGroupCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("associateClientsToGroupCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDisassociateClients()) {
|
||||
handler = applicationContext.getBean("disassociateClientsFromGroupCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("disassociateClientsFromGroupCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isSaveGroupCollectionSheet()) {
|
||||
handler = applicationContext.getBean("saveGroupCollectionSheetCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("saveGroupCollectionSheetCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isAssignRole()) {
|
||||
handler = this.applicationContext.getBean("assignRoleCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUnAssignRole()) {
|
||||
handler = this.applicationContext.getBean("unassignRoleCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdateRole()) {
|
||||
handler = this.applicationContext.getBean("updateGroupRoleCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isCenterResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createCenterCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createCenterCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateCenterCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateCenterCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteCenterCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteCenterCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isCenterActivation()) {
|
||||
handler = applicationContext.getBean("activateCenterCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("activateCenterCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isSaveCenterCollectionSheet()) {
|
||||
handler = applicationContext.getBean("saveCenterCollectionSheetCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("saveCenterCollectionSheetCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isCollectionSheetResource()) {
|
||||
|
||||
if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateCollectionSheetCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateCollectionSheetCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
@@ -440,11 +449,11 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
} else if (wrapper.isReportResource()) {
|
||||
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createReportCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createReportCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateReportCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateReportCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteReportCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteReportCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
@@ -452,16 +461,21 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
} else if (wrapper.isAccountingRuleResource()) {
|
||||
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createAccountingRuleCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("createAccountingRuleCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateAccountingRuleCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateAccountingRuleCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = applicationContext.getBean("deleteAccountingRuleCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("deleteAccountingRuleCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
|
||||
}else {
|
||||
} else if (wrapper.isHolidayResource()) {
|
||||
|
||||
if (wrapper.isCreate()) {
|
||||
handler = applicationContext.getBean("createHolidayCommandHandler", NewCommandSourceHandler.class);
|
||||
}
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -78,4 +78,5 @@ public class CommandProcessingResultBuilder {
|
||||
this.transactionId = withTransactionId;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -79,7 +79,7 @@ public class DataValidatorBuilder {
|
||||
|
||||
public void failWithCode(final String errorCode) {
|
||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(this.parameter)
|
||||
.append(errorCode);
|
||||
.append(".").append(errorCode);
|
||||
StringBuilder defaultEnglishMessage = new StringBuilder("Failed data validation due to: ").append(errorCode).append(".");
|
||||
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(), defaultEnglishMessage.toString(),
|
||||
this.parameter, this.value);
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package org.mifosplatform.infrastructure.core.exception;
|
||||
|
||||
/**
|
||||
* A {@link RuntimeException} thrown when the authenticated user don't have
|
||||
* enough permissions to access.
|
||||
*/
|
||||
public abstract class AbstractPlatformAccessDeniedException extends RuntimeException {
|
||||
|
||||
private final String globalisationMessageCode;
|
||||
private final String defaultUserMessage;
|
||||
private final Object[] defaultUserMessageArgs;
|
||||
|
||||
public AbstractPlatformAccessDeniedException(final String globalisationMessageCode, final String defaultUserMessage,
|
||||
final Object... defaultUserMessageArgs) {
|
||||
this.globalisationMessageCode = globalisationMessageCode;
|
||||
this.defaultUserMessage = defaultUserMessage;
|
||||
this.defaultUserMessageArgs = defaultUserMessageArgs;
|
||||
}
|
||||
|
||||
public String getGlobalisationMessageCode() {
|
||||
return this.globalisationMessageCode;
|
||||
}
|
||||
|
||||
public String getDefaultUserMessage() {
|
||||
return this.defaultUserMessage;
|
||||
}
|
||||
|
||||
public Object[] getDefaultUserMessageArgs() {
|
||||
return this.defaultUserMessageArgs;
|
||||
}
|
||||
|
||||
}
|
||||
+39
-20
@@ -43,7 +43,7 @@ public class DatatableCommandFromApiJsonDeserializer {
|
||||
private final Set<String> supportedParametersForAddColumns = new HashSet<String>(Arrays.asList(
|
||||
"name", "type", "length", "mandatory", "after", "code"));
|
||||
private final Set<String> supportedParametersForChangeColumns = new HashSet<String>(Arrays.asList(
|
||||
"name", "newName", "mandatory", "after", "code", "newCode"));
|
||||
"name", "newName", "length", "mandatory", "after", "code", "newCode"));
|
||||
private final Set<String> supportedParametersForDropColumns = new HashSet<String>(Arrays.asList(
|
||||
"name"));
|
||||
private final Object[] supportedColumnTypes = { "String", "Number", "Decimal", "Date", "Text", "Dropdown" };
|
||||
@@ -61,25 +61,34 @@ public class DatatableCommandFromApiJsonDeserializer {
|
||||
baseDataValidator.reset().parameter("type").value(type).notBlank()
|
||||
.isOneOfTheseValues(supportedColumnTypes);
|
||||
|
||||
final Integer length = fromApiJsonHelper.extractIntegerSansLocaleNamed("length", column);
|
||||
if (type != null && type.equals("String")) {
|
||||
if (length != null) {
|
||||
baseDataValidator.reset().parameter("length").value(length).notBlank()
|
||||
.zeroOrPositiveAmount();
|
||||
if (fromApiJsonHelper.parameterExists("length", column)) {
|
||||
final String lengthStr = fromApiJsonHelper.extractStringNamed("length", column);
|
||||
if (lengthStr != null && !StringUtils.isWhitespace(lengthStr)
|
||||
&& StringUtils.isNumeric(lengthStr) && StringUtils.isNotBlank(lengthStr)) {
|
||||
Integer length = Integer.parseInt(lengthStr);
|
||||
baseDataValidator.reset().parameter("length").value(length).positiveAmount();
|
||||
} else if (StringUtils.isBlank(lengthStr) || StringUtils.isWhitespace(lengthStr)) {
|
||||
baseDataValidator.reset().parameter("length").failWithCode("must.be.provided.when.type.is.String");
|
||||
} else if (!StringUtils.isNumeric(lengthStr)) {
|
||||
baseDataValidator.reset().parameter("length").failWithCode("not.greater.than.zero");
|
||||
}
|
||||
} else {
|
||||
baseDataValidator.reset().parameter("length").value(length)
|
||||
.cantBeBlankWhenParameterProvidedIs("type", type);
|
||||
baseDataValidator.reset().parameter("length").failWithCode("must.be.provided.when.type.is.String");
|
||||
}
|
||||
} else {
|
||||
baseDataValidator.reset().parameter("length").value(length)
|
||||
.mustBeBlankWhenParameterProvidedIs("type", type);
|
||||
baseDataValidator.reset().parameter("length").mustBeBlankWhenParameterProvidedIs("type", type);
|
||||
}
|
||||
|
||||
|
||||
final String code = fromApiJsonHelper.extractStringNamed("code", column);
|
||||
|
||||
if (type != null && type.equals("Dropdown")) {
|
||||
baseDataValidator.reset().parameter("code").value(code).notBlank()
|
||||
.matchesRegularExpression(DATATABLE_NAME_REGEX_PATTERN);
|
||||
if (code != null) {
|
||||
baseDataValidator.reset().parameter("code").value(code).notBlank()
|
||||
.matchesRegularExpression(DATATABLE_NAME_REGEX_PATTERN);
|
||||
} else {
|
||||
baseDataValidator.reset().parameter("code").value(code)
|
||||
.cantBeBlankWhenParameterProvidedIs("type", type);
|
||||
}
|
||||
} else {
|
||||
baseDataValidator.reset().parameter("code").value(code).mustBeBlankWhenParameterProvided("type", type);
|
||||
}
|
||||
@@ -95,15 +104,16 @@ public class DatatableCommandFromApiJsonDeserializer {
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("datatable");
|
||||
|
||||
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||
|
||||
final String datatableName = fromApiJsonHelper.extractStringNamed("datatableName", element);
|
||||
baseDataValidator.reset().parameter("datatableName").value(datatableName).notBlank().notExceedingLengthOf(50)
|
||||
.matchesRegularExpression(DATATABLE_NAME_REGEX_PATTERN);
|
||||
|
||||
final String apptableName = fromApiJsonHelper.extractStringNamed("apptableName", element);
|
||||
baseDataValidator.reset().parameter("apptableName").value(apptableName).notBlank().notExceedingLengthOf(50)
|
||||
.isOneOfTheseValues(supportedApptableNames);
|
||||
final String fkColumnName = (apptableName != null) ? apptableName.substring(2) + "_id" : "";
|
||||
|
||||
final String datatableName = fromApiJsonHelper.extractStringNamed("datatableName", element);
|
||||
baseDataValidator.reset().parameter("datatableName").value(datatableName).notBlank().notExceedingLengthOf(50)
|
||||
.matchesRegularExpression(DATATABLE_NAME_REGEX_PATTERN);
|
||||
|
||||
final Boolean multiRow = fromApiJsonHelper.extractBooleanNamed("multiRow", element);
|
||||
baseDataValidator.reset().parameter("multiRow").value(multiRow).ignoreIfNull().notBlank()
|
||||
.isOneOfTheseValues(true, false);
|
||||
@@ -119,9 +129,6 @@ public class DatatableCommandFromApiJsonDeserializer {
|
||||
baseDataValidator.reset().parameter("name").value(name).notBlank()
|
||||
.isNotOneOfTheseValues("id", fkColumnName).matchesRegularExpression(DATATABLE_COLUMN_NAME_REGEX_PATTERN);
|
||||
|
||||
final String type = fromApiJsonHelper.extractStringNamed("type", column);
|
||||
baseDataValidator.reset().parameter("type").value(type).notBlank().isOneOfTheseValues(supportedColumnTypes);
|
||||
|
||||
validateType(baseDataValidator, column);
|
||||
|
||||
final Boolean mandatory = fromApiJsonHelper.extractBooleanNamed("mandatory", column);
|
||||
@@ -170,6 +177,18 @@ public class DatatableCommandFromApiJsonDeserializer {
|
||||
.notExceedingLengthOf(50).isNotOneOfTheseValues("id", fkColumnName)
|
||||
.matchesRegularExpression(DATATABLE_NAME_REGEX_PATTERN);
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("length", column)) {
|
||||
final String lengthStr = fromApiJsonHelper.extractStringNamed("length", column);
|
||||
if (StringUtils.isWhitespace(lengthStr) || !StringUtils.isNumeric(lengthStr)
|
||||
|| StringUtils.isBlank(lengthStr)) {
|
||||
baseDataValidator.reset().parameter("length").failWithCode("not.greater.than.zero");
|
||||
} else {
|
||||
Integer length = Integer.parseInt(lengthStr);
|
||||
baseDataValidator.reset().parameter("length").value(length).ignoreIfNull().notBlank()
|
||||
.positiveAmount();
|
||||
}
|
||||
}
|
||||
|
||||
final String code = fromApiJsonHelper.extractStringNamed("code", column);
|
||||
baseDataValidator.reset().parameter("code").value(code).ignoreIfNull().notBlank()
|
||||
.notExceedingLengthOf(100).matchesRegularExpression(DATATABLE_COLUMN_NAME_REGEX_PATTERN);
|
||||
|
||||
+66
-18
@@ -24,6 +24,7 @@ import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.mifosplatform.infrastructure.core.serialization.DatatableCommandFromApiJsonDeserializer;
|
||||
@@ -297,6 +298,11 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
||||
return (code + "_cd_" + columnName);
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
|
||||
"Validation errors exist.", dataValidationErrors); }
|
||||
}
|
||||
|
||||
private void parseDatatableColumnObjectForCreate(final JsonObject column, StringBuilder sqlBuilder) {
|
||||
|
||||
String name = (column.has("name")) ? column.get("name").getAsString() : null;
|
||||
@@ -357,7 +363,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
||||
validateAppTable(apptableName);
|
||||
|
||||
String fkColumnName = apptableName.substring(2) + "_id";
|
||||
String fkName = datatableName.toLowerCase().replaceAll("\\s", "_");
|
||||
String fkName = datatableName.toLowerCase().replaceAll("\\s", "_") + "_" + fkColumnName;
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder = sqlBuilder.append("CREATE TABLE `" + datatableName + "` (");
|
||||
|
||||
@@ -380,7 +386,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
||||
if (multiRow) {
|
||||
sqlBuilder = sqlBuilder
|
||||
.append(", PRIMARY KEY (`id`)")
|
||||
.append(", KEY `fk_" + apptableName + "` (`" + fkColumnName + "`)")
|
||||
.append(", KEY `fk_" + apptableName.substring(2) + "_id` (`" + fkColumnName + "`)")
|
||||
.append(", CONSTRAINT `fk_" + fkName + "` ")
|
||||
.append("FOREIGN KEY (`" + fkColumnName + "`) ")
|
||||
.append("REFERENCES `" + apptableName + "` (`id`)");
|
||||
@@ -398,11 +404,17 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
||||
registerDatatable(datatableName, apptableName);
|
||||
} catch (SQLGrammarException e) {
|
||||
Throwable realCause = e.getCause();
|
||||
|
||||
if (realCause.getMessage().contains("Table") && realCause.getMessage().contains("already exists")) {
|
||||
throw new PlatformDataIntegrityException(
|
||||
"error.msg.datatable.already.exists", realCause.getMessage());
|
||||
}
|
||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("datatable");
|
||||
|
||||
if (realCause.getMessage().toLowerCase().contains("duplicate column name")) {
|
||||
baseDataValidator.reset().parameter("name").failWithCode("duplicate.column.name");
|
||||
} else if (realCause.getMessage().contains("Table") && realCause.getMessage().contains("already exists")) {
|
||||
baseDataValidator.reset().parameter("datatableName").value(datatableName)
|
||||
.failWithCode("datatable.already.exists");
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
return new CommandProcessingResultBuilder()
|
||||
@@ -415,6 +427,8 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
||||
final Map<String, ResultsetColumnHeaderData> mapColumnNameDefinition, StringBuilder sqlBuilder) {
|
||||
|
||||
String name = (column.has("name")) ? column.get("name").getAsString() : null;
|
||||
String lengthStr = (column.has("length")) ? column.get("length").getAsString() : null;
|
||||
Integer length = (StringUtils.isNotBlank(lengthStr)) ? Integer.parseInt(lengthStr) : null;
|
||||
String newName = (column.has("newName")) ? column.get("newName").getAsString() : name;
|
||||
Boolean mandatory = (column.has("mandatory")) ? column.get("mandatory").getAsBoolean() : false;
|
||||
String after = (column.has("after")) ? column.get("after").getAsString() : null;
|
||||
@@ -437,13 +451,15 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
||||
}
|
||||
|
||||
String type = mapColumnNameDefinition.get(name).getColumnType();
|
||||
Long length = mapColumnNameDefinition.get(name).getColumnLength();
|
||||
if (length == null && type.toLowerCase().equals("varchar")) {
|
||||
length = mapColumnNameDefinition.get(name).getColumnLength().intValue();
|
||||
}
|
||||
|
||||
sqlBuilder = sqlBuilder.append(", CHANGE `" + name + "` `" + newName + "` " + type);
|
||||
if (length != null && length > 0) {
|
||||
if (type.equals("DECIMAL")) {
|
||||
if (type.toLowerCase().equals("decimal")) {
|
||||
sqlBuilder.append("(19,6)");
|
||||
} else if (type.equals("VARCHAR")) {
|
||||
} else if (type.toLowerCase().equals("varchar")) {
|
||||
sqlBuilder.append("(" + length + ")");
|
||||
}
|
||||
}
|
||||
@@ -531,6 +547,34 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
||||
|
||||
String oldApptableName = this.queryForApplicationTableName(datatableName);
|
||||
if (!StringUtils.equals(oldApptableName, apptableName)) {
|
||||
String oldFKName = oldApptableName.substring(2) + "_id";
|
||||
String newFKName = apptableName.substring(2) + "_id";
|
||||
String oldConstraintName = datatableName.toLowerCase().replaceAll("\\s", "_") + "_" + oldFKName;
|
||||
String newConstraintName = datatableName.toLowerCase().replaceAll("\\s", "_") + "_" + newFKName;
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
|
||||
if (mapColumnNameDefinition.containsKey("id")) {
|
||||
sqlBuilder = sqlBuilder
|
||||
.append("ALTER TABLE `" + datatableName + "` ")
|
||||
.append("DROP KEY `fk_" + oldFKName + "`,")
|
||||
.append("DROP FOREIGN KEY `fk_" + oldConstraintName + "`,")
|
||||
.append("CHANGE COLUMN `" + oldFKName + "` `" + newFKName + "` BIGINT(20) NOT NULL,")
|
||||
.append("ADD KEY `fk_" + newFKName + "` (`" + newFKName + "`),")
|
||||
.append("ADD CONSTRAINT `fk_" + newConstraintName + "` ")
|
||||
.append("FOREIGN KEY (`" + newFKName + "`) ")
|
||||
.append("REFERENCES `" + apptableName + "` (`id`)");
|
||||
} else {
|
||||
sqlBuilder = sqlBuilder
|
||||
.append("ALTER TABLE `" + datatableName + "` ")
|
||||
.append("DROP FOREIGN KEY `fk_" + oldConstraintName + "`,")
|
||||
.append("CHANGE COLUMN `" + oldFKName + "` `" + newFKName + "` BIGINT(20) NOT NULL,")
|
||||
.append("ADD CONSTRAINT `fk_" + newConstraintName + "` ")
|
||||
.append("FOREIGN KEY (`" + newFKName + "`) ")
|
||||
.append("REFERENCES `" + apptableName + "` (`id`)");
|
||||
}
|
||||
|
||||
this.jdbcTemplate.execute(sqlBuilder.toString());
|
||||
|
||||
deregisterDatatable(datatableName);
|
||||
registerDatatable(datatableName, apptableName);
|
||||
}
|
||||
@@ -590,17 +634,18 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
||||
}
|
||||
} catch (SQLGrammarException e) {
|
||||
Throwable realCause = e.getCause();
|
||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("datatable");
|
||||
|
||||
if (realCause.getMessage().toLowerCase().contains("unknown column")) {
|
||||
throw new PlatformDataIntegrityException(
|
||||
"error.msg.datatable.column.missing.update", realCause.getMessage());
|
||||
baseDataValidator.reset().parameter("name").failWithCode("does.not.exist");
|
||||
} else if (realCause.getMessage().toLowerCase().contains("can't drop")) {
|
||||
throw new PlatformDataIntegrityException(
|
||||
"error.msg.datatable.column.missing.drop", realCause.getMessage());
|
||||
baseDataValidator.reset().parameter("name").failWithCode("does.not.exist");
|
||||
} else if (realCause.getMessage().toLowerCase().contains("duplicate column")) {
|
||||
throw new PlatformDataIntegrityException(
|
||||
"error.msg.datatable.duplicate.column", realCause.getMessage());
|
||||
baseDataValidator.reset().parameter("name").failWithCode("column.already.exists");
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,11 +663,14 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
|
||||
this.jdbcTemplate.execute(sql);
|
||||
} catch (SQLGrammarException e) {
|
||||
Throwable realCause = e.getCause();
|
||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("datatable");
|
||||
|
||||
if (realCause.getMessage().contains("Unknown table")) {
|
||||
throw new PlatformDataIntegrityException(
|
||||
"error.msg.datatable.missing", realCause.getMessage());
|
||||
baseDataValidator.reset().parameter("datatableName").failWithCode("does.not.exist");
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package org.mifosplatform.infrastructure.security.exception;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformAccessDeniedException;
|
||||
|
||||
public class PermissionDeniedException extends AbstractPlatformAccessDeniedException {
|
||||
|
||||
public PermissionDeniedException(final String code, final String defaultMessage, final Long userId) {
|
||||
super(code, defaultMessage, userId);
|
||||
}
|
||||
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package org.mifosplatform.organisation.holiday.api;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class HolidayApiConstants {
|
||||
|
||||
public static final String HOLIDAY_RESOURCE_NAME = "holiday";
|
||||
|
||||
// general
|
||||
public static final String localeParamName = "locale";
|
||||
public static final String dateFormatParamName = "dateFormat";
|
||||
|
||||
//request parameters
|
||||
public static final String name = "name";
|
||||
public static final String fromDate = "fromDate";
|
||||
public static final String toDate = "toDate";
|
||||
public static final String description = "description";
|
||||
public static final String offices = "offices";
|
||||
public static final String officeId = "officeId";
|
||||
|
||||
public static final Set<String> HOLIDAY_CREATE_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
|
||||
dateFormatParamName, name, fromDate, toDate, description, offices));
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package org.mifosplatform.organisation.holiday.api;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.mifosplatform.commands.domain.CommandWrapper;
|
||||
import org.mifosplatform.commands.service.CommandWrapperBuilder;
|
||||
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/holidays")
|
||||
@Component
|
||||
@Scope("singleton")
|
||||
public class HolidaysApiResource {
|
||||
|
||||
private final DefaultToApiJsonSerializer<Object> toApiJsonSerializer;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
public HolidaysApiResource(final DefaultToApiJsonSerializer<Object> toApiJsonSerializer, final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
|
||||
this.toApiJsonSerializer = toApiJsonSerializer;
|
||||
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String createNewHoliday(final String apiRequestBodyAsJson) {
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createHoliday().withJson(apiRequestBodyAsJson).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
package org.mifosplatform.organisation.holiday.data;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.mifosplatform.organisation.holiday.api.HolidayApiConstants;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
@Component
|
||||
public class HolidayDataValidator {
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@Autowired
|
||||
public HolidayDataValidator(final FromJsonHelper fromApiJsonHelper) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
}
|
||||
|
||||
public void validateForCreate(final String json) {
|
||||
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, HolidayApiConstants.HOLIDAY_CREATE_REQUEST_DATA_PARAMETERS);
|
||||
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(HolidayApiConstants.HOLIDAY_RESOURCE_NAME);
|
||||
|
||||
final String name = this.fromApiJsonHelper.extractStringNamed(HolidayApiConstants.name, element);
|
||||
baseDataValidator.reset().parameter(HolidayApiConstants.name).value(name).notNull().notExceedingLengthOf(100);
|
||||
|
||||
final LocalDate fromDate = this.fromApiJsonHelper.extractLocalDateNamed(HolidayApiConstants.fromDate, element);
|
||||
baseDataValidator.reset().parameter(HolidayApiConstants.fromDate).value(fromDate).notNull();
|
||||
|
||||
final LocalDate toDate = this.fromApiJsonHelper.extractLocalDateNamed(HolidayApiConstants.toDate, element);
|
||||
baseDataValidator.reset().parameter(HolidayApiConstants.toDate).value(toDate).notNull();
|
||||
|
||||
Set<Long> offices = null;
|
||||
final JsonObject topLevelJsonElement = element.getAsJsonObject();
|
||||
|
||||
if (topLevelJsonElement.has(HolidayApiConstants.offices) && topLevelJsonElement.get(HolidayApiConstants.offices).isJsonArray()) {
|
||||
|
||||
final JsonArray array = topLevelJsonElement.get(HolidayApiConstants.offices).getAsJsonArray();
|
||||
if (array.size() > 0) {
|
||||
offices = new HashSet<Long>(array.size());
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
final JsonObject officeElement = array.get(i).getAsJsonObject();
|
||||
final Long officeId = this.fromApiJsonHelper.extractLongNamed(HolidayApiConstants.officeId, officeElement);
|
||||
baseDataValidator.reset().parameter(HolidayApiConstants.offices).value(officeId).notNull();
|
||||
offices.add(officeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
baseDataValidator.reset().parameter(HolidayApiConstants.offices).value(offices).notNull();
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
//
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.mifosplatform.organisation.holiday.domain;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.organisation.holiday.api.HolidayApiConstants;
|
||||
import org.mifosplatform.organisation.office.domain.Office;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_holiday", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "holiday_name") })
|
||||
public class Holiday extends AbstractPersistable<Long> {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "name", unique = true, nullable = false, length = 100)
|
||||
private String name;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "from_date", nullable = false)
|
||||
@Temporal(TemporalType.DATE)
|
||||
private Date fromDate;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "to_date", nullable = false)
|
||||
@Temporal(TemporalType.DATE)
|
||||
private Date toDate;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "description", length = 100)
|
||||
private String description;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
@JoinTable(name = "m_holiday_office", joinColumns = @JoinColumn(name = "holiday_id"), inverseJoinColumns = @JoinColumn(name = "office_id"))
|
||||
private Set<Office> offices;
|
||||
|
||||
public static Holiday createNew(final Set<Office> offices, final JsonCommand command) {
|
||||
final String name = command.stringValueOfParameterNamed(HolidayApiConstants.name);
|
||||
final LocalDate fromDate = command.localDateValueOfParameterNamed(HolidayApiConstants.fromDate);
|
||||
final LocalDate toDate = command.localDateValueOfParameterNamed(HolidayApiConstants.toDate);
|
||||
final String description = command.stringValueOfParameterNamed(HolidayApiConstants.description);
|
||||
return new Holiday(name, fromDate, toDate, description, offices);
|
||||
}
|
||||
|
||||
private Holiday(final String name, final LocalDate fromDate, final LocalDate toDate, final String description, final Set<Office> offices) {
|
||||
if (StringUtils.isNotBlank(name)) {
|
||||
this.name = name.trim();
|
||||
}
|
||||
|
||||
if (fromDate != null) {
|
||||
this.fromDate = fromDate.toDate();
|
||||
}
|
||||
|
||||
if (toDate != null) {
|
||||
this.toDate = toDate.toDate();
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(name)) {
|
||||
this.description = description.trim();
|
||||
} else {
|
||||
this.description = null;
|
||||
}
|
||||
|
||||
if (offices != null) {
|
||||
this.offices = offices;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.mifosplatform.organisation.holiday.domain;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface HolidayRepository extends JpaRepository<Holiday, Long>,
|
||||
JpaSpecificationExecutor<Holiday> {
|
||||
// no added behaviour
|
||||
}
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package org.mifosplatform.organisation.holiday.handler;
|
||||
|
||||
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.organisation.holiday.service.HolidayWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class CreateHolidayCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final HolidayWritePlatformService holidayWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
public CreateHolidayCommandHandler(final HolidayWritePlatformService holidayWritePlatformService) {
|
||||
this.holidayWritePlatformService = holidayWritePlatformService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
|
||||
return this.holidayWritePlatformService.createHoliday(command);
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package org.mifosplatform.organisation.holiday.service;
|
||||
|
||||
public class HolidayReadPlatformServiceImpl {
|
||||
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package org.mifosplatform.organisation.holiday.service;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
|
||||
public interface HolidayWritePlatformService {
|
||||
|
||||
CommandProcessingResult createHoliday(JsonCommand command);
|
||||
}
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
package org.mifosplatform.organisation.holiday.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.mifosplatform.organisation.holiday.api.HolidayApiConstants;
|
||||
import org.mifosplatform.organisation.holiday.data.HolidayDataValidator;
|
||||
import org.mifosplatform.organisation.holiday.domain.Holiday;
|
||||
import org.mifosplatform.organisation.holiday.domain.HolidayRepository;
|
||||
import org.mifosplatform.organisation.office.domain.Office;
|
||||
import org.mifosplatform.organisation.office.domain.OfficeRepository;
|
||||
import org.mifosplatform.organisation.office.exception.OfficeNotFoundException;
|
||||
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 com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
@Service
|
||||
public class HolidayWritePlatformServiceJpaRepositoryImpl implements HolidayWritePlatformService {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(HolidayWritePlatformServiceJpaRepositoryImpl.class);
|
||||
|
||||
private final HolidayDataValidator fromApiJsonDeserializer;
|
||||
private final HolidayRepository holidayRepository;
|
||||
private final PlatformSecurityContext context;
|
||||
private final OfficeRepository officeRepository;
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@Autowired
|
||||
public HolidayWritePlatformServiceJpaRepositoryImpl(final HolidayDataValidator fromApiJsonDeserializer,
|
||||
final HolidayRepository holidayRepository, final PlatformSecurityContext context, final OfficeRepository officeRepository,
|
||||
final FromJsonHelper fromApiJsonHelper) {
|
||||
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
||||
this.holidayRepository = holidayRepository;
|
||||
this.context = context;
|
||||
this.officeRepository = officeRepository;
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult createHoliday(final JsonCommand command) {
|
||||
|
||||
try {
|
||||
this.context.authenticatedUser();
|
||||
this.fromApiJsonDeserializer.validateForCreate(command.json());
|
||||
|
||||
validateToDateBeforeFromDate(command);
|
||||
|
||||
Set<Office> offices = null;
|
||||
final JsonObject topLevelJsonElement = this.fromApiJsonHelper.parse(command.json()).getAsJsonObject();
|
||||
if (topLevelJsonElement.has(HolidayApiConstants.offices) && topLevelJsonElement.get(HolidayApiConstants.offices).isJsonArray()) {
|
||||
|
||||
final JsonArray array = topLevelJsonElement.get(HolidayApiConstants.offices).getAsJsonArray();
|
||||
offices = new HashSet<Office>(array.size());
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
final JsonObject officeElement = array.get(i).getAsJsonObject();
|
||||
final Long officeId = this.fromApiJsonHelper.extractLongNamed(HolidayApiConstants.officeId, officeElement);
|
||||
final Office office = this.officeRepository.findOne(officeId);
|
||||
if (office == null) { throw new OfficeNotFoundException(officeId); }
|
||||
offices.add(office);
|
||||
}
|
||||
}
|
||||
|
||||
final Holiday holiday = Holiday.createNew(offices, command);
|
||||
|
||||
this.holidayRepository.save(holiday);
|
||||
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(holiday.getId()).build();
|
||||
} catch (final DataIntegrityViolationException dve) {
|
||||
handleDataIntegrityIssues(command, dve);
|
||||
return CommandProcessingResult.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) {
|
||||
final Throwable realCause = dve.getMostSpecificCause();
|
||||
if (realCause.getMessage().contains("holiday_name")) {
|
||||
final String name = command.stringValueOfParameterNamed("name");
|
||||
throw new PlatformDataIntegrityException("error.msg.holiday.duplicate.name", "Holiday with name `" + name + "` already exists",
|
||||
"name", name);
|
||||
}
|
||||
|
||||
logger.error(dve.getMessage(), dve);
|
||||
throw new PlatformDataIntegrityException("error.msg.office.unknown.data.integrity.issue",
|
||||
"Unknown data integrity issue with resource.");
|
||||
}
|
||||
|
||||
private void validateToDateBeforeFromDate(final JsonCommand command) {
|
||||
final LocalDate fromDate = command.localDateValueOfParameterNamed(HolidayApiConstants.fromDate);
|
||||
final LocalDate toDate = command.localDateValueOfParameterNamed(HolidayApiConstants.toDate);
|
||||
if (toDate.isBefore(fromDate)) {
|
||||
|
||||
final String defaultUserMessage = "ToDate date cannot be before the FromDate.";
|
||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.holiday.toDate.cannot be.before.the.FromDate",
|
||||
defaultUserMessage, "ToDate");
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
dataValidationErrors.add(error);
|
||||
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -53,7 +53,7 @@ public class OfficesApiResource {
|
||||
private final OfficeReadPlatformService readPlatformService;
|
||||
private final DefaultToApiJsonSerializer<OfficeData> toApiJsonSerializer;
|
||||
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
public OfficesApiResource(final PlatformSecurityContext context, final OfficeReadPlatformService readPlatformService,
|
||||
|
||||
+1
-21
@@ -22,7 +22,6 @@ import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.mifosplatform.commands.domain.CommandWrapper;
|
||||
import org.mifosplatform.commands.service.CommandWrapperBuilder;
|
||||
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||
@@ -81,8 +80,7 @@ public class StaffApiResource {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions);
|
||||
|
||||
final String extraCriteria = getStaffCriteria(sqlSearch, officeId);
|
||||
final Collection<StaffData> staff = this.readPlatformService.retrieveAllStaff(extraCriteria);
|
||||
final Collection<StaffData> staff = this.readPlatformService.retrieveAllStaff(sqlSearch, officeId);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, staff, RESPONSE_DATA_PARAMETERS);
|
||||
@@ -131,22 +129,4 @@ public class StaffApiResource {
|
||||
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
private String getStaffCriteria(final String sqlSearch, final Long officeId) {
|
||||
|
||||
String extraCriteria = "";
|
||||
|
||||
if (sqlSearch != null) {
|
||||
extraCriteria = " and (" + sqlSearch + ")";
|
||||
}
|
||||
if (officeId != null) {
|
||||
extraCriteria += " and office_id = " + officeId;
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(extraCriteria)) {
|
||||
extraCriteria = extraCriteria.substring(4);
|
||||
}
|
||||
|
||||
return extraCriteria;
|
||||
}
|
||||
}
|
||||
+9
-3
@@ -13,9 +13,15 @@ public interface StaffReadPlatformService {
|
||||
|
||||
StaffData retrieveStaff(Long staffId);
|
||||
|
||||
Collection<StaffData> retrieveAllStaff(final String extraCriteria);
|
||||
|
||||
Collection<StaffData> retrieveAllStaffForDropdown(Long officeId);
|
||||
|
||||
Collection<StaffData> retrieveAllLoanOfficersByOffice(final Long officeId);
|
||||
Collection<StaffData> retrieveAllLoanOfficersInOfficeById(final Long officeId);
|
||||
|
||||
/**
|
||||
* returns all staff in offices that are above the provided
|
||||
* <code>officeId</code>.
|
||||
*/
|
||||
Collection<StaffData> retrieveAllStaffInOfficeAndItsParentOfficeHierarchy(Long officeId, boolean loanOfficersOnly);
|
||||
|
||||
Collection<StaffData> retrieveAllStaff(String sqlSearch, Long officeId);
|
||||
}
|
||||
+82
-13
@@ -26,6 +26,7 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService {
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final PlatformSecurityContext context;
|
||||
private final StaffLookupMapper lookupMapper = new StaffLookupMapper();
|
||||
private final StaffInOfficeHierarchyMapper staffInOfficeHierarchyMapper = new StaffInOfficeHierarchyMapper();
|
||||
|
||||
@Autowired
|
||||
public StaffReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource) {
|
||||
@@ -56,6 +57,42 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class StaffInOfficeHierarchyMapper implements RowMapper<StaffData> {
|
||||
|
||||
public String schema(final boolean loanOfficersOnly) {
|
||||
|
||||
StringBuilder sqlBuilder = new StringBuilder(200);
|
||||
sqlBuilder.append("s.id as id, s.office_id as officeId, o.name as officeName,");
|
||||
sqlBuilder.append("s.firstname as firstname, s.lastname as lastname,");
|
||||
sqlBuilder.append("s.display_name as displayName, s.is_loan_officer as isLoanOfficer ");
|
||||
sqlBuilder.append("from m_office o ");
|
||||
sqlBuilder.append("join m_office ohierarchy on o.hierarchy like concat(ohierarchy.hierarchy, '%') ");
|
||||
sqlBuilder.append("join m_staff s on s.office_id = ohierarchy.id ");
|
||||
|
||||
if (loanOfficersOnly) {
|
||||
sqlBuilder.append("and s.is_loan_officer is true ");
|
||||
}
|
||||
|
||||
sqlBuilder.append("where o.id = ? ");
|
||||
|
||||
return sqlBuilder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public StaffData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final String firstname = rs.getString("firstname");
|
||||
final String lastname = rs.getString("lastname");
|
||||
final String displayName = rs.getString("displayName");
|
||||
final Long officeId = rs.getLong("officeId");
|
||||
final String officeName = rs.getString("officeName");
|
||||
final boolean isLoanOfficer = rs.getBoolean("isLoanOfficer");
|
||||
|
||||
return StaffData.instance(id, firstname, lastname, displayName, officeId, officeName, isLoanOfficer);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class StaffLookupMapper implements RowMapper<StaffData> {
|
||||
|
||||
private final String schemaSql;
|
||||
@@ -84,19 +121,7 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<StaffData> retrieveAllStaff(final String extraCriteria) {
|
||||
|
||||
final StaffMapper rm = new StaffMapper();
|
||||
String sql = "select " + rm.schema();
|
||||
if (StringUtils.isNotBlank(extraCriteria)) {
|
||||
sql += " where " + extraCriteria;
|
||||
}
|
||||
sql = sql + " order by s.lastname";
|
||||
return this.jdbcTemplate.query(sql, rm, new Object[] {});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<StaffData> retrieveAllLoanOfficersByOffice(final Long officeId) {
|
||||
public Collection<StaffData> retrieveAllLoanOfficersInOfficeById(final Long officeId) {
|
||||
return retrieveAllStaff(" office_id=" + officeId + " and is_loan_officer=1");
|
||||
}
|
||||
|
||||
@@ -132,4 +157,48 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService {
|
||||
throw new StaffNotFoundException(staffId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<StaffData> retrieveAllStaff(final String sqlSearch, final Long officeId) {
|
||||
final String extraCriteria = getStaffCriteria(sqlSearch, officeId);
|
||||
return retrieveAllStaff(extraCriteria);
|
||||
}
|
||||
|
||||
private Collection<StaffData> retrieveAllStaff(final String extraCriteria) {
|
||||
|
||||
final StaffMapper rm = new StaffMapper();
|
||||
String sql = "select " + rm.schema();
|
||||
if (StringUtils.isNotBlank(extraCriteria)) {
|
||||
sql += " where " + extraCriteria;
|
||||
}
|
||||
sql = sql + " order by s.lastname";
|
||||
return this.jdbcTemplate.query(sql, rm, new Object[] {});
|
||||
}
|
||||
|
||||
private String getStaffCriteria(final String sqlSearch, final Long officeId) {
|
||||
|
||||
String extraCriteria = "";
|
||||
|
||||
if (sqlSearch != null) {
|
||||
extraCriteria = " and (" + sqlSearch + ")";
|
||||
}
|
||||
if (officeId != null) {
|
||||
extraCriteria += " and office_id = " + officeId;
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(extraCriteria)) {
|
||||
extraCriteria = extraCriteria.substring(4);
|
||||
}
|
||||
|
||||
return extraCriteria;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<StaffData> retrieveAllStaffInOfficeAndItsParentOfficeHierarchy(final Long officeId, final boolean loanOfficersOnly) {
|
||||
|
||||
String sql = "select " + this.staffInOfficeHierarchyMapper.schema(loanOfficersOnly);
|
||||
sql = sql + " order by s.lastname";
|
||||
|
||||
return this.jdbcTemplate.query(sql, this.staffInOfficeHierarchyMapper, new Object[] { officeId });
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -168,7 +168,7 @@ public class Charge extends AbstractPersistable<Long> {
|
||||
this.amount = newValue;
|
||||
}
|
||||
|
||||
final String chargeTimeParamName = "chargeTime";
|
||||
final String chargeTimeParamName = "chargeTimeType";
|
||||
if (command.isChangeInIntegerParameterNamed(chargeTimeParamName, this.chargeTime)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(chargeTimeParamName);
|
||||
actualChanges.put(chargeTimeParamName, newValue);
|
||||
@@ -184,7 +184,7 @@ public class Charge extends AbstractPersistable<Long> {
|
||||
this.chargeAppliesTo = ChargeAppliesTo.fromInt(newValue).getValue();
|
||||
}
|
||||
|
||||
final String chargeCalculationParamName = "chargeCalculation";
|
||||
final String chargeCalculationParamName = "chargeCalculationType";
|
||||
if (command.isChangeInIntegerParameterNamed(chargeCalculationParamName, this.chargeCalculation)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(chargeCalculationParamName);
|
||||
actualChanges.put(chargeCalculationParamName, newValue);
|
||||
|
||||
+5
-3
@@ -31,6 +31,7 @@ public class ClientApiConstants {
|
||||
public static final String officeIdParamName = "officeId";
|
||||
public static final String activeParamName = "active";
|
||||
public static final String activationDateParamName = "activationDate";
|
||||
public static final String staffIdParamName = "staffId";
|
||||
|
||||
// response parameters
|
||||
public static final String statusParamName = "status";
|
||||
@@ -45,14 +46,15 @@ public class ClientApiConstants {
|
||||
|
||||
// template related part of response
|
||||
public static final String officeOptionsParamName = "officeOptions";
|
||||
public static final String staffOptionsParamName = "staffOptions";
|
||||
|
||||
public static final Set<String> CLIENT_CREATE_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
|
||||
dateFormatParamName, groupIdParamName, accountNoParamName, externalIdParamName, firstnameParamName, middlenameParamName,
|
||||
lastnameParamName, fullnameParamName, officeIdParamName, activeParamName, activationDateParamName));
|
||||
lastnameParamName, fullnameParamName, officeIdParamName, activeParamName, activationDateParamName, staffIdParamName));
|
||||
|
||||
public static final Set<String> CLIENT_UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
|
||||
dateFormatParamName, accountNoParamName, externalIdParamName, firstnameParamName, middlenameParamName,
|
||||
lastnameParamName, fullnameParamName, activeParamName, activationDateParamName));
|
||||
lastnameParamName, fullnameParamName, activeParamName, activationDateParamName, staffIdParamName));
|
||||
|
||||
/**
|
||||
* These parameters will match the class level parameters of
|
||||
@@ -62,7 +64,7 @@ public class ClientApiConstants {
|
||||
public static final Set<String> CLIENT_RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(idParamName, accountNoParamName,
|
||||
externalIdParamName, statusParamName, activeParamName, activationDateParamName, firstnameParamName, middlenameParamName,
|
||||
lastnameParamName, fullnameParamName, displayNameParamName, officeIdParamName, officeNameParamName, hierarchyParamName,
|
||||
imageKeyParamName, imagePresentParamName, groupsParamName, officeOptionsParamName));
|
||||
imageKeyParamName, imagePresentParamName, groupsParamName, officeOptionsParamName, staffOptionsParamName));
|
||||
|
||||
public static final Set<String> ACTIVATION_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
|
||||
dateFormatParamName, activationDateParamName));
|
||||
|
||||
+20
-6
@@ -7,6 +7,7 @@ package org.mifosplatform.portfolio.client.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -37,6 +38,8 @@ import org.mifosplatform.infrastructure.core.service.Page;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.mifosplatform.organisation.office.data.OfficeData;
|
||||
import org.mifosplatform.organisation.office.service.OfficeReadPlatformService;
|
||||
import org.mifosplatform.organisation.staff.data.StaffData;
|
||||
import org.mifosplatform.organisation.staff.service.StaffReadPlatformService;
|
||||
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryCollectionData;
|
||||
import org.mifosplatform.portfolio.client.data.ClientData;
|
||||
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
|
||||
@@ -44,6 +47,7 @@ import org.mifosplatform.portfolio.group.service.SearchParameters;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@Path("/clients")
|
||||
@Component
|
||||
@@ -57,13 +61,15 @@ public class ClientsApiResource {
|
||||
private final ToApiJsonSerializer<ClientAccountSummaryCollectionData> clientAccountSummaryToApiJsonSerializer;
|
||||
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
private final StaffReadPlatformService staffReadPlatformService;
|
||||
|
||||
@Autowired
|
||||
public ClientsApiResource(final PlatformSecurityContext context, final ClientReadPlatformService readPlatformService,
|
||||
final OfficeReadPlatformService officeReadPlatformService, final ToApiJsonSerializer<ClientData> toApiJsonSerializer,
|
||||
final ToApiJsonSerializer<ClientAccountSummaryCollectionData> clientAccountSummaryToApiJsonSerializer,
|
||||
final ApiRequestParameterHelper apiRequestParameterHelper,
|
||||
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
|
||||
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
|
||||
final StaffReadPlatformService staffReadPlatformService) {
|
||||
this.context = context;
|
||||
this.clientReadPlatformService = readPlatformService;
|
||||
this.officeReadPlatformService = officeReadPlatformService;
|
||||
@@ -71,17 +77,18 @@ public class ClientsApiResource {
|
||||
this.clientAccountSummaryToApiJsonSerializer = clientAccountSummaryToApiJsonSerializer;
|
||||
this.apiRequestParameterHelper = apiRequestParameterHelper;
|
||||
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
|
||||
this.staffReadPlatformService = staffReadPlatformService;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("template")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retrieveTemplate(@Context final UriInfo uriInfo) {
|
||||
public String retrieveTemplate(@Context final UriInfo uriInfo, @QueryParam("officeId") final Long officeId) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(ClientApiConstants.CLIENT_RESOURCE_NAME);
|
||||
|
||||
final ClientData clientData = this.clientReadPlatformService.retrieveTemplate();
|
||||
final ClientData clientData = this.clientReadPlatformService.retrieveTemplate(officeId);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, clientData, ClientApiConstants.CLIENT_RESPONSE_DATA_PARAMETERS);
|
||||
@@ -121,7 +128,11 @@ public class ClientsApiResource {
|
||||
ClientData clientData = this.clientReadPlatformService.retrieveOne(clientId);
|
||||
if (settings.isTemplate()) {
|
||||
final List<OfficeData> allowedOffices = new ArrayList<OfficeData>(officeReadPlatformService.retrieveAllOfficesForDropdown());
|
||||
clientData = ClientData.templateOnTop(clientData, allowedOffices);
|
||||
Collection<StaffData> staffOptions = this.staffReadPlatformService.retrieveAllStaffForDropdown(clientData.officeId());
|
||||
if (CollectionUtils.isEmpty(staffOptions)) {
|
||||
staffOptions = null;
|
||||
}
|
||||
clientData = ClientData.templateOnTop(clientData, allowedOffices, staffOptions);
|
||||
}
|
||||
|
||||
return this.toApiJsonSerializer.serialize(settings, clientData, ClientApiConstants.CLIENT_RESPONSE_DATA_PARAMETERS);
|
||||
@@ -186,11 +197,14 @@ public class ClientsApiResource {
|
||||
if (is(commandParam, "activate")) {
|
||||
final CommandWrapper commandRequest = builder.activateClient(clientId).build();
|
||||
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
} else if (is(commandParam, "unassignStaff")) {
|
||||
final CommandWrapper commandRequest = builder.unassignClientStaff(clientId).build();
|
||||
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
//
|
||||
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "activate" });
|
||||
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "activate", "unassignStaff" });
|
||||
}
|
||||
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
|
||||
+22
-11
@@ -15,6 +15,7 @@ import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.organisation.office.data.OfficeData;
|
||||
import org.mifosplatform.organisation.staff.data.StaffData;
|
||||
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
|
||||
|
||||
/**
|
||||
@@ -43,28 +44,34 @@ final public class ClientData implements Comparable<ClientData> {
|
||||
|
||||
private final Long imageId;
|
||||
private final Boolean imagePresent;
|
||||
private final Long staffId;
|
||||
private final String staffName;
|
||||
|
||||
// associations
|
||||
private final Collection<GroupGeneralData> groups;
|
||||
|
||||
// template
|
||||
private final Collection<OfficeData> officeOptions;
|
||||
private final Collection<StaffData> staffOptions;
|
||||
|
||||
public static ClientData template(final Long officeId, final LocalDate joinedDate, final Collection<OfficeData> officeOptions) {
|
||||
return new ClientData(null, null, officeId, null, null, null, null, null, null, null, null, joinedDate, null, officeOptions, null);
|
||||
public static ClientData template(final Long officeId, final LocalDate joinedDate, final Collection<OfficeData> officeOptions,
|
||||
final Collection<StaffData> staffOptions) {
|
||||
return new ClientData(null, null, officeId, null, null, null, null, null, null, null, null, joinedDate, null, null, null, officeOptions, null, staffOptions);
|
||||
}
|
||||
|
||||
public static ClientData templateOnTop(final ClientData clientData, final List<OfficeData> allowedOffices) {
|
||||
public static ClientData templateOnTop(final ClientData clientData, final List<OfficeData> allowedOffices, final Collection<StaffData> staffOptions) {
|
||||
|
||||
return new ClientData(clientData.accountNo, clientData.status, clientData.officeId, clientData.officeName, clientData.id,
|
||||
clientData.firstname, clientData.middlename, clientData.lastname, clientData.fullname, clientData.displayName,
|
||||
clientData.externalId, clientData.activationDate, clientData.imageId, allowedOffices, clientData.groups);
|
||||
clientData.externalId, clientData.activationDate, clientData.imageId, clientData.staffId, clientData.staffName,
|
||||
allowedOffices, clientData.groups, staffOptions);
|
||||
}
|
||||
|
||||
public static ClientData setParentGroups(final ClientData clientData, final Collection<GroupGeneralData> parentGroups) {
|
||||
return new ClientData(clientData.accountNo, clientData.status, clientData.officeId, clientData.officeName, clientData.id,
|
||||
clientData.firstname, clientData.middlename, clientData.lastname, clientData.fullname, clientData.displayName,
|
||||
clientData.externalId, clientData.activationDate, clientData.imageId, clientData.officeOptions, parentGroups);
|
||||
clientData.externalId, clientData.activationDate, clientData.imageId, clientData.staffId, clientData.staffName,
|
||||
clientData.officeOptions, parentGroups, clientData.staffOptions);
|
||||
}
|
||||
|
||||
public static ClientData clientIdentifier(final Long id, final String accountNo, final EnumOptionData status, final String firstname,
|
||||
@@ -72,24 +79,25 @@ final public class ClientData implements Comparable<ClientData> {
|
||||
final String officeName) {
|
||||
|
||||
return new ClientData(accountNo, status, officeId, officeName, id, firstname, middlename, lastname, fullname, displayName, null,
|
||||
null, null, null, null);
|
||||
null, null, null, null, null, null,null);
|
||||
}
|
||||
|
||||
public static ClientData lookup(final Long id, final String displayName, final Long officeId, final String officeName) {
|
||||
return new ClientData(null, null, officeId, officeName, id, null, null, null, null, displayName, null, null, null, null, null);
|
||||
return new ClientData(null, null, officeId, officeName, id, null, null, null, null, displayName, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public static ClientData instance(final String accountNo, final EnumOptionData status, final Long officeId, final String officeName,
|
||||
final Long id, final String firstname, final String middlename, final String lastname, final String fullname,
|
||||
final String displayName, final String externalId, final LocalDate activationDate, final Long imageId) {
|
||||
final String displayName, final String externalId, final LocalDate activationDate, final Long imageId, final Long staffId,
|
||||
final String staffName) {
|
||||
return new ClientData(accountNo, status, officeId, officeName, id, firstname, middlename, lastname, fullname, displayName,
|
||||
externalId, activationDate, imageId, null, null);
|
||||
externalId, activationDate, imageId, staffId, staffName, null, null, null);
|
||||
}
|
||||
|
||||
private ClientData(final String accountNo, final EnumOptionData status, final Long officeId, final String officeName, final Long id,
|
||||
final String firstname, final String middlename, final String lastname, final String fullname, final String displayName,
|
||||
final String externalId, final LocalDate activationDate, final Long imageId, final Collection<OfficeData> allowedOffices,
|
||||
final Collection<GroupGeneralData> groups) {
|
||||
final String externalId, final LocalDate activationDate, final Long imageId, final Long staffId, final String staffName,
|
||||
final Collection<OfficeData> allowedOffices, final Collection<GroupGeneralData> groups, final Collection<StaffData> staffOptions) {
|
||||
this.accountNo = accountNo;
|
||||
this.status = status;
|
||||
if (status != null) {
|
||||
@@ -113,12 +121,15 @@ final public class ClientData implements Comparable<ClientData> {
|
||||
} else {
|
||||
this.imagePresent = Boolean.FALSE;
|
||||
}
|
||||
this.staffId = staffId;
|
||||
this.staffName = staffName;
|
||||
|
||||
// associations
|
||||
this.groups = groups;
|
||||
|
||||
// template
|
||||
this.officeOptions = allowedOffices;
|
||||
this.staffOptions = staffOptions;
|
||||
}
|
||||
|
||||
public Long id() {
|
||||
|
||||
+82
-43
@@ -9,8 +9,11 @@ import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activa
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
@@ -42,24 +45,29 @@ public final class ClientDataValidator {
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.CLIENT_CREATE_REQUEST_DATA_PARAMETERS);
|
||||
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.CLIENT_CREATE_REQUEST_DATA_PARAMETERS);
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(ClientApiConstants.CLIENT_RESOURCE_NAME);
|
||||
|
||||
final Long officeId = fromApiJsonHelper.extractLongNamed(ClientApiConstants.officeIdParamName, element);
|
||||
final Long officeId = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.officeIdParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.officeIdParamName).value(officeId).notNull().integerGreaterThanZero();
|
||||
|
||||
if (fromApiJsonHelper.parameterExists(ClientApiConstants.groupIdParamName, element)) {
|
||||
final Long groupId = fromApiJsonHelper.extractLongNamed(ClientApiConstants.groupIdParamName, element);
|
||||
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.groupIdParamName, element)) {
|
||||
final Long groupId = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.groupIdParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.groupIdParamName).value(groupId).notNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists(ClientApiConstants.accountNoParamName, element)) {
|
||||
final String accountNo = fromApiJsonHelper.extractStringNamed(ClientApiConstants.accountNoParamName, element);
|
||||
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.staffIdParamName, element)) {
|
||||
final Long staffId = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.staffIdParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.staffIdParamName).value(staffId).ignoreIfNull().longGreaterThanZero();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.accountNoParamName, element)) {
|
||||
final String accountNo = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.accountNoParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.accountNoParamName).value(accountNo).notBlank().notExceedingLengthOf(20);
|
||||
}
|
||||
|
||||
@@ -103,16 +111,17 @@ public final class ClientDataValidator {
|
||||
}
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists(ClientApiConstants.externalIdParamName, element)) {
|
||||
final String externalId = fromApiJsonHelper.extractStringNamed(ClientApiConstants.externalIdParamName, element);
|
||||
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.externalIdParamName, element)) {
|
||||
final String externalId = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.externalIdParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.externalIdParamName).value(externalId).ignoreIfNull()
|
||||
.notExceedingLengthOf(100);
|
||||
}
|
||||
|
||||
final Boolean active = fromApiJsonHelper.extractBooleanNamed(ClientApiConstants.activeParamName, element);
|
||||
final Boolean active = this.fromApiJsonHelper.extractBooleanNamed(ClientApiConstants.activeParamName, element);
|
||||
if (active != null) {
|
||||
if (active.booleanValue()) {
|
||||
final LocalDate joinedDate = fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.activationDateParamName, element);
|
||||
final LocalDate joinedDate = this.fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.activationDateParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.activationDateParamName).value(joinedDate).notNull();
|
||||
}
|
||||
} else {
|
||||
@@ -123,67 +132,67 @@ public final class ClientDataValidator {
|
||||
}
|
||||
|
||||
private void validateIndividualNamePartsCannotBeUsedWithFullname(final JsonElement element, final DataValidatorBuilder baseDataValidator) {
|
||||
final String firstnameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.firstnameParamName, element);
|
||||
final String firstnameParam = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.firstnameParamName, element);
|
||||
if (StringUtils.isNotBlank(firstnameParam)) {
|
||||
final String fullnameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
|
||||
final String fullnameParam = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.fullnameParamName).value(fullnameParam)
|
||||
.mustBeBlankWhenParameterProvided(ClientApiConstants.firstnameParamName, firstnameParam);
|
||||
}
|
||||
|
||||
final String middlenameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.middlenameParamName, element);
|
||||
final String middlenameParam = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.middlenameParamName, element);
|
||||
if (StringUtils.isNotBlank(middlenameParam)) {
|
||||
final String fullnameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
|
||||
final String fullnameParam = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.fullnameParamName).value(fullnameParam)
|
||||
.mustBeBlankWhenParameterProvided(ClientApiConstants.middlenameParamName, middlenameParam);
|
||||
}
|
||||
|
||||
final String lastnameParamName = fromApiJsonHelper.extractStringNamed(ClientApiConstants.lastnameParamName, element);
|
||||
final String lastnameParamName = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.lastnameParamName, element);
|
||||
if (StringUtils.isNotBlank(lastnameParamName)) {
|
||||
final String fullnameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
|
||||
final String fullnameParam = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.fullnameParamName).value(fullnameParam)
|
||||
.mustBeBlankWhenParameterProvided(ClientApiConstants.lastnameParamName, lastnameParamName);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateRequiredIndividualNamePartsExist(final JsonElement element, final DataValidatorBuilder baseDataValidator) {
|
||||
final String firstnameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.firstnameParamName, element);
|
||||
final String firstnameParam = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.firstnameParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.firstnameParamName).value(firstnameParam).notBlank()
|
||||
.notExceedingLengthOf(50);
|
||||
|
||||
final String middlenameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.middlenameParamName, element);
|
||||
final String middlenameParam = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.middlenameParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.middlenameParamName).value(middlenameParam).ignoreIfNull()
|
||||
.notExceedingLengthOf(50);
|
||||
|
||||
final String lastnameParamName = fromApiJsonHelper.extractStringNamed(ClientApiConstants.lastnameParamName, element);
|
||||
final String lastnameParamName = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.lastnameParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.lastnameParamName).value(lastnameParamName).notBlank()
|
||||
.notExceedingLengthOf(50);
|
||||
}
|
||||
|
||||
private void fullnameCannotBeBlank(final JsonElement element, final DataValidatorBuilder baseDataValidator) {
|
||||
final String fullnameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
|
||||
final String fullnameParam = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.fullnameParamName).value(fullnameParam).notBlank().notExceedingLengthOf(100);
|
||||
}
|
||||
|
||||
private boolean isIndividualNamePartParameterPassed(final JsonElement element) {
|
||||
return fromApiJsonHelper.parameterExists(ClientApiConstants.firstnameParamName, element)
|
||||
|| fromApiJsonHelper.parameterExists(ClientApiConstants.middlenameParamName, element)
|
||||
|| fromApiJsonHelper.parameterExists(ClientApiConstants.lastnameParamName, element);
|
||||
return this.fromApiJsonHelper.parameterExists(ClientApiConstants.firstnameParamName, element)
|
||||
|| this.fromApiJsonHelper.parameterExists(ClientApiConstants.middlenameParamName, element)
|
||||
|| this.fromApiJsonHelper.parameterExists(ClientApiConstants.lastnameParamName, element);
|
||||
}
|
||||
|
||||
private boolean isFullnameParameterPassed(final JsonElement element) {
|
||||
return fromApiJsonHelper.parameterExists(ClientApiConstants.fullnameParamName, element);
|
||||
return this.fromApiJsonHelper.parameterExists(ClientApiConstants.fullnameParamName, element);
|
||||
}
|
||||
|
||||
private boolean isIndividualNameProvided(final JsonElement element) {
|
||||
final String firstname = fromApiJsonHelper.extractStringNamed(ClientApiConstants.firstnameParamName, element);
|
||||
final String middlename = fromApiJsonHelper.extractStringNamed(ClientApiConstants.middlenameParamName, element);
|
||||
final String lastname = fromApiJsonHelper.extractStringNamed(ClientApiConstants.lastnameParamName, element);
|
||||
final String firstname = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.firstnameParamName, element);
|
||||
final String middlename = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.middlenameParamName, element);
|
||||
final String lastname = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.lastnameParamName, element);
|
||||
|
||||
return StringUtils.isNotBlank(firstname) || StringUtils.isNotBlank(middlename) || StringUtils.isNotBlank(lastname);
|
||||
}
|
||||
|
||||
private boolean isFullnameProvided(final JsonElement element) {
|
||||
final String fullname = fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
|
||||
final String fullname = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element);
|
||||
return StringUtils.isNotBlank(fullname);
|
||||
}
|
||||
|
||||
@@ -192,8 +201,8 @@ public final class ClientDataValidator {
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.CLIENT_UPDATE_REQUEST_DATA_PARAMETERS);
|
||||
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.CLIENT_UPDATE_REQUEST_DATA_PARAMETERS);
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
|
||||
@@ -201,9 +210,9 @@ public final class ClientDataValidator {
|
||||
.resource(ClientApiConstants.CLIENT_RESOURCE_NAME);
|
||||
|
||||
boolean atLeastOneParameterPassedForUpdate = false;
|
||||
if (fromApiJsonHelper.parameterExists(ClientApiConstants.accountNoParamName, element)) {
|
||||
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.accountNoParamName, element)) {
|
||||
atLeastOneParameterPassedForUpdate = true;
|
||||
final String accountNo = fromApiJsonHelper.extractStringNamed(ClientApiConstants.accountNoParamName, element);
|
||||
final String accountNo = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.accountNoParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.accountNoParamName).value(accountNo).notBlank().notExceedingLengthOf(20);
|
||||
}
|
||||
|
||||
@@ -247,36 +256,42 @@ public final class ClientDataValidator {
|
||||
}
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists(ClientApiConstants.fullnameParamName, element)) {
|
||||
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.fullnameParamName, element)) {
|
||||
atLeastOneParameterPassedForUpdate = true;
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists(ClientApiConstants.lastnameParamName, element)) {
|
||||
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.lastnameParamName, element)) {
|
||||
atLeastOneParameterPassedForUpdate = true;
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists(ClientApiConstants.middlenameParamName, element)) {
|
||||
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.middlenameParamName, element)) {
|
||||
atLeastOneParameterPassedForUpdate = true;
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists(ClientApiConstants.firstnameParamName, element)) {
|
||||
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.firstnameParamName, element)) {
|
||||
atLeastOneParameterPassedForUpdate = true;
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists(ClientApiConstants.externalIdParamName, element)) {
|
||||
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.externalIdParamName, element)) {
|
||||
atLeastOneParameterPassedForUpdate = true;
|
||||
final String externalId = fromApiJsonHelper.extractStringNamed(ClientApiConstants.externalIdParamName, element);
|
||||
final String externalId = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.externalIdParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.externalIdParamName).value(externalId).notExceedingLengthOf(100);
|
||||
}
|
||||
|
||||
final Boolean active = fromApiJsonHelper.extractBooleanNamed(ClientApiConstants.activeParamName, element);
|
||||
final Boolean active = this.fromApiJsonHelper.extractBooleanNamed(ClientApiConstants.activeParamName, element);
|
||||
if (active != null) {
|
||||
if (active.booleanValue()) {
|
||||
final LocalDate joinedDate = fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.activationDateParamName, element);
|
||||
final LocalDate joinedDate = this.fromApiJsonHelper.extractLocalDateNamed(ClientApiConstants.activationDateParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.activationDateParamName).value(joinedDate).notNull();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.staffIdParamName, element)) {
|
||||
final Long staffId = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.staffIdParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.staffIdParamName).value(staffId).ignoreIfNull().longGreaterThanZero();
|
||||
}
|
||||
|
||||
if (!atLeastOneParameterPassedForUpdate) {
|
||||
final Object forceError = null;
|
||||
baseDataValidator.reset().anyOfNotNull(forceError);
|
||||
@@ -291,7 +306,7 @@ public final class ClientDataValidator {
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.ACTIVATION_REQUEST_DATA_PARAMETERS);
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, ClientApiConstants.ACTIVATION_REQUEST_DATA_PARAMETERS);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
@@ -299,7 +314,7 @@ public final class ClientDataValidator {
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
|
||||
final LocalDate activationDate = fromApiJsonHelper.extractLocalDateNamed(activationDateParamName, element);
|
||||
final LocalDate activationDate = this.fromApiJsonHelper.extractLocalDateNamed(activationDateParamName, element);
|
||||
baseDataValidator.reset().parameter(activationDateParamName).value(activationDate).notNull();
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
@@ -311,4 +326,28 @@ public final class ClientDataValidator {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
public void validateForUnassignStaff(final String json) {
|
||||
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
|
||||
final Set<String> supportedParametersUnassignStaff = new HashSet<String>(Arrays.asList(ClientApiConstants.staffIdParamName));
|
||||
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParametersUnassignStaff);
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(ClientApiConstants.CLIENT_RESOURCE_NAME);
|
||||
|
||||
final String staffIdParameterName = ClientApiConstants.staffIdParamName;
|
||||
final Long staffId = this.fromApiJsonHelper.extractLongNamed(staffIdParameterName, element);
|
||||
baseDataValidator.reset().parameter(staffIdParameterName).value(staffId).notNull().longGreaterThanZero();
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
|
||||
}
|
||||
}
|
||||
+63
-10
@@ -5,6 +5,27 @@
|
||||
*/
|
||||
package org.mifosplatform.portfolio.client.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.Transient;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
@@ -16,14 +37,11 @@ import org.mifosplatform.infrastructure.core.service.DateUtils;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.domain.Image;
|
||||
import org.mifosplatform.infrastructure.security.service.RandomPasswordGenerator;
|
||||
import org.mifosplatform.organisation.office.domain.Office;
|
||||
import org.mifosplatform.organisation.staff.domain.Staff;
|
||||
import org.mifosplatform.portfolio.client.api.ClientApiConstants;
|
||||
import org.mifosplatform.portfolio.group.domain.Group;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_client", uniqueConstraints = { @UniqueConstraint(columnNames = { "account_no" }, name = "account_no_UNIQUE") })
|
||||
public final class Client extends AbstractPersistable<Long> {
|
||||
@@ -67,6 +85,10 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
@Column(name = "external_id", length = 100, nullable = true, unique = true)
|
||||
private String externalId;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "staff_id")
|
||||
private Staff staff;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(name = "m_group_client", joinColumns = @JoinColumn(name = "client_id"), inverseJoinColumns = @JoinColumn(name = "group_id"))
|
||||
private Set<Group> groups;
|
||||
@@ -74,7 +96,7 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
@Transient
|
||||
private boolean accountNumberRequiresAutoGeneration = false;
|
||||
|
||||
public static Client createNew(final Office clientOffice, final Group clientParentGroup, final JsonCommand command) {
|
||||
public static Client createNew(final Office clientOffice, final Group clientParentGroup, final Staff staff, final JsonCommand command) {
|
||||
|
||||
final String accountNo = command.stringValueOfParameterNamed(ClientApiConstants.accountNoParamName);
|
||||
final String externalId = command.stringValueOfParameterNamed(ClientApiConstants.externalIdParamName);
|
||||
@@ -97,7 +119,7 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
return new Client(status, clientOffice, clientParentGroup, accountNo, firstname, middlename, lastname, fullname, activationDate,
|
||||
externalId);
|
||||
externalId, staff);
|
||||
}
|
||||
|
||||
protected Client() {
|
||||
@@ -106,7 +128,7 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
|
||||
private Client(final ClientStatus status, final Office office, final Group clientParentGroup, final String accountNo,
|
||||
final String firstname, final String middlename, final String lastname, final String fullname, final LocalDate activationDate,
|
||||
final String externalId) {
|
||||
final String externalId, final Staff staff) {
|
||||
if (StringUtils.isBlank(accountNo)) {
|
||||
this.accountNumber = new RandomPasswordGenerator(19).generate();
|
||||
this.accountNumberRequiresAutoGeneration = true;
|
||||
@@ -152,6 +174,8 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
this.groups.add(clientParentGroup);
|
||||
}
|
||||
|
||||
this.staff = staff;
|
||||
|
||||
deriveDisplayName();
|
||||
validate();
|
||||
}
|
||||
@@ -280,6 +304,11 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
this.fullname = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInLongParameterNamed(ClientApiConstants.staffIdParamName, staffId())) {
|
||||
final Long newValue = command.longValueOfParameterNamed(ClientApiConstants.staffIdParamName);
|
||||
actualChanges.put(ClientApiConstants.staffIdParamName, newValue);
|
||||
}
|
||||
|
||||
final String dateFormatAsInput = command.dateFormat();
|
||||
final String localeAsInput = command.locale();
|
||||
|
||||
@@ -326,7 +355,7 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
|
||||
private void validateActivationDate(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (this.activationDate != null) {
|
||||
if (office.isOpeningDateAfter(getActivationLocalDate())) {
|
||||
if (this.office.isOpeningDateAfter(getActivationLocalDate())) {
|
||||
final String defaultUserMessage = "Client activation date cannot be a date before the office opening date.";
|
||||
final ApiParameterError error = ApiParameterError.parameterError(
|
||||
"error.msg.clients.activationDate.cannot.be.before.office.activation.date", defaultUserMessage,
|
||||
@@ -374,7 +403,7 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
return this.office.getId();
|
||||
}
|
||||
|
||||
public void setImage(Image image) {
|
||||
public void setImage(final Image image) {
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
@@ -386,8 +415,32 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
return this.displayName;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
public void setDisplayName(final String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public Office getOffice() {
|
||||
return this.office;
|
||||
}
|
||||
|
||||
private Long staffId() {
|
||||
Long staffId = null;
|
||||
if (this.staff != null) {
|
||||
staffId = this.staff.getId();
|
||||
}
|
||||
return staffId;
|
||||
}
|
||||
|
||||
public void updateStaff(final Staff staff) {
|
||||
this.staff = staff;
|
||||
}
|
||||
|
||||
public Staff getStaff() {
|
||||
return this.staff;
|
||||
}
|
||||
|
||||
public void unassignStaff() {
|
||||
this.staff = null;
|
||||
}
|
||||
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package org.mifosplatform.portfolio.client.exception;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
|
||||
public class ClientHasNoStaffException extends AbstractPlatformResourceNotFoundException {
|
||||
|
||||
public ClientHasNoStaffException(final Long clientId) {
|
||||
super("error.msg.client.has.no.staff", "Client with identifier " + clientId + " does not have staff", clientId);
|
||||
}
|
||||
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package org.mifosplatform.portfolio.client.handler;
|
||||
|
||||
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.portfolio.client.service.ClientWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class UnassignClientStaffCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final ClientWritePlatformService clientWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
public UnassignClientStaffCommandHandler(final ClientWritePlatformService clientWritePlatformService) {
|
||||
this.clientWritePlatformService = clientWritePlatformService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
return this.clientWritePlatformService.unassignClientStaff(command.entityId(), command);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -16,7 +16,7 @@ import org.mifosplatform.portfolio.group.service.SearchParameters;
|
||||
|
||||
public interface ClientReadPlatformService {
|
||||
|
||||
ClientData retrieveTemplate();
|
||||
ClientData retrieveTemplate(Long officeId);
|
||||
|
||||
Page<ClientData> retrieveAll(SearchParameters searchParameters);
|
||||
|
||||
|
||||
+37
-11
@@ -22,6 +22,8 @@ import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSourc
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.mifosplatform.organisation.office.data.OfficeData;
|
||||
import org.mifosplatform.organisation.office.service.OfficeReadPlatformService;
|
||||
import org.mifosplatform.organisation.staff.data.StaffData;
|
||||
import org.mifosplatform.organisation.staff.service.StaffReadPlatformService;
|
||||
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryCollectionData;
|
||||
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryData;
|
||||
import org.mifosplatform.portfolio.client.data.ClientData;
|
||||
@@ -40,6 +42,7 @@ import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@Service
|
||||
public class ClientReadPlatformServiceImpl implements ClientReadPlatformService {
|
||||
@@ -47,6 +50,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final PlatformSecurityContext context;
|
||||
private final OfficeReadPlatformService officeReadPlatformService;
|
||||
private final StaffReadPlatformService staffReadPlatformService;
|
||||
|
||||
// data mappers
|
||||
private final PaginationHelper<ClientData> paginationHelper = new PaginationHelper<ClientData>();
|
||||
@@ -57,22 +61,28 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
|
||||
@Autowired
|
||||
public ClientReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource,
|
||||
final OfficeReadPlatformService officeReadPlatformService) {
|
||||
final OfficeReadPlatformService officeReadPlatformService, final StaffReadPlatformService staffReadPlatformService) {
|
||||
this.context = context;
|
||||
this.officeReadPlatformService = officeReadPlatformService;
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
this.staffReadPlatformService = staffReadPlatformService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientData retrieveTemplate() {
|
||||
public ClientData retrieveTemplate(final Long officeId) {
|
||||
|
||||
final AppUser currentUser = context.authenticatedUser();
|
||||
this.context.authenticatedUser();
|
||||
|
||||
final Long defaultOfficeId = defaultToUsersOfficeIfNull(officeId);
|
||||
|
||||
final Collection<OfficeData> offices = officeReadPlatformService.retrieveAllOfficesForDropdown();
|
||||
|
||||
final Long officeId = currentUser.getOffice().getId();
|
||||
|
||||
return ClientData.template(officeId, new LocalDate(), offices);
|
||||
Collection<StaffData> staffOptions = this.staffReadPlatformService.retrieveAllStaffForDropdown(defaultOfficeId);
|
||||
if (CollectionUtils.isEmpty(staffOptions)) {
|
||||
staffOptions = null;
|
||||
}
|
||||
|
||||
return ClientData.template(defaultOfficeId, new LocalDate(), offices, staffOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -226,10 +236,12 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
sqlBuilder.append("c.office_id as officeId, o.name as officeName, ");
|
||||
sqlBuilder.append("c.firstname as firstname, c.middlename as middlename, c.lastname as lastname, ");
|
||||
sqlBuilder.append("c.fullname as fullname, c.display_name as displayName, ");
|
||||
sqlBuilder.append("c.activation_date as activationDate, c.image_id as imageId ");
|
||||
sqlBuilder.append("c.activation_date as activationDate, c.image_id as imageId, ");
|
||||
sqlBuilder.append("c.staff_id as staffId, s.display_name as staffName ");
|
||||
sqlBuilder.append("from m_client c ");
|
||||
sqlBuilder.append("join m_office o on o.id = c.office_id ");
|
||||
sqlBuilder.append("join m_group_client pgc on pgc.client_id = c.id");
|
||||
sqlBuilder.append("join m_group_client pgc on pgc.client_id = c.id ");
|
||||
sqlBuilder.append("left join m_staff s on s.id = c.staff_id ");
|
||||
|
||||
this.schema = sqlBuilder.toString();
|
||||
}
|
||||
@@ -256,9 +268,11 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
final LocalDate activationDate = JdbcSupport.getLocalDate(rs, "activationDate");
|
||||
final Long imageId = JdbcSupport.getLong(rs, "imageId");
|
||||
final String officeName = rs.getString("officeName");
|
||||
final Long staffId = JdbcSupport.getLong(rs, "staffId");
|
||||
final String staffName = rs.getString("staffName");
|
||||
|
||||
return ClientData.instance(accountNo, status, officeId, officeName, id, firstname, middlename, lastname, fullname, displayName,
|
||||
externalId, activationDate, imageId);
|
||||
externalId, activationDate, imageId, staffId, staffName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,9 +288,11 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
builder.append("c.office_id as officeId, o.name as officeName, ");
|
||||
builder.append("c.firstname as firstname, c.middlename as middlename, c.lastname as lastname, ");
|
||||
builder.append("c.fullname as fullname, c.display_name as displayName, ");
|
||||
builder.append("c.activation_date as activationDate, c.image_id as imageId ");
|
||||
builder.append("c.activation_date as activationDate, c.image_id as imageId, ");
|
||||
builder.append("c.staff_id as staffId, s.display_name as staffName ");
|
||||
builder.append("from m_client c ");
|
||||
builder.append("join m_office o on o.id = c.office_id ");
|
||||
builder.append("left join m_staff s on s.id = c.staff_id ");
|
||||
|
||||
this.schema = builder.toString();
|
||||
}
|
||||
@@ -304,9 +320,11 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
final LocalDate activationDate = JdbcSupport.getLocalDate(rs, "activationDate");
|
||||
final String officeName = rs.getString("officeName");
|
||||
final Long imageId = JdbcSupport.getLong(rs, "imageId");
|
||||
final Long staffId = JdbcSupport.getLong(rs, "staffId");
|
||||
final String staffName = rs.getString("staffName");
|
||||
|
||||
return ClientData.instance(accountNo, status, officeId, officeName, id, firstname, middlename, lastname, fullname, displayName,
|
||||
externalId, activationDate, imageId);
|
||||
externalId, activationDate, imageId, staffId, staffName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -560,4 +578,12 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
officeName);
|
||||
}
|
||||
}
|
||||
|
||||
private Long defaultToUsersOfficeIfNull(final Long officeId) {
|
||||
Long defaultOfficeId = officeId;
|
||||
if (defaultOfficeId == null) {
|
||||
defaultOfficeId = this.context.authenticatedUser().getOffice().getId();
|
||||
}
|
||||
return defaultOfficeId;
|
||||
}
|
||||
}
|
||||
+2
@@ -18,4 +18,6 @@ public interface ClientWritePlatformService {
|
||||
|
||||
CommandProcessingResult deleteClient(Long clientId);
|
||||
|
||||
CommandProcessingResult unassignClientStaff(Long clientId, JsonCommand command);
|
||||
|
||||
}
|
||||
+77
-9
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
package org.mifosplatform.portfolio.client.service;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -16,22 +17,27 @@ import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.mifosplatform.infrastructure.security.exception.PermissionDeniedException;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.mifosplatform.organisation.office.domain.Office;
|
||||
import org.mifosplatform.organisation.office.domain.OfficeRepository;
|
||||
import org.mifosplatform.organisation.office.exception.OfficeNotFoundException;
|
||||
import org.mifosplatform.organisation.staff.domain.Staff;
|
||||
import org.mifosplatform.organisation.staff.domain.StaffRepositoryWrapper;
|
||||
import org.mifosplatform.portfolio.client.api.ClientApiConstants;
|
||||
import org.mifosplatform.portfolio.client.data.ClientDataValidator;
|
||||
import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator;
|
||||
import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory;
|
||||
import org.mifosplatform.portfolio.client.domain.Client;
|
||||
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
|
||||
import org.mifosplatform.portfolio.client.exception.ClientHasNoStaffException;
|
||||
import org.mifosplatform.portfolio.client.exception.ClientMustBePendingToBeDeletedException;
|
||||
import org.mifosplatform.portfolio.group.domain.Group;
|
||||
import org.mifosplatform.portfolio.group.domain.GroupRepository;
|
||||
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
|
||||
import org.mifosplatform.portfolio.note.domain.Note;
|
||||
import org.mifosplatform.portfolio.note.domain.NoteRepository;
|
||||
import org.mifosplatform.useradministration.domain.AppUser;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -51,12 +57,13 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
private final GroupRepository groupRepository;
|
||||
private final ClientDataValidator fromApiJsonDeserializer;
|
||||
private final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory;
|
||||
private final StaffRepositoryWrapper staffRepository;
|
||||
|
||||
@Autowired
|
||||
public ClientWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||
final ClientRepositoryWrapper clientRepository, final OfficeRepository officeRepository, final NoteRepository noteRepository,
|
||||
final ClientDataValidator fromApiJsonDeserializer, final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory,
|
||||
final GroupRepository groupRepository) {
|
||||
final GroupRepository groupRepository, final StaffRepositoryWrapper staffRepository) {
|
||||
this.context = context;
|
||||
this.clientRepository = clientRepository;
|
||||
this.officeRepository = officeRepository;
|
||||
@@ -64,6 +71,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
||||
this.accountIdentifierGeneratorFactory = accountIdentifierGeneratorFactory;
|
||||
this.groupRepository = groupRepository;
|
||||
this.staffRepository = staffRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -74,7 +82,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
|
||||
if (client.isNotPending()) { throw new ClientMustBePendingToBeDeletedException(clientId); }
|
||||
|
||||
List<Note> relatedNotes = this.noteRepository.findByClientId(clientId);
|
||||
final List<Note> relatedNotes = this.noteRepository.findByClientId(clientId);
|
||||
this.noteRepository.deleteInBatch(relatedNotes);
|
||||
|
||||
this.clientRepository.delete(client);
|
||||
@@ -92,7 +100,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
*/
|
||||
private void handleDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) {
|
||||
|
||||
Throwable realCause = dve.getMostSpecificCause();
|
||||
final Throwable realCause = dve.getMostSpecificCause();
|
||||
if (realCause.getMessage().contains("external_id")) {
|
||||
|
||||
final String externalId = command.stringValueOfParameterNamed("externalId");
|
||||
@@ -114,7 +122,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
public CommandProcessingResult createClient(final JsonCommand command) {
|
||||
|
||||
try {
|
||||
context.authenticatedUser();
|
||||
this.context.authenticatedUser();
|
||||
|
||||
this.fromApiJsonDeserializer.validateForCreate(command.json());
|
||||
|
||||
@@ -131,7 +139,13 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
if (clientParentGroup == null) { throw new GroupNotFoundException(groupId); }
|
||||
}
|
||||
|
||||
final Client newClient = Client.createNew(clientOffice, clientParentGroup, command);
|
||||
Staff staff = null;
|
||||
final Long staffId = command.longValueOfParameterNamed(ClientApiConstants.staffIdParamName);
|
||||
if (staffId != null) {
|
||||
staff = this.staffRepository.findByOfficeWithNotFoundDetection(staffId, officeId);
|
||||
}
|
||||
|
||||
final Client newClient = Client.createNew(clientOffice, clientParentGroup, staff, command);
|
||||
|
||||
this.clientRepository.save(newClient);
|
||||
|
||||
@@ -149,7 +163,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
.withGroupId(groupId) //
|
||||
.withEntityId(newClient.getId()) //
|
||||
.build();
|
||||
} catch (DataIntegrityViolationException dve) {
|
||||
} catch (final DataIntegrityViolationException dve) {
|
||||
handleDataIntegrityIssues(command, dve);
|
||||
return CommandProcessingResult.empty();
|
||||
}
|
||||
@@ -160,14 +174,35 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
public CommandProcessingResult updateClient(final Long clientId, final JsonCommand command) {
|
||||
|
||||
try {
|
||||
context.authenticatedUser();
|
||||
AppUser user = context.authenticatedUser();
|
||||
|
||||
this.fromApiJsonDeserializer.validateForUpdate(command.json());
|
||||
|
||||
final Client clientForUpdate = this.clientRepository.findOneWithNotFoundDetection(clientId);
|
||||
final String clientHierarchy = clientForUpdate.getOffice().getHierarchy();
|
||||
|
||||
// Don't allow other office user to update
|
||||
final Office loginUserOffice = user.getOffice();
|
||||
final String userHierarchy = loginUserOffice.getHierarchy();
|
||||
|
||||
if (!clientHierarchy.startsWith(userHierarchy)) {
|
||||
final String code = "error.msg.not.enough.permissions.to.access.resource";
|
||||
final String defaultMessage = "The User with id " + user.getId() + " don't have permission to update this client";
|
||||
throw new PermissionDeniedException(code, defaultMessage, user.getId());
|
||||
}
|
||||
|
||||
final Map<String, Object> changes = clientForUpdate.update(command);
|
||||
|
||||
if (changes.containsKey(ClientApiConstants.staffIdParamName)) {
|
||||
|
||||
final Long newValue = command.longValueOfParameterNamed(ClientApiConstants.staffIdParamName);
|
||||
Staff newStaff = null;
|
||||
if (newValue != null) {
|
||||
newStaff = this.staffRepository.findByOfficeWithNotFoundDetection(newValue, clientForUpdate.officeId());
|
||||
}
|
||||
clientForUpdate.updateStaff(newStaff);
|
||||
}
|
||||
|
||||
if (!changes.isEmpty()) {
|
||||
this.clientRepository.saveAndFlush(clientForUpdate);
|
||||
}
|
||||
@@ -179,7 +214,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
.withEntityId(clientId) //
|
||||
.with(changes) //
|
||||
.build();
|
||||
} catch (DataIntegrityViolationException dve) {
|
||||
} catch (final DataIntegrityViolationException dve) {
|
||||
handleDataIntegrityIssues(command, dve);
|
||||
return CommandProcessingResult.empty();
|
||||
}
|
||||
@@ -207,7 +242,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
.withClientId(clientId) //
|
||||
.withEntityId(clientId) //
|
||||
.build();
|
||||
} catch (DataIntegrityViolationException dve) {
|
||||
} catch (final DataIntegrityViolationException dve) {
|
||||
handleDataIntegrityIssues(command, dve);
|
||||
return CommandProcessingResult.empty();
|
||||
}
|
||||
@@ -216,4 +251,37 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
private void logAsErrorUnexpectedDataIntegrityException(final DataIntegrityViolationException dve) {
|
||||
logger.error(dve.getMessage(), dve);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult unassignClientStaff(final Long clientId, final JsonCommand command) {
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(5);
|
||||
|
||||
this.fromApiJsonDeserializer.validateForUnassignStaff(command.json());
|
||||
|
||||
final Client clientForUpdate = this.clientRepository.findOneWithNotFoundDetection(clientId);
|
||||
|
||||
final Staff presentStaff = clientForUpdate.getStaff();
|
||||
Long presentStaffId = null;
|
||||
if (presentStaff == null) { throw new ClientHasNoStaffException(clientId); }
|
||||
presentStaffId = presentStaff.getId();
|
||||
final String staffIdParamName = ClientApiConstants.staffIdParamName;
|
||||
if (!command.isChangeInLongParameterNamed(staffIdParamName, presentStaffId)) {
|
||||
clientForUpdate.unassignStaff();
|
||||
}
|
||||
this.clientRepository.saveAndFlush(clientForUpdate);
|
||||
|
||||
actualChanges.put(staffIdParamName, presentStaffId);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withOfficeId(clientForUpdate.officeId()) //
|
||||
.withEntityId(clientForUpdate.getId()) //
|
||||
.withClientId(clientId) //
|
||||
.with(actualChanges) //
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -210,8 +210,8 @@ public class CentersApiResource {
|
||||
final CommandWrapper commandRequest = builder.saveCenterCollectionSheet(centerId).build();
|
||||
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
} else { //
|
||||
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "activate", "generateCollectionSheet" });
|
||||
} else {
|
||||
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "activate", "generateCollectionSheet", "createRole" });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
@@ -16,6 +16,15 @@ public class GroupingTypesApiConstants {
|
||||
public static final String CENTER_RESOURCE_NAME = "center";
|
||||
public static final String GROUP_RESOURCE_NAME = "group";
|
||||
public static final String COMMUNAL_BANK_RESOURCE_NAME = "communalbank";
|
||||
|
||||
//group roles
|
||||
public static final String GROUP_ROLE_RESOURCE_NAME = "grouprole";
|
||||
public static final String GROUP_ROLE_NAME = "GROUPROLE";
|
||||
|
||||
public static final String roleParamName = "role";
|
||||
public static final String groupIdParamName = "groupId";
|
||||
public static final String clientIdParamName = "clientId";
|
||||
public static final String groupRolesParamName = "groupRoles";
|
||||
|
||||
// general
|
||||
public static final String localeParamName = "locale";
|
||||
@@ -51,6 +60,8 @@ public class GroupingTypesApiConstants {
|
||||
public static final Set<String> GROUP_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName, dateFormatParamName,
|
||||
idParamName, nameParamName, externalIdParamName, centerIdParamName, officeIdParamName, staffIdParamName, activeParamName,
|
||||
activationDateParamName, clientMembersParamName));
|
||||
|
||||
public static final Set<String> GROUP_ROLES_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(roleParamName, clientIdParamName));
|
||||
|
||||
/**
|
||||
* These parameters will match the class level parameters of
|
||||
@@ -74,4 +85,5 @@ public class GroupingTypesApiConstants {
|
||||
|
||||
|
||||
public static final Set<String> COLLECTIONSHEET_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("dueDate", "loanProducts", "groups"));
|
||||
|
||||
}
|
||||
+63
-22
@@ -12,6 +12,7 @@ import java.util.Set;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
@@ -43,8 +44,10 @@ import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetData;
|
||||
import org.mifosplatform.portfolio.collectionsheet.service.CollectionSheetReadPlatformService;
|
||||
import org.mifosplatform.portfolio.group.data.GroupAccountSummaryCollectionData;
|
||||
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
|
||||
import org.mifosplatform.portfolio.group.data.GroupRoleData;
|
||||
import org.mifosplatform.portfolio.group.service.CenterReadPlatformService;
|
||||
import org.mifosplatform.portfolio.group.service.GroupReadPlatformService;
|
||||
import org.mifosplatform.portfolio.group.service.GroupRolesReadPlatformService;
|
||||
import org.mifosplatform.portfolio.group.service.SearchParameters;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
@@ -69,6 +72,7 @@ public class GroupsApiResource {
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
private final CollectionSheetReadPlatformService collectionSheetReadPlatformService;
|
||||
private final FromJsonHelper fromJsonHelper;
|
||||
private final GroupRolesReadPlatformService groupRolesReadPlatformService;
|
||||
|
||||
@Autowired
|
||||
public GroupsApiResource(final PlatformSecurityContext context, final GroupReadPlatformService groupReadPlatformService,
|
||||
@@ -78,7 +82,8 @@ public class GroupsApiResource {
|
||||
final ToApiJsonSerializer<GroupAccountSummaryCollectionData> groupSummaryToApiJsonSerializer,
|
||||
final ApiRequestParameterHelper apiRequestParameterHelper,
|
||||
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
|
||||
final CollectionSheetReadPlatformService collectionSheetReadPlatformService, final FromJsonHelper fromJsonHelper) {
|
||||
final CollectionSheetReadPlatformService collectionSheetReadPlatformService, final FromJsonHelper fromJsonHelper,
|
||||
final GroupRolesReadPlatformService groupRolesReadPlatformService) {
|
||||
this.context = context;
|
||||
this.groupReadPlatformService = groupReadPlatformService;
|
||||
this.centerReadPlatformService = centerReadPlatformService;
|
||||
@@ -90,6 +95,7 @@ public class GroupsApiResource {
|
||||
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
|
||||
this.collectionSheetReadPlatformService = collectionSheetReadPlatformService;
|
||||
this.fromJsonHelper = fromJsonHelper;
|
||||
this.groupRolesReadPlatformService = groupRolesReadPlatformService;
|
||||
}
|
||||
|
||||
@GET
|
||||
@@ -97,8 +103,8 @@ public class GroupsApiResource {
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retrieveTemplate(@Context final UriInfo uriInfo, @QueryParam("officeId") final Long officeId,
|
||||
@QueryParam("center") final boolean isCenterGroup,
|
||||
@QueryParam("centerId") final Long centerId) {
|
||||
@QueryParam("center") final boolean isCenterGroup, @QueryParam("centerId") final Long centerId,
|
||||
@DefaultValue("false") @QueryParam("staffInSelectedOfficeOnly") final boolean staffInSelectedOfficeOnly) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(GroupingTypesApiConstants.GROUP_RESOURCE_NAME);
|
||||
|
||||
@@ -109,7 +115,8 @@ public class GroupsApiResource {
|
||||
GroupingTypesApiConstants.CENTER_GROUP_RESPONSE_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
final GroupGeneralData groupTemplate = this.groupReadPlatformService.retrieveTemplate(officeId, isCenterGroup);
|
||||
final GroupGeneralData groupTemplate = this.groupReadPlatformService.retrieveTemplate(officeId, isCenterGroup,
|
||||
staffInSelectedOfficeOnly);
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.groupGeneralApiJsonSerializer.serialize(settings, groupTemplate,
|
||||
GroupingTypesApiConstants.GROUP_RESPONSE_DATA_PARAMETERS);
|
||||
@@ -130,7 +137,7 @@ public class GroupsApiResource {
|
||||
limit, orderBy, sortOrder);
|
||||
final Page<GroupGeneralData> groups = this.groupReadPlatformService.retrieveAll(searchParameters);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, groups, GroupingTypesApiConstants.GROUP_RESPONSE_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
@@ -138,30 +145,50 @@ public class GroupsApiResource {
|
||||
@Path("{groupId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retrieveOne(@Context final UriInfo uriInfo, @PathParam("groupId") final Long groupId) {
|
||||
public String retrieveOne(@Context final UriInfo uriInfo, @PathParam("groupId") final Long groupId,
|
||||
@DefaultValue("false") @QueryParam("staffInSelectedOfficeOnly") final boolean staffInSelectedOfficeOnly,
|
||||
@QueryParam("roleId") final Long roleId) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(GroupingTypesApiConstants.GROUP_RESOURCE_NAME);
|
||||
final Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
|
||||
|
||||
GroupGeneralData group = this.groupReadPlatformService.retrieveOne(groupId);
|
||||
|
||||
|
||||
// associations
|
||||
Collection<ClientData> membersOfGroup = null;
|
||||
Collection<GroupRoleData> groupRoles = null;
|
||||
GroupRoleData selectedRole = null;
|
||||
if (!associationParameters.isEmpty()) {
|
||||
if (associationParameters.contains("all")) {
|
||||
associationParameters.addAll(Arrays.asList("clientMembers", "groupRoles"));
|
||||
}
|
||||
if (associationParameters.contains("clientMembers")) {
|
||||
membersOfGroup = this.clientReadPlatformService.retrieveClientMembersOfGroup(groupId);
|
||||
if (CollectionUtils.isEmpty(membersOfGroup)) {
|
||||
membersOfGroup = null;
|
||||
}
|
||||
}
|
||||
if (associationParameters.contains("groupRoles")) {
|
||||
groupRoles = this.groupRolesReadPlatformService.retrieveGroupRoles(groupId);
|
||||
if (CollectionUtils.isEmpty(membersOfGroup)) {
|
||||
groupRoles = null;
|
||||
}
|
||||
}
|
||||
if (roleId != null) {
|
||||
selectedRole = this.groupRolesReadPlatformService.retrieveGroupRole(groupId, roleId);
|
||||
if (selectedRole != null) {
|
||||
group = GroupGeneralData.updateSelectedRole(group, selectedRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters());
|
||||
if (template) {
|
||||
final GroupGeneralData templateGroup = this.groupReadPlatformService.retrieveTemplate(group.officeId(), false);
|
||||
group = GroupGeneralData.withTemplateAndAssociations(templateGroup, group, membersOfGroup);
|
||||
final GroupGeneralData templateGroup = this.groupReadPlatformService.retrieveTemplate(group.officeId(), false,
|
||||
staffInSelectedOfficeOnly);
|
||||
group = GroupGeneralData.withTemplateAndAssociations(templateGroup, group, membersOfGroup, groupRoles);
|
||||
} else {
|
||||
group = GroupGeneralData.withAssocations(group, membersOfGroup);
|
||||
group = GroupGeneralData.withAssocations(group, membersOfGroup, groupRoles);
|
||||
}
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
@@ -227,9 +254,9 @@ public class GroupsApiResource {
|
||||
@Path("{groupId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String activateOrGenerateCollectionSheet(@PathParam("groupId") final Long groupId, @QueryParam("command") final String commandParam,
|
||||
final String apiRequestBodyAsJson, @Context final UriInfo uriInfo) {
|
||||
|
||||
public String activateOrGenerateCollectionSheet(@PathParam("groupId") final Long groupId,
|
||||
@QueryParam("command") final String commandParam, @QueryParam("roleId") final Long roleId, final String apiRequestBodyAsJson,
|
||||
@Context final UriInfo uriInfo) {
|
||||
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
||||
|
||||
CommandProcessingResult result = null;
|
||||
@@ -237,32 +264,46 @@ public class GroupsApiResource {
|
||||
final CommandWrapper commandRequest = builder.activateGroup(groupId).build();
|
||||
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}else if (is(commandParam, "associateClients")) {
|
||||
} else if (is(commandParam, "associateClients")) {
|
||||
final CommandWrapper commandRequest = builder.associateClientsToGroup(groupId).build();
|
||||
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}else if (is(commandParam, "disassociateClients")) {
|
||||
} else if (is(commandParam, "disassociateClients")) {
|
||||
final CommandWrapper commandRequest = builder.disassociateClientsFromGroup(groupId).build();
|
||||
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}else if (is(commandParam, "generateCollectionSheet")) {
|
||||
} else if (is(commandParam, "generateCollectionSheet")) {
|
||||
final JsonElement parsedQuery = this.fromJsonHelper.parse(apiRequestBodyAsJson);
|
||||
final JsonQuery query = JsonQuery.from(apiRequestBodyAsJson, parsedQuery, this.fromJsonHelper);
|
||||
final JLGCollectionSheetData collectionSheet = this.collectionSheetReadPlatformService.generateGroupCollectionSheet(groupId, query);
|
||||
final JLGCollectionSheetData collectionSheet = this.collectionSheetReadPlatformService.generateGroupCollectionSheet(groupId,
|
||||
query);
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, collectionSheet, GroupingTypesApiConstants.COLLECTIONSHEET_DATA_PARAMETERS);
|
||||
}else if (is(commandParam, "saveCollectionSheet")) {
|
||||
} else if (is(commandParam, "saveCollectionSheet")) {
|
||||
final CommandWrapper commandRequest = builder.saveGroupCollectionSheet(groupId).build();
|
||||
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}else if (is(commandParam, "unassignStaff")) {
|
||||
} else if (is(commandParam, "unassignStaff")) {
|
||||
final CommandWrapper commandRequest = builder.unassignGroupStaff(groupId).build();
|
||||
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
} else if (is(commandParam, "assignRole")) {
|
||||
final CommandWrapper commandRequest = builder.assignRole(groupId).build();
|
||||
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
} else if (is(commandParam, "unassignRole")) {
|
||||
final CommandWrapper commandRequest = builder.unassignRole(groupId, roleId).build();
|
||||
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
} else if (is(commandParam, "updateRole")) {
|
||||
final CommandWrapper commandRequest = builder.updateRole(groupId, roleId).build();
|
||||
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
} else {
|
||||
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "activate", "generateCollectionSheet", "saveCollectionSheet", "unassignStaff" });
|
||||
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "activate", "generateCollectionSheet",
|
||||
"saveCollectionSheet", "unassignStaff", "assignRole", "unassignRole", "updateassignRole" });
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private boolean is(final String commandParam, final String commandValue) {
|
||||
|
||||
+37
-12
@@ -8,6 +8,7 @@ package org.mifosplatform.portfolio.group.data;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.organisation.office.data.OfficeData;
|
||||
import org.mifosplatform.organisation.staff.data.StaffData;
|
||||
@@ -38,50 +39,59 @@ public class GroupGeneralData {
|
||||
|
||||
// associations
|
||||
private final Collection<ClientData> clientMembers;
|
||||
private final Collection<GroupRoleData> groupRoles;
|
||||
|
||||
// template
|
||||
private final Collection<CenterData> centerOptions;
|
||||
private final Collection<OfficeData> officeOptions;
|
||||
private final Collection<StaffData> staffOptions;
|
||||
private final Collection<ClientData> clientOptions;
|
||||
private final Collection<CodeValueData> availableRoles;
|
||||
private final GroupRoleData selectedRole;
|
||||
|
||||
public static GroupGeneralData lookup(final Long groupId, final String groupName) {
|
||||
final Collection<ClientData> clientMembers = null;
|
||||
final Collection<GroupRoleData> groupRoles = null;
|
||||
|
||||
return new GroupGeneralData(groupId, groupName, null, null, null, null, null, null, null, null, null, null, clientMembers, null,
|
||||
null, null, null);
|
||||
null, null, null, groupRoles, null, null);
|
||||
}
|
||||
|
||||
public static GroupGeneralData template(final Long officeId, final Long centerId, final String centerName, final Long staffId,
|
||||
final String staffName, final Collection<CenterData> centerOptions, final Collection<OfficeData> officeOptions,
|
||||
final Collection<StaffData> staffOptions, final Collection<ClientData> clientOptions) {
|
||||
final Collection<StaffData> staffOptions, final Collection<ClientData> clientOptions,
|
||||
final Collection<CodeValueData> availableRoles) {
|
||||
|
||||
final Collection<ClientData> clientMembers = null;
|
||||
final Collection<GroupRoleData> groupRoles = null;
|
||||
|
||||
return new GroupGeneralData(null, null, null, null, null, officeId, null, centerId, centerName, staffId, staffName, null,
|
||||
clientMembers, centerOptions, officeOptions, staffOptions, clientOptions);
|
||||
clientMembers, centerOptions, officeOptions, staffOptions, clientOptions, groupRoles, availableRoles, null);
|
||||
}
|
||||
|
||||
public static GroupGeneralData withTemplate(final GroupGeneralData templatedGrouping, final GroupGeneralData grouping) {
|
||||
return new GroupGeneralData(grouping.id, grouping.name, grouping.externalId, grouping.status, grouping.activationDate,
|
||||
grouping.officeId, grouping.officeName, grouping.centerId, grouping.centerName, grouping.staffId, grouping.staffName,
|
||||
grouping.hierarchy, grouping.clientMembers, templatedGrouping.centerOptions, templatedGrouping.officeOptions,
|
||||
templatedGrouping.staffOptions, templatedGrouping.clientOptions);
|
||||
templatedGrouping.staffOptions, templatedGrouping.clientOptions, grouping.groupRoles, templatedGrouping.availableRoles,
|
||||
grouping.selectedRole);
|
||||
}
|
||||
|
||||
public static GroupGeneralData withTemplateAndAssociations(final GroupGeneralData templatedGrouping, final GroupGeneralData grouping,
|
||||
final Collection<ClientData> membersOfGroup) {
|
||||
final Collection<ClientData> membersOfGroup, final Collection<GroupRoleData> groupRoles) {
|
||||
return new GroupGeneralData(grouping.id, grouping.name, grouping.externalId, grouping.status, grouping.activationDate,
|
||||
grouping.officeId, grouping.officeName, grouping.centerId, grouping.centerName, grouping.staffId, grouping.staffName,
|
||||
grouping.hierarchy, membersOfGroup, templatedGrouping.centerOptions, templatedGrouping.officeOptions,
|
||||
templatedGrouping.staffOptions, templatedGrouping.clientOptions);
|
||||
templatedGrouping.staffOptions, templatedGrouping.clientOptions, groupRoles, templatedGrouping.availableRoles,
|
||||
grouping.selectedRole);
|
||||
}
|
||||
|
||||
public static GroupGeneralData withAssocations(final GroupGeneralData grouping, final Collection<ClientData> membersOfGroup) {
|
||||
public static GroupGeneralData withAssocations(final GroupGeneralData grouping, final Collection<ClientData> membersOfGroup,
|
||||
final Collection<GroupRoleData> groupRoles) {
|
||||
return new GroupGeneralData(grouping.id, grouping.name, grouping.externalId, grouping.status, grouping.activationDate,
|
||||
grouping.officeId, grouping.officeName, grouping.centerId, grouping.centerName, grouping.staffId, grouping.staffName,
|
||||
grouping.hierarchy, membersOfGroup, grouping.centerOptions, grouping.officeOptions, grouping.staffOptions,
|
||||
grouping.clientOptions);
|
||||
grouping.clientOptions, groupRoles, grouping.availableRoles, grouping.selectedRole);
|
||||
}
|
||||
|
||||
public static GroupGeneralData instance(final Long id, final String name, final String externalId, final EnumOptionData status,
|
||||
@@ -93,16 +103,21 @@ public class GroupGeneralData {
|
||||
final Collection<OfficeData> officeOptions = null;
|
||||
final Collection<StaffData> staffOptions = null;
|
||||
final Collection<ClientData> clientOptions = null;
|
||||
final Collection<GroupRoleData> groupRoles = null;
|
||||
final Collection<CodeValueData> availableRoles = null;
|
||||
final GroupRoleData role = null;
|
||||
|
||||
return new GroupGeneralData(id, name, externalId, status, activationDate, officeId, officeName, centerId, centerName, staffId,
|
||||
staffName, hierarchy, clientMembers, centerOptions, officeOptions, staffOptions, clientOptions);
|
||||
staffName, hierarchy, clientMembers, centerOptions, officeOptions, staffOptions, clientOptions, groupRoles, availableRoles,
|
||||
role);
|
||||
}
|
||||
|
||||
private GroupGeneralData(final Long id, final String name, final String externalId, final EnumOptionData status,
|
||||
final LocalDate activationDate, final Long officeId, final String officeName, final Long centerId, final String centerName,
|
||||
final Long staffId, final String staffName, final String hierarchy, final Collection<ClientData> clientMembers,
|
||||
final Collection<CenterData> centerOptions, final Collection<OfficeData> officeOptions,
|
||||
final Collection<StaffData> staffOptions, final Collection<ClientData> clientOptions) {
|
||||
final Collection<StaffData> staffOptions, final Collection<ClientData> clientOptions,
|
||||
final Collection<GroupRoleData> groupRoles, final Collection<CodeValueData> availableRoles, final GroupRoleData role) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.externalId = externalId;
|
||||
@@ -134,6 +149,9 @@ public class GroupGeneralData {
|
||||
clientOptions.removeAll(clientMembers);
|
||||
}
|
||||
this.clientOptions = clientOptions;
|
||||
this.groupRoles = groupRoles;
|
||||
this.availableRoles = availableRoles;
|
||||
this.selectedRole = role;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
@@ -147,9 +165,16 @@ public class GroupGeneralData {
|
||||
public Long officeId() {
|
||||
return this.officeId;
|
||||
}
|
||||
|
||||
|
||||
public String getHierarchy() {
|
||||
return this.hierarchy;
|
||||
}
|
||||
|
||||
|
||||
public static GroupGeneralData updateSelectedRole(final GroupGeneralData grouping, final GroupRoleData selectedRole) {
|
||||
return new GroupGeneralData(grouping.id, grouping.name, grouping.externalId, grouping.status, grouping.activationDate,
|
||||
grouping.officeId, grouping.officeName, grouping.centerId, grouping.centerName, grouping.staffId, grouping.staffName,
|
||||
grouping.hierarchy, grouping.clientMembers, grouping.centerOptions, grouping.officeOptions, grouping.staffOptions,
|
||||
grouping.clientOptions, grouping.groupRoles, grouping.availableRoles, selectedRole);
|
||||
}
|
||||
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package org.mifosplatform.portfolio.group.data;
|
||||
|
||||
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
|
||||
|
||||
public class GroupRoleData {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final Long id;
|
||||
@SuppressWarnings("unused")
|
||||
private final CodeValueData role;
|
||||
@SuppressWarnings("unused")
|
||||
private final Long clientId;
|
||||
@SuppressWarnings("unused")
|
||||
private final String clientName;
|
||||
|
||||
public static final GroupRoleData template() {
|
||||
return new GroupRoleData(null, null, null, null);
|
||||
}
|
||||
|
||||
public GroupRoleData(final Long id, final CodeValueData role, final Long clientId, final String clientName) {
|
||||
this.id = id;
|
||||
this.role = role;
|
||||
this.clientId = clientId;
|
||||
this.clientName = clientName;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -107,11 +107,13 @@ public final class Group extends AbstractPersistable<Long> {
|
||||
final Set<Client> clientMembers, final Set<Group> groupMembers) {
|
||||
|
||||
GroupingTypeStatus status = GroupingTypeStatus.PENDING;
|
||||
LocalDate groupActivationDate = null;
|
||||
if (active) {
|
||||
status = GroupingTypeStatus.ACTIVE;
|
||||
groupActivationDate = activationDate;//set activation date only if group is made active
|
||||
}
|
||||
|
||||
return new Group(office, staff, parent, groupLevel, name, externalId, status, activationDate, clientMembers, groupMembers);
|
||||
return new Group(office, staff, parent, groupLevel, name, externalId, status, groupActivationDate, clientMembers, groupMembers);
|
||||
}
|
||||
|
||||
public Group(final Office office, final Staff staff, final Group parent, final GroupLevel groupLevel, final String name,
|
||||
@@ -370,4 +372,8 @@ public final class Group extends AbstractPersistable<Long> {
|
||||
public void setParent(final Group parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public Office getOffice() {
|
||||
return this.office;
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package org.mifosplatform.portfolio.group.domain;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.portfolio.client.domain.Client;
|
||||
import org.mifosplatform.portfolio.group.api.GroupingTypesApiConstants;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_group_roles")
|
||||
public class GroupRole extends AbstractPersistable<Long> {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "group_id")
|
||||
private Group group;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "client_id")
|
||||
private Client client;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "role_cv_id")
|
||||
private CodeValue role;
|
||||
|
||||
public GroupRole() {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public static final GroupRole createGroupRole(final Group group, final Client client, final CodeValue role) {
|
||||
return new GroupRole(group, client, role);
|
||||
}
|
||||
|
||||
public GroupRole(final Group group, final Client client, final CodeValue role) {
|
||||
this.group = group;
|
||||
this.client = client;
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(2);
|
||||
|
||||
if (command.isChangeInLongParameterNamed(GroupingTypesApiConstants.clientIdParamName, this.client.getId())) {
|
||||
final Long newValue = command.longValueOfParameterNamed(GroupingTypesApiConstants.clientIdParamName);
|
||||
actualChanges.put(GroupingTypesApiConstants.clientIdParamName, newValue);
|
||||
}
|
||||
|
||||
if (command.isChangeInLongParameterNamed(GroupingTypesApiConstants.roleParamName, this.role.getId())) {
|
||||
final Long newValue = command.longValueOfParameterNamed(GroupingTypesApiConstants.roleParamName);
|
||||
actualChanges.put(GroupingTypesApiConstants.roleParamName, newValue);
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
public void updateRole(final CodeValue role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public void updateClient(final Client client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package org.mifosplatform.portfolio.group.domain;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface GroupRoleRepository extends JpaRepository<GroupRole, Long>, JpaSpecificationExecutor<GroupRole> {
|
||||
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package org.mifosplatform.portfolio.group.domain;
|
||||
|
||||
import org.mifosplatform.portfolio.group.exception.GroupRoleNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class GroupRoleRepositoryWrapper {
|
||||
|
||||
private final GroupRoleRepository repository;
|
||||
|
||||
@Autowired
|
||||
public GroupRoleRepositoryWrapper(final GroupRoleRepository rRepository) {
|
||||
this.repository = rRepository;
|
||||
}
|
||||
|
||||
public GroupRole findOneWithNotFoundDetection(final Long id) {
|
||||
final GroupRole entity = this.repository.findOne(id);
|
||||
if (entity == null) { throw new GroupRoleNotFoundException(id); }
|
||||
return entity;
|
||||
}
|
||||
|
||||
public void save(final GroupRole entity) {
|
||||
this.repository.save(entity);
|
||||
}
|
||||
|
||||
public void saveAndFlush(final GroupRole entity) {
|
||||
this.repository.saveAndFlush(entity);
|
||||
}
|
||||
|
||||
public void delete(final GroupRole entity) {
|
||||
this.repository.delete(entity);
|
||||
}
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package org.mifosplatform.portfolio.group.exception;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
|
||||
public class GroupRoleNotFoundException extends AbstractPlatformResourceNotFoundException {
|
||||
|
||||
public GroupRoleNotFoundException(final Long id) {
|
||||
super("error.msg.group.role.id.invalid", "Group Role with identifier " + id + " does not exist", id);
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package org.mifosplatform.portfolio.group.handler;
|
||||
|
||||
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.portfolio.group.service.GroupRolesWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class AssignRoleCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final GroupRolesWritePlatformService groupRolesWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
public AssignRoleCommandHandler(final GroupRolesWritePlatformService groupRolesWritePlatformService) {
|
||||
this.groupRolesWritePlatformService = groupRolesWritePlatformService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
return this.groupRolesWritePlatformService.createRole(command);
|
||||
}
|
||||
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package org.mifosplatform.portfolio.group.handler;
|
||||
|
||||
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.portfolio.group.service.GroupRolesWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class UnassignRoleCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final GroupRolesWritePlatformService groupRolesWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
public UnassignRoleCommandHandler(final GroupRolesWritePlatformService groupRolesWritePlatformService) {
|
||||
this.groupRolesWritePlatformService = groupRolesWritePlatformService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CommandProcessingResult processCommand(JsonCommand command) {
|
||||
return this.groupRolesWritePlatformService.deleteRole(command.entityId());
|
||||
}
|
||||
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package org.mifosplatform.portfolio.group.handler;
|
||||
|
||||
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.portfolio.group.service.GroupRolesWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class UpdateGroupRoleCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final GroupRolesWritePlatformService groupRolesWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
public UpdateGroupRoleCommandHandler(final GroupRolesWritePlatformService groupRolesWritePlatformService) {
|
||||
this.groupRolesWritePlatformService = groupRolesWritePlatformService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CommandProcessingResult processCommand(JsonCommand command) {
|
||||
return this.groupRolesWritePlatformService.updateRole(command);
|
||||
}
|
||||
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
package org.mifosplatform.portfolio.group.serialization;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.mifosplatform.portfolio.group.api.GroupingTypesApiConstants;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
@Component
|
||||
public class GroupRolesDataValidator {
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@Autowired
|
||||
public GroupRolesDataValidator(final FromJsonHelper fromApiJsonHelper) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
|
||||
public void validateForCreateGroupRole(final JsonCommand command) {
|
||||
|
||||
final String json = command.json();
|
||||
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper
|
||||
.checkForUnsupportedParameters(typeOfMap, json, GroupingTypesApiConstants.GROUP_ROLES_REQUEST_DATA_PARAMETERS);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(GroupingTypesApiConstants.GROUP_ROLE_RESOURCE_NAME);
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
|
||||
final Long roleId = this.fromApiJsonHelper.extractLongNamed(GroupingTypesApiConstants.roleParamName, element);
|
||||
baseDataValidator.reset().parameter(GroupingTypesApiConstants.roleParamName).value(roleId).notNull().longGreaterThanZero();
|
||||
|
||||
final Long clientId = this.fromApiJsonHelper.extractLongNamed(GroupingTypesApiConstants.clientIdParamName, element);
|
||||
baseDataValidator.reset().parameter(GroupingTypesApiConstants.clientIdParamName).value(clientId).notNull().longGreaterThanZero();
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
public void validateForUpdateRole(final JsonCommand command) {
|
||||
final String json = command.json();
|
||||
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper
|
||||
.checkForUnsupportedParameters(typeOfMap, json, GroupingTypesApiConstants.GROUP_ROLES_REQUEST_DATA_PARAMETERS);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(GroupingTypesApiConstants.GROUP_ROLE_RESOURCE_NAME);
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
|
||||
final Long roleId = this.fromApiJsonHelper.extractLongNamed(GroupingTypesApiConstants.roleParamName, element);
|
||||
baseDataValidator.reset().parameter(GroupingTypesApiConstants.roleParamName).value(roleId).ignoreIfNull().notBlank()
|
||||
.longGreaterThanZero();
|
||||
|
||||
final Long clientId = this.fromApiJsonHelper.extractLongNamed(GroupingTypesApiConstants.clientIdParamName, element);
|
||||
baseDataValidator.reset().parameter(GroupingTypesApiConstants.clientIdParamName).value(clientId).ignoreIfNull().notBlank()
|
||||
.longGreaterThanZero();
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -323,7 +323,7 @@ public class CenterReadPlatformServiceImpl implements CenterReadPlatformService
|
||||
}
|
||||
|
||||
return GroupGeneralData.template(centerOfficeId, center.getId(), center.getName(), staffId, staffName, centerOptions,
|
||||
officeOptions, staffOptions, clientOptions);
|
||||
officeOptions, staffOptions, clientOptions, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ import org.mifosplatform.portfolio.group.data.GroupGeneralData;
|
||||
|
||||
public interface GroupReadPlatformService {
|
||||
|
||||
GroupGeneralData retrieveTemplate(Long officeId, boolean isCenterGroup);
|
||||
GroupGeneralData retrieveTemplate(Long officeId, boolean isCenterGroup, boolean staffInSelectedOfficeOnly);
|
||||
|
||||
Page<GroupGeneralData> retrieveAll(SearchParameters searchParameters);
|
||||
|
||||
|
||||
+29
-10
@@ -12,6 +12,8 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
|
||||
import org.mifosplatform.infrastructure.codes.service.CodeValueReadPlatformService;
|
||||
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
|
||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||
import org.mifosplatform.infrastructure.core.service.Page;
|
||||
@@ -25,6 +27,7 @@ import org.mifosplatform.organisation.staff.service.StaffReadPlatformService;
|
||||
import org.mifosplatform.portfolio.client.data.ClientData;
|
||||
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
|
||||
import org.mifosplatform.portfolio.client.service.LoanStatusMapper;
|
||||
import org.mifosplatform.portfolio.group.api.GroupingTypesApiConstants;
|
||||
import org.mifosplatform.portfolio.group.data.CenterData;
|
||||
import org.mifosplatform.portfolio.group.data.GroupAccountSummaryCollectionData;
|
||||
import org.mifosplatform.portfolio.group.data.GroupAccountSummaryData;
|
||||
@@ -48,6 +51,7 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
|
||||
private final OfficeReadPlatformService officeReadPlatformService;
|
||||
private final StaffReadPlatformService staffReadPlatformService;
|
||||
private final CenterReadPlatformService centerReadPlatformService;
|
||||
private final CodeValueReadPlatformService codeValueReadPlatformService;
|
||||
|
||||
private final AllGroupTypesDataMapper allGroupTypesDataMapper = new AllGroupTypesDataMapper();
|
||||
private final PaginationHelper<GroupGeneralData> paginationHelper = new PaginationHelper<GroupGeneralData>();
|
||||
@@ -55,17 +59,19 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
|
||||
@Autowired
|
||||
public GroupReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource,
|
||||
final CenterReadPlatformService centerReadPlatformService, final ClientReadPlatformService clientReadPlatformService,
|
||||
final OfficeReadPlatformService officeReadPlatformService, final StaffReadPlatformService staffReadPlatformService) {
|
||||
final OfficeReadPlatformService officeReadPlatformService, final StaffReadPlatformService staffReadPlatformService,
|
||||
final CodeValueReadPlatformService codeValueReadPlatformService) {
|
||||
this.context = context;
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
this.centerReadPlatformService = centerReadPlatformService;
|
||||
this.clientReadPlatformService = clientReadPlatformService;
|
||||
this.officeReadPlatformService = officeReadPlatformService;
|
||||
this.staffReadPlatformService = staffReadPlatformService;
|
||||
this.codeValueReadPlatformService = codeValueReadPlatformService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupGeneralData retrieveTemplate(final Long officeId, final boolean isCenterGroup) {
|
||||
public GroupGeneralData retrieveTemplate(final Long officeId, final boolean isCenterGroup, final boolean staffInSelectedOfficeOnly) {
|
||||
|
||||
final Long defaultOfficeId = defaultToUsersOfficeIfNull(officeId);
|
||||
|
||||
@@ -75,7 +81,16 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
|
||||
}
|
||||
|
||||
final Collection<OfficeData> officeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
|
||||
Collection<StaffData> staffOptions = this.staffReadPlatformService.retrieveAllStaffForDropdown(defaultOfficeId);
|
||||
|
||||
final boolean loanOfficersOnly = false;
|
||||
Collection<StaffData> staffOptions = null;
|
||||
if (staffInSelectedOfficeOnly) {
|
||||
staffOptions = this.staffReadPlatformService.retrieveAllStaffForDropdown(defaultOfficeId);
|
||||
} else {
|
||||
staffOptions = this.staffReadPlatformService.retrieveAllStaffInOfficeAndItsParentOfficeHierarchy(defaultOfficeId,
|
||||
loanOfficersOnly);
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(staffOptions)) {
|
||||
staffOptions = null;
|
||||
}
|
||||
@@ -85,13 +100,16 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
|
||||
clientOptions = null;
|
||||
}
|
||||
|
||||
final Collection<CodeValueData> availableRoles = this.codeValueReadPlatformService
|
||||
.retrieveCodeValuesByCode(GroupingTypesApiConstants.GROUP_ROLE_NAME);
|
||||
|
||||
final Long centerId = null;
|
||||
final String centerName = null;
|
||||
final Long staffId = null;
|
||||
final String staffName = null;
|
||||
|
||||
return GroupGeneralData.template(defaultOfficeId, centerId, centerName, staffId, staffName, centerOptions, officeOptions,
|
||||
staffOptions, clientOptions);
|
||||
staffOptions, clientOptions, availableRoles);
|
||||
}
|
||||
|
||||
private Long defaultToUsersOfficeIfNull(final Long officeId) {
|
||||
@@ -105,11 +123,11 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
|
||||
@Override
|
||||
public Page<GroupGeneralData> retrieveAll(final SearchParameters searchParameters) {
|
||||
|
||||
final AppUser currentUser = context.authenticatedUser();
|
||||
final AppUser currentUser = this.context.authenticatedUser();
|
||||
final String hierarchy = currentUser.getOffice().getHierarchy();
|
||||
final String hierarchySearchString = hierarchy + "%";
|
||||
|
||||
StringBuilder sqlBuilder = new StringBuilder(200);
|
||||
final StringBuilder sqlBuilder = new StringBuilder(200);
|
||||
sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
|
||||
sqlBuilder.append(this.allGroupTypesDataMapper.schema());
|
||||
sqlBuilder.append(" where o.hierarchy like ?");
|
||||
@@ -181,13 +199,13 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
|
||||
public GroupGeneralData retrieveOne(final Long groupId) {
|
||||
|
||||
try {
|
||||
final AppUser currentUser = context.authenticatedUser();
|
||||
final AppUser currentUser = this.context.authenticatedUser();
|
||||
final String hierarchy = currentUser.getOffice().getHierarchy();
|
||||
final String hierarchySearchString = hierarchy + "%";
|
||||
|
||||
String sql = "select " + this.allGroupTypesDataMapper.schema() + " where g.id = ? and o.hierarchy like ?";
|
||||
final String sql = "select " + this.allGroupTypesDataMapper.schema() + " where g.id = ? and o.hierarchy like ?";
|
||||
return this.jdbcTemplate.queryForObject(sql, this.allGroupTypesDataMapper, new Object[] { groupId, hierarchySearchString });
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
} catch (final EmptyResultDataAccessException e) {
|
||||
throw new GroupNotFoundException(groupId);
|
||||
}
|
||||
}
|
||||
@@ -283,7 +301,8 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
|
||||
|
||||
final StringBuilder accountsSummary = new StringBuilder("l.id as id, l.external_id as externalId,");
|
||||
accountsSummary.append("l.product_id as productId, lp.name as productName,").append("l.loan_status_id as statusId, ")
|
||||
.append("l.account_no as accountNo ").append("from m_loan l ").append("LEFT JOIN m_product_loan AS lp ON lp.id = l.product_id ");
|
||||
.append("l.account_no as accountNo ").append("from m_loan l ")
|
||||
.append("LEFT JOIN m_product_loan AS lp ON lp.id = l.product_id ");
|
||||
|
||||
return accountsSummary.toString();
|
||||
}
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package org.mifosplatform.portfolio.group.service;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.mifosplatform.portfolio.group.data.GroupRoleData;
|
||||
|
||||
public interface GroupRolesReadPlatformService {
|
||||
|
||||
Collection<GroupRoleData> retrieveGroupRoles(Long groupId);
|
||||
|
||||
GroupRoleData retrieveGroupRole(Long groupId, Long roleId);
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package org.mifosplatform.portfolio.group.service;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
|
||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.mifosplatform.portfolio.group.data.GroupRoleData;
|
||||
import org.mifosplatform.portfolio.group.exception.GroupRoleNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class GroupRolesReadPlatformServiceImpl implements GroupRolesReadPlatformService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final PlatformSecurityContext context;
|
||||
|
||||
@Autowired
|
||||
public GroupRolesReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource) {
|
||||
this.context = context;
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<GroupRoleData> retrieveGroupRoles(final Long groupId) {
|
||||
this.context.authenticatedUser();
|
||||
final GroupRolesDataMapper mapper = new GroupRolesDataMapper();
|
||||
final String sql = "Select " + mapper.schema() + " where role.group_id=?";
|
||||
return this.jdbcTemplate.query(sql, mapper, new Object[] { groupId });
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupRoleData retrieveGroupRole(final Long groupId, final Long roleId) {
|
||||
try {
|
||||
this.context.authenticatedUser();
|
||||
final GroupRolesDataMapper mapper = new GroupRolesDataMapper();
|
||||
final String sql = "Select " + mapper.schema() + " where role.group_id=? and role.id=?";
|
||||
return this.jdbcTemplate.queryForObject(sql, mapper, new Object[] { groupId, roleId });
|
||||
} catch (final EmptyResultDataAccessException e) {
|
||||
throw new GroupRoleNotFoundException(roleId);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class GroupRolesDataMapper implements RowMapper<GroupRoleData> {
|
||||
|
||||
public final String schema() {
|
||||
return " role.id AS id, role.client_id AS clientId, c.display_name as clientName, role.role_cv_id AS roleId, cv.code_value AS roleName"
|
||||
+ " from m_code_value cv join m_group_roles role on role.role_cv_id = cv.id left join m_client c on c.id = role.client_id ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupRoleData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
final Long id = JdbcSupport.getLong(rs, "id");
|
||||
final Long clientId = JdbcSupport.getLong(rs, "clientId");
|
||||
final String clientName = rs.getString("clientName");
|
||||
final Long roleId = JdbcSupport.getLong(rs, "roleId");
|
||||
final String roleName = rs.getString("roleName");
|
||||
final CodeValueData role = CodeValueData.instance(roleId, roleName);
|
||||
return new GroupRoleData(id, role, clientId, clientName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package org.mifosplatform.portfolio.group.service;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
|
||||
|
||||
public interface GroupRolesWritePlatformService {
|
||||
|
||||
CommandProcessingResult createRole(JsonCommand command);
|
||||
|
||||
CommandProcessingResult updateRole(JsonCommand command);
|
||||
|
||||
CommandProcessingResult deleteRole(Long ruleId);
|
||||
|
||||
}
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
package org.mifosplatform.portfolio.group.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
|
||||
import org.mifosplatform.infrastructure.codes.domain.CodeValueRepositoryWrapper;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.mifosplatform.portfolio.client.domain.Client;
|
||||
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
|
||||
import org.mifosplatform.portfolio.group.api.GroupingTypesApiConstants;
|
||||
import org.mifosplatform.portfolio.group.domain.Group;
|
||||
import org.mifosplatform.portfolio.group.domain.GroupRepositoryWrapper;
|
||||
import org.mifosplatform.portfolio.group.domain.GroupRole;
|
||||
import org.mifosplatform.portfolio.group.domain.GroupRoleRepositoryWrapper;
|
||||
import org.mifosplatform.portfolio.group.exception.ClientNotInGroupException;
|
||||
import org.mifosplatform.portfolio.group.serialization.GroupRolesDataValidator;
|
||||
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;
|
||||
|
||||
@Service
|
||||
public class GroupRolesWritePlatformServiceJpaRepositoryImpl implements GroupRolesWritePlatformService {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(GroupRolesWritePlatformServiceJpaRepositoryImpl.class);
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final GroupRepositoryWrapper groupRepository;
|
||||
private final GroupRolesDataValidator fromApiJsonDeserializer;
|
||||
private final CodeValueRepositoryWrapper codeValueRepository;
|
||||
private final ClientRepositoryWrapper clientRepository;
|
||||
private final GroupRoleRepositoryWrapper groupRoleRepository;
|
||||
|
||||
@Autowired
|
||||
public GroupRolesWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||
final GroupRepositoryWrapper groupRepository, final GroupRolesDataValidator fromApiJsonDeserializer,
|
||||
final CodeValueRepositoryWrapper codeValueRepository, final ClientRepositoryWrapper clientRepository,
|
||||
final GroupRoleRepositoryWrapper groupRoleRepository) {
|
||||
this.context = context;
|
||||
this.groupRepository = groupRepository;
|
||||
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
||||
this.codeValueRepository = codeValueRepository;
|
||||
this.clientRepository = clientRepository;
|
||||
this.groupRoleRepository = groupRoleRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult createRole(final JsonCommand command) {
|
||||
|
||||
try {
|
||||
this.context.authenticatedUser();
|
||||
this.fromApiJsonDeserializer.validateForCreateGroupRole(command);
|
||||
|
||||
final Long roleId = command.longValueOfParameterNamed(GroupingTypesApiConstants.roleParamName);
|
||||
final CodeValue role = this.codeValueRepository.findOneWithNotFoundDetection(roleId);
|
||||
|
||||
final Long clientId = command.longValueOfParameterNamed(GroupingTypesApiConstants.clientIdParamName);
|
||||
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
|
||||
|
||||
final Group group = this.groupRepository.findOneWithNotFoundDetection(command.getGroupId());
|
||||
if (!group.hasClientAsMember(client)) { throw new ClientNotInGroupException(clientId, command.getGroupId()); }
|
||||
final GroupRole groupRole = GroupRole.createGroupRole(group, client, role);
|
||||
this.groupRoleRepository.save(groupRole);
|
||||
return new CommandProcessingResultBuilder().withClientId(client.getId()).withGroupId(group.getId())
|
||||
.withEntityId(groupRole.getId()).build();
|
||||
|
||||
} catch (final DataIntegrityViolationException dve) {
|
||||
handleGroupDataIntegrityIssues(command, dve);
|
||||
return CommandProcessingResult.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void handleGroupDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) {
|
||||
final Throwable realCause = dve.getMostSpecificCause();
|
||||
|
||||
if (realCause.getMessage().contains("UNIQUE_GROUP_ROLES")) {
|
||||
final String clientId = command.stringValueOfParameterNamed(GroupingTypesApiConstants.clientIdParamName);
|
||||
final String roleId = command.stringValueOfParameterNamed(GroupingTypesApiConstants.roleParamName);
|
||||
final String errorMessageForUser = "Group Role with roleId `" + roleId + "`, clientId `" + clientId + "`, groupId `"
|
||||
+ command.getGroupId() + "` already exists.";
|
||||
final String errorMessageForMachine = "error.msg.group.role.already.exists";
|
||||
throw new PlatformDataIntegrityException(errorMessageForMachine, errorMessageForUser,
|
||||
GroupingTypesApiConstants.clientIdParamName, roleId, clientId, command.getGroupId());
|
||||
}
|
||||
|
||||
logger.error(dve.getMessage(), dve);
|
||||
throw new PlatformDataIntegrityException("error.msg.group.unknown.data.integrity.issue",
|
||||
"Unknown data integrity issue with resource.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult updateRole(final JsonCommand command) {
|
||||
try {
|
||||
this.context.authenticatedUser();
|
||||
this.fromApiJsonDeserializer.validateForUpdateRole(command);
|
||||
|
||||
final Group group = this.groupRepository.findOneWithNotFoundDetection(command.getGroupId());
|
||||
|
||||
final GroupRole groupRole = this.groupRoleRepository.findOneWithNotFoundDetection(command.entityId());
|
||||
final Map<String, Object> actualChanges = groupRole.update(command);
|
||||
|
||||
if (actualChanges.containsKey(GroupingTypesApiConstants.roleParamName)) {
|
||||
final Long newValue = command.longValueOfParameterNamed(GroupingTypesApiConstants.roleParamName);
|
||||
|
||||
CodeValue role = null;
|
||||
if (newValue != null) {
|
||||
role = this.codeValueRepository.findOneWithNotFoundDetection(newValue);
|
||||
}
|
||||
groupRole.updateRole(role);
|
||||
}
|
||||
|
||||
if (actualChanges.containsKey(GroupingTypesApiConstants.clientIdParamName)) {
|
||||
final Long newValue = command.longValueOfParameterNamed(GroupingTypesApiConstants.clientIdParamName);
|
||||
|
||||
Client client = null;
|
||||
if (newValue != null) {
|
||||
client = this.clientRepository.findOneWithNotFoundDetection(newValue);
|
||||
if (!group.hasClientAsMember(client)) { throw new ClientNotInGroupException(newValue, command.getGroupId()); }
|
||||
}
|
||||
groupRole.updateClient(client);
|
||||
}
|
||||
|
||||
this.groupRoleRepository.saveAndFlush(groupRole);
|
||||
return new CommandProcessingResultBuilder().with(actualChanges).withGroupId(group.getId()).withEntityId(groupRole.getId())
|
||||
.build();
|
||||
} catch (final DataIntegrityViolationException dve) {
|
||||
handleGroupDataIntegrityIssues(command, dve);
|
||||
return CommandProcessingResult.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult deleteRole(final Long ruleId) {
|
||||
this.context.authenticatedUser();
|
||||
final GroupRole groupRole = this.groupRoleRepository.findOneWithNotFoundDetection(ruleId);
|
||||
this.groupRoleRepository.delete(groupRole);
|
||||
return new CommandProcessingResultBuilder().withEntityId(groupRole.getId()).build();
|
||||
}
|
||||
|
||||
}
|
||||
+15
@@ -21,6 +21,7 @@ import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.mifosplatform.infrastructure.security.exception.PermissionDeniedException;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.mifosplatform.organisation.office.domain.Office;
|
||||
import org.mifosplatform.organisation.office.domain.OfficeRepository;
|
||||
@@ -45,6 +46,7 @@ import org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepository;
|
||||
import org.mifosplatform.portfolio.note.domain.Note;
|
||||
import org.mifosplatform.portfolio.note.domain.NoteRepository;
|
||||
import org.mifosplatform.useradministration.domain.AppUser;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -213,8 +215,21 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
||||
private CommandProcessingResult updateGroupingType(final Long groupId, final JsonCommand command, final GroupTypes groupingType) {
|
||||
|
||||
try {
|
||||
AppUser user = this.context.authenticatedUser();
|
||||
final Group groupForUpdate = this.groupRepository.findOneWithNotFoundDetection(groupId);
|
||||
final Long officeId = groupForUpdate.officeId();
|
||||
final Office groupOffice = groupForUpdate.getOffice();
|
||||
final String groupHierarchy = groupOffice.getHierarchy();
|
||||
|
||||
//Don't allow other office user to update
|
||||
final Office loginUserOffice = this.context.authenticatedUser().getOffice();
|
||||
final String userHierarchy = loginUserOffice.getHierarchy();
|
||||
|
||||
if (!groupHierarchy.startsWith(userHierarchy)) {
|
||||
final String code = "error.msg.not.enough.permissions.to.access.resource";
|
||||
final String defaultMessage = "The User with id "+user.getId()+" don't have permission to update this "+ groupingType.getValue();
|
||||
throw new PermissionDeniedException(code, defaultMessage, user.getId());
|
||||
}
|
||||
|
||||
final Map<String, Object> actualChanges = groupForUpdate.update(command);
|
||||
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ public class BulkLoansApiResource {
|
||||
StaffAccountSummaryCollectionData staffAccountSummaryCollectionData = null;
|
||||
|
||||
if (officeId != null) {
|
||||
loanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersByOffice(officeId);
|
||||
loanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersInOfficeById(officeId);
|
||||
}
|
||||
|
||||
if (loanOfficerId != null) {
|
||||
|
||||
+30
-5
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
package org.mifosplatform.portfolio.loanaccount.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
@@ -12,6 +13,7 @@ import java.util.Set;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
@@ -162,6 +164,7 @@ public class LoansApiResource {
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String template(@QueryParam("clientId") final Long clientId, @QueryParam("groupId") final Long groupId,
|
||||
@QueryParam("productId") final Long productId, @QueryParam("templateType") final String templateType,
|
||||
@DefaultValue("false") @QueryParam("staffInSelectedOfficeOnly") final boolean staffInSelectedOfficeOnly,
|
||||
@Context final UriInfo uriInfo) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions);
|
||||
@@ -223,7 +226,29 @@ public class LoansApiResource {
|
||||
throw new NotSupportedLoanTemplateTypeException(errorMsg, templateType);
|
||||
}
|
||||
|
||||
if (officeId != null) allowedLoanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersByOffice(officeId);
|
||||
if (officeId != null) {
|
||||
if (staffInSelectedOfficeOnly) {
|
||||
// only bring back loan officers in selected branch/office
|
||||
Collection<StaffData> loanOfficersInBranch = this.staffReadPlatformService
|
||||
.retrieveAllLoanOfficersInOfficeById(officeId);
|
||||
|
||||
if (!CollectionUtils.isEmpty(loanOfficersInBranch)) {
|
||||
allowedLoanOfficers = new ArrayList<StaffData>(loanOfficersInBranch);
|
||||
}
|
||||
} else {
|
||||
// by default bring back all loan officers in selected
|
||||
// branch/office as well as loan officers in officer above
|
||||
// this office
|
||||
final boolean restrictToLoanOfficersOnly = true;
|
||||
Collection<StaffData> loanOfficersInHierarchy = this.staffReadPlatformService
|
||||
.retrieveAllStaffInOfficeAndItsParentOfficeHierarchy(officeId, restrictToLoanOfficersOnly);
|
||||
|
||||
if (!CollectionUtils.isEmpty(loanOfficersInHierarchy)) {
|
||||
allowedLoanOfficers = new ArrayList<StaffData>(loanOfficersInHierarchy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add product options, allowed loan officers and calendar options
|
||||
// (calendar options will be null in individual loan)
|
||||
newLoanAccount = LoanAccountData.associationsAndTemplate(newLoanAccount, productOptions, allowedLoanOfficers, calendarOptions);
|
||||
@@ -336,9 +361,9 @@ public class LoansApiResource {
|
||||
chargeTemplate = this.loanChargeReadPlatformService.retrieveLoanChargeTemplate();
|
||||
|
||||
if (loanBasicDetails.officeId() != null) {
|
||||
allowedLoanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersByOffice(loanBasicDetails.officeId());
|
||||
allowedLoanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersInOfficeById(loanBasicDetails.officeId());
|
||||
} else if (loanBasicDetails.groupOfficeId() != null) {
|
||||
allowedLoanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersByOffice(loanBasicDetails.groupOfficeId());
|
||||
allowedLoanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersInOfficeById(loanBasicDetails.groupOfficeId());
|
||||
}
|
||||
|
||||
loanPurposeOptions = this.codeValueReadPlatformService.retrieveCodeValuesByCode("LoanPurpose");
|
||||
@@ -492,8 +517,8 @@ public class LoansApiResource {
|
||||
// for officeId and loanOfficerId in current way!
|
||||
final LoanAccountData loanBasicDetails = this.loanReadPlatformService.retrieveOne(loanId);
|
||||
|
||||
final Collection<StaffData> allowedLoanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersByOffice(loanBasicDetails
|
||||
.officeId());
|
||||
final Collection<StaffData> allowedLoanOfficers = this.staffReadPlatformService
|
||||
.retrieveAllLoanOfficersInOfficeById(loanBasicDetails.officeId());
|
||||
final Long fromLoanOfficerId = loanBasicDetails.loanOfficerId();
|
||||
|
||||
final BulkTransferLoanOfficerData loanReassignmentData = BulkTransferLoanOfficerData.template(fromLoanOfficerId,
|
||||
|
||||
+3
@@ -20,6 +20,7 @@ import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
@@ -152,6 +153,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
if (loanProduct == null) { throw new LoanProductNotFoundException(productId); }
|
||||
|
||||
this.loanProductCommandFromApiJsonDeserializer.validateMinMaxConstraints(command.parsedJson(), baseDataValidator, loanProduct);
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
|
||||
// validate dates against calendar recurring dates
|
||||
// get calendar
|
||||
|
||||
+2
-2
@@ -279,7 +279,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
// get group associations
|
||||
Collection<ClientData> membersOfGroup = this.clientReadPlatformService.retrieveClientMembersOfGroup(groupId);
|
||||
if (!CollectionUtils.isEmpty(membersOfGroup)) {
|
||||
groupAccount = GroupGeneralData.withAssocations(groupAccount, membersOfGroup);
|
||||
groupAccount = GroupGeneralData.withAssocations(groupAccount, membersOfGroup, null);
|
||||
}
|
||||
|
||||
final LocalDate expectedDisbursementDate = DateUtils.getLocalDateOfTenant();
|
||||
@@ -938,7 +938,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
// get group associations
|
||||
Collection<ClientData> membersOfGroup = this.clientReadPlatformService.retrieveClientMembersOfGroup(groupId);
|
||||
if (!CollectionUtils.isEmpty(membersOfGroup)) {
|
||||
groupAccount = GroupGeneralData.withAssocations(groupAccount, membersOfGroup);
|
||||
groupAccount = GroupGeneralData.withAssocations(groupAccount, membersOfGroup, null);
|
||||
}
|
||||
|
||||
return LoanAccountData.groupDefaults(groupAccount, expectedDisbursementDate);
|
||||
|
||||
+10
-1
@@ -450,7 +450,16 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final String noteText = command.stringValueOfParameterNamed("note");
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
changes.put("note", noteText);
|
||||
Note note = Note.loanTransactionNote(loan, newTransactionDetail, noteText);
|
||||
Note note = null;
|
||||
/**
|
||||
* If a new transaction is not created, associate note with the
|
||||
* transaction to be adjusted
|
||||
**/
|
||||
if (newTransactionDetail.isGreaterThanZero(loan.getPrincpal().getCurrency())) {
|
||||
note = Note.loanTransactionNote(loan, newTransactionDetail, noteText);
|
||||
} else {
|
||||
note = Note.loanTransactionNote(loan, transactionToAdjust, noteText);
|
||||
}
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -183,7 +183,7 @@ public class SavingsAccountDataValidator {
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) {
|
||||
final BigDecimal annualFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).notNull().positiveAmount();
|
||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).positiveAmount();
|
||||
|
||||
if (annualFeeAmount != null) {
|
||||
MonthDay monthDayOfAnnualFee = fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
|
||||
|
||||
+3
-3
@@ -621,7 +621,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
break;
|
||||
case ANNUAL:
|
||||
periodEndDate = periodStartDate.monthOfYear().withMaximumValue();
|
||||
periodEndDate = periodStartDate.dayOfMonth().withMaximumValue();
|
||||
periodEndDate = periodEndDate.dayOfMonth().withMaximumValue();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -680,11 +680,11 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
break;
|
||||
case ANNUAL:
|
||||
periodEndDate = periodStartDate.monthOfYear().withMaximumValue();
|
||||
periodEndDate = periodStartDate.dayOfMonth().withMaximumValue();
|
||||
periodEndDate = periodEndDate.dayOfMonth().withMaximumValue();
|
||||
break;
|
||||
case NO_COMPOUNDING_SIMPLE_INTEREST:
|
||||
periodEndDate = periodStartDate.monthOfYear().withMaximumValue();
|
||||
periodEndDate = periodStartDate.dayOfMonth().withMaximumValue();
|
||||
periodEndDate = periodEndDate.dayOfMonth().withMaximumValue();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user