MIFOSX-290: update api docs and refactor READ side of center, group underneath api.

This commit is contained in:
Keith Woodlock
2013-04-14 13:13:02 +01:00
parent e777491d76
commit 654b31f75e
30 changed files with 1935 additions and 1226 deletions
+626 -212
View File
@@ -228,7 +228,7 @@
</div>
</div>
<div class="flybar-nav">
<h2 class="flybar-button">Group</h2>
<h2 class="flybar-button">Groupings</h2>
<div id="toc-menu-group" class="flybar-menu">
<div class="tocMatrix">
<table class=matrixHeading>
@@ -274,6 +274,22 @@
</tr>
</table></td>
</tr>
<tr class="alt">
<td><a href="#centers">Center</a></td>
<td>centers</td>
<td><a href="#centers_create">Create a Center</a></td>
<td><a href="#centers_list">List Centers</a></td>
<td></td>
<td><a href="#centers_delete">Delete a Center</a></td>
</tr>
<tr>
<td></td>
<td>centers/{centerId}</td>
<td></td>
<td><a href="#centers_retrieve">Retrieve a Center</a></td>
<td><a href="#centers_update">Update a Center</a></td>
<td></td>
</tr>
<tr class="alt">
<td><a href="#groups">Group</a></td>
<td>groups</td>
@@ -290,35 +306,12 @@
<td><a href="#groups_update">Update a Group</a></td>
<td></td>
</tr>
<tr class="alt">
<td></td>
<td>groups/{group}/loans</td>
<td></td>
<td><a href="#groups_loansummary">Retrieve a Group's
Loan Account Summary</a></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>groups/{group}/command/assign_loanofficer</td>
<td><a href="#groups_assignlo">Assign a Loan Officer</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class="alt">
<td></td>
<td>groups/{group}/command/unassign_loanofficer</td>
<td><a href="#groups_unassign_lo">Unassign a Loan Officer</a></td>
<td></a></td>
<td></td>
<td></td>
</tr>
</table>
</div>
</div>
</div>
<div class="flybar-nav">
<h2 class="flybar-button">Loan</h2>
<div id="toc-menu-loan" class="flybar-menu">
@@ -1317,6 +1310,14 @@
</tr>
</table></td>
</tr>
<tr class="alt">
<td>centers/template</td>
<td><a href="#centers_template">Retrieve Center Template</a></td>
</tr>
<tr>
<td>groups/template</td>
<td><a href="#groups_template">Retrieve Group Template</a></td>
</tr>
<tr class="alt">
<td>clients/template</td>
<td><a href="#clients_template">Retrieve Client Template</a></td>
@@ -2579,54 +2580,460 @@ No Request Body:
</div>
</div>
<!-- Start of Administrative Units API-->
<a id="centers" name="centers" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h3>Centers</h3>
<p><b>Centers</b> along with <b>Groups</b> are used to provided a distinctive banking distribution channel used in microfinance. Its common in areas such as India to use Centers and Group administrative units in <b>grameen style lending</b>. Typically groups will contain one to five people and centers themselves will be made of anywhere between 2-7 groups.
</p>
<table class=matrixHeading>
<tr class="matrixHeadingBG">
<td><div class="mifosXHeading2">Field Descriptions</div></td>
</tr>
<tr class=alt>
<td>name</td>
</tr>
<tr>
<td class=fielddesc>Name given to the Center.</td>
</tr>
<tr class=alt>
<td>officeId</td>
</tr>
<tr>
<td class=fielddesc>The officeId of the office/branch this center is administrated through.</td>
</tr>
<tr class=alt>
<td>staffId</td>
</tr>
<tr>
<td class=fielddesc>The staffId of the staff member dealing with this center. The staff member is not specifically the loan officer.</td>
</tr>
<tr class=alt>
<td>externalId</td>
</tr>
<tr>
<td class=fielddesc>A place to put an external reference for this center e.g. The ID another system uses. If provided, it must be unique.
</td>
</tr>
</table>
</div>
</div>
<a id="centers_template" name="centers_template" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Retrieve a Center Template</h4>
<p>Example Requests:</p>
<div class=apiClick>centers/template</div>
<br/>
<div class=apiClick>centers/template?officeId=2</div>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/mifosng-provider/api/v1/centers/template
</code>
<code class="method-response">
{
"officeOptions": [
{
"id": 1,
"name": "Head Office",
"nameDecorated": "Head Office"
},
{
"id": 2,
"name": "Suboffice",
"nameDecorated": "....Suboffice"
}
],
"staffOptions": [
{
"id": 1,
"displayName": "LoanOfficer, HeadOffice"
},
{
"id": 2,
"displayName": "NonLoanOfficer, HeadOffice"
}
]
}
</code>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/mifosng-provider/api/v1/centers/template?officeId=2
</code>
<code class="method-response">
{
"officeId": 2,
"officeOptions": [
{
"id": 1,
"name": "Head Office",
"nameDecorated": "Head Office"
},
{
"id": 2,
"name": "Suboffice",
"nameDecorated": "....Suboffice"
}
],
"staffOptions": [
{
"id": 3,
"displayName": "LoanOfficer, Suboffice"
},
{
"id": 4,
"displayName": "NonLoanOfficer, Suboffice"
}
]
}
</code>
</div>
</div>
<a id="centers_create" name="centers_create" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Create a Center</h4>
<table class=matrixHeading>
<tr class="matrixHeadingBG">
<td><div class="mifosXHeading2">Mandatory Fields</div></td>
</tr>
<tr class=alt>
<td>name, officeId</td>
</tr>
</table>
<br/>
<table class=matrixHeading>
<tr class="matrixHeadingBG">
<td><div class="mifosXHeading2">Optional Fields</div></td>
</tr>
<tr class=alt>
<td>externalId, staffId</td>
</tr>
</table>
</div>
<div class="method-example">
<code class="method-declaration">
POST https://DomainName/mifosng-provider/api/v1/centers
</code>
<code class="method-request">
POST centers
Content-Type: application/json Request Body:
{
"name": "apicenter",
"officeId": 2
}
</code>
<code class="method-response">
{
"officeId": 2,
"groupId": 4,
"resourceId": 4
}
</code>
</div>
</div>
<a id="centers_update" name="centers_update" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Update a Center</h4>
</div>
<div class="method-example">
<code class="method-declaration">
PUT https://DomainName/mifosng-provider/api/v1/centers/{centerId}
</code>
<code class="method-request">
PUT centers/4
Content-Type: application/json
Request Body:
{
"name": "apicenter(updated)"
}
</code>
<code class="method-response">
{
"officeId": 4,
"groupId": 2,
"resourceId": 4,
"changes": {
"name": "apicenter(updated)"
}
}
</code>
</div>
</div>
<a id="centers_delete" name="centers_delete" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Delete a Center</h4>
</div>
<div class="method-example">
<code class="method-declaration">
POST https://DomainName/mifosng-provider/api/v1/centers/{centerId}
</code>
<code class="method-request">
DELETE centers/1
</code>
<code class="method-response">
{
"resourceId":1,
"changes":{}
}
</code>
</div>
</div>
<a id="centers_list" name="centers_list" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>List Centers</h4>
<p>Example Requests:</p>
<div class=apiClick>centers</div>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/mifosng-provider/api/v1/centers
</code>
<code class="method-response">
[
{
"id": 1,
"name": "Center 001",
"externalId": "001",
"officeId": 1,
"officeName": "Head Office",
"hierarchy": ".1."
},
{
"id": 3,
"name": "Suboffice Center",
"externalId": "002",
"officeId": 2,
"officeName": "Suboffice",
"hierarchy": ".3."
}
]
</code>
</div>
</div>
<a id="centers_retrieve" name="centers_retrieve" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Retrieve a Center</h4>
<p>Example Requests:</p>
<div class=apiClick>centers/1</div>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/mifosng-provider/api/v1/centers/1
</code>
<code class="method-response">
{
"id": 1,
"name": "Center 001",
"externalId": "001",
"officeId": 1,
"officeName": "Head Office",
"hierarchy": ".1."
}
</code>
</div>
</div>
<!-- End of Centers API-->
<!-- start of Groups api docs -->
<a id="groups" name="groups" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h3>Groups</h3>
<p>Groups are collection of clients for specific purpose (JLG,SHG, Program etc) </p>
<p><b>Groups</b> are used to provide a distinctive banking distribution channel used in microfinance throughout the world. The Group is an administrative unit. It can contain as few as 5 people or as many as 40 depending on how its used.</p>
<p>Different styles of group lending - Joint-Liability Group, Grameen Model (Center-Group), Self-Help Groups, Village/Communal Banks)</p>
<table class=matrixHeading>
<tr class="matrixHeadingBG">
<td><div class="mifosXHeading2">Field Descriptions</div></td>
</tr>
<tr class=alt>
<td>office_id</td>
</tr>
<tr>
<td class=fielddesc>It stores the officeid of office, to this officer Group belongs.</td>
</tr>
<tr class=alt>
<td>loan_officer_id</td>
</tr>
<tr>
<td class=fielddesc>Id of the officer who manages this group.</td>
</tr>
<tr class=alt>
<td>name</td>
</tr>
<tr>
<td class=fielddesc>Human friendly identity of the Group (Name given to the group).</td>
<td class=fielddesc>Name given to the Group.</td>
</tr>
<tr class=alt>
<td>officeId</td>
</tr>
<tr>
<td class=fielddesc>The officeId of the office/branch this group is administrated through.</td>
</tr>
<tr class=alt>
<td>staffId</td>
</tr>
<tr>
<td class=fielddesc>The staffId of the staff member dealing with this group. The staff member is not specifically the loan officer.</td>
</tr>
<tr class=alt>
<td>externalId</td>
</tr>
<tr>
<td class=fielddesc>A place to put an external reference for
this group e.g. The ID another system uses.<br> If
provided, it must be unique.
<td class=fielddesc>A place to put an external reference for this group e.g. The ID another system uses. If provided, it must be unique.
</td>
</tr>
<tr class=alt>
<td>is_deleted</td>
<tr class=alt>
<td>clientMembers</td>
</tr>
<tr>
<td class=fielddesc>Indicator for active or archived groups.
</td>
<td class=fielddesc>The individual client members that make up the group.</td>
</tr>
</table>
</div>
</div>
<a id="groups_template" name="groups_template" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Retrieve Group Template</h4>
<p>Example Requests:</p>
<div class=apiClick>groups/template?centerId=1</div>
<br/>
<div class=apiClick>groups/template?officeId=2</div>
<br/>
<div class=apiClick>groups/template</div>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/mifosng-provider/api/v1/groups/template
</code>
<code class="method-response">
{
"officeId": 1,
"officeOptions": [
{
"id": 1,
"name": "Head Office",
"nameDecorated": "Head Office"
},
{
"id": 2,
"name": "Suboffice",
"nameDecorated": "....Suboffice"
}
],
"staffOptions": [
{
"id": 1,
"displayName": "LoanOfficer, HeadOffice"
},
{
"id": 2,
"displayName": "NonLoanOfficer, HeadOffice"
}
],
"clientOptions": [
{
"id": 1,
"displayName": "Test one",
"officeId": 1,
"officeName": "Head Office"
}
]
}
</code>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/mifosng-provider/api/v1/groups/template?officeId=2
</code>
<code class="method-response">
{
"officeId": 2,
"officeOptions": [
{
"id": 1,
"name": "Head Office",
"nameDecorated": "Head Office"
},
{
"id": 2,
"name": "Suboffice",
"nameDecorated": "....Suboffice"
}
],
"staffOptions": [
{
"id": 3,
"displayName": "LoanOfficer, Suboffice"
},
{
"id": 4,
"displayName": "NonLoanOfficer, Suboffice"
}
]
}
</code>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/mifosng-provider/api/v1/groups/template?centerId=1
</code>
<code class="method-response">
{
"officeId": 1,
"centerId": 1,
"centerName": "Center 001",
"centerOptions": [
{
"id": 1,
"name": "Center 001",
"externalId": "001",
"officeId": 1,
"officeName": "Head Office",
"hierarchy": ".1."
}
],
"officeOptions": [
{
"id": 1,
"name": "Head Office",
"nameDecorated": "Head Office",
"externalId": "1",
"openingDate": [
2009,
1,
1
],
"hierarchy": "."
}
],
"staffOptions": [
{
"id": 1,
"displayName": "LoanOfficer, HeadOffice"
},
{
"id": 2,
"displayName": "NonLoanOfficer, HeadOffice"
}
],
"clientOptions": [
{
"id": 1,
"displayName": "Test one",
"officeId": 1,
"officeName": "Head Office"
}
]
}
</code>
</div>
</div>
<a id="groups_create" name="groups_create" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
@@ -2636,32 +3043,51 @@ No Request Body:
<td><div class="mifosXHeading2">Mandatory Fields</div></td>
</tr>
<tr class=alt>
<td>name<br>
officeId<br>
clients
</td>
<td>name,officeId</td>
</tr>
</table>
<br/>
<table class=matrixHeading>
<tr class="matrixHeadingBG">
<td><div class="mifosXHeading2">Optional Fields</div></td>
</tr>
<tr class=alt>
<td>externalId,staffId,clientMembers</td>
</tr>
</table>
</div>
<div class="method-example">
<code class="method-declaration">
POST https://DomainName/mifosng-provider/api/v1/groups
POST https://DomainName/mifosng-provider/api/v1/groups
</code>
<code class="method-request">
POST groups
Content-Type: application/json Request Body:
{
"officeId":"1",
"name":"TA Group",
"externalId":"",
"clientMembers":["82","83","84"]
}
POST groups
Content-Type: application/json Request Body:
{
"officeId":"1",
"name":"TA Group"
}
</code>
<code class="method-request">
POST groups
Content-Type: application/json Request Body:
{
"officeId":"1",
"name":"TA Group"
"externalId": "000-1A",
"clientMembers": ["1"]
}
</code>
<code class="method-response">
{"resourceId":24,"changes":{}}
{
"officeId": 2,
"groupId": 5,
"resourceId": 5
}
</code>
</div>
</div>
<a id="groups_list" name="groups_list" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
@@ -2674,114 +3100,115 @@ No Request Body:
GET https://DomainName/mifosng-provider/api/v1/groups
</code>
<code class="method-response">
[{
"id": 1,
"name": "GWT_2",
"externalId": "GWT_EX_ID_2",
"officeId": 7,
"officeName": "Z2"
}, {
"id": 2,
"name": "group22",
"externalId": "11234",
[
{
"id": 10,
"name": "GroupU(Suboffice)",
"officeId": 2,
"officeName": "Suboffice",
"centerId": 4,
"centerName": "apicenter(updated)",
"hierarchy": ""
},
{
"id": 8,
"name": "AnothergroupUI",
"officeId": 1,
"officeName": "Head Office"
}, {
"id": 3,
"name": "PlusOne",
"officeId": 22,
"officeName": "North Point Office"
}]
"officeName": "Head Office",
"centerId": 1,
"centerName": "Center 001",
"hierarchy": ""
},
{
"id": 7,
"name": "NewGroupUI",
"externalId": "0011",
"officeId": 1,
"officeName": "Head Office",
"centerId": 1,
"centerName": "Center 001",
"staffId": 1,
"staffName": "LoanOfficer, HeadOffice",
"hierarchy": ""
},
{
"id": 9,
"name": "GroupUCenter",
"officeId": 1,
"officeName": "Head Office",
"centerId": 1,
"centerName": "Center 001",
"staffId": 1,
"staffName": "LoanOfficer, HeadOffice",
"hierarchy": ""
},
{
"id": 2,
"name": "Group 001-A",
"officeId": 1,
"officeName": "Head Office",
"centerId": 1,
"centerName": "Center 001",
"hierarchy": ""
},
{
"id": 11,
"name": "Test(no parents)",
"officeId": 1,
"officeName": "Head Office",
"hierarchy": ".11."
},
{
"id": 12,
"name": "SubofficeGroup(no parents)",
"officeId": 2,
"officeName": "Suboffice",
"hierarchy": ".12."
}
]
</code>
</div>
</div>
<a id="groups_retrieve" name="groups_retrieve"
class="old-syle-anchor">&nbsp;</a>
<a id="groups_retrieve" name="groups_retrieve" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Retrieve a Group</h4>
<p>Example Requests:</p>
<div class=apiClick>groups/10</div>
<div class=apiClick>groups/12</div>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/mifosng-provider/api/v1/groups/10
GET https://DomainName/mifosng-provider/api/v1/groups/12
</code>
<code class="method-response">
{
"id": 10,
"name": "test123",
"externalId": "tejjjst",
"officeId": 1,
"officeName": "Head Office",
"clientMembers": [{
"id": 1,
"displayName": "Willie O\u0027Meara"
}]
}
</code>
</div>
</div>
<a id="groups_loansummary" name="groups_loansummary"
class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Retrieve a Groups's Loan Account Summary</h4>
<p>
An example of how a loan portfolio summary can be provided. This
one contains quite a bit of redundant data (like the counts)
</p>
<p>Example Requests:</p>
<div class=apiClick>groups/7/loans</div>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/mifosng-provider/api/v1/groups/7/loans
</code>
<code class="method-response">
{
"anyLoanCount": 1,
"pendingApprovalLoanCount": 0,
"pendingApprovalLoans": [],
"awaitingDisbursalLoanCount": 0,
"awaitingDisbursalLoans": [],
"activeLoanCount": 1,
"openLoans": [{
"id": 79,
"productId": 1,
"productName": "1-PORetailLoan",
"accountStatusId": 300
}],
"closedLoanCount": 0,
"closedLoans": [],
"anyIndividualLoanCount": 3,
"pendingApprovalIndividualLoanCount": 0,
"pendingApprovalIndividualLoans": [],
"awaitingDisbursalIndividualLoanCount": 0,
"awaitingDisbursalIndividualLoans": [],
"activeIndividualLoanCount": 3,
"openIndividualLoans": [{
"id": 80,
"productId": 17,
"productName": "17-Intrasoft Business Loan",
"accountStatusId": 300
}, {
"id": 81,
"productId": 1,
"productName": "1-PORetailLoan",
"accountStatusId": 300
}, {
"id": 82,
"productId": 13,
"productName": "13-A Flat Loan",
"accountStatusId": 300
}],
"closedIndividualLoanCount": 0,
"closedIndividualLoans": []
"id": 12,
"name": "SubofficeGroup(no parents)",
"officeId": 2,
"officeName": "Suboffice",
"hierarchy": ".12.",
"clientMembers": [
{
"id": 2,
"accountNo": "000000002",
"firstname": "Another",
"lastname": "client",
"displayName": "Another client",
"officeId": 2,
"officeName": "Suboffice",
"joinedDate": [
2012,
4,
14
]
}
]
}
</code>
</div>
</div>
<a id="groups_update" name="groups_update" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
@@ -2792,75 +3219,27 @@ GET https://DomainName/mifosng-provider/api/v1/groups/7/loans
PUT https://DomainName/mifosng-provider/api/v1/groups/{groupid}
</code>
<code class="method-request">
PUT groups/7
PUT groups/5
Content-Type: application/json
Request Body:
{
"officeId": "26",
"name": "Laxmi SSG U",
"externalId": "Unq 2--124",
"clientMembers": ["91", "93", "94"]
"name": "apigroup(changed)"
}
</code>
<code class="method-response">
{
"resourceId":7,
"changes":{}
"officeId": 5,
"groupId": 2,
"resourceId": 5,
"changes": {
"name": "apigroup(changed)"
}
}
</code>
</div>
</div>
<a id="groups_assignlo" name="groups_assignlo" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Assign a Loan Officer to Group</h4>
</div>
<div class="method-example">
<code class="method-declaration">
POST https://DomainName/mifosng-provider/api/v1/groups/{groupid}/command/assign_loanofficer
</code>
<code class="method-request">
POST groups/20/command/assign_loanofficer
Content-Type: application/json
Request Body:
{
{"loanOfficerId":"1"}
}
</code>
<code class="method-response">
{
"resourceId":20,
"changes":{}
}
</code>
</div>
</div>
<a id="groups_unassign_lo" name="groups_unassign_lo" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Unassign a loan officer to a Group</h4>
</div>
<div class="method-example">
<code class="method-declaration">
POST https://DomainName/mifosng-provider/api/v1/groups/{groupid}/command/assign_loanofficer
</code>
<code class="method-request">
POST groups/20/command/unassign_loanofficer
Content-Type: application/json
Request Body:
{
{"loanOfficerId":"1"}
}
</code>
<code class="method-response">
{
"resourceId":20,
"changes":{}
}
</code>
</div>
</div>
<a id="groups_delete" name="groups_delete" class="old-syle-anchor">&nbsp;</a>
<a id="groups_delete" name="groups_delete" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Delete a Group</h4>
@@ -2870,12 +3249,13 @@ Request Body:
POST https://DomainName/mifosng-provider/api/v1/groups/{groupid}
</code>
<code class="method-request">
DELETE groups/7
DELETE groups/5
</code>
<code class="method-response">
{
"resourceId":7,
"changes":{}
"officeId": 5,
"groupId": 2,
"resourceId": 5
}
</code>
</div>
@@ -12385,6 +12765,40 @@ GET https://DomainName/api/v1/search?query=000000111
</td>
<td></td>
</tr>
<!-- centers groups -->
<tr class="alt">
<td><a href="#centers">Center</a></td>
<td>centers</td>
<td><a href="#centers_create">Create a Center</a></td>
<td><a href="#centers_list">List Centers</a></td>
<td></td>
<td><a href="#centers_delete">Delete a Center</a></td>
</tr>
<tr>
<td></td>
<td>centers/{centerId}</td>
<td></td>
<td><a href="#centers_retrieve">Retrieve a Center</a></td>
<td><a href="#centers_update">Update a Center</a></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><a href="#groups_delete">Delete a Group</a></td>
</tr>
<tr>
<td></td>
<td>groups/{group}</td>
<td></td>
<td><a href="#groups_retrieve">Retrieve a Group</a></td>
<td><a href="#groups_update">Update a Group</a></td>
<td></td>
</tr>
<!-- end of centers, groups api -->
<!-- loans api full matrix-->
<tr class="alt">
<td><a href="#loanproducts">Loan Product</a></td>
@@ -20,7 +20,7 @@ public class StaffData {
private final String displayName;
private final Long officeId;
private final String officeName;
private final boolean isLoanOfficer;
private final Boolean isLoanOfficer;
@SuppressWarnings("unused")
private final Collection<OfficeData> allowedOffices;
@@ -30,13 +30,17 @@ public class StaffData {
staff.isLoanOfficer, allowedOffices);
}
public static StaffData lookup(final Long id, final String displayName) {
return new StaffData(id, null, null, displayName, null, null, null, null);
}
public static StaffData instance(final Long id, final String firstname, final String lastname, final String displayName,
final Long officeId, final String officeName, final boolean isLoanOfficer) {
final Long officeId, final String officeName, final Boolean isLoanOfficer) {
return new StaffData(id, firstname, lastname, displayName, officeId, officeName, isLoanOfficer, null);
}
private StaffData(final Long id, final String firstname, final String lastname, final String displayName, final Long officeId,
final String officeName, final boolean isLoanOfficer, final Collection<OfficeData> allowedOffices) {
final String officeName, final Boolean isLoanOfficer, final Collection<OfficeData> allowedOffices) {
this.id = id;
this.firstname = firstname;
this.lastname = lastname;
@@ -47,40 +51,23 @@ public class StaffData {
this.allowedOffices = allowedOffices;
}
public Long getId() {
return this.id;
}
public String getFirstname() {
return this.firstname;
}
public String getLastname() {
return this.lastname;
}
public String getDisplayName() {
return this.displayName;
}
public Long getOfficeId() {
return this.officeId;
public String getFirstname() {
return this.firstname;
}
public String getLastname() {
return this.lastname;
}
public String getOfficeName() {
return this.officeName;
}
public boolean isLoanOfficer() {
return this.isLoanOfficer;
}
}
@@ -7,7 +7,6 @@ package org.mifosplatform.organisation.staff.service;
import java.util.Collection;
import org.mifosplatform.organisation.staff.data.StaffAccountSummaryCollectionData;
import org.mifosplatform.organisation.staff.data.StaffData;
public interface StaffReadPlatformService {
@@ -16,7 +15,7 @@ public interface StaffReadPlatformService {
Collection<StaffData> retrieveAllStaff(final String extraCriteria);
Collection<StaffData> retrieveAllLoanOfficersByOffice(final Long officeId);
Collection<StaffData> retrieveAllStaffForDropdown(Long officeId);
StaffAccountSummaryCollectionData retrieveLoanOfficerAccountSummary(final Long loanOfficerId);
Collection<StaffData> retrieveAllLoanOfficersByOffice(final Long officeId);
}
@@ -8,19 +8,12 @@ package org.mifosplatform.organisation.staff.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.staff.data.StaffAccountSummaryCollectionData;
import org.mifosplatform.organisation.staff.data.StaffData;
import org.mifosplatform.organisation.staff.exception.StaffNotFoundException;
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryData;
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
import org.mifosplatform.portfolio.group.data.GroupAccountSummaryData;
import org.mifosplatform.portfolio.group.service.GroupReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
@@ -32,16 +25,12 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService {
private final JdbcTemplate jdbcTemplate;
private final PlatformSecurityContext context;
private final ClientReadPlatformService clientReadPlatformService;
private final GroupReadPlatformService groupReadPlatformService;
private final StaffLookupMapper lookupMapper = new StaffLookupMapper();
@Autowired
public StaffReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource,
final ClientReadPlatformService clientReadPlatformService, final GroupReadPlatformService groupReadPlatformService) {
public StaffReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource) {
this.context = context;
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.clientReadPlatformService = clientReadPlatformService;
this.groupReadPlatformService = groupReadPlatformService;
}
private static final class StaffMapper implements RowMapper<StaffData> {
@@ -67,11 +56,36 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService {
}
}
private static final class StaffLookupMapper implements RowMapper<StaffData> {
private final String schemaSql;
public StaffLookupMapper() {
final StringBuilder sqlBuilder = new StringBuilder(100);
sqlBuilder.append("s.id as id, s.display_name as displayName ");
sqlBuilder.append("from m_staff s ");
this.schemaSql = sqlBuilder.toString();
}
public String schema() {
return this.schemaSql;
}
@Override
public StaffData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final String displayName = rs.getString("displayName");
return StaffData.lookup(id, displayName);
}
}
@Override
public Collection<StaffData> retrieveAllStaff(final String extraCriteria) {
context.authenticatedUser();
final StaffMapper rm = new StaffMapper();
String sql = "select " + rm.schema();
if (StringUtils.isNotBlank(extraCriteria)) {
@@ -86,6 +100,24 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService {
return retrieveAllStaff(" office_id=" + officeId + " and is_loan_officer=1");
}
@Override
public Collection<StaffData> retrieveAllStaffForDropdown(final Long officeId) {
final Long defaultOfficeId = defaultToUsersOfficeIfNull(officeId);
final String sql = "select " + this.lookupMapper.schema() + " where s.office_id = ?";
return this.jdbcTemplate.query(sql, this.lookupMapper, new Object[] { defaultOfficeId });
}
private Long defaultToUsersOfficeIfNull(final Long officeId) {
Long defaultOfficeId = officeId;
if (defaultOfficeId == null) {
defaultOfficeId = this.context.authenticatedUser().getOffice().getId();
}
return defaultOfficeId;
}
@Override
public StaffData retrieveStaff(final Long staffId) {
@@ -100,73 +132,4 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService {
throw new StaffNotFoundException(staffId);
}
}
@Override
public StaffAccountSummaryCollectionData retrieveLoanOfficerAccountSummary(final Long loanOfficerId) {
context.authenticatedUser();
final StaffClientMapper staffClientMapper = new StaffClientMapper();
final String clientSql = "select distinct " + staffClientMapper.schema();
final StaffGroupMapper staffGroupMapper = new StaffGroupMapper();
final String groupSql = "select distinct " + staffGroupMapper.schema();
final List<StaffAccountSummaryCollectionData.ClientSummary> clientSummaryList = this.jdbcTemplate.query(clientSql,
staffClientMapper, new Object[] { loanOfficerId });
for (StaffAccountSummaryCollectionData.ClientSummary clientSummary : clientSummaryList) {
final Collection<ClientAccountSummaryData> clientLoanAccounts = this.clientReadPlatformService
.retrieveClientLoanAccountsByLoanOfficerId(clientSummary.getId(), loanOfficerId);
clientSummary.setLoans(clientLoanAccounts);
}
final List<StaffAccountSummaryCollectionData.GroupSummary> groupSummaryList = this.jdbcTemplate.query(groupSql, staffGroupMapper,
new Object[] { loanOfficerId });
for (StaffAccountSummaryCollectionData.GroupSummary groupSummary : groupSummaryList) {
final Collection<GroupAccountSummaryData> groupLoanAccounts = this.groupReadPlatformService
.retrieveGroupLoanAccountsByLoanOfficerId(groupSummary.getId(), loanOfficerId);
groupSummary.setLoans(groupLoanAccounts);
}
return new StaffAccountSummaryCollectionData(clientSummaryList, groupSummaryList);
}
private static final class StaffClientMapper implements RowMapper<StaffAccountSummaryCollectionData.ClientSummary> {
public String schema() {
return " c.id as id, c.display_name as displayName from m_client c "
+ " join m_loan l on c.id = l.client_id where l.loan_officer_id = ? ";
}
@Override
public StaffAccountSummaryCollectionData.ClientSummary mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum)
throws SQLException {
final Long id = JdbcSupport.getLong(rs, "id");
final String displayName = rs.getString("displayName");
return new StaffAccountSummaryCollectionData.ClientSummary(id, displayName);
}
}
private static final class StaffGroupMapper implements RowMapper<StaffAccountSummaryCollectionData.GroupSummary> {
public String schema() {
return " g.id as id, g.name as name from m_group g" + " join m_loan l on g.id = l.group_id where l.loan_officer_id = ? ";
}
@Override
public StaffAccountSummaryCollectionData.GroupSummary mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum)
throws SQLException {
final Long id = JdbcSupport.getLong(rs, "id");
final String name = rs.getString("name");
return new StaffAccountSummaryCollectionData.GroupSummary(id, name);
}
}
}
@@ -9,14 +9,17 @@ import java.util.Collection;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.CompareToBuilder;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.joda.time.LocalDate;
import org.mifosplatform.organisation.office.data.OfficeLookup;
import org.mifosplatform.portfolio.group.data.GroupLookup;
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
/**
* Immutable data object representing client data.
*/
final public class ClientData {
final public class ClientData implements Comparable<ClientData> {
private final Long id;
private final String accountNo;
@@ -32,9 +35,12 @@ final public class ClientData {
private final String imageKey;
@SuppressWarnings("unused")
private final Boolean imagePresent;
private final Collection<GroupLookup> parentGroups;
private final List<OfficeLookup> allowedOffices;
// associations
private final Collection<GroupGeneralData> parentGroups;
// template
private final List<OfficeLookup> allowedOffices;
private final ClientData currentChange;
private final Collection<ClientData> allChanges;
@@ -46,7 +52,8 @@ final public class ClientData {
joiningDate, null, null, null, null, null);
}
public static ClientData integrateChanges(final ClientData clientData, ClientData currentChange, final Collection<ClientData> allChanges) {
public static ClientData integrateChanges(final ClientData clientData, final ClientData currentChange,
final Collection<ClientData> allChanges) {
return new ClientData(clientData.accountNo, clientData.officeId, clientData.officeName, clientData.id, clientData.firstname,
clientData.middlename, clientData.lastname, clientData.fullname, clientData.displayName, clientData.externalId,
clientData.joinedDate, clientData.imageKey, clientData.allowedOffices, currentChange, allChanges, clientData.parentGroups);
@@ -65,7 +72,7 @@ final public class ClientData {
clientData.parentGroups);
}
public static ClientData setParentGroups(final ClientData clientData, final Collection<GroupLookup> parentGroups) {
public static ClientData setParentGroups(final ClientData clientData, final Collection<GroupGeneralData> parentGroups) {
return new ClientData(clientData.accountNo, clientData.officeId, clientData.officeName, clientData.id, clientData.firstname,
clientData.middlename, clientData.lastname, clientData.fullname, clientData.displayName, clientData.externalId,
clientData.joinedDate, clientData.imageKey, clientData.allowedOffices, clientData.currentChange, clientData.allChanges,
@@ -80,10 +87,14 @@ final public class ClientData {
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, officeId, officeName, id, null, null, null, null, displayName, null, null, null, null, null, null, null);
}
public ClientData(final String accountNo, 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 joinedDate, final String imageKey, final List<OfficeLookup> allowedOffices, final ClientData currentChange,
final Collection<ClientData> allChanges, final Collection<GroupLookup> parentGroups) {
final Collection<ClientData> allChanges, final Collection<GroupGeneralData> parentGroups) {
this.accountNo = accountNo;
this.officeId = officeId;
this.officeName = officeName;
@@ -107,6 +118,35 @@ final public class ClientData {
this.parentGroups = parentGroups;
}
@Override
public int compareTo(final ClientData obj) {
if (obj == null) { return -1; }
return new CompareToBuilder() //
.append(this.id, obj.id) //
.append(this.displayName, obj.displayName) //
.toComparison();
}
@Override
public boolean equals(final Object obj) {
if (obj == null) { return false; }
if (obj == this) { return true; }
if (obj.getClass() != getClass()) { return false; }
ClientData rhs = (ClientData) obj;
return new EqualsBuilder() //
.append(this.id, rhs.id) //
.append(this.displayName, rhs.displayName) //
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37) //
.append(this.id) //
.append(this.displayName) //
.toHashCode();
}
public String displayName() {
return this.displayName;
}
@@ -162,5 +202,4 @@ final public class ClientData {
public LocalDate getJoinedDate() {
return this.joinedDate;
}
}
@@ -1,88 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.client.data;
import org.apache.commons.lang.StringUtils;
public class ClientLookup {
private final Long id;
private final String displayName;
private final Long officeId;
private final String officeName;
public static ClientLookup template(final Long id, final String displayName, final Long officeId, final String officeName) {
return new ClientLookup(id, displayName, officeId, officeName);
}
public static ClientLookup create(final Long id, final String displayName) {
return new ClientLookup(id, displayName, null, null);
}
public ClientLookup(final Long id, final String firstname, final String lastname, final Long officeId, final String officeName) {
this.id = id;
StringBuilder displayNameBuilder = new StringBuilder(firstname);
if (StringUtils.isNotBlank(displayNameBuilder.toString())) {
displayNameBuilder.append(' ');
}
displayNameBuilder.append(lastname);
this.displayName = displayNameBuilder.toString();
this.officeId = officeId;
this.officeName = officeName;
}
public ClientLookup(final Long id, final String displayName, final Long officeId, final String officeName) {
this.id = id;
this.displayName = displayName;
this.officeId = officeId;
this.officeName = officeName;
}
public ClientLookup(final Long id, final String firstname, final String lastname) {
this.id = id;
StringBuilder displayNameBuilder = new StringBuilder(firstname);
if (StringUtils.isNotBlank(displayNameBuilder.toString())) {
displayNameBuilder.append(' ');
}
displayNameBuilder.append(lastname);
this.displayName = displayNameBuilder.toString();
this.officeId = null;
this.officeName = null;
}
@Override
public boolean equals(Object obj) {
ClientLookup clientLookup = (ClientLookup) obj;
return this.id.equals(clientLookup.id);
}
@Override
public int hashCode() {
return this.id.hashCode();
}
public Long getId() {
return id;
}
public String getDisplayName() {
return displayName;
}
public Long getOfficeId() {
return officeId;
}
public String getOfficeName() {
return officeName;
}
}
@@ -10,7 +10,6 @@ import java.util.Collection;
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryCollectionData;
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryData;
import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.client.data.ClientLookup;
public interface ClientReadPlatformService {
@@ -20,9 +19,9 @@ public interface ClientReadPlatformService {
ClientData retrieveNewClientDetails();
Collection<ClientLookup> retrieveAllIndividualClientsForLookup(String extraCriteria);
Collection<ClientData> retrieveAllIndividualClientsForLookup(String extraCriteria);
Collection<ClientLookup> retrieveAllIndividualClientsForLookupByOfficeId(Long officeId);
Collection<ClientData> retrieveAllIndividualClientsForLookupByOfficeId(Long officeId);
ClientAccountSummaryCollectionData retrieveClientAccountDetails(Long clientId);
@@ -30,4 +29,5 @@ public interface ClientReadPlatformService {
ClientData retrieveClientByIdentifier(Long identifierTypeId, String identifierKey);
Collection<ClientData> retrieveClientMembersOfGroup(Long groupId);
}
@@ -21,9 +21,8 @@ import org.mifosplatform.organisation.office.service.OfficeReadPlatformService;
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryCollectionData;
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryData;
import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.client.data.ClientLookup;
import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
import org.mifosplatform.portfolio.group.data.GroupLookup;
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
import org.mifosplatform.portfolio.loanaccount.data.LoanStatusEnumData;
import org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations;
import org.mifosplatform.useradministration.domain.AppUser;
@@ -39,6 +38,8 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
private final JdbcTemplate jdbcTemplate;
private final PlatformSecurityContext context;
private final OfficeReadPlatformService officeReadPlatformService;
private final ClientLookupMapper lookupMapper = new ClientLookupMapper();
private final ClientMembersOfGroupMapper membersOfGroupMapper = new ClientMembersOfGroupMapper();
@Autowired
public ClientReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource,
@@ -70,7 +71,6 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
public ClientData retrieveIndividualClient(final Long clientId) {
try {
AppUser currentUser = context.authenticatedUser();
String hierarchy = currentUser.getOffice().getHierarchy();
String hierarchySearchString = hierarchy + "%";
@@ -81,7 +81,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
ParentGroupsMapper cgrm = new ParentGroupsMapper();
String cgSql = "select " + cgrm.parentGroupsSchema();
Collection<GroupLookup> parentGroups = this.jdbcTemplate.query(cgSql, cgrm, new Object[] { clientId });
Collection<GroupGeneralData> parentGroups = this.jdbcTemplate.query(cgSql, cgrm, new Object[] { clientId });
return ClientData.setParentGroups(clientData , parentGroups);
@@ -91,30 +91,23 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
}
@Override
public Collection<ClientLookup> retrieveAllIndividualClientsForLookup(final String extraCriteria) {
public Collection<ClientData> retrieveAllIndividualClientsForLookup(final String extraCriteria) {
this.context.authenticatedUser();
ClientLookupMapper rm = new ClientLookupMapper();
String sql = "select " + rm.clientLookupSchema();
String sql = "select " + this.lookupMapper.schema();
if (StringUtils.isNotBlank(extraCriteria)) {
sql += " and (" + extraCriteria + ")";
}
return this.jdbcTemplate.query(sql, rm, new Object[] {});
return this.jdbcTemplate.query(sql, this.lookupMapper, new Object[] {});
}
@Override
public Collection<ClientLookup> retrieveAllIndividualClientsForLookupByOfficeId(final Long officeId) {
this.context.authenticatedUser();
public Collection<ClientData> retrieveAllIndividualClientsForLookupByOfficeId(final Long officeId) {
ClientLookupMapper rm = new ClientLookupMapper();
final String sql = "select " + this.lookupMapper.schema() + " and c.office_id = ?";
String sql = "select " + rm.clientLookupSchema() + " and c.office_id = " + officeId;
return this.jdbcTemplate.query(sql, rm, new Object[] {});
return this.jdbcTemplate.query(sql, this.lookupMapper, new Object[] { officeId });
}
@Override
@@ -128,6 +121,63 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
return ClientData.template(officeId, new LocalDate(), offices);
}
@Override
public Collection<ClientData> retrieveClientMembersOfGroup(final Long groupId) {
final AppUser currentUser = context.authenticatedUser();
final String hierarchy = currentUser.getOffice().getHierarchy();
final String hierarchySearchString = hierarchy + "%";
final String sql = "select " + this.membersOfGroupMapper.schema()
+ " where o.hierarchy like ? and pgc.group_id = ? and c.is_deleted=0";
return this.jdbcTemplate.query(sql, this.membersOfGroupMapper, new Object[] { hierarchySearchString, groupId });
}
private static final class ClientMembersOfGroupMapper implements RowMapper<ClientData> {
private final String schema;
public ClientMembersOfGroupMapper() {
final StringBuilder sqlBuilder = new StringBuilder(200);
sqlBuilder.append("c.id as id, c.account_no as accountNo, c.external_id as externalId, ");
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.joined_date as joinedDate, c.image_key as imagekey ");
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");
this.schema = sqlBuilder.toString();
}
public String schema() {
return this.schema;
}
@Override
public ClientData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final String accountNo = rs.getString("accountNo");
final Long officeId = JdbcSupport.getLong(rs, "officeId");
final Long id = JdbcSupport.getLong(rs, "id");
final String firstname = rs.getString("firstname");
final String middlename = rs.getString("middlename");
final String lastname = rs.getString("lastname");
final String fullname = rs.getString("fullname");
final String displayName = rs.getString("displayName");
final String externalId = rs.getString("externalId");
final LocalDate joinedDate = JdbcSupport.getLocalDate(rs, "joinedDate");
final String imageKey = rs.getString("imageKey");
final String officeName = rs.getString("officeName");
return new ClientData(accountNo, officeId, officeName, id, firstname, middlename, lastname, fullname, displayName, externalId,
joinedDate, imageKey, null, null, null, null);
}
}
private static final class ClientMapper implements RowMapper<ClientData> {
public String clientSchema() {
@@ -160,7 +210,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
}
private static final class ParentGroupsMapper implements RowMapper<GroupLookup> {
private static final class ParentGroupsMapper implements RowMapper<GroupGeneralData> {
public String parentGroupsSchema() {
return "gp.id As groupId , gp.name As groupName from m_client cl JOIN m_group_client gc ON cl.id = gc.client_id "
@@ -168,31 +218,44 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
}
@Override
public GroupLookup mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
public GroupGeneralData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long groupId = JdbcSupport.getLong(rs, "groupId");
final String groupName = rs.getString("groupName");
return new GroupLookup(groupId, groupName);
return GroupGeneralData.lookup(groupId, groupName);
}
}
private static final class ClientLookupMapper implements RowMapper<ClientLookup> {
private static final class ClientLookupMapper implements RowMapper<ClientData> {
public String clientLookupSchema() {
return "c.id as id, c.display_name as displayName, " + "c.office_id as officeId, o.name as officeName "
+ "from m_client c join m_office o on o.id = c.office_id where c.is_deleted=0 ";
private final String schema;
public ClientLookupMapper() {
StringBuilder builder = new StringBuilder(200);
builder.append("c.id as id, c.display_name as displayName, ");
builder.append("c.office_id as officeId, o.name as officeName ");
builder.append("from m_client c ");
builder.append("join m_office o on o.id = c.office_id ");
builder.append("where c.is_deleted=0");
this.schema = builder.toString();
}
public String schema() {
return this.schema;
}
@Override
public ClientLookup mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
Long id = rs.getLong("id");
String displayName = rs.getString("displayName");
Long officeId = rs.getLong("officeId");
String officeName = rs.getString("officeName");
public ClientData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
return ClientLookup.template(id, displayName, officeId, officeName);
final Long id = rs.getLong("id");
final String displayName = rs.getString("displayName");
final Long officeId = rs.getLong("officeId");
final String officeName = rs.getString("officeName");
return ClientData.lookup(id, displayName, officeId, officeName);
}
}
@@ -21,10 +21,8 @@ import org.mifosplatform.portfolio.collectionsheet.data.JLGClientsData;
import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetData;
import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetFlatData;
import org.mifosplatform.portfolio.collectionsheet.data.LoanDueData;
import org.mifosplatform.portfolio.group.data.GroupData;
import org.mifosplatform.portfolio.group.data.GroupTypes;
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
import org.mifosplatform.portfolio.group.service.GroupReadPlatformServiceImpl;
import org.mifosplatform.portfolio.group.data.CenterData;
import org.mifosplatform.portfolio.group.service.CenterReadPlatformService;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
import org.mifosplatform.useradministration.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired;
@@ -39,43 +37,35 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
private final PlatformSecurityContext context;
private final NamedParameterJdbcTemplate namedParameterjdbcTemplate;
private final GroupReadPlatformServiceImpl groupReadPlatformServiceImpl;
private final CenterReadPlatformService centerReadPlatformService;
@Autowired
public CollectionSheetReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource,
final GroupReadPlatformServiceImpl groupReadPlatformServiceImpl) {
final CenterReadPlatformService centerReadPlatformService) {
this.context = context;
this.centerReadPlatformService = centerReadPlatformService;
this.namedParameterjdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
this.groupReadPlatformServiceImpl = groupReadPlatformServiceImpl;
}
@Override
public JLGCollectionSheetData retriveCollectionSheet(final LocalDate dueDate, final Long groupId) {
public JLGCollectionSheetData retriveCollectionSheet(final LocalDate dueDate, final Long centerId) {
final AppUser currentUser = this.context.authenticatedUser();
final String hierarchy = currentUser.getOffice().getHierarchy();
final String officeHierarchy = hierarchy + "%";
final GroupData groupData = this.groupReadPlatformServiceImpl.retrieveGroup(groupId , GroupTypes.CENTER.getId());
if (groupData == null) { throw new GroupNotFoundException(groupId); }
final String groupHierarchy = groupData.getHierarchy() + "%";
final CenterData center = this.centerReadPlatformService.retrieveOne(centerId);
final String groupHierarchy = center.getHierarchy() + "%";
final JLGCollectionSheetData jlgCollectionSheetData = buildJLGCollectionSheet(groupHierarchy, officeHierarchy, dueDate);
return jlgCollectionSheetData;
}
/**
* @param groupHierarchy
* @param officeHierarchy
* @param dueDate
* @return
*
* Reads all the loans which are due for disbursement or collection
* and builds hierarchical data structure for collections sheet with
* hierarchy Groups >> Clients >> Loans.
*
/*
* Reads all the loans which are due for disbursement or collection and
* builds hierarchical data structure for collections sheet with hierarchy
* Groups >> Clients >> Loans.
*/
@SuppressWarnings("null")
private JLGCollectionSheetData buildJLGCollectionSheet(final String groupHierarchy, final String officeHierarchy,
@@ -99,8 +89,9 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
if (jlgCollectionSheetFlatData != null) {
for (final JLGCollectionSheetFlatData collectionSheetFlatData : jlgCollectionSheetFlatData) {
loanProducts.add(LoanProductData.lookupWithCurrency(collectionSheetFlatData.getProductId(), collectionSheetFlatData.getProductShortName(), collectionSheetFlatData.getCurrency()));
loanProducts.add(LoanProductData.lookupWithCurrency(collectionSheetFlatData.getProductId(),
collectionSheetFlatData.getProductShortName(), collectionSheetFlatData.getCurrency()));
corrCollectioSheetFlatData = collectionSheetFlatData;
if (firstTime || collectionSheetFlatData.getGroupId().equals(prevGroupId)) {
@@ -113,7 +104,7 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
clientLoansData.setLoans(loanDueDatas);
clientLoansDatas.add(clientLoansData);
loanDueDatas = new ArrayList<LoanDueData>();
if (collectionSheetFlatData.getLoanId() != null) {
loanDueDatas.add(collectionSheetFlatData.getLoanDueData());
}
@@ -147,11 +138,11 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
// FIXME Need to check last loan is added under previous
// client/group or new client / previous group or new client / new
// group
if(corrCollectioSheetFlatData != null){
if (corrCollectioSheetFlatData != null) {
final ClientLoansData lastClientLoansData = corrCollectioSheetFlatData.getClientLoansData();
lastClientLoansData.setLoans(loanDueDatas);
clientLoansDatas.add(lastClientLoansData);
final JLGClientsData jlgClientsData = corrCollectioSheetFlatData.getJLGClientsData();
jlgClientsData.setClients(clientLoansDatas);
jlgClientsDatas.add(jlgClientsData);
@@ -230,7 +221,7 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
final Integer accountStatusId = JdbcSupport.getInteger(rs, "accountStatusId");
final String productShortName = rs.getString("productShortName");
final Long productId = JdbcSupport.getLong(rs, "productId");
final String currencyCode = rs.getString("currencyCode");
final String currencyName = rs.getString("currencyName");
final String currencyNameCode = rs.getString("currencyNameCode");
@@ -238,7 +229,7 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
final Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits");
final CurrencyData currencyData = new CurrencyData(currencyCode, currencyName, currencyDigits, currencyDisplaySymbol,
currencyNameCode);
final BigDecimal disbursementAmount = rs.getBigDecimal("disbursementAmount");
final BigDecimal principalDue = rs.getBigDecimal("principalDue");
final BigDecimal principalPaid = rs.getBigDecimal("principalPaid");
@@ -247,8 +238,8 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
final BigDecimal chargesDue = rs.getBigDecimal("chargesDue");
return new JLGCollectionSheetFlatData(groupName, groupId, staffId, staffName, levelId, levelName, clientName, clientId, loanId,
accountId, accountStatusId, productShortName, productId, currencyData, disbursementAmount,
principalDue, principalPaid, interestDue, interestPaid, chargesDue);
accountId, accountStatusId, productShortName, productId, currencyData, disbursementAmount, principalDue, principalPaid,
interestDue, interestPaid, chargesDue);
}
}
@@ -23,7 +23,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;
@@ -33,10 +32,11 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.mifosplatform.infrastructure.core.serialization.ToApiJsonSerializer;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.group.data.CenterData;
import org.mifosplatform.portfolio.group.data.GroupAccountSummaryCollectionData;
import org.mifosplatform.portfolio.group.data.GroupData;
import org.mifosplatform.portfolio.group.data.GroupTypes;
import org.mifosplatform.portfolio.group.service.CenterReadPlatformService;
import org.mifosplatform.portfolio.group.service.GroupReadPlatformService;
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;
@@ -46,30 +46,26 @@ import org.springframework.stereotype.Component;
@Scope("singleton")
public class CentersApiResource {
/*
* GROUP_DATA_PARAMETERS is used by ToApiJsonSerializer<E>, make sure E's properties and E_PARAMETERS are in same
*/
private static final Set<String> CENTER_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "name", "externalId", "officeId",
"officeName", "staffId", "staffName", "parentId", "parentName", "hierarchy", "groupSummaryData", "groupLevelData",
"clientMembers", "allowedClients", "allowedOffices", "allowedParentGroups", "allowedStaffs", "childGroups"));
private final PlatformSecurityContext context;
private final CenterReadPlatformService centerReadPlatformService;
private final GroupReadPlatformService groupReadPlatformService;
private final ToApiJsonSerializer<GroupData> toApiJsonSerializer;
private final ToApiJsonSerializer<CenterData> centerApiJsonSerializer;
private final ToApiJsonSerializer<Object> toApiJsonSerializer;
private final ToApiJsonSerializer<GroupAccountSummaryCollectionData> groupSummaryToApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private static final Long LEVEL_ID = GroupTypes.CENTER.getId();
@Autowired
public CentersApiResource(final PlatformSecurityContext context, final GroupReadPlatformService groupReadPlatformService,
final ToApiJsonSerializer<GroupData> toApiJsonSerializer,
public CentersApiResource(final PlatformSecurityContext context, final CenterReadPlatformService centerReadPlatformService,
final GroupReadPlatformService groupReadPlatformService, final ToApiJsonSerializer<CenterData> centerApiJsonSerializer,
final ToApiJsonSerializer<Object> toApiJsonSerializer,
final ToApiJsonSerializer<GroupAccountSummaryCollectionData> groupSummaryToApiJsonSerializer,
final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
this.context = context;
this.centerReadPlatformService = centerReadPlatformService;
this.groupReadPlatformService = groupReadPlatformService;
this.centerApiJsonSerializer = centerApiJsonSerializer;
this.toApiJsonSerializer = toApiJsonSerializer;
this.groupSummaryToApiJsonSerializer = groupSummaryToApiJsonSerializer;
this.apiRequestParameterHelper = apiRequestParameterHelper;
@@ -77,61 +73,59 @@ public class CentersApiResource {
}
@GET
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllCenters(@Context final UriInfo uriInfo, @QueryParam("sqlSearch") final String sqlSearch,
@QueryParam("officeId") final Long officeId, @QueryParam("externalId") final String externalId,
@QueryParam("name") final String name , @QueryParam("underHierarchy") final String hierarchy) {
public String retrieveTemplate(@Context final UriInfo uriInfo, @QueryParam("officeId") final Long officeId) {
this.context.authenticatedUser().validateHasReadPermission("CENTER");
this.context.authenticatedUser().validateHasReadPermission(GroupingTypesApiConstants.CENTER_RESOURCE_NAME);
final String extraCriteria = getCenterExtraCriteria(sqlSearch, officeId, externalId, name , LEVEL_ID , hierarchy);
final Collection<GroupData> centers = this.groupReadPlatformService.retrieveAllGroups(extraCriteria);
final CenterData template = this.centerReadPlatformService.retrieveTemplate(officeId);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, centers, CENTER_DATA_PARAMETERS);
return this.centerApiJsonSerializer.serialize(settings, template, GroupingTypesApiConstants.CENTER_RESPONSE_DATA_PARAMETERS);
}
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAll(@Context final UriInfo uriInfo, @QueryParam("sqlSearch") final String sqlSearch,
@QueryParam("officeId") final Long officeId, @QueryParam("externalId") final String externalId,
@QueryParam("name") final String name, @QueryParam("underHierarchy") final String hierarchy) {
this.context.authenticatedUser().validateHasReadPermission(GroupingTypesApiConstants.CENTER_RESOURCE_NAME);
final SearchParameters searchCriteria = SearchParameters.from(sqlSearch, officeId, externalId, name, hierarchy);
final Collection<CenterData> centers = this.centerReadPlatformService.retrieveAll(searchCriteria);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.centerApiJsonSerializer.serialize(settings, centers, GroupingTypesApiConstants.CENTER_RESPONSE_DATA_PARAMETERS);
}
@GET
@Path("{centerId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveCenterData(@Context final UriInfo uriInfo, @PathParam("centerId") final Long centerId) {
public String retrieveOne(@Context final UriInfo uriInfo, @PathParam("centerId") final Long centerId) {
this.context.authenticatedUser().validateHasReadPermission("CENTER");
this.context.authenticatedUser().validateHasReadPermission(GroupingTypesApiConstants.CENTER_RESOURCE_NAME);
CenterData center = this.centerReadPlatformService.retrieveOne(centerId);
final boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters());
final GroupData group = this.groupReadPlatformService.retrieveGroupDetails(centerId, LEVEL_ID, template);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, group, CENTER_DATA_PARAMETERS);
}
@GET
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String newGroupDetails(@Context final UriInfo uriInfo, @QueryParam("officeId") final Long officeId) {
this.context.authenticatedUser().validateHasReadPermission("CENTER");
GroupData centerTemplateData = null;
if (officeId != null) {
centerTemplateData = this.groupReadPlatformService.retrieveNewGroupDetails(officeId, LEVEL_ID);
} else {
centerTemplateData = this.groupReadPlatformService.retrieveNewGroupDetails(this.context.authenticatedUser().getOffice().getId(),
LEVEL_ID);
if (template) {
final CenterData templateCenter = this.centerReadPlatformService.retrieveTemplate(center.officeId());
center = CenterData.withTemplate(templateCenter, center);
}
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, centerTemplateData, CENTER_DATA_PARAMETERS);
return this.centerApiJsonSerializer.serialize(settings, center, GroupingTypesApiConstants.CENTER_RESPONSE_DATA_PARAMETERS);
}
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createCenter(final String apiRequestBodyAsJson) {
public String create(final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.createCenter() //
@@ -146,7 +140,7 @@ public class CentersApiResource {
@Path("{centerId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateGroup(@PathParam("centerId") final Long centerId, final String apiRequestBodyAsJson) {
public String update(@PathParam("centerId") final Long centerId, final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.updateCenter(centerId) //
@@ -160,25 +154,24 @@ public class CentersApiResource {
@Path("{centerId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteGroup(@PathParam("centerId") final Long centerId) {
public String delete(@PathParam("centerId") final Long centerId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.deleteCenter(centerId) //
.build(); //
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
@GET
@Path("{groupId}/loans")
@Path("{centerId}/loans")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveGroupAccount(@PathParam("groupId") final Long groupId, @Context final UriInfo uriInfo) {
public String retrieveGroupAccount(@PathParam("centerId") final Long centerId, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission("GROUP");
this.context.authenticatedUser().validateHasReadPermission(GroupingTypesApiConstants.CENTER_RESOURCE_NAME);
final GroupAccountSummaryCollectionData groupAccount = this.groupReadPlatformService.retrieveGroupAccountDetails(groupId);
final GroupAccountSummaryCollectionData groupAccount = this.groupReadPlatformService.retrieveGroupAccountDetails(centerId);
final Set<String> GROUP_ACCOUNTS_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("pendingApprovalLoans",
"awaitingDisbursalLoans", "openLoans", "closedLoans", "anyLoanCount", "pendingApprovalLoanCount",
@@ -187,45 +180,4 @@ public class CentersApiResource {
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.groupSummaryToApiJsonSerializer.serialize(settings, groupAccount, GROUP_ACCOUNTS_DATA_PARAMETERS);
}
// 'g.' preffix because of ERROR 1052 (23000): Column 'column_name' in where
// clause is ambiguous
// caused by the same name of columns in m_office and m_group tables
private String getCenterExtraCriteria(String sqlSearch, final Long officeId, final String externalId, final String name , final Long levelId ,final String hierarchy) {
String extraCriteria = " and g.level_id = " + LEVEL_ID + " ";
if (sqlSearch != null) {
sqlSearch = sqlSearch.replaceAll(" name ", " g.name ");
sqlSearch = sqlSearch.replaceAll("name ", "g.name ");
extraCriteria = " and (" + sqlSearch + ")";
}
if (officeId != null) {
extraCriteria += " and g.office_id = " + officeId;
}
if (levelId != null) {
extraCriteria += " and g.level_Id = " + levelId;
}
if (externalId != null) {
extraCriteria += " and g.external_id = " + ApiParameterHelper.sqlEncodeString(externalId);
}
if (name != null) {
extraCriteria += " and g.name like " + ApiParameterHelper.sqlEncodeString(name + "%");
}
if (hierarchy != null) {
extraCriteria += " and o.hierarchy like " + ApiParameterHelper.sqlEncodeString(hierarchy + "%");
}
if (StringUtils.isNotBlank(extraCriteria)) {
extraCriteria = extraCriteria.substring(4);
}
return extraCriteria;
}
}
@@ -0,0 +1,50 @@
package org.mifosplatform.portfolio.group.api;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.mifosplatform.portfolio.group.data.CenterData;
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";
// general
public static final String localeParamName = "locale";
public static final String dateFormatParamName = "dateFormat";
// center parameters
public static final String idParamName = "id";
public static final String nameParamName = "name";
public static final String externalIdParamName = "externalId";
public static final String officeIdParamName = "officeId";
public static final String staffIdParamName = "staffId";
// response parameters
public static final String hierarchyParamName = "hierarchy";
public static final String officeNameParamName = "officeName";
public static final String staffNameParamName = "staffName";
public static final Set<String> CENTER_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
dateFormatParamName, nameParamName, externalIdParamName, officeIdParamName, staffIdParamName));
/**
* These parameters will match the class level parameters of
* {@link CenterData}. Where possible, we try to get response parameters to
* match those of request parameters.
*/
public static final Set<String> CENTER_RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(idParamName, nameParamName,
externalIdParamName, officeIdParamName, officeNameParamName, staffIdParamName, staffNameParamName, hierarchyParamName,
"officeOptions", "staffOptions"));
public static final Set<String> CENTER_GROUP_RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(idParamName, nameParamName,
externalIdParamName, officeIdParamName, officeNameParamName, staffIdParamName, staffNameParamName, hierarchyParamName,
"officeOptions", "staffOptions"));
public static final Set<String> GROUP_RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(idParamName, nameParamName,
externalIdParamName, officeIdParamName, officeNameParamName, "parentId", "parentName", staffIdParamName, staffNameParamName,
hierarchyParamName, "officeOptions", "staffOptions", "clientOptions"));
}
@@ -23,7 +23,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;
@@ -33,107 +32,122 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.mifosplatform.infrastructure.core.serialization.ToApiJsonSerializer;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
import org.mifosplatform.portfolio.group.data.GroupAccountSummaryCollectionData;
import org.mifosplatform.portfolio.group.data.GroupData;
import org.mifosplatform.portfolio.group.data.GroupTypes;
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
import org.mifosplatform.portfolio.group.service.CenterReadPlatformService;
import org.mifosplatform.portfolio.group.service.GroupReadPlatformService;
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("/groups")
@Component
@Scope("singleton")
public class GroupsApiResource {
/*
* GROUP_DATA_PARAMETERS is used by ToApiJsonSerializer<E>, make sure E's properties and E_PARAMETERS are in same
*/
private static final Set<String> GROUP_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "name", "externalId", "officeId",
"officeName", "staffId", "staffName", "parentId", "parentName", "hierarchy", "groupSummaryData", "groupLevelData",
"clientMembers", "allowedClients", "allowedOffices", "allowedParentGroups", "allowedStaffs", "childGroups"));
private final PlatformSecurityContext context;
private final GroupReadPlatformService groupReadPlatformService;
private final ToApiJsonSerializer<GroupData> toApiJsonSerializer;
private final CenterReadPlatformService centerReadPlatformService;
private final ClientReadPlatformService clientReadPlatformService;
private final ToApiJsonSerializer<Object> toApiJsonSerializer;
private final ToApiJsonSerializer<GroupGeneralData> groupGeneralApiJsonSerializer;
private final ToApiJsonSerializer<GroupAccountSummaryCollectionData> groupSummaryToApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private static final Long LEVEL_ID = GroupTypes.GROUP.getId();
@Autowired
public GroupsApiResource(final PlatformSecurityContext context, final GroupReadPlatformService groupReadPlatformService,
final ToApiJsonSerializer<GroupData> toApiJsonSerializer,
final CenterReadPlatformService centerReadPlatformService, final ClientReadPlatformService clientReadPlatformService,
final ToApiJsonSerializer<Object> toApiJsonSerializer,
final ToApiJsonSerializer<GroupGeneralData> groupTopOfHierarchyApiJsonSerializer,
final ToApiJsonSerializer<GroupAccountSummaryCollectionData> groupSummaryToApiJsonSerializer,
final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
this.context = context;
this.groupReadPlatformService = groupReadPlatformService;
this.centerReadPlatformService = centerReadPlatformService;
this.clientReadPlatformService = clientReadPlatformService;
this.toApiJsonSerializer = toApiJsonSerializer;
this.groupGeneralApiJsonSerializer = groupTopOfHierarchyApiJsonSerializer;
this.groupSummaryToApiJsonSerializer = groupSummaryToApiJsonSerializer;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
}
@GET
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllGroups(@Context final UriInfo uriInfo, @QueryParam("sqlSearch") final String sqlSearch,
public String retrieveTemplate(@Context final UriInfo uriInfo, @QueryParam("officeId") final Long officeId,
@QueryParam("center") final boolean isCenterGroup,
@QueryParam("centerId") final Long centerId) {
this.context.authenticatedUser().validateHasReadPermission(GroupingTypesApiConstants.GROUP_RESOURCE_NAME);
if (centerId != null) {
final GroupGeneralData centerGroupTemplate = this.centerReadPlatformService.retrieveCenterGroupTemplate(centerId);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.groupGeneralApiJsonSerializer.serialize(settings, centerGroupTemplate,
GroupingTypesApiConstants.CENTER_GROUP_RESPONSE_DATA_PARAMETERS);
}
final GroupGeneralData groupTemplate = this.groupReadPlatformService.retrieveTemplate(officeId, isCenterGroup);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.groupGeneralApiJsonSerializer.serialize(settings, groupTemplate,
GroupingTypesApiConstants.GROUP_RESPONSE_DATA_PARAMETERS);
}
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAll(@Context final UriInfo uriInfo, @QueryParam("sqlSearch") final String sqlSearch,
@QueryParam("officeId") final Long officeId, @QueryParam("externalId") final String externalId,
@QueryParam("name") final String name , @QueryParam("underHierarchy") final String hierarchy) {
@QueryParam("name") final String name, @QueryParam("underHierarchy") final String hierarchy) {
this.context.authenticatedUser().validateHasReadPermission("GROUP");
this.context.authenticatedUser().validateHasReadPermission(GroupingTypesApiConstants.GROUP_RESOURCE_NAME);
final String extraCriteria = getGroupExtraCriteria(sqlSearch, officeId, externalId, name , LEVEL_ID , hierarchy);
final Collection<GroupData> groups = this.groupReadPlatformService.retrieveAllGroups(extraCriteria);
final SearchParameters searchCriteria = SearchParameters.from(sqlSearch, officeId, externalId, name, hierarchy);
final Collection<GroupGeneralData> groups = this.groupReadPlatformService.retrieveAll(searchCriteria);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, groups, GROUP_DATA_PARAMETERS);
return this.groupGeneralApiJsonSerializer.serialize(settings, groups, GroupingTypesApiConstants.GROUP_RESPONSE_DATA_PARAMETERS);
}
@GET
@Path("{groupId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveGroupData(@Context final UriInfo uriInfo, @PathParam("groupId") final Long groupId) {
public String retrieveOne(@Context final UriInfo uriInfo, @PathParam("groupId") final Long groupId) {
this.context.authenticatedUser().validateHasReadPermission("GROUP");
this.context.authenticatedUser().validateHasReadPermission(GroupingTypesApiConstants.GROUP_RESOURCE_NAME);
GroupGeneralData group = this.groupReadPlatformService.retrieveOne(groupId);
Collection<ClientData> membersOfGroup = this.clientReadPlatformService.retrieveClientMembersOfGroup(groupId);
if (CollectionUtils.isEmpty(membersOfGroup)) {
membersOfGroup = null;
}
final boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters());
final GroupData group = this.groupReadPlatformService.retrieveGroupDetails(groupId, LEVEL_ID, template);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, group, GROUP_DATA_PARAMETERS);
}
@GET
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String newGroupDetails(@Context final UriInfo uriInfo, @QueryParam("officeId") final Long officeId,
@QueryParam("centerId") final Long centerId) {
this.context.authenticatedUser().validateHasReadPermission("GROUP");
GroupData groupTemplateData = null;
if (centerId != null) {
groupTemplateData = this.groupReadPlatformService.retrieveNewChildGroupDetails(officeId, LEVEL_ID, centerId);
} else if (officeId != null ) {
groupTemplateData = this.groupReadPlatformService.retrieveNewGroupDetails(officeId, LEVEL_ID);
} else{
groupTemplateData = this.groupReadPlatformService.retrieveNewGroupDetails(this.context.authenticatedUser().getOffice().getId(),
LEVEL_ID);
if (template) {
final GroupGeneralData templateGroup = this.groupReadPlatformService.retrieveTemplate(group.officeId(), false);
group = GroupGeneralData.withTemplateAndAssociations(templateGroup, group, membersOfGroup);
} else {
group = GroupGeneralData.withAssocations(group, membersOfGroup);
}
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, groupTemplateData, GROUP_DATA_PARAMETERS);
return this.groupGeneralApiJsonSerializer.serialize(settings, group, GroupingTypesApiConstants.GROUP_RESPONSE_DATA_PARAMETERS);
}
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createGroup(final String apiRequestBodyAsJson) {
public String create(final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.createGroup() //
@@ -141,7 +155,6 @@ public class GroupsApiResource {
.build(); //
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
@POST
@@ -163,7 +176,7 @@ public class GroupsApiResource {
@Path("{groupId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateGroup(@PathParam("groupId") final Long groupId, final String apiRequestBodyAsJson) {
public String update(@PathParam("groupId") final Long groupId, final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.updateGroup(groupId) //
@@ -177,21 +190,20 @@ public class GroupsApiResource {
@Path("{groupId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteGroup(@PathParam("groupId") final Long groupId) {
public String delete(@PathParam("groupId") final Long groupId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.deleteGroup(groupId) //
.build(); //
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
@GET
@Path("{groupId}/loans")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveGroupAccount(@PathParam("groupId") final Long groupId, @Context final UriInfo uriInfo) {
public String retrieveLoans(@PathParam("groupId") final Long groupId, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission("GROUP");
@@ -204,46 +216,4 @@ public class GroupsApiResource {
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.groupSummaryToApiJsonSerializer.serialize(settings, groupAccount, GROUP_ACCOUNTS_DATA_PARAMETERS);
}
// 'g.' preffix because of ERROR 1052 (23000): Column 'column_name' in where
// clause is ambiguous
// caused by the same name of columns in m_office and m_group tables
private String getGroupExtraCriteria(String sqlSearch, final Long officeId, final String externalId, final String name,
final Long levelId , final String hierarchy) {
String extraCriteria = "";
if (sqlSearch != null) {
sqlSearch = sqlSearch.replaceAll(" name ", " g.name ");
sqlSearch = sqlSearch.replaceAll("name ", "g.name ");
extraCriteria = " and (" + sqlSearch + ")";
}
if (officeId != null) {
extraCriteria += " and g.office_id = " + officeId;
}
if (levelId != null) {
extraCriteria += " and g.level_Id = " + levelId;
}
if (externalId != null) {
extraCriteria += " and g.external_id = " + ApiParameterHelper.sqlEncodeString(externalId);
}
if (name != null) {
extraCriteria += " and g.name like " + ApiParameterHelper.sqlEncodeString(name + "%");
}
if (hierarchy != null) {
extraCriteria += " and o.hierarchy like " + ApiParameterHelper.sqlEncodeString(hierarchy + "%");
}
if (StringUtils.isNotBlank(extraCriteria)) {
extraCriteria = extraCriteria.substring(4);
}
return extraCriteria;
}
}
@@ -0,0 +1,90 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.group.data;
import java.util.Collection;
import org.mifosplatform.organisation.office.data.OfficeData;
import org.mifosplatform.organisation.staff.data.StaffData;
/**
* Immutable data object representing groups.
*/
public class CenterData {
private final Long id;
private final String name;
private final String externalId;
private final Long officeId;
private final String officeName;
private final Long staffId;
private final String staffName;
private final String hierarchy;
// associations
@SuppressWarnings("unused")
private final Collection<GroupGeneralData> groups;
// template
private final Collection<OfficeData> officeOptions;
private final Collection<StaffData> staffOptions;
public static CenterData template(final Long officeId, final Collection<OfficeData> officeOptions,
final Collection<StaffData> staffOptions) {
return new CenterData(null, null, null, officeId, null, null, null, null, officeOptions, staffOptions);
}
public static CenterData withTemplate(final CenterData templateCenter, final CenterData center) {
return new CenterData(center.id, center.name, center.externalId, center.officeId, center.officeName, center.staffId,
center.staffName, center.hierarchy, templateCenter.officeOptions, templateCenter.staffOptions);
}
public static CenterData instance(final Long id, final String name, final String externalId, final Long officeId,
final String officeName, final Long staffId, final String staffName, final String hierarchy) {
final Collection<OfficeData> officeOptions = null;
final Collection<StaffData> staffOptions = null;
return new CenterData(id, name, externalId, officeId, officeName, staffId, staffName, hierarchy, officeOptions, staffOptions);
}
private CenterData(final Long id, final String name, final String externalId, final Long officeId, final String officeName,
final Long staffId, final String staffName, final String hierarchy, final Collection<OfficeData> officeOptions,
final Collection<StaffData> staffOptions) {
this.id = id;
this.name = name;
this.externalId = externalId;
this.officeId = officeId;
this.officeName = officeName;
this.staffId = staffId;
this.staffName = staffName;
this.hierarchy = hierarchy;
this.officeOptions = officeOptions;
this.staffOptions = staffOptions;
this.groups = null;
}
public Long officeId() {
return this.officeId;
}
public Long staffId() {
return this.staffId;
}
public Long getId() {
return this.id;
}
public String getName() {
return this.name;
}
public String getHierarchy() {
return this.hierarchy;
}
}
@@ -1,179 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.group.data;
import java.util.Collection;
import org.mifosplatform.organisation.office.data.OfficeData;
import org.mifosplatform.organisation.staff.data.StaffData;
import org.mifosplatform.portfolio.client.data.ClientLookup;
/**
* Immutable data object representing groups.
*/
public class GroupData {
private final Long id;
private final String name;
private final String externalId;
private final Long officeId;
private final String officeName;
private final Long staffId;
private final String staffName;
private final Long parentId;
private final String parentName;
private final String hierarchy;
@SuppressWarnings("unused")
private final GroupSummary groupSummaryData;
@SuppressWarnings("unused")
private final GroupLevelData groupLevelData;
private final Collection<ClientLookup> clientMembers;
@SuppressWarnings("unused")
private final Collection<ClientLookup> allowedClients;
@SuppressWarnings("unused")
private final Collection<OfficeData> allowedOffices;
@SuppressWarnings("unused")
private final Collection<GroupLookup> allowedParentGroups;
@SuppressWarnings("unused")
private final Collection<StaffData> allowedStaffs;
@SuppressWarnings("unused")
private final Collection<GroupLookup> childGroups;
public GroupData(Long id, String name, String externalId, Long officeId, Long staffId, Long parentId, String hierarchy) {
this.id = id;
this.name = name;
this.externalId = externalId;
this.officeId = officeId;
this.staffId = staffId;
this.parentId = parentId;
this.hierarchy = hierarchy;
this.officeName = null;
this.parentName = null;
this.staffName = null;
this.groupSummaryData = null;
this.groupLevelData = null;
this.clientMembers = null;
this.allowedClients = null;
this.allowedOffices = null;
this.allowedParentGroups = null;
this.allowedStaffs = null;
this.childGroups = null;
}
public GroupData(final Long id, final Long officeId, final String officeName, final String name, final String externalId,
final Long parentId, final String parentName, final Long staffId, final String staffName, final String hierarchy) {
this.id = id;
this.officeId = officeId;
this.officeName = officeName;
this.name = name;
this.externalId = externalId;
this.parentId = parentId;
this.parentName = parentName;
this.staffId = staffId;
this.staffName = staffName;
this.hierarchy = hierarchy;
this.groupSummaryData = null;
this.groupLevelData = null;
this.clientMembers = null;
this.allowedClients = null;
this.allowedOffices = null;
this.allowedParentGroups = null;
this.allowedStaffs = null;
this.childGroups = null;
}
public GroupData(final GroupData group, final Collection<ClientLookup> clientMembers, final Collection<ClientLookup> allowedClients,
final Collection<OfficeData> allowedOffices, final Collection<GroupLookup> allowedParentGroups,
final GroupLevelData groupLevelData, final Collection<StaffData> allowedStaffs, final Collection<GroupLookup> childGroups,
final GroupSummary groupSummaryData) {
this.id = group.getId();
this.officeId = group.getOfficeId();
this.officeName = group.getOfficeName();
this.name = group.getName();
this.externalId = group.getExternalId();
this.parentId = group.getParentId();
this.parentName = group.getParentName();
this.staffId = group.getStaffId();
this.staffName = group.getStaffName();
this.hierarchy = group.getHierarchy();
this.groupSummaryData = groupSummaryData;
this.groupLevelData = groupLevelData;
this.clientMembers = clientMembers;
this.allowedClients = allowedClients;
this.allowedOffices = allowedOffices;
this.allowedParentGroups = allowedParentGroups;
this.allowedStaffs = allowedStaffs;
this.childGroups = childGroups;
}
public GroupData(final Long officeId, final Collection<ClientLookup> allowedClients, final Collection<OfficeData> allowedOffices,
final Collection<GroupLookup> allowedParentGroups, final GroupLevelData groupLevelData,
final Collection<StaffData> allowedStaffs) {
this.id = null;
this.officeId = officeId;
this.officeName = null;
this.name = null;
this.externalId = null;
this.clientMembers = null;
this.parentId = null;
this.parentName = null;
this.staffId = null;
this.staffName = null;
this.hierarchy = null;
this.groupSummaryData = null;
this.groupLevelData = groupLevelData;
this.allowedClients = allowedClients;
this.allowedOffices = allowedOffices;
this.allowedParentGroups = allowedParentGroups;
this.allowedStaffs = allowedStaffs;
this.childGroups = null;
}
public Long getId() {
return this.id;
}
public String getName() {
return this.name;
}
public String getExternalId() {
return this.externalId;
}
public Long getOfficeId() {
return this.officeId;
}
public String getOfficeName() {
return this.officeName;
}
public Long getParentId() {
return this.parentId;
}
public Long getStaffId() {
return this.staffId;
}
public String getStaffName() {
return this.staffName;
}
public String getParentName() {
return this.parentName;
}
public String getHierarchy() {
return this.hierarchy;
}
public Collection<ClientLookup> clientMembers() {
return this.clientMembers;
}
}
@@ -0,0 +1,132 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.group.data;
import java.util.Collection;
import org.mifosplatform.organisation.office.data.OfficeData;
import org.mifosplatform.organisation.staff.data.StaffData;
import org.mifosplatform.portfolio.client.data.ClientData;
/**
* Immutable data object representing a general group (so may or may not have a
* parent).
*/
public class GroupGeneralData {
private final Long id;
private final String name;
private final String externalId;
private final Long officeId;
private final String officeName;
private final Long centerId;
private final String centerName;
private final Long staffId;
private final String staffName;
private final String hierarchy;
// associations
private final Collection<ClientData> clientMembers;
// template
private final Collection<CenterData> centerOptions;
private final Collection<OfficeData> officeOptions;
private final Collection<StaffData> staffOptions;
private final Collection<ClientData> clientOptions;
public static GroupGeneralData lookup(final Long groupId, final String groupName) {
final Collection<ClientData> clientMembers = null;
return new GroupGeneralData(groupId, groupName, null, null, null, null, null, null, null, null, clientMembers, null, null, 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<ClientData> clientMembers = null;
return new GroupGeneralData(null, null, null, officeId, null, centerId, centerName, staffId, staffName, null, clientMembers,
centerOptions, officeOptions, staffOptions, clientOptions);
}
public static GroupGeneralData withTemplate(final GroupGeneralData templatedGrouping, final GroupGeneralData grouping) {
return new GroupGeneralData(grouping.id, grouping.name, grouping.externalId, grouping.officeId, grouping.officeName,
grouping.centerId, grouping.centerName, grouping.staffId, grouping.staffName, grouping.hierarchy, grouping.clientMembers,
templatedGrouping.centerOptions, templatedGrouping.officeOptions, templatedGrouping.staffOptions,
templatedGrouping.clientOptions);
}
public static GroupGeneralData withTemplateAndAssociations(final GroupGeneralData templatedGrouping, final GroupGeneralData grouping,
final Collection<ClientData> membersOfGroup) {
return new GroupGeneralData(grouping.id, grouping.name, grouping.externalId, grouping.officeId, grouping.officeName,
grouping.centerId, grouping.centerName, grouping.staffId, grouping.staffName, grouping.hierarchy, membersOfGroup,
templatedGrouping.centerOptions, templatedGrouping.officeOptions, templatedGrouping.staffOptions,
templatedGrouping.clientOptions);
}
public static GroupGeneralData withAssocations(final GroupGeneralData grouping, final Collection<ClientData> membersOfGroup) {
return new GroupGeneralData(grouping.id, grouping.name, grouping.externalId, grouping.officeId, grouping.officeName,
grouping.centerId, grouping.centerName, grouping.staffId, grouping.staffName, grouping.hierarchy, membersOfGroup,
grouping.centerOptions, grouping.officeOptions, grouping.staffOptions, grouping.clientOptions);
}
public static GroupGeneralData instance(final Long id, final String name, final String externalId, final Long officeId,
final String officeName, final Long parentId, final String parentName, final Long staffId, final String staffName,
final String hierarchy) {
final Collection<ClientData> clientMembers = null;
final Collection<CenterData> centerOptions = null;
final Collection<OfficeData> officeOptions = null;
final Collection<StaffData> staffOptions = null;
final Collection<ClientData> clientOptions = null;
return new GroupGeneralData(id, name, externalId, officeId, officeName, parentId, parentName, staffId, staffName, hierarchy,
clientMembers, centerOptions, officeOptions, staffOptions, clientOptions);
}
private GroupGeneralData(final Long id, final String name, final String externalId, final Long officeId, final String officeName,
final Long parentId, final String parentName, 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) {
this.id = id;
this.name = name;
this.externalId = externalId;
this.officeId = officeId;
this.officeName = officeName;
this.centerId = parentId;
this.centerName = parentName;
this.staffId = staffId;
this.staffName = staffName;
this.hierarchy = hierarchy;
// associations
this.clientMembers = clientMembers;
// template
this.centerOptions = centerOptions;
this.officeOptions = officeOptions;
this.staffOptions = staffOptions;
if (clientMembers != null && clientOptions != null) {
clientOptions.removeAll(clientMembers);
}
this.clientOptions = clientOptions;
}
public Long getId() {
return this.id;
}
public String getName() {
return this.name;
}
public Long officeId() {
return this.officeId;
}
}
@@ -8,6 +8,7 @@ package org.mifosplatform.portfolio.group.data;
/**
* Immutable data object representing groups.
*/
@Deprecated
public class GroupLookup {
private final Long id;
@@ -68,5 +68,4 @@ public enum GroupTypes {
public String getValue() {
return this.value;
}
}
}
@@ -0,0 +1,24 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.group.service;
import java.util.Collection;
import org.mifosplatform.portfolio.group.data.CenterData;
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
public interface CenterReadPlatformService {
CenterData retrieveTemplate(Long officeId);
CenterData retrieveOne(Long centerId);
Collection<CenterData> retrieveAllForDropdown(Long officeId);
Collection<CenterData> retrieveAll(SearchParameters searchCriteria);
GroupGeneralData retrieveCenterGroupTemplate(Long centerId);
}
@@ -0,0 +1,234 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.group.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collection;
import org.apache.commons.lang.StringUtils;
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
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.ClientData;
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
import org.mifosplatform.portfolio.group.data.CenterData;
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
import org.mifosplatform.portfolio.group.data.GroupTypes;
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
import org.mifosplatform.useradministration.domain.AppUser;
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;
import org.springframework.util.CollectionUtils;
@Service
public class CenterReadPlatformServiceImpl implements CenterReadPlatformService {
private final JdbcTemplate jdbcTemplate;
private final PlatformSecurityContext context;
private final ClientReadPlatformService clientReadPlatformService;
private final OfficeReadPlatformService officeReadPlatformService;
private final StaffReadPlatformService staffReadPlatformService;
private final CenterDataMapper centerMapper = new CenterDataMapper();
@Autowired
public CenterReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource,
final ClientReadPlatformService clientReadPlatformService, final OfficeReadPlatformService officeReadPlatformService,
final StaffReadPlatformService staffReadPlatformService) {
this.context = context;
this.clientReadPlatformService = clientReadPlatformService;
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.officeReadPlatformService = officeReadPlatformService;
this.staffReadPlatformService = staffReadPlatformService;
}
// 'g.' preffix because of ERROR 1052 (23000): Column 'column_name' in where
// clause is ambiguous
// caused by the same name of columns in m_office and m_group tables
private String getCenterExtraCriteria(final SearchParameters searchCriteria) {
String extraCriteria = " and g.level_id = " + GroupTypes.CENTER.getId() + " ";
String sqlQueryCriteria = searchCriteria.getSqlSearch();
if (StringUtils.isNotBlank(sqlQueryCriteria)) {
sqlQueryCriteria = sqlQueryCriteria.replaceAll(" name ", " g.name ");
sqlQueryCriteria = sqlQueryCriteria.replaceAll("name ", "g.name ");
extraCriteria = " and (" + sqlQueryCriteria + ")";
}
final Long officeId = searchCriteria.getOfficeId();
if (officeId != null) {
extraCriteria += " and g.office_id = " + officeId;
}
final String externalId = searchCriteria.getExternalId();
if (externalId != null) {
extraCriteria += " and g.external_id = " + ApiParameterHelper.sqlEncodeString(externalId);
}
final String name = searchCriteria.getName();
if (name != null) {
extraCriteria += " and g.name like " + ApiParameterHelper.sqlEncodeString(name + "%");
}
final String hierarchy = searchCriteria.getHierarchy();
if (hierarchy != null) {
extraCriteria += " and o.hierarchy like " + ApiParameterHelper.sqlEncodeString(hierarchy + "%");
}
if (StringUtils.isNotBlank(extraCriteria)) {
extraCriteria = extraCriteria.substring(4);
}
return extraCriteria;
}
private static final class CenterDataMapper implements RowMapper<CenterData> {
private final String schemaSql;
public CenterDataMapper() {
final StringBuilder sqlBuilder = new StringBuilder(400);
sqlBuilder.append("g.id as id, g.external_id as externalId, g.name as name, ");
sqlBuilder.append("g.office_id as officeId, o.name as officeName, ");
sqlBuilder.append("g.staff_id as staffId, s.display_name as staffName, ");
sqlBuilder.append("g.hierarchy as hierarchy ");
sqlBuilder.append("from m_group g ");
sqlBuilder.append("join m_office o on o.id = g.office_id ");
sqlBuilder.append("left join m_staff s on s.id = g.staff_id ");
this.schemaSql = sqlBuilder.toString();
}
public String schema() {
return this.schemaSql;
}
@Override
public CenterData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final String name = rs.getString("name");
final String externalId = rs.getString("externalId");
final Long officeId = rs.getLong("officeId");
final String officeName = rs.getString("officeName");
final Long staffId = JdbcSupport.getLong(rs, "staffId");
final String staffName = rs.getString("staffName");
final String hierarchy = rs.getString("hierarchy");
return CenterData.instance(id, name, externalId, officeId, officeName, staffId, staffName, hierarchy);
}
}
@Override
public Collection<CenterData> retrieveAll(final SearchParameters searchCriteria) {
this.context.authenticatedUser();
final AppUser currentUser = context.authenticatedUser();
final String hierarchy = currentUser.getOffice().getHierarchy();
final String hierarchySearchString = hierarchy + "%";
String sql = "select " + centerMapper.schema() + " where o.hierarchy like ?";
final String extraCriteria = getCenterExtraCriteria(searchCriteria);
if (StringUtils.isNotBlank(extraCriteria)) {
sql += " and (" + extraCriteria + ")";
}
sql += "order by g.hierarchy";
return this.jdbcTemplate.query(sql, centerMapper, new Object[] { hierarchySearchString });
}
@Override
public Collection<CenterData> retrieveAllForDropdown(final Long officeId) {
this.context.authenticatedUser();
final AppUser currentUser = context.authenticatedUser();
final String hierarchy = currentUser.getOffice().getHierarchy();
final String hierarchySearchString = hierarchy + "%";
final String sql = "select " + centerMapper.schema()
+ " where g.office_id = ? and g.parent_id is null and g.level_Id = ? and o.hierarchy like ? order by g.hierarchy";
return this.jdbcTemplate.query(sql, centerMapper, new Object[] { officeId, GroupTypes.CENTER.getId(), hierarchySearchString });
}
@Override
public CenterData retrieveTemplate(final Long officeId) {
final Collection<OfficeData> officeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
Collection<StaffData> staffOptions = this.staffReadPlatformService.retrieveAllStaffForDropdown(officeId);
if (CollectionUtils.isEmpty(staffOptions)) {
staffOptions = null;
}
return CenterData.template(officeId, officeOptions, staffOptions);
}
@Override
public CenterData retrieveOne(final Long centerId) {
try {
final AppUser currentUser = context.authenticatedUser();
final String hierarchy = currentUser.getOffice().getHierarchy();
final String hierarchySearchString = hierarchy + "%";
String sql = "select " + this.centerMapper.schema() + " where g.id = ? and o.hierarchy like ?";
return this.jdbcTemplate.queryForObject(sql, this.centerMapper, new Object[] { centerId, hierarchySearchString });
} catch (EmptyResultDataAccessException e) {
throw new GroupNotFoundException(centerId);
}
}
@Override
public GroupGeneralData retrieveCenterGroupTemplate(final Long centerId) {
final CenterData center = this.retrieveOne(centerId);
final Long centerOfficeId = center.officeId();
final OfficeData centerOffice = this.officeReadPlatformService.retrieveOffice(centerOfficeId);
StaffData staff = null;
final Long staffId = center.staffId();
String staffName = null;
if (staffId != null) {
staff = this.staffReadPlatformService.retrieveStaff(staffId);
staffName = staff.getDisplayName();
}
final Collection<CenterData> centerOptions = Arrays.asList(center);
final Collection<OfficeData> officeOptions = Arrays.asList(centerOffice);
Collection<StaffData> staffOptions = this.staffReadPlatformService.retrieveAllStaffForDropdown(centerOfficeId);
if (CollectionUtils.isEmpty(staffOptions)) {
staffOptions = null;
}
Collection<ClientData> clientOptions = this.clientReadPlatformService
.retrieveAllIndividualClientsForLookupByOfficeId(centerOfficeId);
if (CollectionUtils.isEmpty(clientOptions)) {
clientOptions = null;
}
return GroupGeneralData.template(centerOfficeId, center.getId(), center.getName(), staffId, staffName, centerOptions,
officeOptions, staffOptions, clientOptions);
}
}
@@ -9,47 +9,35 @@ import java.util.Collection;
import org.mifosplatform.organisation.monetary.data.MoneyData;
import org.mifosplatform.organisation.staff.data.StaffData;
import org.mifosplatform.portfolio.client.data.ClientLookup;
import org.mifosplatform.portfolio.group.data.GroupAccountSummaryCollectionData;
import org.mifosplatform.portfolio.group.data.GroupAccountSummaryData;
import org.mifosplatform.portfolio.group.data.GroupData;
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
import org.mifosplatform.portfolio.group.data.GroupLevelData;
import org.mifosplatform.portfolio.group.data.GroupLookup;
public interface GroupReadPlatformService {
Collection<GroupData> retrieveAllGroups(String extraCriteria);
GroupGeneralData retrieveTemplate(Long officeId, boolean isCenterGroup);
GroupData retrieveGroup(Long groupId, Long levelId);
Collection<GroupGeneralData> retrieveAll(SearchParameters searchCriteria);
GroupData retrieveNewGroupDetails(Long officeId, Long levelId);
Collection<ClientLookup> retrieveClientMembers(Long groupId);
GroupGeneralData retrieveOne(Long groupId);
//
GroupAccountSummaryCollectionData retrieveGroupAccountDetails(Long groupId);
Collection<GroupAccountSummaryData> retrieveGroupLoanAccountsByLoanOfficerId(Long groupId, Long loanOfficerId);
Collection<GroupLookup> retrieveAllGroupsbyOfficeIdAndLevelId(Long officeId, Long levelId);
GroupLevelData retrieveGroupLevelDetails(Long levelId);
Collection<StaffData> retrieveStaffsbyOfficeId(Long officeId);
GroupData retrieveGroupDetails(Long groupId, Long levelId, boolean template);
Collection<GroupLookup> retrieveChildGroupsbyGroupId(Long groupId);
Long retrieveTotalNoOfChildGroups(Long groupId);
Long retrieveTotalClients(String hierarchy);
Collection<MoneyData> retrieveGroupLoanPortfolio(String hierarchy);
GroupData retrieveNewChildGroupDetails(Long officeId, Long levelId, Long parentGroupId);
StaffData retrieveStaffsbyId(Long staffId);
Long getLevelIdByGroupId(final Long groupId);
}
Long getLevelIdByGroupId(final Long groupId);
}
@@ -13,6 +13,7 @@ import java.util.Collection;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
@@ -21,17 +22,16 @@ 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.exception.StaffNotFoundException;
import org.mifosplatform.portfolio.client.data.ClientLookup;
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.data.CenterData;
import org.mifosplatform.portfolio.group.data.GroupAccountSummaryCollectionData;
import org.mifosplatform.portfolio.group.data.GroupAccountSummaryData;
import org.mifosplatform.portfolio.group.data.GroupData;
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
import org.mifosplatform.portfolio.group.data.GroupLevelData;
import org.mifosplatform.portfolio.group.data.GroupLookup;
import org.mifosplatform.portfolio.group.data.GroupSummary;
import org.mifosplatform.portfolio.group.domain.Group;
import org.mifosplatform.portfolio.group.domain.GroupRepository;
import org.mifosplatform.portfolio.group.data.GroupTypes;
import org.mifosplatform.portfolio.group.exception.GroupLevelNotFoundException;
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
import org.mifosplatform.useradministration.domain.AppUser;
@@ -40,6 +40,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 GroupReadPlatformServiceImpl implements GroupReadPlatformService {
@@ -48,90 +49,136 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
private final PlatformSecurityContext context;
private final ClientReadPlatformService clientReadPlatformService;
private final OfficeReadPlatformService officeReadPlatformService;
private final GroupRepository groupRepository;
private final StaffReadPlatformService staffReadPlatformService;
private final AllGroupTypesDataMapper allGroupTypesDataMapper = new AllGroupTypesDataMapper();
private final CenterReadPlatformService centerReadPlatformService;
@Autowired
public GroupReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource,
final ClientReadPlatformService clientReadPlatformService, final OfficeReadPlatformService officeReadPlatformService,
final GroupRepository groupRepository) {
final CenterReadPlatformService centerReadPlatformService, final ClientReadPlatformService clientReadPlatformService,
final OfficeReadPlatformService officeReadPlatformService, final StaffReadPlatformService staffReadPlatformService) {
this.context = context;
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.centerReadPlatformService = centerReadPlatformService;
this.clientReadPlatformService = clientReadPlatformService;
this.officeReadPlatformService = officeReadPlatformService;
this.groupRepository = groupRepository;
this.staffReadPlatformService = staffReadPlatformService;
}
@Override
public Collection<GroupData> retrieveAllGroups(final String extraCriteria) {
public GroupGeneralData retrieveTemplate(final Long officeId, final boolean isCenterGroup) {
this.context.authenticatedUser();
AppUser currentUser = context.authenticatedUser();
String hierarchy = currentUser.getOffice().getHierarchy();
String hierarchySearchString = hierarchy + "%";
final Long defaultOfficeId = defaultToUsersOfficeIfNull(officeId);
final GroupDataMapper rm = new GroupDataMapper();
Collection<CenterData> centerOptions = null;
if (isCenterGroup) {
centerOptions = this.centerReadPlatformService.retrieveAllForDropdown(defaultOfficeId);
}
String sql = "select " + rm.groupSchema() + " where o.hierarchy like ? and g.is_deleted=0 ";
final Collection<OfficeData> officeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
Collection<StaffData> staffOptions = this.staffReadPlatformService.retrieveAllStaffForDropdown(defaultOfficeId);
if (CollectionUtils.isEmpty(staffOptions)) {
staffOptions = null;
}
Collection<ClientData> clientOptions = this.clientReadPlatformService
.retrieveAllIndividualClientsForLookupByOfficeId(defaultOfficeId);
if (CollectionUtils.isEmpty(clientOptions)) {
clientOptions = null;
}
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);
}
private Long defaultToUsersOfficeIfNull(final Long officeId) {
Long defaultOfficeId = officeId;
if (defaultOfficeId == null) {
defaultOfficeId = this.context.authenticatedUser().getOffice().getId();
}
return defaultOfficeId;
}
@Override
public Collection<GroupGeneralData> retrieveAll(final SearchParameters searchCriteria) {
final AppUser currentUser = context.authenticatedUser();
final String hierarchy = currentUser.getOffice().getHierarchy();
final String hierarchySearchString = hierarchy + "%";
String sql = "select " + this.allGroupTypesDataMapper.schema() + " where o.hierarchy like ?";
final String extraCriteria = getGroupExtraCriteria(searchCriteria);
if (StringUtils.isNotBlank(extraCriteria)) {
sql += " and (" + extraCriteria + ")";
}
sql += "order by g.hierarchy";
return this.jdbcTemplate.query(sql, rm, new Object[] {hierarchySearchString});
sql += " order by g.hierarchy";
return this.jdbcTemplate.query(sql, this.allGroupTypesDataMapper, new Object[] { hierarchySearchString });
}
// 'g.' preffix because of ERROR 1052 (23000): Column 'column_name' in where
// clause is ambiguous
// caused by the same name of columns in m_office and m_group tables
private String getGroupExtraCriteria(final SearchParameters searchCriteria) {
String extraCriteria = " and g.level_Id = " + GroupTypes.GROUP.getId();
String sqlSearch = searchCriteria.getSqlSearch();
if (sqlSearch != null) {
sqlSearch = sqlSearch.replaceAll(" name ", " g.name ");
sqlSearch = sqlSearch.replaceAll("name ", "g.name ");
extraCriteria = " and (" + sqlSearch + ")";
}
final Long officeId = searchCriteria.getOfficeId();
if (officeId != null) {
extraCriteria += " and g.office_id = " + officeId;
}
final String externalId = searchCriteria.getExternalId();
if (externalId != null) {
extraCriteria += " and g.external_id = " + ApiParameterHelper.sqlEncodeString(externalId);
}
final String name = searchCriteria.getName();
if (name != null) {
extraCriteria += " and g.name like " + ApiParameterHelper.sqlEncodeString("%" + name + "%");
}
final String hierarchy = searchCriteria.getHierarchy();
if (hierarchy != null) {
extraCriteria += " and o.hierarchy like " + ApiParameterHelper.sqlEncodeString(hierarchy + "%");
}
if (StringUtils.isNotBlank(extraCriteria)) {
extraCriteria = extraCriteria.substring(4);
}
return extraCriteria;
}
@Override
public GroupData retrieveGroup(final Long groupId , final Long levelId) {
public GroupGeneralData retrieveOne(final Long groupId) {
try {
this.context.authenticatedUser();
final AppUser currentUser = context.authenticatedUser();
final String hierarchy = currentUser.getOffice().getHierarchy();
final String hierarchySearchString = hierarchy + "%";
final GroupDataMapper rm = new GroupDataMapper();
final String sql = "select " + rm.groupSchema() + " where g.id = ? and g.is_deleted=0 and g.level_id = " + levelId;
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { groupId });
} catch (final EmptyResultDataAccessException e) {
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) {
throw new GroupNotFoundException(groupId);
}
}
@Override
public Collection<GroupLookup> retrieveAllGroupsbyOfficeIdAndLevelId(final Long officeId, final Long levelId) {
this.context.authenticatedUser();
final GroupLookupMapper rm = new GroupLookupMapper();
final String sql = "select " + rm.groupLookupSchema() + " from m_group g where g.office_id = ? and level_id = ? and g.is_deleted=0";
return this.jdbcTemplate.query(sql, rm, new Object[] { officeId, levelId });
}
private GroupLookup retrieveGroupbyId(final Long parentGroupId) {
try {
this.context.authenticatedUser();
final GroupLookupMapper rm = new GroupLookupMapper();
final String sql = "select " + rm.groupLookupSchema() + " from m_group g where g.id = ? and g.is_deleted=0";
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { parentGroupId });
} catch (final EmptyResultDataAccessException e) {
throw new GroupNotFoundException(parentGroupId);
}
}
@Override
public Collection<GroupLookup> retrieveChildGroupsbyGroupId(final Long groupId) {
this.context.authenticatedUser();
final GroupLookupMapper rm = new GroupLookupMapper();
final String sql = "select " + rm.groupLookupSchema()
+ " from m_group pg join m_group g where pg.id = g.parent_id and pg.id = ? and g.is_deleted=0";
return this.jdbcTemplate.query(sql, rm, new Object[] { groupId });
}
@Override
public GroupLevelData retrieveGroupLevelDetails(final Long levelId) {
@@ -146,108 +193,6 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
}
}
@Override
public GroupData retrieveNewGroupDetails(final Long officeId, final Long levelId) {
final GroupLevelData groupLevelData = retrieveGroupLevelDetails(levelId);
if (groupLevelData == null) { throw new GroupLevelNotFoundException(levelId); }
List<ClientLookup> allowedClients = null;
if (groupLevelData.isCanHaveClients()) {
allowedClients = new ArrayList<ClientLookup>(
this.clientReadPlatformService.retrieveAllIndividualClientsForLookupByOfficeId(officeId));
}
final List<OfficeData> allowedOffices = new ArrayList<OfficeData>(this.officeReadPlatformService.retrieveAllOfficesForDropdown());
List<GroupLookup> allowedParentGroups = null;
if (groupLevelData.getParentLevelId() != null) {
allowedParentGroups = new ArrayList<GroupLookup>(retrieveAllGroupsbyOfficeIdAndLevelId(officeId,
groupLevelData.getParentLevelId()));
}
final List<StaffData> allowedStaffs = new ArrayList<StaffData>(retrieveStaffsbyOfficeId(officeId));
return new GroupData(officeId, allowedClients, allowedOffices, allowedParentGroups, groupLevelData, allowedStaffs);
}
@Override
public GroupData retrieveNewChildGroupDetails(Long officeId, final Long levelId, final Long parentGroupId) {
final GroupLevelData groupLevelData = retrieveGroupLevelDetails(levelId);
if (groupLevelData == null) { throw new GroupLevelNotFoundException(levelId); }
final Group group = this.groupRepository.findOne(parentGroupId);
if (group == null || group.isDeleted()) { throw new GroupNotFoundException(parentGroupId); }
if (officeId == null) {
officeId = group.getOfficeId();
}
List<ClientLookup> allowedClients = null;
if (groupLevelData.isCanHaveClients()) {
allowedClients = new ArrayList<ClientLookup>(
this.clientReadPlatformService.retrieveAllIndividualClientsForLookupByOfficeId(officeId));
}
final List<OfficeData> allowedOffices = new ArrayList<OfficeData>();
allowedOffices.add(this.officeReadPlatformService.retrieveOffice(officeId));
final List<GroupLookup> allowedParentGroups = new ArrayList<GroupLookup>();
allowedParentGroups.add(retrieveGroupbyId(parentGroupId));
final List<StaffData> allowedStaffs = new ArrayList<StaffData>();
allowedStaffs.addAll(retrieveStaffsbyOfficeId(officeId));
return new GroupData(officeId, allowedClients, allowedOffices, allowedParentGroups, groupLevelData, allowedStaffs);
}
@Override
public GroupData retrieveGroupDetails(final Long groupId, final Long levelId , final boolean template) {
GroupData group = retrieveGroup(groupId, levelId);
final Collection<ClientLookup> clientMembers = retrieveClientMembers(groupId);
Collection<ClientLookup> availableClients = null;
Collection<OfficeData> allowedOffices = null;
Collection<GroupLookup> allowedParentGroups = null;
final GroupLevelData groupLevelData = retrieveGroupLevelDetails(getLevelIdByGroupId(groupId));
;
Collection<StaffData> allowedStaffs = null;
final Collection<GroupLookup> childGroups = retrieveChildGroupsbyGroupId(groupId);
final Long totalActiveClients = retrieveTotalClients(group.getHierarchy());
final Long totalChildGroups = retrieveTotalNoOfChildGroups(groupId);
final Collection<MoneyData> totalLoanPortfolio = retrieveGroupLoanPortfolio(group.getHierarchy());
final GroupSummary groupSummaryData = new GroupSummary(totalActiveClients, totalChildGroups, totalLoanPortfolio, null);
group = new GroupData(group, clientMembers, availableClients, allowedOffices, allowedParentGroups, groupLevelData, allowedStaffs,
childGroups, groupSummaryData);
if (template) {
if (groupLevelData.isCanHaveClients()) {
availableClients = this.clientReadPlatformService.retrieveAllIndividualClientsForLookupByOfficeId(group.getOfficeId());
availableClients.removeAll(group.clientMembers());
}
allowedOffices = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
if (groupLevelData.getParentLevelId() != null) {
allowedParentGroups = retrieveAllGroupsbyOfficeIdAndLevelId(group.getOfficeId(), groupLevelData.getParentLevelId());
}
allowedStaffs = retrieveStaffsbyOfficeId(group.getOfficeId());
group = new GroupData(group, group.clientMembers(), availableClients, allowedOffices, allowedParentGroups, groupLevelData,
allowedStaffs, childGroups, groupSummaryData);
}
return group;
}
@Override
public Collection<StaffData> retrieveStaffsbyOfficeId(final Long officeId) {
@@ -273,14 +218,14 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
}
@Override
public Long getLevelIdByGroupId(final Long groupId){
public Long getLevelIdByGroupId(final Long groupId) {
this.context.authenticatedUser();
final String sqlTotalClients = "SELECT g.level_Id as levelId FROM m_group g WHERE g.id = ?";
return this.jdbcTemplate.queryForLong(sqlTotalClients, new Object[] { groupId });
}
@Override
public Long retrieveTotalClients(final String hierarchy) {
@@ -333,25 +278,39 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
return new MoneyData(currencyCode, amount, decimalPlaces);
}
}
private static final class GroupDataMapper implements RowMapper<GroupData> {
// GroupTopOfHierarchyData
private static final class AllGroupTypesDataMapper implements RowMapper<GroupGeneralData> {
public String groupSchema() {
return "g.office_id as officeId, g.parent_id as parentId , o.name as officeName,"
+ " g.id as id, g.external_id as externalId, g.name as name , s.display_name as staffName , pg.name as"
+ " parentName , g.staff_id as staffId , g.hierarchy as hierarchy from m_group g join m_office o on o.id = g.office_id left join"
+ " m_staff s on s.id = g.staff_id left join m_group pg on pg.id = g.parent_id";
private final String schemaSql;
public AllGroupTypesDataMapper() {
final StringBuilder sqlBuilder = new StringBuilder(400);
sqlBuilder.append("g.id as id, g.external_id as externalId, g.name as name, ");
sqlBuilder.append("g.office_id as officeId, o.name as officeName, ");
sqlBuilder.append("g.parent_id as parentId, pg.name as parentName, ");
sqlBuilder.append("g.staff_id as staffId, s.display_name as staffName, ");
sqlBuilder.append("g.hierarchy as hierarchy ");
sqlBuilder.append("from m_group g ");
sqlBuilder.append("join m_office o on o.id = g.office_id ");
sqlBuilder.append("left join m_staff s on s.id = g.staff_id ");
sqlBuilder.append("left join m_group pg on pg.id = g.parent_id ");
this.schemaSql = sqlBuilder.toString();
}
public String schema() {
return this.schemaSql;
}
@Override
public GroupData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
public GroupGeneralData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final String name = rs.getString("name");
final String externalId = rs.getString("externalId");
final Long officeId = rs.getLong("officeId");
final Long officeId = JdbcSupport.getLong(rs, "officeId");
final String officeName = rs.getString("officeName");
final Long parentId = JdbcSupport.getLong(rs, "parentId");
final String parentName = rs.getString("parentName");
@@ -359,27 +318,9 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
final String staffName = rs.getString("staffName");
final String hierarchy = rs.getString("hierarchy");
return new GroupData(id, officeId, officeName, name, externalId, parentId, parentName, staffId, staffName,
return GroupGeneralData.instance(id, name, externalId, officeId, officeName, parentId, parentName, staffId, staffName,
hierarchy);
}
}
private static final class GroupLookupMapper implements RowMapper<GroupLookup> {
public String groupLookupSchema() {
return "g.id as id, g.name as name ";
}
@Override
public GroupLookup mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final String name = rs.getString("name");
return new GroupLookup(id, name);
}
}
private static final class GroupLevelDataMapper implements RowMapper<GroupLevelData> {
@@ -430,35 +371,6 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
return StaffData.instance(id, firstname, lastname, displayName, officeId, officeName, isLoanOfficer);
}
}
@Override
public Collection<ClientLookup> retrieveClientMembers(final Long groupId) {
this.context.authenticatedUser();
final ClientMemberSummaryDataMapper rm = new ClientMemberSummaryDataMapper();
final String sql = "select " + rm.clientMemberSummarySchema() + " where cm.is_deleted = 0 and pgc.group_id = ?";
return this.jdbcTemplate.query(sql, rm, new Object[] { groupId });
}
private static final class ClientMemberSummaryDataMapper implements RowMapper<ClientLookup> {
public String clientMemberSummarySchema() {
return "cm.id, cm.display_name as displayName from m_client cm INNER JOIN m_group_client pgc ON pgc.client_id = cm.id";
}
@Override
public ClientLookup mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final String displayName = rs.getString("displayName");
return ClientLookup.create(id, displayName);
}
}
@Override
@@ -467,7 +379,7 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
this.context.authenticatedUser();
// Check if group exists
//retrieveGroup(groupId);
// retrieveGroup(groupId);
final List<GroupAccountSummaryData> pendingApprovalLoans = new ArrayList<GroupAccountSummaryData>();
final List<GroupAccountSummaryData> awaitingDisbursalLoans = new ArrayList<GroupAccountSummaryData>();
@@ -534,7 +446,7 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
this.context.authenticatedUser();
// Check if group exists
//retrieveGroup(groupId);
// retrieveGroup(groupId);
final GroupLoanAccountSummaryDataMapper rm = new GroupLoanAccountSummaryDataMapper();
@@ -569,5 +481,4 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
return new GroupAccountSummaryData(id, externalId, productId, loanProductName, loanStatusId);
}
}
}
}
@@ -10,10 +10,9 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
public interface GroupWritePlatformService {
CommandProcessingResult createGroup(Long parentId, Long levelId,
JsonCommand command);
CommandProcessingResult createGroup(Long parentId, Long levelId, JsonCommand command);
CommandProcessingResult updateGroup(Long grouptId, JsonCommand command);
CommandProcessingResult updateGroup(Long groupId, JsonCommand command);
CommandProcessingResult deleteGroup(Long groupId);
@@ -42,6 +42,7 @@ import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import com.google.common.collect.Sets;
@Service
@@ -72,8 +73,8 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla
@Transactional
@Override
public CommandProcessingResult createGroup(final Long parentId , final Long levelId , final JsonCommand command) {
public CommandProcessingResult createGroup(final Long parentId, final Long levelId, final JsonCommand command) {
GroupLevel groupLevel = this.groupLevelRepository.findOne(levelId);
try {
this.context.authenticatedUser();
@@ -137,17 +138,17 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla
.build();
} catch (final DataIntegrityViolationException dve) {
handleGroupDataIntegrityIssues(command, dve , groupLevel );
handleGroupDataIntegrityIssues(command, dve, groupLevel);
return new CommandProcessingResult(Long.valueOf(-1));
}
}
@Transactional
@Override
public CommandProcessingResult updateGroup(final Long grouptId, final JsonCommand command) {
public CommandProcessingResult updateGroup(final Long groupId, final JsonCommand command) {
GroupLevel groupLevel = null;
try {
this.context.authenticatedUser();
@@ -155,8 +156,8 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla
this.fromApiJsonDeserializer.validateForUpdate(command.json());
final Group groupForUpdate = this.groupRepository.findOne(grouptId);
if (groupForUpdate == null || groupForUpdate.isDeleted()) { throw new GroupNotFoundException(grouptId); }
final Group groupForUpdate = this.groupRepository.findOne(groupId);
if (groupForUpdate == null || groupForUpdate.isDeleted()) { throw new GroupNotFoundException(groupId); }
final Long officeId = groupForUpdate.getOfficeId();
@@ -184,9 +185,9 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla
if (command.isChangeInLongParameterNamed(staffIdParamName, presentStaffId)) {
final Long newValue = command.longValueOfParameterNamed(staffIdParamName);
actualChanges.put(staffIdParamName, newValue);
Staff newStaff = null;
if(newValue != null){
if (newValue != null) {
newStaff = this.staffRepository.findByOffice(newValue, officeId);
if (newStaff == null) { throw new StaffNotFoundException(newValue); }
}
@@ -235,12 +236,13 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla
throw new InvalidGroupLevelException("add", "invalid.level", errorMessage);
}
}
groupForUpdate.setParent(newParentGroup);
// Parent has changed, re-generate 'Hierarchy' as parent is changed
// Parent has changed, re-generate 'Hierarchy' as parent is
// changed
groupForUpdate.generateHierarchy();
}
}
@@ -248,7 +250,7 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla
final String clientMembersParamName = "clientMembers";
if (!clientMembers.equals(groupForUpdate.getClientMembers())) {
Set<Client> diffClients = Sets.symmetricDifference(clientMembers, groupForUpdate.getClientMembers());
Set<Client> diffClients = Sets.symmetricDifference(clientMembers, groupForUpdate.getClientMembers());
final String[] diffClientsIds = getClientIds(diffClients);
actualChanges.put(clientMembersParamName, diffClientsIds);
groupForUpdate.setClientMembers(clientMembers);
@@ -265,7 +267,7 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla
.build();
} catch (final DataIntegrityViolationException dve) {
handleGroupDataIntegrityIssues(command, dve , groupLevel);
handleGroupDataIntegrityIssues(command, dve, groupLevel);
return new CommandProcessingResult(Long.valueOf(-1));
}
}
@@ -305,18 +307,28 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla
}
/**
* Switched delete to hard delete of group. Will use 'status' when is added
* to determine if group can be deleted or not along with contraints on
* database i.e. cant delete group with any loans/savings accounts.
*/
@Transactional
@Override
public CommandProcessingResult deleteGroup(final Long groupId) {
this.context.authenticatedUser();
// TODO add logic to check any active group loans are preset
final Group groupForDelete = this.groupRepository.findOne(groupId);
if (groupForDelete == null || groupForDelete.isDeleted()) { throw new GroupNotFoundException(groupId); }
groupForDelete.delete();
this.groupRepository.save(groupForDelete);
if (groupForDelete == null) { throw new GroupNotFoundException(groupId); }
// groupForDelete.delete();
// this.groupRepository.save(groupForDelete);
// List<Note> relatedNotes =
// this.noteRepository.findByLoanId(loan.getId());
// this.noteRepository.deleteInBatch(relatedNotes);
this.groupRepository.delete(groupId);
return new CommandProcessingResultBuilder() //
.withOfficeId(groupForDelete.getId()) //
@@ -371,8 +383,8 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla
String[] clientIds = new String[clients.size()];
Iterator<Client> it = clients.iterator();
for (int i = 0; it.hasNext(); i++) {
clientIds[i] = it.next().getId().toString();
for (int i = 0; it.hasNext(); i++) {
clientIds[i] = it.next().getId().toString();
}
return clientIds;
}
@@ -381,7 +393,8 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla
* Guaranteed to throw an exception no matter what the data integrity issue
* is.
*/
private void handleGroupDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve, GroupLevel groupLevel) {
private void handleGroupDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve,
final GroupLevel groupLevel) {
final Throwable realCause = dve.getMostSpecificCause();
String errorMessageForUser = null;
@@ -389,18 +402,16 @@ public class GroupWritePlatformServiceJpaRepositoryImpl implements GroupWritePla
if (realCause.getMessage().contains("external_id")) {
errorMessageForUser = groupLevel.getLevelName() + " with externalId {0} already exists";
final String externalId = command.stringValueOfParameterNamed("externalId");
errorMessageForUser = groupLevel.getLevelName() + " with externalId `" + externalId + "` already exists.";
errorMessageForMachine = "error.msg." + groupLevel.getLevelName().toLowerCase() + ".duplicate.externalId";
throw new PlatformDataIntegrityException(errorMessageForMachine, errorMessageForUser, "externalId",
command.stringValueOfParameterNamed("externalId"));
throw new PlatformDataIntegrityException(errorMessageForMachine, errorMessageForUser, "externalId", externalId);
} else if (realCause.getMessage().contains("name")) {
errorMessageForUser = groupLevel.getLevelName() + " with name {0} already exists";
final String name = command.stringValueOfParameterNamed("name");
errorMessageForUser = groupLevel.getLevelName() + " with name `" + name + "` already exists.";
errorMessageForMachine = "error.msg." + groupLevel.getLevelName().toLowerCase() + ".duplicate.name";
throw new PlatformDataIntegrityException(errorMessageForMachine, errorMessageForUser, "name",
command.stringValueOfParameterNamed("name"));
throw new PlatformDataIntegrityException(errorMessageForMachine, errorMessageForUser, "name", name);
}
logger.error(dve.getMessage(), dve);
@@ -0,0 +1,43 @@
package org.mifosplatform.portfolio.group.service;
public class SearchParameters {
private final String sqlSearch;
private final Long officeId;
private final String externalId;
private final String name;
private final String hierarchy;
public static SearchParameters from(final String sqlSearch, final Long officeId, final String externalId, final String name,
final String hierarchy) {
return new SearchParameters(sqlSearch, officeId, externalId, name, hierarchy);
}
private SearchParameters(final String sqlSearch, final Long officeId, final String externalId, final String name, final String hierarchy) {
this.sqlSearch = sqlSearch;
this.officeId = officeId;
this.externalId = externalId;
this.name = name;
this.hierarchy = hierarchy;
}
public String getSqlSearch() {
return this.sqlSearch;
}
public Long getOfficeId() {
return this.officeId;
}
public String getExternalId() {
return this.externalId;
}
public String getName() {
return this.name;
}
public String getHierarchy() {
return this.hierarchy;
}
}
@@ -35,6 +35,7 @@ import org.mifosplatform.organisation.staff.data.BulkTransferLoanOfficerData;
import org.mifosplatform.organisation.staff.data.StaffAccountSummaryCollectionData;
import org.mifosplatform.organisation.staff.data.StaffData;
import org.mifosplatform.organisation.staff.service.StaffReadPlatformService;
import org.mifosplatform.portfolio.loanaccount.service.BulkLoansReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@@ -52,19 +53,21 @@ public class BulkLoansApiResource {
private final PlatformSecurityContext context;
private final StaffReadPlatformService staffReadPlatformService;
private final OfficeReadPlatformService officeReadPlatformService;
private final BulkLoansReadPlatformService bulkLoansReadPlatformService;
private final DefaultToApiJsonSerializer<BulkTransferLoanOfficerData> toApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
@Autowired
public BulkLoansApiResource(final PlatformSecurityContext context, final StaffReadPlatformService staffReadPlatformService,
final OfficeReadPlatformService officeReadPlatformService,
final OfficeReadPlatformService officeReadPlatformService, final BulkLoansReadPlatformService bulkLoansReadPlatformService,
final DefaultToApiJsonSerializer<BulkTransferLoanOfficerData> toApiJsonSerializer,
final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
this.context = context;
this.staffReadPlatformService = staffReadPlatformService;
this.officeReadPlatformService = officeReadPlatformService;
this.bulkLoansReadPlatformService = bulkLoansReadPlatformService;
this.toApiJsonSerializer = toApiJsonSerializer;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
@@ -89,7 +92,7 @@ public class BulkLoansApiResource {
}
if (loanOfficerId != null) {
staffAccountSummaryCollectionData = this.staffReadPlatformService.retrieveLoanOfficerAccountSummary(loanOfficerId);
staffAccountSummaryCollectionData = this.bulkLoansReadPlatformService.retrieveLoanOfficerAccountSummary(loanOfficerId);
}
final BulkTransferLoanOfficerData loanReassignmentData = BulkTransferLoanOfficerData.templateForBulk(officeId, loanOfficerId,
@@ -19,7 +19,7 @@ import org.mifosplatform.organisation.staff.data.StaffData;
import org.mifosplatform.portfolio.charge.data.ChargeData;
import org.mifosplatform.portfolio.collateral.data.CollateralData;
import org.mifosplatform.portfolio.fund.data.FundData;
import org.mifosplatform.portfolio.group.data.GroupData;
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
import org.mifosplatform.portfolio.loanaccount.guarantor.data.GuarantorData;
import org.mifosplatform.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
@@ -46,7 +46,7 @@ public class LoanAccountData {
private final Long clientId;
private final String clientName;
private final Long clientOfficeId;
private final GroupData group;
private final GroupGeneralData group;
private final Long loanProductId;
private final String loanProductName;
private final String loanProductDescription;
@@ -107,7 +107,7 @@ public class LoanAccountData {
private final Collection<CodeValueData> loanCollateralOptions;
@Transient
private BigDecimal feeChargesAtDisbursementCharged;
private final BigDecimal feeChargesAtDisbursementCharged;
/**
* Used to produce a {@link LoanAccountData} with only collateral options
@@ -121,7 +121,7 @@ public class LoanAccountData {
final Long clientId = null;
final String clientName = null;
final Long clientOfficeId = null;
final GroupData group = null;
final GroupGeneralData group = null;
final Long loanProductId = null;
final String loanProductName = null;
final String loanProductDescription = null;
@@ -171,16 +171,16 @@ public class LoanAccountData {
final Collection<StaffData> loanOfficerOptions = null;
final Collection<CodeValueData> loanPurposeOptions = null;
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group,
loanProductId, loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName,
loanOfficerId, loanOfficerName, currencyData, principal, inArrearsTolerance, termFrequency, termPeriodFrequencyType,
numberOfRepayments, repaymentEvery, repaymentFrequencyType, transactionProcessingStrategyId, amortizationType,
interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType,
expectedFirstRepaymentOnDate, interestChargedFromDate, timeline, summary, feeChargesDueAtDisbursementCharged,
repaymentSchedule, transactions, charges, collateral, guarantors, productOptions, termFrequencyTypeOptions,
repaymentFrequencyTypeOptions, transactionProcessingStrategyOptions, interestRateFrequencyTypeOptions,
amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions,
chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions);
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanProductId,
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
currencyData, principal, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments, repaymentEvery,
repaymentFrequencyType, transactionProcessingStrategyId, amortizationType, interestRatePerPeriod,
interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType, expectedFirstRepaymentOnDate,
interestChargedFromDate, timeline, summary, feeChargesDueAtDisbursementCharged, repaymentSchedule, transactions, charges,
collateral, guarantors, productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions,
transactionProcessingStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions,
interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions,
loanCollateralOptions);
}
/**
@@ -193,7 +193,7 @@ public class LoanAccountData {
final String accountNo = null;
final LoanStatusEnumData status = null;
final String externalId = null;
final GroupData group = null;
final GroupGeneralData group = null;
final String groupName = null;
final Long loanProductId = null;
final String loanProductName = null;
@@ -245,24 +245,22 @@ public class LoanAccountData {
final Collection<CodeValueData> loanPurposeOptions = null;
final Collection<CodeValueData> loanCollateralOptions = null;
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group,
loanProductId, loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName,
loanOfficerId, loanOfficerName, currencyData, principal, inArrearsTolerance, termFrequency, termPeriodFrequencyType,
numberOfRepayments, repaymentEvery, repaymentFrequencyType, transactionProcessingStrategyId, amortizationType,
interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType,
expectedFirstRepaymentOnDate, interestChargedFromDate, timeline, summary, feeChargesDueAtDisbursementCharged,
repaymentSchedule, transactions, charges, collateral, guarantors, productOptions, termFrequencyTypeOptions,
repaymentFrequencyTypeOptions, repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions,
interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions,
loanPurposeOptions, loanCollateralOptions);
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanProductId,
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
currencyData, principal, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments, repaymentEvery,
repaymentFrequencyType, transactionProcessingStrategyId, amortizationType, interestRatePerPeriod,
interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType, expectedFirstRepaymentOnDate,
interestChargedFromDate, timeline, summary, feeChargesDueAtDisbursementCharged, repaymentSchedule, transactions, charges,
collateral, guarantors, productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentStrategyOptions,
interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions,
fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions);
}
/**
* Used to produce a {@link LoanAccountData} with only group information
* defaulted.
*/
public static LoanAccountData groupDefaults(final GroupData group,
final LocalDate expectedDisbursementDate) {
public static LoanAccountData groupDefaults(final GroupGeneralData group, final LocalDate expectedDisbursementDate) {
final Long id = null;
final String accountNo = null;
@@ -321,16 +319,15 @@ public class LoanAccountData {
final Collection<CodeValueData> loanPurposeOptions = null;
final Collection<CodeValueData> loanCollateralOptions = null;
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group,
loanProductId, loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName,
loanOfficerId, loanOfficerName, currencyData, principal, inArrearsTolerance, termFrequency, termPeriodFrequencyType,
numberOfRepayments, repaymentEvery, repaymentFrequencyType, transactionProcessingStrategyId, amortizationType,
interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType,
expectedFirstRepaymentOnDate, interestChargedFromDate, timeline, summary, feeChargesDueAtDisbursementCharged,
repaymentSchedule, transactions, charges, collateral, guarantors, productOptions, termFrequencyTypeOptions,
repaymentFrequencyTypeOptions, repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions,
interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions,
loanPurposeOptions, loanCollateralOptions);
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanProductId,
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
currencyData, principal, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments, repaymentEvery,
repaymentFrequencyType, transactionProcessingStrategyId, amortizationType, interestRatePerPeriod,
interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType, expectedFirstRepaymentOnDate,
interestChargedFromDate, timeline, summary, feeChargesDueAtDisbursementCharged, repaymentSchedule, transactions, charges,
collateral, guarantors, productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentStrategyOptions,
interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions,
fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions);
}
public static LoanAccountData populateLoanProductDefaults(final LoanAccountData acc, final LoanProductData product) {
@@ -363,9 +360,9 @@ public class LoanAccountData {
}
return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId,
acc.group, product.getId(), product.getName(), product.getDescription(),
product.getFundId(), product.getFundName(), acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName,
product.getCurrency(), product.getPrincipal(), product.getInArrearsTolerance(), termFrequency, termPeriodFrequencyType,
acc.group, product.getId(), product.getName(), product.getDescription(), product.getFundId(), product.getFundName(),
acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, product.getCurrency(),
product.getPrincipal(), product.getInArrearsTolerance(), termFrequency, termPeriodFrequencyType,
product.getNumberOfRepayments(), product.getRepaymentEvery(), product.getRepaymentFrequencyType(),
product.getTransactionProcessingStrategyId(), product.getAmortizationType(), product.getInterestRatePerPeriod(),
product.getInterestRateFrequencyType(), product.getAnnualInterestRate(), product.getInterestType(),
@@ -381,15 +378,14 @@ public class LoanAccountData {
* query.
*/
public static LoanAccountData basicLoanDetails(final Long id, final String accountNo, final LoanStatusEnumData status,
final String externalId, final Long clientId, final String clientName, final Long clientOfficeId, final GroupData group,
final Long loanProductId, final String loanProductName,
final String loanProductDescription, final Long fundId, final String fundName, final Long loanPurposeId,
final String loanPurposeName, final Long loanOfficerId, final String loanOfficerName, final CurrencyData currencyData,
final BigDecimal principal, final BigDecimal inArrearsTolerance, final Integer termFrequency,
final EnumOptionData termPeriodFrequencyType, final Integer numberOfRepayments, final Integer repaymentEvery,
final EnumOptionData repaymentFrequencyType, final Long transactionStrategyId, final EnumOptionData amortizationType,
final BigDecimal interestRatePerPeriod, final EnumOptionData interestRateFrequencyType, final BigDecimal annualInterestRate,
final EnumOptionData interestType, final EnumOptionData interestCalculationPeriodType,
final String externalId, final Long clientId, final String clientName, final Long clientOfficeId, final GroupGeneralData group,
final Long loanProductId, final String loanProductName, final String loanProductDescription, final Long fundId,
final String fundName, final Long loanPurposeId, final String loanPurposeName, final Long loanOfficerId,
final String loanOfficerName, final CurrencyData currencyData, final BigDecimal principal, final BigDecimal inArrearsTolerance,
final Integer termFrequency, final EnumOptionData termPeriodFrequencyType, final Integer numberOfRepayments,
final Integer repaymentEvery, final EnumOptionData repaymentFrequencyType, final Long transactionStrategyId,
final EnumOptionData amortizationType, final BigDecimal interestRatePerPeriod, final EnumOptionData interestRateFrequencyType,
final BigDecimal annualInterestRate, final EnumOptionData interestType, final EnumOptionData interestCalculationPeriodType,
final LocalDate expectedFirstRepaymentOnDate, final LocalDate interestChargedFromDate,
final LoanApplicationTimelineData timeline, final LoanSummaryData loanSummary,
final BigDecimal feeChargesDueAtDisbursementCharged) {
@@ -414,16 +410,15 @@ public class LoanAccountData {
final Collection<CodeValueData> loanPurposeOptions = null;
final Collection<CodeValueData> loanCollateralOptions = null;
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group,
loanProductId, loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName,
loanOfficerId, loanOfficerName, currencyData, principal, inArrearsTolerance, termFrequency, termPeriodFrequencyType,
numberOfRepayments, repaymentEvery, repaymentFrequencyType, transactionStrategyId, amortizationType, interestRatePerPeriod,
interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType, expectedFirstRepaymentOnDate,
interestChargedFromDate, timeline, loanSummary, feeChargesDueAtDisbursementCharged, repaymentSchedule, transactions,
charges, collateral, guarantors, productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions,
repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions,
interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions,
loanCollateralOptions);
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanProductId,
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
currencyData, principal, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments, repaymentEvery,
repaymentFrequencyType, transactionStrategyId, amortizationType, interestRatePerPeriod, interestRateFrequencyType,
annualInterestRate, interestType, interestCalculationPeriodType, expectedFirstRepaymentOnDate, interestChargedFromDate,
timeline, loanSummary, feeChargesDueAtDisbursementCharged, repaymentSchedule, transactions, charges, collateral,
guarantors, productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentStrategyOptions,
interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions,
fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions);
}
/*
@@ -442,16 +437,16 @@ public class LoanAccountData {
final Collection<StaffData> loanOfficerOptions, final Collection<CodeValueData> loanPurposeOptions,
final Collection<CodeValueData> loanCollateralOptions) {
return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId,
acc.group, acc.loanProductId, acc.loanProductName, acc.loanProductDescription,
acc.fundId, acc.fundName, acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency,
acc.principal, acc.inArrearsTolerance, acc.termFrequency, acc.termPeriodFrequencyType, acc.numberOfRepayments,
acc.repaymentEvery, acc.repaymentFrequencyType, acc.transactionProcessingStrategyId, acc.amortizationType,
acc.interestRatePerPeriod, acc.interestRateFrequencyType, acc.annualInterestRate, acc.interestType,
acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate, acc.interestChargedFromDate, acc.timeline,
acc.summary, acc.feeChargesAtDisbursementCharged, repaymentSchedule, transactions, charges, collateral, guarantors,
productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, transactionProcessingStrategyOptions,
interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions,
fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions);
acc.group, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, acc.fundId, acc.fundName, acc.loanPurposeId,
acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.principal, acc.inArrearsTolerance,
acc.termFrequency, acc.termPeriodFrequencyType, acc.numberOfRepayments, acc.repaymentEvery, acc.repaymentFrequencyType,
acc.transactionProcessingStrategyId, acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType,
acc.annualInterestRate, acc.interestType, acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate,
acc.interestChargedFromDate, acc.timeline, acc.summary, acc.feeChargesAtDisbursementCharged, repaymentSchedule,
transactions, charges, collateral, guarantors, productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions,
transactionProcessingStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions,
interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions,
loanCollateralOptions);
}
private LoanAccountData(
@@ -462,7 +457,7 @@ public class LoanAccountData {
final Long clientId,
final String clientName,
final Long clientOfficeId, //
final GroupData group,
final GroupGeneralData group,
final Long loanProductId,
final String loanProductName,
final String loanProductDescription, //
@@ -0,0 +1,9 @@
package org.mifosplatform.portfolio.loanaccount.service;
import org.mifosplatform.organisation.staff.data.StaffAccountSummaryCollectionData;
public interface BulkLoansReadPlatformService {
StaffAccountSummaryCollectionData retrieveLoanOfficerAccountSummary(final Long loanOfficerId);
}
@@ -0,0 +1,111 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.loanaccount.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.staff.data.StaffAccountSummaryCollectionData;
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryData;
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
import org.mifosplatform.portfolio.group.data.GroupAccountSummaryData;
import org.mifosplatform.portfolio.group.service.GroupReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
public class BulkLoansReadPlatformServiceImpl implements BulkLoansReadPlatformService {
private final JdbcTemplate jdbcTemplate;
private final PlatformSecurityContext context;
private final ClientReadPlatformService clientReadPlatformService;
private final GroupReadPlatformService groupReadPlatformService;
@Autowired
public BulkLoansReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource,
final ClientReadPlatformService clientReadPlatformService, final GroupReadPlatformService groupReadPlatformService) {
this.context = context;
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.clientReadPlatformService = clientReadPlatformService;
this.groupReadPlatformService = groupReadPlatformService;
}
@Override
public StaffAccountSummaryCollectionData retrieveLoanOfficerAccountSummary(final Long loanOfficerId) {
context.authenticatedUser();
final StaffClientMapper staffClientMapper = new StaffClientMapper();
final String clientSql = "select distinct " + staffClientMapper.schema();
final StaffGroupMapper staffGroupMapper = new StaffGroupMapper();
final String groupSql = "select distinct " + staffGroupMapper.schema();
final List<StaffAccountSummaryCollectionData.ClientSummary> clientSummaryList = this.jdbcTemplate.query(clientSql,
staffClientMapper, new Object[] { loanOfficerId });
for (StaffAccountSummaryCollectionData.ClientSummary clientSummary : clientSummaryList) {
final Collection<ClientAccountSummaryData> clientLoanAccounts = this.clientReadPlatformService
.retrieveClientLoanAccountsByLoanOfficerId(clientSummary.getId(), loanOfficerId);
clientSummary.setLoans(clientLoanAccounts);
}
final List<StaffAccountSummaryCollectionData.GroupSummary> groupSummaryList = this.jdbcTemplate.query(groupSql, staffGroupMapper,
new Object[] { loanOfficerId });
for (StaffAccountSummaryCollectionData.GroupSummary groupSummary : groupSummaryList) {
final Collection<GroupAccountSummaryData> groupLoanAccounts = this.groupReadPlatformService
.retrieveGroupLoanAccountsByLoanOfficerId(groupSummary.getId(), loanOfficerId);
groupSummary.setLoans(groupLoanAccounts);
}
return new StaffAccountSummaryCollectionData(clientSummaryList, groupSummaryList);
}
private static final class StaffClientMapper implements RowMapper<StaffAccountSummaryCollectionData.ClientSummary> {
public String schema() {
return " c.id as id, c.display_name as displayName from m_client c "
+ " join m_loan l on c.id = l.client_id where l.loan_officer_id = ? ";
}
@Override
public StaffAccountSummaryCollectionData.ClientSummary mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum)
throws SQLException {
final Long id = JdbcSupport.getLong(rs, "id");
final String displayName = rs.getString("displayName");
return new StaffAccountSummaryCollectionData.ClientSummary(id, displayName);
}
}
private static final class StaffGroupMapper implements RowMapper<StaffAccountSummaryCollectionData.GroupSummary> {
public String schema() {
return " g.id as id, g.name as name from m_group g" + " join m_loan l on g.id = l.group_id where l.loan_officer_id = ? ";
}
@Override
public StaffAccountSummaryCollectionData.GroupSummary mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum)
throws SQLException {
final Long id = JdbcSupport.getLong(rs, "id");
final String name = rs.getString("name");
return new StaffAccountSummaryCollectionData.GroupSummary(id, name);
}
}
}
@@ -26,8 +26,7 @@ import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
import org.mifosplatform.portfolio.group.data.GroupData;
import org.mifosplatform.portfolio.group.data.GroupTypes;
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
import org.mifosplatform.portfolio.group.service.GroupReadPlatformService;
import org.mifosplatform.portfolio.loanaccount.data.DisbursementData;
import org.mifosplatform.portfolio.loanaccount.data.LoanAccountData;
@@ -167,7 +166,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
context.authenticatedUser();
final GroupData groupAccount = this.groupReadPlatformService.retrieveGroupDetails(groupId, GroupTypes.GROUP.getId(), false);
final GroupGeneralData groupAccount = this.groupReadPlatformService.retrieveOne(groupId);
final LocalDate expectedDisbursementDate = DateUtils.getLocalDateOfTenant();
LoanAccountData loanDetails = LoanAccountData.groupDefaults(groupAccount, expectedDisbursementDate);
@@ -184,7 +183,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
context.authenticatedUser();
final GroupData groupAccount = this.groupReadPlatformService.retrieveGroup(groupId, GroupTypes.GROUP.getId());
final GroupGeneralData groupAccount = this.groupReadPlatformService.retrieveOne(groupId);
final LocalDate expectedDisbursementDate = DateUtils.getLocalDateOfTenant();
LoanAccountData loanDetails = LoanAccountData.groupDefaults(groupAccount, expectedDisbursementDate);
@@ -525,11 +524,10 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
totalWaived, totalWrittenOff, totalOutstanding, totalOverdue, overdueSinceDate);
}
GroupData groupData = null;
GroupGeneralData groupData = null;
if (groupId != null) {
groupData = new GroupData(groupId, groupName, groupExternalId, groupOfficeId, groupStaffId, groupParentId, groupHierarchy);
groupData = GroupGeneralData.instance(groupId, groupName, groupExternalId, groupOfficeId, null, groupParentId, null,
groupStaffId, null, groupHierarchy);
}
return LoanAccountData.basicLoanDetails(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, groupData,
@@ -19,8 +19,7 @@ import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext
import org.mifosplatform.organisation.monetary.data.CurrencyData;
import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
import org.mifosplatform.portfolio.group.data.GroupData;
import org.mifosplatform.portfolio.group.data.GroupTypes;
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
import org.mifosplatform.portfolio.group.service.GroupReadPlatformService;
import org.mifosplatform.portfolio.savings.data.SavingsAccountData;
import org.mifosplatform.portfolio.savings.data.SavingsAccountStatusEnumData;
@@ -211,9 +210,9 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
client = this.clientReadPlatformService.retrieveIndividualClient(clientId);
}
GroupData group = null;
GroupGeneralData group = null;
if (groupId != null) {
group = this.groupReadPlatformService.retrieveGroup(groupId , GroupTypes.GROUP.getId());
group = this.groupReadPlatformService.retrieveOne(groupId);
}
final Collection<SavingsProductData> productOptions = this.savingsProductReadPlatformService.retrieveAllForLookup();
@@ -385,11 +384,11 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
private static final class SavingAccountTemplateMapper implements RowMapper<SavingsAccountData> {
private final ClientData client;
private final GroupData group;
private final GroupGeneralData group;
private final String schemaSql;
public SavingAccountTemplateMapper(final ClientData client, final GroupData group) {
public SavingAccountTemplateMapper(final ClientData client, final GroupGeneralData group) {
this.client = client;
this.group = group;
@@ -432,8 +431,9 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
final BigDecimal nominalAnnualIterestRate = rs.getBigDecimal("nominalAnnualIterestRate");
EnumOptionData interestCompoundingPeriodType = SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType
.fromInt(JdbcSupport.getInteger(rs, "interestCompoundingPeriodType")));
EnumOptionData interestCompoundingPeriodType = SavingsEnumerations
.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.fromInt(JdbcSupport.getInteger(rs,
"interestCompoundingPeriodType")));
final EnumOptionData interestPostingPeriodType = SavingsEnumerations.interestPostingPeriodType(SavingsInterestPostingPeriodType
.fromInt(JdbcSupport.getInteger(rs, "interestPostingPeriodType")));