Merge remote-tracking branch 'vishwas/mifosx-240'

This commit is contained in:
Keith Woodlock
2013-03-16 17:26:13 +00:00
15 changed files with 905 additions and 411 deletions
+389 -34
View File
@@ -187,6 +187,22 @@
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr class="alt">
<td><a href="#client_identifiers">Client Identifiers</a></td>
<td>clients/{clientId}/identifiers</td>
<td><a href="#client_identifiers_create">Create an Identifier for a Client</a></td>
<td><a href="#client_identifiers_list">List all Identifiers for a Client</a></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>clients/{clientId}/identifiers/{identifierId}</td>
<td></td>
<td><a href="#client_identifiers_retrieve">Retrieve a Client Identifier</a></td>
<td><a href="#client_identifiers_update">Update a Client Identifier</a></td>
<td><a href="#client_identifiers_delete">Delete a Client Identifier</a></td>
</tr>
</table> </table>
</div> </div>
</div> </div>
@@ -434,6 +450,24 @@
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td><a href="#guarantors">Loan Guarantors</a></td>
<td>loans/{loanId}/guarantors</td>
<td><a href="#guarantors_create">Create a Guarantor
</a></td>
<td><a href="#guarantors_list">List Guarantors
</a></td>
<td></td>
<td></td>
</tr>
<tr class="alt">
<td></td>
<td>loans/{loanId}/guarantors/{guarantorId}</td>
<td></td>
<td><a href="#guarantors_retrieve">Retrieve a Guarantor</a></td>
<td><a href="#guarantors_update">Update a Guarantor</a></td>
<td><a href="#guarantors_delete">Delete a Guarantor</a></td>
</tr>
</table> </table>
</div> </div>
</div> </div>
@@ -2014,6 +2048,256 @@ GET https://DomainName/api/v1/clients/{clientId}/loans
</div> </div>
</div> </div>
<!-- start of client Identifiers API docs-->
<a id="client_identifiers" name="client_identifiers" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h3>Client Identifiers</h3>
<p>Client Identifiers refer to documents that are
used to uniquely identify a customer <br/>
Ex: Drivers License, Passport, Ration card etc
</p>
<table class=matrixHeading>
<tr class="matrixHeadingBG">
<td><div class="mifosXHeading2">Field Descriptions</div></td>
</tr>
<tr class=alt>
<td>documentKey</td>
</tr>
<tr>
<td class=fielddesc>Number/String used to uniquely identify a particular
document (Driving License number for a driving license etc)</td>
</tr>
<tr class=alt>
<td>documentType</td>
</tr>
<tr>
<td class=fielddesc>Type of the identification document
(License, Passport Etc)</td>
</tr>
<tr class=alt>
<td>description</td>
</tr>
<tr>
<td class=fielddesc>Any user comments to be associated
with the Client Identifier</td>
</tr>
</table>
</div>
</div>
<a id="client_identifiers_list" name="client_identifiers_list" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>List all Identifiers for a Client</h4>
<p>Example Requests:</p>
<div class=apiClick>clients/1/identifiers</div>
<br>
<br>
<div class=apiClick>clients/1/identifiers?fields=documentKey,documentType,description</div>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/api/v1/clients/{clientId}/identifiers
</code>
<code class="method-response">
[
{
"id": 2,
"clientId": 1,
"documentType": {
"id": 3,
"name": "Drivers License"
},
"documentKey": "12345",
"description": "Issued in the year 2--7"
}
]
</code>
</div>
</div>
<a id="client_identifiers_template" name="client_identifiers_template"
class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Retrieve Client Identifier Details Template</h4>
<p>This is a convenience resource. It can be useful when
building maintenance user interface screens for client
applications. The template data returned consists of any or all
of:
<ul>
<li class=normalli>Field Defaults</li>
<li class=normalli>Allowed Value Lists</li>
</ul>
</p>
<p>Example Request:</p>
<div class=apiClick>clients/1/identifiers/template</div>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/api/v1/clients/{clientId}/identifiers/template
</code>
<code class="method-response">
{
"allowedDocumentTypes": [
{
"id": 1,
"name": "Passport",
"position": 0
},
{
"id": 2,
"name": "Id",
"position": 0
},
{
"id": 3,
"name": "Drivers License",
"position": 0
},
{
"id": 4,
"name": "Any Other Id Type",
"position": 0
}
]
}
</code>
</div>
</div>
<a id="client_identifiers_retrieve" name="client_identifiers_retrieve"
class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Retrieve a Client Identifier</h4>
<p>Example Requests:</p>
<div class=apiClick>clients/1/identifier/2</div>
<br>
<br>
<div class=apiClick>clients/1/identifier/2?template=true</div>
<br>
<br>
<div class=apiClick>clients/1/identifiers/2?fields=documentKey,documentType,description</div>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/api/v1/clients/{clientId}/identifiers/{identifierId}
</code>
<code class="method-response">
{
"id": 2,
"clientId": 1,
"documentType": {
"id": 3,
"name": "Drivers License"
},
"documentKey": "12345",
"description": "Issued in 2007"
}
</code>
</div>
</div>
<a id="client_identifiers_create" name="client_identifiers_create" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Create an Identifier for a Client</h4>
<table class=matrixHeading>
<tr class="matrixHeadingBG">
<td><div class="mifosXHeading2">Mandatory Fields</div></td>
</tr>
<tr class=alt>
<td>documentKey, documentTypeId
</td>
</tr>
</table>
</div>
<div class="method-example">
<code class="method-declaration">
POST https://DomainName/api/v1/clients/{clientId}/identifiers
</code>
<code class="method-request">
POST clients/1/identifiers
Content-Type: application/json
Request Body:
{
"documentTypeId":"1",
"documentKey":"KA-54677",
"description":"Document has been verified"
}
</code>
<code class="method-response">
{
"officeId": 1,
"clientId": 1,
"resourceId": 3
}
</code>
</div>
</div>
<a id="client_identifiers_update" name="client_identifiers_update" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Update a Client Identifier</h4>
</div>
<div class="method-example">
<code class="method-declaration">
PUT https://DomainName/api/v1/clients/{clientId}/identifiers/{identifierId}
</code>
<code class="method-request">
PUT clients/1/identifiers/3
Content-Type: application/json
Request Body:
{
"documentTypeId":"4",
"documentKey":"KA-94667",
"description":"Document has been updated"
}
</code>
<code class="method-response">
{
"officeId": 1,
"clientId": 1,
"resourceId": 3,
"changes": {
"documentTypeId": 4,
"documentKey": "KA-94667",
"description": "Document has been updated"
}
}
</code>
</div>
</div>
<a id="client_identifiers_delete" name="client_identifiers_delete" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Delete a Client Identifier</h4>
</div>
<div class="method-example">
<code class="method-declaration">
DELETE https://DomainName/api/v1/clients/{clientId}/identifiers/{identifierId}
</code>
<code class="method-request">
DELETE clients/1/identifiers/3
Content-Type: application/json
No Request Body:
</code>
<code class="method-response">
{
"officeId": 1,
"clientId": 1,
"resourceId": 3
}
</code>
</div>
</div>
<!-- start of Groups api docs --> <!-- start of Groups api docs -->
<a id="groups" name="groups" class="old-syle-anchor">&nbsp;</a> <a id="groups" name="groups" class="old-syle-anchor">&nbsp;</a>
<div class="method-section"> <div class="method-section">
@@ -11319,8 +11603,24 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<!-- loans api full matrix--> <tr>
<td><a href="#client_identifiers">Client Identifiers</a></td>
<td>clients/{clientId}/identifiers</td>
<td><a href="#client_identifiers_create">Create an Identifier for a Client</a></td>
<td><a href="#client_identifiers_list">List all Identifiers for a Client</a></td>
<td></td>
<td></td>
</tr>
<tr class="alt"> <tr class="alt">
<td></td>
<td>clients/{clientId}/identifiers/{identifierId}</td>
<td></td>
<td><a href="#client_identifiers_retrieve">Retrieve a Client Identifier</a></td>
<td><a href="#client_identifiers_update">Update a Client Identifier</a></td>
<td><a href="#client_identifiers_delete">Delete a Client Identifier</a></td>
</tr>
<!-- loans api full matrix-->
<tr>
<td><a href="#loans">Loans</a></td> <td><a href="#loans">Loans</a></td>
<td>loans?calculateLoanSchedule</td> <td>loans?calculateLoanSchedule</td>
<td><a href="#loans_calculate">Calculate Loan Repayment Schedule</a></td> <td><a href="#loans_calculate">Calculate Loan Repayment Schedule</a></td>
@@ -11328,7 +11628,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr class="alt">
<td></td> <td></td>
<td>loans</td> <td>loans</td>
<td><a href="#loans_create">Submit a new Loan Application</a></td> <td><a href="#loans_create">Submit a new Loan Application</a></td>
@@ -11336,7 +11636,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr class="alt"> <tr>
<td></td> <td></td>
<td>loans/{loanId}</td> <td>loans/{loanId}</td>
<td></td> <td></td>
@@ -11344,7 +11644,7 @@ Content-Type: application/json
<td></td> <td></td>
<td><a href="#loans_delete">Delete a Loan Application</a></td> <td><a href="#loans_delete">Delete a Loan Application</a></td>
</tr> </tr>
<tr> <tr class="alt">
<td></td> <td></td>
<td>loans/{loanId}?command=approve</td> <td>loans/{loanId}?command=approve</td>
<td><a href="#loans_approve">Approve Loan Application</a></td> <td><a href="#loans_approve">Approve Loan Application</a></td>
@@ -11352,7 +11652,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr class="alt"> <tr>
<td></td> <td></td>
<td>loans/{loanId}?command=undoApproval</td> <td>loans/{loanId}?command=undoApproval</td>
<td><a href="#loans_approve_undo">Undo Loan Application Approval</a></td> <td><a href="#loans_approve_undo">Undo Loan Application Approval</a></td>
@@ -11360,7 +11660,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr class="alt">
<td></td> <td></td>
<td>loans/{loanId}?command=reject</td> <td>loans/{loanId}?command=reject</td>
<td><a href="#loans_reject">Reject Loan Application</a></td> <td><a href="#loans_reject">Reject Loan Application</a></td>
@@ -11368,7 +11668,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr class="alt"> <tr>
<td></td> <td></td>
<td>loans/{loanId}?command=withdraw</td> <td>loans/{loanId}?command=withdraw</td>
<td><a href="#loans_withdraw">Withdraw Loan Application</a></td> <td><a href="#loans_withdraw">Withdraw Loan Application</a></td>
@@ -11376,7 +11676,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr class="alt">
<td></td> <td></td>
<td>loans/{loanId}?command=disburse</td> <td>loans/{loanId}?command=disburse</td>
<td><a href="#loans_disburse">Disburse Loan</a></td> <td><a href="#loans_disburse">Disburse Loan</a></td>
@@ -11384,7 +11684,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr class="alt"> <tr>
<td></td> <td></td>
<td>loans/{loanId}?command=undoDisbursal</td> <td>loans/{loanId}?command=undoDisbursal</td>
<td><a href="#loans_disburse_undo">Undo Loan Application Disbursal</a></td> <td><a href="#loans_disburse_undo">Undo Loan Application Disbursal</a></td>
@@ -11392,7 +11692,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr class="alt">
<td><a href="#loans_transactions">Loan Transactions</a></td> <td><a href="#loans_transactions">Loan Transactions</a></td>
<td>loans/{loanId}/transactions?command=repayment</td> <td>loans/{loanId}/transactions?command=repayment</td>
<td><a href="#loans_transaction_repayment">Enter a repayment</a></td> <td><a href="#loans_transaction_repayment">Enter a repayment</a></td>
@@ -11400,7 +11700,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr class="alt"> <tr>
<td></td> <td></td>
<td>loans/{loanId}/transactions?command=waiveInterest</td> <td>loans/{loanId}/transactions?command=waiveInterest</td>
<td><a href="#loans_transaction_waiveinterest">Waive Interest</a></td> <td><a href="#loans_transaction_waiveinterest">Waive Interest</a></td>
@@ -11408,7 +11708,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr class="alt">
<td></td> <td></td>
<td>loans/{loanId}/transactions/{transactionId}</td> <td>loans/{loanId}/transactions/{transactionId}</td>
<td></td> <td></td>
@@ -11416,7 +11716,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr class="alt"> <tr>
<td></td> <td></td>
<td>loans/{loanId}/transactions/{transactionId}</td> <td>loans/{loanId}/transactions/{transactionId}</td>
<td><a href="#loans_transaction_adjust">Adjust a Transaction</a></td> <td><a href="#loans_transaction_adjust">Adjust a Transaction</a></td>
@@ -11424,7 +11724,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr class="alt">
<td><a href="#loans_charges">Loan Charges</a></td> <td><a href="#loans_charges">Loan Charges</a></td>
<td>loans/{loanId}/charges</td> <td>loans/{loanId}/charges</td>
<td><a href="#loans_charges_create">Add a loan charge</a></td> <td><a href="#loans_charges_create">Add a loan charge</a></td>
@@ -11432,7 +11732,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr class="alt"> <tr>
<td></td> <td></td>
<td>loans/{loanId}/charges/{loanChargeId}</td> <td>loans/{loanId}/charges/{loanChargeId}</td>
<td></td> <td></td>
@@ -11440,7 +11740,7 @@ Content-Type: application/json
<td><a href="#loans_charges_update">Modify a Loan Charge</a></td> <td><a href="#loans_charges_update">Modify a Loan Charge</a></td>
<td><a href="#loans_charges_delete">Delete a Loan Charge</a></td> <td><a href="#loans_charges_delete">Delete a Loan Charge</a></td>
</tr> </tr>
<tr> <tr class="alt">
<td><a href="#guarantors">Loan Guarantors</a></td> <td><a href="#guarantors">Loan Guarantors</a></td>
<td>loans/{loanId}/guarantors</td> <td>loans/{loanId}/guarantors</td>
<td><a href="#guarantors_create">Create a Guarantor <td><a href="#guarantors_create">Create a Guarantor
@@ -11450,7 +11750,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr class="alt"> <tr>
<td></td> <td></td>
<td>loans/{loanId}/guarantors/{guarantorId}</td> <td>loans/{loanId}/guarantors/{guarantorId}</td>
<td></td> <td></td>
@@ -11458,7 +11758,6 @@ Content-Type: application/json
<td><a href="#guarantors_update">Update a Guarantor</a></td> <td><a href="#guarantors_update">Update a Guarantor</a></td>
<td><a href="#guarantors_delete">Delete a Guarantor</a></td> <td><a href="#guarantors_delete">Delete a Guarantor</a></td>
</tr> </tr>
<tr class="alt"> <tr class="alt">
<td><a href="#offices">OFFICE</a></td> <td><a href="#offices">OFFICE</a></td>
<td>offices</td> <td>offices</td>
@@ -11623,6 +11922,62 @@ Content-Type: application/json
Table (One to Many)</a></td> Table (One to Many)</a></td>
</tr> </tr>
<tr> <tr>
<td><a href="#glaccounts">General Ledger Account</a></td>
<td>glaccounts</td>
<td><a href="#glaccounts_create">Create a New Ledger Account</a></td>
<td><a href="#glaccounts_list">List Ledger Accounts</a></td>
<td></td>
<td></td>
</tr>
<tr class="alt">
<td></td>
<td>glaccounts/{glaccountId}</td>
<td></td>
<td><a href="#glaccounts_retrieve">Retrieve a Ledger Account</a></td>
<td><a href="#glaccounts_update">Update a Ledger Account</a></td>
<td><a href="#glaccounts_delete">Delete a Ledger Account</a></td>
</tr>
<tr>
<td><a href="#glclosures">Accounting Closure</a></td>
<td>glclosures</td>
<td><a href="#glclosures_create">Create an Accounting Closure</a></td>
<td><a href="#glclosures_list">List Accounting Closures</a></td>
<td></td>
<td></td>
</tr>
<tr class="alt">
<td></td>
<td>glclosures/{glclosureId}</td>
<td></td>
<td><a href="#glclosures_retrieve">Retrieve an Accounting Closure</a></td>
<td><a href="#glclosures_update">Update an Accounting Closure</a></td>
<td><a href="#glclosures_delete">Delete an Accounting Closure</a></td>
</tr>
<tr>
<td><a href="#journalentries">Journal Entries</a></td>
<td>journalentries</td>
<td><a href="#journalentries_create">Create Journal Entries</a></td>
<td><a href="#journalentries_list">List Journal Entries</a></td>
<td></td>
<td></td>
</tr>
<tr class="alt">
<td></td>
<td>journalentries/{entryId}</td>
<td></td>
<td><a href="#journalentries_retrieve">Retrieve a single Entry</a></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>journalentries/{transactionId}/reversal</td>
<td><a href="#journalentries_reverse">Reverse Journal Entries</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class="alt">
<td><a href="#reports">REPORT</a></td> <td><a href="#reports">REPORT</a></td>
<td>reports</td> <td>reports</td>
<td></td> <td></td>
@@ -11630,7 +11985,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr class="alt"> <tr>
<td></td> <td></td>
<td>reports/{reportName}</td> <td>reports/{reportName}</td>
<td></td> <td></td>
@@ -11638,7 +11993,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr class="alt">
<td><a href="#authentication">AUTHENTICATION</a></td> <td><a href="#authentication">AUTHENTICATION</a></td>
<td>authentication</td> <td>authentication</td>
<td><a href="#authenticate_request">Verify Authentication</a></td> <td><a href="#authenticate_request">Verify Authentication</a></td>
@@ -11646,7 +12001,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr class="alt"> <tr>
<td><a href="#users">USER</a></td> <td><a href="#users">USER</a></td>
<td>users</td> <td>users</td>
<td><a href="#users_create">Create a User</a></td> <td><a href="#users_create">Create a User</a></td>
@@ -11654,7 +12009,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr class="alt">
<td></td> <td></td>
<td>users/{userId}</td> <td>users/{userId}</td>
<td></td> <td></td>
@@ -11662,7 +12017,7 @@ Content-Type: application/json
<td><a href="#users_update">Update a User</a></td> <td><a href="#users_update">Update a User</a></td>
<td><a href="#users_delete">Delete a User</a></td> <td><a href="#users_delete">Delete a User</a></td>
</tr> </tr>
<tr class="alt"> <tr>
<td><a href="#roles">ROLE</a></td> <td><a href="#roles">ROLE</a></td>
<td>roles</td> <td>roles</td>
<td><a href="#roles_create">Create a New Role</a></td> <td><a href="#roles_create">Create a New Role</a></td>
@@ -11670,7 +12025,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr class="alt">
<td></td> <td></td>
<td>roles/{roleId}</td> <td>roles/{roleId}</td>
<td></td> <td></td>
@@ -11678,7 +12033,7 @@ Content-Type: application/json
<td><a href="#roles_update">Update a Role</a></td> <td><a href="#roles_update">Update a Role</a></td>
<td></td> <td></td>
</tr> </tr>
<tr class="alt"> <tr>
<td></td> <td></td>
<td>roles/{roleId}/permissions</td> <td>roles/{roleId}/permissions</td>
<td></td> <td></td>
@@ -11688,7 +12043,7 @@ Content-Type: application/json
Permissions</a></td> Permissions</a></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr class="alt">
<td><a href="#permissions">PERMISSION</a></td> <td><a href="#permissions">PERMISSION</a></td>
<td>permissions</td> <td>permissions</td>
<td></td> <td></td>
@@ -11697,7 +12052,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr class="alt"> <tr>
<td><a href="#depositproducts">DEPOSIT PRODUCT</a></td> <td><a href="#depositproducts">DEPOSIT PRODUCT</a></td>
<td>depositproducts</td> <td>depositproducts</td>
<td><a href="#depositproducts_create">Create a Deposit product</a></td> <td><a href="#depositproducts_create">Create a Deposit product</a></td>
@@ -11705,7 +12060,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr class="alt">
<td></td> <td></td>
<td>depositproducts/{prodcutId}</td> <td>depositproducts/{prodcutId}</td>
<td></td> <td></td>
@@ -11713,7 +12068,7 @@ Content-Type: application/json
<td><a href="#depositproducts_update">Update a Deposit product</a></td> <td><a href="#depositproducts_update">Update a Deposit product</a></td>
<td><a href="#depositproducts_delete">Delete a Deposit product</a></td> <td><a href="#depositproducts_delete">Delete a Deposit product</a></td>
</tr> </tr>
<tr class="alt"> <tr>
<td><a href="#savingproducts">SAVING PRODUCT</a></td> <td><a href="#savingproducts">SAVING PRODUCT</a></td>
<td>savingproducts</td> <td>savingproducts</td>
<td><a href="#savingproducts_create">Create a Saving product</a></td> <td><a href="#savingproducts_create">Create a Saving product</a></td>
@@ -11721,7 +12076,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr class="alt">
<td></td> <td></td>
<td>savingproducts/{prodcutId}</td> <td>savingproducts/{prodcutId}</td>
<td></td> <td></td>
@@ -11730,7 +12085,7 @@ Content-Type: application/json
<td><a href="#savingproducts_delete">Delete a Saving product</a></td> <td><a href="#savingproducts_delete">Delete a Saving product</a></td>
</tr> </tr>
<tr class="alt"> <tr>
<td><a href="#fixeddeposits">FIXED DEPOSITS</a></td> <td><a href="#fixeddeposits">FIXED DEPOSITS</a></td>
<td>depositaccounts</td> <td>depositaccounts</td>
<td><a href="#fixeddeposits_create">Create a New Deposit <td><a href="#fixeddeposits_create">Create a New Deposit
@@ -11739,7 +12094,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr class="alt">
<td></td> <td></td>
<td>depositaccounts/{accountId}</td> <td>depositaccounts/{accountId}</td>
<td><a href="#fixeddeposits_approve_etc">Approve, Undo Approve, <td><a href="#fixeddeposits_approve_etc">Approve, Undo Approve,
@@ -11752,7 +12107,7 @@ Content-Type: application/json
Application</a></td> Application</a></td>
</tr> </tr>
<tr class="alt"> <tr>
<td><a href="#savingaccounts">SAVING ACCOUNTS</a></td> <td><a href="#savingaccounts">SAVING ACCOUNTS</a></td>
<td>savingaccounts</td> <td>savingaccounts</td>
<td><a href="#savingaccounts_create">Create a New Saving <td><a href="#savingaccounts_create">Create a New Saving
@@ -11761,7 +12116,7 @@ Content-Type: application/json
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr class="alt">
<td></td> <td></td>
<td>savingaccounts/{accountId}</td> <td>savingaccounts/{accountId}</td>
<td><a href="#savingaccounts_approve_etc">Approve, Undo Approve, <td><a href="#savingaccounts_approve_etc">Approve, Undo Approve,
@@ -35,6 +35,7 @@ import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext
import org.mifosplatform.portfolio.client.data.ClientData; import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.client.data.ClientIdentifierData; import org.mifosplatform.portfolio.client.data.ClientIdentifierData;
import org.mifosplatform.portfolio.client.exception.DuplicateClientIdentifierException; import org.mifosplatform.portfolio.client.exception.DuplicateClientIdentifierException;
import org.mifosplatform.portfolio.client.service.ClientIdentifierReadPlatformService;
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService; import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
@@ -46,12 +47,13 @@ import org.springframework.stereotype.Component;
public class ClientIdentifiersApiResource { public class ClientIdentifiersApiResource {
private static final Set<String> CLIENT_IDENTIFIER_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "clientId", private static final Set<String> CLIENT_IDENTIFIER_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "clientId",
"documentTypeId", "documentKey", "description", "documentTypeName", "allowedDocumentTypes")); "documentType", "documentKey", "description", "allowedDocumentTypes"));
private final String resourceNameForPermissions = "CLIENTIDENTIFIER"; private final String resourceNameForPermissions = "CLIENTIDENTIFIER";
private final PlatformSecurityContext context; private final PlatformSecurityContext context;
private final ClientReadPlatformService clientReadPlatformService; private final ClientReadPlatformService clientReadPlatformService;
private final ClientIdentifierReadPlatformService clientIdentifierReadPlatformService;
private final CodeValueReadPlatformService codeValueReadPlatformService; private final CodeValueReadPlatformService codeValueReadPlatformService;
private final DefaultToApiJsonSerializer<ClientIdentifierData> toApiJsonSerializer; private final DefaultToApiJsonSerializer<ClientIdentifierData> toApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper; private final ApiRequestParameterHelper apiRequestParameterHelper;
@@ -62,13 +64,15 @@ public class ClientIdentifiersApiResource {
final CodeValueReadPlatformService codeValueReadPlatformService, final CodeValueReadPlatformService codeValueReadPlatformService,
final DefaultToApiJsonSerializer<ClientIdentifierData> toApiJsonSerializer, final DefaultToApiJsonSerializer<ClientIdentifierData> toApiJsonSerializer,
final ApiRequestParameterHelper apiRequestParameterHelper, final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) { final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
final ClientIdentifierReadPlatformService clientIdentifierReadPlatformService) {
this.context = context; this.context = context;
this.clientReadPlatformService = readPlatformService; this.clientReadPlatformService = readPlatformService;
this.codeValueReadPlatformService = codeValueReadPlatformService; this.codeValueReadPlatformService = codeValueReadPlatformService;
this.toApiJsonSerializer = toApiJsonSerializer; this.toApiJsonSerializer = toApiJsonSerializer;
this.apiRequestParameterHelper = apiRequestParameterHelper; this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
this.clientIdentifierReadPlatformService = clientIdentifierReadPlatformService;
} }
@GET @GET
@@ -76,11 +80,12 @@ public class ClientIdentifiersApiResource {
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllClientIdentifiers(@Context final UriInfo uriInfo, @PathParam("clientId") final Long clientId) { public String retrieveAllClientIdentifiers(@Context final UriInfo uriInfo, @PathParam("clientId") final Long clientId) {
context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions); this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
final Collection<ClientIdentifierData> clientIdentifiers = this.clientReadPlatformService.retrieveClientIdentifiers(clientId); final Collection<ClientIdentifierData> clientIdentifiers = this.clientIdentifierReadPlatformService
.retrieveClientIdentifiers(clientId);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, clientIdentifiers, CLIENT_IDENTIFIER_DATA_PARAMETERS); return this.toApiJsonSerializer.serialize(settings, clientIdentifiers, CLIENT_IDENTIFIER_DATA_PARAMETERS);
} }
@@ -90,12 +95,12 @@ public class ClientIdentifiersApiResource {
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
public String newClientIdentifierDetails(@Context final UriInfo uriInfo) { public String newClientIdentifierDetails(@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions); this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
final Collection<CodeValueData> codeValues = codeValueReadPlatformService.retrieveCodeValuesByCode("Customer Identifier"); final Collection<CodeValueData> codeValues = this.codeValueReadPlatformService.retrieveCodeValuesByCode("Customer Identifier");
final ClientIdentifierData clientIdentifierData = ClientIdentifierData.template(codeValues); final ClientIdentifierData clientIdentifierData = ClientIdentifierData.template(codeValues);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, clientIdentifierData, CLIENT_IDENTIFIER_DATA_PARAMETERS); return this.toApiJsonSerializer.serialize(settings, clientIdentifierData, CLIENT_IDENTIFIER_DATA_PARAMETERS);
} }
@@ -111,11 +116,11 @@ public class ClientIdentifiersApiResource {
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result); return this.toApiJsonSerializer.serialize(result);
} catch (DuplicateClientIdentifierException e) { } catch (final DuplicateClientIdentifierException e) {
DuplicateClientIdentifierException rethrowas = e; DuplicateClientIdentifierException rethrowas = e;
if (e.getDocumentTypeId() != null) { if (e.getDocumentTypeId() != null) {
// need to fetch client info // need to fetch client info
ClientData clientInfo = this.clientReadPlatformService.retrieveClientByIdentifier(e.getDocumentTypeId(), final ClientData clientInfo = this.clientReadPlatformService.retrieveClientByIdentifier(e.getDocumentTypeId(),
e.getIdentifierKey()); e.getIdentifierKey());
rethrowas = new DuplicateClientIdentifierException(clientInfo.displayName(), clientInfo.officeName(), rethrowas = new DuplicateClientIdentifierException(clientInfo.displayName(), clientInfo.officeName(),
e.getIdentifierType(), e.getIdentifierKey()); e.getIdentifierType(), e.getIdentifierKey());
@@ -131,14 +136,14 @@ public class ClientIdentifiersApiResource {
public String retrieveClientIdentifiers(@PathParam("clientId") final Long clientId, public String retrieveClientIdentifiers(@PathParam("clientId") final Long clientId,
@PathParam("identifierId") final Long clientIdentifierId, @Context final UriInfo uriInfo) { @PathParam("identifierId") final Long clientIdentifierId, @Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions); this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
ClientIdentifierData clientIdentifierData = this.clientReadPlatformService.retrieveClientIdentifier(clientId, clientIdentifierId); ClientIdentifierData clientIdentifierData = this.clientIdentifierReadPlatformService.retrieveClientIdentifier(clientId,
clientIdentifierId);
if (settings.isTemplate()) { if (settings.isTemplate()) {
final Collection<CodeValueData> codeValues = codeValueReadPlatformService final Collection<CodeValueData> codeValues = this.codeValueReadPlatformService.retrieveCodeValuesByCode("Customer Identifier");
.retrieveCodeValuesByCode("Customer Identifier");
clientIdentifierData = ClientIdentifierData.template(clientIdentifierData, codeValues); clientIdentifierData = ClientIdentifierData.template(clientIdentifierData, codeValues);
} }
@@ -159,10 +164,10 @@ public class ClientIdentifiersApiResource {
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result); return this.toApiJsonSerializer.serialize(result);
} catch (DuplicateClientIdentifierException e) { } catch (final DuplicateClientIdentifierException e) {
DuplicateClientIdentifierException reThrowAs = e; DuplicateClientIdentifierException reThrowAs = e;
if (e.getDocumentTypeId() != null) { if (e.getDocumentTypeId() != null) {
ClientData clientInfo = this.clientReadPlatformService.retrieveClientByIdentifier(e.getDocumentTypeId(), final ClientData clientInfo = this.clientReadPlatformService.retrieveClientByIdentifier(e.getDocumentTypeId(),
e.getIdentifierKey()); e.getIdentifierKey());
reThrowAs = new DuplicateClientIdentifierException(clientInfo.displayName(), clientInfo.officeName(), reThrowAs = new DuplicateClientIdentifierException(clientInfo.displayName(), clientInfo.officeName(),
e.getIdentifierType(), e.getIdentifierKey()); e.getIdentifierType(), e.getIdentifierKey());
@@ -37,114 +37,133 @@ import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataBodyPart; import com.sun.jersey.multipart.FormDataBodyPart;
import com.sun.jersey.multipart.FormDataParam; import com.sun.jersey.multipart.FormDataParam;
// FIXME - KW - image should be images to keep consistent with rest of API - even if we only support one image per client. @Path("/clients/{clientId}/images")
@Path("/clients/{clientId}/image")
@Component @Component
@Scope("singleton") @Scope("singleton")
public class ClientImagesApiResource { public class ClientImagesApiResource {
private final PlatformSecurityContext context; private final PlatformSecurityContext context;
private final ClientReadPlatformService clientReadPlatformService; private final ClientReadPlatformService clientReadPlatformService;
private final ClientWritePlatformService clientWritePlatformService; private final ClientWritePlatformService clientWritePlatformService;
private final DefaultToApiJsonSerializer<ClientData> toApiJsonSerializer; private final DefaultToApiJsonSerializer<ClientData> toApiJsonSerializer;
@Autowired @Autowired
public ClientImagesApiResource(final PlatformSecurityContext context, final ClientReadPlatformService readPlatformService, public ClientImagesApiResource(final PlatformSecurityContext context,
final ClientWritePlatformService clientWritePlatformService, final DefaultToApiJsonSerializer<ClientData> toApiJsonSerializer) { final ClientReadPlatformService readPlatformService,
this.context = context; final ClientWritePlatformService clientWritePlatformService,
this.clientReadPlatformService = readPlatformService; final DefaultToApiJsonSerializer<ClientData> toApiJsonSerializer) {
this.clientWritePlatformService = clientWritePlatformService; this.context = context;
this.toApiJsonSerializer = toApiJsonSerializer; this.clientReadPlatformService = readPlatformService;
} this.clientWritePlatformService = clientWritePlatformService;
this.toApiJsonSerializer = toApiJsonSerializer;
}
/** /**
* Upload images through multi-part form upload * Upload images through multi-part form upload
*/ */
@POST @POST
@Consumes({ MediaType.MULTIPART_FORM_DATA }) @Consumes({ MediaType.MULTIPART_FORM_DATA })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
public String addNewClientImage(@PathParam("clientId") final Long clientId, @HeaderParam("Content-Length") final Long fileSize, public String addNewClientImage(
@FormDataParam("file") final InputStream inputStream, @FormDataParam("file") final FormDataContentDisposition fileDetails, @PathParam("clientId") final Long clientId,
@FormDataParam("file") final FormDataBodyPart bodyPart) { @HeaderParam("Content-Length") final Long fileSize,
@FormDataParam("file") final InputStream inputStream,
@FormDataParam("file") final FormDataContentDisposition fileDetails,
@FormDataParam("file") final FormDataBodyPart bodyPart) {
// TODO: vishwas might need more advances validation (like reading magic // TODO: vishwas might need more advances validation (like reading magic
// number) for handling malicious clients // number) for handling malicious clients
// and clients not setting mime type // and clients not setting mime type
FileUtils.validateClientImageNotEmpty(fileDetails.getFileName()); FileUtils.validateClientImageNotEmpty(fileDetails.getFileName());
FileUtils.validateImageMimeType(bodyPart.getMediaType().toString()); FileUtils.validateImageMimeType(bodyPart.getMediaType().toString());
FileUtils.validateFileSizeWithinPermissibleRange(fileSize, fileDetails.getFileName(), ApiConstants.MAX_FILE_UPLOAD_SIZE_IN_MB); FileUtils.validateFileSizeWithinPermissibleRange(fileSize,
fileDetails.getFileName(),
ApiConstants.MAX_FILE_UPLOAD_SIZE_IN_MB);
final CommandProcessingResult result = this.clientWritePlatformService.saveOrUpdateClientImage(clientId, fileDetails.getFileName(), final CommandProcessingResult result = this.clientWritePlatformService
inputStream); .saveOrUpdateClientImage(clientId, fileDetails.getFileName(),
inputStream);
return this.toApiJsonSerializer.serialize(result); return this.toApiJsonSerializer.serialize(result);
} }
/** /**
* Upload image as a Data URL (essentially a base64 encoded stream) * Upload image as a Data URL (essentially a base64 encoded stream)
*/ */
@POST @POST
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
public String addNewClientImage(@PathParam("clientId") final Long clientId, final String jsonRequestBody) { public String addNewClientImage(@PathParam("clientId") final Long clientId,
final String jsonRequestBody) {
final Base64EncodedImage base64EncodedImage = FileUtils.extractImageFromDataURL(jsonRequestBody); final Base64EncodedImage base64EncodedImage = FileUtils
.extractImageFromDataURL(jsonRequestBody);
final CommandProcessingResult result = this.clientWritePlatformService.saveOrUpdateClientImage(clientId, base64EncodedImage); final CommandProcessingResult result = this.clientWritePlatformService
.saveOrUpdateClientImage(clientId, base64EncodedImage);
return this.toApiJsonSerializer.serialize(result); return this.toApiJsonSerializer.serialize(result);
} }
/** /**
* Returns a base 64 encoded client image * Returns a base 64 encoded client image
*/ */
@GET @GET
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
public String retrieveClientImage(@PathParam("clientId") final Long clientId) { public String retrieveClientImage(@PathParam("clientId") final Long clientId) {
context.authenticatedUser().validateHasReadPermission("CLIENTIMAGE"); context.authenticatedUser().validateHasReadPermission("CLIENTIMAGE");
final ClientData clientData = this.clientReadPlatformService.retrieveIndividualClient(clientId); final ClientData clientData = this.clientReadPlatformService
.retrieveIndividualClient(clientId);
if (clientData.imageKeyDoesNotExist()) { throw new ImageNotFoundException("clients", clientId); } if (clientData.imageKeyDoesNotExist()) {
throw new ImageNotFoundException("clients", clientId);
}
return Base64.encodeFromFile(clientData.imageKey()); return Base64.encodeFromFile(clientData.imageKey());
} }
/** /**
* This method is added only for consistency with other URL patterns and for * This method is added only for consistency with other URL patterns and for
* maintaining consistency of usage of the HTTP "verb" at the client side * maintaining consistency of usage of the HTTP "verb" at the client side
*/ */
@PUT @PUT
@Consumes({ MediaType.MULTIPART_FORM_DATA }) @Consumes({ MediaType.MULTIPART_FORM_DATA })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
public String updateClientImage(@PathParam("clientId") final Long clientId, @HeaderParam("Content-Length") final Long fileSize, public String updateClientImage(
@FormDataParam("file") final InputStream inputStream, @FormDataParam("file") final FormDataContentDisposition fileDetails, @PathParam("clientId") final Long clientId,
@FormDataParam("file") final FormDataBodyPart bodyPart) { @HeaderParam("Content-Length") final Long fileSize,
@FormDataParam("file") final InputStream inputStream,
@FormDataParam("file") final FormDataContentDisposition fileDetails,
@FormDataParam("file") final FormDataBodyPart bodyPart) {
return addNewClientImage(clientId, fileSize, inputStream, fileDetails, bodyPart); return addNewClientImage(clientId, fileSize, inputStream, fileDetails,
} bodyPart);
}
@DELETE @DELETE
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
public String deleteClientImage(@PathParam("clientId") final Long clientId) { public String deleteClientImage(@PathParam("clientId") final Long clientId) {
this.clientWritePlatformService.deleteClientImage(clientId); this.clientWritePlatformService.deleteClientImage(clientId);
return this.toApiJsonSerializer.serialize(new CommandProcessingResult(clientId)); return this.toApiJsonSerializer.serialize(new CommandProcessingResult(
} clientId));
}
/** /**
* This method is added only for consistency with other URL patterns and for * This method is added only for consistency with other URL patterns and for
* maintaining consistency of usage of the HTTP "verb" at the client side * maintaining consistency of usage of the HTTP "verb" at the client side
* *
* Upload image as a Data URL (essentially a base64 encoded stream) * Upload image as a Data URL (essentially a base64 encoded stream)
*/ */
@PUT @PUT
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
public String updateClientImage(@PathParam("clientId") final Long clientId, final String jsonRequestBody) { public String updateClientImage(@PathParam("clientId") final Long clientId,
return addNewClientImage(clientId, jsonRequestBody); final String jsonRequestBody) {
} return addNewClientImage(clientId, jsonRequestBody);
}
} }
@@ -14,37 +14,44 @@ import org.mifosplatform.infrastructure.codes.data.CodeValueData;
*/ */
public class ClientIdentifierData { public class ClientIdentifierData {
private final Long id; private final Long id;
private final Long clientId; private final Long clientId;
private final Long documentTypeId; private final CodeValueData documentType;
private final String documentTypeName; private final String documentKey;
private final String documentKey; private final String description;
private final String description; @SuppressWarnings("unused")
@SuppressWarnings("unused") private final Collection<CodeValueData> allowedDocumentTypes;
private final Collection<CodeValueData> allowedDocumentTypes;
public static ClientIdentifierData singleItem(final Long id, final Long clientId, final Long documentTypeId, final String documentKey, public static ClientIdentifierData singleItem(final Long id,
final String description, final String documentTypeName) { final Long clientId, final CodeValueData documentType,
return new ClientIdentifierData(id, clientId, documentTypeId, documentKey, description, documentTypeName, null); final String documentKey, final String description) {
} return new ClientIdentifierData(id, clientId, documentType,
documentKey, description, null);
}
public static ClientIdentifierData template(final Collection<CodeValueData> codeValues) { public static ClientIdentifierData template(
return new ClientIdentifierData(null, null, null, null, null, null, codeValues); final Collection<CodeValueData> codeValues) {
} return new ClientIdentifierData(null, null, null, null, null,
codeValues);
}
public static ClientIdentifierData template(final ClientIdentifierData data, final Collection<CodeValueData> codeValues) { public static ClientIdentifierData template(
return new ClientIdentifierData(data.id, data.clientId, data.documentTypeId, data.documentKey, data.description, final ClientIdentifierData data,
data.documentTypeName, codeValues); final Collection<CodeValueData> codeValues) {
} return new ClientIdentifierData(data.id, data.clientId,
data.documentType, data.documentKey, data.description,
codeValues);
}
public ClientIdentifierData(final Long id, final Long clientId, final Long documentTypeId, final String documentKey, public ClientIdentifierData(final Long id, final Long clientId,
final String description, final String documentTypeName, final Collection<CodeValueData> allowedDocumentTypes) { final CodeValueData documentType, final String documentKey,
this.id = id; final String description,
this.clientId = clientId; final Collection<CodeValueData> allowedDocumentTypes) {
this.documentTypeId = documentTypeId; this.id = id;
this.documentKey = documentKey; this.clientId = clientId;
this.description = description; this.documentType = documentType;
this.documentTypeName = documentTypeName; this.documentKey = documentKey;
this.allowedDocumentTypes = allowedDocumentTypes; this.description = description;
} this.allowedDocumentTypes = allowedDocumentTypes;
}
} }
@@ -8,7 +8,7 @@ package org.mifosplatform.portfolio.client.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler; import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.portfolio.client.service.ClientWritePlatformService; import org.mifosplatform.portfolio.client.service.ClientIdentifierWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -16,17 +16,17 @@ import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class CreateClientIdentifierCommandHandler implements NewCommandSourceHandler { public class CreateClientIdentifierCommandHandler implements NewCommandSourceHandler {
private final ClientWritePlatformService clientWritePlatformService; private final ClientIdentifierWritePlatformService clientIdentifierWritePlatformService;
@Autowired @Autowired
public CreateClientIdentifierCommandHandler(final ClientWritePlatformService clientWritePlatformService) { public CreateClientIdentifierCommandHandler(final ClientIdentifierWritePlatformService clientIdentifierWritePlatformService) {
this.clientWritePlatformService = clientWritePlatformService; this.clientIdentifierWritePlatformService = clientIdentifierWritePlatformService;
} }
@Transactional @Transactional
@Override @Override
public CommandProcessingResult processCommand(final JsonCommand command) { public CommandProcessingResult processCommand(final JsonCommand command) {
return this.clientWritePlatformService.addClientIdentifier(command.getClientId(), command); return this.clientIdentifierWritePlatformService.addClientIdentifier(command.getClientId(), command);
} }
} }
@@ -8,7 +8,7 @@ package org.mifosplatform.portfolio.client.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler; import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.portfolio.client.service.ClientWritePlatformService; import org.mifosplatform.portfolio.client.service.ClientIdentifierWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -16,17 +16,18 @@ import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class DeleteClientIdentifierCommandHandler implements NewCommandSourceHandler { public class DeleteClientIdentifierCommandHandler implements NewCommandSourceHandler {
private final ClientWritePlatformService clientWritePlatformService; private final ClientIdentifierWritePlatformService clientIdentifierWritePlatformService;
@Autowired @Autowired
public DeleteClientIdentifierCommandHandler(final ClientWritePlatformService clientWritePlatformService) { public DeleteClientIdentifierCommandHandler(final ClientIdentifierWritePlatformService clientIdentifierWritePlatformService) {
this.clientWritePlatformService = clientWritePlatformService; this.clientIdentifierWritePlatformService = clientIdentifierWritePlatformService;
} }
@Transactional @Transactional
@Override @Override
public CommandProcessingResult processCommand(final JsonCommand command) { public CommandProcessingResult processCommand(final JsonCommand command) {
return this.clientWritePlatformService.deleteClientIdentifier(command.getClientId(), command.entityId(), command.commandId()); return this.clientIdentifierWritePlatformService.deleteClientIdentifier(command.getClientId(), command.entityId(),
command.commandId());
} }
} }
@@ -8,7 +8,7 @@ package org.mifosplatform.portfolio.client.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler; import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.portfolio.client.service.ClientWritePlatformService; import org.mifosplatform.portfolio.client.service.ClientIdentifierWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -16,17 +16,16 @@ import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class UpdateClientIdentifierCommandHandler implements NewCommandSourceHandler { public class UpdateClientIdentifierCommandHandler implements NewCommandSourceHandler {
private final ClientWritePlatformService clientWritePlatformService; private final ClientIdentifierWritePlatformService clientIdentifierWritePlatformService;
@Autowired @Autowired
public UpdateClientIdentifierCommandHandler(final ClientWritePlatformService clientWritePlatformService) { public UpdateClientIdentifierCommandHandler(final ClientIdentifierWritePlatformService clientIdentifierWritePlatformService) {
this.clientWritePlatformService = clientWritePlatformService; this.clientIdentifierWritePlatformService = clientIdentifierWritePlatformService;
} }
@Transactional @Transactional
@Override @Override
public CommandProcessingResult processCommand(final JsonCommand command) { public CommandProcessingResult processCommand(final JsonCommand command) {
return this.clientIdentifierWritePlatformService.updateClientIdentifier(command.getClientId(), command.entityId(), command);
return this.clientWritePlatformService.updateClientIdentifier(command.getClientId(), command.entityId(), command);
} }
} }
@@ -0,0 +1,18 @@
/**
* 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.service;
import java.util.Collection;
import org.mifosplatform.portfolio.client.data.ClientIdentifierData;
public interface ClientIdentifierReadPlatformService {
Collection<ClientIdentifierData> retrieveClientIdentifiers(Long clientId);
ClientIdentifierData retrieveClientIdentifier(Long clientId, Long clientIdentifierId);
}
@@ -0,0 +1,105 @@
/**
* 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.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.client.data.ClientIdentifierData;
import org.mifosplatform.portfolio.client.exception.ClientIdentifierNotFoundException;
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;
@Service
public class ClientIdentifierReadPlatformServiceImpl implements ClientIdentifierReadPlatformService {
private final JdbcTemplate jdbcTemplate;
private final PlatformSecurityContext context;
@Autowired
public ClientIdentifierReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource) {
this.context = context;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public Collection<ClientIdentifierData> retrieveClientIdentifiers(final Long clientId) {
AppUser currentUser = context.authenticatedUser();
String hierarchy = currentUser.getOffice().getHierarchy();
String hierarchySearchString = hierarchy + "%";
ClientIdentityMapper rm = new ClientIdentityMapper();
String sql = "select " + rm.schema();
sql += " order by ci.id";
return this.jdbcTemplate.query(sql, rm, new Object[] { clientId, hierarchySearchString });
}
@Override
public ClientIdentifierData retrieveClientIdentifier(final Long clientId, final Long clientIdentifierId) {
try {
AppUser currentUser = context.authenticatedUser();
String hierarchy = currentUser.getOffice().getHierarchy();
String hierarchySearchString = hierarchy + "%";
ClientIdentityMapper rm = new ClientIdentityMapper();
String sql = "select " + rm.schema();
sql += " and ci.id = ?";
final ClientIdentifierData clientIdentifierData = this.jdbcTemplate.queryForObject(sql, rm, new Object[] { clientId,
hierarchySearchString, clientIdentifierId });
return clientIdentifierData;
} catch (EmptyResultDataAccessException e) {
throw new ClientIdentifierNotFoundException(clientIdentifierId);
}
}
private static final class ClientIdentityMapper implements RowMapper<ClientIdentifierData> {
public ClientIdentityMapper() {}
public String schema() {
return "ci.id as id, ci.client_id as clientId, ci.document_type_id as documentTypeId, ci.document_key as documentKey,"
+ " ci.description as description, cv.code_value as documentType "
+ " from m_client_identifier ci, m_client c, m_office o, m_code_value cv"
+ " where ci.client_id=c.id and c.office_id=o.id" + " and ci.document_type_id=cv.id"
+ " and ci.client_id = ? and o.hierarchy like ? ";
}
@Override
public ClientIdentifierData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = JdbcSupport.getLong(rs, "id");
final Long clientId = JdbcSupport.getLong(rs, "clientId");
final Long documentTypeId = JdbcSupport.getLong(rs, "documentTypeId");
final String documentKey = rs.getString("documentKey");
final String description = rs.getString("description");
final String documentTypeName = rs.getString("documentType");
CodeValueData documentType = CodeValueData.instance(documentTypeId, documentTypeName);
return ClientIdentifierData.singleItem(id, clientId, documentType, documentKey, description);
}
}
}
@@ -0,0 +1,18 @@
/**
* 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.service;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
public interface ClientIdentifierWritePlatformService {
CommandProcessingResult addClientIdentifier(Long clientId, JsonCommand command);
CommandProcessingResult updateClientIdentifier(Long clientId, Long clientIdentifierId, JsonCommand command);
CommandProcessingResult deleteClientIdentifier(Long clientId, Long clientIdentifierId, Long commandId);
}
@@ -0,0 +1,181 @@
/**
* 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.service;
import java.util.Map;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
import org.mifosplatform.infrastructure.codes.domain.CodeValueRepositoryWrapper;
import org.mifosplatform.infrastructure.codes.exception.CodeValueNotFoundException;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.client.command.ClientIdentifierCommand;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.domain.ClientIdentifier;
import org.mifosplatform.portfolio.client.domain.ClientIdentifierRepository;
import org.mifosplatform.portfolio.client.domain.ClientRepository;
import org.mifosplatform.portfolio.client.exception.ClientIdentifierNotFoundException;
import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
import org.mifosplatform.portfolio.client.exception.DuplicateClientIdentifierException;
import org.mifosplatform.portfolio.client.serialization.ClientIdentifierCommandFromApiJsonDeserializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ClientIdentifierWritePlatformServiceJpaRepositoryImpl implements ClientIdentifierWritePlatformService {
private final static Logger logger = LoggerFactory.getLogger(ClientIdentifierWritePlatformServiceJpaRepositoryImpl.class);
private final PlatformSecurityContext context;
private final ClientRepository clientRepository;
private final ClientIdentifierRepository clientIdentifierRepository;
private final CodeValueRepositoryWrapper codeValueRepository;
private final ClientIdentifierCommandFromApiJsonDeserializer clientIdentifierCommandFromApiJsonDeserializer;
@Autowired
public ClientIdentifierWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
final ClientRepository clientRepository, final ClientIdentifierRepository clientIdentifierRepository,
final CodeValueRepositoryWrapper codeValueRepository,
final ClientIdentifierCommandFromApiJsonDeserializer clientIdentifierCommandFromApiJsonDeserializer) {
this.context = context;
this.clientRepository = clientRepository;
this.clientIdentifierRepository = clientIdentifierRepository;
this.codeValueRepository = codeValueRepository;
this.clientIdentifierCommandFromApiJsonDeserializer = clientIdentifierCommandFromApiJsonDeserializer;
}
@Transactional
@Override
public CommandProcessingResult addClientIdentifier(final Long clientId, final JsonCommand command) {
context.authenticatedUser();
final ClientIdentifierCommand clientIdentifierCommand = this.clientIdentifierCommandFromApiJsonDeserializer
.commandFromApiJson(command.json());
clientIdentifierCommand.validateForCreate();
String documentKey = clientIdentifierCommand.getDocumentKey();
String documentTypeLabel = null;
Long documentTypeId = null;
try {
final Client client = this.clientRepository.findOne(clientId);
if (client == null || client.isDeleted()) { throw new ClientNotFoundException(clientId); }
final CodeValue documentType = this.codeValueRepository.findOneWithNotFoundDetection(clientIdentifierCommand
.getDocumentTypeId());
documentTypeId = documentType.getId();
documentTypeLabel = documentType.label();
final ClientIdentifier clientIdentifier = ClientIdentifier.fromJson(client, documentType, command);
this.clientIdentifierRepository.save(clientIdentifier);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withOfficeId(client.getOffice().getId()) //
.withClientId(clientId) //
.withEntityId(clientIdentifier.getId()) //
.build();
} catch (DataIntegrityViolationException dve) {
handleClientIdentifierDataIntegrityViolation(documentTypeLabel, documentTypeId, documentKey, dve);
return CommandProcessingResult.empty();
}
}
@Transactional
@Override
public CommandProcessingResult updateClientIdentifier(final Long clientId, final Long identifierId, final JsonCommand command) {
context.authenticatedUser();
final ClientIdentifierCommand clientIdentifierCommand = this.clientIdentifierCommandFromApiJsonDeserializer
.commandFromApiJson(command.json());
clientIdentifierCommand.validateForUpdate();
String documentTypeLabel = null;
String documentKey = null;
Long documentTypeId = clientIdentifierCommand.getDocumentTypeId();
try {
CodeValue documentType = null;
final ClientIdentifier clientIdentifierForUpdate = this.clientIdentifierRepository.findOne(identifierId);
if (clientIdentifierForUpdate == null) { throw new ClientIdentifierNotFoundException(identifierId); }
final Map<String, Object> changes = clientIdentifierForUpdate.update(command);
if (changes.containsKey("documentTypeId")) {
documentType = this.codeValueRepository.findOneWithNotFoundDetection(documentTypeId);
if (documentType == null) { throw new CodeValueNotFoundException(documentTypeId); }
documentTypeId = documentType.getId();
documentTypeLabel = documentType.label();
clientIdentifierForUpdate.update(documentType);
}
if (changes.containsKey("documentTypeId") && changes.containsKey("documentKey")) {
documentTypeId = clientIdentifierCommand.getDocumentTypeId();
documentKey = clientIdentifierCommand.getDocumentKey();
} else if (changes.containsKey("documentTypeId") && !changes.containsKey("documentKey")) {
documentTypeId = clientIdentifierCommand.getDocumentTypeId();
documentKey = clientIdentifierForUpdate.documentKey();
} else if (!changes.containsKey("documentTypeId") && changes.containsKey("documentKey")) {
documentTypeId = clientIdentifierForUpdate.documentTypeId();
documentKey = clientIdentifierForUpdate.documentKey();
}
if (!changes.isEmpty()) {
this.clientIdentifierRepository.saveAndFlush(clientIdentifierForUpdate);
}
final Client client = this.clientRepository.findOne(clientId);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withOfficeId(client.getOffice().getId()) //
.withClientId(clientId) //
.withEntityId(identifierId) //
.with(changes) //
.build();
} catch (DataIntegrityViolationException dve) {
handleClientIdentifierDataIntegrityViolation(documentTypeLabel, documentTypeId, documentKey, dve);
return new CommandProcessingResult(Long.valueOf(-1));
}
}
@Transactional
@Override
public CommandProcessingResult deleteClientIdentifier(final Long clientId, final Long identifierId, final Long commandId) {
final ClientIdentifier clientIdentifier = this.clientIdentifierRepository.findOne(identifierId);
if (clientIdentifier == null) { throw new ClientIdentifierNotFoundException(identifierId); }
this.clientIdentifierRepository.delete(clientIdentifier);
final Client client = this.clientRepository.findOne(clientId);
return new CommandProcessingResultBuilder().withCommandId(commandId).withOfficeId(client.getOffice().getId())
.withClientId(clientId).withEntityId(identifierId).build();
}
private void handleClientIdentifierDataIntegrityViolation(final String documentTypeLabel, final Long documentTypeId,
final String documentKey, final DataIntegrityViolationException dve) {
if (dve.getMostSpecificCause().getMessage().contains("unique_client_identifier")) {
throw new DuplicateClientIdentifierException(documentTypeLabel);
} else if (dve.getMostSpecificCause().getMessage().contains("unique_identifier_key")) { throw new DuplicateClientIdentifierException(
documentTypeId, documentTypeLabel, documentKey); }
logAsErrorUnexpectedDataIntegrityException(dve);
throw new PlatformDataIntegrityException("error.msg.clientIdentifier.unknown.data.integrity.issue",
"Unknown data integrity issue with resource.");
}
private void logAsErrorUnexpectedDataIntegrityException(final DataIntegrityViolationException dve) {
logger.error(dve.getMessage(), dve);
}
}
@@ -10,7 +10,6 @@ import java.util.Collection;
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryCollectionData; import org.mifosplatform.portfolio.client.data.ClientAccountSummaryCollectionData;
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryData; import org.mifosplatform.portfolio.client.data.ClientAccountSummaryData;
import org.mifosplatform.portfolio.client.data.ClientData; import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.client.data.ClientIdentifierData;
import org.mifosplatform.portfolio.client.data.ClientLookup; import org.mifosplatform.portfolio.client.data.ClientLookup;
public interface ClientReadPlatformService { public interface ClientReadPlatformService {
@@ -29,9 +28,6 @@ public interface ClientReadPlatformService {
Collection<ClientAccountSummaryData> retrieveClientLoanAccountsByLoanOfficerId(Long clientId, Long loanOfficerId); Collection<ClientAccountSummaryData> retrieveClientLoanAccountsByLoanOfficerId(Long clientId, Long loanOfficerId);
Collection<ClientIdentifierData> retrieveClientIdentifiers(Long clientId);
ClientIdentifierData retrieveClientIdentifier(Long clientId, Long clientIdentifierId);
ClientData retrieveClientByIdentifier(Long identifierTypeId, String identifierKey); ClientData retrieveClientByIdentifier(Long identifierTypeId, String identifierKey);
} }
@@ -21,9 +21,7 @@ import org.mifosplatform.organisation.office.service.OfficeReadPlatformService;
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryCollectionData; import org.mifosplatform.portfolio.client.data.ClientAccountSummaryCollectionData;
import org.mifosplatform.portfolio.client.data.ClientAccountSummaryData; import org.mifosplatform.portfolio.client.data.ClientAccountSummaryData;
import org.mifosplatform.portfolio.client.data.ClientData; import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.client.data.ClientIdentifierData;
import org.mifosplatform.portfolio.client.data.ClientLookup; import org.mifosplatform.portfolio.client.data.ClientLookup;
import org.mifosplatform.portfolio.client.exception.ClientIdentifierNotFoundException;
import org.mifosplatform.portfolio.client.exception.ClientNotFoundException; import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
import org.mifosplatform.portfolio.loanaccount.data.LoanStatusEnumData; import org.mifosplatform.portfolio.loanaccount.data.LoanStatusEnumData;
import org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations; import org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations;
@@ -346,72 +344,6 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
} }
} }
@Override
public Collection<ClientIdentifierData> retrieveClientIdentifiers(final Long clientId) {
AppUser currentUser = context.authenticatedUser();
String hierarchy = currentUser.getOffice().getHierarchy();
String hierarchySearchString = hierarchy + "%";
ClientIdentityMapper rm = new ClientIdentityMapper();
String sql = "select " + rm.schema();
sql += " order by ci.id";
return this.jdbcTemplate.query(sql, rm, new Object[] { clientId, hierarchySearchString });
}
@Override
public ClientIdentifierData retrieveClientIdentifier(final Long clientId, final Long clientIdentifierId) {
try {
AppUser currentUser = context.authenticatedUser();
String hierarchy = currentUser.getOffice().getHierarchy();
String hierarchySearchString = hierarchy + "%";
ClientIdentityMapper rm = new ClientIdentityMapper();
String sql = "select " + rm.schema();
sql += " and ci.id = ?";
final ClientIdentifierData clientIdentifierData = this.jdbcTemplate.queryForObject(sql, rm, new Object[] { clientId,
hierarchySearchString, clientIdentifierId });
return clientIdentifierData;
} catch (EmptyResultDataAccessException e) {
throw new ClientIdentifierNotFoundException(clientIdentifierId);
}
}
private static final class ClientIdentityMapper implements RowMapper<ClientIdentifierData> {
public ClientIdentityMapper() {}
public String schema() {
return "ci.id as id, ci.client_id as clientId, ci.document_type_id as documentTypeId, ci.document_key as documentKey,"
+ " ci.description as description, cv.code_value as documentType "
+ " from m_client_identifier ci, m_client c, m_office o, m_code_value cv"
+ " where ci.client_id=c.id and c.office_id=o.id" + " and ci.document_type_id=cv.id"
+ " and ci.client_id = ? and o.hierarchy like ? ";
}
@Override
public ClientIdentifierData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = JdbcSupport.getLong(rs, "id");
final Long clientId = JdbcSupport.getLong(rs, "clientId");
final Long documentTypeId = JdbcSupport.getLong(rs, "documentTypeId");
final String documentKey = rs.getString("documentKey");
final String description = rs.getString("description");
final String documentTypeName = rs.getString("documentType");
return ClientIdentifierData.singleItem(id, clientId, documentTypeId, documentKey, description, documentTypeName);
}
}
@Override @Override
public ClientData retrieveClientByIdentifier(final Long identifierTypeId, final String identifierKey) { public ClientData retrieveClientByIdentifier(final Long identifierTypeId, final String identifierKey) {
try { try {
@@ -29,9 +29,4 @@ public interface ClientWritePlatformService {
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'DELETE_CLIENTIMAGE')") @PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'DELETE_CLIENTIMAGE')")
CommandProcessingResult deleteClientImage(Long clientId); CommandProcessingResult deleteClientImage(Long clientId);
CommandProcessingResult addClientIdentifier(Long clientId, JsonCommand command);
CommandProcessingResult updateClientIdentifier(Long clientId, Long clientIdentifierId, JsonCommand command);
CommandProcessingResult deleteClientIdentifier(Long clientId, Long clientIdentifierId, Long commandId);
} }
@@ -11,9 +11,6 @@ import java.io.InputStream;
import java.util.Map; import java.util.Map;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
import org.mifosplatform.infrastructure.codes.domain.CodeValueRepositoryWrapper;
import org.mifosplatform.infrastructure.codes.exception.CodeValueNotFoundException;
import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
@@ -25,18 +22,12 @@ import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext
import org.mifosplatform.organisation.office.domain.Office; import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.organisation.office.domain.OfficeRepository; import org.mifosplatform.organisation.office.domain.OfficeRepository;
import org.mifosplatform.organisation.office.exception.OfficeNotFoundException; import org.mifosplatform.organisation.office.exception.OfficeNotFoundException;
import org.mifosplatform.portfolio.client.command.ClientIdentifierCommand;
import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator; import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator;
import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory; import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory;
import org.mifosplatform.portfolio.client.domain.Client; import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.domain.ClientIdentifier;
import org.mifosplatform.portfolio.client.domain.ClientIdentifierRepository;
import org.mifosplatform.portfolio.client.domain.ClientRepository; import org.mifosplatform.portfolio.client.domain.ClientRepository;
import org.mifosplatform.portfolio.client.exception.ClientIdentifierNotFoundException;
import org.mifosplatform.portfolio.client.exception.ClientNotFoundException; import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
import org.mifosplatform.portfolio.client.exception.DuplicateClientIdentifierException;
import org.mifosplatform.portfolio.client.serialization.ClientCommandFromApiJsonDeserializer; import org.mifosplatform.portfolio.client.serialization.ClientCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.client.serialization.ClientIdentifierCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.group.domain.Group; import org.mifosplatform.portfolio.group.domain.Group;
import org.mifosplatform.portfolio.group.domain.GroupRepository; import org.mifosplatform.portfolio.group.domain.GroupRepository;
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException; import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
@@ -54,29 +45,19 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
private final PlatformSecurityContext context; private final PlatformSecurityContext context;
private final ClientRepository clientRepository; private final ClientRepository clientRepository;
private final ClientIdentifierRepository clientIdentifierRepository;
private final OfficeRepository officeRepository; private final OfficeRepository officeRepository;
private final GroupRepository groupRepository; private final GroupRepository groupRepository;
private final CodeValueRepositoryWrapper codeValueRepository;
private final ClientCommandFromApiJsonDeserializer fromApiJsonDeserializer; private final ClientCommandFromApiJsonDeserializer fromApiJsonDeserializer;
private final ClientIdentifierCommandFromApiJsonDeserializer clientIdentifierCommandFromApiJsonDeserializer;
private final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory; private final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory;
@Autowired @Autowired
public ClientWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final ClientRepository clientRepository, public ClientWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final ClientRepository clientRepository,
final ClientIdentifierRepository clientIdentifierRepository, final OfficeRepository officeRepository, final OfficeRepository officeRepository, final ClientCommandFromApiJsonDeserializer fromApiJsonDeserializer,
final CodeValueRepositoryWrapper codeValueRepository, final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory, final GroupRepository groupRepository) {
final ClientCommandFromApiJsonDeserializer fromApiJsonDeserializer,
final ClientIdentifierCommandFromApiJsonDeserializer clientIdentifierCommandFromApiJsonDeserializer,
final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory,
final GroupRepository groupRepository) {
this.context = context; this.context = context;
this.clientRepository = clientRepository; this.clientRepository = clientRepository;
this.clientIdentifierRepository = clientIdentifierRepository;
this.officeRepository = officeRepository; this.officeRepository = officeRepository;
this.codeValueRepository = codeValueRepository;
this.fromApiJsonDeserializer = fromApiJsonDeserializer; this.fromApiJsonDeserializer = fromApiJsonDeserializer;
this.clientIdentifierCommandFromApiJsonDeserializer = clientIdentifierCommandFromApiJsonDeserializer;
this.accountIdentifierGeneratorFactory = accountIdentifierGeneratorFactory; this.accountIdentifierGeneratorFactory = accountIdentifierGeneratorFactory;
this.groupRepository = groupRepository; this.groupRepository = groupRepository;
} }
@@ -137,12 +118,12 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
Group clientParentGroup = null; Group clientParentGroup = null;
if(groupId != null){ if (groupId != null) {
clientParentGroup = this.groupRepository.findOne(groupId); clientParentGroup = this.groupRepository.findOne(groupId);
if (clientParentGroup == null) { throw new GroupNotFoundException(groupId); } if (clientParentGroup == null) { throw new GroupNotFoundException(groupId); }
} }
final Client newClient = Client.fromJson(clientOffice, clientParentGroup , command); final Client newClient = Client.fromJson(clientOffice, clientParentGroup, command);
this.clientRepository.save(newClient); this.clientRepository.save(newClient);
if (newClient.isAccountNumberRequiresAutoGeneration()) { if (newClient.isAccountNumberRequiresAutoGeneration()) {
@@ -203,129 +184,6 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
} }
} }
@Transactional
@Override
public CommandProcessingResult addClientIdentifier(final Long clientId, final JsonCommand command) {
context.authenticatedUser();
final ClientIdentifierCommand clientIdentifierCommand = this.clientIdentifierCommandFromApiJsonDeserializer
.commandFromApiJson(command.json());
clientIdentifierCommand.validateForCreate();
String documentKey = clientIdentifierCommand.getDocumentKey();
String documentTypeLabel = null;
Long documentTypeId = null;
try {
final Client client = this.clientRepository.findOne(clientId);
if (client == null || client.isDeleted()) { throw new ClientNotFoundException(clientId); }
final CodeValue documentType = this.codeValueRepository.findOneWithNotFoundDetection(clientIdentifierCommand.getDocumentTypeId());
documentTypeId = documentType.getId();
documentTypeLabel = documentType.label();
final ClientIdentifier clientIdentifier = ClientIdentifier.fromJson(client, documentType, command);
this.clientIdentifierRepository.save(clientIdentifier);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withOfficeId(client.getOffice().getId()) //
.withClientId(clientId) //
.withEntityId(clientIdentifier.getId()) //
.build();
} catch (DataIntegrityViolationException dve) {
handleClientIdentifierDataIntegrityViolation(documentTypeLabel, documentTypeId, documentKey, dve);
return CommandProcessingResult.empty();
}
}
@Transactional
@Override
public CommandProcessingResult updateClientIdentifier(final Long clientId, final Long identifierId, final JsonCommand command) {
context.authenticatedUser();
final ClientIdentifierCommand clientIdentifierCommand = this.clientIdentifierCommandFromApiJsonDeserializer
.commandFromApiJson(command.json());
clientIdentifierCommand.validateForUpdate();
String documentTypeLabel = null;
String documentKey = null;
Long documentTypeId = clientIdentifierCommand.getDocumentTypeId();
try {
CodeValue documentType = null;
final ClientIdentifier clientIdentifierForUpdate = this.clientIdentifierRepository.findOne(identifierId);
if (clientIdentifierForUpdate == null) { throw new ClientIdentifierNotFoundException(identifierId); }
final Map<String, Object> changes = clientIdentifierForUpdate.update(command);
if (changes.containsKey("documentTypeId")) {
documentType = this.codeValueRepository.findOneWithNotFoundDetection(documentTypeId);
if (documentType == null) { throw new CodeValueNotFoundException(documentTypeId); }
documentTypeId = documentType.getId();
documentTypeLabel = documentType.label();
clientIdentifierForUpdate.update(documentType);
}
if (changes.containsKey("documentTypeId") && changes.containsKey("documentKey")) {
documentTypeId = clientIdentifierCommand.getDocumentTypeId();
documentKey = clientIdentifierCommand.getDocumentKey();
} else if (changes.containsKey("documentTypeId") && !changes.containsKey("documentKey")) {
documentTypeId = clientIdentifierCommand.getDocumentTypeId();
documentKey = clientIdentifierForUpdate.documentKey();
} else if (!changes.containsKey("documentTypeId") && changes.containsKey("documentKey")) {
documentTypeId = clientIdentifierForUpdate.documentTypeId();
documentKey = clientIdentifierForUpdate.documentKey();
}
if (!changes.isEmpty()) {
this.clientIdentifierRepository.saveAndFlush(clientIdentifierForUpdate);
}
final Client client = this.clientRepository.findOne(clientId);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withOfficeId(client.getOffice().getId()) //
.withClientId(clientId) //
.withEntityId(identifierId) //
.with(changes) //
.build();
} catch (DataIntegrityViolationException dve) {
handleClientIdentifierDataIntegrityViolation(documentTypeLabel, documentTypeId, documentKey, dve);
return new CommandProcessingResult(Long.valueOf(-1));
}
}
private void handleClientIdentifierDataIntegrityViolation(final String documentTypeLabel, final Long documentTypeId,
final String documentKey, final DataIntegrityViolationException dve) {
if (dve.getMostSpecificCause().getMessage().contains("unique_client_identifier")) {
throw new DuplicateClientIdentifierException(documentTypeLabel);
} else if (dve.getMostSpecificCause().getMessage().contains("unique_identifier_key")) { throw new DuplicateClientIdentifierException(
documentTypeId, documentTypeLabel, documentKey); }
logAsErrorUnexpectedDataIntegrityException(dve);
throw new PlatformDataIntegrityException("error.msg.clientIdentifier.unknown.data.integrity.issue",
"Unknown data integrity issue with resource.");
}
private void logAsErrorUnexpectedDataIntegrityException(final DataIntegrityViolationException dve) {
logger.error(dve.getMessage(), dve);
}
@Transactional
@Override
public CommandProcessingResult deleteClientIdentifier(final Long clientId, final Long identifierId, final Long commandId) {
final ClientIdentifier clientIdentifier = this.clientIdentifierRepository.findOne(identifierId);
if (clientIdentifier == null) { throw new ClientIdentifierNotFoundException(identifierId); }
this.clientIdentifierRepository.delete(clientIdentifier);
final Client client = this.clientRepository.findOne(clientId);
return new CommandProcessingResultBuilder().withCommandId(commandId).withOfficeId(client.getOffice().getId())
.withClientId(clientId).withEntityId(identifierId).build();
}
@Transactional @Transactional
@Override @Override
public CommandProcessingResult saveOrUpdateClientImage(Long clientId, String imageName, InputStream inputStream) { public CommandProcessingResult saveOrUpdateClientImage(Long clientId, String imageName, InputStream inputStream) {
@@ -393,4 +251,9 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
return new CommandProcessingResult(clientId); return new CommandProcessingResult(clientId);
} }
private void logAsErrorUnexpectedDataIntegrityException(final DataIntegrityViolationException dve) {
logger.error(dve.getMessage(), dve);
}
} }