diff --git a/tests/unit/workflow/engine/src/ProcessMaker/Model/DelegationTest.php b/tests/unit/workflow/engine/src/ProcessMaker/Model/DelegationTest.php index d2e21d8a6..207f1dc02 100644 --- a/tests/unit/workflow/engine/src/ProcessMaker/Model/DelegationTest.php +++ b/tests/unit/workflow/engine/src/ProcessMaker/Model/DelegationTest.php @@ -1553,4 +1553,183 @@ class DelegationTest extends TestCase $result = Delegation::countSelfService($user->USR_UID); $this->assertEquals(25, $result); } + + /** + * This check if return the USR_UID assigned in the thread OPEN + * + * @covers Delegation::getCurrentUser + * @test + */ + public function it_should_return_current_user_for_thread_open() + { + //Create process + $process = factory(Process::class)->create(); + //Create a case + $application = factory(Application::class)->create(); + //Create user + $user = factory(User::class)->create(); + //Create a delegation + factory(Delegation::class)->create([ + 'APP_NUMBER' => $application->APP_NUMBER, + 'DEL_THREAD_STATUS' => 'OPEN', + 'DEL_INDEX' => 2, + 'USR_UID' => $user->USR_UID, + ]); + factory(Delegation::class)->create([ + 'APP_NUMBER' => $application->APP_NUMBER, + 'DEL_THREAD_STATUS' => 'CLOSED', + 'DEL_INDEX' => 1, + 'USR_UID' => $user->USR_UID, + ]); + + //Get the current user assigned in the open thread + $result = Delegation::getCurrentUser($application->APP_NUMBER, 2, 'OPEN'); + $this->assertEquals($user->USR_UID, $result); + } + + /** + * This check if return the USR_UID assigned in the thread CLOSED + * + * @covers Delegation::getCurrentUser + * @test + */ + public function it_should_return_current_user_for_thread_closed() + { + //Create process + $process = factory(Process::class)->create(); + //Create a case + $application = factory(Application::class)->create(); + //Create user + $user = factory(User::class)->create(); + //Create a delegation + factory(Delegation::class)->create([ + 'APP_NUMBER' => $application->APP_NUMBER, + 'DEL_THREAD_STATUS' => 'CLOSED', + 'DEL_INDEX' => 1, + 'USR_UID' => $user->USR_UID, + ]); + factory(Delegation::class)->create([ + 'APP_NUMBER' => $application->APP_NUMBER, + 'DEL_THREAD_STATUS' => 'OPEN', + 'DEL_INDEX' => 2, + 'USR_UID' => $user->USR_UID, + ]); + + //Get the current user assigned in the open thread + $result = Delegation::getCurrentUser($application->APP_NUMBER, 1, 'CLOSED'); + $this->assertEquals($user->USR_UID, $result); + } + + /** + * This check if return empty when the data does not exits + * + * @covers Delegation::getCurrentUser + * @test + */ + public function it_should_return_empty_when_row_does_not_exist() + { + //Create process + $process = factory(Process::class)->create(); + //Create a case + $application = factory(Application::class)->create(); + //Create user + $user = factory(User::class)->create(); + //Create a delegation + factory(Delegation::class)->create([ + 'APP_NUMBER' => $application->APP_NUMBER, + 'DEL_THREAD_STATUS' => 'CLOSED', + 'DEL_INDEX' => 1, + 'USR_UID' => $user->USR_UID, + ]); + factory(Delegation::class)->create([ + 'APP_NUMBER' => $application->APP_NUMBER, + 'DEL_THREAD_STATUS' => 'OPEN', + 'DEL_INDEX' => 2, + 'USR_UID' => $user->USR_UID, + ]); + + //Get the current user assigned in the open thread + $result = Delegation::getCurrentUser($application->APP_NUMBER, 3, 'CLOSED'); + $this->assertEmpty($result); + + $result = Delegation::getCurrentUser($application->APP_NUMBER, 3, 'OPEN'); + $this->assertEmpty($result); + } + + /** + * This checks if return the open thread + * + * @covers Delegation::getOpenThreads + * @test + */ + public function it_should_return_thread_open() + { + //Create process + $process = factory(Process::class)->create(); + //Create a case + $application = factory(Application::class)->create(); + //Create user + $user = factory(User::class)->create(); + //Create task + $task = factory(Task::class)->create(); + //Create a delegation + factory(Delegation::class)->create([ + 'DEL_THREAD_STATUS' => 'OPEN', + 'DEL_FINISH_DATE' => null, + 'APP_NUMBER' => $application->APP_NUMBER, + 'TAS_UID' => $task->TAS_UID, + ]); + $result = Delegation::getOpenThreads($application->APP_NUMBER, $task->TAS_UID); + $this->assertEquals($application->APP_NUMBER, $result['APP_NUMBER']); + } + + /** + * This checks if return empty when the thread is CLOSED + * + * @covers Delegation::getOpenThreads + * @test + */ + public function it_should_return_empty_when_thread_is_closed() + { + //Create process + $process = factory(Process::class)->create(); + //Create a case + $application = factory(Application::class)->create(); + //Create task + $task = factory(Task::class)->create(); + //Create a delegation + factory(Delegation::class)->create([ + 'DEL_THREAD_STATUS' => 'CLOSED', + 'APP_NUMBER' => $application->APP_NUMBER, + 'TAS_UID' => $task->TAS_UID, + ]); + $result = Delegation::getOpenThreads($application->APP_NUMBER, $task->TAS_UID); + $this->assertEmpty($result); + } + + /** + * This checks if return empty when the data is not null + * + * @covers Delegation::getOpenThreads + * @test + */ + public function it_should_return_empty_when_thread_finish_date_is_not_null() + { + //Create process + $process = factory(Process::class)->create(); + //Create a case + $application = factory(Application::class)->create(); + //Create user + $user = factory(User::class)->create(); + //Create task + $task = factory(Task::class)->create(); + //Create a delegation + factory(Delegation::class)->create([ + 'DEL_THREAD_STATUS' => 'CLOSED', + 'APP_NUMBER' => $application->APP_NUMBER, + 'TAS_UID' => $task->TAS_UID, + ]); + $result = Delegation::getOpenThreads($application->APP_NUMBER, $task->TAS_UID); + $this->assertEmpty($result); + } } \ No newline at end of file diff --git a/workflow/engine/methods/cases/proxySaveReassignCasesList.php b/workflow/engine/methods/cases/proxySaveReassignCasesList.php index 01bd39698..958f6bdb8 100644 --- a/workflow/engine/methods/cases/proxySaveReassignCasesList.php +++ b/workflow/engine/methods/cases/proxySaveReassignCasesList.php @@ -2,132 +2,81 @@ /** * proxySaveReassignCasesList.php * - * ProcessMaker Open Source Edition - * Copyright (C) 2004 - 2008 Colosa Inc.23 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - * For more information, contact Colosa Inc, 2566 Le Jeune Rd., - * Coral Gables, FL, 33134, USA, or email info@colosa.com. + * Reassign functionality only from the cases list Review + * @see https://wiki.processmaker.com/3.0/Cases#Reassign */ -$aData = G::json_decode( $_POST['data'] ); -$appSelectedUids = array (); -$items = explode( ",", $_POST['APP_UIDS'] ); -foreach ($items as $item) { - $dataUids = explode( "|", $item ); - $appSelectedUids[] = $dataUids[0]; -} + +use ProcessMaker\Model\Delegation; + +// $_POST['data'] is information about the cases that will reassign +$dataPost = G::json_decode($_POST['data']); $casesReassignedCount = 0; -$serverResponse = array (); +$serverResponse = []; -$oCases = new Cases(); - -$oAppCacheView = new AppCacheView(); -$oAppDel = new AppDelegation(); -$oCasesReassignList = $oAppCacheView->getToReassignListCriteria(null); -if (isset( $_POST['selected'] ) && $_POST['selected'] == 'true') { - $oCasesReassignList->add( AppCacheViewPeer::APP_UID, $appSelectedUids, Criteria::IN ); -} // if there are no records to save return -1 -if (empty( $aData )) { - $serverResponse['TOTAL'] = - 1; - echo G::json_encode( $serverResponse ); +if (empty($dataPost)) { + $serverResponse['TOTAL'] = -1; + + echo G::json_encode($serverResponse); die(); -} - -if (is_array( $aData )) { +} elseif (is_array($dataPost)) { + $cases = new Cases(); $currentCasesReassigned = 0; - require_once ("classes/model/AppNotes.php"); - foreach ($aData as $data) { - $oTmpReassignCriteria = $oCasesReassignList; - $oTmpReassignCriteria->add( AppCacheViewPeer::APP_UID, $data->APP_UID ); - $oTmpReassignCriteria->add( AppCacheViewPeer::TAS_UID, $data->TAS_UID ); - $rs = AppCacheViewPeer::doSelectRS( $oTmpReassignCriteria ); - $rs->setFetchmode( ResultSet::FETCHMODE_ASSOC ); - $rs->next(); - $row = $rs->getRow(); - - //Current users of OPEN DEL_INDEX thread - $aCurUser = $oAppDel->getCurrentUsers($row['APP_UID'], $row['DEL_INDEX']); - $flagReassign = true; - if(!empty($aCurUser)){ - foreach ($aCurUser as $key => $value) { - if($value === $data->APP_REASSIGN_USER_UID){ + foreach ($dataPost as $data) { + // It was supposed will return only one thread related to the task + // todo: implement the reassign case for multi instance task + $openThreads = Delegation::getOpenThreads($data->APP_NUMBER, $data->TAS_UID); + if (!empty($openThreads)) { + // Get the user information assigned in the index + $currentUsrUid = Delegation::getCurrentUser($openThreads['APP_NUMBER'], $openThreads['DEL_INDEX']); + $flagReassign = true; + // Define the flag: it was supposed that the case was assigned another person + if (!empty($currentUsrUid)) { + if ($currentUsrUid === $data->APP_REASSIGN_USER_UID) { $flagReassign = false; } + } else { + // Return an error if the index was CLOSED + throw new Exception(G::LoadTranslation('ID_REASSIGNMENT_ERROR')); + } + // If the currentUsrUid is different to nextUser, create the thread + if ($flagReassign) { + $cases->reassignCase( + $openThreads['APP_UID'], + $openThreads['DEL_INDEX'], + (!empty($openThreads['USR_UID']) ? $openThreads['USR_UID'] : $_SESSION['USER_LOGGED']), + $data->APP_REASSIGN_USER_UID + ); + } + + $currentCasesReassigned++; + $casesReassignedCount++; + $serverResponse[] = [ + 'APP_REASSIGN_USER' => $data->APP_REASSIGN_USER, + 'APP_TITLE' => $data->APP_TITLE, + 'TAS_TITLE' => $data->APP_TAS_TITLE, + 'REASSIGNED_CASES' => $currentCasesReassigned + ]; + + // Save the note reassign reason + if (!empty($data->NOTE_REASON)) { + $appNotes = new AppNotes(); + $noteContent = addslashes($data->NOTE_REASON); + $appNotes->postNewNote( + $openThreads['APP_UID'], + $_SESSION['USER_LOGGED'], + $noteContent, + isset($data->NOTIFY_REASSIGN) ? $data->NOTIFY_REASSIGN : false + ); } } else { - //DEL_INDEX is CLOSED + // Return an error if the index was CLOSED throw new Exception(G::LoadTranslation('ID_REASSIGNMENT_ERROR')); } - - //If the currentUser is diferent to nextUser, create the thread - if($flagReassign){ - $oCases->reassignCase( $row['APP_UID'], $row['DEL_INDEX'], ($row['USR_UID'] != '' ? $row['USR_UID'] : $_SESSION['USER_LOGGED']), $data->APP_REASSIGN_USER_UID ); - } - - $currentCasesReassigned ++; - $casesReassignedCount ++; - $serverResponse[] = array ('APP_REASSIGN_USER' => $data->APP_REASSIGN_USER,'APP_TITLE' => $data->APP_TITLE,'TAS_TITLE' => $data->APP_TAS_TITLE,'REASSIGNED_CASES' => $currentCasesReassigned - ); - - // Save the note reassign reason - if (isset($data->NOTE_REASON) && $data->NOTE_REASON !== '') { - $appNotes = new AppNotes(); - $noteContent = addslashes($data->NOTE_REASON); - $appNotes->postNewNote($row['APP_UID'], $_SESSION['USER_LOGGED'], $noteContent, isset($data->NOTIFY_REASSIGN) ? $data->NOTIFY_REASSIGN : false); - } } -} else { - $oTmpReassignCriteria = $oCasesReassignList; - $oTmpReassignCriteria->add( AppCacheViewPeer::TAS_UID, $aData->TAS_UID ); - $rs = AppCacheViewPeer::doSelectRS( $oTmpReassignCriteria ); - $rs->setFetchmode( ResultSet::FETCHMODE_ASSOC ); - $rs->next(); - $row = $rs->getRow(); - $currentCasesReassigned = 0; - while (is_array( $row )) { - $APP_UID = $row['APP_UID']; - $aCase = $oCases->loadCaseInCurrentDelegation( $APP_UID ); - - //Current users of OPEN DEL_INDEX thread - $aCurUser = $oAppDel->getCurrentUsers($APP_UID, $aCase['DEL_INDEX']); - $flagReassign = true; - if(!empty($aCurUser)){ - foreach ($aCurUser as $key => $value) { - if($value === $aData->APP_REASSIGN_USER_UID){ - $flagReassign = false; - } - } - } else { - //DEL_INDEX is CLOSED - throw new Exception(G::LoadTranslation('ID_REASSIGNMENT_ERROR')); - } - - //If the currentUser is diferent to nextUser, create the thread - if($flagReassign){ - $oCases->reassignCase( $aCase['APP_UID'], $aCase['DEL_INDEX'], ($aCase['USR_UID'] != '' ? $aCase['USR_UID'] : $_SESSION['USER_LOGGED']), $aData->APP_REASSIGN_USER_UID ); - } - - $currentCasesReassigned ++; - $casesReassignedCount ++; - $rs->next(); - $row = $rs->getRow(); - } - $serverResponse[] = array ('TAS_TITLE' => $aData->APP_TAS_TITLE,'REASSIGNED_CASES' => $currentCasesReassigned); } + $serverResponse['TOTAL'] = $casesReassignedCount; -echo G::json_encode( $serverResponse ); +echo G::json_encode($serverResponse); diff --git a/workflow/engine/src/ProcessMaker/Model/Delegation.php b/workflow/engine/src/ProcessMaker/Model/Delegation.php index 5c3c7475f..0749b00ba 100644 --- a/workflow/engine/src/ProcessMaker/Model/Delegation.php +++ b/workflow/engine/src/ProcessMaker/Model/Delegation.php @@ -505,4 +505,55 @@ class Delegation extends Model return $query->count(); } + + /** + * This function get the current user related to the specific case and index + * + * @param integer $appNumber, Case number + * @param integer $index, Index to review + * @param string $status, The status of the thread + * + * @return string + */ + public static function getCurrentUser($appNumber, $index, $status = 'OPEN') + { + $query = Delegation::query()->select('USR_UID'); + $query->where('APP_NUMBER', $appNumber); + $query->where('DEL_INDEX', $index); + $query->where('DEL_THREAD_STATUS', $status); + $query->first(); + $results = $query->get(); + + $userUid = ''; + $results->each(function ($item, $key) use (&$userUid) { + $userUid = $item->USR_UID; + }); + + return $userUid; + } + + /** + * Return the open thread related to the task + * + * @param integer $appNumber, Case number + * @param string $tasUid, The task uid + * + * @return array + */ + public static function getOpenThreads($appNumber, $tasUid) + { + $query = Delegation::query()->select(); + $query->where('DEL_THREAD_STATUS', 'OPEN'); + $query->where('DEL_FINISH_DATE', null); + $query->where('APP_NUMBER', $appNumber); + $query->where('TAS_UID', $tasUid); + $results = $query->get(); + + $arrayOpenThreads = []; + $results->each(function ($item, $key) use (&$arrayOpenThreads) { + $arrayOpenThreads = $item->toArray(); + }); + + return $arrayOpenThreads; + } } diff --git a/workflow/engine/templates/cases/casesList.js b/workflow/engine/templates/cases/casesList.js index f9ff4d3ac..3d816942b 100644 --- a/workflow/engine/templates/cases/casesList.js +++ b/workflow/engine/templates/cases/casesList.js @@ -722,39 +722,6 @@ Ext.onReady ( function() { } }); - var btnExecReassign = new Ext.Button ({ - text: _('ID_REASSIGN_ALL'), - // text: 'Reassign All', - // text: TRANSLATIONS.LABEL_SELECT_ALL, - handler: function(){ - - var rs = storeReassignCases.getModifiedRecords(); - var sv = []; - for(var i = 0; i <= rs.length-1; i++){ - //sv[i]= rs[i].data['name']; - sv[i]= rs[i].data; - } - var gridData = storeReassignCases.getModifiedRecords(); - - Ext.Ajax.request({ - url: 'proxySaveReassignCasesList', - success: function(response) { - newPopUp.hide(); - storeCases.reload(); - }, - params: { APP_UIDS:ids, data:Ext.util.JSON.encode(sv), selected:false } - }); - - /* - storeReassignCases.setBaseParam('selected', false); - var result = storeReassignCases.save(); - newPopUp.hide(); - storeCases.reload(); - */ - //storeReassignCases.reload(); - } - }); - var ExecReassign = function () { newPopUp.hide(); var rs = storeReassignCases.getModifiedRecords(); @@ -2569,7 +2536,6 @@ Ext.onReady ( function() { //newPopUp.add(reassignGrid); newPopUp.add(gridForm); newPopUp.addButton(btnExecReassignSelected); - //newPopUp.addButton(btnExecReassign); newPopUp.addButton(btnCloseReassign); //storeProcesses.load();