MIFOSX-97: wip on supporting maker checker approach in platform starting with clients flow.

This commit is contained in:
Keith Woodlock
2012-11-19 21:13:28 +00:00
parent 30d4ca7681
commit f79da8144b
17 changed files with 396 additions and 224 deletions
@@ -193,10 +193,11 @@ CREATE TABLE `m_office_transaction` (
CREATE TABLE `m_permission` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`grouping` varchar(45) DEFAULT NULL,
`order_in_grouping` int(11) DEFAULT NULL,
`code` varchar(100) NOT NULL,
`default_description` varchar(500) NOT NULL,
`default_name` varchar(100) NOT NULL,
`entity_name` varchar(100) DEFAULT NULL,
`action_name` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `code` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+44 -154
View File
@@ -157,167 +157,58 @@ VALUES
-- ========= roles and permissions =========
-- === System Supplied Permissons ==
/*
this scripts removes all current m_role_permission and m_permission entries
and then inserts new m_permission entries and just one m_role_permission entry
which gives the role (id 1 - super user) an ALL_FUNCTIONS permission
If you had other roles set up with specific permissions you will have to set up their permissions again.
*/
delete from m_role_permission;
delete from m_permission;
INSERT INTO m_permission VALUES
(1,'special',5,'USER_ADMINISTRATION_SUPER_USER','An application user will have permission to execute all tasks related to user administration.','User administration
ALL'),
(2,'special',4,'ORGANISATION_ADMINISTRATION_SUPER_USER','An application user will have permission to execute all tasks related to organisation
administration.','Organisation adminsitration ALL'),
(3,'special',3,'PORTFOLIO_MANAGEMENT_SUPER_USER','An application user will have permission to execute all tasks related to portfolio management.','Portfolio management
ALL'),
(4,'special',6,'REPORTING_SUPER_USER','An application user will have permission to execute and view all reports.','Reporting ALL'),
(5,'portfolio',NULL,'CREATE_LOAN','Allows an application user to sumit new loan application.','Can submit new loan application'),
(6,'portfolio',NULL,'CREATEHISTORIC_LOAN','Allows an application user to sumit new loan application where the submitted on date is in the past.','Can submit historic
loan application'),
(7,'portfolio',NULL,'APPROVE_LOAN','Allows an application user to approve a loan application.','Can approve loan application'),
(8,'portfolio',NULL,'APPROVEINPAST_LOAN','Allows an application user to approve a loan application where the approval date is in the past.','Can approve loan
application in the past'),
(9,'portfolio',NULL,'REJECT_LOAN','Allows an application user to reject a loan application.','Can reject loan application'),
(10,'portfolio',NULL,'REJECTINPAST_LOAN','Allows an application user to reject a loan application where the rejected date is in the past.','Can reject loan application
in the past'),
(11,'portfolio',NULL,'WITHDRAW_LOAN','Allows an application user to mark loan application as withdrawn by client.','Can withdraw loan application'),
(12,'portfolio',NULL,'WITHDRAWINPAST_LOAN','Allows an application user to mark loan application as withdrawn by client where the withdran on date is in the past.','Can
withdraw loan application in the past'),(13,'portfolio',NULL,'DELETE_LOAN','Allows an application user to complete delete the loan application if it is submitted but
not approved.','Can delete submitted loan application'),(14,'portfolio',NULL,'APPROVALUNDO_LOAN','Allows an application user to undo a loan approval.','Can undo loan
approval'),(15,'portfolio',NULL,'DISBURSE_LOAN','Allows an application user to disburse a loan application.','Can disburse loan'),
(16,'portfolio',NULL,'DISBURSEINPAST_LOAN','Allows an application user to disburse a loan where the disbursement date is in the past.','Can disburse loan in the
past'),(17,'portfolio',NULL,'DISBURSALUNDO_LOAN','Allows an application user to undo a loan disbursal if not payments already made.','Can undo loan disbursal'),
(18,'portfolio',NULL,'REPAYMENT_LOAN','Allows an application user to enter a repayment on the loan.','Can enter a repayment against a loan'),
(19,'portfolio',NULL,'REPAYMENTINPAST_LOAN','Allows an application user to enter a repayment on the loan where the repayment date is in the past.','Can enter a
repayment against a loan in the past'),
(20,'portfolio',NULL,'CREATE_CLIENT','Allows an application user to add a new client.','Can add a new client.'),
(42,'special',1,'ALL_FUNCTIONS','An application user will have permission to execute all tasks.','ALL'),
(43,'special',2,'ALL_FUNCTIONS_READ','An application user will have permission to execute all read tasks.','ALL READ'),
(112,'organisation',NULL,'CREATE_CHARGE','Create a Charge','Create a Charge'),(113,'organisation',NULL,'READ_CHARGE','Read Charges','Read Charges'),
(114,'organisation',NULL,'UPDATE_CHARGE','Update a Charge','Update a Charge'),(115,'organisation',NULL,'DELETE_CHARGE','Delete a Charge','Delete a Charge'),
(120,'portfolio',NULL,'READ_CLIENT','Read Clients','Read Clients'),(121,'portfolio',NULL,'UPDATE_CLIENT','Update a Client','Update a Client'),
(122,'portfolio',NULL,'DELETE_CLIENT','Delete a Client','Delete a Client'),(123,'portfolio',NULL,'CREATE_CLIENTIMAGE','Create/Update Client Image','Create/Update
Client Image'),(124,'portfolio',NULL,'READ_CLIENTIMAGE','Read Client Images','Read Client Images'),(126,'portfolio',NULL,'DELETE_CLIENTIMAGE','Delete Client
Image','Delete Client Image'),(127,'portfolio',NULL,'CREATE_CLIENTNOTE','Create a Client Note','Create a Client Note'),(128,'portfolio',NULL,'READ_CLIENTNOTE','Read
Client Notes','Read Client Notes'),(129,'portfolio',NULL,'UPDATE_CLIENTNOTE','Update a Client Note','Update a Client Note'),
(130,'portfolio',NULL,'DELETE_CLIENTNOTE','Delete a Client Note','Delete a Client Note'),(131,'portfolio',NULL,'CREATE_CLIENTIDENTIFIER','Create a Client
Identifier','Create a Client Identifier'),(132,'portfolio',NULL,'READ_CLIENTIDENTIFIER','Read Client Identifiers','Read Client Identifiers'),
(133,'portfolio',NULL,'UPDATE_CLIENTIDENTIFIER','Update a Client Identifier','Update a Client Identifier'),(134,'portfolio',NULL,'DELETE_CLIENTIDENTIFIER','Delete a
Client Identifier','Delete a Client Identifier'),(135,'configuration',NULL,'CREATE_CODE','Create a Code','Create a Code'),(136,'configuration',NULL,'READ_CODE','Read
Codes','Read Codes'),(137,'configuration',NULL,'UPDATE_CODE','Update a Code','Update a Code'),(138,'configuration',NULL,'DELETE_CODE','Delete a Code','Delete a
Code'),(139,'configuration',NULL,'READ_CURRENCY','Read Currencies','Read Currencies'),(140,'configuration',NULL,'UPDATE_CURRENCY','Update Currencies','Update
Currencies'),(141,'portfolio',NULL,'CREATE_DOCUMENT','Create and Upload a Document','Create and Upload a Document'),(142,'portfolio',NULL,'READ_DOCUMENT','Read
Documents','Read Documents'),(143,'portfolio',NULL,'UPDATE_DOCUMENT','Update and Upload a Document','Update and Upload a Document'),
(144,'portfolio',NULL,'DELETE_DOCUMENT','Delete a Document','Delete a Document'),(145,'organisation',NULL,'CREATE_FUND','Create a Fund','Create a Fund'),
(146,'organisation',NULL,'READ_FUND','Read Funds','Read Funds'),(147,'organisation',NULL,'UPDATE_FUND','Update a Fund','Update a Fund'),
(148,'organisation',NULL,'DELETE_FUND','Delete Fund','Delete Fund'),(149,'portfolio',NULL,'CREATE_GROUP','Create a Group','Create a Group'),
(150,'portfolio',NULL,'READ_GROUP','Read Groups','Read Groups'),(151,'portfolio',NULL,'UPDATE_GROUP','Update a Group','Update a Group'),
(152,'portfolio',NULL,'DELETE_GROUP','Delete a Group','Delete a Group'),(153,'organisation',NULL,'CREATE_LOANPRODUCT','Create a Loan Product','Create a Loan
Product'),(154,'organisation',NULL,'READ_LOANPRODUCT','Read Loan Products','Read Loan Products'),(155,'organisation',NULL,'UPDATE_LOANPRODUCT','Update a Loan
Product','Update a Loan Product'),(156,'organisation',NULL,'DELETE_LOANPRODUCT','Delete a Loan Product','Delete a Loan Product'),
(157,'portfolio',NULL,'READ_LOAN','Read Loans','Read Loans'),(158,'portfolio',NULL,'UPDATE_LOAN','Update a Loan','Update a Loan'),
(159,'portfolio',NULL,'UPDATEHISTORIC_LOAN','Update a Loan that was Created Historically','Update a Loan that was Created Historically'),
(160,'portfolio',NULL,'CREATE_LOANCHARGE','Create a Loan Charge','Create a Loan Charge'),(161,'portfolio',NULL,'UPDATE_LOANCHARGE','Update a Loan Charge','Update a
Loan Charge'),(162,'portfolio',NULL,'DELETE_LOANCHARGE','Delete a Loan Charge','Delete a Loan Charge'),(163,'portfolio',NULL,'WAIVE_LOANCHARGE','Waive a Loan
Charge','Waive a Loan Charge'),(164,'portfolio',NULL,'BULKREASSIGN_LOAN','Bulk Reassign Loans','Bulk Reassign Loans'),
(165,'portfolio',NULL,'ADJUST_LOAN','Adjust a Loan Transaction','Adjust a Loan Transaction'),(166,'portfolio',NULL,'WAIVEINTERESTPORTION_LOAN','Waive Portion of Loan
Interest','Waive Portion of Loan Interest'),(167,'portfolio',NULL,'WRITEOFF_LOAN','Write-Off a Loan','Write-Off a Loan'),(168,'portfolio',NULL,'CLOSE_LOAN','Close a
Loan','Close a Loan'),(169,'portfolio',NULL,'CLOSEASRESCHEDULED_LOAN','Close a Loan (having been Rescheduled (Mifos Legacy Need)','Close a Loan (having been
Rescheduled (Mifos Legacy Need)'),(170,'organisation',NULL,'READ_MAKERCHECKER','Read Maker-Checker Entries','Read Maker-Checker Entries'),
(171,'organisation',NULL,'CREATE_OFFICE','Create an Office','Create an Office'),(172,'organisation',NULL,'READ_OFFICE','Read Offices','Read Offices'),
(173,'organisation',NULL,'UPDATE_OFFICE','Update an Office','Update an Office'),(174,'organisation',NULL,'DELETE_OFFICE','Delete an Office','Delete an Office'),
(175,'organisation',NULL,'READ_OFFICETRANSACTION','Read Office Transactions','Read Office Transactions'),
(176,'organisation',NULL,'CREATE_OFFICETRANSACTION','Create an Office Transaction','Create an Office Transaction'),
(177,'authorisation',NULL,'READ_PERMISSION','Read Permissions','Read Permissions'),
(178,'authorisation',NULL,'CREATE_ROLE','Create a Role','Create a Role'),
(179,'authorisation',NULL,'READ_ROLE','Read Roles','Read Roles'),
(180,'authorisation',NULL,'UPDATE_ROLE','Update a Role','Update a Role'),
(181,'authorisation',NULL,'DELETE_ROLE','Delete a Role','Delete a Role'),
(182,'authorisation',NULL,'CREATE_USER','Create a User','Create a User'),
(183,'authorisation',NULL,'READ_USER','Read Users','Read Users'),
(184,'authorisation',NULL,'UPDATE_USER','Update a User','Update a User'),
(185,'authorisation',NULL,'DELETE_USER','Create a User','Create a User'),
(186,'organisation',NULL,'CREATE_STAFF','Create a Staff Member','Create a Staff Member'),
(187,'organisation',NULL,'READ_STAFF','Read Staff','Read Staff'),
(188,'organisation',NULL,'UPDATE_STAFF','Update a Staff Member','Update a Staff Member'),
(189,'organisation',NULL,'DELETE_STAFF','Delete a Staff Member','Delete a Staff Member'),
(190,'organisation',NULL,'CREATE_SAVINGSPRODUCT','Create a Savings Product','Create a Savings Product'),
(191,'organisation',NULL,'READ_SAVINGSPRODUCT','Read Savings Products','Read Savings Products'),
(192,'organisation',NULL,'UPDATE_SAVINGSPRODUCT','Update a Savings Product','Update a Savings Product'),
(193,'organisation',NULL,'DELETE_SAVINGSPRODUCT','Delete a Savings Product','Delete a Savings Product'),
(194,'organisation',NULL,'CREATE_DEPOSITPRODUCT','Create a Deposit Product','Create a Deposit Product'),
(195,'organisation',NULL,'READ_DEPOSITPRODUCT','Read Deposit Products','Read Deposit Products'),
(196,'organisation',NULL,'UPDATE_DEPOSITPRODUCT','Update a Deposit Product','Update a Deposit Product'),
(197,'organisation',NULL,'DELETE_DEPOSITPRODUCT','Delete a Deposit Product','Delete a Deposit Product'),
(198,'portfolio',NULL,'CREATE_DEPOSITACCOUNT','Create a Deposit Account','Create a Deposit Account'),
(199,'portfolio',NULL,'READ_DEPOSITACCOUNT','Read Deposit Accounts','Read Deposit Accounts'),
(200,'portfolio',NULL,'UPDATE_DEPOSITACCOUNT','Update a Deposit Account','Update a Deposit Account'),
(201,'portfolio',NULL,'DELETE_DEPOSITACCOUNT','Delete a Deposit Account','Delete a Deposit Account'),
(202,'portfolio',NULL,'APPROVE_DEPOSITACCOUNT','Approve a Deposit Account','Approve a Deposit Account'),
(203,'portfolio',NULL,'REJECT_DEPOSITACCOUNT','Reject Deposit Account','Reject Deposit Account'),
(204,'portfolio',NULL,'WITHDRAW_DEPOSITACCOUNT','Withdraw Deposit Account','Withdraw Deposit Account'),
(205,'portfolio',NULL,'APPROVALUNDO_DEPOSITACCOUNT','Undo Approval of Deposit Account','Undo Approval of Deposit Account'),
(206,'portfolio',NULL,'WITHDRAWAL_DEPOSITACCOUNT','Make a Withdrawal From Deposit Account','Make a Withdrawal From Deposit Account'),
(207,'portfolio',NULL,'INTEREST_DEPOSITACCOUNT','Apply Interest to Deposit Accounts','Apply Interest to Deposit Accounts'),
(208,'portfolio',NULL,'RENEW_DEPOSITACCOUNT','Renew Deposit Account','Renew Deposit Account'),
(209,'portfolio',NULL,'CREATE_SAVINGSACCOUNT','Create a Savings Account','Create a Savings Account'),
(210,'portfolio',NULL,'READ_SAVINGSACCOUNT','Read Savings Accounts','Read Savings Accounts'),
(211,'portfolio',NULL,'UPDATE_SAVINGSACCOUNT','Update a Savings Account','Update a Savings Account'),
(212,'portfolio',NULL,'DELETE_SAVINGSACCOUNT','Delete a Savings Account','Delete a Savings Account');
/* System Supplied Permissons */
INSERT INTO `m_permission` VALUES (1,'special','USER_ADMINISTRATION_SUPER_USER','An application user will have permission to execute all tasks related to user administration.','User administration ALL',NULL,NULL),(2,'special','ORGANISATION_ADMINISTRATION_SUPER_USER','An application user will have permission to execute all tasks related to organisation administration.','Organisation adminsitration ALL',NULL,NULL),(3,'special','PORTFOLIO_MANAGEMENT_SUPER_USER','An application user will have permission to execute all tasks related to portfolio management.','Portfolio management ALL',NULL,NULL),(4,'special','REPORTING_SUPER_USER','An application user will have permission to execute and view all reports.','Reporting ALL',NULL,NULL),(5,'portfolio','CREATE_LOAN','Allows an application user to sumit new loan application.','Can submit new loan application','LOAN','CREATE'),(6,'portfolio','CREATEHISTORIC_LOAN','Allows an application user to sumit new loan application where the submitted on date is in the past.','Can submit historic loan application','LOAN','CREATEHISTORIC'),(7,'transaction_loan','APPROVE_LOAN','Allows an application user to approve a loan application.','Can approve loan application','LOAN','APPROVE'),(8,'transaction_loan','APPROVEINPAST_LOAN','Allows an application user to approve a loan application where the approval date is in the past.','Can approve loan application in the past','LOAN','APPROVEINPAST'),(9,'transaction_loan','REJECT_LOAN','Allows an application user to reject a loan application.','Can reject loan application','LOAN','REJECT'),(10,'transaction_loan','REJECTINPAST_LOAN','Allows an application user to reject a loan application where the rejected date is in the past.','Can reject loan application in the past','LOAN','REJECTINPAST'),
(11,'transaction_loan','WITHDRAW_LOAN','Allows an application user to mark loan application as withdrawn by client.','Can withdraw loan application','LOAN','WITHDRAW'),(12,'transaction_loan','WITHDRAWINPAST_LOAN','Allows an application user to mark loan application as withdrawn by client where the withdran on date is in the past.','Can withdraw loan application in the past','LOAN','WITHDRAWINPAST'),(13,'portfolio','DELETE_LOAN','Allows an application user to complete delete the loan application if it is submitted but not approved.','Can delete submitted loan application','LOAN','DELETE'),(14,'transaction_loan','APPROVALUNDO_LOAN','Allows an application user to undo a loan approval.','Can undo loan approval','LOAN','APPROVALUNDO'),(15,'transaction_loan','DISBURSE_LOAN','Allows an application user to disburse a loan application.','Can disburse loan','LOAN','DISBURSE'),(16,'transaction_loan','DISBURSEINPAST_LOAN','Allows an application user to disburse a loan where the disbursement date is in the past.','Can disburse loan in the past','LOAN','DISBURSEINPAST'),(17,'transaction_loan','DISBURSALUNDO_LOAN','Allows an application user to undo a loan disbursal if not payments already made.','Can undo loan disbursal','LOAN','DISBURSALUNDO'),(18,'transaction_loan','REPAYMENT_LOAN','Allows an application user to enter a repayment on the loan.','Can enter a repayment against a loan','LOAN','REPAYMENT'),(19,'transaction_loan','REPAYMENTINPAST_LOAN','Allows an application user to enter a repayment on the loan where the repayment date is in the past.','Can enter a repayment against a loan in the past','LOAN','REPAYMENTINPAST'),(20,'portfolio','CREATE_CLIENT','Allows an application user to add a new client.','Can add a new client.','CLIENT','CREATE'),
(42,'special','ALL_FUNCTIONS','An application user will have permission to execute all tasks.','ALL',NULL,NULL),(43,'special','ALL_FUNCTIONS_READ','An application user will have permission to execute all read tasks.','ALL READ',NULL,NULL),(112,'organisation','CREATE_CHARGE','Create a Charge','Create a Charge','CHARGE','CREATE'),(113,'organisation','READ_CHARGE','Read Charges','Read Charges','CHARGE','READ'),(114,'organisation','UPDATE_CHARGE','Update a Charge','Update a Charge','CHARGE','UPDATE'),(115,'organisation','DELETE_CHARGE','Delete a Charge','Delete a Charge','CHARGE','DELETE'),(120,'portfolio','READ_CLIENT','Read Clients','Read Clients','CLIENT','READ'),(121,'portfolio','UPDATE_CLIENT','Update a Client','Update a Client','CLIENT','UPDATE'),(122,'portfolio','DELETE_CLIENT','Delete a Client','Delete a Client','CLIENT','DELETE'),(123,'portfolio','CREATE_CLIENTIMAGE','Create/Update Client Image','Create/Update Client Image','CLIENTIMAGE','CREATE'),(124,'portfolio','READ_CLIENTIMAGE','Read Client Images','Read Client Images','CLIENTIMAGE','READ'),(126,'portfolio','DELETE_CLIENTIMAGE','Delete Client Image','Delete Client Image','CLIENTIMAGE','DELETE'),(127,'portfolio','CREATE_CLIENTNOTE','Create a Client Note','Create a Client Note','CLIENTNOTE','CREATE'),(128,'portfolio','READ_CLIENTNOTE','Read Client Notes','Read Client Notes','CLIENTNOTE','READ'),(129,'portfolio','UPDATE_CLIENTNOTE','Update a Client Note','Update a Client Note','CLIENTNOTE','UPDATE'),(130,'portfolio','DELETE_CLIENTNOTE','Delete a Client Note','Delete a Client Note','CLIENTNOTE','DELETE'),(131,'portfolio','CREATE_CLIENTIDENTIFIER','Create a Client Identifier','Create a Client Identifier','CLIENTIDENTIFIER','CREATE'),
(132,'portfolio','READ_CLIENTIDENTIFIER','Read Client Identifiers','Read Client Identifiers','CLIENTIDENTIFIER','READ'),(133,'portfolio','UPDATE_CLIENTIDENTIFIER','Update a Client Identifier','Update a Client Identifier','CLIENTIDENTIFIER','UPDATE'),(134,'portfolio','DELETE_CLIENTIDENTIFIER','Delete a Client Identifier','Delete a Client Identifier','CLIENTIDENTIFIER','DELETE'),(135,'configuration','CREATE_CODE','Create a Code','Create a Code','CODE','CREATE'),(136,'configuration','READ_CODE','Read Codes','Read Codes','CODE','READ'),(137,'configuration','UPDATE_CODE','Update a Code','Update a Code','CODE','UPDATE'),(138,'configuration','DELETE_CODE','Delete a Code','Delete a Code','CODE','DELETE'),(139,'configuration','READ_CURRENCY','Read Currencies','Read Currencies','CURRENCY','READ'),(140,'configuration','UPDATE_CURRENCY','Update Currencies','Update Currencies','CURRENCY','UPDATE'),(141,'portfolio','CREATE_DOCUMENT','Create and Upload a Document','Create and Upload a Document','DOCUMENT','CREATE'),(142,'portfolio','READ_DOCUMENT','Read Documents','Read Documents','DOCUMENT','READ'),(143,'portfolio','UPDATE_DOCUMENT','Update and Upload a Document','Update and Upload a Document','DOCUMENT','UPDATE'),(144,'portfolio','DELETE_DOCUMENT','Delete a Document','Delete a Document','DOCUMENT','DELETE'),(145,'organisation','CREATE_FUND','Create a Fund','Create a Fund','FUND','CREATE'),(146,'organisation','READ_FUND','Read Funds','Read Funds','FUND','READ'),(147,'organisation','UPDATE_FUND','Update a Fund','Update a Fund','FUND','UPDATE'),(148,'organisation','DELETE_FUND','Delete Fund','Delete Fund','FUND','DELETE'),(149,'portfolio','CREATE_GROUP','Create a Group','Create a Group','GROUP','CREATE'),
(150,'portfolio','READ_GROUP','Read Groups','Read Groups','GROUP','READ'),(151,'portfolio','UPDATE_GROUP','Update a Group','Update a Group','GROUP','UPDATE'),(152,'portfolio','DELETE_GROUP','Delete a Group','Delete a Group','GROUP','DELETE'),(153,'organisation','CREATE_LOANPRODUCT','Create a Loan Product','Create a Loan Product','LOANPRODUCT','CREATE'),(154,'organisation','READ_LOANPRODUCT','Read Loan Products','Read Loan Products','LOANPRODUCT','READ'),(155,'organisation','UPDATE_LOANPRODUCT','Update a Loan Product','Update a Loan Product','LOANPRODUCT','UPDATE'),(156,'organisation','DELETE_LOANPRODUCT','Delete a Loan Product','Delete a Loan Product','LOANPRODUCT','DELETE'),(157,'portfolio','READ_LOAN','Read Loans','Read Loans','LOAN','READ'),(158,'portfolio','UPDATE_LOAN','Update a Loan','Update a Loan','LOAN','UPDATE'),(159,'portfolio','UPDATEHISTORIC_LOAN','Update a Loan that was Created Historically','Update a Loan that was Created Historically','LOAN','UPDATEHISTORIC'),(160,'portfolio','CREATE_LOANCHARGE','Create a Loan Charge','Create a Loan Charge','LOANCHARGE','CREATE'),(161,'portfolio','UPDATE_LOANCHARGE','Update a Loan Charge','Update a Loan Charge','LOANCHARGE','UPDATE'),(162,'portfolio','DELETE_LOANCHARGE','Delete a Loan Charge','Delete a Loan Charge','LOANCHARGE','DELETE'),(163,'portfolio','WAIVE_LOANCHARGE','Waive a Loan Charge','Waive a Loan Charge','LOANCHARGE','WAIVE'),(164,'transaction_loan','BULKREASSIGN_LOAN','Bulk Reassign Loans','Bulk Reassign Loans','LOAN','BULKREASSIGN'),(165,'transaction_loan','ADJUST_LOAN','Adjust a Loan Transaction','Adjust a Loan Transaction','LOAN','ADJUST'),(166,'transaction_loan','WAIVEINTERESTPORTION_LOAN','Waive Portion of Loan Interest','Waive Portion of Loan Interest','LOAN','WAIVEINTERESTPORTION'),
(167,'transaction_loan','WRITEOFF_LOAN','Write-Off a Loan','Write-Off a Loan','LOAN','WRITEOFF'),(168,'transaction_loan','CLOSE_LOAN','Close a Loan','Close a Loan','LOAN','CLOSE'),(169,'transaction_loan','CLOSEASRESCHEDULED_LOAN','Close a Loan (having been Rescheduled (Mifos Legacy Need)','Close a Loan (having been Rescheduled (Mifos Legacy Need)','LOAN','CLOSEASRESCHEDULED'),(170,'organisation','READ_MAKERCHECKER','Read Maker-Checker Entries','Read Maker-Checker Entries','MAKERCHECKER','READ'),(171,'organisation','CREATE_OFFICE','Create an Office','Create an Office','OFFICE','CREATE'),(172,'organisation','READ_OFFICE','Read Offices','Read Offices','OFFICE','READ'),(173,'organisation','UPDATE_OFFICE','Update an Office','Update an Office','OFFICE','UPDATE'),(174,'organisation','DELETE_OFFICE','Delete an Office','Delete an Office','OFFICE','DELETE'),(175,'organisation','READ_OFFICETRANSACTION','Read Office Transactions','Read Office Transactions','OFFICETRANSACTION','READ'),(176,'organisation','CREATE_OFFICETRANSACTION','Create an Office Transaction','Create an Office Transaction','OFFICETRANSACTION','CREATE'),(177,'authorisation','READ_PERMISSION','Read Permissions','Read Permissions','PERMISSION','READ'),(178,'authorisation','CREATE_ROLE','Create a Role','Create a Role','ROLE','CREATE'),(179,'authorisation','READ_ROLE','Read Roles','Read Roles','ROLE','READ'),(180,'authorisation','UPDATE_ROLE','Update a Role','Update a Role','ROLE','UPDATE'),(181,'authorisation','DELETE_ROLE','Delete a Role','Delete a Role','ROLE','DELETE'),(182,'authorisation','CREATE_USER','Create a User','Create a User','USER','CREATE'),(183,'authorisation','READ_USER','Read Users','Read Users','USER','READ'),(184,'authorisation','UPDATE_USER','Update a User','Update a User','USER','UPDATE'),
(185,'authorisation','DELETE_USER','Create a User','Create a User','USER','DELETE'),(186,'organisation','CREATE_STAFF','Create a Staff Member','Create a Staff Member','STAFF','CREATE'),(187,'organisation','READ_STAFF','Read Staff','Read Staff','STAFF','READ'),(188,'organisation','UPDATE_STAFF','Update a Staff Member','Update a Staff Member','STAFF','UPDATE'),(189,'organisation','DELETE_STAFF','Delete a Staff Member','Delete a Staff Member','STAFF','DELETE'),(190,'organisation','CREATE_SAVINGSPRODUCT','Create a Savings Product','Create a Savings Product','SAVINGSPRODUCT','CREATE'),(191,'organisation','READ_SAVINGSPRODUCT','Read Savings Products','Read Savings Products','SAVINGSPRODUCT','READ'),(192,'organisation','UPDATE_SAVINGSPRODUCT','Update a Savings Product','Update a Savings Product','SAVINGSPRODUCT','UPDATE'),(193,'organisation','DELETE_SAVINGSPRODUCT','Delete a Savings Product','Delete a Savings Product','SAVINGSPRODUCT','DELETE'),(194,'organisation','CREATE_DEPOSITPRODUCT','Create a Deposit Product','Create a Deposit Product','DEPOSITPRODUCT','CREATE'),(195,'organisation','READ_DEPOSITPRODUCT','Read Deposit Products','Read Deposit Products','DEPOSITPRODUCT','READ'),(196,'organisation','UPDATE_DEPOSITPRODUCT','Update a Deposit Product','Update a Deposit Product','DEPOSITPRODUCT','UPDATE'),(197,'organisation','DELETE_DEPOSITPRODUCT','Delete a Deposit Product','Delete a Deposit Product','DEPOSITPRODUCT','DELETE'),(198,'portfolio','CREATE_DEPOSITACCOUNT','Create a Deposit Account','Create a Deposit Account','DEPOSITACCOUNT','CREATE'),(199,'portfolio','READ_DEPOSITACCOUNT','Read Deposit Accounts','Read Deposit Accounts','DEPOSITACCOUNT','READ'),(200,'portfolio','UPDATE_DEPOSITACCOUNT','Update a Deposit Account','Update a Deposit Account','DEPOSITACCOUNT','UPDATE'),
(201,'portfolio','DELETE_DEPOSITACCOUNT','Delete a Deposit Account','Delete a Deposit Account','DEPOSITACCOUNT','DELETE'),(202,'transaction_deposit','APPROVE_DEPOSITACCOUNT','Approve a Deposit Account','Approve a Deposit Account','DEPOSITACCOUNT','APPROVE'),(203,'transaction_deposit','REJECT_DEPOSITACCOUNT','Reject Deposit Account','Reject Deposit Account','DEPOSITACCOUNT','REJECT'),(204,'transaction_deposit','WITHDRAW_DEPOSITACCOUNT','Withdraw Deposit Account','Withdraw Deposit Account','DEPOSITACCOUNT','WITHDRAW'),(205,'transaction_deposit','APPROVALUNDO_DEPOSITACCOUNT','Undo Approval of Deposit Account','Undo Approval of Deposit Account','DEPOSITACCOUNT','APPROVALUNDO'),(206,'transaction_deposit','WITHDRAWAL_DEPOSITACCOUNT','Make a Withdrawal From Deposit Account','Make a Withdrawal From Deposit Account','DEPOSITACCOUNT','WITHDRAWAL'),(207,'transaction_deposit','INTEREST_DEPOSITACCOUNT','Apply Interest to Deposit Accounts','Apply Interest to Deposit Accounts','DEPOSITACCOUNT','INTEREST'),(208,'transaction_deposit','RENEW_DEPOSITACCOUNT','Renew Deposit Account','Renew Deposit Account','DEPOSITACCOUNT','RENEW'),(209,'portfolio','CREATE_SAVINGSACCOUNT','Create a Savings Account','Create a Savings Account','SAVINGSACCOUNT','CREATE'),(210,'portfolio','READ_SAVINGSACCOUNT','Read Savings Accounts','Read Savings Accounts','SAVINGSACCOUNT','READ'),(211,'portfolio','UPDATE_SAVINGSACCOUNT','Update a Savings Account','Update a Savings Account','SAVINGSACCOUNT','UPDATE'),(212,'portfolio','DELETE_SAVINGSACCOUNT','Delete a Savings Account','Delete a Savings Account','SAVINGSACCOUNT','DELETE');
INSERT INTO `m_role` (`id`, `name`, `description`, `createdby_id`, `created_date`, `lastmodified_date`, `lastmodifiedby_id`)
VALUES
(1,'Super user','This role provides all application permissions.',NULL,NULL,NULL,NULL),
(2,'Read Only user','This role provides read only application permissions.',NULL,NULL,NULL,NULL);
(1,'Super user','This role provides all application permissions.',NULL,NULL,NULL,NULL);
/* role 1 is super user, give it ALL_FUNCTIONS */
INSERT INTO m_role_permission(role_id, permission_id)
select 1, id
from m_permission
where code = 'ALL_FUNCTIONS';
INSERT INTO `m_role_permission` (`role_id`, `permission_id`)
VALUES
(1,42), (2,43);
/* add a read permission for each defined report */
insert into m_permission(grouping, `code`, default_description, default_name, entity_name, action_name)
select 'report', concat('READ_', sr.report_name), concat('READ_', sr.report_name), concat('READ_', sr.report_name), sr.report_name, 'READ'
from stretchy_report sr;
/* add a create, read, update and delete permission for each registered datatable */
insert into m_permission(grouping, `code`, default_description, default_name, entity_name, action_name)
select 'datatable', concat('CREATE_', r.registered_table_name), concat('CREATE_', r.registered_table_name), concat('CREATE_', r.registered_table_name), r.registered_table_name, 'CREATE'
from x_registered_table r;
insert into m_permission(grouping, `code`, default_description, default_name, entity_name, action_name)
select 'datatable', concat('READ_', r.registered_table_name), concat('READ_', r.registered_table_name), concat('READ_', r.registered_table_name), r.registered_table_name, 'READ'
from x_registered_table r;
insert into m_permission(grouping, `code`, default_description, default_name, entity_name, action_name)
select 'datatable', concat('UPDATE_', r.registered_table_name), concat('UPDATE_', r.registered_table_name), concat('UPDATE_', r.registered_table_name), r.registered_table_name, 'UPDATE'
from x_registered_table r;
insert into m_permission(grouping, `code`, default_description, default_name, entity_name, action_name)
select 'datatable', concat('DELETE_', r.registered_table_name), concat('DELETE_', r.registered_table_name), concat('DELETE_', r.registered_table_name), r.registered_table_name, 'DELETE'
from x_registered_table r;
INSERT INTO `m_appuser` (`id`, `office_id`, `username`, `firstname`, `lastname`, `password`, `email`,
`firsttime_login_remaining`, `nonexpired`, `nonlocked`, `nonexpired_credentials`, `enabled`,
@@ -328,7 +219,6 @@ VALUES
INSERT INTO `m_appuser_role` (`appuser_id`, `role_id`) VALUES (1,1);
INSERT INTO `stretchy_parameter` VALUES
(3,'FullReportList',NULL,'n/a','n/a','n/a','n/a','Y',NULL,NULL,'select r.report_id, r.report_name, r.report_type,
r.report_subtype, r.report_category,\r\nrp.parameter_id, rp.report_parameter_name, p.parameter_name\r\nfrom stretchy_report r\r\nleft join stretchy_report_parameter rp
+8
View File
@@ -16,6 +16,14 @@ apply plugin: 'eclipse'
apply plugin: 'tomcat'
apply plugin: 'project-report'
/* define the valid syntax level for source files */
sourceCompatibility = JavaVersion.VERSION_1_6
/* define binary compatiblity version */
targetCompatibility = JavaVersion.VERSION_1_6
// targetCompatibility = 1.6
// sourceCompatibility = 1.6
project.ext.springVersion = '3.1.1.RELEASE'
project.ext.springSecurityVersion = '3.1.0.RELEASE'
project.ext.hibernateValidatorVersion = '4.3.0.Final'
@@ -24,7 +24,6 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.apache.commons.lang.StringUtils;
import org.mifosng.platform.api.commands.ClientCommand;
import org.mifosng.platform.api.commands.NoteCommand;
import org.mifosng.platform.api.data.ClientAccountSummaryCollectionData;
import org.mifosng.platform.api.data.ClientData;
@@ -159,7 +158,7 @@ public class ClientsApiResource {
@Path("{clientId}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String retrieveClientData(
public String retrieveClient(
@PathParam("clientId") final Long clientId,
@Context final UriInfo uriInfo) {
@@ -176,15 +175,46 @@ public class ClientsApiResource {
clientData = ClientData.templateOnTop(clientData, allowedOffices);
}
if (makerCheckerId != null) {
final CommandSourceData entry = this.commandSourceReadPlatformService.retrieveById(makerCheckerId);
final ClientCommand command = this.apiDataConversionService.convertJsonToClientCommand(null, entry.json(), false);
clientData = ClientData.integrateChanges(clientData, command);
clientData = handleMakerCheckerRequest(clientId, makerCheckerId, clientData);
}
boolean retrieveChanges = true;
if (retrieveChanges) {
final Collection<ClientData> dataChanges = retrieveAllUnprocessedDataChanges(clientId);
clientData = ClientData.integrateChanges(clientData, clientData.currentChange(), dataChanges);
}
return this.apiJsonSerializerService.serializeClientDataToJson(prettyPrint, responseParameters, clientData);
}
private ClientData handleMakerCheckerRequest(final Long clientId, final Long makerCheckerId, ClientData clientData) {
final CommandSourceData entry = this.commandSourceReadPlatformService.retrieveById(makerCheckerId);
final ClientData currentChange = this.apiDataConversionService.convertInternalJsonFormatToClientDataChange(clientId, entry.json());
final Collection<ClientData> dataChanges = retrieveAllUnprocessedDataChanges(clientId);
clientData = ClientData.integrateChanges(clientData, currentChange, dataChanges);
return clientData;
}
private Collection<ClientData> retrieveAllUnprocessedDataChanges(final Long clientId) {
Collection<ClientData> dataChanges = new ArrayList<ClientData>();
boolean retrieveChanges = true;
if (retrieveChanges) {
Collection<CommandSourceData> unprocessedChanges = this.commandSourceReadPlatformService.retrieveUnprocessChangesByResourceId("clients", clientId);
for (CommandSourceData commandSourceData : unprocessedChanges) {
ClientData change = this.apiDataConversionService.convertInternalJsonFormatToClientDataChange(clientId, commandSourceData.json());
dataChanges.add(change);
}
}
if (dataChanges.isEmpty()) {
dataChanges = null;
}
return dataChanges;
}
@GET
@Path("template")
@Consumes({MediaType.APPLICATION_JSON})
@@ -199,10 +229,7 @@ public class ClientsApiResource {
ClientData clientData = this.clientReadPlatformService.retrieveNewClientDetails();
if (makerCheckerId != null) {
final CommandSourceData entry = this.commandSourceReadPlatformService.retrieveById(makerCheckerId);
final ClientCommand command = this.apiDataConversionService.convertJsonToClientCommand(null, entry.json(), false);
clientData = ClientData.integrateChanges(clientData, command);
clientData = handleMakerCheckerRequest(null, makerCheckerId, clientData);
}
return this.apiJsonSerializerService.serializeClientDataToJson(prettyPrint, responseParameters, clientData);
@@ -9,7 +9,6 @@ import org.joda.time.LocalDate;
*/
public class ClientCommand {
private final Long id;
private final String externalId;
private final String firstname;
private final String lastname;
@@ -18,6 +17,7 @@ public class ClientCommand {
private final LocalDate joiningDate;
// made transient as dont want them to be serialized/converted to JSON
private final transient Long id;
private final transient boolean makerCheckerApproval;
private final transient Set<String> parametersPassedInRequest;
@@ -1,10 +1,10 @@
package org.mifosng.platform.api.data;
import java.util.Collection;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosng.platform.api.commands.ClientCommand;
/**
* Immutable data object representing client data.
@@ -22,13 +22,13 @@ final public class ClientData {
private final LocalDate joinedDate;
private final String imageKey;
@SuppressWarnings("unused")
private final boolean imagePresent;
private final Boolean imagePresent;
private final List<OfficeLookup> allowedOffices;
@SuppressWarnings("unused")
private final ClientCommand changes;
private final ClientData currentChange;
private final Collection<ClientData> allChanges;
private static String buildDisplayNameFrom(final String firstname, final String lastname) {
String displayName = null;
StringBuilder displayNameBuilder = new StringBuilder();
@@ -43,7 +43,27 @@ final public class ClientData {
return displayName;
}
public static ClientData integrateChanges(final ClientData clientData, final ClientCommand command) {
public static ClientData dataChangeInstance(
final Long id,
final Long officeId,
final String externalId,
final String firstname,
final String lastname,
final String clientOrBusinessName,
final LocalDate joiningDate) {
String firstnameValue = firstname;
String lastnameValue = lastname;
if (StringUtils.isNotBlank(clientOrBusinessName)) {
firstnameValue = null;
lastnameValue = clientOrBusinessName;
}
final String displayName = buildDisplayNameFrom(firstnameValue, lastnameValue);
return new ClientData(officeId, null, id, firstname, lastname, displayName, externalId, joiningDate, null, null, null, null);
}
public static ClientData integrateChanges(final ClientData clientData, ClientData currentChange, final Collection<ClientData> allChanges) {
String firstname = clientData.firstname;
String lastname = clientData.lastname;
if (StringUtils.isNotBlank(clientData.clientOrBusinessName)) {
@@ -52,11 +72,11 @@ final public class ClientData {
}
final String displayName = buildDisplayNameFrom(firstname, lastname);
return new ClientData(clientData.officeId, clientData.officeName, clientData.id, firstname, lastname, displayName,
clientData.externalId, clientData.joinedDate, clientData.imageKey, clientData.allowedOffices, command);
clientData.externalId, clientData.joinedDate, clientData.imageKey, clientData.allowedOffices, currentChange, allChanges);
}
public static ClientData template(final Long officeId, final LocalDate joinedDate, final List<OfficeLookup> allowedOffices) {
return new ClientData(officeId, null, null, null, null, null, null, joinedDate, null, allowedOffices, null);
return new ClientData(officeId, null, null, null, null, null, null, joinedDate, null, allowedOffices, null, null);
}
public static ClientData templateOnTop(final ClientData clientData, final List<OfficeLookup> allowedOffices) {
@@ -69,7 +89,7 @@ final public class ClientData {
}
final String displayName = buildDisplayNameFrom(firstname, lastname);
return new ClientData(clientData.officeId, clientData.officeName, clientData.id, firstname, lastname, displayName,
clientData.externalId, clientData.joinedDate, clientData.imageKey, allowedOffices, null);
clientData.externalId, clientData.joinedDate, clientData.imageKey, allowedOffices, clientData.currentChange, clientData.allChanges);
}
public static ClientData clientIdentifier(
@@ -81,7 +101,7 @@ final public class ClientData {
final String displayName = buildDisplayNameFrom(firstname, lastname);
return new ClientData(officeId, officeName, id, firstname, lastname, displayName, null, null, null, null, null);
return new ClientData(officeId, officeName, id, firstname, lastname, displayName, null, null, null, null, null, null);
}
public ClientData(
@@ -95,7 +115,8 @@ final public class ClientData {
final LocalDate joinedDate,
final String imageKey,
final List<OfficeLookup> allowedOffices,
final ClientCommand changes) {
final ClientData currentChange,
final Collection<ClientData> allChanges) {
this.officeId = officeId;
this.officeName = officeName;
this.id = id;
@@ -113,9 +134,14 @@ final public class ClientData {
this.externalId = externalId;
this.joinedDate = joinedDate;
this.imageKey = imageKey;
this.imagePresent = (imageKey != null);
if (imageKey != null) {
this.imagePresent = Boolean.TRUE;
} else {
this.imagePresent = null;
}
this.allowedOffices = allowedOffices;
this.changes = changes;
this.currentChange = currentChange;
this.allChanges = allChanges;
}
public String displayName() {
@@ -145,4 +171,8 @@ final public class ClientData {
public Long officeId() {
return this.officeId;
}
public ClientData currentChange() {
return this.currentChange;
}
}
@@ -7,6 +7,7 @@ import java.util.Set;
import org.mifosng.platform.accounting.api.data.ChartOfAccountsData;
import org.mifosng.platform.api.LoanScheduleData;
import org.mifosng.platform.api.commands.ClientCommand;
import org.mifosng.platform.api.data.AdditionalFieldsSetData;
import org.mifosng.platform.api.data.AppUserData;
import org.mifosng.platform.api.data.AuthenticatedUserData;
@@ -497,14 +498,15 @@ public class GoogleGsonPortfolioApiJsonSerializerService implements PortfolioApi
}
@Override
public String serializeClientDataToJson(final boolean prettyPrint,
final Set<String> responseParameters,
final Collection<ClientData> clients) {
public String serializeClientCommandToJson(final ClientCommand command) {
final Gson gsonDeserializer = helper
.createGsonBuilderWithParameterExclusionSerializationStrategy(
CLIENT_DATA_PARAMETERS, prettyPrint, responseParameters);
return helper.serializedJsonFrom(gsonDeserializer,
clients.toArray(new ClientData[clients.size()]));
.createGsonBuilderWithParameterExclusionSerializationStrategy(new HashSet<String>(), false, new HashSet<String>());
return helper.serializedJsonFrom(gsonDeserializer, command);
}
@Override
public String serializeClientDataToJson(final ClientData client) {
return serializeClientDataToJson(false, new HashSet<String>(), client);
}
@Override
@@ -515,6 +517,17 @@ public class GoogleGsonPortfolioApiJsonSerializerService implements PortfolioApi
CLIENT_DATA_PARAMETERS, prettyPrint, responseParameters);
return helper.serializedJsonFrom(gsonDeserializer, client);
}
@Override
public String serializeClientDataToJson(final boolean prettyPrint,
final Set<String> responseParameters,
final Collection<ClientData> clients) {
final Gson gsonDeserializer = helper
.createGsonBuilderWithParameterExclusionSerializationStrategy(
CLIENT_DATA_PARAMETERS, prettyPrint, responseParameters);
return helper.serializedJsonFrom(gsonDeserializer,
clients.toArray(new ClientData[clients.size()]));
}
@Override
public String serializeClientAccountSummaryCollectionDataToJson(
@@ -28,6 +28,7 @@ import org.mifosng.platform.api.commands.SavingAccountCommand;
import org.mifosng.platform.api.commands.SavingProductCommand;
import org.mifosng.platform.api.commands.StaffCommand;
import org.mifosng.platform.api.commands.UserCommand;
import org.mifosng.platform.api.data.ClientData;
public interface PortfolioApiDataConversionService {
@@ -49,7 +50,13 @@ public interface PortfolioApiDataConversionService {
DepositProductCommand convertJsonToDepositProductCommand(Long resourceIdentifier, String json);
ClientCommand convertJsonToClientCommand(Long resourceIdentifier, String json, boolean makerCheckerApproval);
ClientCommand convertApiRequestJsonToClientCommand(Long resourceIdentifier, String json);
ClientCommand convertInternalJsonFormatToClientCommand(Long resourceIdentifier, String json, boolean checkerApproved);
ClientData convertInternalJsonFormatToClientDataChange(Long clientId, String json);
ClientCommand detectChanges(Long resourceId, String baseJson, String workingJson);
GroupCommand convertJsonToGroupCommand(Long resourceIdentifier, String json);
@@ -19,7 +19,6 @@ import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.mifosng.platform.api.commands.AdjustLoanTransactionCommand;
import org.mifosng.platform.api.commands.BranchMoneyTransferCommand;
import org.mifosng.platform.api.commands.LoanReassignmentCommand;
import org.mifosng.platform.api.commands.ChargeCommand;
import org.mifosng.platform.api.commands.ClientCommand;
import org.mifosng.platform.api.commands.ClientIdentifierCommand;
@@ -35,6 +34,7 @@ import org.mifosng.platform.api.commands.GroupCommand;
import org.mifosng.platform.api.commands.LoanApplicationCommand;
import org.mifosng.platform.api.commands.LoanChargeCommand;
import org.mifosng.platform.api.commands.LoanProductCommand;
import org.mifosng.platform.api.commands.LoanReassignmentCommand;
import org.mifosng.platform.api.commands.LoanStateTransitionCommand;
import org.mifosng.platform.api.commands.LoanTransactionCommand;
import org.mifosng.platform.api.commands.NoteCommand;
@@ -46,6 +46,7 @@ import org.mifosng.platform.api.commands.SavingProductCommand;
import org.mifosng.platform.api.commands.StaffCommand;
import org.mifosng.platform.api.commands.UserCommand;
import org.mifosng.platform.api.data.ApiParameterError;
import org.mifosng.platform.api.data.ClientData;
import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
import org.mifosng.platform.infrastructure.api.JsonParserHelper;
import org.mifosng.platform.infrastructure.errorhandling.InvalidJsonException;
@@ -376,7 +377,96 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo
}
@Override
public ClientCommand convertJsonToClientCommand(final Long resourceIdentifier, final String json, final boolean makerCheckerApproval) {
public ClientCommand detectChanges(final Long resourceIdentifier, final String baseJson, final String workingJson) {
final Type typeOfMap = new TypeToken<Map<String, Object>>(){}.getType();
final Map<String, Object> workingVersion = gsonConverter.fromJson(workingJson, typeOfMap);
final Set<String> workingParameters = workingVersion.keySet();
final JsonParser parser = new JsonParser();
final JsonElement baseElement = parser.parse(baseJson);
final JsonElement workingElement = parser.parse(workingJson);
final JsonParserHelper helper = new JsonParserHelper();
final Set<String> ignoreParameters = new HashSet<String>();
final Set<String> parametersPassedInRequest = new HashSet<String>();
Long officeId = null;
String externalId = null;
String firstname = null;
String lastname = null;
String clientOrBusinessName = null;
LocalDate joiningDate = null;
for (final String parameter : workingParameters) {
final String officeIdParameterName = "officeId";
if (officeIdParameterName.equalsIgnoreCase(parameter)) {
final Long baseOfficeId = helper.extractLongNamed(officeIdParameterName, baseElement, ignoreParameters);
final Long workingOfficeId = helper.extractLongNamed(officeIdParameterName, workingElement, ignoreParameters);
if (!workingOfficeId.equals(baseOfficeId)) {
officeId = workingOfficeId;
parametersPassedInRequest.add(officeIdParameterName);
}
}
final String externalIdParamName = "externalId";
if (externalIdParamName.equalsIgnoreCase(parameter)) {
final String baseExternalId = helper.extractStringNamed(externalIdParamName, baseElement, ignoreParameters);
final String workingExternalId = helper.extractStringNamed(externalIdParamName, workingElement, ignoreParameters);
if (!baseExternalId.equals(workingExternalId)) {
externalId = workingExternalId;
parametersPassedInRequest.add(externalIdParamName);
}
}
final String firstnameParamName = "firstname";
if (firstnameParamName.equalsIgnoreCase(parameter)) {
final String baseValue = helper.extractStringNamed(firstnameParamName, baseElement, ignoreParameters);
final String workingCopyValue = helper.extractStringNamed(firstnameParamName, workingElement, ignoreParameters);
if (!baseValue.equals(workingCopyValue)) {
firstname = workingCopyValue;
parametersPassedInRequest.add(firstnameParamName);
}
}
final String lastnameParamName = "lastname";
if (lastnameParamName.equalsIgnoreCase(parameter)) {
final String baseValue = helper.extractStringNamed(lastnameParamName, baseElement, ignoreParameters);
final String workingCopyValue = helper.extractStringNamed(lastnameParamName, workingElement, ignoreParameters);
if (!baseValue.equals(workingCopyValue)) {
lastname = workingCopyValue;
parametersPassedInRequest.add(lastnameParamName);
}
}
final String clientOrBusinessNameParamName = "clientOrBusinessName";
if (clientOrBusinessNameParamName.equalsIgnoreCase(parameter)) {
final String baseValue = helper.extractStringNamed(clientOrBusinessNameParamName, baseElement, ignoreParameters);
final String workingCopyValue = helper.extractStringNamed(clientOrBusinessNameParamName, workingElement, ignoreParameters);
if (!baseValue.equals(workingCopyValue)) {
clientOrBusinessName = workingCopyValue;
parametersPassedInRequest.add(clientOrBusinessNameParamName);
}
}
final String joinedDateParamName = "joinedDate";
if (joinedDateParamName.equalsIgnoreCase(parameter)) {
final LocalDate baseValue = helper.extractLocalDateAsArrayNamed(joinedDateParamName, baseElement, ignoreParameters);
final LocalDate workingCopyValue = helper.extractLocalDateAsArrayNamed(joinedDateParamName, workingElement, ignoreParameters);
if (!baseValue.isEqual(workingCopyValue)) {
joiningDate = workingCopyValue;
parametersPassedInRequest.add(joinedDateParamName);
}
}
}
return new ClientCommand(parametersPassedInRequest, resourceIdentifier, externalId, firstname, lastname, clientOrBusinessName, officeId, joiningDate, false);
}
@Override
public ClientCommand convertApiRequestJsonToClientCommand(final Long resourceIdentifier, final String json) {
if (StringUtils.isBlank(json)) {
throw new InvalidJsonException();
}
@@ -385,7 +475,7 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo
final Map<String, String> requestMap = gsonConverter.fromJson(json, typeOfMap);
final Set<String> supportedParams = new HashSet<String>(
Arrays.asList("externalId", "firstname", "lastname", "clientOrBusinessName", "officeId", "joiningDate", "locale", "dateFormat")
Arrays.asList("id", "externalId", "firstname", "lastname", "clientOrBusinessName", "officeId", "joiningDate", "locale", "dateFormat")
);
checkForUnsupportedParameters(requestMap, supportedParams);
@@ -402,7 +492,46 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo
final String clientOrBusinessName = helper.extractStringNamed("clientOrBusinessName", element, parametersPassedInRequest);
final LocalDate joiningDate = helper.extractLocalDateNamed("joiningDate", element, parametersPassedInRequest);
return new ClientCommand(parametersPassedInRequest, resourceIdentifier, externalId, firstname, lastname, clientOrBusinessName, officeId, joiningDate, makerCheckerApproval);
return new ClientCommand(parametersPassedInRequest, resourceIdentifier, externalId, firstname, lastname, clientOrBusinessName, officeId, joiningDate, false);
}
@Override
public ClientCommand convertInternalJsonFormatToClientCommand(final Long resourceIdentifier, final String json, final boolean checkerApproved) {
if (StringUtils.isBlank(json)) {
throw new InvalidJsonException();
}
final Type typeOfMap = new TypeToken<Map<String, Object>>(){}.getType();
final Map<String, Object> requestMap = gsonConverter.fromJson(json, typeOfMap);
final Set<String> supportedParams = new HashSet<String>(
Arrays.asList("id", "externalId", "firstname", "lastname", "clientOrBusinessName", "officeId", "joiningDate")
);
checkForUnsupportedParameters(requestMap, supportedParams);
final JsonParser parser = new JsonParser();
final JsonElement element = parser.parse(json);
final JsonParserHelper helper = new JsonParserHelper();
final Set<String> parametersPassedInRequest = new HashSet<String>();
final Long officeId = helper.extractLongNamed("officeId", element, parametersPassedInRequest);
final String externalId = helper.extractStringNamed("externalId", element, parametersPassedInRequest);
final String firstname = helper.extractStringNamed("firstname", element, parametersPassedInRequest);
final String lastname = helper.extractStringNamed("lastname", element, parametersPassedInRequest);
final String clientOrBusinessName = helper.extractStringNamed("clientOrBusinessName", element, parametersPassedInRequest);
final LocalDate joiningDate = helper.extractLocalDateAsArrayNamed("joiningDate", element, parametersPassedInRequest);
return new ClientCommand(parametersPassedInRequest, resourceIdentifier, externalId, firstname, lastname, clientOrBusinessName, officeId, joiningDate, checkerApproved);
}
@Override
public ClientData convertInternalJsonFormatToClientDataChange(final Long resourceIdentifier, final String json) {
final ClientCommand command = convertInternalJsonFormatToClientCommand(resourceIdentifier, json, false);
return ClientData.dataChangeInstance(resourceIdentifier, command.getOfficeId(), command.getExternalId(),
command.getFirstname(), command.getLastname(), command.getClientOrBusinessName(), command.getJoiningDate());
}
@Override
@@ -5,6 +5,7 @@ import java.util.Set;
import org.mifosng.platform.accounting.api.data.ChartOfAccountsData;
import org.mifosng.platform.api.LoanScheduleData;
import org.mifosng.platform.api.commands.ClientCommand;
import org.mifosng.platform.api.data.AdditionalFieldsSetData;
import org.mifosng.platform.api.data.AppUserData;
import org.mifosng.platform.api.data.AuthenticatedUserData;
@@ -91,10 +92,14 @@ public interface PortfolioApiJsonSerializerService {
String serializeDepositAccountDataToJson(boolean prettyPrint, Set<String> responseParameters, DepositAccountData account);
String serializeClientDataToJson(boolean prettyPrint, Set<String> responseParameters, Collection<ClientData> clients);
String serializeClientCommandToJson(ClientCommand command);
String serializeClientDataToJson(ClientData clientData);
String serializeClientDataToJson(boolean prettyPrint, Set<String> responseParameters, ClientData clientData);
String serializeClientDataToJson(boolean prettyPrint, Set<String> responseParameters, Collection<ClientData> clients);
String serializeClientAccountSummaryCollectionDataToJson(boolean prettyPrint, Set<String> responseParameters, ClientAccountSummaryCollectionData clientAccount);
String serializeGroupAccountSummaryCollectionDataToJson(boolean prettyPrint, Set<String> responseParameters, GroupAccountSummaryCollectionData groupAccount);
@@ -157,7 +157,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
final String officeName = rs.getString("officeName");
return new ClientData(officeId, officeName, id, firstname,
lastname, displayName, externalId, joinedDate,imageKey, null, null);
lastname, displayName, externalId, joinedDate,imageKey, null, null, null);
}
}
@@ -18,6 +18,7 @@ import org.mifosng.platform.api.data.ApiParameterError;
import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
import org.springframework.format.number.NumberFormatter;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
@@ -176,6 +177,32 @@ public class JsonParserHelper {
}
return clientApplicationLocale;
}
/**
* Used with the local date is in array format
*/
public LocalDate extractLocalDateAsArrayNamed(final String parameterName, final JsonElement element, final Set<String> parametersPassedInCommand) {
LocalDate value = null;
if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
if (object.has(parameterName) && object.get(parameterName).isJsonArray()) {
parametersPassedInCommand.add(parameterName);
final JsonArray dateArray = object.get(parameterName).getAsJsonArray();
Integer year = dateArray.get(0).getAsInt();
Integer month = dateArray.get(1).getAsInt();
Integer day = dateArray.get(2).getAsInt();
value = new LocalDate().withYearOfEra(year).withMonthOfYear(month).withDayOfMonth(day);
}
}
return value;
}
public LocalDate extractLocalDateNamed(
final String parameterName,
@@ -56,10 +56,9 @@ public class CommandSource extends AbstractPersistable<Long> {
final String apiOperation,
final String resource,
final Long resourceId,
final String jsonRequestBody,
final AppUser maker,
final LocalDate madeOnDate) {
return new CommandSource(apiOperation, resource, resourceId, jsonRequestBody, maker, madeOnDate);
return new CommandSource(apiOperation, resource, resourceId, maker, madeOnDate);
}
protected CommandSource() {
@@ -70,13 +69,11 @@ public class CommandSource extends AbstractPersistable<Long> {
final String apiOperation,
final String resource,
final Long resourceId,
final String jsonRequestBody,
final AppUser maker,
final LocalDate madeOnDate) {
this.apiOperation = StringUtils.defaultIfEmpty(apiOperation, null);
this.resource = StringUtils.defaultIfEmpty(resource, null);
this.resourceId = resourceId;
this.commandAsJson = StringUtils.defaultIfEmpty(jsonRequestBody, null);
this.maker = maker;
this.madeOnDate = madeOnDate.toDate();
}
@@ -90,6 +87,10 @@ public class CommandSource extends AbstractPersistable<Long> {
this.resourceId = resourceId;
}
public void updateJsonTo(final String json) {
this.commandAsJson = json;
}
public Long resourceId() {
return this.resourceId;
}
@@ -2,8 +2,11 @@ package org.mifosng.platform.makerchecker.service;
import org.joda.time.LocalDate;
import org.mifosng.platform.api.commands.ClientCommand;
import org.mifosng.platform.api.data.ClientData;
import org.mifosng.platform.api.data.EntityIdentifier;
import org.mifosng.platform.api.infrastructure.PortfolioApiDataConversionService;
import org.mifosng.platform.api.infrastructure.PortfolioApiJsonSerializerService;
import org.mifosng.platform.client.service.ClientReadPlatformService;
import org.mifosng.platform.client.service.ClientWritePlatformService;
import org.mifosng.platform.client.service.RollbackTransactionAsCommandIsNotApprovedByCheckerException;
import org.mifosng.platform.makerchecker.domain.CommandSource;
@@ -14,71 +17,91 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
*
*/
@Service
public class PortfolioCommandSourceWriteServiceImpl implements PortfolioCommandSourceWritePlatformService {
private final PlatformSecurityContext context;
private final CommandSourceRepository commandSourceRepository;
private final PortfolioApiDataConversionService apiDataConversionService;
private final PortfolioApiJsonSerializerService apiJsonSerializerService;
private final ClientWritePlatformService clientWritePlatformService;
private final ClientReadPlatformService clientReadPlatformService;
@Autowired
public PortfolioCommandSourceWriteServiceImpl(final PlatformSecurityContext context, final CommandSourceRepository makerCheckerRepository,
final PortfolioApiDataConversionService apiDataConversionService,
final ClientWritePlatformService clientWritePlatformService) {
final PortfolioApiJsonSerializerService apiJsonSerializerService,
final ClientWritePlatformService clientWritePlatformService,
final ClientReadPlatformService clientReadPlatformService) {
this.context = context;
this.commandSourceRepository = makerCheckerRepository;
this.apiDataConversionService = apiDataConversionService;
this.apiJsonSerializerService = apiJsonSerializerService;
this.clientWritePlatformService = clientWritePlatformService;
this.clientReadPlatformService = clientReadPlatformService;
}
// NOT TRANSACTIONAL BY DESIGN FOR NOW
@Override
public EntityIdentifier logCommandSource(final String taskOperation, final String taskEntity, final Long entityId, final String taskJson) {
public EntityIdentifier logCommandSource(final String apiOperation, final String resource, final Long resourceId, final String jsonRequestBody) {
final AppUser maker = context.authenticatedUser();
final LocalDate asToday = new LocalDate();
final CommandSource entity = CommandSource.createdBy(taskOperation, taskEntity, entityId, taskJson, maker, asToday);
final CommandSource commandSource = CommandSource.createdBy(apiOperation, resource, resourceId, maker, asToday);
final boolean makerCheckerApproval = false;
Long resourceId = null;
if (entity.isClientResource()) {
final ClientCommand command = this.apiDataConversionService.convertJsonToClientCommand(entityId, entity.json(), makerCheckerApproval);
if (entity.isCreate()) {
Long newResourceId = null;
if (commandSource.isClientResource()) {
// translate incoming api request json into java object catering for local and dateFormat parts of api
final ClientCommand command = this.apiDataConversionService.convertApiRequestJsonToClientCommand(resourceId, jsonRequestBody);
// produce serialized json of internal java object representation for persistence.
final String internalCommandSerializedAsJson = this.apiJsonSerializerService.serializeClientCommandToJson(command);
commandSource.updateJsonTo(internalCommandSerializedAsJson);
if (commandSource.isCreate()) {
try {
resourceId = this.clientWritePlatformService.createClient(command);
entity.markAsChecked(maker, asToday);
entity.updateResourceId(resourceId);
newResourceId = this.clientWritePlatformService.createClient(command);
commandSource.markAsChecked(maker, asToday);
commandSource.updateResourceId(newResourceId);
} catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) {
// swallow this rollback transaction by design
}
} else if (entity.isUpdate()) {
} else if (commandSource.isUpdate()) {
try {
EntityIdentifier result = this.clientWritePlatformService.updateClientDetails(command);
resourceId = result.getEntityId();
entity.markAsChecked(maker, asToday);
// useful to employ change detection on update scenario to only store what details have changed
final ClientData originalClient = this.clientReadPlatformService.retrieveIndividualClient(resourceId);
final ClientData changedClient = this.apiDataConversionService.convertInternalJsonFormatToClientDataChange(resourceId, internalCommandSerializedAsJson);
final String baseJson = this.apiJsonSerializerService.serializeClientDataToJson(originalClient);
final String workingJson = this.apiJsonSerializerService.serializeClientDataToJson(changedClient);
final ClientCommand changesOnly = this.apiDataConversionService.detectChanges(resourceId, baseJson, workingJson);
final String changesOnlyJson = this.apiJsonSerializerService.serializeClientCommandToJson(changesOnly);
commandSource.updateJsonTo(changesOnlyJson);
EntityIdentifier result = this.clientWritePlatformService.updateClientDetails(changesOnly);
newResourceId = result.getEntityId();
commandSource.markAsChecked(maker, asToday);
} catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) {
// swallow this rollback transaction by design
}
} else if (entity.isDelete()) {
} else if (commandSource.isDelete()) {
try {
EntityIdentifier result = this.clientWritePlatformService.deleteClient(command);
resourceId = result.getEntityId();
entity.markAsChecked(maker, asToday);
newResourceId = result.getEntityId();
commandSource.markAsChecked(maker, asToday);
} catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) {
// swallow this rollback transaction by design
}
}
}
commandSourceRepository.save(entity);
commandSourceRepository.save(commandSource);
return EntityIdentifier.makerChecker(resourceId, entity.getId());
return EntityIdentifier.makerChecker(newResourceId, commandSource.getId());
}
@Transactional
@@ -92,7 +115,7 @@ public class PortfolioCommandSourceWriteServiceImpl implements PortfolioCommandS
Long resourceId = null;
if (entity.isClientResource()) {
final ClientCommand command = this.apiDataConversionService.convertJsonToClientCommand(entity.resourceId(), entity.json(), true);
final ClientCommand command = this.apiDataConversionService.convertInternalJsonFormatToClientCommand(entity.resourceId(), entity.json(), true);
if (entity.isCreate()) {
resourceId = this.clientWritePlatformService.createClient(command);
} else if (entity.isUpdate()) {
@@ -10,4 +10,6 @@ public interface PortfolioCommandsReadPlatformService {
CommandSourceData retrieveById(Long id);
Collection<CommandSourceData> retrieveUnprocessChangesByResourceId(String apiResource, Long clientId);
}
@@ -69,4 +69,13 @@ public class PortfolioCommandsReadPlatformServiceImpl implements PortfolioComman
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] {id});
}
@Override
public Collection<CommandSourceData> retrieveUnprocessChangesByResourceId(final String apiResource, final Long resourceId) {
final CommandSourceMapper rm = new CommandSourceMapper();
final String sql = "select " + rm.schema() + " where mc.api_resource like ? and mc.resource_id = ? and mc.checker_id is null order by mc.made_on_date DESC, mc.api_operation ASC";
return this.jdbcTemplate.query(sql, rm, new Object[] {apiResource, resourceId});
}
}
@@ -12,6 +12,6 @@ public interface CodeWritePlatformService {
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'ORGANISATION_ADMINISTRATION_SUPER_USER', 'UPDATE_CODE)")
Long updateCode(final CodeCommand command);
@PreAuthorize(value = "hasAnyRole('ORGANISATION_ADMINISTRATION_SUPER_USER_ROLE')")
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'ORGANISATION_ADMINISTRATION_SUPER_USER_ROLE', 'DELETE_CODE')")
EntityIdentifier deleteCode(Long codeId);
}