getConnection(); function jsonResponse(bool $success, string $message = '', array $extra = []): void { header('Content-Type: application/json; charset=utf-8'); echo json_encode(array_merge([ 'success' => $success, 'message' => $message, ], $extra)); exit; } function cleanString(?string $value): string { return trim((string)$value); } function cleanNullableString(?string $value): ?string { $value = trim((string)$value); return $value === '' ? null : $value; } function toActiveValue($value): int { return ((string)$value === '1') ? 1 : 0; } function syncSubRolePpeLinks(PDO $pdo, int $subRoleId, array $ppeIds): void { $stmt = $pdo->prepare(" DELETE FROM job_sub_role_ppe_items WHERE job_sub_role_id = ? "); $stmt->execute([$subRoleId]); $ppeIds = array_values(array_unique(array_filter(array_map('intval', $ppeIds)))); if (!$ppeIds) { return; } $stmt = $pdo->prepare(" INSERT INTO job_sub_role_ppe_items ( job_sub_role_id, ppe_item_id, requirement_type, sort_order, is_active, created_at, updated_at ) VALUES ( :job_sub_role_id, :ppe_item_id, 'mandatory', :sort_order, 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP ) "); $sortOrder = 1; foreach ($ppeIds as $ppeId) { $stmt->execute([ ':job_sub_role_id' => $subRoleId, ':ppe_item_id' => $ppeId, ':sort_order' => $sortOrder, ]); $sortOrder++; } } /* |-------------------------------------------------------------------------- | AJAX actions |-------------------------------------------------------------------------- */ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) { try { $action = $_POST['action']; if ($action === 'save_role') { $id = isset($_POST['id']) && $_POST['id'] !== '' ? (int)$_POST['id'] : null; $name = cleanString($_POST['name'] ?? ''); $description = cleanNullableString($_POST['description'] ?? null); $sortOrder = isset($_POST['sort_order']) && $_POST['sort_order'] !== '' ? (int)$_POST['sort_order'] : 999; $isActive = toActiveValue($_POST['is_active'] ?? 1); if ($name === '') { jsonResponse(false, 'Il nome della mansione è obbligatorio.'); } if ($id) { $stmt = $pdo->prepare(" UPDATE job_roles SET name = :name, description = :description, sort_order = :sort_order, is_active = :is_active, updated_at = CURRENT_TIMESTAMP WHERE id = :id "); $stmt->execute([ ':name' => $name, ':description' => $description, ':sort_order' => $sortOrder, ':is_active' => $isActive, ':id' => $id, ]); jsonResponse(true, 'Mansione aggiornata correttamente.'); } $stmt = $pdo->prepare(" INSERT INTO job_roles (name, description, sort_order, is_active, created_at, updated_at) VALUES (:name, :description, :sort_order, :is_active, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) "); $stmt->execute([ ':name' => $name, ':description' => $description, ':sort_order' => $sortOrder, ':is_active' => $isActive, ]); jsonResponse(true, 'Mansione creata correttamente.'); } if ($action === 'get_role') { $id = (int)($_POST['id'] ?? 0); if ($id <= 0) { jsonResponse(false, 'ID mansione non valido.'); } $stmt = $pdo->prepare(" SELECT id, name, description, sort_order, is_active FROM job_roles WHERE id = ? LIMIT 1 "); $stmt->execute([$id]); $role = $stmt->fetch(PDO::FETCH_ASSOC); if (!$role) { jsonResponse(false, 'Mansione non trovata.'); } jsonResponse(true, '', [ 'role' => $role, ]); } if ($action === 'delete_role') { $id = (int)($_POST['id'] ?? 0); if ($id <= 0) { jsonResponse(false, 'ID mansione non valido.'); } $pdo->beginTransaction(); $stmt = $pdo->prepare("DELETE FROM job_roles WHERE id = ?"); $stmt->execute([$id]); $pdo->commit(); jsonResponse(true, 'Mansione eliminata correttamente.'); } if ($action === 'save_sub_role') { $id = isset($_POST['id']) && $_POST['id'] !== '' ? (int)$_POST['id'] : null; $jobRoleId = (int)($_POST['job_role_id'] ?? 0); $name = cleanString($_POST['name'] ?? ''); $description = cleanNullableString($_POST['description'] ?? null); $sortOrder = isset($_POST['sort_order']) && $_POST['sort_order'] !== '' ? (int)$_POST['sort_order'] : 999; $isActive = toActiveValue($_POST['is_active'] ?? 1); if ($jobRoleId <= 0) { jsonResponse(false, 'Mansione principale non valida.'); } if ($name === '') { jsonResponse(false, 'Il nome della sottomansione è obbligatorio.'); } $checkRole = $pdo->prepare("SELECT id FROM job_roles WHERE id = ? LIMIT 1"); $checkRole->execute([$jobRoleId]); if (!$checkRole->fetchColumn()) { jsonResponse(false, 'La mansione principale selezionata non esiste.'); } if ($id) { $stmt = $pdo->prepare(" UPDATE job_sub_roles SET job_role_id = :job_role_id, name = :name, description = :description, sort_order = :sort_order, is_active = :is_active, updated_at = CURRENT_TIMESTAMP WHERE id = :id "); $stmt->execute([ ':job_role_id' => $jobRoleId, ':name' => $name, ':description' => $description, ':sort_order' => $sortOrder, ':is_active' => $isActive, ':id' => $id, ]); jsonResponse(true, 'Sottomansione aggiornata correttamente.'); } $stmt = $pdo->prepare(" INSERT INTO job_sub_roles (job_role_id, name, description, sort_order, is_active, created_at, updated_at) VALUES (:job_role_id, :name, :description, :sort_order, :is_active, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) "); $stmt->execute([ ':job_role_id' => $jobRoleId, ':name' => $name, ':description' => $description, ':sort_order' => $sortOrder, ':is_active' => $isActive, ]); jsonResponse(true, 'Sottomansione creata correttamente.'); } if ($action === 'get_sub_role') { $id = (int)($_POST['id'] ?? 0); if ($id <= 0) { jsonResponse(false, 'ID sottomansione non valido.'); } $stmt = $pdo->prepare(" SELECT id, job_role_id, name, description, sort_order, is_active FROM job_sub_roles WHERE id = ? LIMIT 1 "); $stmt->execute([$id]); $subRole = $stmt->fetch(PDO::FETCH_ASSOC); if (!$subRole) { jsonResponse(false, 'Sottomansione non trovata.'); } jsonResponse(true, '', [ 'sub_role' => $subRole, ]); } if ($action === 'delete_sub_role') { $id = (int)($_POST['id'] ?? 0); if ($id <= 0) { jsonResponse(false, 'ID sottomansione non valido.'); } $stmt = $pdo->prepare("DELETE FROM job_sub_roles WHERE id = ?"); $stmt->execute([$id]); jsonResponse(true, 'Sottomansione eliminata correttamente.'); } if ($action === 'get_sub_role_ppe') { $subRoleId = (int)($_POST['sub_role_id'] ?? 0); if ($subRoleId <= 0) { jsonResponse(false, 'ID sottomansione non valido.'); } $stmt = $pdo->prepare(" SELECT jsr.id, jsr.name, jr.name AS role_name FROM job_sub_roles jsr INNER JOIN job_roles jr ON jr.id = jsr.job_role_id WHERE jsr.id = ? LIMIT 1 "); $stmt->execute([$subRoleId]); $subRole = $stmt->fetch(PDO::FETCH_ASSOC); if (!$subRole) { jsonResponse(false, 'Sottomansione non trovata.'); } $stmt = $pdo->prepare(" SELECT ppe_item_id FROM job_sub_role_ppe_items WHERE job_sub_role_id = ? AND is_active = 1 "); $stmt->execute([$subRoleId]); $selectedPpeIds = array_map('intval', $stmt->fetchAll(PDO::FETCH_COLUMN)); jsonResponse(true, '', [ 'sub_role' => $subRole, 'selected_ppe_ids' => $selectedPpeIds, ]); } if ($action === 'save_sub_role_ppe') { $subRoleId = (int)($_POST['sub_role_id'] ?? 0); $ppeIds = $_POST['ppe_items'] ?? []; if ($subRoleId <= 0) { jsonResponse(false, 'ID sottomansione non valido.'); } $stmt = $pdo->prepare("SELECT id FROM job_sub_roles WHERE id = ? LIMIT 1"); $stmt->execute([$subRoleId]); if (!$stmt->fetchColumn()) { jsonResponse(false, 'Sottomansione non trovata.'); } syncSubRolePpeLinks($pdo, $subRoleId, is_array($ppeIds) ? $ppeIds : []); jsonResponse(true, 'DPI associati correttamente.'); } jsonResponse(false, 'Azione non riconosciuta.'); } catch (Throwable $e) { if ($pdo->inTransaction()) { $pdo->rollBack(); } jsonResponse(false, 'Errore: ' . $e->getMessage()); } } /* |-------------------------------------------------------------------------- | Page data |-------------------------------------------------------------------------- */ $stmt = $pdo->prepare(" SELECT jr.id, jr.name, jr.description, jr.sort_order, jr.is_active, jr.created_at, jr.updated_at, COUNT(jsr.id) AS sub_roles_count FROM job_roles jr LEFT JOIN job_sub_roles jsr ON jsr.job_role_id = jr.id GROUP BY jr.id, jr.name, jr.description, jr.sort_order, jr.is_active, jr.created_at, jr.updated_at ORDER BY jr.sort_order ASC, jr.name ASC "); $stmt->execute(); $roles = $stmt->fetchAll(PDO::FETCH_ASSOC); $stmt = $pdo->prepare(" SELECT jsr.id, jsr.job_role_id, jsr.name, jsr.description, jsr.sort_order, jsr.is_active, jr.name AS role_name FROM job_sub_roles jsr INNER JOIN job_roles jr ON jr.id = jsr.job_role_id ORDER BY jr.sort_order ASC, jr.name ASC, jsr.sort_order ASC, jsr.name ASC "); $stmt->execute(); $subRoles = $stmt->fetchAll(PDO::FETCH_ASSOC); $stmt = $pdo->prepare(" SELECT id, name, category, photo, standard_reference, is_active FROM ppe_items WHERE is_active = 1 ORDER BY sort_order ASC, name ASC "); $stmt->execute(); $ppeItems = $stmt->fetchAll(PDO::FETCH_ASSOC); $stmt = $pdo->prepare(" SELECT jsp.job_sub_role_id, jsp.ppe_item_id, p.name AS ppe_name, p.category AS ppe_category, p.photo AS ppe_photo FROM job_sub_role_ppe_items jsp INNER JOIN ppe_items p ON p.id = jsp.ppe_item_id WHERE jsp.is_active = 1 AND p.is_active = 1 ORDER BY jsp.sort_order ASC, p.name ASC "); $stmt->execute(); $ppeLinksRows = $stmt->fetchAll(PDO::FETCH_ASSOC); $ppeLinksBySubRole = []; foreach ($ppeLinksRows as $ppeLink) { $ppeLinksBySubRole[(int)$ppeLink['job_sub_role_id']][] = $ppeLink; } $subRolesByRole = []; foreach ($subRoles as $subRole) { $subRoleId = (int)$subRole['id']; $subRole['ppe_items'] = $ppeLinksBySubRole[$subRoleId] ?? []; $subRolesByRole[(int)$subRole['job_role_id']][] = $subRole; } $totalRoles = count($roles); $totalActiveRoles = 0; $totalSubRoles = count($subRoles); $totalActiveSubRoles = 0; foreach ($roles as $role) { if ((int)$role['is_active'] === 1) { $totalActiveRoles++; } } foreach ($subRoles as $subRole) { if ((int)$subRole['is_active'] === 1) { $totalActiveSubRoles++; } } $jsonFlags = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT; $subRolesByRoleJson = json_encode($subRolesByRole, $jsonFlags); ?> Mansioni e Sottomansioni - <?= htmlspecialchars($titlewebsite ?? '', ENT_QUOTES, 'UTF-8'); ?>

Mansioni e Sottomansioni

Gestione compatta delle mansioni, sottomansioni e DPI necessari.

Mansioni totali
Mansioni attive
Sottomansioni totali
Sottomansioni attive
Elenco Mansioni
Mansione Sottomansioni Stato Azioni
Attiva Inattiva
Usa la freccia per espandere la mansione e gestire le sottomansioni. I DPI si associano dalla singola sottomansione con selezione multipla.