diff --git a/APIFolder/api.htm b/APIFolder/api.htm index 16a11f812..246512ac1 100644 --- a/APIFolder/api.htm +++ b/APIFolder/api.htm @@ -30,12 +30,12 @@
  • Retrieve Client Details Template
  • Retrieve a Client
  • Create a Client
  • +
  • Update a Client
  • Retrieve a Client's Loan Account Summary
  • Retrieve a Client's Notes
  • Add a Client Note
  • Retrieve a Client Note
  • Update a Client Note
  • - No update a client? @@ -47,7 +47,6 @@
  • Retrieve Loan Details Template
  • Retrieve a Loan
  • Create a New Loan
  • -
  • Submit a Loan Application
  • Approve a Loan
  • Disburse a Loan
  • Reject a Loan
  • @@ -188,67 +187,67 @@

    API Endpoint

    - https://thedomainname/ + https://thedomainname/api
    Summary of Resource URL Patterns
    - - - - - - + + + + + + - - - - - - - + + + + + + + - - - + + + - - - + + + - + - - + + - - + + - + - - - + + + - - - + + + - - - + + + - +
    ResourcesVerbs
    /api/v1/clientsGET, POST
    /api/v1/clients/templateGET
    /api/v1/clients/{clientId}GET
    /api/v1/clients/{clientId}/loansGET
    /api/v1/clients/{clientId}/notesGET, POST
    /api/v1/clients/{clientId}/notes/{noteId}GET, PUT
    /v1/clientsGET, POST
    /v1/clients/templateGET
    /v1/clients/{clientId}GET
    /v1/clients/{clientId}/loansGET
    /v1/clients/{clientId}/notesGET, POST
    /v1/clients/{clientId}/notes/{noteId}GET, PUT
    /api/v1/loansPOST
    /api/v1/loans/templateGET
    /api/v1/loans/{loanId}GET, POST, DELETE
    /api/v1/loans/{loanId}/undoPOST
    /api/v1/loans/{loanId}/transactions/templateGET
    /api/v1/loans/{loanId}/transactionsPOST
    /api/v1/loans/{loanId}/transactions/{repaymentId}GET, PUT
    /v1/loansPOST
    /v1/loans/templateGET
    /v1/loans/{loanId}GET, POST, DELETE
    /v1/loans/{loanId}/undoPOST
    /v1/loans/{loanId}/transactions/templateGET
    /v1/loans/{loanId}/transactionsPOST
    /v1/loans/{loanId}/transactions/{repaymentId}GET, PUT
    /api/v1/officesGET, POST
    /api/v1/offices/templateGET
    /api/v1/offices/{officeId}GET, PUT
    /v1/officesGET, POST
    /v1/offices/templateGET
    /v1/offices/{officeId}GET, PUT
    /api/v1/loanproductsGET, POST
    /api/v1/loanproducts/templateGET
    /api/v1/loanproducts/{productId}GET, PUT
    /v1/loanproductsGET, POST
    /v1/loanproducts/templateGET
    /v1/loanproducts/{productId}GET, PUT
    /api/v1/configurations/currencyGET, PUT
    /v1/configurations/currencyGET, PUT
    /api/v1/additionalfieldsGET
    /api/v1/additionalfields/{Type}/{Set}/{id}GET, POST
    /v1/additionalfieldsGET
    /v1/additionalfields/{Type}/{Set}/{id}GET, POST
    /api/v1/reportsGET
    /api/v1/reports/{reportName}GET
    /v1/reportsGET
    /v1/reports/{reportName}GET
    /api/v1/authenticationPOST
    /v1/authenticationPOST
    /api/v1/useraccounts/currentGET, PUT
    /api/v1/useraccounts/current/passwordPUT
    /api/v1/useraccounts/current/password/templateGET
    /v1/useraccounts/currentGET, PUT
    /v1/useraccounts/current/passwordPUT
    /v1/useraccounts/current/password/templateGET
    /api/v1/usersGET, POST
    /api/v1/users/templateGET
    /api/v1/users/{userId}GET, PUT, DELETE
    /v1/usersGET, POST
    /v1/users/templateGET
    /v1/users/{userId}GET, PUT, DELETE
    /api/v1/rolesGET, POST
    /api/v1/roles/templateGET
    /api/v1/roles/{roleId}GET, PUT
    /v1/rolesGET, POST
    /v1/roles/templateGET
    /v1/roles/{roleId}GET, PUT
    /api/v1/permissionsGET
    /v1/permissionsGET
    @@ -442,8 +441,7 @@

    Clients

    -

    Clients words. -

    +

    Clients ...

    @@ -475,13 +473,46 @@

    List Clients

    Example Request: - http://localhost:8080/mifosng-provider/api/v1/clients + https://localhost:8443/mifosng-provider/api/v1/clients

    GET https://thedomainname/api/v1/clients - to be done - +{ + "clients": [ + { + "organisationId": 1, + "organisationName": "Demo MFI", + "officeId": 2, + "officeName": "sub branch 1", + "id": 14, + "firstname": "Patrick", + "lastname": "Asare-Frimpong", + "displayName": "Patrick Asare-Frimpong", + "externalId": null, + "joinedDate": "2012-04-18", + "allowedOffices": [], + "maxJoinedOnOffsetFromToday": -34 + }, + ... + ... + { + "organisationId": 1, + "organisationName": "Demo MFI", + "officeId": 1, + "officeName": "Demo MFI Head Office", + "id": 17, + "firstname": "Fred", + "lastname": "Ziffle", + "displayName": "Fred Ziffle", + "externalId": null, + "joinedDate": "2012-04-21", + "allowedOffices": [], + "maxJoinedOnOffsetFromToday": -31 + } + ] +} +
    @@ -490,16 +521,49 @@

    Retrieve Client Details Template

    -

    Returns a template that contains the client fields and allowed value lists. This helps build a maintenance User Interface. -

    +

    Returns a template that contains the client fields and allowed value lists. This helps build a maintenance User Interface.

    Example Request: - http://localhost:8080/mifosng-provider/api/v1/clients/template + https://localhost:8443/mifosng-provider/api/v1/clients/template

    GET https://thedomainname/api/v1/clients/template - to be done - +{ + "organisationId": 1, + "organisationName": null, + "officeId": 1, + "officeName": null, + "id": -1, + "firstname": "", + "lastname": "", + "displayName": "", + "externalId": null, + "joinedDate": "2012-05-22", + "allowedOffices": [ + { + "id": 1, + "name": "Demo MFI Head Office", + "externalId": "1", + "openingDate": "2009-01-01", + "hierarchy": ".", + "parentName": null, + "parentId": 0, + "allowedParents": [] + }, + { + "id": 2, + "name": "sub branch 1", + "externalId": "2", + "openingDate": "2012-01-02", + "hierarchy": ".2.", + "parentName": "Demo MFI Head Office", + "parentId": 1, + "allowedParents": [] + } + ], + "maxJoinedOnOffsetFromToday": 0 +} +
    @@ -508,120 +572,242 @@

    Retrieve a Client

    -

    Returns client fields. It also returns allowed value lists which help build a maintenance User Interface. +

    Returns client fields. It also returns allowed value lists which help build a maintenance User Interface.

    Example Request: - http://localhost:8080/mifosng-provider/api/v1/clients/1 + https://localhost:8443/mifosng-provider/api/v1/clients/1

    GET https://thedomainname/api/v1/clients/{clientId} - - +{ + "organisationId": 1, + "organisationName": "Demo MFI", + "officeId": 1, + "officeName": "Demo MFI Head Office", + "id": 1, + "firstname": "Patrick", + "lastname": "O'Meara", + "displayName": "Patrick O'Meara", + "externalId": null, + "joinedDate": "2009-01-04", + "allowedOffices": [], + "maxJoinedOnOffsetFromToday": -1234 +} +
    - -   -
    -
    -

    Create a Client

    -
    -
    - POST https://thedomainname/api/v1/clients - http://localhost:8080/mifosng-provider/api/v1/clients - - - Content-Type: application/json - Request Body: - new json here - - { "entityId": 2 } - -
    -
    -   -
    -
    -

    Retrieve a Client's Loan Account Summary

    -

    Example Request: - http://localhost:8080/mifosng-provider/api/v1/clients/1/loans -

    -
    -
    - GET https://thedomainname/api/v1/clients/{clientId}/loans - - -
    -
    -   -
    -
    -

    Retrieve a Client's Notes

    -

    Example Request: - http://localhost:8080/mifosng-provider/api/v1/clients/1/notes -

    -
    -
    - GET https://thedomainname/api/v1/clients/{clientId}/notes - - -
    -
    -   -
    -
    -

    Add a Client Note

    -
    -
    - POST https://thedomainname/api/v1/clients/{clientId}/notes - http://localhost:8080/mifosng-provider/api/v1/clients/1/notes - - - Content-Type: application/json - Request Body: - new json here - - { "entityId": 2 } - -
    -
    +  +
    +
    +

    Create a Client

    +
    +
    + POST https://thedomainname/api/v1/clients +https://localhost:8443/mifosng-provider/api/v1/clients +Content-Type: application/json +Request Body: +{ + "officeId": 1, + "firstname": "Firstname", + "lastname": "Surname", + "externalId": null, + "dateFormat": "dd MMMM yyyy", + "joiningDateFormatted": "04 March 2009" +} + +{ "entityId": 2} +
    +
    -   -
    -
    -

    Retrieve a Client Note

    -

    Example Request: - http://localhost:8080/mifosng-provider/api/v1/clients/1/notes/1 -

    -
    -
    - GET https://thedomainname/api/v1/clients/{clientId}/notes/{noteId} - - -
    -
    -   -
    -
    -

    Update a Client Note

    -
    -
    - PUT https://thedomainname/api/v1/clients/{clientId}/notes/{noteId} - http://localhost:8080/mifosng-provider/api/v1/clients/1/notes/1 - - - Content-Type: application/json - Request Body: - new json here - - { "entityId": 2 } - -
    -
    - +  +
    +
    +

    Update a Client

    +
    +
    + PUT https://thedomainname/api/v1/clients/1 +PUT https://localhost:8443/mifosng-provider/api/v1/clients/1 +Content-Type: application/json +Request Body: +{ + "officeId": 1, + "firstname": "Firstname", + "lastname": "Surname", + "externalId": null, + "dateFormat": "dd MMMM yyyy", + "joiningDateFormatted": "04 March 2009" +} + +{ "entityId": 2} +
    +
    + +  +
    +
    +

    Retrieve a Client's Loan Account Summary

    +

    Example Request: + https://localhost:8443/mifosng-provider/api/v1/clients/1/loans +

    +
    +
    + GET https://thedomainname/api/v1/clients/{clientId}/loans +{ + "pendingApprovalLoans": [], + "awaitingDisbursalLoans": [ + { + "id": 17, + "externalId": null, + "loanProductId": 1, + "loanProductName": "Agricultural Loan", + "loanStatusId": 200, + "pendingApproval": false, + "waitingForDisbursal": true, + "open": false, + "closed": false, + "lifeCycleStatusText": "Approved", + "lifeCycleStatusDate": null + } + ], + "openLoans": [], + "closedLoans": [ + { + "id": 1, + "externalId": null, + "loanProductId": 1, + "loanProductName": "Agricultural Loan", + "loanStatusId": 600, + "pendingApproval": false, + "waitingForDisbursal": false, + "open": false, + "closed": true, + "lifeCycleStatusText": "Closed", + "lifeCycleStatusDate": null + } + ], + "anyLoanCount": 2, + "pendingApprovalLoanCount": 0, + "awaitingDisbursalLoanCount": 1, + "activeLoanCount": 0, + "closedLoanCount": 1 +} + +
    +
    +  +
    +
    +

    Retrieve a Client's Notes

    +

    Example Request: + https://localhost:8443/mifosng-provider/api/v1/clients/2/notes +

    +
    +
    + GET https://thedomainname/api/v1/clients/{clientId}/notes +{ + "notes": [ + { + "id": 20, + "clientId": 2, + "loanId": 0, + "loanTransactionId": 0, + "noteTypeId": 100, + "note": "This is an extra note!", + "createdById": 2, + "createdByUsername": "super1", + "createdOn": "2012-04-22T13:50:25.000+01:00", + "updatedById": 2, + "updatedByUsername": "super1", + "updatedOn": "2012-04-22T13:50:25.000+01:00" + }, + { + "id": 16, + "clientId": 2, + "loanId": 0, + "loanTransactionId": 0, + "noteTypeId": 100, + "note": "loan only 1/2 amount expected\r\nyes", + "createdById": 2, + "createdByUsername": "super1", + "createdOn": "2012-04-18T15:15:04.000+01:00", + "updatedById": 2, + "updatedByUsername": "super1", + "updatedOn": "2012-04-23T09:38:13.000+01:00" + } + ] +} + +
    +
    + +  +
    +
    +

    Add a Client Note

    +
    +
    + POST https://thedomainname/api/v1/clients/{clientId}/notes + POST https://localhost:8443/mifosng-provider/api/v1/clients/1/notes +Content-Type: application/json +Request Body: +{ +"note": "a note about the client" +} + +{ "entityId": 40} +
    +
    + +  +
    +
    +

    Retrieve a Client Note

    +

    Example Request: + https://localhost:8443/mifosng-provider/api/v1/clients/1/notes/40 +

    +
    +
    + GET https://thedomainname/api/v1/clients/{clientId}/notes/{noteId} + { + "id": 40, + "clientId": 2, + "loanId": 0, + "loanTransactionId": 0, + "noteTypeId": 100, + "note": "a note about the client", + "createdById": 1, + "createdByUsername": "mifos", + "createdOn": "2012-05-22T21:40:05.000+01:00", + "updatedById": 1, + "updatedByUsername": "mifos", + "updatedOn": "2012-05-22T21:40:05.000+01:00" +} + +
    +
    + +  +
    +
    +

    Update a Client Note

    +
    +
    + PUT https://thedomainname/api/v1/clients/{clientId}/notes/{noteId} +PUT https://localhost:8443/mifosng-provider/api/v1/clients/1/notes/40 +Content-Type: application/json +Request Body: +{ +"note": "an updated note about the client" +} + + {"entityId": 40} +
    +
    +   @@ -671,7 +857,7 @@
    The 'id' of the Loan Product

    Example Request: - http://localhost:8080/mifosng-provider/api/v1/loans/template?clientId=1&productId=1 + https://localhost:8443/mifosng-provider/api/v1/loans/template?clientId=1&productId=1

    @@ -687,7 +873,7 @@

    Returns loan fields.

    Example Request: - http://localhost:8080/mifosng-provider/api/v1/loans/1 + https://localhost:8443/mifosng-provider/api/v1/loans/1

    @@ -696,33 +882,32 @@
    -   -   -
    -
    -

    Create a New Loan/Submit a Loan Application

    -
    Arguments
    -
    -
    command
    -
    String Optional, case-insensitive
    -
    The default action is to Submit a New Loan Application. If the value is 'calculateLoanSchedule' then a new loan entry is created without entering the loan life cycle.
    -
    -
    -
    - POST https://thedomainname/api/v1/loans - http://localhost:8080/mifosng-provider/api/v1/loans - - - Content-Type: application/json - Request Body: - new json here - - { - "entityId": 2 -} - -
    -
    + +  +
    +
    +

    Create a New Loan/Submit a Loan Application

    +
    Arguments
    +
    +
    command
    +
    String Optional, case-insensitive
    +
    The default action is to Submit a New Loan Application. If the value is 'calculateLoanSchedule' then a new loan entry is created without entering the loan life cycle.
    +
    +
    +
    + POST https://thedomainname/api/v1/loans + https://localhost:8443/mifosng-provider/api/v1/loans + + + Content-Type: application/json + Request Body: + new json here + + {"entityId": 2} + +
    +
    +       @@ -742,7 +927,7 @@
    POST https://thedomainname/api/v1/loans/{loanId} - http://localhost:8080/mifosng-provider/api/v1/loans/1?command=approve + https://localhost:8443/mifosng-provider/api/v1/loans/1?command=approve Content-Type: application/json @@ -762,7 +947,7 @@
    DELETE https://thedomainname/api/v1/loans/{loanId} - http://localhost:8080/mifosng-provider/api/v1/loans/1 + https://localhost:8443/mifosng-provider/api/v1/loans/1 Content-Type: application/json @@ -789,7 +974,7 @@
    POST https://thedomainname/api/v1/loans/{loanId}/undo - http://localhost:8080/mifosng-provider/api/v1/loans/1/undo + https://localhost:8443/mifosng-provider/api/v1/loans/1/undo Content-Type: application/json @@ -818,7 +1003,7 @@
    The default action is to return details for Repayment of a loan. If the value is 'waiver' then details relevant to Waiving a loan amount are returned.

    Example Request: - http://localhost:8080/mifosng-provider/api/v1/loans/1/transactions/template?type=waiver" + https://localhost:8443/mifosng-provider/api/v1/loans/1/transactions/template?type=waiver"

    @@ -840,7 +1025,7 @@
    POST https://thedomainname/api/v1/loans/{loanId}/transactions - http://localhost:8080/mifosng-provider/api/v1/loans/1/transactions + https://localhost:8443/mifosng-provider/api/v1/loans/1/transactions Content-Type: application/json @@ -859,7 +1044,7 @@
    @@ -876,7 +1061,7 @@
    POST https://thedomainname/api/v1/loans/{loanId}/transactions/{repaymentId} - http://localhost:8080/mifosng-provider/api/v1/loans/1/transactions/1 + https://localhost:8443/mifosng-provider/api/v1/loans/1/transactions/1 Content-Type: application/json @@ -1679,7 +1864,7 @@ Request Body:
    The Additional Fields Type (Mifos X database table) to restrict the output to

    Example Request: - http://localhost:8080/mifosng-provider/api/v1/additionalfields?type=portfolio_client + https://localhost:8443/mifosng-provider/api/v1/additionalfields?type=portfolio_client

    @@ -1711,7 +1896,7 @@ Request Body: Returns the Set of Additional Fields data for the ID provided. The ID is the id field of the Type table e.g. portfolio_client might have an id value of 4. The output is a JSON formatted "Generic Resultset". The Generic Resultset contains Column Heading as well as Data information. The Column Heading information may include allowed values (columnValues array).

    Example Request: - http://localhost:8080/mifosng-provider/api/v1/additionalfields/portfolio_client/Additional Information/2 + https://localhost:8443/mifosng-provider/api/v1/additionalfields/portfolio_client/Additional Information/2

    @@ -1843,7 +2028,7 @@ Request Body:
    POST https://thedomainname/api/v1/additionalfields/{type}/{set}/{id} - http://localhost:8080/mifosng-provider/api/v1/additionalfields/portfolio_client/Additional Information/2 + https://localhost:8443/mifosng-provider/api/v1/additionalfields/portfolio_client/Additional Information/2 Content-Type: application/json @@ -1908,7 +2093,7 @@ Request Body:
    Output will be delivered as a CSV file instead of JSON.

    Example Request: - http://localhost:8080/mifosng-provider/api/v1/reports + https://localhost:8443/mifosng-provider/api/v1/reports

    @@ -2004,7 +2189,7 @@ Request Body:
    Output will be delivered as a CSV file instead of JSON. Doesn't apply to Pentaho reports.

    Example Request: - http://localhost:8080/mifosng-provider/api/v1/reports/Client%20Listing?R_officeId=1 + https://localhost:8443/mifosng-provider/api/v1/reports/Client%20Listing?R_officeId=1

    @@ -2834,7 +3019,7 @@ Request body:
    - +  
    @@ -2860,7 +3045,195 @@ Request body:
    - + +   +
    +
    +

    Permissions

    +

    An API capability to support management of application permissions for user administration.

    +
    +
    + +   +
    +
    +

    Retrieve list of permissions

    +

    Returns all permissions.

    +

    Example Request: + https://localhost:8443/mifosng-provider/api/v1/permissions +

    +
    +
    + GET https://thedomainname/api/v1/permissions +GET https://localhost:8443/mifosng-provider/api/v1/permissions + +{ + "permissions": [ + { + "id": 1, + "orgId": 1, + "name": "User administration ALL", + "description": "An application user will have permission to execute all tasks related to user administration.", + "code": "USER_ADMINISTRATION_SUPER_USER_ROLE", + "groupType": 1 + }, + { + "id": 2, + "orgId": 1, + "name": "Organisation adminsitration ALL", + "description": "An application user will have permission to execute all tasks related to organisation administration.", + "code": "ORGANISATION_ADMINISTRATION_SUPER_USER_ROLE", + "groupType": 2 + }, + { + "id": 3, + "orgId": 1, + "name": "Portfolio management ALL", + "description": "An application user will have permission to execute all tasks related to portfolio management.", + "code": "PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE", + "groupType": 3 + }, + { + "id": 4, + "orgId": 1, + "name": "Reporting ALL", + "description": "An application user will have permission to execute and view all reports.", + "code": "REPORTING_SUPER_USER_ROLE", + "groupType": 4 + }, + { + "id": 5, + "orgId": 1, + "name": "Can submit new loan application", + "description": "Allows an application user to sumit new loan application.", + "code": "CAN_SUBMIT_NEW_LOAN_APPLICATION_ROLE", + "groupType": 3 + }, + { + "id": 6, + "orgId": 1, + "name": "Can submit historic loan application", + "description": "Allows an application user to sumit new loan application where the submitted on date is in the past.", + "code": "CAN_SUBMIT_HISTORIC_LOAN_APPLICATION_ROLE", + "groupType": 3 + }, + { + "id": 7, + "orgId": 1, + "name": "Can approve loan application", + "description": "Allows an application user to approve a loan application.", + "code": "CAN_APPROVE_LOAN_ROLE", + "groupType": 3 + }, + { + "id": 8, + "orgId": 1, + "name": "Can approve loan application in the past", + "description": "Allows an application user to approve a loan application where the approval date is in the past.", + "code": "CAN_APPROVE_LOAN_IN_THE_PAST_ROLE", + "groupType": 3 + }, + { + "id": 9, + "orgId": 1, + "name": "Can reject loan application", + "description": "Allows an application user to reject a loan application.", + "code": "CAN_REJECT_LOAN_ROLE", + "groupType": 3 + }, + { + "id": 10, + "orgId": 1, + "name": "Can reject loan application in the past", + "description": "Allows an application user to reject a loan application where the rejected date is in the past.", + "code": "CAN_REJECT_LOAN_IN_THE_PAST_ROLE", + "groupType": 3 + }, + { + "id": 11, + "orgId": 1, + "name": "Can withdraw loan application", + "description": "Allows an application user to mark loan application as withdrawn by client.", + "code": "CAN_WITHDRAW_LOAN_ROLE", + "groupType": 3 + }, + { + "id": 12, + "orgId": 1, + "name": "Can withdraw loan application in the past", + "description": "Allows an application user to mark loan application as withdrawn by client where the withdran on date is in the past.", + "code": "CAN_WITHDRAW_LOAN_IN_THE_PAST_ROLE", + "groupType": 3 + }, + { + "id": 13, + "orgId": 1, + "name": "Can delete submitted loan application", + "description": "Allows an application user to complete delete the loan application if it is submitted but not approved.", + "code": "CAN_DELETE_LOAN_THAT_IS_SUBMITTED_AND_NOT_APPROVED", + "groupType": 3 + }, + { + "id": 14, + "orgId": 1, + "name": "Can undo loan approval", + "description": "Allows an application user to undo a loan approval.", + "code": "CAN_UNDO_LOAN_APPROVAL_ROLE", + "groupType": 3 + }, + { + "id": 15, + "orgId": 1, + "name": "Can disburse loan", + "description": "Allows an application user to disburse a loan application.", + "code": "CAN_DISBURSE_LOAN_ROLE", + "groupType": 3 + }, + { + "id": 16, + "orgId": 1, + "name": "Can disburse loan in the past", + "description": "Allows an application user to disburse a loan where the disbursement date is in the past.", + "code": "CAN_DISBURSE_LOAN_IN_THE_PAST_ROLE", + "groupType": 3 + }, + { + "id": 17, + "orgId": 1, + "name": "Can undo loan disbursal", + "description": "Allows an application user to undo a loan disbursal if not payments already made.", + "code": "CAN_UNDO_LOAN_DISBURSAL_ROLE", + "groupType": 3 + }, + { + "id": 18, + "orgId": 1, + "name": "Can enter a repayment against a loan", + "description": "Allows an application user to enter a repayment on the loan.", + "code": "CAN_MAKE_LOAN_REPAYMENT_LOAN_ROLE", + "groupType": 3 + }, + { + "id": 19, + "orgId": 1, + "name": "Can enter a repayment against a loan in the past", + "description": "Allows an application user to enter a repayment on the loan where the repayment date is in the past.", + "code": "CAN_MAKE_LOAN_REPAYMENT_IN_THE_PAST_ROLE", + "groupType": 3 + }, + { + "id": 20, + "orgId": 1, + "name": "Can add a new client.", + "description": "Allows an application user to add a new client.", + "code": "CAN_ENROLL_NEW_CLIENT_ROLE", + "groupType": 3 + } + ] +} + +
    +
    diff --git a/mifosng-data/src/main/java/org/mifosng/data/command/EnrollClientCommand.java b/mifosng-data/src/main/java/org/mifosng/data/command/ClientCommand.java similarity index 85% rename from mifosng-data/src/main/java/org/mifosng/data/command/EnrollClientCommand.java rename to mifosng-data/src/main/java/org/mifosng/data/command/ClientCommand.java index 5b67334cd..2e563a4ca 100644 --- a/mifosng-data/src/main/java/org/mifosng/data/command/EnrollClientCommand.java +++ b/mifosng-data/src/main/java/org/mifosng/data/command/ClientCommand.java @@ -5,8 +5,9 @@ import javax.xml.bind.annotation.XmlRootElement; import org.joda.time.LocalDate; @XmlRootElement -public class EnrollClientCommand { +public class ClientCommand { + private Long id; private String firstname; private String lastname; private String fullname; @@ -17,11 +18,11 @@ public class EnrollClientCommand { private String joiningDateFormatted; private LocalDate joiningDate; - protected EnrollClientCommand() { + protected ClientCommand() { // } - public EnrollClientCommand(final String firstname, final String lastname, String fullname, final Long officeId, final LocalDate joiningDate) { + public ClientCommand(final String firstname, final String lastname, String fullname, final Long officeId, final LocalDate joiningDate) { this.firstname = firstname; this.lastname = lastname; this.fullname = fullname; @@ -92,4 +93,12 @@ public class EnrollClientCommand { public void setJoiningDateFormatted(String joiningDateFormatted) { this.joiningDateFormatted = joiningDateFormatted; } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } } \ No newline at end of file diff --git a/mifosng-data/src/main/java/org/mifosng/data/command/ImportClientCommand.java b/mifosng-data/src/main/java/org/mifosng/data/command/ImportClientCommand.java index 44923d05c..5f57f7145 100644 --- a/mifosng-data/src/main/java/org/mifosng/data/command/ImportClientCommand.java +++ b/mifosng-data/src/main/java/org/mifosng/data/command/ImportClientCommand.java @@ -8,17 +8,17 @@ import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class ImportClientCommand { - private List clients = new ArrayList(); + private List clients = new ArrayList(); public ImportClientCommand() { // } - public List getClients() { + public List getClients() { return clients; } - public void setClients(List clients) { + public void setClients(List clients) { this.clients = clients; } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/ImportPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/ImportPlatformServiceImpl.java index 9acb17891..d26160d4f 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/ImportPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/ImportPlatformServiceImpl.java @@ -22,7 +22,7 @@ import org.mifosng.data.LoanSchedule; import org.mifosng.data.MoneyData; import org.mifosng.data.ScheduledLoanInstallment; import org.mifosng.data.command.CalculateLoanScheduleCommand; -import org.mifosng.data.command.EnrollClientCommand; +import org.mifosng.data.command.ClientCommand; import org.mifosng.data.command.ImportClientCommand; import org.mifosng.data.command.ImportLoanCommand; import org.mifosng.data.command.ImportLoanRepaymentsCommand; @@ -115,7 +115,7 @@ public class ImportPlatformServiceImpl implements ImportPlatformService { List newClientCollection = new ArrayList(); - for (EnrollClientCommand client : command.getClients()) { + for (ClientCommand client : command.getClients()) { Office clientOffice = findById(allOffices, client.getOfficeId()); Client newClient = Client.newClient(currentUser.getOrganisation(), clientOffice, client.getFirstname(), client.getLastname(), client.getJoiningDate(), client.getExternalId()); @@ -544,7 +544,7 @@ public class ImportPlatformServiceImpl implements ImportPlatformService { // success = false; // } - List parsedClients = new ArrayList(); + List parsedClients = new ArrayList(); while (clients.readRecord()) { String externalId = clients.get("ExternalId"); String firstname = clients.get("FirstName"); @@ -555,7 +555,7 @@ public class ImportPlatformServiceImpl implements ImportPlatformService { LocalDate joiningDate = new LocalDate(isoParser.parseDateTime(joined)); - EnrollClientCommand parsedClient = new EnrollClientCommand(firstname, lastname, "", matchingOffice.getId(), joiningDate); + ClientCommand parsedClient = new ClientCommand(firstname, lastname, "", matchingOffice.getId(), joiningDate); parsedClient.setExternalId(externalId); parsedClients.add(parsedClient); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/ClientApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/ClientApiResource.java index 40ec16e1a..2981c1386 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/ClientApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/ClientApiResource.java @@ -19,7 +19,7 @@ import org.mifosng.data.ClientLoanAccountSummaryCollectionData; import org.mifosng.data.EntityIdentifier; import org.mifosng.data.NoteData; import org.mifosng.data.NoteDataList; -import org.mifosng.data.command.EnrollClientCommand; +import org.mifosng.data.command.ClientCommand; import org.mifosng.data.command.NoteCommand; import org.mifosng.platform.api.infrastructure.ApiDataConversionService; import org.mifosng.platform.client.service.ClientReadPlatformService; @@ -43,8 +43,8 @@ public class ClientApiResource { private ApiDataConversionService apiDataConversionService; @GET - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) - @Produces({ MediaType.APPLICATION_JSON}) + @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_JSON}) public Response retrieveAllIndividualClients() { Collection clients = this.clientReadPlatformService.retrieveAllIndividualClients(); @@ -54,8 +54,8 @@ public class ClientApiResource { @GET @Path("{clientId}") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) - @Produces({ MediaType.APPLICATION_JSON}) + @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_JSON}) public Response retrieveClientData(@PathParam("clientId") final Long clientId) { ClientData clientData = this.clientReadPlatformService.retrieveIndividualClient(clientId); @@ -65,8 +65,8 @@ public class ClientApiResource { @GET @Path("template") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) - @Produces({ MediaType.APPLICATION_JSON}) + @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_JSON}) public Response newClientDetails() { ClientData clientData = this.clientReadPlatformService.retrieveNewClientDetails(); @@ -75,9 +75,9 @@ public class ClientApiResource { } @POST - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response enrollClient(final EnrollClientCommand command) { + @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_JSON }) + public Response enrollClient(final ClientCommand command) { LocalDate joiningDate = apiDataConversionService.convertFrom(command.getJoiningDateFormatted(), "joiningDateFormatted", command.getDateFormat()); command.setJoiningDate(joiningDate); @@ -87,11 +87,25 @@ public class ClientApiResource { return Response.ok().entity(new EntityIdentifier(clientId)).build(); } + @PUT + @Path("{clientId}") + @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_JSON }) + public Response updateClient(@PathParam("clientId") final Long clientId, final ClientCommand command) { + + LocalDate joiningDate = apiDataConversionService.convertFrom(command.getJoiningDateFormatted(), "joiningDateFormatted", command.getDateFormat()); + command.setJoiningDate(joiningDate); + command.setId(clientId); + + EntityIdentifier identifier = this.clientWritePlatformService.updateClientDetails(command); + + return Response.ok().entity(identifier).build(); + } @GET @Path("{clientId}/loans") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_JSON }) public Response retrieveClientAccount(@PathParam("clientId") final Long clientId) { ClientLoanAccountSummaryCollectionData clientAccount = this.clientReadPlatformService.retrieveClientAccountDetails(clientId); @@ -101,8 +115,8 @@ public class ClientApiResource { @GET @Path("{clientId}/notes") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) - @Produces({ MediaType.APPLICATION_JSON}) + @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_JSON}) public Response retrieveAllClientNotes(@PathParam("clientId") final Long clientId) { Collection notes = this.clientReadPlatformService.retrieveAllClientNotes(clientId); @@ -112,8 +126,8 @@ public class ClientApiResource { @POST @Path("{clientId}/notes") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) - @Produces({ MediaType.APPLICATION_JSON}) + @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_JSON}) public Response addNewClientNote(@PathParam("clientId") final Long clientId, final NoteCommand command) { command.setClientId(clientId); @@ -125,8 +139,8 @@ public class ClientApiResource { @GET @Path("{clientId}/notes/{noteId}") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_JSON }) public Response retrieveClientNote(@PathParam("clientId") final Long clientId, @PathParam("noteId") final Long noteId) { NoteData note = this.clientReadPlatformService.retrieveClientNote(clientId, noteId); @@ -136,8 +150,8 @@ public class ClientApiResource { @PUT @Path("{clientId}/notes/{noteId}") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_JSON }) public Response updateClientNote(@PathParam("clientId") final Long clientId, @PathParam("noteId") final Long noteId, final NoteCommand command) { command.setClientId(clientId); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/client/domain/Client.java b/mifosng-provider/src/main/java/org/mifosng/platform/client/domain/Client.java index a5eea881f..9825c9db9 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/client/domain/Client.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/client/domain/Client.java @@ -13,6 +13,7 @@ import javax.persistence.UniqueConstraint; import org.apache.commons.lang.StringUtils; import org.joda.time.LocalDate; +import org.mifosng.data.command.ClientCommand; import org.mifosng.platform.infrastructure.AbstractAuditableCustom; import org.mifosng.platform.organisation.domain.Office; import org.mifosng.platform.organisation.domain.Organisation; @@ -34,19 +35,19 @@ public class Client extends AbstractAuditableCustom { @SuppressWarnings("unused") @Column(name = "firstname", length=50) - private final String firstName; + private String firstName; @SuppressWarnings("unused") @Column(name = "lastname", length=50) - private final String lastName; + private String lastName; @SuppressWarnings("unused") @Column(name = "joining_date") @Temporal(TemporalType.DATE) - private final Date joiningDate; + private Date joiningDate; @Column(name = "external_id", length=100) - private final String externalId; + private String externalId; public static Client newClient(Organisation organisation, Office clientOffice, String firstname, String lastname, @@ -85,4 +86,31 @@ public class Client extends AbstractAuditableCustom { public boolean identifiedBy(final String identifier) { return identifier.equalsIgnoreCase(this.externalId); } + + public void update(ClientCommand command) { + this.joiningDate = command.getJoiningDate().toDate(); + this.firstName = command.getFirstname(); + this.lastName = command.getLastname(); + + if (StringUtils.isNotBlank(command.getFullname())) { + this.firstName = null; + this.lastName = command.getFullname().trim(); + } + + if (StringUtils.isNotBlank(command.getExternalId())) { + this.externalId = command.getExternalId().trim(); + } else { + this.externalId = null; + } + } + + public void update(Office clientOffice, String firstname, String lastname, String externalId, LocalDate joiningDate) { + this.joiningDate = joiningDate.toDate(); + this.firstName = firstname; + this.lastName = lastname; + this.externalId = externalId; + if (StringUtils.isNotBlank(externalId)) { + this.externalId = externalId.trim(); + } + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/EnrollClientCommandValidator.java b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientCommandValidator.java similarity index 92% rename from mifosng-provider/src/main/java/org/mifosng/platform/client/service/EnrollClientCommandValidator.java rename to mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientCommandValidator.java index f1a2cbb7c..11819e2fb 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/EnrollClientCommandValidator.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientCommandValidator.java @@ -5,14 +5,14 @@ import java.util.List; import org.apache.commons.lang.StringUtils; import org.mifosng.data.ApiParameterError; -import org.mifosng.data.command.EnrollClientCommand; +import org.mifosng.data.command.ClientCommand; import org.mifosng.platform.exceptions.PlatformApiDataValidationException; -public class EnrollClientCommandValidator { +public class ClientCommandValidator { - private final EnrollClientCommand command; + private final ClientCommand command; - public EnrollClientCommandValidator(EnrollClientCommand command) { + public ClientCommandValidator(ClientCommand command) { this.command = command; } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformService.java index e2993a782..8715b9458 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformService.java @@ -1,17 +1,21 @@ package org.mifosng.platform.client.service; import org.mifosng.data.EntityIdentifier; -import org.mifosng.data.command.EnrollClientCommand; +import org.mifosng.data.command.ClientCommand; import org.mifosng.data.command.NoteCommand; import org.springframework.security.access.prepost.PreAuthorize; public interface ClientWritePlatformService { @PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_ENROLL_NEW_CLIENT_ROLE')") - Long enrollClient(EnrollClientCommand command); + Long enrollClient(ClientCommand command); + + EntityIdentifier updateClientDetails(ClientCommand command); // FIXME - add permission for adding and updating client notes. EntityIdentifier addClientNote(NoteCommand command); EntityIdentifier updateNote(NoteCommand command); + + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java index d64c7f989..468014b61 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java @@ -1,10 +1,10 @@ package org.mifosng.platform.client.service; -import static org.mifosng.platform.Specifications.officesThatMatch; +import static org.mifosng.platform.Specifications.*; import org.apache.commons.lang.StringUtils; import org.mifosng.data.EntityIdentifier; -import org.mifosng.data.command.EnrollClientCommand; +import org.mifosng.data.command.ClientCommand; import org.mifosng.data.command.NoteCommand; import org.mifosng.platform.client.domain.Client; import org.mifosng.platform.client.domain.ClientRepository; @@ -37,11 +37,11 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP @Transactional @Override - public Long enrollClient(final EnrollClientCommand command) { + public Long enrollClient(final ClientCommand command) { AppUser currentUser = context.authenticatedUser(); - EnrollClientCommandValidator validator = new EnrollClientCommandValidator(command); + ClientCommandValidator validator = new ClientCommandValidator(command); validator.validate(); Office clientOffice = this.officeRepository.findOne(officesThatMatch(currentUser.getOrganisation(), command.getOfficeId())); @@ -60,6 +60,33 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP return newClient.getId(); } + @Transactional + @Override + public EntityIdentifier updateClientDetails(ClientCommand command) { + + AppUser currentUser = context.authenticatedUser(); + + //EnrollClientCommandValidator validator = new EnrollClientCommandValidator(command); + //validator.validate(); + + Office clientOffice = this.officeRepository.findOne(officesThatMatch(currentUser.getOrganisation(), command.getOfficeId())); + + String firstname = command.getFirstname(); + String lastname = command.getLastname(); + if (StringUtils.isNotBlank(command.getFullname())) { + lastname = command.getFullname(); + firstname = null; + } + + Client clientForUpdate = this.clientRepository.findOne(clientsThatMatch(currentUser.getOrganisation(), command.getId())); + + clientForUpdate.update(clientOffice, firstname, lastname, command.getExternalId(), command.getJoiningDate()); + + this.clientRepository.save(clientForUpdate); + + return new EntityIdentifier(clientForUpdate.getId()); + } + @Transactional @Override public EntityIdentifier addClientNote(NoteCommand command) { diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductReadPlatformServiceImpl.java index a9a2c540f..0b5b9b3af 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductReadPlatformServiceImpl.java @@ -45,7 +45,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo public LoanProductData retrieveLoanProduct(final Long loanProductId) { try { - List allowedCurrencies = currencyReadPlatformService.retrieveAllowedCurrencies(); + List allowedCurrencies = currencyReadPlatformService.retrieveAllPlatformCurrencies(); LoanProductMapper rm = new LoanProductMapper(allowedCurrencies); String sql = "select " + rm.loanProductSchema() + " where lp.id = ?"; @@ -65,7 +65,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo AppUser currentUser = this.context.authenticatedUser(); - List allowedCurrencies = currencyReadPlatformService.retrieveAllowedCurrencies(); + List allowedCurrencies = currencyReadPlatformService.retrieveAllPlatformCurrencies(); LoanProductMapper rm = new LoanProductMapper(allowedCurrencies); @@ -134,7 +134,9 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo int currencyDigits = rs.getInt("currencyDigits"); CurrencyData currencyData = findCurrencyByCode(currencyCode, allowedCurrencies); - currencyData.setDecimalPlaces(currencyDigits); + if (currencyData != null) { + currencyData.setDecimalPlaces(currencyDigits); + } BigDecimal principal = rs.getBigDecimal("principal"); BigDecimal tolerance = rs.getBigDecimal("tolerance");