From 708233f9b4830be19cecfa2d6a438d5e9f1808eb Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Mon, 2 Mar 2026 19:32:17 +0000 Subject: [PATCH] =?UTF-8?q?Podzia=C5=82=20na=20typy=20proces=C3=B3w?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WorkflowEngine.php | 101 +++++++++++++- _get_instance_details.php | 11 +- _init_single_instance.php | 54 +++----- _save_process_definition.php | 11 +- _sidebar.php | 18 +++ assets/js/process_definitions.js | 2 + cookie.txt | 2 +- .../038_add_subject_scope_and_run_number.php | 42 ++++++ groups_processes.php | 114 ++++++++++++++++ meetings_processes.php | 127 ++++++++++++++++++ organization_processes.php | 106 +++++++++++++++ patch_form.py | 23 ++++ patch_js.py | 22 +++ patch_modal.py | 89 +++++------- patch_save_def.php | 43 ++++++ patch_save_def.py | 39 ++++++ patch_sidebar.php | 31 +++++ patch_we.php | 121 +++++++++++++++++ patch_we.py | 109 +++++++++++++++ process_definitions.php | 11 +- 20 files changed, 975 insertions(+), 101 deletions(-) create mode 100644 db/migrations/038_add_subject_scope_and_run_number.php create mode 100644 groups_processes.php create mode 100644 meetings_processes.php create mode 100644 organization_processes.php create mode 100644 patch_form.py create mode 100644 patch_js.py create mode 100644 patch_save_def.php create mode 100644 patch_save_def.py create mode 100644 patch_sidebar.php create mode 100644 patch_we.php create mode 100644 patch_we.py diff --git a/WorkflowEngine.php b/WorkflowEngine.php index 9fd2c8f..100149c 100644 --- a/WorkflowEngine.php +++ b/WorkflowEngine.php @@ -57,7 +57,7 @@ class WorkflowEngine { $people = $stmt_people->fetchAll(PDO::FETCH_ASSOC); // 4. Fetch all process definitions with their JSON - $stmt_defs = $this->pdo->prepare("SELECT id, code, name, definition_json, is_active FROM process_definitions WHERE is_active = 1 AND is_latest = 1 ORDER BY sort_order, name"); + $stmt_defs = $this->pdo->prepare("SELECT id, code, name, definition_json, is_active FROM process_definitions WHERE is_active = 1 AND is_latest = 1 AND subject_scope = 'person' ORDER BY sort_order, name"); $stmt_defs->execute(); $process_definitions_raw = $stmt_defs->fetchAll(PDO::FETCH_ASSOC); @@ -1155,4 +1155,103 @@ $spotkania_cols = []; return $stmt->fetchAll(PDO::FETCH_ASSOC); } + + public function getOrCreateInstanceBySubject(string $subjectType, int $subjectId, string $processCode, int $userId, string $mode='resume_or_create'): array { + if (!in_array($subjectType, ['person', 'meeting', 'bni_group', 'organization'])) { + throw new \InvalidArgumentException("Invalid subjectType."); + } + if ($subjectId <= 0) { + throw new \InvalidArgumentException("subjectId must be > 0."); + } + if (empty($processCode)) { + throw new \InvalidArgumentException("processCode cannot be empty."); + } + + $inTransaction = $this->pdo->inTransaction(); + if (!$inTransaction) { $this->pdo->beginTransaction(); } + + try { + $sql = "SELECT * FROM process_definitions WHERE code = ? AND is_active = 1 AND subject_scope = ? ORDER BY version DESC, id DESC LIMIT 1"; + $stmt = $this->pdo->prepare($sql); + $stmt->execute([$processCode, $subjectType]); + $definition = $stmt->fetch(\PDO::FETCH_ASSOC); + + if (!$definition) { + $stmt = $this->pdo->prepare("SELECT * FROM process_definitions WHERE code = ? AND is_active = 1 ORDER BY version DESC, id DESC LIMIT 1"); + $stmt->execute([$processCode]); + $definition = $stmt->fetch(\PDO::FETCH_ASSOC); + if (!$definition) { + throw new WorkflowNotFoundException("No active process definition found for code '$processCode'"); + } + } + + $defId = $definition['id']; + $defJson = json_decode($definition['definition_json'], true); + $startNodeId = $defJson['start_node_id'] ?? null; + if (!$startNodeId) { + throw new \Exception("Process definition missing start_node_id"); + } + + $instance = null; + if ($mode === 'resume_or_create') { + $stmt = $this->pdo->prepare( + "SELECT pi.* FROM process_instances pi\n JOIN process_definitions pd ON pi.process_definition_id = pd.id\n WHERE pi.subject_type = ? AND pi.subject_id = ? AND pd.code = ?\n ORDER BY pi.id DESC LIMIT 1" + ); + $stmt->execute([$subjectType, $subjectId, $processCode]); + $instance = $stmt->fetch(\PDO::FETCH_ASSOC); + } + + if (!$instance) { + $stmt = $this->pdo->prepare( + "SELECT MAX(pi.run_number) + FROM process_instances pi + JOIN process_definitions pd ON pi.process_definition_id = pd.id + WHERE pi.subject_type = ? AND pi.subject_id = ? AND pd.code = ?" + ); + $stmt->execute([$subjectType, $subjectId, $processCode]); + $maxRun = (int)$stmt->fetchColumn(); + $runNumber = $maxRun + 1; + + $personIdVal = ($subjectType === 'person') ? $subjectId : null; + $status = $defJson['nodes'][$startNodeId]['ui_hints']['status'] ?? 'in_progress'; + $reason = $defJson['nodes'][$startNodeId]['ui_hints']['reason'] ?? ''; + $nextStep = $defJson['nodes'][$startNodeId]['ui_hints']['next_step'] ?? ''; + + $stmt = $this->pdo->prepare( + "INSERT INTO process_instances + (subject_type, subject_id, person_id, process_definition_id, current_node_id, current_status, current_reason, suggested_next_step, run_number, last_activity_at, data_json) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), '{}')" + ); + $stmt->execute([ + $subjectType, $subjectId, $personIdVal, $defId, $startNodeId, $status, $reason, $nextStep, $runNumber + ]); + + $instanceId = $this->pdo->lastInsertId(); + $this->addEvent($instanceId, 'system', 'Process started.', $startNodeId, [], $userId); + + $stmt = $this->pdo->prepare("SELECT * FROM process_instances WHERE id = ?"); + $stmt->execute([$instanceId]); + $instance = $stmt->fetch(\PDO::FETCH_ASSOC); + } + + if (!$inTransaction) { $this->pdo->commit(); } + + return [ + 'instance_id' => $instance['id'], + 'process_definition_id' => $instance['process_definition_id'], + 'process_code' => $processCode, + 'subject_type' => $instance['subject_type'], + 'subject_id' => $instance['subject_id'], + 'person_id' => $instance['person_id'], + 'current_node_id' => $instance['current_node_id'], + 'current_status' => $instance['current_status'], + 'last_activity_at' => $instance['last_activity_at'], + 'data_json' => $instance['data_json'] + ]; + + } catch (\Exception $e) { + if (!$inTransaction) { $this->pdo->rollBack(); } + throw $e; + } + } } diff --git a/_get_instance_details.php b/_get_instance_details.php index f616002..4b315a8 100644 --- a/_get_instance_details.php +++ b/_get_instance_details.php @@ -53,6 +53,15 @@ if ($subject_type === 'person') { if ($meeting) { $subjectName = $meeting['group_name'] . ' - ' . date('d.m.Y', strtotime($meeting['meeting_datetime'])); } +} elseif ($subject_type === 'bni_group') { + $stmt_group = $pdo->prepare("SELECT name FROM bni_groups WHERE id = ?"); + $stmt_group->execute([$subject_id]); + $group = $stmt_group->fetch(); + if ($group) { + $subjectName = 'Grupa ' . $group['name']; + } +} elseif ($subject_type === 'organization') { + $subjectName = 'Główna Organizacja'; } $stmt_process = $pdo->prepare("SELECT * FROM process_definitions WHERE id = ?"); @@ -302,7 +311,7 @@ $instance = $engine->getActiveInstanceForSubject($process['code'], $subject_type

-

This process has not been started for this person.

+

This process has not been started for this subject.

diff --git a/_init_single_instance.php b/_init_single_instance.php index a11ea10..f6edc1a 100644 --- a/_init_single_instance.php +++ b/_init_single_instance.php @@ -19,51 +19,35 @@ if (!isset($_SESSION['user_id'])) { $userId = $_SESSION['user_id']; $personId = filter_input(INPUT_POST, 'person_id', FILTER_VALIDATE_INT); -$subjectType = filter_input(INPUT_POST, 'subject_type', FILTER_SANITIZE_STRING) ?: 'person'; -$subjectId = filter_input(INPUT_POST, 'subject_id', FILTER_VALIDATE_INT) ?: $personId; $processDefinitionId = filter_input(INPUT_POST, 'process_id', FILTER_VALIDATE_INT); + +$subjectType = filter_input(INPUT_POST, 'subject_type', FILTER_SANITIZE_STRING); +$subjectId = filter_input(INPUT_POST, 'subject_id', FILTER_VALIDATE_INT); $processCode = filter_input(INPUT_POST, 'process_code', FILTER_SANITIZE_STRING); -$deleteExisting = filter_input(INPUT_POST, 'delete_existing'); -$mode = filter_input(INPUT_POST, 'mode', FILTER_SANITIZE_STRING); +$mode = filter_input(INPUT_POST, 'mode', FILTER_SANITIZE_STRING) ?: 'resume_or_create'; + +if ($personId && !$subjectType) { + $subjectType = 'person'; + $subjectId = $personId; +} $pdo = db(); -if (!$processDefinitionId && $processCode) { - $stmt = $pdo->prepare("SELECT id FROM process_definitions WHERE code = ? AND is_latest = 1 LIMIT 1"); - $stmt->execute([$processCode]); - $processDefinitionId = $stmt->fetchColumn(); +if ($processDefinitionId && !$processCode) { + $stmt = $pdo->prepare("SELECT code FROM process_definitions WHERE id = ?"); + $stmt->execute([$processDefinitionId]); + $processCode = $stmt->fetchColumn(); } -if (!$subjectId || !$processDefinitionId) { - throw new InvalidArgumentException('Invalid or missing subject_id or process_id/process_code.'); +if (!$subjectId || !$subjectType || !$processCode) { + throw new InvalidArgumentException('Invalid or missing subject_type, subject_id, or process_code.'); } $engine = new WorkflowEngine(); +$instance = $engine->getOrCreateInstanceBySubject($subjectType, $subjectId, $processCode, $userId, $mode); - - $stmt_def = $pdo->prepare("SELECT code FROM process_definitions WHERE id = ?"); - $stmt_def->execute([$processDefinitionId]); - $code = $stmt_def->fetchColumn() ?: $processCode; - -if($deleteExisting === '1') { - $instance = $engine->getActiveInstanceForSubject($code, $subjectType, $subjectId, $cycleKey); - if ($instance) { - $engine->deleteInstance($instance['id']); - } -} - -if ($mode === 'create_new_run' || filter_input(INPUT_POST, 'force', FILTER_VALIDATE_INT) === 1) { - // start new process - $instanceId = $engine->startProcessForSubject($code, $subjectType, $subjectId, $userId, 'create_new_run', $cycleKey); - $stmt = $pdo->prepare("SELECT * FROM process_instances WHERE id = ?"); - $stmt->execute([$instanceId]); - $instance = $stmt->fetch(PDO::FETCH_ASSOC); -} else { - $instance = $engine->getOrCreateInstanceForSubject($processDefinitionId, $subjectType, $subjectId, $userId); -} - -if ($instance) { - echo json_encode(['success' => true, 'message' => 'Process initialized successfully.', 'instance_id' => $instance['id']]); +if ($instance && isset($instance['instance_id'])) { + echo json_encode(['success' => true, 'message' => 'Process initialized successfully.', 'instance_id' => $instance['instance_id']]); } else { throw new Exception("Failed to initialize process for an unknown reason."); -} +} \ No newline at end of file diff --git a/_save_process_definition.php b/_save_process_definition.php index b3ec95b..ce3aae2 100644 --- a/_save_process_definition.php +++ b/_save_process_definition.php @@ -93,6 +93,7 @@ try { $processId = $_POST['process_id'] ?? null; $name = $_POST['name'] ?? ''; $definition_json = $_POST['definition_json'] ?? ''; + $subject_scope = $_POST['subject_scope'] ?? 'person'; validate_definition_json($definition_json); @@ -108,14 +109,14 @@ try { if (empty($processId)) { // Create new process - $sql = 'INSERT INTO process_definitions (name, code, definition_json, start_node_id, is_active, version, is_latest) VALUES (?, ?, ?, ?, 1, 1, 1)'; - $params = [$name, $code, $definition_json, $start_node]; + $sql = 'INSERT INTO process_definitions (name, code, definition_json, start_node_id, is_active, version, is_latest, subject_scope) VALUES (?, ?, ?, ?, 1, 1, 1, ?)'; + $params = [$name, $code, $definition_json, $start_node, $subject_scope]; $message = 'Process created successfully.'; $stmt = $pdo->prepare($sql); $stmt->execute($params); } else { // "Update" existing process by creating a new version - $stmt_old = $pdo->prepare('SELECT code, version, sort_order, is_active FROM process_definitions WHERE id = ?'); + $stmt_old = $pdo->prepare('SELECT code, version, sort_order, is_active, subject_scope FROM process_definitions WHERE id = ?'); $stmt_old->execute([$processId]); $old = $stmt_old->fetch(); @@ -129,8 +130,8 @@ try { $stmt_update->execute([$db_code]); // Insert new version - $sql = 'INSERT INTO process_definitions (name, code, definition_json, start_node_id, is_active, version, supersedes_definition_id, is_latest, sort_order) VALUES (?, ?, ?, ?, ?, ?, ?, 1, ?)'; - $params = [$name, $db_code, $definition_json, $start_node, $is_active, $new_version, $processId, $old['sort_order']]; + $sql = 'INSERT INTO process_definitions (name, code, definition_json, start_node_id, is_active, version, supersedes_definition_id, is_latest, sort_order, subject_scope) VALUES (?, ?, ?, ?, ?, ?, ?, 1, ?, ?)'; + $params = [$name, $db_code, $definition_json, $start_node, $is_active, $new_version, $processId, $old['sort_order'], $subject_scope]; $stmt = $pdo->prepare($sql); $stmt->execute($params); $message = 'Process updated successfully (new version created).'; diff --git a/_sidebar.php b/_sidebar.php index 5a9364a..723f624 100644 --- a/_sidebar.php +++ b/_sidebar.php @@ -7,6 +7,24 @@ + + + + + + +HTML; + +$search = '