ShruthiRajaram closed pull request #466: FINERACT:628 API support for self 
share accounts
URL: https://github.com/apache/fineract/pull/466
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm
index 9a87171cc..c6f966ff7 100644
--- a/api-docs/apiLive.htm
+++ b/api-docs/apiLive.htm
@@ -3697,6 +3697,30 @@ <h2 class="flybar-button">Self Service</h2>
                                                                <td></td>
                                                                <td></td>
                                                        </tr>
+                                                       <tr>
+                                                               <td><a 
href="#selfshareaccount_template">Share Accounts</a></td>
+                                                               
<td>self/shareaccounts/template?clientId=?productId=?</td>
+                                                               <td></td>
+                                                               <td><a 
href="#selfshareaccount_template">Share Accounts Template</a></td>
+                                                               <td></td>
+                                                               <td></td>
+                                                       </tr>
+                                                       
+                                                       <tr>
+                                                               <td></td>
+                                                               
<td>self/shareaccounts</td>
+                                                               <td><a 
href="#selfshareaccount_create">Submit New Share Application</a></td>
+                                                               <td></td>
+                                                               <td></td>
+                                                               <td></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td></td>
+                                                               
<td>self/shareaccounts/{accountId}</td>
+                                                               <td></td>
+                                                               <td><a 
href="#selfshareaccount_retrieve">Retrieve a Share Application/Account</a></td>
+                                                               <td></td>
+                                                       </tr>                   
        
                                                        <tr>
                                                                <td><a 
href="#selftransfertemplate">Own Account Transfers</a></td>
                                                                
<td>self/accounttransfers/template</td>
@@ -47487,6 +47511,889 @@ <h2>Third Party Account Transfer</h2>
                </code>
            </div>
        </div>
+       
+       <a id="selfshareaccount_template" name="selfshareaccount_template" 
class="old-syle-anchor">&nbsp;</a>
+       <div class="method-section">
+           <div class="method-description">
+               <h2>Retrieve Share Account Template:</h2>
+                   <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>
+               <h4>Arguments</h4>
+               <dl class="argument-list">
+                   <dt>clientId</dt>
+                   <dd>Integer <span>mandatory</span></dd>
+                   <dt>productId</dt>
+                   <dd>Integer <span>optional</span></dd>
+                   <dd>If entered, productId, productName and selectedProduct 
fields are returned.</dd>
+               </dl>
+               <p>Example Requests: </p>
+               <div 
class=apiClick>self/shareaccounts/template?clientId=14</div>
+               <br><br>
+               <div 
class=apiClick>self/shareaccounts/template?clientId=14&productId=3</div>
+           </div>
+           <div class="method-example">
+               <code class="method-declaration">GET https://Domain 
Name/api/v1/self/shareaccounts/template?clientId={clientId}</code>
+                       <code class="method-response">
+{
+    "clientId": 14,
+    "productOptions": [
+        {
+            "id": 3,
+            "name": "SP",
+            "shortName": "SP",
+            "totalShares": 1000
+        },
+        {
+            "id": 4,
+            "name": "Product1",
+            "shortName": "test",
+            "totalShares": 1000
+        }
+    ],
+    "chargeOptions": [
+        {
+            "id": 2,
+            "name": "Activation fee",
+            "active": true,
+            "penalty": false,
+            "currency": {
+                "code": "USD",
+                "name": "US Dollar",
+                "decimalPlaces": 2,
+                "displaySymbol": "$",
+                "nameCode": "currency.USD",
+                "displayLabel": "US Dollar ($)"
+            },
+            "amount": 2,
+            "chargeTimeType": {
+                "id": 14,
+                "code": "chargeTimeType.sharespurchase",
+                "value": "Share Purchase"
+            },
+            "chargeAppliesTo": {
+                "id": 4,
+                "code": "chargeAppliesTo.shares",
+                "value": "Shares"
+            },
+            "chargeCalculationType": {
+                "id": 1,
+                "code": "chargeCalculationType.flat",
+                "value": "Flat"
+            },
+            "chargePaymentMode": {
+                "id": 0,
+                "code": "chargepaymentmode.regular",
+                "value": "Regular"
+            }
+        }
+    ]
+}
+                       </code>
+           </div>
+
+           <div class="method-example">
+               <code class="method-declaration">GET https://Domain 
Name/api/v1/self/shareaccounts/template?clientId={clientId}&productId={productId}</code>
+                       <code class="method-response">
+{
+    "clientId": 14,
+    "productOptions": [
+        {
+            "id": 3,
+            "name": "SP",
+            "shortName": "SP",
+            "description": "SP1",
+            "currency": {
+                "code": "USD",
+                "name": "US Dollar",
+                "decimalPlaces": 2,
+                "inMultiplesOf": 1,
+                "displaySymbol": "$",
+                "nameCode": "currency.USD",
+                "displayLabel": "US Dollar ($)"
+            },
+            "totalShares": 1000,
+            "totalSharesIssued": 900,
+            "unitPrice": 1,
+            "shareCapital": 900,
+            "minimumShares": 8,
+            "nominalShares": 500,
+            "maximumShares": 500,
+            "marketPrice": [],
+            "charges": [],
+            "allowDividendCalculationForInactiveClients": false,
+            "lockinPeriod": 50,
+            "lockPeriodTypeEnum": {
+                "id": 0,
+                "code": "shares.lockin.sharePeriodFrequencyType.days",
+                "value": "Days"
+            },
+            "minimumActivePeriod": 10,
+            "minimumActivePeriodForDividendsTypeEnum": {
+                "id": 0,
+                "code": "shares.minimumactive.sharePeriodFrequencyType.days",
+                "value": "Days"
+            },
+            "accountingRule": {
+                "id": 2,
+                "code": "accountingRuleType.cash",
+                "value": "CASH BASED"
+            },
+            "accountingMappings": {
+                "shareReferenceId": {
+                    "id": 32,
+                    "name": "Cash In Hand",
+                    "glCode": "20301"
+                },
+                "incomeFromFeeAccountId": {
+                    "id": 40,
+                    "name": "Other Operating Income",
+                    "glCode": "30105"
+                },
+                "shareEquityId": {
+                    "id": 56,
+                    "name": "Share Equity",
+                    "glCode": "00098"
+                },
+                "shareSuspenseId": {
+                    "id": 2,
+                    "name": "Overpayment Liability",
+                    "glCode": "10200"
+                }
+            },
+            "currencyOptions": [
+                {
+                    "code": "USD",
+                    "name": "US Dollar",
+                    "decimalPlaces": 2,
+                    "displaySymbol": "$",
+                    "nameCode": "currency.USD",
+                    "displayLabel": "US Dollar ($)"
+                }
+            ],
+            "chargeOptions": [
+                {
+                    "id": 2,
+                    "name": "Activation fee",
+                    "active": true,
+                    "penalty": false,
+                    "currency": {
+                        "code": "USD",
+                        "name": "US Dollar",
+                        "decimalPlaces": 2,
+                        "displaySymbol": "$",
+                        "nameCode": "currency.USD",
+                        "displayLabel": "US Dollar ($)"
+                    },
+                    "amount": 2,
+                    "chargeTimeType": {
+                        "id": 14,
+                        "code": "chargeTimeType.sharespurchase",
+                        "value": "Share Purchase"
+                    },
+                    "chargeAppliesTo": {
+                        "id": 4,
+                        "code": "chargeAppliesTo.shares",
+                        "value": "Shares"
+                    },
+                    "chargeCalculationType": {
+                        "id": 1,
+                        "code": "chargeCalculationType.flat",
+                        "value": "Flat"
+                    },
+                    "chargePaymentMode": {
+                        "id": 0,
+                        "code": "chargepaymentmode.regular",
+                        "value": "Regular"
+                    }
+                }
+            ],
+            "minimumActivePeriodFrequencyTypeOptions": [
+                {
+                    "id": 0,
+                    "code": "shares.lockin.sharePeriodFrequencyType.days",
+                    "value": "Days"
+                }
+            ],
+            "lockinPeriodFrequencyTypeOptions": [
+                {
+                    "id": 0,
+                    "code": "shares.lockin.sharePeriodFrequencyType.days",
+                    "value": "Days"
+                },
+                {
+                    "id": 1,
+                    "code": "shares.lockin.sharePeriodFrequencyType.weeks",
+                    "value": "Weeks"
+                },
+                {
+                    "id": 2,
+                    "code": "shares.lockin.sharePeriodFrequencyType.months",
+                    "value": "Months"
+                },
+                {
+                    "id": 3,
+                    "code": "shares.lockin.sharePeriodFrequencyType.years",
+                    "value": "Years"
+                }
+            ],
+            "accountingMappingOptions": {
+                "liabilityAccountOptions": [
+                    {
+                        "id": 30,
+                        "name": "Recurring Deposits",
+                        "parentId": 1,
+                        "glCode": "10104",
+                        "disabled": false,
+                        "manualEntriesAllowed": true,
+                        "type": {
+                            "id": 2,
+                            "code": "accountType.liability",
+                            "value": "LIABILITY"
+                        },
+                        "usage": {
+                            "id": 1,
+                            "code": "accountUsage.detail",
+                            "value": "DETAIL"
+                        },
+                        "nameDecorated": "....Recurring Deposits",
+                        "tagId": {
+                            "id": 0,
+                            "active": false,
+                            "mandatory": false
+                        }
+                    },
+                    {
+                        "id": 2,
+                        "name": "Overpayment Liability",
+                        "glCode": "10200",
+                        "disabled": false,
+                        "manualEntriesAllowed": true,
+                        "type": {
+                            "id": 2,
+                            "code": "accountType.liability",
+                            "value": "LIABILITY"
+                        },
+                        "usage": {
+                            "id": 1,
+                            "code": "accountUsage.detail",
+                            "value": "DETAIL"
+                        },
+                        "nameDecorated": "Overpayment Liability",
+                        "tagId": {
+                            "id": 0,
+                            "active": false,
+                            "mandatory": false
+                        }
+                    },
+                    {
+                        "id": 55,
+                        "name": "Liability Transfer (Temp)",
+                        "glCode": "220004-Temp",
+                        "disabled": false,
+                        "manualEntriesAllowed": true,
+                        "type": {
+                            "id": 2,
+                            "code": "accountType.liability",
+                            "value": "LIABILITY"
+                        },
+                        "usage": {
+                            "id": 1,
+                            "code": "accountUsage.detail",
+                            "value": "DETAIL"
+                        },
+                        "description": "Temporary Liability account to track 
Account Transfers",
+                        "nameDecorated": "Liability Transfer (Temp)",
+                        "tagId": {
+                            "id": 0,
+                            "active": false,
+                            "mandatory": false
+                        }
+                    }
+                ],
+                "assetAccountOptions": [
+                    {
+                        "id": 31,
+                        "name": "Furniture and Fixtures",
+                        "parentId": 8,
+                        "glCode": "20101",
+                        "disabled": false,
+                        "manualEntriesAllowed": true,
+                        "type": {
+                            "id": 1,
+                            "code": "accountType.asset",
+                            "value": "ASSET"
+                        },
+                        "usage": {
+                            "id": 1,
+                            "code": "accountUsage.detail",
+                            "value": "DETAIL"
+                        },
+                        "nameDecorated": "....Furniture and Fixtures",
+                        "tagId": {
+                            "id": 0,
+                            "active": false,
+                            "mandatory": false
+                        }
+                    },
+                    {
+                        "id": 32,
+                        "name": "Cash In Hand",
+                        "parentId": 10,
+                        "glCode": "20301",
+                        "disabled": false,
+                        "manualEntriesAllowed": true,
+                        "type": {
+                            "id": 1,
+                            "code": "accountType.asset",
+                            "value": "ASSET"
+                        },
+                        "usage": {
+                            "id": 1,
+                            "code": "accountUsage.detail",
+                            "value": "DETAIL"
+                        },
+                        "nameDecorated": "....Cash In Hand",
+                        "tagId": {
+                            "id": 0,
+                            "active": false,
+                            "mandatory": false
+                        }
+                    },
+                    {
+                        "id": 33,
+                        "name": "Petty Cash",
+                        "parentId": 10,
+                        "glCode": "20302",
+                        "disabled": false,
+                        "manualEntriesAllowed": true,
+                        "type": {
+                            "id": 1,
+                            "code": "accountType.asset",
+                            "value": "ASSET"
+                        },
+                        "usage": {
+                            "id": 1,
+                            "code": "accountUsage.detail",
+                            "value": "DETAIL"
+                        },
+                        "nameDecorated": "....Petty Cash",
+                        "tagId": {
+                            "id": 0,
+                            "active": false,
+                            "mandatory": false
+                        }
+                    },
+                    {
+                        "id": 34,
+                        "name": "Loans to Customers",
+                        "parentId": 12,
+                        "glCode": "20501",
+                        "disabled": false,
+                        "manualEntriesAllowed": true,
+                        "type": {
+                            "id": 1,
+                            "code": "accountType.asset",
+                            "value": "ASSET"
+                        },
+                        "usage": {
+                            "id": 1,
+                            "code": "accountUsage.detail",
+                            "value": "DETAIL"
+                        },
+                        "nameDecorated": "....Loans to Customers",
+                        "tagId": {
+                            "id": 0,
+                            "active": false,
+                            "mandatory": false
+                        }
+                    },
+                    {
+                        "id": 35,
+                        "name": "Current Account Overdrafts",
+                        "parentId": 12,
+                        "glCode": "20502",
+                        "disabled": false,
+                        "manualEntriesAllowed": true,
+                        "type": {
+                            "id": 1,
+                            "code": "accountType.asset",
+                            "value": "ASSET"
+                        },
+                        "usage": {
+                            "id": 1,
+                            "code": "accountUsage.detail",
+                            "value": "DETAIL"
+                        },
+                        "nameDecorated": "....Current Account Overdrafts",
+                        "tagId": {
+                            "id": 0,
+                            "active": false,
+                            "mandatory": false
+                        }
+                    },
+                    {
+                        "id": 17,
+                        "name": "Suspense Account",
+                        "glCode": "9999",
+                        "disabled": false,
+                        "manualEntriesAllowed": true,
+                        "type": {
+                            "id": 1,
+                            "code": "accountType.asset",
+                            "value": "ASSET"
+                        },
+                        "usage": {
+                            "id": 1,
+                            "code": "accountUsage.detail",
+                            "value": "DETAIL"
+                        },
+                        "nameDecorated": "Suspense Account",
+                        "tagId": {
+                            "id": 0,
+                            "active": false,
+                            "mandatory": false
+                        }
+                    }
+                ],
+                "incomeAccountOptions": [
+                    {
+                        "id": 54,
+                        "name": "Loan Recovery (Temp)",
+                        "glCode": "220002-Temp",
+                        "disabled": false,
+                        "manualEntriesAllowed": true,
+                        "type": {
+                            "id": 4,
+                            "code": "accountType.income",
+                            "value": "INCOME"
+                        },
+                        "usage": {
+                            "id": 1,
+                            "code": "accountUsage.detail",
+                            "value": "DETAIL"
+                        },
+                        "description": "Temporary account to track income from 
Loan recovery",
+                        "nameDecorated": "Loan Recovery (Temp)",
+                        "tagId": {
+                            "id": 0,
+                            "active": false,
+                            "mandatory": false
+                        }
+                    },
+                    {
+                        "id": 36,
+                        "name": "Fees and Charges",
+                        "parentId": 18,
+                        "glCode": "30101",
+                        "disabled": false,
+                        "manualEntriesAllowed": true,
+                        "type": {
+                            "id": 4,
+                            "code": "accountType.income",
+                            "value": "INCOME"
+                        },
+                        "usage": {
+                            "id": 1,
+                            "code": "accountUsage.detail",
+                            "value": "DETAIL"
+                        },
+                        "nameDecorated": "....Fees and Charges",
+                        "tagId": {
+                            "id": 0,
+                            "active": false,
+                            "mandatory": false
+                        }
+                    },
+                    {
+                        "id": 37,
+                        "name": "Penalties",
+                        "parentId": 18,
+                        "glCode": "30102",
+                        "disabled": false,
+                        "manualEntriesAllowed": true,
+                        "type": {
+                            "id": 4,
+                            "code": "accountType.income",
+                            "value": "INCOME"
+                        },
+                        "usage": {
+                            "id": 1,
+                            "code": "accountUsage.detail",
+                            "value": "DETAIL"
+                        },
+                        "nameDecorated": "....Penalties",
+                        "tagId": {
+                            "id": 0,
+                            "active": false,
+                            "mandatory": false
+                        }
+                    },
+                    {
+                        "id": 38,
+                        "name": "Interest Received from Borrowers",
+                        "parentId": 18,
+                        "glCode": "30103",
+                        "disabled": false,
+                        "manualEntriesAllowed": true,
+                        "type": {
+                            "id": 4,
+                            "code": "accountType.income",
+                            "value": "INCOME"
+                        },
+                        "usage": {
+                            "id": 1,
+                            "code": "accountUsage.detail",
+                            "value": "DETAIL"
+                        },
+                        "nameDecorated": "....Interest Received from 
Borrowers",
+                        "tagId": {
+                            "id": 0,
+                            "active": false,
+                            "mandatory": false
+                        }
+                    },
+                    {
+                        "id": 39,
+                        "name": "Insurance Charges",
+                        "parentId": 18,
+                        "glCode": "30104",
+                        "disabled": false,
+                        "manualEntriesAllowed": true,
+                        "type": {
+                            "id": 4,
+                            "code": "accountType.income",
+                            "value": "INCOME"
+                        },
+                        "usage": {
+                            "id": 1,
+                            "code": "accountUsage.detail",
+                            "value": "DETAIL"
+                        },
+                        "nameDecorated": "....Insurance Charges",
+                        "tagId": {
+                            "id": 0,
+                            "active": false,
+                            "mandatory": false
+                        }
+                    },
+                    {
+                        "id": 40,
+                        "name": "Other Operating Income",
+                        "parentId": 18,
+                        "glCode": "30105",
+                        "disabled": false,
+                        "manualEntriesAllowed": true,
+                        "type": {
+                            "id": 4,
+                            "code": "accountType.income",
+                            "value": "INCOME"
+                        },
+                        "usage": {
+                            "id": 1,
+                            "code": "accountUsage.detail",
+                            "value": "DETAIL"
+                        },
+                        "nameDecorated": "....Other Operating Income",
+                        "tagId": {
+                            "id": 0,
+                            "active": false,
+                            "mandatory": false
+                        }
+                    }
+                ],
+                "equityAccountOptions": [
+                    {
+                        "id": 56,
+                        "name": "Share Equity",
+                        "parentId": 25,
+                        "glCode": "00098",
+                        "disabled": false,
+                        "manualEntriesAllowed": true,
+                        "type": {
+                            "id": 3,
+                            "code": "accountType.equity",
+                            "value": "EQUITY"
+                        },
+                        "usage": {
+                            "id": 1,
+                            "code": "accountUsage.detail",
+                            "value": "DETAIL"
+                        },
+                        "nameDecorated": "....Share Equity",
+                        "tagId": {
+                            "id": 0,
+                            "active": false,
+                            "mandatory": false
+                        }
+                    }
+                ]
+            }
+        }
+    ],
+    "chargeOptions": [
+        {
+            "id": 2,
+            "name": "Activation fee",
+            "active": true,
+            "penalty": false,
+            "currency": {
+                "code": "USD",
+                "name": "US Dollar",
+                "decimalPlaces": 2,
+                "displaySymbol": "$",
+                "nameCode": "currency.USD",
+                "displayLabel": "US Dollar ($)"
+            },
+            "amount": 2,
+            "chargeTimeType": {
+                "id": 14,
+                "code": "chargeTimeType.sharespurchase",
+                "value": "Share Purchase"
+            },
+            "chargeAppliesTo": {
+                "id": 4,
+                "code": "chargeAppliesTo.shares",
+                "value": "Shares"
+            },
+            "chargeCalculationType": {
+                "id": 1,
+                "code": "chargeCalculationType.flat",
+                "value": "Flat"
+            },
+            "chargePaymentMode": {
+                "id": 0,
+                "code": "chargepaymentmode.regular",
+                "value": "Regular"
+            }
+        }
+    ]
+}
+                       </code>
+           </div>
+</div>
+
+<a id="selfshareaccount_create" name="selfshareaccount_create" 
class="old-syle-anchor">&nbsp;</a>
+       <div class="method-section">
+           <div class="method-description">
+               <h2>Submit new share application</h2>
+               <br/>
+               <table class=matrixHeading>
+                   <tr class="matrixHeadingBG"><td><div 
class="fineractHeading2">Mandatory Fields</div></td></tr>
+                   <tr class=alt><td>clientId, productId, submittedDate, 
savingsAccountId, requestedShares, applicationDate</td></tr>
+               </table>
+               <br/>
+               <table class=matrixHeading>
+                   <tr class="matrixHeadingBG"><td><div 
class="fineractHeading2">Optional Fields</div></td></tr>
+                   <tr class=alt><td>accountNo, externalId</td></tr>
+               </table>
+               <br/>
+               <table class=matrixHeading>
+                   <tr class="matrixHeadingBG"><td><div 
class="fineractHeading2">Inherited from Product (if not 
provided)</div></td></tr>
+                   <tr class=alt><td> minimumActivePeriod, 
minimumActivePeriodFrequencyType, lockinPeriodFrequency, 
lockinPeriodFrequencyType</td>
+                       </tr>
+               </table>
+           </div>
+           <div class="method-example">
+               <p>Minimal request: accountNo auto generated, remaining details 
inherited from Share product.</p>
+               <code class="method-declaration">POST https://Domain 
Name/api/v1/self/shareaccounts</code>
+               <code class="method-request">POST Share Account
+Content-Type: application/json
+Request Body:
+{  
+   "productId":3,
+   "unitPrice":1,
+   "requestedShares":500,
+   "submittedDate":"31 July 2018",
+   "savingsAccountId":2,
+   "applicationDate":"31 July 2018",
+   "locale":"en",
+   "dateFormat":"dd MMMM yyyy",
+   "charges":[  
+      {  
+         "chargeId":2,
+         "amount":2
+      }
+   ],
+   "clientId":"14"
+}
+                       </code>
+               <code class="method-response">
+{
+    "resourceId": 12
+}
+               </code>
+           </div>
+</div>
+
+<a id="selfshareaccount_retrieve" name="selfshareaccount_retrieve" 
class="old-syle-anchor">&nbsp;</a>
+       <div class="method-section">
+           <div class="method-description">
+               <h2>Retrieve a share application/account:</h2>
+
+               <p>Example Requests : </p>
+               <div class=apiClick>self/shareaccounts/12</div>
+           </div>
+           <div class="method-example">
+               <code class="method-declaration">GET 
https://DomainName/api/v1/self/shareaccounts/{accountId}</code>
+               <code class="method-response">
+{
+    "id": 12,
+    "accountNo": "000000012",
+    "savingsAccountNumber": "000000002",
+    "clientId": 14,
+    "clientName": "Bheem",
+    "productId": 3,
+    "productName": "SP",
+    "status": {
+        "id": 100,
+        "code": "shareAccountStatusType.submitted.and.pending.approval",
+        "value": "Submitted and pending approval",
+        "submittedAndPendingApproval": true,
+        "approved": false,
+        "rejected": false,
+        "active": false,
+        "closed": false
+    },
+    "timeline": {
+        "submittedOnDate": [
+            2018,
+            7,
+            31
+        ],
+        "submittedByUsername": "self",
+        "submittedByFirstname": "self",
+        "submittedByLastname": "self"
+    },
+    "currency": {
+        "code": "USD",
+        "name": "US Dollar",
+        "decimalPlaces": 2,
+        "inMultiplesOf": 1,
+        "displaySymbol": "$",
+        "nameCode": "currency.USD",
+        "displayLabel": "US Dollar ($)"
+    },
+    "summary": {
+        "id": 12,
+        "accountNo": "000000012",
+        "totalApprovedShares": 0,
+        "totalPendingForApprovalShares": 500,
+        "productId": 3,
+        "productName": "SP",
+        "status": {
+            "id": 100,
+            "code": "shareAccountStatusType.submitted.and.pending.approval",
+            "value": "Submitted and pending approval",
+            "submittedAndPendingApproval": true,
+            "approved": false,
+            "rejected": false,
+            "active": false,
+            "closed": false
+        },
+        "currency": {
+            "code": "USD",
+            "name": "US Dollar",
+            "decimalPlaces": 2,
+            "inMultiplesOf": 1,
+            "displaySymbol": "$",
+            "nameCode": "currency.USD",
+            "displayLabel": "US Dollar ($)"
+        },
+        "timeline": {
+            "submittedOnDate": [
+                2018,
+                7,
+                31
+            ],
+            "submittedByUsername": "self",
+            "submittedByFirstname": "self",
+            "submittedByLastname": "self"
+        }
+    },
+    "purchasedShares": [
+        {
+            "id": 13,
+            "accountId": 12,
+            "purchasedDate": [
+                2018,
+                7,
+                31
+            ],
+            "numberOfShares": 500,
+            "purchasedPrice": 1,
+            "status": {
+                "id": 100,
+                "code": "purchasedSharesStatusType.applied",
+                "value": "Pending Approval"
+            },
+            "type": {
+                "id": 500,
+                "code": "purchasedSharesType.purchased",
+                "value": "Purchase"
+            },
+            "amount": 502,
+            "chargeAmount": 2,
+            "amountPaid": 500
+        }
+    ],
+    "savingsAccountId": 2,
+    "currentMarketPrice": 1,
+    "lockPeriodTypeEnum": {
+        "id": 4,
+        "code": "sharePeriodFrequencyType.invalid",
+        "value": "Invalid"
+    },
+    "minimumActivePeriodTypeEnum": {
+        "id": 4,
+        "code": "sharePeriodFrequencyType.invalid",
+        "value": "Invalid"
+    },
+    "allowDividendCalculationForInactiveClients": false,
+    "charges": [
+        {
+            "id": 9,
+            "chargeId": 2,
+            "accountId": 12,
+            "name": "Activation fee",
+            "chargeTimeType": {
+                "id": 14,
+                "code": "chargeTimeType.sharespurchase",
+                "value": "Share Purchase"
+            },
+            "chargeCalculationType": {
+                "id": 1,
+                "code": "chargeCalculationType.flat",
+                "value": "Flat"
+            },
+            "percentage": 0,
+            "amountPercentageAppliedTo": 0,
+            "currency": {
+                "code": "USD",
+                "name": "US Dollar",
+                "decimalPlaces": 2,
+                "displaySymbol": "$",
+                "nameCode": "currency.USD",
+                "displayLabel": "US Dollar ($)"
+            },
+            "amount": 2,
+            "amountPaid": 0,
+            "amountWaived": 0,
+            "amountWrittenOff": 0,
+            "amountOutstanding": 2,
+            "amountOrPercentage": 2,
+            "isActive": true
+        }
+    ],
+    "dividends": []
+}
+               </code>
+           </div>
+</div>
+
                        <!-- end of Customer Self Service APIs-->
         </div>
                <!-- main-content-wrapper -->
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accounts/constants/ShareAccountApiConstants.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accounts/constants/ShareAccountApiConstants.java
index 7ab98a1ca..04aeb749c 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accounts/constants/ShareAccountApiConstants.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accounts/constants/ShareAccountApiConstants.java
@@ -95,7 +95,9 @@
        
        public String additionalshares_paramname = "additionalshares" ;
        
-       public String closeddate_paramname = "closedDate" ;
+       public String closeddate_paramname = "closedDate";
+
+       public static final String shareEntityType = "share";
        
        Set<String> supportedParameters = new 
HashSet<>(Arrays.asList(locale_paramname, dateformat_paramname, 
id_paramname,clientid_paramname, productid_paramname,
                submitteddate_paramname,approveddate_paramname, 
externalid_paramname, currency_paramname, digitsafterdecimal_paramname,
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/shareaccounts/api/SelfShareAccountsApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/shareaccounts/api/SelfShareAccountsApiResource.java
new file mode 100644
index 000000000..11adb1121
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/shareaccounts/api/SelfShareAccountsApiResource.java
@@ -0,0 +1,167 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fineract.portfolio.self.shareaccounts.api;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
+import 
org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
+import 
org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
+import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.apache.fineract.portfolio.accounts.api.AccountsApiResource;
+import 
org.apache.fineract.portfolio.accounts.constants.ShareAccountApiConstants;
+import org.apache.fineract.portfolio.accounts.data.AccountData;
+import 
org.apache.fineract.portfolio.accounts.exceptions.ShareAccountNotFoundException;
+import org.apache.fineract.portfolio.charge.data.ChargeData;
+import org.apache.fineract.portfolio.charge.service.ChargeReadPlatformService;
+import org.apache.fineract.portfolio.client.exception.ClientNotFoundException;
+import org.apache.fineract.portfolio.products.data.ProductData;
+import 
org.apache.fineract.portfolio.products.service.ProductReadPlatformService;
+import 
org.apache.fineract.portfolio.self.client.service.AppuserClientMapperReadService;
+import 
org.apache.fineract.portfolio.self.shareaccounts.data.SelfShareAccountsDataValidator;
+import 
org.apache.fineract.portfolio.self.shareaccounts.service.AppUserShareAccountsMapperReadPlatformService;
+import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountData;
+import 
org.apache.fineract.portfolio.shareaccounts.service.ShareAccountReadPlatformService;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+@Path("/self/shareaccounts")
+@Component
+@Scope("singleton")
+public class SelfShareAccountsApiResource {
+
+       private final PlatformSecurityContext context;
+       private final AccountsApiResource accountsApiResource;
+       private final ShareAccountReadPlatformService readPlatformService;
+       private final ApiRequestParameterHelper apiRequestParameterHelper;
+
+       private final DefaultToApiJsonSerializer<AccountData> 
toApiJsonSerializer;
+       private final AppuserClientMapperReadService 
appuserClientMapperReadService;
+       private final SelfShareAccountsDataValidator 
selfShareAccountsDataValidator;
+       private final ProductReadPlatformService productReadPlatformService;
+       private final ChargeReadPlatformService chargeReadPlatformService;
+       private final AppUserShareAccountsMapperReadPlatformService 
appUserShareAccountsMapperReadPlatformService;
+
+       @Autowired
+       public SelfShareAccountsApiResource(final PlatformSecurityContext 
context,
+                       final AccountsApiResource accountsApiResource, final 
ShareAccountReadPlatformService readPlatformService,
+                       final DefaultToApiJsonSerializer<AccountData> 
toApiJsonSerializer,
+                       final ApiRequestParameterHelper 
apiRequestParameterHelper,
+                       final AppuserClientMapperReadService 
appuserClientMapperReadService,
+                       final SelfShareAccountsDataValidator 
selfShareAccountsDataValidator,
+                       final ProductReadPlatformService 
productReadPlatformService,
+                       final ChargeReadPlatformService 
chargeReadPlatformService,
+                       final AppUserShareAccountsMapperReadPlatformService 
appUserShareAccountsMapperReadPlatformService) {
+               this.context = context;
+               this.accountsApiResource = accountsApiResource;
+               this.readPlatformService = readPlatformService;
+               this.toApiJsonSerializer = toApiJsonSerializer;
+               this.apiRequestParameterHelper = apiRequestParameterHelper;
+               this.selfShareAccountsDataValidator = 
selfShareAccountsDataValidator;
+               this.appuserClientMapperReadService = 
appuserClientMapperReadService;
+               this.productReadPlatformService = productReadPlatformService;
+               this.chargeReadPlatformService = chargeReadPlatformService;
+               this.appUserShareAccountsMapperReadPlatformService = 
appUserShareAccountsMapperReadPlatformService;
+
+       }
+
+       @GET
+       @Path("template")
+       @Consumes({ MediaType.APPLICATION_JSON })
+       @Produces({ MediaType.APPLICATION_JSON })
+       public String template(@QueryParam("clientId") final Long clientId, 
@QueryParam("productId") final Long productId,
+                       @Context final UriInfo uriInfo) {
+               
+               validateAppuserClientsMapping(clientId);
+
+               Collection<ProductData> productOptions = new 
ArrayList<ProductData>();
+               if (productId != null) {
+                       final boolean includeTemplate = true;
+                       
productOptions.add(productReadPlatformService.retrieveOne(productId, 
includeTemplate));
+               } else {
+                       productOptions = 
productReadPlatformService.retrieveAllForLookup();
+               }
+
+               String clientName = null;
+
+               final Collection<ChargeData> chargeOptions = 
this.chargeReadPlatformService.retrieveSharesApplicableCharges();
+               final ShareAccountData accountData = new 
ShareAccountData(clientId, clientName, productOptions, chargeOptions);
+
+               return this.toApiJsonSerializer.serialize(accountData);
+
+       }
+
+       @POST
+       @Consumes({ MediaType.APPLICATION_JSON })
+       @Produces({ MediaType.APPLICATION_JSON })
+       public String createAccount(final String apiRequestBodyAsJson) {
+               HashMap<String, Object> attr = 
this.selfShareAccountsDataValidator
+                               
.validateShareAccountApplication(apiRequestBodyAsJson);
+               final Long clientId = (Long) 
attr.get(ShareAccountApiConstants.clientid_paramname);
+               validateAppuserClientsMapping(clientId);
+               String accountType = ShareAccountApiConstants.shareEntityType;
+               return this.accountsApiResource.createAccount(accountType, 
apiRequestBodyAsJson);
+       }
+
+       @GET
+       @Path("{accountId}")
+       @Consumes({ MediaType.APPLICATION_JSON })
+       @Produces({ MediaType.APPLICATION_JSON })
+       public String retrieveShareAccount(@PathParam("accountId") final Long 
accountId, @Context final UriInfo uriInfo) {
+               validateAppuserShareAccountMapping(accountId);
+               final boolean includeTemplate = false;
+               AccountData accountData = 
this.readPlatformService.retrieveOne(accountId, includeTemplate);
+               final ApiRequestJsonSerializationSettings settings = 
this.apiRequestParameterHelper
+                               .process(uriInfo.getQueryParameters());
+               return this.toApiJsonSerializer.serialize(settings, 
accountData, readPlatformService.getResponseDataParams());
+       }
+
+       private void validateAppuserShareAccountMapping(final Long accountId) {
+               AppUser user = this.context.authenticatedUser();
+               final boolean isMapped = 
this.appUserShareAccountsMapperReadPlatformService
+                               .isShareAccountsMappedToUser(accountId, 
user.getId());
+               if (!isMapped) {
+                       throw new ShareAccountNotFoundException(accountId);
+               }
+       }
+
+       private void validateAppuserClientsMapping(final Long clientId) {
+               AppUser user = this.context.authenticatedUser();
+               final boolean mappedClientId = 
this.appuserClientMapperReadService.isClientMappedToUser(clientId, 
user.getId());
+               if (!mappedClientId) {
+                       throw new ClientNotFoundException(clientId);
+               }
+       }
+}
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/shareaccounts/data/SelfShareAccountsDataValidator.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/shareaccounts/data/SelfShareAccountsDataValidator.java
new file mode 100644
index 000000000..c762ecb75
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/shareaccounts/data/SelfShareAccountsDataValidator.java
@@ -0,0 +1,75 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fineract.portfolio.self.shareaccounts.data;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.fineract.infrastructure.core.data.ApiParameterError;
+import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
+import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
+import 
org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
+import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
+import 
org.apache.fineract.portfolio.accounts.constants.ShareAccountApiConstants;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.google.gson.JsonElement;
+
+@Component
+public class SelfShareAccountsDataValidator {
+
+       private final FromJsonHelper fromApiJsonHelper;
+
+       @Autowired
+       public SelfShareAccountsDataValidator(final FromJsonHelper 
fromApiJsonHelper) {
+               this.fromApiJsonHelper = fromApiJsonHelper;
+       }
+
+       public HashMap<String, Object> validateShareAccountApplication(final 
String json) {
+               if (StringUtils.isBlank(json)) {
+                       throw new InvalidJsonException();
+               }
+
+               final List<ApiParameterError> dataValidationErrors = new 
ArrayList<>();
+               final DataValidatorBuilder baseDataValidator = new 
DataValidatorBuilder(dataValidationErrors)
+                               
.resource(ShareAccountApiConstants.shareEntityType);
+
+               final JsonElement element = this.fromApiJsonHelper.parse(json);
+
+               final String clientId = 
this.fromApiJsonHelper.extractStringNamed(ShareAccountApiConstants.clientid_paramname,
+                               element);
+               
baseDataValidator.reset().parameter(ShareAccountApiConstants.clientid_paramname).value(clientId).notNull()
+                               .longGreaterThanZero();
+
+               if (!dataValidationErrors.isEmpty()) {
+                       throw new 
PlatformApiDataValidationException(dataValidationErrors);
+               }
+
+               HashMap<String, Object> retAttr = new HashMap<>();
+               retAttr.put(ShareAccountApiConstants.clientid_paramname, 
Long.parseLong(clientId));
+
+               return retAttr;
+
+       }
+
+}
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/shareaccounts/service/AppUserShareAccountsMapperReadPlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/shareaccounts/service/AppUserShareAccountsMapperReadPlatformService.java
new file mode 100644
index 000000000..3e7edbdfb
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/shareaccounts/service/AppUserShareAccountsMapperReadPlatformService.java
@@ -0,0 +1,26 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fineract.portfolio.self.shareaccounts.service;
+
+public interface AppUserShareAccountsMapperReadPlatformService {
+
+       public Boolean isShareAccountsMappedToUser(Long accountId, Long 
appUserId);
+
+}
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/shareaccounts/service/AppUserShareAccountsMapperReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/shareaccounts/service/AppUserShareAccountsMapperReadPlatformServiceImpl.java
new file mode 100644
index 000000000..eb464f1a2
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/shareaccounts/service/AppUserShareAccountsMapperReadPlatformServiceImpl.java
@@ -0,0 +1,51 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fineract.portfolio.self.shareaccounts.service;
+
+import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Service;
+
+@Service
+public class AppUserShareAccountsMapperReadPlatformServiceImpl
+               implements AppUserShareAccountsMapperReadPlatformService {
+
+
+       private final JdbcTemplate jdbcTemplate;
+
+       @Autowired
+       public AppUserShareAccountsMapperReadPlatformServiceImpl(
+                       final RoutingDataSource dataSource) {
+               this.jdbcTemplate = new JdbcTemplate(dataSource);
+       }
+       
+       @Override
+       public Boolean isShareAccountsMappedToUser(Long accountId, Long 
appUserId) {
+               return this.jdbcTemplate
+                               .queryForObject(
+                                               "select case when (count(*) > 
0) then true else false end "
+                                                               + " from 
m_selfservice_user_client_mapping as m "
+                                                               + " left join 
m_share_account as shares on shares.client_id = m.client_id  "
+                                                               + " where 
shares.id = ? and m.appuser_id = ? ",
+                                               new Object[] { accountId, 
appUserId }, Boolean.class);
+       }
+
+}


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to