HOR-6 "No se puede reasignar un caso cuando se..." SOLVED

Issue:
    No se puede reasignar un caso cuando se tiene asignados a la tarea 40000 usuarios
Cause:
    El metodo "Cases::getUsersToReassign()" no es optimo
Solution:
    - Se a creado el metodo "\ProcessMaker\BusinessModel\Cases::getUsersToReassign()", el cual esta optimizado (backend)
    - Se hizo un refactor de las interfaces (frontend)
This commit is contained in:
Victor Saisa Lopez
2016-01-11 17:36:00 -04:00
parent 591d4f59c4
commit b58bdc7af1
6 changed files with 508 additions and 130 deletions

View File

@@ -518,14 +518,33 @@ class Ajax
print G::json_encode( $response );
die();
}
G::LoadClass( 'tasks' );
$task = new Task();
$tasks = $task->load($_SESSION['TASK']);
$case = new Cases();
$result = new stdclass();
$result->data = $case->getUsersToReassign($_SESSION['TASK'], $_SESSION['USER_LOGGED'], $tasks['PRO_UID']);
print G::json_encode($result);
$taskUid = $_SESSION['TASK'];
$search = $_POST['search'];
$pageSize = $_POST['pageSize'];
$sortField = (isset($_POST['sort']))? $_POST['sort'] : '';
$sortDir = (isset($_POST['dir']))? $_POST['dir'] : '';
$start = (isset($_POST['start']))? $_POST['start'] : 0;
$limit = (isset($_POST['limit']))? $_POST['limit'] : $pageSize;
$response = [];
try {
$case = new \ProcessMaker\BusinessModel\Cases();
$result = $case->getUsersToReassign($_SESSION['USER_LOGGED'], $taskUid, ['filter' => $search], $sortField, $sortDir, $start, $limit);
$response['status'] = 'OK';
$response['success'] = true;
$response['resultTotal'] = $result['total'];
$response['resultRoot'] = $result['data'];
} catch (Exception $e) {
$response['status'] = 'ERROR';
$response['message'] = $e->getMessage();
}
echo G::json_encode($response);
}
public function reassignCase()

View File

@@ -85,7 +85,7 @@ if ($actionAjax == "userValues") {
$cUsers->addSelectColumn(UsersPeer::USR_FIRSTNAME);
$cUsers->addSelectColumn(UsersPeer::USR_LASTNAME);
$cUsers->add( UsersPeer::USR_STATUS, 'CLOSED', Criteria::NOT_EQUAL );
if (!is_null($query)) {
$filters = $cUsers->getNewCriterion( UsersPeer::USR_FIRSTNAME, '%'.$query.'%', Criteria::LIKE )->addOr(
$cUsers->getNewCriterion( UsersPeer::USR_LASTNAME, '%'.$query.'%', Criteria::LIKE )->addOr(
@@ -217,14 +217,32 @@ if ($actionAjax == "processListExtJs") {
}
if ($actionAjax == "getUsersToReassign") {
$_SESSION['TASK'] = $_REQUEST['TAS_UID'];
$case = new Cases();
G::LoadClass( 'tasks' );
$task = new Task();
$tasks = $task->load($_SESSION['TASK']);
$result = new stdclass();
$result->data = $case->getUsersToReassign( $_SESSION['TASK'], $_SESSION['USER_LOGGED'], $tasks['PRO_UID'] );
print G::json_encode( $result );
$taskUid = $_POST['taskUid'];
$search = $_POST['search'];
$pageSize = $_POST['pageSize'];
$sortField = (isset($_POST['sort']))? $_POST['sort'] : '';
$sortDir = (isset($_POST['dir']))? $_POST['dir'] : '';
$start = (isset($_POST['start']))? $_POST['start'] : 0;
$limit = (isset($_POST['limit']))? $_POST['limit'] : $pageSize;
$response = [];
try {
$case = new \ProcessMaker\BusinessModel\Cases();
$result = $case->getUsersToReassign($_SESSION['USER_LOGGED'], $taskUid, ['filter' => $search], $sortField, $sortDir, $start, $limit);
$response['status'] = 'OK';
$response['success'] = true;
$response['resultTotal'] = $result['total'];
$response['resultRoot'] = $result['data'];
} catch (Exception $e) {
$response['status'] = 'ERROR';
$response['message'] = $e->getMessage();
}
echo G::json_encode($response);
}
if ($actionAjax == 'reassignCase') {

View File

@@ -2477,4 +2477,196 @@ class Cases
throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage()));
}
}
/**
* Get Users to reassign
*
* @param string $userUid Unique id of User (User logged)
* @param string $taskUid Unique id of Task
* @param array $arrayFilterData Data of the filters
* @param string $sortField Field name to sort
* @param string $sortDir Direction of sorting (ASC, DESC)
* @param int $start Start
* @param int $limit Limit
*
* @return array Return Users to reassign
*/
public function getUsersToReassign($userUid, $taskUid, $arrayFilterData = null, $sortField = null, $sortDir = null, $start = null, $limit = null)
{
try {
$arrayUser = [];
$numRecTotal = 0;
//Set variables
$task = \TaskPeer::retrieveByPK($taskUid);
$processUid = $task->getProUid();
$user = new \ProcessMaker\BusinessModel\User();
$task = new \Tasks();
$group = new \Groups();
//Set variables
$filterName = 'filter';
if (!is_null($arrayFilterData) && is_array($arrayFilterData) && isset($arrayFilterData['filter'])) {
$arrayAux = [
'' => 'filter',
'LEFT' => 'lfilter',
'RIGHT' => 'rfilter'
];
$filterName = $arrayAux[(isset($arrayFilterData['filterOption']))? $arrayFilterData['filterOption'] : ''];
}
//Get data
if (!is_null($limit) && $limit . '' == '0') {
//Return
return [
'total' => $numRecTotal,
'start' => (int)((!is_null($start))? $start : 0),
'limit' => (int)((!is_null($limit))? $limit : 0),
$filterName => (!is_null($arrayFilterData) && is_array($arrayFilterData) && isset($arrayFilterData['filter']))? $arrayFilterData['filter'] : '',
'data' => $arrayUser
];
}
//Set variables
$processSupervisor = new \ProcessMaker\BusinessModel\ProcessSupervisor();
$arrayResult = $processSupervisor->getProcessSupervisors($processUid, 'ASSIGNED', null, null, null, 'group');
$arrayGroupUid = array_merge(
array_map(function ($value) { return $value['GRP_UID']; }, $task->getGroupsOfTask($taskUid, 1)), //Groups
array_map(function ($value) { return $value['GRP_UID']; }, $task->getGroupsOfTask($taskUid, 2)), //AdHoc Groups
array_map(function ($value) { return $value['grp_uid']; }, $arrayResult['data']) //ProcessSupervisor Groups
);
$sqlTaskUser = '
SELECT ' . \TaskUserPeer::USR_UID . '
FROM ' . \TaskUserPeer::TABLE_NAME . '
WHERE ' . \TaskUserPeer::TAS_UID . ' = \'%s\' AND
' . \TaskUserPeer::TU_TYPE . ' IN (1, 2) AND
' . \TaskUserPeer::TU_RELATION . ' = 1
';
$sqlGroupUser = '
SELECT ' . \GroupUserPeer::USR_UID . '
FROM ' . \GroupUserPeer::TABLE_NAME . '
WHERE ' . \GroupUserPeer::GRP_UID . ' IN (%s)
';
$sqlProcessSupervisor = '
SELECT ' . \ProcessUserPeer::USR_UID . '
FROM ' . \ProcessUserPeer::TABLE_NAME . '
WHERE ' . \ProcessUserPeer::PRO_UID . ' = \'%s\' AND
' . \ProcessUserPeer::PU_TYPE . ' = \'%s\'
';
$sqlUserToReassign = '(' . sprintf($sqlTaskUser, $taskUid) . ')';
if (!empty($arrayGroupUid)) {
$sqlUserToReassign .= ' UNION (' . sprintf($sqlGroupUser, '\'' . implode('\', \'', $arrayGroupUid) . '\'') . ')';
}
$sqlUserToReassign .= ' UNION (' . sprintf($sqlProcessSupervisor, $processUid, 'SUPERVISOR') . ')';
//Query
$criteria = new \Criteria('workflow');
$criteria->addSelectColumn(\UsersPeer::USR_UID);
$criteria->addSelectColumn(\UsersPeer::USR_USERNAME);
$criteria->addSelectColumn(\UsersPeer::USR_FIRSTNAME);
$criteria->addSelectColumn(\UsersPeer::USR_LASTNAME);
$criteria->addAlias('USER_TO_REASSIGN', '(' . $sqlUserToReassign . ')');
$criteria->addJoin(\UsersPeer::USR_UID, 'USER_TO_REASSIGN.USR_UID', \Criteria::INNER_JOIN);
if (!is_null($arrayFilterData) && is_array($arrayFilterData) && isset($arrayFilterData['filter']) && trim($arrayFilterData['filter']) != '') {
$arraySearch = [
'' => '%' . $arrayFilterData['filter'] . '%',
'LEFT' => $arrayFilterData['filter'] . '%',
'RIGHT' => '%' . $arrayFilterData['filter']
];
$search = $arraySearch[(isset($arrayFilterData['filterOption']))? $arrayFilterData['filterOption'] : ''];
$criteria->add(
$criteria->getNewCriterion(\UsersPeer::USR_USERNAME, $search, \Criteria::LIKE)->addOr(
$criteria->getNewCriterion(\UsersPeer::USR_FIRSTNAME, $search, \Criteria::LIKE))->addOr(
$criteria->getNewCriterion(\UsersPeer::USR_LASTNAME, $search, \Criteria::LIKE))
);
}
$criteria->add(\UsersPeer::USR_STATUS, 'ACTIVE', \Criteria::EQUAL);
if (!$user->checkPermission($userUid, 'PM_SUPERVISOR')) {
$criteria->add(\UsersPeer::USR_UID, $userUid, \Criteria::NOT_EQUAL);
}
//Number records total
$criteriaCount = clone $criteria;
$criteriaCount->clearSelectColumns();
$criteriaCount->addSelectColumn('COUNT(' . \UsersPeer::USR_UID . ') AS NUM_REC');
$rsCriteriaCount = \UsersPeer::doSelectRS($criteriaCount);
$rsCriteriaCount->setFetchmode(\ResultSet::FETCHMODE_ASSOC);
$result = $rsCriteriaCount->next();
$row = $rsCriteriaCount->getRow();
$numRecTotal = (int)($row['NUM_REC']);
//Query
if (!is_null($sortField) && trim($sortField) != '') {
$sortField = strtoupper($sortField);
if (in_array(\UsersPeer::TABLE_NAME . '.' . $sortField, $criteria->getSelectColumns())) {
$sortField = \UsersPeer::TABLE_NAME . '.' . $sortField;
} else {
$sortField = \UsersPeer::USR_FIRSTNAME;
}
} else {
$sortField = \UsersPeer::USR_FIRSTNAME;
}
if (!is_null($sortDir) && trim($sortDir) != '' && strtoupper($sortDir) == 'DESC') {
$criteria->addDescendingOrderByColumn($sortField);
} else {
$criteria->addAscendingOrderByColumn($sortField);
}
if (!is_null($start)) {
$criteria->setOffset((int)($start));
}
if (!is_null($limit)) {
$criteria->setLimit((int)($limit));
}
$rsCriteria = \UsersPeer::doSelectRS($criteria);
$rsCriteria->setFetchmode(\ResultSet::FETCHMODE_ASSOC);
while ($rsCriteria->next()) {
$row = $rsCriteria->getRow();
$arrayUser[] = $row;
}
//Return
return [
'total' => $numRecTotal,
'start' => (int)((!is_null($start))? $start : 0),
'limit' => (int)((!is_null($limit))? $limit : 0),
$filterName => (!is_null($arrayFilterData) && is_array($arrayFilterData) && isset($arrayFilterData['filter']))? $arrayFilterData['filter'] : '',
'data' => $arrayUser
];
} catch (\Exception $e) {
throw $e;
}
}
}

View File

@@ -2,7 +2,6 @@
namespace ProcessMaker\BusinessModel;
use \G;
use Luracast\Restler\User;
class ProcessSupervisor
{

View File

@@ -1460,7 +1460,8 @@ Ext.onReady ( function() {
var APP_UID = optionMenuReassignGlobal.APP_UID;
var DEL_INDEX = optionMenuReassignGlobal.DEL_INDEX;
var rowSelected = Ext.getCmp('reassignGrid').getSelectionModel().getSelected();
var rowSelected = Ext.getCmp("grdpnlUsersToReassign").getSelectionModel().getSelected();
if( rowSelected ) {
PMExt.confirm(_('ID_CONFIRM'), _('ID_REASSIGN_CONFIRM'), function(){
var loadMask = new Ext.LoadMask(winReassignInCasesList.getEl(), {msg: _('ID_PROCESSING')});
@@ -1500,6 +1501,8 @@ Ext.onReady ( function() {
//optionMenuPause.setMinValue('2010-11-04');
var loadMaskUsersToReassign = new Ext.LoadMask(Ext.getBody(), {msg: _("ID_LOADING_GRID")});
var optionMenuReassignGlobal = {};
optionMenuReassignGlobal.APP_UID = "";
optionMenuReassignGlobal.DEL_INDEX = "";
@@ -1548,83 +1551,156 @@ Ext.onReady ( function() {
optionMenuReassignGlobal.APP_UID = APP_UID;
optionMenuReassignGlobal.DEL_INDEX = DEL_INDEX;
if( rowSelected ){
var store = new Ext.data.Store( {
autoLoad: true,
proxy : new Ext.data.HttpProxy({
url: 'casesList_Ajax?actionAjax=getUsersToReassign&TAS_UID='+TAS_UID
//Variables
var pageSizeUsersToReassign = 10;
//Stores
var storeUsersToReassign = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({
url: "casesList_Ajax",
method: "POST"
}),
reader : new Ext.data.JsonReader( {
root: 'data',
fields : [
{name : 'USR_UID'},
{name : 'USR_USERNAME'},
{name : 'USR_FIRSTNAME'},
{name : 'USR_LASTNAME'}
reader: new Ext.data.JsonReader({
root: "resultRoot",
totalProperty: "resultTotal",
fields: [
{name : "USR_UID"},
{name : "USR_USERNAME"},
{name : "USR_FIRSTNAME"},
{name : "USR_LASTNAME"}
]
})
}),
remoteSort: true,
listeners: {
beforeload: function (store)
{
winReassignInCasesList.setDisabled(true);
loadMaskUsersToReassign.show();
this.baseParams = {
actionAjax: "getUsersToReassign",
taskUid: TAS_UID,
search: Ext.getCmp("txtSearchUsersToReassign").getValue(),
pageSize: pageSizeUsersToReassign
};
},
load: function (store, record, opt)
{
winReassignInCasesList.setDisabled(false);
loadMaskUsersToReassign.hide();
}
}
});
var grid = new Ext.grid.GridPanel( {
id: 'reassignGrid',
height:300,
width:'300',
title : '',
stateful : true,
stateId : 'gridCasesList',
//Components
var pagingUsersToReassign = new Ext.PagingToolbar({
id: "pagingUsersToReassign",
pageSize: pageSizeUsersToReassign,
store: storeUsersToReassign,
displayInfo: true,
displayMsg: _("ID_DISPLAY_ITEMS"),
emptyMsg: _("ID_NO_RECORDS_FOUND")
});
var cmodelUsersToReassign = new Ext.grid.ColumnModel({
defaults: {
width: 200,
sortable: true
},
columns: [
{id: "USR_UID", dataIndex: "USR_UID", hidden: true, hideable: false},
{id: "USR_FIRSTNAME", dataIndex: "USR_FIRSTNAME", header: _("ID_FIRSTNAME"), width: 300},
{id: "USR_LASTNAME", dataIndex: "USR_LASTNAME", header: _("ID_LASTNAME"), width: 300}
]
});
var smodelUsersToReassign = new Ext.grid.RowSelectionModel({
singleSelect: true
});
var grdpnlUsersToReassign = new Ext.grid.GridPanel({
id: "grdpnlUsersToReassign",
store: storeUsersToReassign,
colModel: cmodelUsersToReassign,
selModel: smodelUsersToReassign,
columnLines: true,
viewConfig: {forceFit: true},
enableColumnResize: true,
enableHdMenu: true,
frame:false,
cls : 'grid_with_checkbox',
columnLines: true,
viewConfig: {
forceFit:true
},
cm: new Ext.grid.ColumnModel({
defaults: {
width: 200,
sortable: true
},
columns: [
{id:'USR_UID', dataIndex: 'USR_UID', hidden:true, hideable:false},
{header: _('ID_FIRSTNAME'), dataIndex: 'USR_FIRSTNAME', width: 300},
{header: _('ID_LASTNAME'), dataIndex: 'USR_LASTNAME', width: 300}
]
}),
store: store,
tbar:[
tbar: [
{
text:_('ID_REASSIGN'),
iconCls: 'ICON_CASES_TO_REASSIGN',
handler: function(){
//Actions.reassignCase
text: _("ID_REASSIGN"),
iconCls: "ICON_CASES_TO_REASSIGN",
handler: function ()
{
reassingCaseToUser();
}
},
"->",
{
xtype: "textfield",
id: "txtSearchUsersToReassign",
emptyText: _("ID_EMPTY_SEARCH"),
width: 150,
allowBlank: true,
listeners: {
specialkey: function (f, e)
{
if (e.getKey() == e.ENTER) {
pagingUsersToReassign.moveFirst();
}
}
}
},
{
text: "X",
ctCls: "pm_search_x_button",
handler: function ()
{
Ext.getCmp("txtSearchUsersToReassign").reset();
}
},
{
text: _("ID_SEARCH"),
handler: function ()
{
pagingUsersToReassign.moveFirst();
}
}
],
listeners: {
//rowdblclick: openCase,
render: function(){
this.loadMask = new Ext.LoadMask(this.body, {msg:_('ID_LOADING')});
this.ownerCt.doLayout();
}
}
bbar: pagingUsersToReassign,
title: ""
});
winReassignInCasesList = new Ext.Window({
title: '',
width: 450,
height: 280,
height: 350,
layout:'fit',
autoScroll:true,
modal: true,
maximizable: false,
items: [grid]
items: [grdpnlUsersToReassign]
});
winReassignInCasesList.show();
grdpnlUsersToReassign.store.load();
}
}
},

View File

@@ -926,82 +926,153 @@ Ext.onReady(function(){
Actions.getUsersToReassign = function()
{
var store = new Ext.data.Store( {
autoLoad: true,
proxy : new Ext.data.HttpProxy({
url: 'ajaxListener?action=getUsersToReassign'
}),
reader : new Ext.data.JsonReader( {
root: 'data',
fields : [
{name : 'USR_UID'},
{name : 'USR_USERNAME'},
{name : 'USR_FIRSTNAME'},
{name : 'USR_LASTNAME'}
]
})
var loadMaskUsersToReassign = new Ext.LoadMask(Ext.getBody(), {msg: _("ID_LOADING_GRID")});
//Variables
var pageSizeUsersToReassign = 10;
//Stores
var storeUsersToReassign = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({
url: "ajaxListener",
method: "POST"
}),
reader: new Ext.data.JsonReader({
root: "resultRoot",
totalProperty: "resultTotal",
fields: [
{name : "USR_UID"},
{name : "USR_USERNAME"},
{name : "USR_FIRSTNAME"},
{name : "USR_LASTNAME"}
]
}),
remoteSort: true,
listeners: {
beforeload: function (store)
{
winReassignInCasesList.setDisabled(true);
loadMaskUsersToReassign.show();
this.baseParams = {
action: "getUsersToReassign",
search: Ext.getCmp("txtSearchUsersToReassign").getValue(),
pageSize: pageSizeUsersToReassign
};
},
load: function (store, record, opt)
{
winReassignInCasesList.setDisabled(false);
loadMaskUsersToReassign.hide();
}
}
});
var grid = new Ext.grid.GridPanel( {
id: 'reassignGrid',
height:300,
width:'300',
title : '',
stateful : true,
stateId : 'gridCasesOpen',
enableColumnResize: true,
enableHdMenu: true,
frame:false,
cls : 'grid_with_checkbox',
columnLines: true,
//Components
var pagingUsersToReassign = new Ext.PagingToolbar({
id: "pagingUsersToReassign",
viewConfig: {
forceFit:true
},
pageSize: pageSizeUsersToReassign,
store: storeUsersToReassign,
displayInfo: true,
displayMsg: _("ID_DISPLAY_ITEMS"),
emptyMsg: _("ID_NO_RECORDS_FOUND")
});
cm: new Ext.grid.ColumnModel({
var cmodelUsersToReassign = new Ext.grid.ColumnModel({
defaults: {
width: 200,
sortable: true
},
columns: [
{id:'USR_UID', dataIndex: 'USR_UID', hidden:true, hideable:false},
{header: _('ID_USER_NAME'), dataIndex: 'USR_USERNAME', width: 300},
{header: _('ID_FIRSTNAME'), dataIndex: 'USR_FIRSTNAME', width: 300},
{header: _('ID_LASTNAME'), dataIndex: 'USR_LASTNAME', width: 300}
{id: "USR_UID", dataIndex: "USR_UID", hidden: true, hideable: false},
{id: "USR_FIRSTNAME", dataIndex: "USR_FIRSTNAME", header: _("ID_FIRSTNAME"), width: 300},
{id: "USR_LASTNAME", dataIndex: "USR_LASTNAME", header: _("ID_LASTNAME"), width: 300}
]
}),
sm: new Ext.grid.RowSelectionModel({singleSelect: true}),
store: store,
tbar:[
{
text:_('ID_REASSIGN'),
iconCls: 'ICON_CASES_TO_REASSIGN',
handler: Actions.reassignCase
}
],
listeners: {
//rowdblclick: openCase,
render: function(){
this.loadMask = new Ext.LoadMask(this.body, {msg:_('ID_LOADING')});
this.ownerCt.doLayout();
}
}
});
var win = new Ext.Window({
var smodelUsersToReassign = new Ext.grid.RowSelectionModel({
singleSelect: true
});
var grdpnlUsersToReassign = new Ext.grid.GridPanel({
id: "grdpnlUsersToReassign",
store: storeUsersToReassign,
colModel: cmodelUsersToReassign,
selModel: smodelUsersToReassign,
columnLines: true,
viewConfig: {forceFit: true},
enableColumnResize: true,
enableHdMenu: true,
tbar: [
{
text: _("ID_REASSIGN"),
iconCls: "ICON_CASES_TO_REASSIGN",
handler: Actions.reassignCase
},
"->",
{
xtype: "textfield",
id: "txtSearchUsersToReassign",
emptyText: _("ID_EMPTY_SEARCH"),
width: 150,
allowBlank: true,
listeners: {
specialkey: function (f, e)
{
if (e.getKey() == e.ENTER) {
pagingUsersToReassign.moveFirst();
}
}
}
},
{
text: "X",
ctCls: "pm_search_x_button",
handler: function ()
{
Ext.getCmp("txtSearchUsersToReassign").reset();
}
},
{
text: _("ID_SEARCH"),
handler: function ()
{
pagingUsersToReassign.moveFirst();
}
}
],
bbar: pagingUsersToReassign,
title: ""
});
var winReassignInCasesList = new Ext.Window({
title: '',
width: 450,
height: 280,
height: 350,
layout:'fit',
autoScroll:true,
modal: true,
resizable: false,
maximizable: false,
items: [grid]
items: [grdpnlUsersToReassign]
});
Ext.Ajax.request({
Ext.Ajax.request({
url : 'ajaxListener' ,
params : {action : 'verifySession'},
success: function ( result, request ) {
@@ -1026,7 +1097,9 @@ Ext.onReady(function(){
}
});
} else {
win.show();
winReassignInCasesList.show();
grdpnlUsersToReassign.store.load();
}
},
failure: function ( result, request) {
@@ -1039,7 +1112,8 @@ Ext.onReady(function(){
Actions.reassignCase = function()
{
var rowSelected = Ext.getCmp('reassignGrid').getSelectionModel().getSelected();
var rowSelected = Ext.getCmp("grdpnlUsersToReassign").getSelectionModel().getSelected();
if( rowSelected ) {
PMExt.confirm(_('ID_CONFIRM'), _('ID_REASSIGN_CONFIRM'), function(){
Ext.Ajax.request({