From eb182466d8ee229bd2b95a4833a03ec12dcd6231 Mon Sep 17 00:00:00 2001 From: Paula Quispe Date: Fri, 14 Feb 2020 15:33:28 -0400 Subject: [PATCH] PMCORE-1160 --- .circleci/config.yml | 2 +- database/factories/AppDelayFactory.php | 26 ++++ database/factories/UserReportingFactory.php | 13 ++ .../workflow/engine/classes/WsBaseTest.php | 121 +++++++++++++----- workflow/engine/classes/Cases.php | 3 +- .../engine/classes/IndicatorsCalculator.php | 50 ++++---- workflow/engine/classes/model/AppDelay.php | 1 + .../engine/classes/model/ListCanceled.php | 1 + workflow/engine/classes/model/Task.php | 36 +++--- .../src/ProcessMaker/Model/AppDelay.php | 11 ++ .../src/ProcessMaker/Model/UserReporting.php | 13 ++ 11 files changed, 206 insertions(+), 71 deletions(-) create mode 100644 database/factories/AppDelayFactory.php create mode 100644 database/factories/UserReportingFactory.php create mode 100644 workflow/engine/src/ProcessMaker/Model/AppDelay.php create mode 100644 workflow/engine/src/ProcessMaker/Model/UserReporting.php diff --git a/.circleci/config.yml b/.circleci/config.yml index 1e8722d11..54f3680e5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,7 +15,7 @@ jobs: name: Run Test Units command: | mkdir coverage - vendor/phpunit/phpunit/phpunit --testdox-html coverage/result.html --coverage-html coverage --verbose tests/unit/ + vendor/phpunit/phpunit/phpunit --stop-on-failure --testdox-html coverage/result.html --coverage-html coverage --verbose tests/unit/ - store_artifacts: path: coverage destination: coverage diff --git a/database/factories/AppDelayFactory.php b/database/factories/AppDelayFactory.php new file mode 100644 index 000000000..8398732d6 --- /dev/null +++ b/database/factories/AppDelayFactory.php @@ -0,0 +1,26 @@ +define(\ProcessMaker\Model\AppDelay::class, function (Faker $faker) { + $actions = ['CANCEL', 'PAUSE', 'REASSIGN']; + return [ + 'APP_DELAY_UID' => G::generateUniqueID(), + 'PRO_UID' => G::generateUniqueID(), + 'APP_UID' => G::generateUniqueID(), + 'APP_NUMBER' => $faker->unique()->numberBetween(1000), + 'APP_THREAD_INDEX' => 1, + 'APP_DEL_INDEX' => $faker->unique()->numberBetween(10), + 'APP_TYPE' => $faker->randomElement($actions), + 'APP_STATUS' => 'TO_DO', + 'APP_NEXT_TASK' => 0, + 'APP_DELEGATION_USER' => G::generateUniqueID(), + 'APP_ENABLE_ACTION_USER' => G::generateUniqueID(), + 'APP_ENABLE_ACTION_DATE' => $faker->dateTime(), + 'APP_DISABLE_ACTION_USER' => G::generateUniqueID(), + 'APP_DISABLE_ACTION_DATE' => $faker->dateTime(), + 'APP_AUTOMATIC_DISABLED_DATE' => '', + 'APP_DELEGATION_USER_ID' => $faker->unique()->numberBetween(1000), + 'PRO_ID' => $faker->unique()->numberBetween(1000), + ]; +}); diff --git a/database/factories/UserReportingFactory.php b/database/factories/UserReportingFactory.php new file mode 100644 index 000000000..46da8d3fd --- /dev/null +++ b/database/factories/UserReportingFactory.php @@ -0,0 +1,13 @@ +define(\ProcessMaker\Model\UserReporting::class, function (Faker $faker) { + return [ + 'USR_UID' => G::generateUniqueID(), + 'TAS_UID' => G::generateUniqueID(), + 'PRO_UID' => G::generateUniqueID(), + 'MONTH' => 12, + 'YEAR' => 2020, + ]; +}); diff --git a/tests/unit/workflow/engine/classes/WsBaseTest.php b/tests/unit/workflow/engine/classes/WsBaseTest.php index a7f541096..3c7a1ffb5 100755 --- a/tests/unit/workflow/engine/classes/WsBaseTest.php +++ b/tests/unit/workflow/engine/classes/WsBaseTest.php @@ -11,11 +11,12 @@ use ProcessMaker\Model\EmailServerModel; use ProcessMaker\Model\Process; use ProcessMaker\Model\Task; use ProcessMaker\Model\User; +use ProcessMaker\Model\UserReporting; use ProcessMaker\Util\WsMessageResponse; use Tests\TestCase; /** - * Class WsBase + * Class WsBaseTest * * @coversDefaultClass WsBase */ @@ -862,14 +863,27 @@ class WsBaseTest extends TestCase } /** - * Review the cancel case with one thread open + * Review the cancel case with one thread open was executed successfully * * @covers WsBase::cancelCase() * @test */ public function it_should_cancel_case() { - $application = factory(Application::class)->create([ + // Definition for avoid the error: Trying to get property 'aUserInfo' of non-object in the action buildAppDelayRow() + global $RBAC; + $user = User::where('USR_ID', '=', 1)->get()->first(); + $_SESSION['USER_LOGGED'] = $user['USR_UID']; + $RBAC = RBAC::getSingleton(PATH_DATA, session_id()); + $RBAC->initRBAC(); + $RBAC->loadUserRolePermission('PROCESSMAKER', $_SESSION['USER_LOGGED']); + + // Create the data related to the cancel a case + $task = factory(Task::class)->create(); + factory(UserReporting::class)->create([ + 'TAS_UID' => $task->TAS_UID + ]); + $application = factory(Application::class)->states('foreign_keys')->create([ 'APP_STATUS_ID' => 2, 'APP_STATUS' => 'TO_DO' ]); @@ -881,6 +895,8 @@ class WsBaseTest extends TestCase 'DEL_INDEX' => 2 ]); $delegation = factory(Delegation::class)->states('foreign_keys')->create([ + 'TAS_UID' => $task->TAS_UID, + 'PRO_UID' => $application->PRO_UID, 'APP_NUMBER' => $application->APP_NUMBER, 'APP_UID' => $application->APP_UID, 'DEL_THREAD_STATUS' => 'OPEN', @@ -888,38 +904,38 @@ class WsBaseTest extends TestCase ]); $ws = new WsBase(); - // todo: the action Case::cancelCase() use Propel queries $response = (object)$ws->cancelCase($delegation->APP_UID, $delegation->DEL_INDEX, $delegation->USR_UID); $this->assertNotEmpty($response); - $this->markTestIncomplete( - 'This test was not fully implemented.' - ); + $this->assertObjectHasAttribute('status_code', $response); + $this->assertEquals($response->message, G::LoadTranslation("ID_COMMAND_EXECUTED_SUCCESSFULLY")); } /** - * Review the cancel case with parallel threads + * Review the cancel case with parallel threads was executed successfully * * @covers WsBase::cancelCase() * @test */ public function it_should_cancel_case_parallel() { - $application = factory(Application::class)->create([ + // Definition for avoid the error: Trying to get property 'aUserInfo' of non-object in the action buildAppDelayRow() + global $RBAC; + $user = User::where('USR_ID', '=', 1)->get()->first(); + $_SESSION['USER_LOGGED'] = $user['USR_UID']; + $RBAC = RBAC::getSingleton(PATH_DATA, session_id()); + $RBAC->initRBAC(); + $RBAC->loadUserRolePermission('PROCESSMAKER', $_SESSION['USER_LOGGED']); + + // Create the data related to the cancel a case + $task = factory(Task::class)->create(); + factory(UserReporting::class)->create([ + 'TAS_UID' => $task->TAS_UID + ]); + $application = factory(Application::class)->states('foreign_keys')->create([ 'APP_STATUS_ID' => 2, 'APP_STATUS' => 'TO_DO' ]); - factory(AppThread::class)->create([ - 'APP_UID' => $application->APP_UID, - 'APP_THREAD_INDEX' => 1, - 'APP_THREAD_PARENT' => 1, - 'APP_THREAD_STATUS' => 'OPEN', - 'DEL_INDEX' => 1 - ]); - factory(Delegation::class)->states('foreign_keys')->create([ - 'APP_NUMBER' => $application->APP_NUMBER, - 'APP_UID' => $application->APP_UID, - 'DEL_THREAD_STATUS' => 'OPEN' - ]); + // Create the first thread factory(AppThread::class)->create([ 'APP_UID' => $application->APP_UID, 'APP_THREAD_INDEX' => 2, @@ -927,20 +943,67 @@ class WsBaseTest extends TestCase 'APP_THREAD_STATUS' => 'OPEN', 'DEL_INDEX' => 2 ]); + factory(Delegation::class)->states('foreign_keys')->create([ + 'TAS_UID' => $task->TAS_UID, + 'PRO_UID' => $application->PRO_UID, + 'APP_NUMBER' => $application->APP_NUMBER, + 'APP_UID' => $application->APP_UID, + 'DEL_THREAD_STATUS' => 'OPEN', + 'DEL_INDEX' => 2, + ]); + // Create the second thread + factory(AppThread::class)->create([ + 'APP_UID' => $application->APP_UID, + 'APP_THREAD_INDEX' => 3, + 'APP_THREAD_PARENT' => 1, + 'APP_THREAD_STATUS' => 'OPEN', + 'DEL_INDEX' => 3 + ]); + $delegation = factory(Delegation::class)->states('foreign_keys')->create([ + 'TAS_UID' => $task->TAS_UID, + 'PRO_UID' => $application->PRO_UID, + 'APP_NUMBER' => $application->APP_NUMBER, + 'APP_UID' => $application->APP_UID, + 'DEL_THREAD_STATUS' => 'OPEN', + 'DEL_INDEX' => 3, + ]); + + $ws = new WsBase(); + $response = (object)$ws->cancelCase($delegation->APP_UID, null, null); + $this->assertNotEmpty($response); + $this->assertObjectHasAttribute('status_code', $response); + $this->assertEquals($response->message, G::LoadTranslation("ID_COMMAND_EXECUTED_SUCCESSFULLY")); + } + + /** + * Review the cancel case when the applications does not exist + * + * @covers WsBase::cancelCase() + * @test + */ + public function it_tried_cancel_an_undefined_case() + { + $fakeApp = G::generateUniqueID(); + $application = factory(Application::class)->create([ + 'APP_STATUS_ID' => 2, + 'APP_STATUS' => 'TO_DO' + ]); + factory(AppThread::class)->create([ + 'APP_UID' => $application->APP_UID, + 'APP_THREAD_INDEX' => 1, + 'APP_THREAD_PARENT' => 1, + 'APP_THREAD_STATUS' => 'OPEN', + 'DEL_INDEX' => 2 + ]); $delegation = factory(Delegation::class)->states('foreign_keys')->create([ 'APP_NUMBER' => $application->APP_NUMBER, 'APP_UID' => $application->APP_UID, 'DEL_THREAD_STATUS' => 'OPEN', 'DEL_INDEX' => 2, ]); - $ws = new WsBase(); - // todo: the action Case::cancelCase() use Propel queries - $response = (object)$ws->cancelCase($delegation->APP_UID, null, null); - $this->assertNotEmpty($response); - // Stop here and mark this test as incomplete. - $this->markTestIncomplete( - 'This test was not fully implemented.' - ); + $response = (object)$ws->cancelCase($fakeApp, $delegation->DEL_INDEX, $delegation->USR_UID); + $this->assertEquals($response->status_code, 100); + $this->assertEquals($response->message, "The Application row '$fakeApp' doesn't exist!"); } } diff --git a/workflow/engine/classes/Cases.php b/workflow/engine/classes/Cases.php index 80a4034bb..b763d91ea 100644 --- a/workflow/engine/classes/Cases.php +++ b/workflow/engine/classes/Cases.php @@ -4374,7 +4374,7 @@ class Cases /** Create a register in APP_DELAY */ $delay = new AppDelay(); - foreach ($indexesClosed as $value){ + foreach ($indexesClosed as $value) { $dataList = []; $rowDelay = AppDelay::buildAppDelayRow( $caseFields['PRO_UID'], @@ -4402,6 +4402,7 @@ class Cases $dataList = array_merge($caseFields, $dataList); $listCanceled = new ListCanceled(); + // This action requires interaction with IndicatorsCalculator class $listCanceled->create($dataList); /*----------------------------------********---------------------------------*/ } diff --git a/workflow/engine/classes/IndicatorsCalculator.php b/workflow/engine/classes/IndicatorsCalculator.php index 426ea1d3b..c1106d198 100644 --- a/workflow/engine/classes/IndicatorsCalculator.php +++ b/workflow/engine/classes/IndicatorsCalculator.php @@ -766,32 +766,32 @@ class IndicatorsCalculator return $returnVal; } - public function suggestedTimeForTask($taskId) + /** + * Get some calculations related to the specific task + * Returns population standard deviation of the expression from timeByTask/totalCase + * Return the average from timeByTask/totalCase + * + * @param string $tasUid + * + * @return array + * @throws Exception + */ + public function suggestedTimeForTask($tasUid) { - $qryParams = array(); - $qryParams[':taskId'] = $taskId; - $sqlString = 'select - ROUND(AVG(TOTAL_TIME_BY_TASK/TOTAL_CASES_OUT), 2) as average, - ROUND(STDDEV(TOTAL_TIME_BY_TASK/TOTAL_CASES_OUT), 2) as sdv - from USR_REPORTING where TAS_UID = :taskId'; - $retval = $this->pdoExecutor($sqlString, $qryParams); - return $retval[0]; - } + try { + $criteria = new Criteria('workflow'); + $criteria->addSelectColumn(UsrReportingPeer::TOTAL_CASES_OUT); + $criteria->addAsColumn('average', 'ROUND(AVG(TOTAL_TIME_BY_TASK/TOTAL_CASES_OUT), 2)'); + $criteria->addAsColumn('sdv', 'ROUND(STDDEV(TOTAL_TIME_BY_TASK/TOTAL_CASES_OUT), 2)'); + $criteria->add(UsrReportingPeer::TAS_UID, $tasUid); + $dataset = UsrReportingPeer::doSelectRS($criteria); + $dataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $dataset->next(); + $result = $dataset->getRow(); - - /* For debug only: - * public function interpolateQuery($query, $params) { - $keys = array(); - # build a regular expression for each parameter - foreach ($params as $key => $value) { - echo "
key", $key, " -- value", $value; - if (is_string($key)) { - $keys[] = '/:'.$key.'/'; - } else { - $keys[] = '/[?]/'; - } + return $result; + } catch (Exception $error) { + throw $error; } - $query = preg_replace($keys, $params, $query, 1, $count); - return $query; - }*/ + } } diff --git a/workflow/engine/classes/model/AppDelay.php b/workflow/engine/classes/model/AppDelay.php index 6157d6907..53b9706a1 100644 --- a/workflow/engine/classes/model/AppDelay.php +++ b/workflow/engine/classes/model/AppDelay.php @@ -152,6 +152,7 @@ class AppDelay extends BaseAppDelay /** * Build the row for the appDelay to be inserted + * This function check the instance of RBAC * * @param string $proUid * @param integer $proId diff --git a/workflow/engine/classes/model/ListCanceled.php b/workflow/engine/classes/model/ListCanceled.php index 7796b74cb..4aa6ea450 100644 --- a/workflow/engine/classes/model/ListCanceled.php +++ b/workflow/engine/classes/model/ListCanceled.php @@ -111,6 +111,7 @@ class ListCanceled extends BaseListCanceled implements ListInterface } if (!empty($data['TAS_UID'])) { $t = new Task(); + // The load task gets some calculations related to the Indicators $data['TAS_ID'] = $t->load($data['TAS_UID'])['TAS_ID']; } $con = Propel::getConnection(ListCanceledPeer::DATABASE_NAME); diff --git a/workflow/engine/classes/model/Task.php b/workflow/engine/classes/model/Task.php index 0f80b9cac..da29c7d97 100644 --- a/workflow/engine/classes/model/Task.php +++ b/workflow/engine/classes/model/Task.php @@ -487,32 +487,38 @@ class Task extends BaseTask return $row; } - public function load($TasUid) + /** + * Load the properties related to the task + * + * @param string $tasUid + * + * @return array + * @throws Exception + */ + public function load($tasUid) { try { - $oRow = TaskPeer::retrieveByPK($TasUid); + $rows = TaskPeer::retrieveByPK($tasUid); - if (!is_null($oRow)) { - $aFields = $oRow->toArray(BasePeer::TYPE_FIELDNAME); - - $this->fromArray($aFields, BasePeer::TYPE_FIELDNAME); //Populating an object from of the array - //Populating attributes + if (!is_null($rows)) { + $fields = $rows->toArray(BasePeer::TYPE_FIELDNAME); + $this->fromArray($fields, BasePeer::TYPE_FIELDNAME); //Populating an object from of the array + //Populating attributes $this->setNew(false); /*----------------------------------********---------------------------------*/ $indicator = new IndicatorsCalculator(); - $data = $indicator->suggestedTimeForTask($TasUid); - $aFields["TAS_AVERAGE"] = $data['average']; - $aFields["TAS_SDV"] = $data['sdv']; + $data = $indicator->suggestedTimeForTask($tasUid); + $fields["TAS_AVERAGE"] = $data['average']; + $fields["TAS_SDV"] = $data['sdv']; /*----------------------------------********---------------------------------*/ - /////// - return $aFields; + return $fields; } else { - throw (new Exception("The row '" . $TasUid . "' in table TASK doesn't exist!")); + throw new Exception("The row '" . $tasUid . "' in table TASK doesn't exist!"); } - } catch (Exception $oError) { - throw ($oError); + } catch (Exception $error) { + throw $error; } } diff --git a/workflow/engine/src/ProcessMaker/Model/AppDelay.php b/workflow/engine/src/ProcessMaker/Model/AppDelay.php new file mode 100644 index 000000000..bbe11e9e6 --- /dev/null +++ b/workflow/engine/src/ProcessMaker/Model/AppDelay.php @@ -0,0 +1,11 @@ +