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
= (int)$totalRoles; ?>
Mansioni attive
= (int)$totalActiveRoles; ?>
Sottomansioni totali
= (int)$totalSubRoles; ?>
Sottomansioni attive
= (int)$totalActiveSubRoles; ?>
|
Mansione |
Sottomansioni |
Stato |
Azioni |
|
|
= htmlspecialchars($role['name'], ENT_QUOTES, 'UTF-8'); ?>
= htmlspecialchars($role['description'], ENT_QUOTES, 'UTF-8'); ?>
|
= (int)$role['sub_roles_count']; ?>
|
Attiva
Inattiva
|
|
Usa la freccia per espandere la mansione e gestire le sottomansioni. I DPI si associano dalla singola sottomansione con selezione multipla.