From a81099ea180796762e61f7954b6921ee92e741c6 Mon Sep 17 00:00:00 2001 From: Victor Saisa Lopez Date: Tue, 7 Jul 2015 11:51:12 -0400 Subject: [PATCH] PM-2576 "Support for Timer-Event (End-points and Backend)" SOLVED - Se a implementado el Timer-Event CRON, el cual se ejecuta con el siguiente comando: /path/to/processmaker/workflow/engine/bin$ php -f timereventcron.php +wMyWorkspace - Se a implementado el registro de logs para el Timer-Event CRON --- workflow/engine/bin/timereventcron.php | 147 +++++ workflow/engine/bin/timereventcron_single.php | 243 ++++++++ workflow/engine/classes/class.case.php | 13 +- workflow/engine/classes/class.derivation.php | 25 +- workflow/engine/classes/class.wsBase.php | 23 +- .../classes/model/ListParticipatedLast.php | 4 + workflow/engine/classes/model/Users.php | 12 +- .../model/map/TimerEventMapBuilder.php | 6 +- workflow/engine/config/schema.xml | 6 +- workflow/engine/data/mysql/schema.sql | 6 +- .../ProcessMaker/BusinessModel/TimerEvent.php | 550 ++++++++++++++++-- 11 files changed, 967 insertions(+), 68 deletions(-) create mode 100644 workflow/engine/bin/timereventcron.php create mode 100644 workflow/engine/bin/timereventcron_single.php diff --git a/workflow/engine/bin/timereventcron.php b/workflow/engine/bin/timereventcron.php new file mode 100644 index 000000000..b67623d97 --- /dev/null +++ b/workflow/engine/bin/timereventcron.php @@ -0,0 +1,147 @@ + 0 && $arrayAux[count($arrayAux) - 1] == "workflow") { + $arrayPathToCron = $arrayAux; + $flagPathToCron = true; + } + + if (!$flagPathToCron) { + throw new Exception("Error: Unable to execute the Timer-Event CRON, the path is incorrect"); + } + + $pathHome = implode(PATH_SEP, $arrayPathToCron) . PATH_SEP; + + array_pop($arrayPathToCron); + + $pathTrunk = implode(PATH_SEP, $arrayPathToCron) . PATH_SEP; + + array_pop($arrayPathToCron); + + $pathOutTrunk = implode(PATH_SEP, $arrayPathToCron) . PATH_SEP; + + define("PATH_HOME", $pathHome); + define("PATH_TRUNK", $pathTrunk); + define("PATH_OUTTRUNK", $pathOutTrunk); + + //Include files + require_once(PATH_HOME . "engine" . PATH_SEP . "config" . PATH_SEP . "paths.php"); + + G::LoadClass("system"); + + $config = System::getSystemConfiguration(); + + G::LoadSystem('inputfilter'); + $filter = new InputFilter(); + $config['time_zone'] = $filter->validateInput($config['time_zone']); + + ini_set("date.timezone", $config["time_zone"]); + + //CRON command options + $arrayCommandOption = array( + "force" => "+force" + ); + + //CRON status + $flagIsRunning = false; + $lastExecution = ""; + $processcTimeProcess = 0; + $processcTimeStart = 0; + + $force = in_array($arrayCommandOption["force"], $argv); + + if (!$force && file_exists(PATH_DATA . "timereventcron")) { + //Windows flag + //Get data of CRON file + $arrayCron = unserialize(trim(file_get_contents(PATH_DATA . "timereventcron"))); + + $flagIsRunning = (boolean)($arrayCron["flagIsRunning"]); + $lastExecution = $arrayCron["lastExecution"]; + $processcTimeProcess = (isset($arrayCron["processcTimeProcess"]))? (int)($arrayCron["processcTimeProcess"]) : 10; //Minutes + $processcTimeStart = (isset($arrayCron["processcTimeStart"]))? $arrayCron["processcTimeStart"] : 0; + } + + if (!$force && $osIsLinux) { + //Linux flag + //Check if CRON it's running + exec("ps -fea | grep timereventcron.php | grep -v grep", $arrayOutput); + + if (count($arrayOutput) > 1) { + $flagIsRunning = true; + } + } + + if ($force || !$flagIsRunning) { + //Start CRON + $arrayCron = array("flagIsRunning" => "1", "lastExecution" => date("Y-m-d H:i:s")); + file_put_contents(PATH_DATA . "timereventcron", serialize($arrayCron)); + + try { + $messageEventCronSinglePath = PATH_CORE . "bin" . PATH_SEP . "timereventcron_single.php"; + + $workspace = ""; + + for ($i = 1; $i <= count($argv) - 1; $i++) { + if (preg_match("/^\+w(.+)$/", $argv[$i], $arrayMatch)) { + $workspace = $arrayMatch[1]; + break; + } + } + + $countw = 0; + + if ($workspace == "") { + $d = dir(PATH_DB); + + while (($entry = $d->read()) !== false) { + if ($entry != "" && $entry != "." && $entry != "..") { + if (is_dir(PATH_DB . $entry)) { + if (file_exists(PATH_DB . $entry . PATH_SEP . "db.php")) { + $countw++; + + passthru("php -f \"$messageEventCronSinglePath\" $entry \"" . base64_encode(PATH_HOME) . "\" \"" . base64_encode(PATH_TRUNK) . "\" \"" . base64_encode(PATH_OUTTRUNK) . "\""); + } + } + } + } + } else { + if (!is_dir(PATH_DB . $workspace) || !file_exists(PATH_DB . $workspace . PATH_SEP . "db.php")) { + throw new Exception("Error: The workspace \"$workspace\" does not exist"); + } + + $countw++; + + passthru("php -f \"$messageEventCronSinglePath\" $workspace \"" . base64_encode(PATH_HOME) . "\" \"" . base64_encode(PATH_TRUNK) . "\" \"" . base64_encode(PATH_OUTTRUNK) . "\""); + } + + eprintln("Finished $countw workspaces processed"); + } catch (Exception $e) { + throw $e; + } + + //End CRON + $arrayCron = array("flagIsRunning" => "0", "lastExecution" => date("Y-m-d H:i:s")); + file_put_contents(PATH_DATA . "timereventcron", serialize($arrayCron)); + } else { + eprintln("The Timer-Event CRON is running, please wait for it to finish\nStarted in $lastExecution"); + eprintln("If do you want force the execution use the option \"" . $arrayCommandOption["force"] . "\", example: php -f timereventcron.php +wworkflow " . $arrayCommandOption["force"] ,"green"); + } + + echo "Done!\n"; +} catch (Exception $e) { + echo $e->getMessage() . "\n"; +} + diff --git a/workflow/engine/bin/timereventcron_single.php b/workflow/engine/bin/timereventcron_single.php new file mode 100644 index 000000000..cec2aeb94 --- /dev/null +++ b/workflow/engine/bin/timereventcron_single.php @@ -0,0 +1,243 @@ +add(PATH_TRUNK . "framework" . PATH_SEP . "src" . PATH_SEP, "Maveriks"); + $classLoader->add(PATH_TRUNK . "workflow" . PATH_SEP . "engine" . PATH_SEP . "src" . PATH_SEP, "ProcessMaker"); + $classLoader->add(PATH_TRUNK . "workflow" . PATH_SEP . "engine" . PATH_SEP . "src" . PATH_SEP); + + //Add vendors to autoloader + //$classLoader->add(PATH_TRUNK . "vendor" . PATH_SEP . "luracast" . PATH_SEP . "restler" . PATH_SEP . "vendor", "Luracast"); + //$classLoader->add(PATH_TRUNK . "vendor" . PATH_SEP . "bshaffer" . PATH_SEP . "oauth2-server-php" . PATH_SEP . "src" . PATH_SEP, "OAuth2"); + $classLoader->addClass("Bootstrap", PATH_TRUNK . "gulliver" . PATH_SEP . "system" . PATH_SEP . "class.bootstrap.php"); + + $classLoader->addModelClassPath(PATH_TRUNK . "workflow" . PATH_SEP . "engine" . PATH_SEP . "classes" . PATH_SEP . "model" . PATH_SEP); + + //Load classes + G::LoadThirdParty("pear/json", "class.json"); + G::LoadThirdParty("smarty/libs", "Smarty.class"); + G::LoadSystem("error"); + G::LoadSystem("dbconnection"); + G::LoadSystem("dbsession"); + G::LoadSystem("dbrecordset"); + G::LoadSystem("dbtable"); + G::LoadSystem("rbac" ); + G::LoadSystem("publisher"); + G::LoadSystem("templatePower"); + G::LoadSystem("xmlDocument"); + G::LoadSystem("xmlform"); + G::LoadSystem("xmlformExtension"); + G::LoadSystem("form"); + G::LoadSystem("menu"); + G::LoadSystem("xmlMenu"); + G::LoadSystem("dvEditor"); + G::LoadSystem("table"); + G::LoadSystem("pagedTable"); + G::LoadClass("system"); + + require_once("propel/Propel.php"); + require_once("creole/Creole.php"); + + $config = System::getSystemConfiguration(); + + $e_all = (defined("E_DEPRECATED"))? E_ALL & ~E_DEPRECATED : E_ALL; + $e_all = (defined("E_STRICT"))? $e_all & ~E_STRICT : $e_all; + $e_all = ($config["debug"])? $e_all : $e_all & ~E_NOTICE; + + G::LoadSystem('inputfilter'); + $filter = new InputFilter(); + $config['debug'] = $filter->validateInput($config['debug']); + $config['wsdl_cache'] = $filter->validateInput($config['wsdl_cache'],'int'); + $config['time_zone'] = $filter->validateInput($config['time_zone']); + //Do not change any of these settings directly, use env.ini instead + ini_set("display_errors", $config["debug"]); + ini_set("error_reporting", $e_all); + ini_set("short_open_tag", "On"); + ini_set("default_charset", "UTF-8"); + //ini_set("memory_limit", $config["memory_limit"]); + ini_set("soap.wsdl_cache_enabled", $config["wsdl_cache"]); + ini_set("date.timezone", $config["time_zone"]); + + define("DEBUG_SQL_LOG", $config["debug_sql"]); + define("DEBUG_TIME_LOG", $config["debug_time"]); + define("DEBUG_CALENDAR_LOG", $config["debug_calendar"]); + define("MEMCACHED_ENABLED", $config["memcached"]); + define("MEMCACHED_SERVER", $config["memcached_server"]); + define("TIME_ZONE", $config["time_zone"]); + + //require_once(PATH_GULLIVER . PATH_SEP . "class.bootstrap.php"); + //define("PATH_GULLIVER_HOME", PATH_TRUNK . "gulliver" . PATH_SEP); + + spl_autoload_register(array("Bootstrap", "autoloadClass")); + + //DATABASE propel classes used in "Cases" Options + Bootstrap::registerClass("PMLicensedFeatures", PATH_CLASSES . "class.licensedFeatures.php"); + Bootstrap::registerClass("calendar", PATH_CLASSES . "class.calendar.php"); + + Bootstrap::registerClass("wsResponse", PATH_HOME . "engine" . PATH_SEP . "classes" . PATH_SEP . "class.wsResponse.php"); + + G::LoadClass("processes"); + G::LoadClass("derivation"); + G::LoadClass("dates"); //Load Criteria + + //Workflow + $workflow = $argv[1]; + + if (is_dir(PATH_DB . $workflow) && file_exists(PATH_DB . $workflow . PATH_SEP . "db.php")) { + define("SYS_SYS", $workflow); + + include_once(PATH_HOME . "engine" . PATH_SEP . "config" . PATH_SEP . "paths_installed.php"); + include_once(PATH_HOME . "engine" . PATH_SEP . "config" . PATH_SEP . "paths.php"); + + //PM Paths DATA + define("PATH_DATA_SITE", PATH_DATA . "sites/" . SYS_SYS . "/"); + define("PATH_DOCUMENT", PATH_DATA_SITE . "files/"); + define("PATH_DATA_MAILTEMPLATES", PATH_DATA_SITE . "mailTemplates/"); + define("PATH_DATA_PUBLIC", PATH_DATA_SITE . "public/"); + define("PATH_DATA_REPORTS", PATH_DATA_SITE . "reports/"); + define("PATH_DYNAFORM", PATH_DATA_SITE . "xmlForms/"); + define("PATH_IMAGES_ENVIRONMENT_FILES", PATH_DATA_SITE . "usersFiles" . PATH_SEP); + define("PATH_IMAGES_ENVIRONMENT_USERS", PATH_DATA_SITE . "usersPhotographies" . PATH_SEP); + + if (is_file(PATH_DATA_SITE.PATH_SEP . ".server_info")) { + $SERVER_INFO = file_get_contents(PATH_DATA_SITE.PATH_SEP.".server_info"); + $SERVER_INFO = unserialize($SERVER_INFO); + + define("SERVER_NAME", $SERVER_INFO ["SERVER_NAME"]); + define("SERVER_PORT", $SERVER_INFO ["SERVER_PORT"]); + } else { + eprintln("WARNING! No server info found!", "red"); + } + + //DB + $phpCode = ""; + + $fileDb = fopen(PATH_DB . $workflow . PATH_SEP . "db.php", "r"); + + if ($fileDb) { + while (!feof($fileDb)) { + $buffer = fgets($fileDb, 4096); //Read a line + + $phpCode .= preg_replace("/define\s*\(\s*[\x22\x27](.*)[\x22\x27]\s*,\s*(\x22.*\x22|\x27.*\x27)\s*\)\s*;/i", "\$$1 = $2;", $buffer); + } + + fclose($fileDb); + } + + $phpCode = str_replace(array(""), array("", "", ""), $phpCode); + + eval($phpCode); + + $dsn = $DB_ADAPTER . "://" . $DB_USER . ":" . $DB_PASS . "@" . $DB_HOST . "/" . $DB_NAME; + $dsnRbac = $DB_ADAPTER . "://" . $DB_RBAC_USER . ":" . $DB_RBAC_PASS . "@" . $DB_RBAC_HOST . "/" . $DB_RBAC_NAME; + $dsnRp = $DB_ADAPTER . "://" . $DB_REPORT_USER . ":" . $DB_REPORT_PASS . "@" . $DB_REPORT_HOST . "/" . $DB_REPORT_NAME; + + switch ($DB_ADAPTER) { + case "mysql": + $dsn .= "?encoding=utf8"; + $dsnRbac .= "?encoding=utf8"; + break; + case "mssql": + //$dsn .= "?sendStringAsUnicode=false"; + //$dsnRbac .= "?sendStringAsUnicode=false"; + break; + default: + break; + } + + $pro = array(); + $pro["datasources"]["workflow"]["connection"] = $dsn; + $pro["datasources"]["workflow"]["adapter"] = $DB_ADAPTER; + $pro["datasources"]["rbac"]["connection"] = $dsnRbac; + $pro["datasources"]["rbac"]["adapter"] = $DB_ADAPTER; + $pro["datasources"]["rp"]["connection"] = $dsnRp; + $pro["datasources"]["rp"]["adapter"] = $DB_ADAPTER; + //$pro["datasources"]["dbarray"]["connection"] = "dbarray://user:pass@localhost/pm_os"; + //$pro["datasources"]["dbarray"]["adapter"] = "dbarray"; + + $oFile = fopen(PATH_CORE . "config" . PATH_SEP . "_databases_.php", "w"); + fwrite($oFile, ""); + fclose($oFile); + + Propel::init(PATH_CORE . "config" . PATH_SEP . "_databases_.php"); + //Creole::registerDriver("dbarray", "creole.contrib.DBArrayConnection"); + + //Enable RBAC + Bootstrap::LoadSystem("rbac"); + + $rbac = &RBAC::getSingleton(PATH_DATA, session_id()); + $rbac->sSystem = "PROCESSMAKER"; + + if (!defined("DB_ADAPTER")) { + define("DB_ADAPTER", $DB_ADAPTER); + } + + eprintln("Processing workspace: " . $workflow, "green"); + + try { + $timerEvent = new \ProcessMaker\BusinessModel\TimerEvent(); + + $timerEvent->startContinueCaseByTimerEvent(date("Y-m-d H:i:s"), true); + } catch (Exception $e) { + echo $e->getMessage() . "\n"; + + eprintln("Problem in workspace: " . $workflow . " it was omitted.", "red"); + } + + eprintln(); + } + + if (file_exists(PATH_CORE . "config" . PATH_SEP . "_databases_.php")) { + unlink(PATH_CORE . "config" . PATH_SEP . "_databases_.php"); + } +} catch (Exception $e) { + echo $e->getMessage() . "\n"; +} + diff --git a/workflow/engine/classes/class.case.php b/workflow/engine/classes/class.case.php index c651f551e..810b01e05 100755 --- a/workflow/engine/classes/class.case.php +++ b/workflow/engine/classes/class.case.php @@ -2028,16 +2028,21 @@ class Cases { if ($sTasUid != '') { try { - $this->Task = new Task; - $Fields = $this->Task->Load($sTasUid); + $task = TaskPeer::retrieveByPK($sTasUid); + + if (is_null($task)) { + throw new Exception(G::LoadTranslation("ID_TASK_NOT_EXIST", array("TAS_UID", $sTasUid))); + } //To allow Self Service as the first task - if (($Fields['TAS_ASSIGN_TYPE'] != 'SELF_SERVICE') && ($sUsrUid == '')) { + $arrayTaskTypeToExclude = array("START-TIMER-EVENT"); + + if (!is_null($task) && !in_array($task->getTasType(), $arrayTaskTypeToExclude) && $task->getTasAssignType() != "SELF_SERVICE" && $sUsrUid == "") { throw (new Exception('You tried to start a new case without send the USER UID!')); } //Process - $sProUid = $this->Task->getProUid(); + $sProUid = $task->getProUid(); $this->Process = new Process; $proFields = $this->Process->Load($sProUid); diff --git a/workflow/engine/classes/class.derivation.php b/workflow/engine/classes/class.derivation.php index ee530a872..89d99baad 100755 --- a/workflow/engine/classes/class.derivation.php +++ b/workflow/engine/classes/class.derivation.php @@ -439,20 +439,21 @@ class Derivation */ function getNextAssignedUser ($tasInfo) { - $oUser = new Users(); + //$oUser = new Users(); $nextAssignedTask = $tasInfo['NEXT_TASK']; $lastAssigned = $tasInfo['NEXT_TASK']['TAS_LAST_ASSIGNED']; $sTasUid = $tasInfo['NEXT_TASK']['TAS_UID']; - // to do: we can increase the LOCATION by COUNTRY, STATE and LOCATION - /* Verify if the next Task is set with the option "TAS_ASSIGN_LOCATION == TRUE" */ - $assignLocation = ''; - if ($tasInfo['NEXT_TASK']['TAS_ASSIGN_LOCATION'] == 'TRUE') { - $oUser->load( $tasInfo['USER_UID'] ); - krumo( $oUser->getUsrLocation() ); - //to do: assign for location - //$assignLocation = " AND USR_LOCATION = " . $oUser->Fields['USR_LOCATION']; - } - /* End - Verify if the next Task is set with the option "TAS_ASSIGN_LOCATION == TRUE" */ + + //// to do: we can increase the LOCATION by COUNTRY, STATE and LOCATION + ///* Verify if the next Task is set with the option "TAS_ASSIGN_LOCATION == TRUE" */ + //$assignLocation = ''; + //if ($tasInfo['NEXT_TASK']['TAS_ASSIGN_LOCATION'] == 'TRUE') { + // $oUser->load( $tasInfo['USER_UID'] ); + // krumo( $oUser->getUsrLocation() ); + // //to do: assign for location + // //$assignLocation = " AND USR_LOCATION = " . $oUser->Fields['USR_LOCATION']; + //} + ///* End - Verify if the next Task is set with the option "TAS_ASSIGN_LOCATION == TRUE" */ $uidUser = ''; switch ($nextAssignedTask['TAS_ASSIGN_TYPE']) { @@ -507,7 +508,7 @@ class Derivation $userFields['USR_EMAIL'] = ''; //get the report_to user & its full info - $useruid = $this->checkReplacedByUser( $this->getDenpendentUser( $tasInfo['USER_UID'] ) ); + $useruid = ($tasInfo["USER_UID"] != "")? $this->checkReplacedByUser($this->getDenpendentUser($tasInfo["USER_UID"])) : ""; if (isset( $useruid ) && $useruid != '') { $userFields = $this->getUsersFullNameFromArray( $useruid ); diff --git a/workflow/engine/classes/class.wsBase.php b/workflow/engine/classes/class.wsBase.php index 7edfc284d..9895119ca 100755 --- a/workflow/engine/classes/class.wsBase.php +++ b/workflow/engine/classes/class.wsBase.php @@ -1985,7 +1985,11 @@ class wsBase } } - if ($founded == '') { + $task = TaskPeer::retrieveByPK($taskId); + + $arrayTaskTypeToExclude = array("START-TIMER-EVENT"); + + if (!is_null($task) && !in_array($task->getTasType(), $arrayTaskTypeToExclude) && $founded == "") { $result = new wsResponse( 14, G::loadTranslation( 'ID_TASK_INVALID_USER_NOT_ASSIGNED_TASK' ) ); $g->sessionVarRestore(); @@ -2227,6 +2231,7 @@ class wsBase } } + $aData = array(); $aData['APP_UID'] = $caseId; $aData['DEL_INDEX'] = $delIndex; $aData['USER_UID'] = $userId; @@ -2482,14 +2487,20 @@ class wsBase } } - $oUser = new Users(); - $aUser = $oUser->load( $userId ); + $sFromName = ""; - if (trim( $aUser['USR_EMAIL'] ) == '') { - $aUser['USR_EMAIL'] = 'info@' . $_SERVER['HTTP_HOST']; + if ($userId != "") { + $user = new Users(); + + $arrayUserData = $user->load($userId); + + if (trim($arrayUserData["USR_EMAIL"]) == "") { + $arrayUserData["USR_EMAIL"] = "info@" . $_SERVER["HTTP_HOST"]; + } + + $sFromName = "\"" . $arrayUserData["USR_FIRSTNAME"] . " " . $arrayUserData["USR_LASTNAME"] . "\" <" . $arrayUserData["USR_EMAIL"] . ">"; } - $sFromName = '"' . $aUser['USR_FIRSTNAME'] . ' ' . $aUser['USR_LASTNAME'] . '" <' . $aUser['USR_EMAIL'] . '>'; $oCase->sendNotifications( $appdel['TAS_UID'], $nextDelegations, $appFields['APP_DATA'], $caseId, $delIndex, $sFromName ); //Save data - Start diff --git a/workflow/engine/classes/model/ListParticipatedLast.php b/workflow/engine/classes/model/ListParticipatedLast.php index 7b9de8dee..d43cf9c6a 100644 --- a/workflow/engine/classes/model/ListParticipatedLast.php +++ b/workflow/engine/classes/model/ListParticipatedLast.php @@ -113,6 +113,10 @@ class ListParticipatedLast extends BaseListParticipatedLast { $data['APP_STATUS'] = (empty($data['APP_STATUS'])) ? 'TO_DO' : $data['APP_STATUS']; if (!$isSelfService) { + if ($data["USR_UID"] == "") { + return; + } + $criteria = new Criteria(); $criteria->addSelectColumn(UsersPeer::USR_USERNAME); $criteria->addSelectColumn(UsersPeer::USR_FIRSTNAME); diff --git a/workflow/engine/classes/model/Users.php b/workflow/engine/classes/model/Users.php index 9b7ad4e9b..e956d7d90 100755 --- a/workflow/engine/classes/model/Users.php +++ b/workflow/engine/classes/model/Users.php @@ -261,7 +261,7 @@ class Users extends BaseUsers //Calendar $calendar = new Calendar(); $calendarInfo = $calendar->getCalendarFor( $userUid, $userUid, $userUid ); - $aFields["USR_CALENDAR"] = ($calendarInfo["CALENDAR_APPLIED"] != "DEFAULT") ? $calendarInfo["CALENDAR_UID"] : ""; + $aFields["USR_CALENDAR"] = ($calendarInfo["CALENDAR_APPLIED"] != "DEFAULT") ? $calendarInfo["CALENDAR_UID"] : ""; //Photo $pathPhoto = PATH_IMAGES_ENVIRONMENT_USERS . $userUid . ".gif"; @@ -290,12 +290,12 @@ class Users extends BaseUsers if(strlen($arrayData["replacedby"] != 0)){ $oUser = UsersPeer::retrieveByPK( $arrayData["replacedby"] ); $arrayData["replacedbyfullname"] = $oUser->getUsrFirstname() . ' ' . $oUser->getUsrLastname(); - } + } $arrayData["duedate"] = $aFields["USR_DUE_DATE"]; $arrayData["calendar"] = $aFields["USR_CALENDAR"]; if(strlen($aFields["USR_CALENDAR"] != 0)){ - $arrayData["calendarname"] = $calendar->calendarName( $aFields["USR_CALENDAR"] ); - } + $arrayData["calendarname"] = $calendar->calendarName( $aFields["USR_CALENDAR"] ); + } $arrayData["status"] = $aFields["USR_STATUS"]; $arrayData["department"] = $aFields["DEP_UID"]; if (strlen($arrayData["department"]) != 0) { @@ -399,6 +399,10 @@ class Users extends BaseUsers public function refreshTotal ($userId, $type = 'add', $list = "inbox", $total = 1) { + if ($userId == "") { + return; + } + $nameList = self::getNameTotal($list); $criteria = new Criteria(); $criteria->addSelectColumn( $nameList ); diff --git a/workflow/engine/classes/model/map/TimerEventMapBuilder.php b/workflow/engine/classes/model/map/TimerEventMapBuilder.php index 439bae621..8fa5ebf40 100644 --- a/workflow/engine/classes/model/map/TimerEventMapBuilder.php +++ b/workflow/engine/classes/model/map/TimerEventMapBuilder.php @@ -77,11 +77,11 @@ class TimerEventMapBuilder $tMap->addColumn('TMREVN_END_DATE', 'TmrevnEndDate', 'int', CreoleTypes::DATE, false, null); - $tMap->addColumn('TMREVN_DAY', 'TmrevnDay', 'string', CreoleTypes::VARCHAR, true, 2); + $tMap->addColumn('TMREVN_DAY', 'TmrevnDay', 'string', CreoleTypes::VARCHAR, true, 5); - $tMap->addColumn('TMREVN_HOUR', 'TmrevnHour', 'string', CreoleTypes::VARCHAR, true, 2); + $tMap->addColumn('TMREVN_HOUR', 'TmrevnHour', 'string', CreoleTypes::VARCHAR, true, 5); - $tMap->addColumn('TMREVN_MINUTE', 'TmrevnMinute', 'string', CreoleTypes::VARCHAR, true, 2); + $tMap->addColumn('TMREVN_MINUTE', 'TmrevnMinute', 'string', CreoleTypes::VARCHAR, true, 5); $tMap->addColumn('TMREVN_CONFIGURATION_DATA', 'TmrevnConfigurationData', 'string', CreoleTypes::LONGVARCHAR, true, null); diff --git a/workflow/engine/config/schema.xml b/workflow/engine/config/schema.xml index a6cd512d7..6b41635d6 100755 --- a/workflow/engine/config/schema.xml +++ b/workflow/engine/config/schema.xml @@ -5098,9 +5098,9 @@ - - - + + + diff --git a/workflow/engine/data/mysql/schema.sql b/workflow/engine/data/mysql/schema.sql index 631abf018..173d08cb0 100755 --- a/workflow/engine/data/mysql/schema.sql +++ b/workflow/engine/data/mysql/schema.sql @@ -2861,9 +2861,9 @@ CREATE TABLE TIMER_EVENT TMREVN_OPTION VARCHAR(50) default 'DAILY' NOT NULL, TMREVN_START_DATE DATE, TMREVN_END_DATE DATE, - TMREVN_DAY VARCHAR(2) default '' NOT NULL, - TMREVN_HOUR VARCHAR(2) default '' NOT NULL, - TMREVN_MINUTE VARCHAR(2) default '' NOT NULL, + TMREVN_DAY VARCHAR(5) default '' NOT NULL, + TMREVN_HOUR VARCHAR(5) default '' NOT NULL, + TMREVN_MINUTE VARCHAR(5) default '' NOT NULL, TMREVN_CONFIGURATION_DATA MEDIUMTEXT default '' NOT NULL, TMREVN_NEXT_RUN_DATE DATETIME, TMREVN_LAST_RUN_DATE DATETIME, diff --git a/workflow/engine/src/ProcessMaker/BusinessModel/TimerEvent.php b/workflow/engine/src/ProcessMaker/BusinessModel/TimerEvent.php index a7d17932b..1770256ad 100644 --- a/workflow/engine/src/ProcessMaker/BusinessModel/TimerEvent.php +++ b/workflow/engine/src/ProcessMaker/BusinessModel/TimerEvent.php @@ -104,13 +104,13 @@ class TimerEvent try { $arrayData = array(); - if (preg_match("/^(\d{4})\-(\d{2})\-(\d{2})(?:\s(\d{2})\:(\d{2})\:(\d{2}))?$/", $datetime, $arrayMatch)) { + if (preg_match("/^([1-9]\d{3})\-(0[1-9]|1[0-2])\-([0][1-9]|[12][0-9]|3[01])(?:\s([0-1]\d|2[0-3])\:([0-5]\d)\:([0-5]\d))?$/", $datetime, $arrayMatch)) { $arrayData[] = $arrayMatch[1]; //Year $arrayData[] = $arrayMatch[2]; //Month $arrayData[] = $arrayMatch[3]; //Day $arrayData[] = (isset($arrayMatch[4]))? $arrayMatch[4] : "00"; //Hour - $arrayData[] = (isset($arrayMatch[4]))? $arrayMatch[5] : "00"; //Minute - $arrayData[] = (isset($arrayMatch[4]))? $arrayMatch[6] : "00"; //Second + $arrayData[] = (isset($arrayMatch[5]))? $arrayMatch[5] : "00"; //Minute + $arrayData[] = (isset($arrayMatch[6]))? $arrayMatch[6] : "00"; //Second } //Return @@ -161,14 +161,14 @@ class TimerEvent $weekday = (int)(date("w", strtotime($datetime))); $weekday = ($weekday == 0)? 7 : $weekday; - $firstWeekday = (int)($arrayWeekdaysData[0]); + $firstWeekday = $arrayWeekdaysData[0]; $nextWeekday = $firstWeekday; $typeStatement = "this"; $flag = false; foreach ($arrayWeekdaysData as $value) { - $d = (int)($value); + $d = $value; if (($flagIncludeDatetime && $d >= $weekday) || (!$flagIncludeDatetime && $d > $weekday)) { $nextWeekday = $d; @@ -198,13 +198,13 @@ class TimerEvent if (!empty($arrayMonthsData)) { sort($arrayMonthsData); - $firstMonth = (int)($arrayMonthsData[0]); + $firstMonth = $arrayMonthsData[0]; $nextMonth = $firstMonth; $flag = false; foreach ($arrayMonthsData as $value) { - $m = (int)($value); + $m = $value; if (($flagIncludeDatetime && $m >= $month) || (!$flagIncludeDatetime && $m > $month)) { $nextMonth = $m; @@ -252,7 +252,7 @@ class TimerEvent } //Return - return $nextRunDate; + return date("Y-m-d H:i:s", strtotime($nextRunDate)); } catch (\Exception $e) { throw $e; } @@ -318,6 +318,28 @@ class TimerEvent } } + /** + * Unset fields + * + * @param array $arrayData Data with the fields + * + * return array Return data with the fields + */ + public function unsetFields(array $arrayData) + { + try { + unset($arrayData["TMREVN_UID"]); + unset($arrayData["PRJ_UID"]); + unset($arrayData["TMREVN_LAST_RUN_DATE"]); + unset($arrayData["TMREVN_LAST_EXECUTION_DATE"]); + + //Return + return $arrayData; + } catch (\Exception $e) { + throw $e; + } + } + /** * Verify if exists the Timer-Event * @@ -475,6 +497,11 @@ class TimerEvent } $arrayFieldDefinition = array(); + $arrayValidateData = array( + "TMREVN_DAY" => array("/^(?:[0][1-9]|[12][0-9]|3[01])$/", $this->arrayFieldNameForException["timerEventDay"]), + "TMREVN_HOUR" => array("/^(?:[0-1]\d|2[0-3])$/", $this->arrayFieldNameForException["timerEventHour"]), + "TMREVN_MINUTE" => array("/^(?:[0-5]\d)$/", $this->arrayFieldNameForException["timerEventMinute"]) + ); switch ($arrayFinalData["TMREVN_OPTION"]) { case "HOURLY": @@ -508,6 +535,9 @@ class TimerEvent "TMREVN_HOUR" => array("type" => "string", "required" => true, "empty" => false, "defaultValues" => array(), "fieldNameAux" => "timerEventHour"), "TMREVN_MINUTE" => array("type" => "string", "required" => true, "empty" => false, "defaultValues" => array(), "fieldNameAux" => "timerEventMinute") ); + + $arrayValidateData["TMREVN_HOUR"][0] = "/^(?:0|[1-9]\d*)$/"; + $arrayValidateData["TMREVN_MINUTE"][0] = "/^(?:0|[1-9]\d*)$/"; break; case "ONE-DATE-TIME": $arrayFieldDefinition = array( @@ -518,6 +548,9 @@ class TimerEvent //TMREVN_DAY //TMREVN_HOUR //TMREVN_MINUTE + $arrayValidateData["TMREVN_DAY"][0] = "/^(?:0|[1-9]\d*)$/"; + $arrayValidateData["TMREVN_HOUR"][0] = "/^(?:0|[1-9]\d*)$/"; + $arrayValidateData["TMREVN_MINUTE"][0] = "/^(?:0|[1-9]\d*)$/"; break; case "WAIT-UNTIL-SPECIFIED-DATE-TIME": $arrayFieldDefinition = array( @@ -530,12 +563,6 @@ class TimerEvent $process->throwExceptionIfDataNotMetFieldDefinition($arrayFinalData, $arrayFieldDefinition, $this->arrayFieldNameForException, $flagInsert); } - $arrayValidateData = array( - "TMREVN_DAY" => array("/^(?:[0-2]\d|3[01])$/", $this->arrayFieldNameForException["timerEventDay"]), - "TMREVN_HOUR" => array("/^(?:[0-1]\d|2[0-3])$/", $this->arrayFieldNameForException["timerEventHour"]), - "TMREVN_MINUTE" => array("/^(?:[0-5]\d)$/", $this->arrayFieldNameForException["timerEventMinute"]) - ); - foreach ($arrayValidateData as $key => $value) { if (isset($arrayData[$key]) && !preg_match($value[0], $arrayData[$key])) { throw new \Exception(\G::LoadTranslation("ID_INVALID_VALUE", array($value[1]))); @@ -567,11 +594,6 @@ class TimerEvent //Set data $arrayData = array_change_key_case($arrayData, CASE_UPPER); - unset($arrayData["TMREVN_UID"]); - unset($arrayData["PRJ_UID"]); - unset($arrayData["TMREVN_LAST_RUN_DATE"]); - unset($arrayData["TMREVN_LAST_EXECUTION_DATE"]); - //Verify data $process->throwExceptionIfNotExistsProcess($projectUid, $this->arrayFieldNameForException["projectUid"]); @@ -580,6 +602,8 @@ class TimerEvent //Create $cnn = \Propel::getConnection("workflow"); + $arrayData = $this->unsetFields($arrayData); + try { $timerEvent = new \TimerEvent(); $bpmnEvent = \BpmnEventPeer::retrieveByPK($arrayData["EVN_UID"]); @@ -692,7 +716,7 @@ class TimerEvent * @param string $timerEventUid Unique id of Timer-Event * @param array $arrayData Data * - * return array Return data of the Timer-Event updated + * return int Return the number of rows affected by this update */ public function update($timerEventUid, array $arrayData) { @@ -706,12 +730,6 @@ class TimerEvent //Set data $arrayData = array_change_key_case($arrayData, CASE_UPPER); - $arrayDataBackup = $arrayData; - - unset($arrayData["TMREVN_UID"]); - unset($arrayData["PRJ_UID"]); - unset($arrayData["TMREVN_LAST_RUN_DATE"]); - unset($arrayData["TMREVN_LAST_EXECUTION_DATE"]); //Set variables $arrayTimerEventData = $this->getTimerEvent($timerEventUid, true); @@ -726,6 +744,8 @@ class TimerEvent //Update $cnn = \Propel::getConnection("workflow"); + $arrayData = $this->unsetFields($arrayData); + try { $timerEvent = \TimerEventPeer::retrieveByPK($timerEventUid); $bpmnEvent = \BpmnEventPeer::retrieveByPK($arrayFinalData["EVN_UID"]); @@ -807,13 +827,53 @@ class TimerEvent $cnn->commit(); //Return - $arrayData = $arrayDataBackup; + return $result; + } else { + $msg = ""; - if (!$this->formatFieldNameInUppercase) { - $arrayData = array_change_key_case($arrayData, CASE_LOWER); + foreach ($timerEvent->getValidationFailures() as $validationFailure) { + $msg = $msg . (($msg != "")? "\n" : "") . $validationFailure->getMessage(); } - return $arrayData; + throw new \Exception(\G::LoadTranslation("ID_REGISTRY_CANNOT_BE_UPDATED") . (($msg != "")? "\n" . $msg : "")); + } + } catch (\Exception $e) { + $cnn->rollback(); + + throw $e; + } + } catch (\Exception $e) { + throw $e; + } + } + + /** + * Single update Timer-Event + * + * @param string $timerEventUid Unique id of Timer-Event + * @param array $arrayData Data + * + * return int Return integer + */ + public function singleUpdate($timerEventUid, array $arrayData) + { + try { + $cnn = \Propel::getConnection("workflow"); + + try { + $timerEvent = \TimerEventPeer::retrieveByPK($timerEventUid); + + $timerEvent->fromArray($arrayData, \BasePeer::TYPE_FIELDNAME); + + if ($timerEvent->validate()) { + $cnn->begin(); + + $result = $timerEvent->save(); + + $cnn->commit(); + + //Return + return $result; } else { $msg = ""; @@ -931,9 +991,9 @@ class TimerEvent $this->getFieldNameByFormatFieldName("TMREVN_OPTION") => $record["TMREVN_OPTION"], $this->getFieldNameByFormatFieldName("TMREVN_START_DATE") => $record["TMREVN_START_DATE"] . "", $this->getFieldNameByFormatFieldName("TMREVN_END_DATE") => $record["TMREVN_END_DATE"] . "", - $this->getFieldNameByFormatFieldName("TMREVN_DAY") => $record["TMREVN_DAY"] . "", - $this->getFieldNameByFormatFieldName("TMREVN_HOUR") => $record["TMREVN_HOUR"] . "", - $this->getFieldNameByFormatFieldName("TMREVN_MINUTE") => $record["TMREVN_MINUTE"] . "", + $this->getFieldNameByFormatFieldName("TMREVN_DAY") => $record["TMREVN_DAY"], + $this->getFieldNameByFormatFieldName("TMREVN_HOUR") => $record["TMREVN_HOUR"], + $this->getFieldNameByFormatFieldName("TMREVN_MINUTE") => $record["TMREVN_MINUTE"], $this->getFieldNameByFormatFieldName("TMREVN_CONFIGURATION_DATA") => $record["TMREVN_CONFIGURATION_DATA"], $this->getFieldNameByFormatFieldName("TMREVN_NEXT_RUN_DATE") => $record["TMREVN_NEXT_RUN_DATE"] . "", $this->getFieldNameByFormatFieldName("TMREVN_LAST_RUN_DATE") => $record["TMREVN_LAST_RUN_DATE"] . "", @@ -1069,5 +1129,429 @@ class TimerEvent throw $e; } } + + /** + * Log + * + * @param string $action Action + * @param string $value Value + * + * return void + */ + private function log($action, $value = "") + { + try { + $workspace = (defined("SYS_SYS"))? SYS_SYS : "Wokspace Undefined"; + $ipClient = \G::getIpAddress(); + + $username = "timereventcron"; + $fullname = "timereventcron"; + + \G::log("|". $workspace ."|". $ipClient ."|". $username . "|" . $fullname ."|" . $action . "|" . $value, PATH_DATA, "timerevent.log"); + } catch (\Exception $e) { + throw $e; + } + } + + /** + * Start/Continue case by Timer-Event + * + * @param string $datetime Datetime (yyyy-mm-dd hh:ii:ss) + * @param bool $frontEnd Flag to represent the terminal front-end + * + * return void + */ + public function startContinueCaseByTimerEvent($datetime, $frontEnd = false) + { + try { + \G::LoadClass("wsBase"); + + //Set variables + $ws = new \wsBase(); + $case = new \Cases(); + $common = new \ProcessMaker\Util\Common(); + + $common->setFrontEnd($frontEnd); + + list($year, $month, $day, $hour, $minute) = $this->getYearMonthDayHourMinuteSecondByDatetime($datetime); + + $date = "$year-$month-$day"; + $dateIni = "$year-$month-$day 00:00:00"; + $dateEnd = "$year-$month-$day 23:59:59"; + + //Start Timer-Event (start new case) /////////////////////////////////////////////////////////////////////// + $common->frontEndShow("START"); + + $this->log("START-NEW-CASES", "Date \"$datetime\": Start new cases"); + + //Query + $criteria = $this->getTimerEventCriteria(); + + $criteria->addSelectColumn(\BpmnEventPeer::EVN_NAME); + $criteria->addSelectColumn(\ElementTaskRelationPeer::TAS_UID); + + $arrayCondition = array(); + $arrayCondition[] = array(\TimerEventPeer::PRJ_UID, \ElementTaskRelationPeer::PRJ_UID, \Criteria::EQUAL); + $arrayCondition[] = array(\TimerEventPeer::EVN_UID, \ElementTaskRelationPeer::ELEMENT_UID, \Criteria::EQUAL); + $criteria->addJoinMC($arrayCondition, \Criteria::INNER_JOIN); + + $criteria->add(\ElementTaskRelationPeer::ELEMENT_TYPE, "bpmnEvent", \Criteria::EQUAL); + + $arrayCondition = array(); + $arrayCondition[] = array(\ElementTaskRelationPeer::PRJ_UID, \TaskPeer::PRO_UID, \Criteria::EQUAL); + $arrayCondition[] = array(\ElementTaskRelationPeer::TAS_UID, \TaskPeer::TAS_UID, \Criteria::EQUAL); + $criteria->addJoinMC($arrayCondition, \Criteria::INNER_JOIN); + + $criteria->add(\TaskPeer::TAS_TYPE, "START-TIMER-EVENT", \Criteria::EQUAL); + + $arrayCondition = array(); + $arrayCondition[] = array(\TimerEventPeer::PRJ_UID, \BpmnEventPeer::PRJ_UID, \Criteria::EQUAL); + $arrayCondition[] = array(\TimerEventPeer::EVN_UID, \BpmnEventPeer::EVN_UID, \Criteria::EQUAL); + $criteria->addJoinMC($arrayCondition, \Criteria::INNER_JOIN); + + $criteria->add(\BpmnEventPeer::EVN_TYPE, "START", \Criteria::EQUAL); + $criteria->add(\BpmnEventPeer::EVN_MARKER, "TIMER", \Criteria::EQUAL); + + $criteria->add(\TimerEventPeer::TMREVN_OPTION, array("HOURLY", "DAILY", "MONTHLY", "EVERY", "ONE-DATE-TIME"), \Criteria::IN); + $criteria->add(\TimerEventPeer::TMREVN_STATUS, "ACTIVE", \Criteria::EQUAL); + + $criteria->add( + $criteria->getNewCriterion(\TimerEventPeer::TMREVN_NEXT_RUN_DATE, $dateIni, \Criteria::GREATER_EQUAL)->addAnd( + $criteria->getNewCriterion(\TimerEventPeer::TMREVN_NEXT_RUN_DATE, $dateEnd, \Criteria::LESS_EQUAL))->addOr( + $criteria->getNewCriterion(\TimerEventPeer::TMREVN_NEXT_RUN_DATE, $dateIni, \Criteria::LESS_THAN)) + ); + + $criteria->add( + $criteria->getNewCriterion(\TimerEventPeer::TMREVN_END_DATE, $date, \Criteria::GREATER_EQUAL)->addOr( + $criteria->getNewCriterion(\TimerEventPeer::TMREVN_END_DATE, null, \Criteria::EQUAL)) + ); + + $rsCriteria = \TimerEventPeer::doSelectRS($criteria); + $rsCriteria->setFetchmode(\ResultSet::FETCHMODE_ASSOC); + + $flagRecord = false; + + while ($rsCriteria->next()) { + $row = $rsCriteria->getRow(); + $row["TMREVN_CONFIGURATION_DATA"] = unserialize($row["TMREVN_CONFIGURATION_DATA"]); + + //Set variables + $arrayTimerEventData = $row; + + $bpmnEventName = $row["EVN_NAME"]; + $taskUid = $row["TAS_UID"]; + + //Create the new case + $timerEventNextRunDate = $arrayTimerEventData["TMREVN_NEXT_RUN_DATE"]; + $timerEventNextRunDateNew = ""; + + $flagCase = false; + + if (strtotime($timerEventNextRunDate) < strtotime($dateIni)) { + $timerEventNextRunDateNew = $this->getNextRunDateByDataAndDatetime($arrayTimerEventData, $datetime); //Generate new date for old TMREVN_NEXT_RUN_DATE + + $flagCase = true; //Create the old case + } else { + list( , , , $hourCase, $minuteCase) = $this->getYearMonthDayHourMinuteSecondByDatetime($timerEventNextRunDate); + + if ((int)($hour . $minute) <= (int)($hourCase . $minuteCase)) { + $flagCase = $hourCase == $hour && $minuteCase == $minute; + } else { + $flagCase = true; //Create the old case + } + } + + if ($flagCase) { + if ($flagRecord) { + $common->frontEndShow("TEXT", ""); + } + + if ($bpmnEventName != "") { + $common->frontEndShow("TEXT", "> Name Timer-Event: $bpmnEventName"); + } + + $common->frontEndShow("TEXT", "> Creating the new case..."); + + //Start new case + $result = $ws->newCase($arrayTimerEventData["PRJ_UID"], "", $taskUid, array()); + + $arrayResult = json_decode(json_encode($result), true); + + if ($arrayResult["status_code"] == 0) { + $applicationUid = $arrayResult["caseId"]; + $applicationNumber = $arrayResult["caseNumber"]; + + $common->frontEndShow("TEXT", " - OK case #$applicationNumber was created"); + $common->frontEndShow("TEXT", "> Routing the case #$applicationNumber..."); + + $this->log("CREATED-NEW-CASE", "Case #$applicationNumber created, APP_UID: $applicationUid, PRO_UID: " . $arrayTimerEventData["PRJ_UID"]); + + //Derivate new case + $result = $ws->derivateCase("", $applicationUid, 1); + + $arrayResult = json_decode(json_encode($result), true); + + if ($arrayResult["status_code"] == 0) { + $common->frontEndShow("TEXT", " - OK"); + + $this->log("ROUTED-NEW-CASE", "Case #$applicationNumber routed, APP_UID: $applicationUid, PRO_UID: " . $arrayTimerEventData["PRJ_UID"]); + } else { + $common->frontEndShow("TEXT", " - Failed: " . $arrayResult["message"]); + + $this->log("ROUTED-NEW-CASE", "Failed: " . $arrayResult["message"] . ", Case: #$applicationNumber, APP_UID: $applicationUid, PRO_UID: " . $arrayTimerEventData["PRJ_UID"]); + } + } else { + $common->frontEndShow("TEXT", " - Failed: " . $arrayResult["message"]); + + $this->log("CREATED-NEW-CASE", "Failed: " . $arrayResult["message"] . ", PRO_UID: " . $arrayTimerEventData["PRJ_UID"]); + } + + //Update Timer-Event + $arrayData = array(); + + switch ($arrayTimerEventData["TMREVN_OPTION"]) { + case "HOURLY": + case "DAILY": + case "MONTHLY": + case "EVERY": + if ($timerEventNextRunDateNew == "") { + $timerEventNextRunDateNew = $this->getNextRunDateByDataAndDatetime($arrayTimerEventData, $timerEventNextRunDate, false); + } + + if ($arrayTimerEventData["TMREVN_OPTION"] != "EVERY" && + $arrayTimerEventData["TMREVN_END_DATE"] . "" != "" && strtotime($timerEventNextRunDateNew) > strtotime($arrayTimerEventData["TMREVN_END_DATE"] . " 23:59:59") + ) { + $arrayData["TMREVN_STATUS"] = "PROCESSED"; + } else { + $arrayData["TMREVN_NEXT_RUN_DATE"] = $timerEventNextRunDateNew; + } + break; + case "ONE-DATE-TIME": + $arrayData["TMREVN_STATUS"] = "PROCESSED"; + break; + } + + $arrayData["TMREVN_LAST_RUN_DATE"] = $timerEventNextRunDate; + $arrayData["TMREVN_LAST_EXECUTION_DATE"] = date("Y-m-d H:i:s"); + + $result = $this->singleUpdate($arrayTimerEventData["TMREVN_UID"], $arrayData); + + $flagRecord = true; + } + } + + if (!$flagRecord) { + $common->frontEndShow("TEXT", "Not exists any record to start a new case, on date \"$datetime\""); + + $this->log("NO-RECORDS", "Not exists any record to start a new case"); + } + + $common->frontEndShow("END"); + + $this->log("END-NEW-CASES", "Date \"$datetime\": End new cases"); + + //Intermediate Catch Timer-Event (continue the case) /////////////////////////////////////////////////////// + $this->log("START-CONTINUE-CASES", "Date \"$datetime\": Start continue the cases"); + + //Query + $criteriaMain = $this->getTimerEventCriteria(); + + $criteriaMain->addSelectColumn(\AppDelegationPeer::APP_UID); + $criteriaMain->addSelectColumn(\AppDelegationPeer::DEL_INDEX); + $criteriaMain->addSelectColumn(\AppDelegationPeer::DEL_DELEGATE_DATE); + $criteriaMain->addSelectColumn(\BpmnEventPeer::EVN_NAME); + + $arrayCondition = array(); + $arrayCondition[] = array(\AppDelegationPeer::APP_UID, \ApplicationPeer::APP_UID, \Criteria::EQUAL); + $criteriaMain->addJoinMC($arrayCondition, \Criteria::INNER_JOIN); + + $criteriaMain->add(\ApplicationPeer::APP_STATUS, "DRAFT", \Criteria::NOT_EQUAL); + + $arrayCondition = array(); + $arrayCondition[] = array(\AppDelegationPeer::PRO_UID, \TaskPeer::PRO_UID, \Criteria::EQUAL); + $arrayCondition[] = array(\AppDelegationPeer::TAS_UID, \TaskPeer::TAS_UID, \Criteria::EQUAL); + $criteriaMain->addJoinMC($arrayCondition, \Criteria::INNER_JOIN); + + $criteriaMain->add(\TaskPeer::TAS_TYPE, "INTERMEDIATE-CATCH-TIMER-EVENT", \Criteria::EQUAL); + + $arrayCondition = array(); + $arrayCondition[] = array(\TaskPeer::PRO_UID, \ElementTaskRelationPeer::PRJ_UID, \Criteria::EQUAL); + $arrayCondition[] = array(\TaskPeer::TAS_UID, \ElementTaskRelationPeer::TAS_UID, \Criteria::EQUAL); + $criteriaMain->addJoinMC($arrayCondition, \Criteria::INNER_JOIN); + + $criteriaMain->add(\ElementTaskRelationPeer::ELEMENT_TYPE, "bpmnEvent", \Criteria::EQUAL); + + $arrayCondition = array(); + $arrayCondition[] = array(\ElementTaskRelationPeer::PRJ_UID, \TimerEventPeer::PRJ_UID, \Criteria::EQUAL); + $arrayCondition[] = array(\ElementTaskRelationPeer::ELEMENT_UID, \TimerEventPeer::EVN_UID, \Criteria::EQUAL); + $criteriaMain->addJoinMC($arrayCondition, \Criteria::INNER_JOIN); + + $arrayCondition = array(); + $arrayCondition[] = array(\TimerEventPeer::PRJ_UID, \BpmnEventPeer::PRJ_UID, \Criteria::EQUAL); + $arrayCondition[] = array(\TimerEventPeer::EVN_UID, \BpmnEventPeer::EVN_UID, \Criteria::EQUAL); + $criteriaMain->addJoinMC($arrayCondition, \Criteria::INNER_JOIN); + + $criteriaMain->add(\BpmnEventPeer::EVN_TYPE, "INTERMEDIATE", \Criteria::EQUAL); + $criteriaMain->add(\BpmnEventPeer::EVN_MARKER, "TIMER", \Criteria::EQUAL); + + $criteriaMain->add(\TimerEventPeer::TMREVN_OPTION, array("WAIT-FOR", "WAIT-UNTIL-SPECIFIED-DATE-TIME"), \Criteria::IN); + $criteriaMain->add(\TimerEventPeer::TMREVN_STATUS, "ACTIVE", \Criteria::EQUAL); + + $criteriaMain->add(\AppDelegationPeer::DEL_THREAD_STATUS, "OPEN", \Criteria::EQUAL); + $criteriaMain->add(\AppDelegationPeer::DEL_FINISH_DATE, null, \Criteria::ISNULL); + + //Number records total + $criteriaCount = clone $criteriaMain; + + $criteriaCount->clearSelectColumns(); + $criteriaCount->addSelectColumn("COUNT(" . \AppDelegationPeer::APP_UID . ") AS NUM_REC"); + + $rsCriteriaCount = \AppDelegationPeer::doSelectRS($criteriaCount); + $rsCriteriaCount->setFetchmode(\ResultSet::FETCHMODE_ASSOC); + + $result = $rsCriteriaCount->next(); + $row = $rsCriteriaCount->getRow(); + + $numRecTotal = $row["NUM_REC"]; + + //Query + $total = $numRecTotal; + $counter = 0; + + $start = 0; + $limit = 1000; + + $flagRecord = false; + + do { + $flagNextRecord = false; + + $criteria = clone $criteriaMain; + + $criteria->setOffset($start); + $criteria->setLimit($limit); + + $rsCriteria = \AppDelegationPeer::doSelectRS($criteria); + $rsCriteria->setFetchmode(\ResultSet::FETCHMODE_ASSOC); + + while ($rsCriteria->next()) { + if ($counter + 1 > $total) { + $flagNextRecord = false; + break; + } + + $row = $rsCriteria->getRow(); + $row["TMREVN_CONFIGURATION_DATA"] = unserialize($row["TMREVN_CONFIGURATION_DATA"]); + + //Set variables + $arrayTimerEventData = $row; + $arrayApplicationData = $case->loadCase($row["APP_UID"]); + + $applicationUid = $row["APP_UID"]; + $applicationNumber = $arrayApplicationData["APP_NUMBER"]; + $delIndex = $row["DEL_INDEX"]; + $delDelegateDate = $row["DEL_DELEGATE_DATE"]; + $bpmnEventName = $row["EVN_NAME"]; + + //Continue the case + $continueCaseDate = $delDelegateDate; + + switch ($arrayTimerEventData["TMREVN_OPTION"]) { + case "WAIT-FOR": + if ($arrayTimerEventData["TMREVN_DAY"] . "" != "") { + $continueCaseDate = date("Y-m-d H:i:s", strtotime("$continueCaseDate +" . ((int)($arrayTimerEventData["TMREVN_DAY"])) . " days")); + } + + if ($arrayTimerEventData["TMREVN_HOUR"] . "" != "") { + $continueCaseDate = date("Y-m-d H:i:s", strtotime("$continueCaseDate +" . ((int)($arrayTimerEventData["TMREVN_HOUR"])) . " hours")); + } + + if ($arrayTimerEventData["TMREVN_MINUTE"] . "" != "") { + $continueCaseDate = date("Y-m-d H:i:s", strtotime("$continueCaseDate +" . ((int)($arrayTimerEventData["TMREVN_MINUTE"])) . " minutes")); + } + break; + case "WAIT-UNTIL-SPECIFIED-DATE-TIME": + $continueCaseDate = \G::replaceDataField($arrayTimerEventData["TMREVN_CONFIGURATION_DATA"], $arrayApplicationData["APP_DATA"]); + break; + } + + $arrayContinueCaseDateData = $this->getYearMonthDayHourMinuteSecondByDatetime($continueCaseDate); + + if (!empty($arrayContinueCaseDateData)) { + $flagCase = false; + + if (strtotime($continueCaseDate) < strtotime($dateIni)) { + $flagCase = true; //Continue the old case + } else { + $yearCase = $arrayContinueCaseDateData[0]; + $monthCase = $arrayContinueCaseDateData[1]; + $dayCase = $arrayContinueCaseDateData[2]; + $hourCase = $arrayContinueCaseDateData[3]; + $minuteCase = $arrayContinueCaseDateData[4]; + + if ("$yearCase-$monthCase-$dayCase" == "$year-$month-$day") { + if ((int)($hour . $minute) <= (int)($hourCase . $minuteCase)) { + $flagCase = $hourCase == $hour && $minuteCase == $minute; + } else { + $flagCase = true; //Continue the old case + } + } + } + + if ($flagCase) { + if ($flagRecord) { + $common->frontEndShow("TEXT", ""); + } + + if ($bpmnEventName != "") { + $common->frontEndShow("TEXT", "> Name Timer-Event: $bpmnEventName"); + } + + $common->frontEndShow("TEXT", "> Continue the case #$applicationNumber"); + $common->frontEndShow("TEXT", "> Routing the case #$applicationNumber..."); + + //Continue the case + //Derivate case + $result = $ws->derivateCase("", $applicationUid, $delIndex); + + $arrayResult = json_decode(json_encode($result), true); + + if ($arrayResult["status_code"] == 0) { + $common->frontEndShow("TEXT", " - OK"); + + $this->log("CONTINUED-CASE", "Case #$applicationNumber continued, APP_UID: $applicationUid, PRO_UID: " . $arrayTimerEventData["PRJ_UID"]); + } else { + $common->frontEndShow("TEXT", " - Failed: " . $arrayResult["message"]); + + $this->log("CONTINUED-CASE", "Failed: " . $arrayResult["message"] . ", Case: #$applicationNumber, APP_UID: $applicationUid, PRO_UID: " . $arrayTimerEventData["PRJ_UID"]); + } + + $flagRecord = true; + } + } else { + $this->log("INVALID-CONTINUE-DATE", "Continue date: $continueCaseDate, Case: #$applicationNumber, APP_UID: $applicationUid, PRO_UID: " . $arrayTimerEventData["PRJ_UID"]); + } + + $counter++; + + $flagNextRecord = true; + } + + $start = $start + $limit; + } while ($flagNextRecord); + + if (!$flagRecord) { + $common->frontEndShow("TEXT", "Not exists any record to continue a case, on date \"$datetime\""); + + $this->log("NO-RECORDS", "Not exists any record to continue a case"); + } + + $common->frontEndShow("END"); + + $this->log("END-CONTINUE-CASES", "Date \"$datetime\": End continue the cases"); + } catch (\Exception $e) { + throw $e; + } + } }