Merged in feature/PMCORE-640 (pull request #7271)

PMCORE-640

Approved-by: Julio Cesar Laura Avendaño <contact@julio-laura.com>
Approved-by: Paula Quispe <paula.quispe@processmaker.com>
This commit is contained in:
Paula Quispe
2020-11-25 13:23:49 +00:00
committed by Julio Cesar Laura Avendaño
35 changed files with 1267 additions and 514 deletions

View File

@@ -5,21 +5,21 @@ use Faker\Generator as Faker;
$factory->define(\ProcessMaker\Model\Application::class, function(Faker $faker) {
$user = factory(\ProcessMaker\Model\User::class)->create();
$appNumber = $faker->unique()->numberBetween(1000);
// APP_TITLE field is used in 'MYSQL: MATCH() AGAINST()' function, string size should not be less than 3.
$appTitle = $faker->lexify(str_repeat('?', rand(3, 5)) . ' ' . str_repeat('?', rand(3, 5)));
//APP_STATUS must start in TO_DO because all tests require this state.
return [
'APP_UID' => G::generateUniqueID(),
'APP_TITLE' => $appTitle,
'APP_DESCRIPTION' => $faker->text,
'APP_NUMBER' => $appNumber,
'APP_STATUS' => 'TO_DO',
'APP_STATUS_ID' => 2,
'PRO_UID' => function() {
return factory(\ProcessMaker\Model\Process::class)->create()->PRO_UID;
},
'APP_PROC_STATUS' => '',
'APP_PROC_CODE' => '',
'APP_PARALLEL' => 'N',
'APP_INIT_USER' => $user->USR_UID,
'APP_CUR_USER' => $user->USR_UID,
@@ -41,15 +41,19 @@ $factory->state(\ProcessMaker\Model\Application::class, 'foreign_keys', function
// APP_TITLE field is used in 'MYSQL: MATCH() AGAINST()' function, string size should not be less than 3.
$appTitle = $faker->lexify(str_repeat('?', rand(3, 5)) . ' ' . str_repeat('?', rand(3, 5)));
//APP_STATUS must start in TO_DO because all tests require this state.
$statuses = ['DRAFT', 'TO_DO', 'COMPLETED', 'CANCELLED'];
$status = $faker->randomElement($statuses);
$statusId = array_search($status, $statuses) + 1;
return [
'APP_UID' => G::generateUniqueID(),
'APP_TITLE' => $appTitle,
'APP_NUMBER' => $appNumber,
'APP_STATUS' => 'TO_DO',
'APP_STATUS_ID' => 2,
'APP_STATUS' => $status,
'APP_STATUS_ID' => $statusId,
'PRO_UID' => $process->PRO_UID,
'APP_PROC_STATUS' => '',
'APP_PROC_CODE' => '',
'APP_PARALLEL' => 'N',
'APP_INIT_USER' => $user->USR_UID,
'APP_CUR_USER' => $user->USR_UID,

View File

@@ -18,3 +18,4 @@ $factory->define(\ProcessMaker\Model\BpmnProcess::class, function(Faker $faker)
'PRO_IS_SUBPROCESS' => 0,
];
});

View File

@@ -3,17 +3,22 @@
use Faker\Generator as Faker;
$factory->define(\ProcessMaker\Model\BpmnProject::class, function (Faker $faker) {
// Create user
$user = factory(\ProcessMaker\Model\User::class)->create();
// Create process
$process = factory(\ProcessMaker\Model\Process::class)->create();
return [
'PRJ_UID' => G::generateUniqueID(),
'PRJ_NAME' => '',
'PRJ_NAME' => $faker->sentence(5),
'PRJ_DESCRIPTION' => $faker->text,
'PRJ_EXPRESION_LANGUAGE' => '',
'PRJ_TYPE_LANGUAGE' => '',
'PRJ_EXPORTER' => '',
'PRJ_EXPORTER_VERSION' => '',
'PRJ_CREATE_DATE' => new \Carbon\Carbon(2030, 1, 1),
'PRJ_UPDATE_DATE' => new \Carbon\Carbon(2030, 1, 1),
'PRJ_AUTHOR' => '',
'PRJ_CREATE_DATE' => $faker->dateTime(),
'PRJ_UPDATE_DATE' => $faker->dateTime(),
'PRJ_AUTHOR' => $user->USR_UID,
'PRJ_AUTHOR_VERSION' => '',
'PRJ_ORIGINAL_SOURCE' => '',
];

View File

@@ -5,20 +5,25 @@
use Faker\Generator as Faker;
$factory->define(\ProcessMaker\Model\Process::class, function(Faker $faker) {
// Return with default values
//The incremental fields of the tables must not be specified in the creation list.
return [
'PRO_UID' => G::generateUniqueID(),
'PRO_ID' => $faker->unique()->numberBetween(1000),
'PRO_TITLE' => $faker->sentence(3),
'PRO_DESCRIPTION' => $faker->paragraph(3),
'PRO_CREATE_USER' => '00000000000000000000000000000001',
'PRO_DYNAFORMS' => '',
'PRO_ITEE' => 1,
'PRO_PARENT' => G::generateUniqueID(),
'PRO_STATUS' => 'ACTIVE',
'PRO_STATUS_ID' => 1,
'PRO_TYPE' => 'NORMAL',
'PRO_ASSIGNMENT' => 'FALSE',
'PRO_TYPE_PROCESS' => 'PUBLIC',
'PRO_UPDATE_DATE' => $faker->dateTime(),
'PRO_CREATE_DATE' => $faker->dateTime(),
'PRO_CREATE_USER' => '00000000000000000000000000000001',
'PRO_DEBUG' => 0,
'PRO_DYNAFORMS' => serialize([]),
'PRO_ITEE' => 1,
'PRO_ACTION_DONE' => serialize([]),
'PRO_CATEGORY' => function() {
return factory(\ProcessMaker\Model\ProcessCategory::class)->create()->CATEGORY_UID;
},
@@ -27,44 +32,29 @@ $factory->define(\ProcessMaker\Model\Process::class, function(Faker $faker) {
// Create a process with the foreign keys
$factory->state(\ProcessMaker\Model\Process::class, 'foreign_keys', function (Faker $faker) {
// Create user
$user = factory(\ProcessMaker\Model\User::class)->create();
return [
'PRO_UID' => G::generateUniqueID(),
'PRO_ID' => $faker->unique()->numberBetween(1000),
'PRO_TITLE' => $faker->sentence(3),
'PRO_DESCRIPTION' => $faker->paragraph(3),
'PRO_CREATE_USER' => $user->USR_UID,
'PRO_DYNAFORMS' => '',
'PRO_ITEE' => 1,
'PRO_PARENT' => G::generateUniqueID(),
'PRO_STATUS' => 'ACTIVE',
'PRO_STATUS_ID' => 1,
'PRO_TYPE' => 'NORMAL',
'PRO_ASSIGNMENT' => 'FALSE',
'PRO_TYPE_PROCESS' => 'PUBLIC',
'PRO_UPDATE_DATE' => $faker->dateTime(),
'PRO_CREATE_DATE' => $faker->dateTime(),
'PRO_CATEGORY' => '',
];
});
// Create a process related to the flow designer
$factory->state(\ProcessMaker\Model\Process::class, 'flow', function (Faker $faker) {
// Create values in the foreign key relations
$user = factory(\ProcessMaker\Model\User::class)->create();
$process = [
'PRO_UID' => G::generateUniqueID(),
'PRO_TITLE' => $faker->sentence(3),
'PRO_DESCRIPTION' => $faker->paragraph(3),
'PRO_CREATE_USER' => $user->USR_UID,
'PRO_DYNAFORMS' => '',
'PRO_DEBUG' => 0,
'PRO_DYNAFORMS' => serialize([]),
'PRO_ITEE' => 1,
'PRO_STATUS' => 'ACTIVE',
'PRO_STATUS_ID' => 1,
'PRO_TYPE_PROCESS' => 'PUBLIC',
'PRO_UPDATE_DATE' => $faker->dateTime(),
'PRO_CREATE_DATE' => $faker->dateTime(),
'PRO_CATEGORY' => '',
'PRO_ACTION_DONE' => serialize([]),
'PRO_CATEGORY' => function() {
return factory(\ProcessMaker\Model\ProcessCategory::class)->create()->CATEGORY_UID;
},
];
// Create a task related to this process
$task = factory(\ProcessMaker\Model\Task::class)->create([
'PRO_UID' => $process->PRO_UID,
'PRO_ID' => $process->PRO_ID,
]);
});

View File

@@ -17,6 +17,15 @@ class ProcessTest extends TestCase
{
use DatabaseTransactions;
/**
* Call the setUp parent method
*/
public function setUp()
{
parent::setUp();
Process::query()->delete();
}
/**
* Test belongs to PRO_ID
*
@@ -242,4 +251,92 @@ class ProcessTest extends TestCase
// This asserts the process was converted from private to public
$this->assertEquals('PUBLIC', $p[0]->PRO_TYPE_PROCESS);
}
/**
* It tests the process list
*
* @covers \ProcessMaker\Model\Process::getProcessesFilter()
* @covers \ProcessMaker\Model\Process::scopeNoStatus()
* @covers \ProcessMaker\Model\Process::scopeSubProcess()
* @test
*/
public function it_should_test_process_without_filter()
{
$process = factory(Process::class)->create();
$result = Process::getProcessesFilter(
null,
null,
null,
$process->PRO_CREATE_USER
);
$this->assertEquals($process->PRO_CREATE_USER, $result[0]['USR_UID']);
}
/**
* It tests the process list with specific category
*
* @covers \ProcessMaker\Model\Process::getProcessesFilter()
* @covers \ProcessMaker\Model\Process::scopeCategory()
* @test
*/
public function it_should_test_process_with_category_filter()
{
$process = factory(Process::class)->create([
'PRO_CATEGORY' => function () {
return factory(ProcessCategory::class)->create()->CATEGORY_UID;
}
]);
$result = Process::getProcessesFilter(
$process->PRO_CATEGORY
);
$this->assertEquals($process->PRO_CATEGORY, $result[0]['PRO_CATEGORY']);
}
/**
* It tests the process list with specific process
*
* @covers \ProcessMaker\Model\Process::getProcessesFilter()
* @covers \ProcessMaker\Model\Process::scopeProcess()
* @test
*/
public function it_should_test_process_with_process_filter()
{
$process = factory(Process::class)->create();
$result = Process::getProcessesFilter(
null,
$process->PRO_UID
);
$this->assertEquals($process->PRO_UID, $result[0]['PRO_UID']);
}
/**
* It tests the process list with specific process title
*
* @covers \ProcessMaker\Model\Process::getProcessesFilter()
* @covers \ProcessMaker\Model\Process::scopeTitle()
* @test
*/
public function it_should_test_process_with_title_filter()
{
$process = factory(Process::class)->create();
$result = Process::getProcessesFilter(
null,
null,
$process->PRO_TITLE
);
$this->assertEquals($process->PRO_TITLE, $result[0]['PRO_TITLE']);
}
/**
* It tests the count process
*
* @covers \ProcessMaker\Model\Process::getCounter()
* @test
*/
public function it_should_test_count_process()
{
$process = factory(Process::class)->create();
$total = Process::getCounter($process->PRO_CREATE_USER);
$this->assertEquals(1, $total);
}
}

View File

@@ -17,7 +17,8 @@ try {
'ldapcron' => ['title' => 'LDAP Advanced CRON'],
'messageeventcron' => ['title' => 'Message-Event CRON'],
'timereventcron' => ['title' => 'Timer-Event CRON'],
'sendnotificationscron' => ['title' => 'Send-Notifications CRON']
'sendnotificationscron' => ['title' => 'Send-Notifications CRON'],
'webentriescron' => ['title' => 'Web Entries CRON']
];
//Define constants

View File

@@ -6,6 +6,8 @@
* @see workflow/engine/bin/cron.php
* @see workflow/engine/bin/timereventcron.php
* @see workflow/engine/bin/ldapcron.php
* @see workflow/engine/bin/sendnotificationscron.php
* @see workflow/engine/bin/webentriescron.php
* @see workflow/engine/methods/setup/cron.php
*
* @link https://wiki.processmaker.com/3.2/Executing_cron.php
@@ -18,6 +20,7 @@ require_once __DIR__ . '/../../../gulliver/system/class.g.php';
require_once __DIR__ . '/../../../bootstrap/autoload.php';
require_once __DIR__ . '/../../../bootstrap/app.php';
use ProcessMaker\BusinessModel\WebEntry;
use ProcessMaker\Core\JobsManager;
use ProcessMaker\Core\System;
use ProcessMaker\Plugins\PluginRegistry;
@@ -345,6 +348,11 @@ try {
$task->sendNotifications();
}
break;
case 'webentriescron':
setExecutionMessage('Deleting web entry cases created one week ago or more');
WebEntry::deleteOldWebEntries();
setExecutionResultMessage('FINISHED');
break;
/*----------------------------------********---------------------------------*/
case 'actionsByEmailEmailResponse':
$task = new Task($asynchronous, $sObject);

View File

@@ -1,5 +1,6 @@
<?php
use ProcessMaker\BusinessModel\WebEntry;
use ProcessMaker\Core\JobsManager;
use ProcessMaker\Model\Process;
use ProcessMaker\Validation\MySQL57;
@@ -439,6 +440,16 @@ EOT
CLI::taskArg('workspace');
CLI::taskRun('add_async_option_to_scheduler_commands');
/**
* Convert Web Entries v1.0 to v2.0 for BPMN processes in order to deprecate the old version.
*/
CLI::taskName('convert-old-web-entries');
CLI::taskDescription(<<<EOT
Convert Web Entries v1.0 to v2.0 for BPMN processes in order to deprecate the old version.
EOT
);
CLI::taskRun('convert_old_web_entries');
/**
* Function run_info
*
@@ -1640,3 +1651,41 @@ function add_async_option_to_scheduler_commands($args, $opts)
}
}
}
/**
* Convert Web Entries v1.0 to v2.0 for BPMN processes in order to deprecate the old version.
*
* @param array $args
*/
function convert_old_web_entries($args)
{
try {
if (!empty($args)) {
// Print initial message
$start = microtime(true);
CLI::logging("> Converting Web Entries v1.0 to v2.0 for BPMN processes...\n");
// Set workspace constants and initialize DB connection
Bootstrap::setConstantsRelatedWs($args[0]);
Propel::init(PATH_CONFIG . 'databases.php');
// Convert Web Entries
WebEntry::convertFromV1ToV2();
// Print last message
$stop = microtime(true);
CLI::logging("<*> Converting Web Entries v1.0 to v2.0 for BPMN processes data took " . ($stop - $start) . " seconds.\n");
} else {
// If a workspace is not specified, get all available workspaces in the server
$workspaces = get_workspaces_from_args($args);
// Execute the command for each workspace
foreach ($workspaces as $workspace) {
passthru(PHP_BINARY . ' processmaker convert-old-web-entries ' . $workspace->name);
}
}
} catch (Exception $e) {
// Display the error message
CLI::logging($e->getMessage() . PHP_EOL . PHP_EOL);
}
}

View File

@@ -0,0 +1,3 @@
<?php
require_once 'cron.php';

View File

@@ -983,7 +983,8 @@ class Cases
/** Update case*/
$app->update($Fields);
//Update the reportTables and tables related to the case
//Update the reportTables and tables related to the case, only for applications with positive application number
if ($appFields['APP_NUMBER'] > 0) {
require_once 'classes/model/AdditionalTables.php';
$reportTables = new ReportTables();
$additionalTables = new additionalTables();
@@ -999,6 +1000,7 @@ class Cases
$additionalTables->updateReportTables(
$appFields['PRO_UID'], $appUid, $Fields['APP_NUMBER'], $appData, $Fields['APP_STATUS']
);
}
//Update the priority related to the task
$delIndex = isset($Fields['DEL_INDEX']) ? trim($Fields['DEL_INDEX']) : '';
@@ -2105,167 +2107,169 @@ class Cases
* This function start a case using the task for the user $sUsrUid
* With this function we can Start a case
*
* @name startCase
* @param string $sTasUid
* @param string $sUsrUid
* @return Fields
* @param string $taskUid
* @param string $userUid
* @param bool $isSubProcess
* @param array $dataPreviousApplication
* @param bool $isSelfService
* @param string $sequenceType
* @return array
* @throws Exception
*/
public function startCase($sTasUid, $sUsrUid, $isSubprocess = false, $dataPreviusApplication = array(), $isSelfService = false)
public function startCase($taskUid, $userUid, $isSubProcess = false, $dataPreviousApplication = [], $isSelfService = false, $sequenceType = AppSequence::APP_TYPE_NORMAL)
{
if ($sTasUid != '') {
if ($taskUid != '') {
try {
$task = TaskPeer::retrieveByPK($sTasUid);
$user = UsersPeer::retrieveByPK($sUsrUid);
$task = TaskPeer::retrieveByPK($taskUid);
$user = UsersPeer::retrieveByPK($userUid);
if (is_null($task)) {
throw new Exception(G::LoadTranslation("ID_TASK_NOT_EXIST", array("TAS_UID", $sTasUid)));
throw new Exception(G::LoadTranslation("ID_TASK_NOT_EXIST", ["TAS_UID", $taskUid]));
}
// To allow Self Service as the first task
$arrayTaskTypeToExclude = array("START-TIMER-EVENT");
$arrayTaskTypeToExclude = ["START-TIMER-EVENT"];
if (!is_null($task) && !in_array($task->getTasType(), $arrayTaskTypeToExclude) && $task->getTasAssignType() != "SELF_SERVICE" && $sUsrUid == "") {
if (!is_null($task) && !in_array($task->getTasType(), $arrayTaskTypeToExclude) && $task->getTasAssignType() != "SELF_SERVICE" && $userUid == "") {
throw (new Exception('You tried to start a new case without send the USER UID!'));
}
// Process
$sProUid = $task->getProUid();
$processUid = $task->getProUid();
$this->Process = new Process;
$proFields = $this->Process->Load($sProUid);
$proFields = $this->Process->Load($processUid);
//application
$Application = new Application;
$sAppUid = $Application->create($sProUid, $sUsrUid);
// Application
$application = new Application;
$appUid = $application->create($processUid, $userUid, $sequenceType);
//appDelegation
$AppDelegation = new AppDelegation;
$iAppThreadIndex = 1; // Start Thread
$iAppDelPrio = 3; // Priority
$iDelIndex = $AppDelegation->createAppDelegation(
$sProUid,
$sAppUid,
$sTasUid,
$sUsrUid,
$iAppThreadIndex,
$iAppDelPrio,
$isSubprocess,
// AppDelegation
$appDelegation = new AppDelegation;
$appThreadIndex = 1; // Start Thread
$appDelPriority = 3; // Priority
$delIndex = $appDelegation->createAppDelegation(
$processUid,
$appUid,
$taskUid,
$userUid,
$appThreadIndex,
$appDelPriority,
$isSubProcess,
-1,
null,
false,
false,
0,
$Application->getAppNumber(),
$application->getAppNumber(),
$task->getTasId(),
(empty($user)) ? 0 : $user->getUsrId(),
$this->Process->getProId()
);
//appThread
$AppThread = new AppThread;
$iAppThreadIndex = $AppThread->createAppThread($sAppUid, $iDelIndex, 0);
// AppThread
$appThread = new AppThread;
$appThreadIndex = $appThread->createAppThread($appUid, $delIndex, 0);
$oDerivation = new Derivation();
$derivation = new Derivation();
// Multiple Instance
$aUserFields = array();
$usersFields = [];
$taskAssignType = $task->getTasAssignType();
$nextTaskAssignVariable = $task->getTasAssignVariable();
if ($taskAssignType == "MULTIPLE_INSTANCE" || $taskAssignType == "MULTIPLE_INSTANCE_VALUE_BASED") {
switch ($taskAssignType) {
case 'MULTIPLE_INSTANCE':
$userFields = $oDerivation->getUsersFullNameFromArray($oDerivation->getAllUsersFromAnyTask($sTasUid));
$userFields = $derivation->getUsersFullNameFromArray($derivation->getAllUsersFromAnyTask($taskUid));
break;
default:
throw (new Exception('Invalid Task Assignment method'));
break;
}
$userFields = $oDerivation->getUsersFullNameFromArray($oDerivation->getAllUsersFromAnyTask($sTasUid));
$userFields = $derivation->getUsersFullNameFromArray($derivation->getAllUsersFromAnyTask($taskUid));
$count = 0;
foreach ($userFields as $rowUser) {
if ($rowUser["USR_UID"] != $sUsrUid) {
//appDelegation
$AppDelegation = new AppDelegation;
$iAppThreadIndex ++; // Start Thread
$iAppDelPrio = 3; // Priority
if ($rowUser["USR_UID"] != $userUid) {
// AppDelegation
$appDelegation = new AppDelegation;
$appThreadIndex ++; // Start Thread
$appDelPriority = 3; // Priority
$user = UsersPeer::retrieveByPK($rowUser["USR_UID"]);
$iDelIndex1 = $AppDelegation->createAppDelegation(
$sProUid,
$sAppUid,
$sTasUid,
$delIndex1 = $appDelegation->createAppDelegation(
$processUid,
$appUid,
$taskUid,
$rowUser["USR_UID"],
$iAppThreadIndex,
$iAppDelPrio,
$isSubprocess,
$appThreadIndex,
$appDelPriority,
$isSubProcess,
-1,
null,
false,
false,
0,
$Application->getAppNumber(),
$application->getAppNumber(),
$task->getTasId(),
(empty($user)) ? 0 : $user->getUsrId(),
$this->Process->getProId()
);
//appThread
$AppThread = new AppThread;
$iAppThreadIndex = $AppThread->createAppThread($sAppUid, $iDelIndex1, 0);
// AppThread
$appThread = new AppThread;
$appThreadIndex = $appThread->createAppThread($appUid, $delIndex1, 0);
// Save Information
$aUserFields[$count] = $rowUser;
$aUserFields[$count]["DEL_INDEX"] = $iDelIndex1;
$usersFields[$count] = $rowUser;
$usersFields[$count]["DEL_INDEX"] = $delIndex1;
$count++;
}
}
}
//DONE: Al ya existir un delegation, se puede "calcular" el caseTitle.
$Fields = $Application->toArray(BasePeer::TYPE_FIELDNAME);
$aApplicationFields = $Fields['APP_DATA'];
$Fields['DEL_INDEX'] = $iDelIndex;
$newValues = $this->newRefreshCaseTitleAndDescription($sAppUid, $Fields, $aApplicationFields);
$fields = $application->toArray(BasePeer::TYPE_FIELDNAME);
$applicationFields = $fields['APP_DATA'];
$fields['DEL_INDEX'] = $delIndex;
$newValues = $this->newRefreshCaseTitleAndDescription($appUid, $fields, $applicationFields);
if (!isset($newValues['APP_TITLE'])) {
$newValues['APP_TITLE'] = '';
}
$caseNumber = $Fields['APP_NUMBER'];
$Application->update($Fields);
$caseNumber = $fields['APP_NUMBER'];
$application->update($fields);
// Update the task last assigned (for web entry and web services)
$oDerivation->setTasLastAssigned($sTasUid, $sUsrUid);
$derivation->setTasLastAssigned($taskUid, $userUid);
// Execute Events
require_once 'classes/model/Event.php';
$event = new Event();
$event->createAppEvents($sProUid, $sAppUid, $iDelIndex, $sTasUid);
$event->createAppEvents($processUid, $appUid, $delIndex, $taskUid);
//update searchindex
// Update search index
if ($this->appSolr != null) {
$this->appSolr->updateApplicationSearchIndex($sAppUid);
$this->appSolr->updateApplicationSearchIndex($appUid);
}
/*----------------------------------********---------------------------------*/
$Fields['TAS_UID'] = $sTasUid;
$Fields['USR_UID'] = $sUsrUid;
$Fields['DEL_INDEX'] = $iDelIndex;
$Fields['APP_STATUS'] = 'TO_DO';
$Fields['DEL_DELEGATE_DATE'] = $Fields['APP_INIT_DATE'];
if (!$isSubprocess) {
$Fields['APP_STATUS'] = 'DRAFT';
$fields['TAS_UID'] = $taskUid;
$fields['USR_UID'] = $userUid;
$fields['DEL_INDEX'] = $delIndex;
$fields['APP_STATUS'] = 'TO_DO';
$fields['DEL_DELEGATE_DATE'] = $fields['APP_INIT_DATE'];
if (!$isSubProcess) {
$fields['APP_STATUS'] = 'DRAFT';
} else {
$Fields['APP_INIT_DATE'] = null;
$fields['APP_INIT_DATE'] = null;
}
$inbox = new ListInbox();
$inbox->newRow($Fields, $sUsrUid, $isSelfService);
$inbox->newRow($fields, $userUid, $isSelfService);
// Multiple Instance
foreach ($aUserFields as $rowUser) {
$Fields["USR_UID"] = $rowUser["USR_UID"];
$Fields["DEL_INDEX"] = $rowUser["DEL_INDEX"];
foreach ($usersFields as $rowUser) {
$fields["USR_UID"] = $rowUser["USR_UID"];
$fields["DEL_INDEX"] = $rowUser["DEL_INDEX"];
$inbox = new ListInbox();
$inbox->newRow($Fields, $sUsrUid, $isSelfService);
$inbox->newRow($fields, $userUid, $isSelfService);
}
/*----------------------------------********---------------------------------*/
} catch (exception $e) {
} catch (Exception $e) {
throw ($e);
}
} else {
@@ -2275,29 +2279,29 @@ class Cases
// Log
$message = 'Create case';
$context = $data = [
"appUid" => $sAppUid,
"usrUid" => $sUsrUid,
"tasUid" => $sTasUid,
"isSubprocess" => $isSubprocess,
"appUid" => $appUid,
"usrUid" => $userUid,
"tasUid" => $taskUid,
"isSubProcess" => $isSubProcess,
"appNumber" => $caseNumber,
"delIndex" => $iDelIndex,
"appInitDate" => $Fields['APP_INIT_DATE']
"delIndex" => $delIndex,
"appInitDate" => $fields['APP_INIT_DATE']
];
Log::channel(':CreateCase')->info($message, Bootstrap::context($context));
//call plugin
// Call plugin
if (class_exists('folderData')) {
$folderData = new folderData($sProUid, $proFields['PRO_TITLE'], $sAppUid, $newValues['APP_TITLE'], $sUsrUid);
$oPluginRegistry = PluginRegistry::loadSingleton();
$oPluginRegistry->executeTriggers(PM_CREATE_CASE, $folderData);
$folderData = new folderData($processUid, $proFields['PRO_TITLE'], $appUid, $newValues['APP_TITLE'], $userUid);
$pluginRegistry = PluginRegistry::loadSingleton();
$pluginRegistry->executeTriggers(PM_CREATE_CASE, $folderData);
}
$this->getExecuteTriggerProcess($sAppUid, 'CREATE');
//end plugin
return array(
'APPLICATION' => $sAppUid,
'INDEX' => $iDelIndex,
'PROCESS' => $sProUid,
$this->getExecuteTriggerProcess($appUid, 'CREATE');
// End plugin
return [
'APPLICATION' => $appUid,
'INDEX' => $delIndex,
'PROCESS' => $processUid,
'CASE_NUMBER' => $caseNumber
);
];
}
/**

View File

@@ -7,6 +7,7 @@ use ProcessMaker\BusinessModel\Process as BmProcess;
/*----------------------------------********---------------------------------*/
use ProcessMaker\ChangeLog\ChangeLog;
/*----------------------------------********---------------------------------*/
use ProcessMaker\BusinessModel\WebEntry;
use ProcessMaker\Core\Installer;
use ProcessMaker\Core\ProcessesManager;
use ProcessMaker\Core\System;
@@ -369,6 +370,13 @@ class WorkspaceTools
$start = microtime(true);
$this->addAsyncOptionToSchedulerCommands(true);
CLI::logging("* End adding +async option to scheduler commands...(Completed on " . (microtime(true) - $start) . " seconds)\n");
CLI::logging("* Start Converting Web Entries v1.0 to v2.0 for BPMN processes...\n");
$start = microtime(true);
Bootstrap::setConstantsRelatedWs($workspace);
Propel::init(PATH_CONFIG . 'databases.php');
WebEntry::convertFromV1ToV2();
CLI::logging("* End converting Web Entries v1.0 to v2.0 for BPMN processes...(" . (microtime(true) - $start) . " seconds)\n");
}
/**
@@ -1248,12 +1256,15 @@ class WorkspaceTools
if ($action == 'ADD') {
$tablesToAddColumns[$tableName] = $actionData;
// In a very old schema the primary key for table "LOGIN_LOG" was changed and we need to delete the
// In a very old schema the primary key for tables "LOGIN_LOG" and "APP_SEQUENCE" were changed and we need to delete the
// primary index to avoid errors in the database upgrade
// TO DO: The change of a Primary Key in a table should be generic
if ($tableName == 'LOGIN_LOG' && array_key_exists('LOG_ID', $actionData)) {
$database->executeQuery('DROP INDEX `PRIMARY` ON LOGIN_LOG;');
}
if ($tableName == 'APP_SEQUENCE' && array_key_exists('APP_TYPE', $actionData)) {
$database->executeQuery('DROP INDEX `PRIMARY` ON APP_SEQUENCE;');
}
} else {
foreach ($actionData as $columnName => $meta) {
switch ($action) {
@@ -2214,8 +2225,15 @@ class WorkspaceTools
CLI::logging("* Start adding +async option to scheduler commands...\n");
$start = microtime(true);
$this->addAsyncOptionToSchedulerCommands(false);
$workspace->addAsyncOptionToSchedulerCommands(false);
CLI::logging("* End adding +async option to scheduler commands...(Completed on " . (microtime(true) - $start) . " seconds)\n");
CLI::logging("* Start Converting Web Entries v1.0 to v2.0 for BPMN processes...\n");
$start = microtime(true);
Bootstrap::setConstantsRelatedWs($workspace);
Propel::init(PATH_CONFIG . 'databases.php');
WebEntry::convertFromV1ToV2();
CLI::logging("* End converting Web Entries v1.0 to v2.0 for BPMN processes...(" . (microtime(true) - $start) . " seconds)\n");
}
CLI::logging("> Start To Verify License Enterprise...\n");
@@ -3295,22 +3313,46 @@ class WorkspaceTools
}
}
/**
* Add sequence numbers
*/
public function checkSequenceNumber()
{
$criteria = new Criteria("workflow");
// Instance required class
$appSequenceInstance = new AppSequence();
// Get a record from APP_SEQUENCE table
$criteria = new Criteria('workflow');
$rsCriteria = AppSequencePeer::doSelectRS($criteria);
$rsCriteria->setFetchmode(ResultSet::FETCHMODE_ASSOC);
$rsCriteria->next();
$appSequenceRow = $rsCriteria->getRow();
// If table APP_SEQUENCE is empty, insert two records
if (empty($appSequenceRow)) {
$sequenceInstance = SequencesPeer::retrieveByPK("APP_NUMBER");
$appSequenceInstance = new AppSequence();
// Check if exist a value in old table SEQUENCES
$sequenceInstance = SequencesPeer::retrieveByPK('APP_NUMBER');
if (!is_null($sequenceInstance)) {
// If exists a value in SEQUENCE table, copy the same to APP_SEQUENCES table
$sequenceFields = $sequenceInstance->toArray(BasePeer::TYPE_FIELDNAME);
$appSequenceInstance->updateSequenceNumber($sequenceFields['SEQ_VALUE']);
} else {
// If not exists a value in SEQUENCE table, insert a initial value
$appSequenceInstance->updateSequenceNumber(0);
}
// Insert a initial value for the web entries
$appSequenceInstance->updateSequenceNumber(0, AppSequence::APP_TYPE_WEB_ENTRY);
} else {
// Create a new instance of Criteria class
$criteria = new Criteria('workflow');
$criteria->add(AppSequencePeer::APP_TYPE, AppSequence::APP_TYPE_WEB_ENTRY);
// Check if exists a record for the web entries, if not exist insert the initial value
if (AppSequencePeer::doCount($criteria) === 0) {
$appSequenceInstance->updateSequenceNumber(0, AppSequence::APP_TYPE_WEB_ENTRY);
}
}
}
@@ -4949,7 +4991,9 @@ class WorkspaceTools
$case = new Cases();
//select cases for this Process, ordered by APP_NUMBER
$applications = Application::where('PRO_UID', '=', $processUid)
$applications = Application::query()
->where('PRO_UID', '=', $processUid)
->where('APP_NUMBER', '>', 0)
->orderBy('APP_NUMBER', 'asc')
->offset($start)
->limit($limit)

View File

@@ -314,6 +314,8 @@ class AppFolder extends BaseAppFolder
$oCriteria->addSelectColumn( AppDocumentPeer::APP_DOC_STATUS_DATE);
$oCriteria->addSelectColumn( AppDocumentPeer::APP_DOC_FIELDNAME);
$oCriteria->addSelectColumn(AppDocumentPeer::APP_DOC_DRIVE_DOWNLOAD);
$oCriteria->addJoin(AppDocumentPeer::APP_UID, ApplicationPeer::APP_UID);
$oCriteria->add(ApplicationPeer::APP_NUMBER, 0, Criteria::GREATER_THAN);
if ((is_array( $docIdFilter )) && (count( $docIdFilter ) > 0)) {
//Search by App Doc UID no matter what Folder it is

View File

@@ -16,27 +16,34 @@ require_once 'classes/model/om/BaseAppSequence.php';
*/
class AppSequence extends BaseAppSequence {
const APP_TYPE_NORMAL = 'NORMAL';
const APP_TYPE_WEB_ENTRY = 'WEB_ENTRY';
/**
* Get an Set new sequence number
*
* @param string $sequenceType
* @return mixed
* @throws Exception
*/
public function sequenceNumber()
public function sequenceNumber($sequenceType)
{
try {
$con = Propel::getConnection('workflow');
$stmt = $con->createStatement();
//UPDATE SEQUENCES SET SEQ_VALUE = LAST_INSERT_ID(SEQ_VALUE + 1);
$sql = "UPDATE APP_SEQUENCE SET ID=LAST_INSERT_ID(ID+1)";
$sql = "UPDATE APP_SEQUENCE SET ID=LAST_INSERT_ID(ID+1) WHERE APP_TYPE = '{$sequenceType}'";
$stmt->executeQuery($sql, ResultSet::FETCHMODE_ASSOC);
//SELECT LAST_INSERT_ID()
$sql = "SELECT LAST_INSERT_ID()";
$rs = $stmt->executeQuery($sql, ResultSet::FETCHMODE_ASSOC);
$rs->next();
$row = $rs->getRow();
$result = $row['LAST_INSERT_ID()'];
} catch (\Exception $e) {
// If the type is WEB_ENTRY, we need to change to negative
if ($sequenceType === 'WEB_ENTRY') {
$result *= -1;
}
} catch (Exception $e) {
throw ($e);
}
return $result;
@@ -46,26 +53,36 @@ class AppSequence extends BaseAppSequence {
/**
* Update sequence number
*
* @return mixed
* @param int $number
* @param string $sequenceType
*
* @throws Exception
*/
public function updateSequenceNumber($number)
public function updateSequenceNumber($number, $sequenceType = AppSequence::APP_TYPE_NORMAL)
{
try {
$con = Propel::getConnection('workflow');
$stmt = $con->createStatement();
$c = new Criteria();
$rs = AppSequencePeer::doSelectRS($c);
$rs->setFetchmode(ResultSet::FETCHMODE_ASSOC);
$rs->next();
$row = $rs->getRow();
// Get the current connection
$connection = Propel::getConnection('workflow');
// Create a statement instance
$statement = $connection->createStatement();
// Get the record according to the sequence type
$criteria = new Criteria();
$criteria->add(AppSequencePeer::APP_TYPE, $sequenceType);
$rsCriteria = AppSequencePeer::doSelectRS($criteria);
$rsCriteria->setFetchmode(ResultSet::FETCHMODE_ASSOC);
$rsCriteria->next();
$row = $rsCriteria->getRow();
// Insert/Update sequence table with the number sent
if ($row) {
$sql = "UPDATE APP_SEQUENCE SET ID=LAST_INSERT_ID('$number')";
$sql = "UPDATE APP_SEQUENCE SET ID=LAST_INSERT_ID('{$number}') WHERE APP_TYPE = '{$sequenceType}'";
} else {
$sql = "INSERT INTO APP_SEQUENCE (ID) VALUES ('$number');";
$sql = "INSERT INTO APP_SEQUENCE (ID, APP_TYPE) VALUES ('{$number}', '{$sequenceType}')";
}
$stmt->executeQuery($sql, ResultSet::FETCHMODE_ASSOC);
} catch (\Exception $e) {
$statement->executeQuery($sql, ResultSet::FETCHMODE_ASSOC);
} catch (Exception $e) {
throw ($e);
}
}

View File

@@ -207,30 +207,31 @@ class Application extends BaseApplication
}
/**
* Creates the Application
* Creates an Application
*
* @param
* $sProUid the process id
* $sUsrUid the userid
* @return void
* @param string $processUid
* @param string $userUid
* @param string $sequenceType
* @throws PropelException
* @throws Exception
* @return string
*/
public function create($sProUid, $sUsrUid)
public function create($processUid, $userUid, $sequenceType)
{
require_once ("classes/model/AppSequence.php");
$con = Propel::getConnection('workflow');
try {
//fill the default values for new application row
// Fill the default values for new application row
$this->setAppUid(G::generateUniqueID());
$this->setAppParent('');
$this->setAppStatus('DRAFT');
$this->setAppStatusId(1);
$this->setProUid($sProUid);
$this->setProUid($processUid);
$this->setAppProcStatus('');
$this->setAppProcCode('');
$this->setAppParallel('N');
$this->setAppInitUser($sUsrUid);
$this->setAppCurUser($sUsrUid);
$this->setAppInitUser($userUid);
$this->setAppCurUser($userUid);
$this->setAppCreateDate('now');
$this->setAppInitDate('now');
$this->setAppUpdateDate('now');
@@ -241,8 +242,8 @@ class Application extends BaseApplication
$c = new Criteria();
$c->clearSelectColumns();
$oAppSequence = new AppSequence();
$maxNumber = $oAppSequence->sequenceNumber();
$appSequence = new AppSequence();
$maxNumber = $appSequence->sequenceNumber($sequenceType);
$this->setAppNumber($maxNumber);
$this->setAppData(serialize(['APP_NUMBER' => $maxNumber, 'PIN' => $pin]));
@@ -253,9 +254,7 @@ class Application extends BaseApplication
$con->begin();
$this->setAppTitleContent('#' . $maxNumber);
$this->setAppDescriptionContent('');
//to do: ID_CASE in translation $this->setAppTitle(G::LoadTranslation('ID_CASE') . $maxNumber);
//Content::insertContent('APP_PROC_CODE', '', $this->getAppUid(), $lang, '');
$res = $this->save();
$this->save();
$con->commit();
return $this->getAppUid();

View File

@@ -65,7 +65,9 @@ class AppSequenceMapBuilder
$tMap->setUseIdGenerator(false);
$tMap->addPrimaryKey('ID', 'Id', 'int', CreoleTypes::INTEGER, true, null);
$tMap->addColumn('ID', 'Id', 'int', CreoleTypes::INTEGER, true, null);
$tMap->addColumn('APP_TYPE', 'AppType', 'string', CreoleTypes::VARCHAR, true, 20);
} // doBuild()

View File

@@ -33,6 +33,12 @@ abstract class BaseAppSequence extends BaseObject implements Persistent
*/
protected $id;
/**
* The value for the app_type field.
* @var string
*/
protected $app_type = 'NORMAL';
/**
* Flag to prevent endless save loop, if this object is referenced
* by another object which falls in this transaction.
@@ -58,6 +64,17 @@ abstract class BaseAppSequence extends BaseObject implements Persistent
return $this->id;
}
/**
* Get the [app_type] column value.
*
* @return string
*/
public function getAppType()
{
return $this->app_type;
}
/**
* Set the value of [id] column.
*
@@ -80,6 +97,28 @@ abstract class BaseAppSequence extends BaseObject implements Persistent
} // setId()
/**
* Set the value of [app_type] column.
*
* @param string $v new value
* @return void
*/
public function setAppType($v)
{
// Since the native PHP type for this column is string,
// we will cast the input to a string (if it is not).
if ($v !== null && !is_string($v)) {
$v = (string) $v;
}
if ($this->app_type !== $v || $v === 'NORMAL') {
$this->app_type = $v;
$this->modifiedColumns[] = AppSequencePeer::APP_TYPE;
}
} // setAppType()
/**
* Hydrates (populates) the object variables with values from the database resultset.
*
@@ -99,12 +138,14 @@ abstract class BaseAppSequence extends BaseObject implements Persistent
$this->id = $rs->getInt($startcol + 0);
$this->app_type = $rs->getString($startcol + 1);
$this->resetModified();
$this->setNew(false);
// FIXME - using NUM_COLUMNS may be clearer.
return $startcol + 1; // 1 = AppSequencePeer::NUM_COLUMNS - AppSequencePeer::NUM_LAZY_LOAD_COLUMNS).
return $startcol + 2; // 2 = AppSequencePeer::NUM_COLUMNS - AppSequencePeer::NUM_LAZY_LOAD_COLUMNS).
} catch (Exception $e) {
throw new PropelException("Error populating AppSequence object", $e);
@@ -311,6 +352,9 @@ abstract class BaseAppSequence extends BaseObject implements Persistent
case 0:
return $this->getId();
break;
case 1:
return $this->getAppType();
break;
default:
return null;
break;
@@ -332,6 +376,7 @@ abstract class BaseAppSequence extends BaseObject implements Persistent
$keys = AppSequencePeer::getFieldNames($keyType);
$result = array(
$keys[0] => $this->getId(),
$keys[1] => $this->getAppType(),
);
return $result;
}
@@ -366,6 +411,9 @@ abstract class BaseAppSequence extends BaseObject implements Persistent
case 0:
$this->setId($value);
break;
case 1:
$this->setAppType($value);
break;
} // switch()
}
@@ -393,6 +441,10 @@ abstract class BaseAppSequence extends BaseObject implements Persistent
$this->setId($arr[$keys[0]]);
}
if (array_key_exists($keys[1], $arr)) {
$this->setAppType($arr[$keys[1]]);
}
}
/**
@@ -408,6 +460,10 @@ abstract class BaseAppSequence extends BaseObject implements Persistent
$criteria->add(AppSequencePeer::ID, $this->id);
}
if ($this->isColumnModified(AppSequencePeer::APP_TYPE)) {
$criteria->add(AppSequencePeer::APP_TYPE, $this->app_type);
}
return $criteria;
}
@@ -424,29 +480,32 @@ abstract class BaseAppSequence extends BaseObject implements Persistent
{
$criteria = new Criteria(AppSequencePeer::DATABASE_NAME);
$criteria->add(AppSequencePeer::ID, $this->id);
return $criteria;
}
/**
* Returns the primary key for this object (row).
* @return int
* Returns NULL since this table doesn't have a primary key.
* This method exists only for BC and is deprecated!
* @return null
*/
public function getPrimaryKey()
{
return $this->getId();
return null;
}
/**
* Generic method to set the primary key (id column).
* Dummy primary key setter.
*
* @param int $key Primary key.
* @return void
* This function only exists to preserve backwards compatibility. It is no longer
* needed or required by the Persistent interface. It will be removed in next BC-breaking
* release of Propel.
*
* @deprecated
*/
public function setPrimaryKey($key)
public function setPrimaryKey($pk)
{
$this->setId($key);
// do nothing, because this object doesn't have any primary keys
}
/**
@@ -462,11 +521,13 @@ abstract class BaseAppSequence extends BaseObject implements Persistent
public function copyInto($copyObj, $deepCopy = false)
{
$copyObj->setId($this->id);
$copyObj->setAppType($this->app_type);
$copyObj->setNew(true);
$copyObj->setId(NULL); // this is a pkey column, so set to default value
}
/**

View File

@@ -25,7 +25,7 @@ abstract class BaseAppSequencePeer
const CLASS_DEFAULT = 'classes.model.AppSequence';
/** The total number of columns. */
const NUM_COLUMNS = 1;
const NUM_COLUMNS = 2;
/** The number of lazy-loaded columns. */
const NUM_LAZY_LOAD_COLUMNS = 0;
@@ -34,6 +34,9 @@ abstract class BaseAppSequencePeer
/** the column name for the ID field */
const ID = 'APP_SEQUENCE.ID';
/** the column name for the APP_TYPE field */
const APP_TYPE = 'APP_SEQUENCE.APP_TYPE';
/** The PHP to DB Name Mapping */
private static $phpNameMap = null;
@@ -45,10 +48,10 @@ abstract class BaseAppSequencePeer
* e.g. self::$fieldNames[self::TYPE_PHPNAME][0] = 'Id'
*/
private static $fieldNames = array (
BasePeer::TYPE_PHPNAME => array ('Id', ),
BasePeer::TYPE_COLNAME => array (AppSequencePeer::ID, ),
BasePeer::TYPE_FIELDNAME => array ('ID', ),
BasePeer::TYPE_NUM => array (0, )
BasePeer::TYPE_PHPNAME => array ('Id', 'AppType', ),
BasePeer::TYPE_COLNAME => array (AppSequencePeer::ID, AppSequencePeer::APP_TYPE, ),
BasePeer::TYPE_FIELDNAME => array ('ID', 'APP_TYPE', ),
BasePeer::TYPE_NUM => array (0, 1, )
);
/**
@@ -58,10 +61,10 @@ abstract class BaseAppSequencePeer
* e.g. self::$fieldNames[BasePeer::TYPE_PHPNAME]['Id'] = 0
*/
private static $fieldKeys = array (
BasePeer::TYPE_PHPNAME => array ('Id' => 0, ),
BasePeer::TYPE_COLNAME => array (AppSequencePeer::ID => 0, ),
BasePeer::TYPE_FIELDNAME => array ('ID' => 0, ),
BasePeer::TYPE_NUM => array (0, )
BasePeer::TYPE_PHPNAME => array ('Id' => 0, 'AppType' => 1, ),
BasePeer::TYPE_COLNAME => array (AppSequencePeer::ID => 0, AppSequencePeer::APP_TYPE => 1, ),
BasePeer::TYPE_FIELDNAME => array ('ID' => 0, 'APP_TYPE' => 1, ),
BasePeer::TYPE_NUM => array (0, 1, )
);
/**
@@ -164,10 +167,12 @@ abstract class BaseAppSequencePeer
$criteria->addSelectColumn(AppSequencePeer::ID);
$criteria->addSelectColumn(AppSequencePeer::APP_TYPE);
}
const COUNT = 'COUNT(APP_SEQUENCE.ID)';
const COUNT_DISTINCT = 'COUNT(DISTINCT APP_SEQUENCE.ID)';
const COUNT = 'COUNT(*)';
const COUNT_DISTINCT = 'COUNT(DISTINCT *)';
/**
* Returns the number of rows matching criteria.
@@ -376,9 +381,6 @@ abstract class BaseAppSequencePeer
if ($values instanceof Criteria) {
$criteria = clone $values; // rename for clarity
$comparison = $criteria->getComparison(AppSequencePeer::ID);
$selectCriteria->add(AppSequencePeer::ID, $criteria->remove(AppSequencePeer::ID), $comparison);
} else {
$criteria = $values->buildCriteria(); // gets full criteria
$selectCriteria = $values->buildPkeyCriteria(); // gets criteria w/ primary key(s)
@@ -436,11 +438,22 @@ abstract class BaseAppSequencePeer
$criteria = clone $values; // rename for clarity
} elseif ($values instanceof AppSequence) {
$criteria = $values->buildPkeyCriteria();
$criteria = $values->buildCriteria();
} else {
// it must be the primary key
$criteria = new Criteria(self::DATABASE_NAME);
$criteria->add(AppSequencePeer::ID, (array) $values, Criteria::IN);
// primary key is composite; we therefore, expect
// the primary key passed to be an array of pkey
// values
if (count($values) == count($values, COUNT_RECURSIVE)) {
// array is not multi-dimensional
$values = array($values);
}
$vals = array();
foreach ($values as $value) {
}
}
// Set the correct dbName
@@ -498,54 +511,6 @@ abstract class BaseAppSequencePeer
return BasePeer::doValidate(AppSequencePeer::DATABASE_NAME, AppSequencePeer::TABLE_NAME, $columns);
}
/**
* Retrieve a single object by pkey.
*
* @param mixed $pk the primary key.
* @param Connection $con the connection to use
* @return AppSequence
*/
public static function retrieveByPK($pk, $con = null)
{
if ($con === null) {
$con = Propel::getConnection(self::DATABASE_NAME);
}
$criteria = new Criteria(AppSequencePeer::DATABASE_NAME);
$criteria->add(AppSequencePeer::ID, $pk);
$v = AppSequencePeer::doSelect($criteria, $con);
return !empty($v) > 0 ? $v[0] : null;
}
/**
* Retrieve multiple objects by pkey.
*
* @param array $pks List of primary keys
* @param Connection $con the connection to use
* @throws PropelException Any exceptions caught during processing will be
* rethrown wrapped into a PropelException.
*/
public static function retrieveByPKs($pks, $con = null)
{
if ($con === null) {
$con = Propel::getConnection(self::DATABASE_NAME);
}
$objs = null;
if (empty($pks)) {
$objs = array();
} else {
$criteria = new Criteria();
$criteria->add(AppSequencePeer::ID, $pks, Criteria::IN);
$objs = AppSequencePeer::doSelect($criteria, $con);
}
return $objs;
}
}

View File

@@ -117,7 +117,8 @@
</unique>
</table>
<table name="APP_SEQUENCE" idMethod="native">
<column name="ID" type="INTEGER" required="true" primaryKey="true"/>
<column name="ID" type="INTEGER" required="true"/>
<column name="APP_TYPE" type="VARCHAR" size="20" required="true" default="NORMAL"/>
</table>
<table name="APP_DELEGATION" idMethod="native">
<vendor type="mysql">

File diff suppressed because one or more lines are too long

View File

@@ -10931,6 +10931,12 @@ msgstr "Case Scheduler Log"
msgid "Log Information"
msgstr "Log Information"
# TRANSLATION
# LABEL/ID_MAFE_TRANSLATION_DIRECTORY
#: LABEL/ID_MAFE_TRANSLATION_DIRECTORY
msgid "MAFE Translation Directory"
msgstr "MAFE Translation Directory"
# TRANSLATION
# LABEL/ID_MAFE_0015b7e51c1ca4293041c429985ca323
#: LABEL/ID_MAFE_0015b7e51c1ca4293041c429985ca323
@@ -22085,6 +22091,12 @@ msgstr "The report table '{0}' is related to a process not present in the worksp
msgid "[LABEL/ID_PROCESS_NO_CATEGORY] No Category"
msgstr "No Category"
# TRANSLATION
# LABEL/ID_PROCESS_NONE_CATEGORY
#: LABEL/ID_PROCESS_NONE_CATEGORY
msgid "- No Category -"
msgstr "- No Category -"
# TRANSLATION
# LABEL/ID_PROCESS_NO_EXIST
#: LABEL/ID_PROCESS_NO_EXIST
@@ -25499,6 +25511,18 @@ msgstr "Thu"
msgid "Timer event"
msgstr "Timer event"
# TRANSLATION
# LABEL/ID_CLEAN_WEBENTRIES
#: LABEL/ID_CLEAN_WEBENTRIES
msgid "Clean web-entries"
msgstr "Clean web-entries"
# TRANSLATION
# LABEL/ID_CLEAN_WEBENTRIES_DESC
#: LABEL/ID_CLEAN_WEBENTRIES_DESC
msgid "Clean web-entries"
msgstr "Clean web-entries"
# TRANSLATION
# LABEL/ID_TIMER_EVENT_DESC
#: LABEL/ID_TIMER_EVENT_DESC

View File

@@ -1,5 +1,7 @@
<?php
use ProcessMaker\Model\ProcessCategory as ModelCategories;
class ProcessProxy extends HttpProxyController
{
@@ -9,15 +11,29 @@ class ProcessProxy extends HttpProxyController
$RBAC->allows(basename(__FILE__), $name);
parent::call($name);
}
/**
* get Process Categories List with defailt value (empty option) and -All- aoption
* Get Categories list with default values
*
* @link https://wiki.processmaker.com/3.2/Processes#Designer_Menu
*/
public function categoriesList()
{
$data = $this->getCategoriesList();
$defaultOption[] = Array ('CATEGORY_UID' => '<reset>','CATEGORY_NAME' => G::LoadTranslation( 'ID_ALL' ));
$defaultOption = [];
// Add the option All categories
$defaultOption[] = [
'CATEGORY_UID' => '',
'CATEGORY_NAME' => G::LoadTranslation('ID_ALL')
];
// Add the option Without categories
$defaultOption[] = [
'CATEGORY_UID' => 'NONE',
'CATEGORY_NAME' => G::LoadTranslation('ID_PROCESS_NO_CATEGORY')
];
return array_merge( $defaultOption, $data );
$listCategories = ModelCategories::getCategories();
return array_merge($defaultOption, $listCategories);
}
/**

View File

@@ -57529,6 +57529,8 @@ INSERT INTO TRANSLATION (TRN_CATEGORY,TRN_ID,TRN_LANG,TRN_VALUE,TRN_UPDATE_DATE
( 'LABEL','ID_CLASS_ALREADY_EXISTS','en','Class already exists','2014-01-15') ,
( 'LABEL','ID_CLASS_TABLE_DOESNT_EXIST','en','This Class Table doesn''t exist!','2014-01-15') ,
( 'LABEL','ID_CLEAR','en','Clear','2014-01-15') ,
( 'LABEL','ID_CLEAN_WEBENTRIES','en','Clean web-entries','2020-11-10') ,
( 'LABEL','ID_CLEAN_WEBENTRIES_DESC','en','Clean web-entries','2020-11-10') ,
( 'LABEL','ID_CLEAR_CACHE','en','Clear Cache','2014-01-15') ,
( 'LABEL','ID_CLEAR_CACHE_CONFIRM1','en','Clear all cache files now?','2014-01-15') ,
( 'LABEL','ID_CLEAR_CACHE_MSG1','en','All cache data was deleted','2014-01-15') ,
@@ -58675,6 +58677,7 @@ INSERT INTO TRANSLATION (TRN_CATEGORY,TRN_ID,TRN_LANG,TRN_VALUE,TRN_UPDATE_DATE
( 'LABEL','ID_LOG_AGAIN','en','Please login again to apply the changes.','2014-01-15') ,
( 'LABEL','ID_LOG_CASE_SCHEDULER','en','Case Scheduler Log','2014-01-15') ,
( 'LABEL','ID_LOG_INFO','en','Log Information','2014-01-15') ,
( 'LABEL','ID_MAFE_TRANSLATION_DIRECTORY','en','MAFE Translation Directory','2014-01-15') ,
( 'LABEL','ID_MAFE_0015b7e51c1ca4293041c429985ca323','en','The specified subform could not be found in the process.', NOW()) ,
( 'LABEL','ID_MAFE_0025301679e9722c3abd5914cfbc7dd7','en','Database connection edited successfully', NOW()) ,
( 'LABEL','ID_MAFE_004d33be4d12eb8c0ae00703e7c70f61','en','Pick Second', NOW()) ,
@@ -60577,6 +60580,7 @@ INSERT INTO TRANSLATION (TRN_CATEGORY,TRN_ID,TRN_LANG,TRN_VALUE,TRN_UPDATE_DATE
( 'LABEL','ID_PROCESS_NOCATEGORY','en','No Category','2014-01-15') ,
( 'LABEL','ID_PROCESS_NOT_EXIST','en','The report table ''{0}'' is related to a process not present in the workspace, import the related process first. To relate the report table to other process, open the process in the designer and import from there. The report table can''t be imported.','2016-03-08') ,
( 'LABEL','ID_PROCESS_NO_CATEGORY','en','No Category','2014-01-15') ,
( 'LABEL','ID_PROCESS_NONE_CATEGORY','en','- No Category -','2020-10-23') ,
( 'LABEL','ID_PROCESS_NO_EXIST','en','Process doesn''t exist!','2014-01-15') ,
( 'LABEL','ID_PROCESS_PERMISSIONS','en','Process Permissions','2014-01-15') ,
( 'LABEL','ID_PROCESS_PERMISSIONS_CREATE','en','Process Permission created successfully','2014-01-15') ,
@@ -61791,6 +61795,7 @@ INSERT INTO ADDONS_MANAGER (ADDON_DESCRIPTION,ADDON_ID,ADDON_NAME,ADDON_NICK,ADD
('User-based Time Zone Management.','userBasedTimeZone','userBasedTimeZone','userBasedTimeZone','Colosa','localRegistry','ready','','00000000000000000000000000010014','features','','','0'),
('SSO with an LDAP provider.','windowsSSO','windowsSSO','windowsSSO','Colosa','localRegistry','ready','','00000000000000000000000000010011','features','','','0');
INSERT INTO APP_SEQUENCE (ID) VALUES
('0');
INSERT INTO APP_SEQUENCE (ID, APP_TYPE) VALUES
(0, 'NORMAL'),
(0, 'WEB_ENTRY');

View File

@@ -54,7 +54,7 @@ DROP TABLE IF EXISTS `APP_SEQUENCE`;
CREATE TABLE `APP_SEQUENCE`
(
`ID` INTEGER NOT NULL,
PRIMARY KEY (`ID`)
`APP_TYPE` VARCHAR(20) default 'NORMAL' NOT NULL
)ENGINE=InnoDB ;
#-----------------------------------------------------------------------------
#-- APP_DELEGATION

View File

@@ -6,6 +6,7 @@
* This page define some functions used in the start new case
*
* @link https://wiki.processmaker.com/3.1/Cases#New_Case
* @link https://wiki.processmaker.com/3.2/Web_Entry
*/
use ProcessMaker\Plugins\PluginRegistry;
@@ -179,14 +180,16 @@ function lookinginforContentProcess ($sproUid)
}
/**
* Start a case and get the next step
*/
function startCase()
{
$filter = new InputFilter();
$_POST = $filter->xssFilterHard($_POST);
$_REQUEST = $filter->xssFilterHard($_REQUEST);
/* GET , POST & $_SESSION Vars */
/* unset any variable, because we are starting a new case */
// Unset any variable, because we are starting a new case
if (isset($_SESSION['APPLICATION'])) {
unset($_SESSION['APPLICATION']);
}
@@ -203,37 +206,42 @@ function startCase ()
unset($_SESSION['STEP_POSITION']);
}
/* Process */
try {
$oCase = new Cases();
// Initializing variables
$sequenceType = (!empty($_REQUEST['actionFrom']) && $_REQUEST['actionFrom'] === 'webEntry') ? AppSequence::APP_TYPE_WEB_ENTRY : AppSequence::APP_TYPE_NORMAL;
// Update CONTENT table
lookinginforContentProcess($_POST['processId']);
$aData = $oCase->startCase( $_REQUEST['taskId'], $_SESSION['USER_LOGGED'] );
$aData = $filter->xssFilterHard($aData);
// Create the new case
$casesInstance = new Cases();
$newCase = $casesInstance->startCase($_REQUEST['taskId'], $_SESSION['USER_LOGGED'], false, [], false, $sequenceType);
$_SESSION['APPLICATION'] = $aData['APPLICATION'];
$_SESSION['INDEX'] = $aData['INDEX'];
$_SESSION['PROCESS'] = $aData['PROCESS'];
// Set session variables
$_SESSION['APPLICATION'] = $newCase['APPLICATION'];
$_SESSION['INDEX'] = $newCase['INDEX'];
$_SESSION['PROCESS'] = $newCase['PROCESS'];
$_SESSION['TASK'] = $_REQUEST['taskId'];
$_SESSION['STEP_POSITION'] = 0;
$_SESSION['CASES_REFRESH'] = true;
$oCase = new Cases();
$aNextStep = $oCase->getNextStep( $_SESSION['PROCESS'], $_SESSION['APPLICATION'], $_SESSION['INDEX'], $_SESSION['STEP_POSITION'] );
// Get the first step for the new case
$casesInstance = new Cases();
$nextStep = $casesInstance->getNextStep($_SESSION['PROCESS'], $_SESSION['APPLICATION'], $_SESSION['INDEX'],
$_SESSION['STEP_POSITION']);
$nextStep['PAGE'] = 'open?APP_UID=' . $newCase['APPLICATION'] . '&DEL_INDEX=' . $newCase['INDEX'] . '&action=draft';
$_SESSION['BREAKSTEP']['NEXT_STEP'] = $nextStep;
$aNextStep['PAGE'] = 'open?APP_UID=' . $aData['APPLICATION'] . '&DEL_INDEX=' . $aData['INDEX'] . '&action=draft';
// Complete required information
$newCase['openCase'] = $nextStep;
$newCase['status'] = 'success';
$_SESSION['BREAKSTEP']['NEXT_STEP'] = $aNextStep;
$aData['openCase'] = $aNextStep;
$aData['status'] = 'success';
print (G::json_encode( $aData )) ;
// Print JSON response
print (G::json_encode($newCase));
} catch (Exception $e) {
$aData['status'] = 'failure';
$aData['message'] = $e->getMessage();
print_r( G::json_encode( $aData ) );
$newCase['status'] = 'failure';
$newCase['message'] = $e->getMessage();
print_r(G::json_encode($newCase));
}
}

View File

@@ -1061,6 +1061,9 @@ try {
$tplFile = 'webentry/cases_ScreenDerivation';
$caseId = $currentTask['APP_UID'];
$delIndex = $currentTask['DEL_INDEX'];
// Swap temporary APP_NUMBER
$newAppNumber = $bmWebEntry->swapTemporaryAppNumber($caseId);
$Fields['APP_NUMBER'] = $Fields['APP_DATA']['APP_NUMBER'] = $newAppNumber;
$derivationResponse = PMFDerivateCase($caseId, $delIndex, true);
if ($derivationResponse) {
$webEntryUrl = $bmWebEntry->getCallbackUrlByTask($currentTask['TAS_UID']);

View File

@@ -1,63 +1,63 @@
<?php
/**
* processesList.php
*
* Get an overview information about the all the processes
*
* @link https://wiki.processmaker.com/3.2/Processes
*/
use ProcessMaker\Model\Process;
use ProcessMaker\Util\DateTime;
require_once 'classes/model/Process.php';
$start = isset($_POST['start']) ? $_POST['start'] : 0;
$limit = isset($_POST['limit']) ? $_POST['limit'] : '';
$limit = isset($_POST['limit']) ? $_POST['limit'] : 25;
$dir = isset($_POST['dir']) ? $_POST['dir'] : 'ASC';
$sort = isset($_POST['sort']) ? $_POST['sort'] : '';
$oProcess = new Process();
$oProcess->dir = $dir;
$oProcess->sort = $sort;
$memkey = 'no memcache';
$memcacheUsed = 'not used';
$sort = isset($_POST['sort']) ? $_POST['sort'] : 'PRO_CREATE_DATE';
switch ($sort) {
case 'PRO_DEBUG_LABEL':
$sort = 'PRO_DEBUG';
break;
case 'PRO_CREATE_USER_LABEL':
$sort = 'USR_UID';
break;
case 'PRO_STATUS_LABEL':
$sort = 'PRO_STATUS';
break;
case 'PROJECT_TYPE':
$sort = 'PRO_TYPE';
break;
case 'PRO_CATEGORY_LABEL':
$sort = 'PRO_CATEGORY';
break;
default:
// keep the sort value
}
$totalCount = 0;
if (isset($_POST['category']) && $_POST['category'] !== '<reset>') {
if (isset($_POST['processName'])) {
$proData = $oProcess->getAllProcesses($start, $limit, $_POST['category'], $_POST['processName'], true, false, $_SESSION["USER_LOGGED"]);
} else {
$proData = $oProcess->getAllProcesses($start, $limit, $_POST['category'], null, true, false, $_SESSION["USER_LOGGED"]);
}
} else {
if (isset($_POST['processName'])) {
$memkey = 'processList-' . $start . '-' . $limit . '-' . $_POST['processName'];
$memcacheUsed = 'yes';
$proData = $memcache->get($memkey);
if ($proData === false) {
$proData = $oProcess->getAllProcesses($start, $limit, null, $_POST['processName'], true, false, $_SESSION["USER_LOGGED"]);
$memcache->set($memkey, $proData, PMmemcached::ONE_HOUR);
$totalCount = count($proData);
$proData = array_splice($proData, $start, $limit);
$memcacheUsed = 'no';
} else {
$proData = $oProcess->orderMemcache($proData, $start, $limit);
$totalCount = $proData->totalCount;
$proData = $proData->dataMemcache;
}
} else {
$memkey = 'processList-allProcesses-' . $start . '-' . $limit;
$memkeyTotal = $memkey . '-total';
$memcacheUsed = 'yes';
if (($proData = $memcache->get($memkey)) === false || ($totalCount = $memcache->get($memkeyTotal)) === false) {
$proData = $oProcess->getAllProcesses($start, $limit, null, null, true, false, $_SESSION["USER_LOGGED"]);
$totalCount = count($proData);
$proData = array_splice($proData, $start, $limit);
$memcache->set($memkey, $proData, PMmemcached::ONE_HOUR);
$memcache->set($memkeyTotal, $totalCount, PMmemcached::ONE_HOUR);
$memcacheUsed = 'no';
} else {
$proData = $oProcess->orderMemcache($proData, $start, $limit);
$totalCount = $proData->totalCount;
$proData = $proData->dataMemcache;
}
}
}
$r = new stdclass();
$r->memkey = htmlspecialchars($memkey);
$r->memcache = $memcacheUsed;
$r->data = \ProcessMaker\Util\DateTime::convertUtcToTimeZone($proData);
$r->totalCount = $totalCount;
echo G::json_encode($r);
// Get the category uid to search
$catUid = !empty($_POST['category']) ? $_POST['category'] : null;
// Get the process name to search
$process = !empty($_POST['processName']) ? $_POST['processName'] : null;
$usrUid = $_SESSION["USER_LOGGED"];
$proData = Process::getProcessesFilter(
$catUid,
null,
$process,
$usrUid,
$start,
$limit,
$dir,
$sort
);
$response = new stdclass();
$response->data = DateTime::convertUtcToTimeZone($proData);
$response->totalCount = Process::getCounter($usrUid);
echo G::json_encode($response);

View File

@@ -355,7 +355,8 @@ $webEntryModel = \WebEntryPeer::retrieveByPK($weUid);
data: {
action: 'startCase',
processId: processUid,
taskId: tasUid
taskId: tasUid,
actionFrom: 'webEntry'
},
success: function (data) {
data.TAS_UID = tasUid;

View File

@@ -42,84 +42,94 @@ class FilesManager
/**
* Return the Process Files Manager Path
*
* @param string $sProcessUID {@min 32} {@max 32}
* @param string $processUid
* @param string $path
* @param boolean $getContent
*
* return array
* @return array
* @throws Exception
*
* @access public
*/
public function getProcessFilesManagerPath($sProcessUID, $path, $getContent = true)
public function getProcessFilesManagerPath($processUid, $path, $getContent = true)
{
try {
$checkPath = substr($path, -1);
if ($checkPath == '/') {
$path = substr($path, 0, -1);
}
$sMainDirectory = current(explode("/", $path));
$mainDirectory = current(explode('/', $path));
if (strstr($path,'/')) {
$sSubDirectory = substr($path, strpos($path, "/")+1). PATH_SEP ;
$subDirectory = substr($path, strpos($path, '/') + 1) . PATH_SEP;
} else {
$sSubDirectory = '';
$subDirectory = '';
}
switch ($sMainDirectory) {
switch ($mainDirectory) {
case 'templates':
$sDirectory = PATH_DATA_MAILTEMPLATES . $sProcessUID . PATH_SEP . $sSubDirectory;
$currentDirectory = PATH_DATA_MAILTEMPLATES . $processUid . PATH_SEP . $subDirectory;
break;
case 'public':
$sDirectory = PATH_DATA_PUBLIC . $sProcessUID . PATH_SEP . $sSubDirectory;
$currentDirectory = PATH_DATA_PUBLIC . $processUid . PATH_SEP . $subDirectory;
break;
default:
throw new \Exception(\G::LoadTranslation("ID_INVALID_VALUE_FOR", array('path')));
throw new Exception(G::LoadTranslation('ID_INVALID_VALUE_FOR', ['path']));
break;
}
\G::verifyPath($sDirectory, true);
$aTheFiles = array();
$aFiles = array();
$oDirectory = dir($sDirectory);
while ($sObject = $oDirectory->read()) {
if (($sObject !== '.') && ($sObject !== '..')) {
$sPath = $sDirectory . $sObject;
if (is_dir($sPath)) {
$aTheFiles[] = array('prf_name' => $sObject,
'prf_type' => "folder",
'prf_path' => $sMainDirectory);
G::verifyPath($currentDirectory, true);
$filesToList = [];
$files = [];
$directory = dir($currentDirectory);
while ($object = $directory->read()) {
if (($object !== '.') && ($object !== '..')) {
// Skip files related to web entries
if ($object === 'wsClient.php' || WebEntry::isWebEntry($processUid, $object)) {
continue;
}
$path = $currentDirectory . $object;
if (is_dir($path)) {
$filesToList[] = [
'prf_name' => $object,
'prf_type' => 'folder',
'prf_path' => $mainDirectory
];
} else {
$aAux = pathinfo($sPath);
$aAux['extension'] = (isset($aAux['extension'])?$aAux['extension']:'');
$aFiles[] = array('FILE' => $sObject, 'EXT' => $aAux['extension'] );
$aux = pathinfo($path);
$aux['extension'] = (isset($aux['extension']) ? $aux['extension'] : '');
$files[] = ['FILE' => $object, 'EXT' => $aux['extension']];
}
}
}
foreach ($aFiles as $aFile) {
$arrayFileUid = $this->getFileManagerUid($sDirectory.$aFile['FILE'], $aFile['FILE']);
$fcontent = "";
foreach ($files as $file) {
$arrayFileUid = $this->getFileManagerUid($currentDirectory.$file['FILE'], $file['FILE']);
$content = '';
if ($getContent === true) {
$fcontent = file_get_contents($sDirectory . $aFile['FILE']);
$content = file_get_contents($currentDirectory . $file['FILE']);
}
$fileUid = isset($arrayFileUid["PRF_UID"]) ? $arrayFileUid["PRF_UID"] : '';
$derivationScreen = isset($arrayFileUid["DERIVATION_SCREEN_TPL"]) ? true : false;
$fileUid = isset($arrayFileUid['PRF_UID']) ? $arrayFileUid['PRF_UID'] : '';
$derivationScreen = isset($arrayFileUid['DERIVATION_SCREEN_TPL']) ? true : false;
if ($fileUid != null) {
$oProcessFiles = \ProcessFilesPeer::retrieveByPK($fileUid);
$editable = $oProcessFiles->getPrfEditable();
$processFiles = ProcessFilesPeer::retrieveByPK($fileUid);
$editable = $processFiles->getPrfEditable();
if ($editable == '1') {
$editable = 'true';
} else {
$editable = 'false';
}
$aTheFiles[] = array( 'prf_uid' => $oProcessFiles->getPrfUid(),
'prf_filename' => $aFile['FILE'],
'usr_uid' => $oProcessFiles->getUsrUid(),
'prf_update_usr_uid' => $oProcessFiles->getPrfUpdateUsrUid(),
'prf_path' => $sMainDirectory. PATH_SEP .$sSubDirectory,
'prf_type' => $oProcessFiles->getPrfType(),
$filesToList[] = [
'prf_uid' => $processFiles->getPrfUid(),
'prf_filename' => $file['FILE'],
'usr_uid' => $processFiles->getUsrUid(),
'prf_update_usr_uid' => $processFiles->getPrfUpdateUsrUid(),
'prf_path' => $mainDirectory. PATH_SEP .$subDirectory,
'prf_type' => $processFiles->getPrfType(),
'prf_editable' => $editable,
'prf_create_date' => $oProcessFiles->getPrfCreateDate(),
'prf_update_date' => $oProcessFiles->getPrfUpdateDate(),
'prf_content' => $fcontent,
'prf_derivation_screen' => $derivationScreen);
'prf_create_date' => $processFiles->getPrfCreateDate(),
'prf_update_date' => $processFiles->getPrfUpdateDate(),
'prf_content' => $content,
'prf_derivation_screen' => $derivationScreen
];
} else {
$explodeExt = explode(".", $aFile['FILE']);
$explodeExt = explode('.', $file['FILE']);
$extension = end($explodeExt);
if ($extension == 'docx' || $extension == 'doc' || $extension == 'html' || $extension == 'php' || $extension == 'jsp'
|| $extension == 'xlsx' || $extension == 'xls' || $extension == 'js' || $extension == 'css' || $extension == 'txt') {
@@ -127,21 +137,23 @@ class FilesManager
} else {
$editable = 'false';
}
$aTheFiles[] = array('prf_uid' => '',
'prf_filename' => $aFile['FILE'],
$filesToList[] = [
'prf_uid' => '',
'prf_filename' => $file['FILE'],
'usr_uid' => '',
'prf_update_usr_uid' => '',
'prf_path' => $sMainDirectory. PATH_SEP .$sSubDirectory,
'prf_path' => $mainDirectory. PATH_SEP .$subDirectory,
'prf_type' => 'file',
'prf_editable' => $editable,
'prf_create_date' => '',
'prf_update_date' => '',
'prf_content' => $fcontent,
'prf_derivation_screen' => false);
'prf_content' => $content,
'prf_derivation_screen' => false
];
}
}
return $aTheFiles;
} catch (\Exception $e) {
return $filesToList;
} catch (Exception $e) {
throw $e;
}
}

View File

@@ -83,6 +83,21 @@ class TaskSchedulerBM
"expression" => "*/1 * * * 0,1,2,3,4,5,6",
"description" => "ID_TIMER_EVENT_DESC"
],
[
"title" => "ID_CLEAN_WEBENTRIES",
"enable" => "0",
"service" => "",
"category" => "case_actions",
"file" => "workflow/engine/bin/webentriescron.php",
"filew" => "workflow\\engine\bin\\webentriescron.php",
"startingTime" => null,
"endingTime" => null,
"timezone" => null,
"everyOn" => "1",
"interval" => "week",
"expression" => "0 20 * * 5",
"description" => "ID_CLEAN_WEBENTRIES_DESC"
],
[
"title" => "ID_TASK_SCHEDULER_CASE_EMAILS",
"enable" => "1",

View File

@@ -1,8 +1,12 @@
<?php
namespace ProcessMaker\BusinessModel;
use AppSequence;
use Cases;
use Criteria;
use Illuminate\Support\Facades\DB;
use ProcessMaker\Core\System;
use ProcessMaker\Model\Application;
use ResultSet;
use WebEntryPeer;
@@ -1125,5 +1129,92 @@ class WebEntry
}
return $message;
}
/**
* Swap temporary web entry application number to a normal application number
*
* @param string $appUid
* @return int
*/
public function swapTemporaryAppNumber($appUid)
{
// Get the application
$application = Application::query()->select(['APP_NUMBER'])->where('APP_UID', '=', $appUid)->first()->toArray();
// If application exists, swap the number
if (!empty($application)) {
// Get a normal sequence number
$appSequence = new AppSequence();
$appNumber = $appSequence->sequenceNumber(AppSequence::APP_TYPE_NORMAL);
// Update case with the new application number
$cases = new Cases();
$casesData = $cases->loadCase($appUid);
$casesData['APP_NUMBER'] = $casesData['APP_DATA']['APP_NUMBER'] = $appNumber;
$cases->updateCase($appUid, $casesData);
// Build the query to update related tables and fields
$query = "UPDATE `APPLICATION` SET `APP_TITLE` = '#{$appNumber}' WHERE `APP_UID` = '{$appUid}';";
$query .= "UPDATE `APP_DATA_CHANGE_LOG` SET `APP_NUMBER` = {$appNumber} WHERE `APP_NUMBER` = {$application['APP_NUMBER']};";
$query .= "UPDATE `APP_DELEGATION` SET `APP_NUMBER` = {$appNumber} WHERE `APP_UID` = '{$appUid}';";
$query .= "UPDATE `LIST_INBOX` SET `APP_NUMBER` = {$appNumber}, `APP_TITLE` = '#{$appNumber}' WHERE `APP_UID` = '{$appUid}';";
$query .= "UPDATE `LIST_PARTICIPATED_HISTORY` SET `APP_NUMBER` = {$appNumber}, `APP_TITLE` = '#{$appNumber}' WHERE `APP_UID` = '{$appUid}';";
$query .= "UPDATE `LIST_PARTICIPATED_LAST` SET `APP_NUMBER` = {$appNumber}, `APP_TITLE` = '#{$appNumber}' WHERE `APP_UID` = '{$appUid}';";
// Execute the query
DB::connection('workflow')->unprepared($query);
// Return new application number
return $appNumber;
}
}
/**
* Convert Web Entries v1.0 to v2.0
*/
public static function convertFromV1ToV2()
{
// Build query
$query = "UPDATE
`WEB_ENTRY`
LEFT JOIN
`BPMN_PROCESS`
ON
(`WEB_ENTRY`.`PRO_UID` = `BPMN_PROCESS`.`PRJ_UID`)
SET
`WEB_ENTRY`.`DYN_UID` = '', `WEB_ENTRY`.`WE_TYPE` = 'MULTIPLE'
WHERE
`WE_TYPE` = 'SINGLE' AND `WE_AUTHENTICATION` = 'ANONYMOUS' AND
`WE_CALLBACK` = 'PROCESSMAKER' AND `BPMN_PROCESS`.`PRJ_UID` IS NOT NULL";
// Execute query
DB::connection('workflow')->statement($query);
}
/**
* Delete web entries created one week ago or more
*/
public static function deleteOldWebEntries()
{
// Define some values for PM tables classes
if (!defined('PATH_WORKSPACE')) {
define('PATH_WORKSPACE', PATH_DB . config('system.workspace') . PATH_SEP);
}
set_include_path(get_include_path() . PATH_SEPARATOR . PATH_WORKSPACE);
// Calculate date, one week ago from today
$date = now()->subWeek()->format('Y-m-d H:i:s');
// Build query
$query = "SELECT `APP_UID` FROM `APPLICATION` WHERE `APP_NUMBER` < 0 AND `APP_CREATE_DATE` < '{$date}'";
// Execute query
$cases = DB::connection('workflow')->select($query);
// Delete cases, one by one with all related records
$casesInstance = new Cases();
foreach ($cases as $case) {
$casesInstance->removeCase($case->APP_UID);
}
}
}

View File

@@ -28,6 +28,19 @@ class Application extends Model
return $this->belongsTo(User::class, 'APP_INIT_USER', 'USR_UID');
}
/**
* Scope for query to get the positive cases
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopePositivesCases($query)
{
$result = $query->where('APP_NUMBER', '>', 0);
return $result;
}
/**
* Scope for query to get the application by APP_UID.
*
@@ -42,6 +55,20 @@ class Application extends Model
return $result;
}
/**
* Scope for query to get the application by status Id
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param integer $status
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeStatusId($query, int $status)
{
$result = $query->where('APP_STATUS_ID', '=', $status);
return $result;
}
/**
* Scope for query to get the applications by PRO_UID.
*
@@ -69,6 +96,7 @@ class Application extends Model
$query = Application::query()
->select()
->proUid($proUid)
->positivesCases()
->orderBy('APP_NUMBER', 'ASC');
return $query->get();
}
@@ -111,4 +139,24 @@ class Application extends Model
return $properties;
}
/**
* Get Applications by PRO_UID, ordered by APP_NUMBER.
*
* @param string $proUid
* @param int $status
*
* @return object
* @see ReportTables->populateTable()
*/
public static function getCountByProUid(string $proUid, $status = 2)
{
$query = Application::query()
->select()
->proUid($proUid)
->statusId($status)
->positivesCases();
return $query->get()->count();
}
}

View File

@@ -13,4 +13,20 @@ class BpmnProject extends Model
// We do not have create/update timestamps for this table
public $timestamps = false;
/**
* Check is the Process is BPMN.
*
* @param string $proUid
*
* @return int 1 if is BPMN process or 0 if a Normal process
*/
public static function isBpmnProcess(string $proUid)
{
$query = BpmnProject::query()
->select()
->where('PRJ_UID', '=', $proUid);
$result = $query->get()->values()->toArray();
return empty($result) ? 0 : 1;
}
}

View File

@@ -2,8 +2,10 @@
namespace ProcessMaker\Model;
use Configurations;
use Exception;
use G;
use Illuminate\Database\Eloquent\Model;
use RbacUsers;
use RBAC;
/**
@@ -20,22 +22,164 @@ class Process extends Model
// Our custom timestamp columns
const CREATED_AT = 'PRO_CREATE_DATE';
const UPDATED_AT = 'PRO_UPDATE_DATE';
// Columns to see in the process list
public $listColumns = [
'PRO_UID',
'PRO_TITLE',
'PRO_DESCRIPTION',
'PRO_PARENT',
'PRO_STATUS',
'PRO_TYPE',
'PRO_CATEGORY',
'PRO_UPDATE_DATE',
'PRO_CREATE_DATE',
'PRO_CREATE_USER',
'PRO_DEBUG',
'PRO_TYPE_PROCESS',
'USR_UID',
'USR_USERNAME',
'USR_FIRSTNAME',
'USR_LASTNAME',
'CATEGORY_UID',
'CATEGORY_NAME'
];
/**
* Get the columns related to the process list
* @return array
*/
public function getListColumns()
{
return $this->listColumns;
}
/**
* Returns the task related to the process belongs to
*/
public function tasks()
{
return $this->belongsTo(Task::class, 'PRO_ID', 'PRO_ID');
}
/**
* Returns the user creator belongs to
*/
public function creator()
{
return $this->belongsTo(User::class, 'PRO_CREATE_USER', 'USR_UID');
}
/**
* Returns the category related to the process belongs to
*/
public function category()
{
return $this->belongsTo(ProcessCategory::class, 'PRO_CATEGORY', 'CATEGORY_UID');
}
/**
* Scope a query to specific process
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $proUid
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeProcess($query, $proUid)
{
return $query->where('PRO_UID', '=', $proUid);
}
/**
* Scope a query to specific title
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $title
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeTitle($query, $title)
{
return $query->where('PRO_TITLE', 'LIKE', "%{$title}%");
}
/**
* Scope a query to exclude a specific status
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $status
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeNoStatus($query, $status = 'DISABLED')
{
return $query->where('PRO_STATUS', '!=', $status);
}
/**
* Scope a query to include subprocess
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeSubProcess($query)
{
return $query->where('PRO_SUBPROCESS', '=', 1);
}
/**
* Scope a query to include a specific process category
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $category
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeCategory($query, $category)
{
return $query->where('PROCESS.PRO_CATEGORY', $category);
}
/**
* Scope a query to include the user owner or public process
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $userUid
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopePerUser($query, string $userUid)
{
$query->where(function ($query) use ($userUid) {
$query->orWhere('PRO_CREATE_USER', $userUid);
$query->orWhere('PRO_TYPE_PROCESS', 'PUBLIC');
});
return $query;
}
/**
* Scope a query to include the process related to the specific user
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeJoinUsers($query)
{
$query->join('USERS', function ($join) {
$join->on('PROCESS.PRO_CREATE_USER', '=', 'USERS.USR_UID');
});
return $query;
}
/**
* Scope a query to join with categories
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeJoinCategory($query)
{
$query->leftJoin('PROCESS_CATEGORY', function ($join) {
$join->on('PROCESS.PRO_CATEGORY', '=', 'PROCESS_CATEGORY.CATEGORY_UID');
});
return $query;
}
/**
* Obtains the process list for an specific user and/or for the specific category
*
@@ -93,4 +237,157 @@ class Process extends Model
Process::where('PRO_CREATE_USER', $userUid)
->update(['PRO_CREATE_USER' => $admin]);
}
/**
* Get the process list applying some extra filters
*
* @param string $catUid
* @param string $proUid
* @param string $title
* @param string $userUid
* @param int $start
* @param int $limit
* @param string $dir
* @param string $sort
* @param boolean $counterByProcess
* @param boolean $subProcess
*
* @return array
* @throw Exception
*/
public static function getProcessesFilter(
$catUid = null,
$proUid = null,
$title = null,
$userUid = null,
$start = 0,
$limit = 25,
$dir = 'ASC',
$sort = 'PRO_CREATE_DATE',
$counterByProcess = true,
$subProcess = false
) {
$process = new Process();
$rows = $process->getListColumns();
if (!in_array($sort, $rows)) {
throw new Exception('The column ' . $sort . ' does not exist');
}
// Select rows
$query = Process::query()->select($rows)->noStatus();
// Join with users
$query->joinUsers();
// Join with category
$query->joinCategory();
// Check if the owner is the user logged or if the process is PUBLIC
if (!empty($userUid)) {
//Only process PRO_TYPE_PROCESS = "PUBLIC" or related user owner
$query->perUser($userUid);
}
// Check if we can list only the sub-process
if ($subProcess) {
$query->subProcess();
}
// Specific process
if ($proUid) {
$query->process($proUid);
}
// Specific process title
if ($title) {
$query->title($title);
}
// Search a specific category
if (!empty($catUid)) {
if ($catUid == 'NONE') {
// Processes without category
$query->category('');
} else {
// Processes with the category $catUid
$query->category($catUid);
}
}
// Order the data
$query->orderBy($sort, $dir);
// Define the pagination
$query->offset($start)->limit($limit);
// Get the results
$results = $query->get();
// Define the class for get workspace configurations
$systemConf = new Configurations();
$systemConf->loadConfig($obj, 'ENVIRONMENT_SETTINGS', '');
$mask = isset($systemConf->aConfig['dateFormat']) ? $systemConf->aConfig['dateFormat'] : '';
// Prepare the final result
$results->transform(function ($item, $key) use ($counterByProcess, $systemConf, $mask){
// Get the counter related to the status
// todo: those counters needs to remove when the PMCORE-2314 was implemented
$item['CASES_COUNT_DRAFT'] = $counterByProcess ? Application::getCountByProUid($item['PRO_UID'], 1) : 0;
$item['CASES_COUNT_TO_DO'] = $counterByProcess ? Application::getCountByProUid($item['PRO_UID'], 2) : 0;
$item['CASES_COUNT_COMPLETED'] = $counterByProcess ? Application::getCountByProUid($item['PRO_UID'], 3) : 0;
$item['CASES_COUNT_CANCELLED'] = $counterByProcess ? Application::getCountByProUid($item['PRO_UID'], 4) : 0;
$item['CASES_COUNT'] = $item['CASES_COUNT_DRAFT'] + $item['CASES_COUNT_TO_DO'] + $item['CASES_COUNT_COMPLETED'] + $item['CASES_COUNT_CANCELLED'];
// Get the description
// todo: we will to remove htmlspecialchars but frontEnd needs to add application wide XSS prevention measures
$item['PRO_DESCRIPTION'] = empty($item['PRO_DESCRIPTION']) ? '' : htmlspecialchars($item['PRO_DESCRIPTION']);
// Get the type: bpmn or classic
$bpmnProcess = BpmnProject::isBpmnProcess($item['PRO_UID']);
$item['PROJECT_TYPE'] = ($bpmnProcess) ? 'bpmn' : 'classic';
// Get the process type: PUBLIC or PRIVATE
$item['PRO_TYPE_PROCESS'] = ($item['PRO_TYPE_PROCESS'] == 'PUBLIC') ? G::LoadTranslation("ID_PUBLIC") : G::LoadTranslation("ID_PRIVATE");;
// Get information about the owner, with the format defined
$creatorOwner = $systemConf->usersNameFormat($item['USR_USERNAME'], $item['USR_FIRSTNAME'], $item['USR_LASTNAME']);
$item['PRO_CREATE_USER_LABEL'] = empty($creatorOwner) ? $item['USR_FIRSTNAME'] . ' ' . $item['USR_LASTNAME'] : $creatorOwner;
// Get debug label
$item['PRO_DEBUG_LABEL'] = ($item['PRO_DEBUG'] == '1') ? G::LoadTranslation('ID_ON') : G::LoadTranslation('ID_OFF');
// Get status label
$item['PRO_STATUS_LABEL'] = $item['PRO_STATUS'] == 'ACTIVE' ? G::LoadTranslation('ID_ACTIVE') : G::LoadTranslation('ID_INACTIVE');
// Get category label
$item['PRO_CATEGORY_LABEL'] = trim($item['PRO_CATEGORY']) != '' ? $item['CATEGORY_NAME'] : G::LoadTranslation('ID_PROCESS_NONE_CATEGORY');
// Apply the date format defined in environment
if (!empty($mask)) {
$item['PRO_CREATE_DATE_LABEL'] = $item['PRO_CREATE_DATE']->format($mask);
$item['PRO_UPDATE_DATE_LABEL'] = $item['PRO_UPDATE_DATE']->format($mask);
}
return $item;
});
return $results->values()->toArray();
}
/**
* Get the number of rows corresponding to the process
*
* @param string $userUid
* @return integer
*/
public static function getCounter($userUid = '')
{
$query = Process::query()->select();
$query->noStatus();
if (!empty($userUid)) {
//Only process PRO_TYPE_PROCESS = "PUBLIC" or related user owner
$query->perUser($userUid);
}
return $query->count();
}
}

View File

@@ -16,4 +16,26 @@ class ProcessCategory extends Model
protected $table = 'PROCESS_CATEGORY';
public $timestamps = false;
/**
* Get the categories
*
* @param string $dir
*
* @return array
*
* @see ProcessProxy::categoriesList()
* @link https://wiki.processmaker.com/3.0/Process_Categories
*/
public static function getCategories( $dir = 'ASC')
{
$query = ProcessCategory::query()
->select([
'CATEGORY_UID',
'CATEGORY_NAME'
])
->orderBy('CATEGORY_NAME', $dir);
return $query->get()->values()->toArray();
}
}

View File

@@ -135,7 +135,6 @@ Ext.onReady(function(){
Ext.QuickTips.init();
store = new Ext.data.GroupingStore( {
//var store = new Ext.data.Store( {
remoteSort: true,
proxy : new Ext.data.HttpProxy({
url: 'processesList'
@@ -168,9 +167,6 @@ Ext.onReady(function(){
]
}),
//sortInfo:{field: 'PRO_TITLE', direction: "ASC"}
//groupField:'PRO_CATEGORY_LABEL'
listeners: {
load: function (store) {
Ext.ComponentMgr.get("export").setDisabled(true);
@@ -225,44 +221,6 @@ Ext.onReady(function(){
store.load({params: {category: filter, start: 0, limit: 25}});
}}
})
/* storePageSize = new Ext.data.SimpleStore({
fields: ['size'],
data: [['20'],['30'],['40'],['50'],['100']],
autoLoad: true
});
var comboPageSize = new Ext.form.ComboBox({
typeAhead : false,
mode : 'local',
triggerAction : 'all',
store: storePageSize,
valueField: 'size',
displayField: 'size',
width: 50,
editable: false,
listeners:{
select: function(c,d,i){
//UpdatePageConfig(d.data['size']);
bbar.pageSize = parseInt(d.data['size']);
bbar.moveFirst();
//Ext.getCmp('bbar').setPageSize(comboPageSize.getValue());
}
}
});
comboPageSize.setValue(pageSize);
var bbar = new Ext.PagingToolbar({
id: 'bbar',
pageSize: '15',
store: store,
displayInfo: true,
displayMsg: 'Displaying Processes {0} - {1} of {2}',
emptyMsg: "",
items:[_('ID_PAGE_SIZE')+':',comboPageSize]
}) */
var mnuNewBpmnProject = {
text: _("ID_NEW_BPMN_PROJECT"),
@@ -453,11 +411,11 @@ Ext.onReady(function(){
}}
,{header: _('ID_OWNER'), dataIndex: 'PRO_CREATE_USER_LABEL', width: 90}
,{header: _('ID_PRO_CREATE_DATE'), dataIndex: 'PRO_CREATE_DATE', width: 90}
,{header: _('ID_INBOX'), dataIndex: 'CASES_COUNT_TO_DO', width: 50, align:'right'}
,{header: _('ID_DRAFT'), dataIndex: 'CASES_COUNT_DRAFT', width: 50, align:'right'}
,{header: _('ID_COMPLETED'), dataIndex: 'CASES_COUNT_COMPLETED', width: 50, align:'right'}
,{header: _('ID_CANCELLED'), dataIndex: 'CASES_COUNT_CANCELLED', width: 50, align:'right'}
,{header: _('ID_TOTAL_CASES'), dataIndex: 'CASES_COUNT', width: 70, renderer:function(v){return "<b>"+v+"</b>";}, align:'right'}
,{header: _('ID_INBOX'), dataIndex: 'CASES_COUNT_TO_DO', width: 50, align:'right', sortable: false}
,{header: _('ID_DRAFT'), dataIndex: 'CASES_COUNT_DRAFT', width: 50, align:'right', sortable: false}
,{header: _('ID_COMPLETED'), dataIndex: 'CASES_COUNT_COMPLETED', width: 50, align:'right', sortable: false}
,{header: _('ID_CANCELLED'), dataIndex: 'CASES_COUNT_CANCELLED', width: 50, align:'right', sortable: false}
,{header: _('ID_TOTAL_CASES'), dataIndex: 'CASES_COUNT', width: 70, renderer:function(v){return "<b>"+v+"</b>";}, align:'right', sortable: false}
,{header: _('ID_PRO_DEBUG'), dataIndex: 'PRO_DEBUG_LABEL', width: 30}
/*----------------------------------********---------------------------------*/
,{header: _("ID_TYPE_PROCESS"), dataIndex: "PRO_TYPE_PROCESS", width: 70}
@@ -468,25 +426,14 @@ Ext.onReady(function(){
sm: proSelModel,
store: store,
tbar:[
newTypeProcess,/*
{
text: _('ID_NEW'),
iconCls: 'button_menu_ext ss_sprite ss_add',
//icon: '/images/addc.png',
handler: newProcess
},*/
newTypeProcess,
'-'
,{
text: _('ID_EDIT'),
iconCls: 'button_menu_ext',
icon: '/images/pencil.png',
handler: editProcess
},/*{
text: 'Edit (New Editor)',
iconCls: 'button_menu_ext',
icon: '/images/pencil_beta.png',
handler: editNewProcess
},*/{
},{
text: _('ID_STATUS'),
id:'activator',
icon: '',
@@ -541,12 +488,9 @@ Ext.onReady(function(){
text:'X',
ctCls:'pm_search_x_button_des',
handler: function(){
//store.setBaseParam( 'category', '<reset>');
store.setBaseParam('processName', '');
store.load({params: {start: 0, limit: 25}});
Ext.getCmp('searchTxt').setValue('');
//comboCategory.setValue('');
//store.reload();
}
},{
text: _('ID_SEARCH'),
@@ -882,8 +826,6 @@ function saveProcess()
}
function doSearch() {
if(comboCategory.getValue() == '')
store.setBaseParam( 'category', '<reset>');
filter = Ext.getCmp('searchTxt').getValue();
store.setBaseParam('processName', filter);