Poprawki dotyczące procesów
This commit is contained in:
parent
f2aacc643f
commit
9134470c19
@ -63,7 +63,9 @@ class WorkflowEngine {
|
|||||||
|
|
||||||
$definitions = [];
|
$definitions = [];
|
||||||
$definition_map = [];
|
$definition_map = [];
|
||||||
|
$codeToIdMap = [];
|
||||||
foreach ($process_definitions_raw as $def) {
|
foreach ($process_definitions_raw as $def) {
|
||||||
|
$codeToIdMap[$def['code']] = $def['id'];
|
||||||
$definitions[$def['id']] = [
|
$definitions[$def['id']] = [
|
||||||
'id' => $def['id'],
|
'id' => $def['id'],
|
||||||
'code' => $def['code'],
|
'code' => $def['code'],
|
||||||
@ -78,7 +80,7 @@ class WorkflowEngine {
|
|||||||
$person_ids = array_column($people, 'id');
|
$person_ids = array_column($people, 'id');
|
||||||
if (!empty($person_ids)) {
|
if (!empty($person_ids)) {
|
||||||
$placeholders = implode(',', array_fill(0, count($person_ids), '?'));
|
$placeholders = implode(',', array_fill(0, count($person_ids), '?'));
|
||||||
$stmt_instances = $this->pdo->prepare("SELECT * FROM process_instances WHERE person_id IN ($placeholders)");
|
$stmt_instances = $this->pdo->prepare("SELECT pi.*, pd.code as process_code, pd.definition_json as pd_definition_json FROM process_instances pi JOIN process_definitions pd ON pi.process_definition_id = pd.id WHERE pi.person_id IN ($placeholders) ORDER BY pi.last_activity_at DESC");
|
||||||
$stmt_instances->execute($person_ids);
|
$stmt_instances->execute($person_ids);
|
||||||
$instances_data = $stmt_instances->fetchAll(PDO::FETCH_ASSOC);
|
$instances_data = $stmt_instances->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
@ -87,7 +89,7 @@ class WorkflowEngine {
|
|||||||
$def_id = $instance['process_definition_id'];
|
$def_id = $instance['process_definition_id'];
|
||||||
$node_id = $instance['current_node_id'];
|
$node_id = $instance['current_node_id'];
|
||||||
|
|
||||||
$definition = $definition_map[$def_id] ?? null;
|
$definition = !empty($instance['pd_definition_json']) ? json_decode($instance['pd_definition_json'], true) : ($definition_map[$def_id] ?? null);
|
||||||
|
|
||||||
if ($definition && isset($definition['type']) && $definition['type'] === 'checklist') {
|
if ($definition && isset($definition['type']) && $definition['type'] === 'checklist') {
|
||||||
$tasks = $definition['tasks'] ?? [];
|
$tasks = $definition['tasks'] ?? [];
|
||||||
|
|||||||
@ -15,6 +15,15 @@ if (!isset($_SESSION['user_id'])) {
|
|||||||
|
|
||||||
$person_id = $_GET['person_id'] ?? null;
|
$person_id = $_GET['person_id'] ?? null;
|
||||||
$process_definition_id = $_GET['process_id'] ?? null;
|
$process_definition_id = $_GET['process_id'] ?? null;
|
||||||
|
$process_code = $_GET['process_code'] ?? null;
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
if (!$process_definition_id && $process_code) {
|
||||||
|
$stmt = $pdo->prepare("SELECT id FROM process_definitions WHERE code = ? AND is_latest = 1 LIMIT 1");
|
||||||
|
$stmt->execute([$process_code]);
|
||||||
|
$process_definition_id = $stmt->fetchColumn();
|
||||||
|
}
|
||||||
|
|
||||||
if (!$person_id || !$process_definition_id) {
|
if (!$person_id || !$process_definition_id) {
|
||||||
http_response_code(400);
|
http_response_code(400);
|
||||||
@ -24,7 +33,6 @@ if (!$person_id || !$process_definition_id) {
|
|||||||
|
|
||||||
$userId = $_SESSION['user_id'];
|
$userId = $_SESSION['user_id'];
|
||||||
$engine = new WorkflowEngine();
|
$engine = new WorkflowEngine();
|
||||||
$pdo = db();
|
|
||||||
|
|
||||||
// Fetch Person and Process Definition details first
|
// Fetch Person and Process Definition details first
|
||||||
$stmt_person = $pdo->prepare("SELECT first_name, last_name FROM people WHERE id = ?");
|
$stmt_person = $pdo->prepare("SELECT first_name, last_name FROM people WHERE id = ?");
|
||||||
|
|||||||
@ -20,11 +20,20 @@ if (!isset($_SESSION['user_id'])) {
|
|||||||
$userId = $_SESSION['user_id'];
|
$userId = $_SESSION['user_id'];
|
||||||
$personId = filter_input(INPUT_POST, 'person_id', FILTER_VALIDATE_INT);
|
$personId = filter_input(INPUT_POST, 'person_id', FILTER_VALIDATE_INT);
|
||||||
$processDefinitionId = filter_input(INPUT_POST, 'process_id', FILTER_VALIDATE_INT);
|
$processDefinitionId = filter_input(INPUT_POST, 'process_id', FILTER_VALIDATE_INT);
|
||||||
|
$processCode = filter_input(INPUT_POST, 'process_code', FILTER_SANITIZE_STRING);
|
||||||
$deleteExisting = filter_input(INPUT_POST, 'delete_existing');
|
$deleteExisting = filter_input(INPUT_POST, 'delete_existing');
|
||||||
|
$mode = filter_input(INPUT_POST, 'mode', FILTER_SANITIZE_STRING);
|
||||||
|
|
||||||
|
$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 (!$personId || !$processDefinitionId) {
|
if (!$personId || !$processDefinitionId) {
|
||||||
// InvalidArgumentException will be caught by the handler and result in a 400 Bad Request
|
throw new InvalidArgumentException('Invalid or missing person_id or process_id/process_code.');
|
||||||
throw new InvalidArgumentException('Invalid or missing person_id or process_id.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$engine = new WorkflowEngine();
|
$engine = new WorkflowEngine();
|
||||||
@ -36,22 +45,14 @@ if($deleteExisting === '1') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The getOrCreateInstanceByDefId method is now responsible for all checks:
|
if ($mode === 'create_new_run' || filter_input(INPUT_POST, 'force', FILTER_VALIDATE_INT) === 1) {
|
||||||
// 1. Validating the process definition exists.
|
$instance = $engine->createNewInstance($personId, $processDefinitionId, $userId);
|
||||||
// 2. Checking if the process is active.
|
|
||||||
// 3. Checking if the person is eligible.
|
|
||||||
// 4. Creating the instance if it doesn't exist.
|
|
||||||
// It will throw specific exceptions (WorkflowNotFoundException, WorkflowNotAllowedException, WorkflowEligibilityException) which our ErrorHandler will turn into 404, 409, and 422 responses.
|
|
||||||
= filter_input(INPUT_POST, 'force', FILTER_VALIDATE_INT);
|
|
||||||
if ( === 1) {
|
|
||||||
= ->createNewInstance(, , );
|
|
||||||
} else {
|
} else {
|
||||||
= ->getOrCreateInstanceByDefId(, , );
|
$instance = $engine->getOrCreateInstanceByDefId($personId, $processDefinitionId, $userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($instance) {
|
if ($instance) {
|
||||||
echo json_encode(['success' => true, 'message' => 'Process initialized successfully.', 'instance_id' => $instance['id']]);
|
echo json_encode(['success' => true, 'message' => 'Process initialized successfully.', 'instance_id' => $instance['id']]);
|
||||||
} else {
|
} else {
|
||||||
// This case should not be reached if the engine works as expected, as failures should throw exceptions.
|
|
||||||
throw new Exception("Failed to initialize process for an unknown reason.");
|
throw new Exception("Failed to initialize process for an unknown reason.");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,4 +2,4 @@
|
|||||||
# https://curl.se/docs/http-cookies.html
|
# https://curl.se/docs/http-cookies.html
|
||||||
# This file was generated by libcurl! Edit at your own risk.
|
# This file was generated by libcurl! Edit at your own risk.
|
||||||
|
|
||||||
localhost FALSE / FALSE 0 PHPSESSID rfo6k0p8l4tpnmgek7dkpkopbl
|
127.0.0.1 FALSE / FALSE 0 PHPSESSID np7q4kbboaogr1lb2gg3753mdu
|
||||||
|
|||||||
70
index.php
70
index.php
@ -1245,6 +1245,76 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
// --- Actions inside Instance Modal ---
|
// --- Actions inside Instance Modal ---
|
||||||
if (instanceModalElement) {
|
if (instanceModalElement) {
|
||||||
instanceModalElement.addEventListener('click', function(event) {
|
instanceModalElement.addEventListener('click', function(event) {
|
||||||
|
const restartBtn = event.target.closest('#restartProcessBtn');
|
||||||
|
if (restartBtn) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
const personId = restartBtn.dataset.personId;
|
||||||
|
const processCode = restartBtn.dataset.processCode;
|
||||||
|
const mode = restartBtn.dataset.mode;
|
||||||
|
|
||||||
|
if (!personId || !processCode) {
|
||||||
|
alert('Brak ID osoby lub kodu procesu');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const originalText = restartBtn.innerHTML;
|
||||||
|
restartBtn.disabled = true;
|
||||||
|
restartBtn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>...';
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('person_id', personId);
|
||||||
|
formData.append('process_code', processCode);
|
||||||
|
formData.append('mode', mode || 'create_new_run');
|
||||||
|
|
||||||
|
fetch('_init_single_instance.php', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
return response.text().then(text => {
|
||||||
|
throw new Error(`HTTP ${response.status}: ${text.substring(0, 100)}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
window.matrixNeedsRefresh = true;
|
||||||
|
const modalBody = instanceModalElement.querySelector('.modal-body');
|
||||||
|
modalBody.innerHTML = '<div class="text-center mt-4"><div class="spinner-border text-primary" role="status"></div><p class="mt-2">Ładowanie...</p></div>';
|
||||||
|
|
||||||
|
// Use process_id if we have it from dataset, otherwise fetch using code.
|
||||||
|
// The original _get_instance_details endpoint seems to accept process_id or process_code? Let's check.
|
||||||
|
// Actually let's use the instanceModalElement.dataset.lastProcessId if it exists.
|
||||||
|
const fetchUrl = `_get_instance_details.php?person_id=${personId}&process_code=${processCode}`;
|
||||||
|
|
||||||
|
fetch(fetchUrl)
|
||||||
|
.then(r => r.text())
|
||||||
|
.then(html => {
|
||||||
|
modalBody.innerHTML = html;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
let errMsg = data.error?.message || data.error || 'Nieoczekiwany błąd';
|
||||||
|
if (data.correlation_id) {
|
||||||
|
errMsg += ' (ID: ' + data.correlation_id + ')';
|
||||||
|
}
|
||||||
|
alert('Błąd: ' + errMsg);
|
||||||
|
restartBtn.disabled = false;
|
||||||
|
restartBtn.innerHTML = originalText;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
alert('Błąd: ' + err.message);
|
||||||
|
restartBtn.disabled = false;
|
||||||
|
restartBtn.innerHTML = originalText;
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Apply Transition Button
|
// Apply Transition Button
|
||||||
if (event.target.classList.contains('apply-transition-btn')) {
|
if (event.target.classList.contains('apply-transition-btn')) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|||||||
@ -1,22 +0,0 @@
|
|||||||
with open('index.php', 'r', encoding='utf-8') as f:
|
|
||||||
content = f.read()
|
|
||||||
|
|
||||||
start_str = " const instanceModalElement = document.getElementById('instanceModal');\n if (instanceModalElement) {\n instanceModalElement.addEventListener('click', function(event) {\n const btn = event.target.closest('#startProcessBtn');\n if (!btn) return;"
|
|
||||||
end_str = " });\n }"
|
|
||||||
|
|
||||||
start_idx = content.find(start_str)
|
|
||||||
if start_idx != -1:
|
|
||||||
end_idx = content.find(end_str, start_idx)
|
|
||||||
if end_idx != -1:
|
|
||||||
end_idx += len(end_str)
|
|
||||||
|
|
||||||
replacement = " const instanceModalElement = document.getElementById('instanceModal');\n if (instanceModalElement) {\n instanceModalElement.addEventListener('click', function(event) {\n const startBtn = event.target.closest('#startProcessBtn');\n const restartBtn = event.target.closest('#restartProcessBtn');\n const btn = startBtn || restartBtn;\n if (!btn) return;\n \n event.preventDefault();\n event.stopPropagation();\n \n const isRestart = !!restartBtn;\n \n const personId = btn.dataset.personId;\n const processId = btn.dataset.processId;\n const processCode = btn.dataset.processCode;\n \n if (!personId) {\n alert('Brak ID osoby');\n return;\n }\n if (isRestart && !processCode) {\n alert('Brak kodu procesu');\n return;\n }\n if (!isRestart && !processId) {\n alert('Brak ID procesu');\n return;\n }\n \n const originalText = btn.innerHTML;\n btn.disabled = true;\n btn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>...';\n \n const formData = new FormData();\n formData.append('person_id', personId);\n \n if (isRestart) {\n formData.append('process_code', processCode);\n formData.append('mode', 'create_new_run');\n } else {\n formData.append('process_id', processId);\n }\n \n if (instanceModalElement && processId) {\n instanceModalElement.dataset.lastPersonId = personId;\n instanceModalElement.dataset.lastProcessId = processId;\n }\n \n fetch('_init_single_instance.php', {\n method: 'POST',\n body: formData\n })\n .then(async response => {\n let data;\n try {\n data = await response.json();\n } catch (e) {\n throw new Error(`Błąd serwera (HTTP ${response.status}): Nieoczekiwany błąd (invalid JSON)`);\n }\n \n if (!response.ok || !data.success) {\n let errMsg = data?.error?.message || data?.error || 'Nieznany błąd';\n if (data?.correlation_id) {\n errMsg += ` (ID błędu: ${data.correlation_id})`;\n }\n throw new Error(errMsg);\n }\n return data;\n })\n .then(data => {\n const modalBody = instanceModalElement.querySelector('.modal-body');\n modalBody.innerHTML = '<div class="text-center mt-4"><div class="spinner-border text-primary" role="status"></div><p class="mt-2">Ładowanie...</p></div>';\n \n const refreshProcessId = data.process_definition_id || processId || instanceModalElement.dataset.lastProcessId;\n if (refreshProcessId) {\n instanceModalElement.dataset.lastProcessId = refreshProcessId;\n }\n \n fetch(`_get_instance_details.php?person_id=${personId}&process_id=${refreshProcessId}`)\n .then(r => r.text())\n .then(html => {\n modalBody.innerHTML = html;\n window.matrixNeedsRefresh = true;\n });\n })\n .catch(err => {\n console.error(err);\n alert(err.message || 'Błąd sieci');\n btn.disabled = false;\n btn.innerHTML = originalText;\n });\n });\n }"
|
|
||||||
|
|
||||||
new_content = content[:start_idx] + replacement + content[end_idx:]
|
|
||||||
with open('index.php', 'w', encoding='utf-8') as f:
|
|
||||||
f.write(new_content)
|
|
||||||
print("Replaced index.php block successfully.")
|
|
||||||
else:
|
|
||||||
print("End string not found.")
|
|
||||||
else:
|
|
||||||
print("Start string not found.")
|
|
||||||
Loading…
x
Reference in New Issue
Block a user