Głęboka refactoryzacja kodu
This commit is contained in:
parent
a703aeb1e2
commit
3b1a26adc9
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
// Cache-buster: 1720638682
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
require_once __DIR__ . '/lib/WorkflowExceptions.php';
|
||||
|
||||
class WorkflowEngine {
|
||||
|
||||
@ -31,7 +32,8 @@ class WorkflowEngine {
|
||||
foreach ($process_definitions_raw as $def) {
|
||||
$definitions[$def['id']] = [
|
||||
'id' => $def['id'],
|
||||
'name' => $def['name']
|
||||
'name' => $def['name'],
|
||||
'is_active' => $def['is_active']
|
||||
];
|
||||
$definition_map[$def['id']] = !empty($def['definition_json']) ? json_decode($def['definition_json'], true) : null;
|
||||
}
|
||||
@ -87,20 +89,18 @@ class WorkflowEngine {
|
||||
$instances[$instance['person_id']][$def_id] = $enriched_instance;
|
||||
}
|
||||
|
||||
// Remove pre-emptive eligibility check. This is now handled on-demand by _get_instance_details.php
|
||||
/*
|
||||
foreach ($people as $person) {
|
||||
foreach ($definitions as $def) {
|
||||
if (!isset($instances[$person['id']][$def['id']])) {
|
||||
$is_eligible = true;
|
||||
try {
|
||||
$process_definition = $process_definitions_raw[array_search($def['id'], array_column($process_definitions_raw, 'id'))];
|
||||
$this->checkEligibility($person['id'], $process_definition);
|
||||
} catch (WorkflowNotAllowedException $e) {
|
||||
$is_eligible = false;
|
||||
}
|
||||
$instances[$person['id']][$def['id']] = ['is_eligible' => $is_eligible];
|
||||
$process_definition_raw = $process_definitions_raw[array_search($def['id'], array_column($process_definitions_raw, 'id'))];
|
||||
$eligibility = $this->checkEligibility($person['id'], $process_definition_raw);
|
||||
$instances[$person['id']][$def['id']] = ['is_eligible' => $eligibility['is_eligible']];
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Fetch ancillary data
|
||||
$stmt_functions = $this->pdo->query("SELECT * FROM functions ORDER BY display_order");
|
||||
@ -253,6 +253,8 @@ class WorkflowEngine {
|
||||
foreach ($transition['actions'] as $action) {
|
||||
if ($action['type'] === 'start_process') {
|
||||
$this->executeStartProcessAction($instance['person_id'], $action, $userId);
|
||||
} elseif ($action['type'] === 'set_data') {
|
||||
$this->executeSetDataAction($instanceId, $action);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -436,6 +438,13 @@ class WorkflowEngine {
|
||||
return $instance ?: null;
|
||||
}
|
||||
|
||||
public function getInstanceByDefId(int $personId, int $processDefinitionId): ?array {
|
||||
$stmt = $this->pdo->prepare("SELECT * FROM process_instances WHERE `person_id` = ? AND `process_definition_id` = ?");
|
||||
$stmt->execute([$personId, $processDefinitionId]);
|
||||
$instance = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
return $instance ?: null;
|
||||
}
|
||||
|
||||
public function getEvents(int $instanceId): array {
|
||||
$stmt_events = $this->pdo->prepare("SELECT pe.*, p.email as user_email, p.first_name, p.last_name FROM process_events pe JOIN people p ON pe.created_by = p.id WHERE pe.process_instance_id = ? ORDER BY pe.created_at DESC");
|
||||
$stmt_events->execute([$instanceId]);
|
||||
@ -476,44 +485,101 @@ class WorkflowEngine {
|
||||
return $definition['nodes'] ?? [];
|
||||
}
|
||||
|
||||
private function checkEligibility(int $personId, array $definition): void {
|
||||
$definition_json = !empty($definition['definition_json']) ? json_decode($definition['definition_json'], true) : [];
|
||||
if (empty($definition_json) || empty($definition_json['eligibility_rules'])) {
|
||||
return; // No rules to check
|
||||
public function checkEligibility(int $personId, int $processDefinitionId): array {
|
||||
$stmt_def = $this->pdo->prepare("SELECT definition_json FROM process_definitions WHERE id = ?");
|
||||
$stmt_def->execute([$processDefinitionId]);
|
||||
$definition_json = $stmt_def->fetchColumn();
|
||||
|
||||
$definition = !empty($definition_json) ? json_decode($definition_json, true) : [];
|
||||
|
||||
$reasons = [];
|
||||
if (empty($definition) || empty($definition['eligibility_rules'])) {
|
||||
return ['is_eligible' => true, 'reasons' => []];
|
||||
}
|
||||
|
||||
foreach ($definition_json['eligibility_rules'] as $rule) {
|
||||
foreach ($definition['eligibility_rules'] as $rule) {
|
||||
try {
|
||||
$params = $rule['params'] ?? $rule;
|
||||
switch ($rule['type']) {
|
||||
case 'process_completed':
|
||||
$this->checkProcessCompletedRule($personId, $rule);
|
||||
case 'checkProcessCompletedRule':
|
||||
case 'process_completed': // Backward compatibility
|
||||
$this->checkProcessCompletedRule($personId, $params);
|
||||
break;
|
||||
case 'checkProcessDataRule':
|
||||
$this->checkProcessDataRule($personId, $params);
|
||||
break;
|
||||
// Add other rule types here
|
||||
}
|
||||
} catch (WorkflowNotAllowedException $e) {
|
||||
$reasons[] = $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
private function checkProcessCompletedRule(int $personId, array $rule): void {
|
||||
$stmt = $this->pdo->prepare("
|
||||
SELECT pi.id
|
||||
FROM process_instances pi
|
||||
JOIN process_definitions pd ON pi.process_definition_id = pd.id
|
||||
WHERE pi.person_id = ? AND pd.name = ? AND pi.current_status = ?
|
||||
");
|
||||
$stmt->execute([$personId, $rule['process_name'], $rule['expected_status']]);
|
||||
return ['is_eligible' => empty($reasons), 'reasons' => $reasons];
|
||||
}
|
||||
|
||||
private function checkProcessCompletedRule(int $personId, array $params): void {
|
||||
$stmt = $this->pdo->prepare("\n SELECT pi.id\n FROM process_instances pi\n JOIN process_definitions pd ON pi.process_definition_id = pd.id\n WHERE pi.person_id = ? AND pd.code = ? AND pi.current_status = ?\n ORDER BY pi.last_activity_at DESC\n LIMIT 1\n ");
|
||||
$stmt->execute([$personId, $params['process_code'], $params['expected_status']]);
|
||||
$instance = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$instance) {
|
||||
throw new WorkflowNotAllowedException("Not eligible to start this process. Prerequisite process '{$rule['process_name']}' not completed with status '{$rule['expected_status']}'.");
|
||||
throw new WorkflowNotAllowedException("Prerequisite process '{$params['process_code']}' not completed with status '{$params['expected_status']}'.");
|
||||
}
|
||||
}
|
||||
|
||||
private function checkProcessDataRule(int $personId, array $params): void {
|
||||
$stmt = $this->pdo->prepare("
|
||||
SELECT pi.data_json
|
||||
FROM process_instances pi
|
||||
JOIN process_definitions pd ON pi.process_definition_id = pd.id
|
||||
WHERE pi.person_id = ? AND pd.code = ? AND pi.current_status = ?
|
||||
ORDER BY pi.last_activity_at DESC
|
||||
LIMIT 1
|
||||
");
|
||||
$stmt->execute([$personId, $params['process_code'], $params['expected_status']]);
|
||||
$data_json = $stmt->fetchColumn();
|
||||
|
||||
if (!$data_json) {
|
||||
throw new WorkflowNotAllowedException("Not eligible to start this process. Prerequisite process '{$params['process_code']}' not found with status '{$params['expected_status']}'.");
|
||||
}
|
||||
|
||||
$data = json_decode($data_json, true);
|
||||
if (!is_array($data)) {
|
||||
$data = [];
|
||||
}
|
||||
|
||||
foreach ($params['expected_data'] as $key => $expected_value) {
|
||||
if (!isset($data[$key]) || $data[$key] !== $expected_value) {
|
||||
throw new WorkflowNotAllowedException("Not eligible. Condition not met: '$key' is not '$expected_value'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function executeStartProcessAction(int $personId, array $action, int $userId): void {
|
||||
$stmt = $this->pdo->prepare("SELECT id FROM process_definitions WHERE name = ?");
|
||||
$stmt->execute([$action['process_name']]);
|
||||
$stmt = $this->pdo->prepare("SELECT id FROM process_definitions WHERE code = ?");
|
||||
$stmt->execute([$action['process_code']]);
|
||||
$processDefinitionId = $stmt->fetchColumn();
|
||||
|
||||
if ($processDefinitionId) {
|
||||
$this->getOrCreateInstanceByDefId($personId, $processDefinitionId, $userId);
|
||||
}
|
||||
}
|
||||
|
||||
private function executeSetDataAction(int $instanceId, array $action): void {
|
||||
$stmt = $this->pdo->prepare("SELECT data_json FROM process_instances WHERE id = ?");
|
||||
$stmt->execute([$instanceId]);
|
||||
$dataJson = $stmt->fetchColumn();
|
||||
|
||||
$data = $dataJson ? json_decode($dataJson, true) : [];
|
||||
|
||||
$key = $action['params']['key'];
|
||||
$value = $action['params']['value'];
|
||||
$data[$key] = $value;
|
||||
|
||||
$newDataJson = json_encode($data);
|
||||
|
||||
$stmt_update = $this->pdo->prepare("UPDATE process_instances SET data_json = ? WHERE id = ?");
|
||||
$stmt_update->execute([$newDataJson, $instanceId]);
|
||||
}
|
||||
}
|
||||
@ -7,28 +7,25 @@ session_start();
|
||||
|
||||
// Security check
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
throw new WorkflowNotAllowedException('Brak autoryzacji');
|
||||
http_response_code(401);
|
||||
echo json_encode(['error' => 'Unauthorized']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$person_id = $_GET['person_id'] ?? null;
|
||||
$process_definition_id = $_GET['process_id'] ?? null;
|
||||
|
||||
if (!$person_id || !$process_definition_id) {
|
||||
throw new WorkflowRuleFailedException('Brakujące parametry');
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Missing person_id or process_id']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$userId = $_SESSION['user_id'];
|
||||
$engine = new WorkflowEngine();
|
||||
$pdo = db();
|
||||
|
||||
// 1. Get or create instance
|
||||
$instance = $engine->getOrCreateInstanceByDefId($person_id, $process_definition_id, $userId);
|
||||
if (!$instance) {
|
||||
throw new WorkflowNotFoundException("Nie można pobrać lub utworzyć instancji procesu.");
|
||||
}
|
||||
$instanceId = $instance['id'];
|
||||
|
||||
// 2. Fetch all related data
|
||||
// Fetch Person and Process Definition details first
|
||||
$stmt_person = $pdo->prepare("SELECT first_name, last_name FROM people WHERE id = ?");
|
||||
$stmt_person->execute([$person_id]);
|
||||
$person = $stmt_person->fetch();
|
||||
@ -36,24 +33,37 @@ $person = $stmt_person->fetch();
|
||||
$stmt_process = $pdo->prepare("SELECT * FROM process_definitions WHERE id = ?");
|
||||
$stmt_process->execute([$process_definition_id]);
|
||||
$process = $stmt_process->fetch();
|
||||
$definition = $process && $process['definition_json'] ? json_decode($process['definition_json'], true) : null;
|
||||
$isChecklist = ($definition && isset($definition['type']) && $definition['type'] === 'checklist');
|
||||
|
||||
$events = $engine->getEvents($instanceId);
|
||||
if (!$person || !$process) {
|
||||
http_response_code(404);
|
||||
echo "<p class='text-danger'>Could not find person or process.</p>";
|
||||
exit;
|
||||
}
|
||||
|
||||
// Try to find an existing instance
|
||||
$instance = $engine->getInstanceByDefId($person_id, $process_definition_id);
|
||||
|
||||
?>
|
||||
|
||||
<!-- Title for the modal, to be grabbed by JS -->
|
||||
<div id="instance-modal-title" class="d-none">
|
||||
<?= htmlspecialchars($person['first_name'] . ' ' . $person['last_name']) ?> - <?= htmlspecialchars($process['name']) ?>
|
||||
<?= htmlspecialchars($person['first_name']." ".$person['last_name']) ?> - <?= htmlspecialchars($process['name']) ?>
|
||||
</div>
|
||||
|
||||
<?php if ($isChecklist): ?>
|
||||
<?php if ($instance): // INSTANCE EXISTS ?>
|
||||
<?php
|
||||
$instanceId = $instance['id'];
|
||||
$definition = $process['definition_json'] ? json_decode($process['definition_json'], true) : null;
|
||||
$isChecklist = ($definition && isset($definition['type']) && $definition['type'] === 'checklist');
|
||||
$events = $engine->getEvents($instanceId);
|
||||
?>
|
||||
|
||||
<?php if ($isChecklist): ?>
|
||||
<?php
|
||||
$tasks = $definition['tasks'] ?? [];
|
||||
$instanceData = $instance && $instance['data_json'] ? json_decode($instance['data_json'], true) : [];
|
||||
$instanceData = $instance['data_json'] ? json_decode($instance['data_json'], true) : [];
|
||||
?>
|
||||
<div class="checklist-modal-container">
|
||||
<div class="checklist-modal-container" data-instance-id="<?= $instanceId ?>">
|
||||
<h5>Zadania do wykonania</h5>
|
||||
<div class="checklist-container">
|
||||
<?php foreach ($tasks as $task):
|
||||
@ -69,8 +79,7 @@ $events = $engine->getEvents($instanceId);
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php else: ?>
|
||||
<?php else: ?>
|
||||
<?php
|
||||
$currentNodeId = $instance['current_node_id'];
|
||||
$all_nodes = $engine->getProcessDefinitionNodes($process_definition_id);
|
||||
@ -79,7 +88,7 @@ $events = $engine->getEvents($instanceId);
|
||||
$available_target_node_ids = array_map(function($t) { return $t['to']; }, $availableTransitions);
|
||||
$available_transitions_map = [];
|
||||
foreach ($availableTransitions as $t) {
|
||||
$available_transitions_map[$t['to']] = $t;
|
||||
$available_transitions_map[$t['id']] = $t;
|
||||
}
|
||||
|
||||
$visited_nodes = [];
|
||||
@ -92,15 +101,12 @@ $events = $engine->getEvents($instanceId);
|
||||
<div class="process-steps-container">
|
||||
<h5>Kroki procesu</h5>
|
||||
<ul class="list-group">
|
||||
<?php foreach ($all_nodes as $nodeId => $node): ?>
|
||||
<?php
|
||||
<?php foreach ($all_nodes as $nodeId => $node):
|
||||
$is_current = ($currentNodeId === $nodeId);
|
||||
$is_completed = isset($visited_nodes[$nodeId]) && !$is_current;
|
||||
$is_available = in_array($nodeId, $available_target_node_ids);
|
||||
|
||||
$status_icon = '';
|
||||
$li_class = '';
|
||||
$button = '';
|
||||
|
||||
if ($is_current) {
|
||||
$li_class = 'list-group-item-primary';
|
||||
@ -110,18 +116,7 @@ $events = $engine->getEvents($instanceId);
|
||||
$status_icon = '<i class="bi bi-check-circle-fill text-success me-2"></i>';
|
||||
} else {
|
||||
$li_class = 'text-muted';
|
||||
$status_icon = '<i class="bi bi-lock-fill me-2"></i>';
|
||||
}
|
||||
|
||||
if ($is_available) {
|
||||
$transition = $available_transitions_map[$nodeId];
|
||||
$button = <<<HTML
|
||||
<button class="btn btn-sm btn-primary apply-transition-btn"
|
||||
data-instance-id="{$instanceId}"
|
||||
data-transition-id="{$transition['id']}">
|
||||
{$transition['name']}
|
||||
</button>
|
||||
HTML;
|
||||
$status_icon = '<i class="bi bi-circle me-2"></i>';
|
||||
}
|
||||
?>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center <?= $li_class ?>">
|
||||
@ -129,26 +124,39 @@ HTML;
|
||||
<?= $status_icon ?>
|
||||
<strong><?= htmlspecialchars($node['name']) ?></strong>
|
||||
</div>
|
||||
<?= $button ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<div class="mt-3">
|
||||
<h5>Available Actions</h5>
|
||||
<?php if (empty($availableTransitions)): ?>
|
||||
<p>No actions available.</p>
|
||||
<?php else: ?>
|
||||
<?php foreach ($availableTransitions as $transition): ?>
|
||||
<button class="btn btn-sm btn-primary apply-transition-btn"
|
||||
data-instance-id="<?= $instanceId ?>"
|
||||
data-transition-id="<?= $transition['id'] ?>">
|
||||
<?= htmlspecialchars($transition['name']) ?>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<hr>
|
||||
<hr>
|
||||
|
||||
<div class="add-note-container">
|
||||
<div class="add-note-container">
|
||||
<h5>Dodaj notatkę</h5>
|
||||
<div class="mb-3">
|
||||
<textarea id="noteMessage" class="form-control" rows="2" placeholder="Wpisz treść notatki..."></textarea>
|
||||
</div>
|
||||
<button id="addNoteBtn" class="btn btn-secondary" data-instance-id="<?= $instanceId ?>">Dodaj notatkę</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<hr>
|
||||
|
||||
<div class="history-container">
|
||||
<div class="history-container">
|
||||
<h5>Historia</h5>
|
||||
<?php if (empty($events)): ?>
|
||||
<p>Brak zdarzeń.</p>
|
||||
@ -169,7 +177,28 @@ HTML;
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<?php else: // NO INSTANCE EXISTS ?>
|
||||
<?php
|
||||
$eligibility = $engine->checkEligibility($person_id, $process_definition_id);
|
||||
?>
|
||||
|
||||
<div class="text-center">
|
||||
<?php if ($eligibility['is_eligible']): ?>
|
||||
<h4>Process Not Started</h4>
|
||||
<p>This process has not been started for this person.</p>
|
||||
<button id="startProcessBtn" class="btn btn-primary" data-person-id="<?= $person_id ?>" data-process-id="<?= $process_definition_id ?>">
|
||||
Start Process
|
||||
</button>
|
||||
<?php else: ?>
|
||||
<h4>Not Eligible</h4>
|
||||
<p>This person is not eligible to start this process.</p>
|
||||
<ul class="list-group list-group-flush text-start">
|
||||
<?php foreach ($eligibility['reasons'] as $reason): ?>
|
||||
<li class="list-group-item list-group-item-danger"><?= htmlspecialchars($reason) ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
@ -2,48 +2,96 @@
|
||||
require_once 'db/config.php';
|
||||
require_once 'lib/ErrorHandler.php';
|
||||
|
||||
register_error_handler();
|
||||
|
||||
session_start();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
function validate_definition_json($json) {
|
||||
if (empty($json)) {
|
||||
return; // No validation for empty json
|
||||
}
|
||||
$data = json_decode($json, true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
http_response_code(422);
|
||||
throw new WorkflowRuleFailedException('Invalid JSON format in definition.');
|
||||
}
|
||||
|
||||
$allowed_statuses = ['none', 'negative', 'in_progress', 'positive'];
|
||||
|
||||
if (isset($data['nodes'])) {
|
||||
foreach ($data['nodes'] as $node) {
|
||||
if (isset($node['ui_hints']['status']) && !in_array($node['ui_hints']['status'], $allowed_statuses)) {
|
||||
http_response_code(422);
|
||||
throw new WorkflowRuleFailedException('Invalid status in ui_hints. Allowed values are: ' . implode(', ', $allowed_statuses));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($data['transitions'])) {
|
||||
foreach ($data['transitions'] as $transition) {
|
||||
if (isset($transition['actions'])) {
|
||||
foreach ($transition['actions'] as $action) {
|
||||
if ($action['type'] === 'start_process' && isset($action['process_name'])) {
|
||||
http_response_code(422);
|
||||
throw new WorkflowRuleFailedException('Use process_code instead of process_name in transition actions.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($data['eligibility_rules'])) {
|
||||
foreach ($data['eligibility_rules'] as $rule) {
|
||||
if ($rule['type'] === 'process_completed' && isset($rule['process_name'])) {
|
||||
http_response_code(422);
|
||||
throw new WorkflowRuleFailedException('Use process_code instead of process_name in eligibility_rules.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$processId = $_POST['process_id'] ?? null;
|
||||
$name = $_POST['name'] ?? '';
|
||||
$definition_json = $_POST['definition_json'] ?? '';
|
||||
|
||||
validate_definition_json($definition_json);
|
||||
|
||||
// Generate a simple code from the name
|
||||
$code = strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $name)));
|
||||
|
||||
if (empty($name)) {
|
||||
throw new WorkflowRuleFailedException('Process name is required.');
|
||||
}
|
||||
|
||||
// Validate JSON
|
||||
if (!empty($definition_json)) {
|
||||
json_decode($definition_json);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
throw new WorkflowRuleFailedException('Invalid JSON format in definition.');
|
||||
}
|
||||
}
|
||||
|
||||
$pdo = db();
|
||||
|
||||
if (empty($processId)) {
|
||||
// Create new process
|
||||
$sql = 'INSERT INTO process_definitions (name, definition_json, is_active) VALUES (?, ?, 1)';
|
||||
$params = [$name, $definition_json, 1];
|
||||
$sql = 'INSERT INTO process_definitions (name, code, definition_json, is_active) VALUES (?, ?, ?, 1)';
|
||||
$params = [$name, $code, $definition_json];
|
||||
$message = 'Process created successfully.';
|
||||
} else {
|
||||
// Update existing process
|
||||
$sql = 'UPDATE process_definitions SET name = ?, definition_json = ? WHERE id = ?';
|
||||
$params = [$name, $definition_json, $processId];
|
||||
$is_active = isset($_POST['is_active']) ? (int)$_POST['is_active'] : 0;
|
||||
$sql = 'UPDATE process_definitions SET name = ?, code = ?, definition_json = ?, is_active = ? WHERE id = ?';
|
||||
$params = [$name, $code, $definition_json, $is_active, $processId];
|
||||
$message = 'Process updated successfully.';
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
|
||||
if (isset($_SERVER['HTTP_ACCEPT']) && strpos($_SERVER['HTTP_ACCEPT'], 'application/json') !== false) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['message' => $message]);
|
||||
} else {
|
||||
$_SESSION['success_message'] = $message;
|
||||
header('Location: process_definitions.php');
|
||||
}
|
||||
exit();
|
||||
}
|
||||
}
|
||||
} catch (WorkflowRuleFailedException $e) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['error' => $e->getMessage()]);
|
||||
}
|
||||
38
index.php
38
index.php
@ -206,36 +206,50 @@ $status_colors = [
|
||||
$instance = $instances[$person['id']][$process['id']] ?? null;
|
||||
$lastActivity = $instance && isset($instance['last_activity_at']) ? date('d/m/y', strtotime($instance['last_activity_at'])) : '';
|
||||
|
||||
$is_eligible = $instance ? ($instance['is_eligible'] ?? true) : false;
|
||||
// Correctly check eligibility using the WorkflowEngine
|
||||
$eligibilityCheck = $workflowEngine->checkEligibility($person['id'], $process['id']);
|
||||
$is_eligible = $eligibilityCheck['is_eligible'];
|
||||
|
||||
if ($instance && isset($instance['id'])) { // Existing instance
|
||||
$is_active = $process['is_active'] ?? true;
|
||||
$modal_target = ''; // Default to not clickable
|
||||
$is_clickable = false;
|
||||
|
||||
if (!$is_active) {
|
||||
$status = 'inactive';
|
||||
$color = $status_colors['inactive'];
|
||||
$title = 'Process inactive';
|
||||
} elseif ($instance && isset($instance['id'])) { // Existing instance
|
||||
$status = $instance['computed_status'];
|
||||
$color = $status_colors[$status] ?? $status_colors['inactive'];
|
||||
$title = ucfirst($status);
|
||||
if (!empty($instance['computed_reason'])) {
|
||||
$title = $instance['computed_reason'];
|
||||
}
|
||||
$title = !empty($instance['computed_reason']) ? $instance['computed_reason'] : ucfirst($status);
|
||||
$modal_target = '#instanceModal';
|
||||
$is_clickable = true;
|
||||
} else { // No instance
|
||||
if ($is_eligible) {
|
||||
$status = 'not_started';
|
||||
$color = $status_colors[$status];
|
||||
$title = 'Not Started';
|
||||
$modal_target = '#bulkInitModal';
|
||||
$modal_target = '#instanceModal';
|
||||
$is_clickable = true;
|
||||
} else {
|
||||
$status = 'ineligible';
|
||||
$color = '#e9ecef'; // A light gray color
|
||||
$title = 'Not eligible';
|
||||
$modal_target = ''; // Prevent modal
|
||||
$color = '#e9ecef'; // A light gray color for the circle
|
||||
$title = implode(' ', $eligibilityCheck['reasons']); // Use the reason from the engine
|
||||
$modal_target = '#instanceModal'; // Still open the modal to show details
|
||||
$is_clickable = true;
|
||||
}
|
||||
}
|
||||
?>
|
||||
<td class="text-center align-middle"
|
||||
style="cursor: <?= $modal_target ? 'pointer' : 'not-allowed' ?>;"
|
||||
<?= $modal_target ? 'data-bs-toggle="modal"' : '' ?>
|
||||
<?php if ($is_clickable): ?>
|
||||
style="cursor: pointer;"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="<?= $modal_target ?>"
|
||||
data-person-id="<?= $person['id'] ?>"
|
||||
data-process-id="<?= $process['id'] ?>"
|
||||
<?php else: ?>
|
||||
style="cursor: not-allowed;"
|
||||
<?php endif; ?>
|
||||
title="<?= htmlspecialchars($title) ?>">
|
||||
<span style="height: 20px; width: 20px; background-color: <?= $color ?>; border-radius: 50%; display: inline-block;"></span>
|
||||
<small class="text-muted d-block mt-1"><?= $lastActivity ?></small>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user