getConnection();
function normalizeNullableInt($value): ?int
{
return (isset($value) && $value !== '') ? (int)$value : null;
}
function normalizeIntArray($values): array
{
if (!is_array($values)) {
$values = $values !== null && $values !== '' ? [$values] : [];
}
return array_values(array_unique(array_filter(array_map('intval', $values))));
}
function validateJobSubRoles(PDO $pdo, array $jobSubRoleIds): array
{
$jobSubRoleIds = normalizeIntArray($jobSubRoleIds);
if (!$jobSubRoleIds) {
return [];
}
$placeholders = implode(',', array_fill(0, count($jobSubRoleIds), '?'));
$stmt = $pdo->prepare("
SELECT jsr.id
FROM job_sub_roles jsr
INNER JOIN job_roles jr ON jr.id = jsr.job_role_id
WHERE jsr.id IN ($placeholders)
AND jsr.is_active = 1
AND jr.is_active = 1
");
$stmt->execute($jobSubRoleIds);
$validIds = array_map('intval', $stmt->fetchAll(PDO::FETCH_COLUMN));
sort($validIds);
$requestedIds = $jobSubRoleIds;
sort($requestedIds);
if ($validIds !== $requestedIds) {
throw new Exception('Una o più sottomansioni selezionate non sono valide o non sono attive.');
}
return $jobSubRoleIds;
}
function getPrimaryJobRoleAndSubRole(PDO $pdo, array $jobSubRoleIds): array
{
$jobSubRoleIds = normalizeIntArray($jobSubRoleIds);
if (!$jobSubRoleIds) {
return [null, null];
}
$stmt = $pdo->prepare("
SELECT job_role_id
FROM job_sub_roles
WHERE id = ?
LIMIT 1
");
$stmt->execute([$jobSubRoleIds[0]]);
$jobRoleId = $stmt->fetchColumn();
return [$jobRoleId !== false ? (int)$jobRoleId : null, (int)$jobSubRoleIds[0]];
}
function saveEmployeeSubRoles(PDO $pdo, int $employeeId, array $jobSubRoleIds): void
{
$jobSubRoleIds = validateJobSubRoles($pdo, $jobSubRoleIds);
$stmtDelete = $pdo->prepare("DELETE FROM employee_job_sub_roles WHERE employee_id = ?");
$stmtDelete->execute([$employeeId]);
if (!$jobSubRoleIds) {
return;
}
$stmtInsert = $pdo->prepare("
INSERT INTO employee_job_sub_roles
(employee_id, job_sub_role_id, is_primary, created_at)
VALUES
(?, ?, ?, NOW())
");
foreach ($jobSubRoleIds as $index => $jobSubRoleId) {
$stmtInsert->execute([$employeeId, $jobSubRoleId, $index === 0 ? 1 : 0]);
}
}
function getEmployeeSubRoleIds(PDO $pdo, int $employeeId): array
{
$stmt = $pdo->prepare("
SELECT job_sub_role_id
FROM employee_job_sub_roles
WHERE employee_id = ?
ORDER BY is_primary DESC, id ASC
");
$stmt->execute([$employeeId]);
return array_map('intval', $stmt->fetchAll(PDO::FETCH_COLUMN));
}
function jsonResponse(array $data): void
{
header('Content-Type: application/json; charset=utf-8');
echo json_encode($data);
exit;
}
function calculateExpiryDate(?int $validityMonths): ?string
{
if ($validityMonths === null || $validityMonths <= 0) {
return null;
}
return date('Y-m-d', strtotime('+' . $validityMonths . ' months'));
}
function getCurrentAuthUserId(): ?int
{
$candidateVariables = ['iduserlogin', 'idUserLogin', 'authUserId', 'userid', 'user_id'];
foreach ($candidateVariables as $variableName) {
if (isset($GLOBALS[$variableName]) && (int)$GLOBALS[$variableName] > 0) {
return (int)$GLOBALS[$variableName];
}
}
if (isset($_SESSION['auth_user_id']) && (int)$_SESSION['auth_user_id'] > 0) {
return (int)$_SESSION['auth_user_id'];
}
if (isset($_SESSION['user_id']) && (int)$_SESSION['user_id'] > 0) {
return (int)$_SESSION['user_id'];
}
return null;
}
function assignPpeToEmployee(
PDO $pdo,
int $employeeId,
array $ppeIds,
string $notes = '',
?string $assignedDate = null,
?string $deliveredBy = null,
?int $createdBy = null
): int {
$ppeIds = array_values(array_unique(array_filter(array_map('intval', $ppeIds))));
if (!$ppeIds) {
return 0;
}
$assignedDate = $assignedDate ?: date('Y-m-d');
$deliveredBy = trim((string)$deliveredBy) !== '' ? trim((string)$deliveredBy) : null;
$createdBy = $createdBy ?: getCurrentAuthUserId();
$stmtPpe = $pdo->prepare("SELECT id, validity_months FROM ppe_items WHERE id = ? AND is_active = 1 LIMIT 1");
$stmtExists = $pdo->prepare("
SELECT COUNT(*)
FROM employee_ppe_items
WHERE employee_id = ?
AND ppe_item_id = ?
AND status = 'assigned'
AND (expiry_date IS NULL OR expiry_date >= CURDATE())
");
$stmtInsert = $pdo->prepare("
INSERT INTO employee_ppe_items
(employee_id, ppe_item_id, assigned_date, expiry_date, delivered_by, quantity, status, notes, created_by, created_at, updated_at)
VALUES
(:employee_id, :ppe_item_id, :assigned_date, :expiry_date, :delivered_by, 1, 'assigned', :notes, :created_by, NOW(), NOW())
");
$inserted = 0;
foreach ($ppeIds as $ppeId) {
if ($ppeId <= 0) {
continue;
}
$stmtPpe->execute([$ppeId]);
$ppe = $stmtPpe->fetch(PDO::FETCH_ASSOC);
if (!$ppe) {
continue;
}
$stmtExists->execute([$employeeId, $ppeId]);
if ((int)$stmtExists->fetchColumn() > 0) {
continue;
}
$expiryDate = calculateExpiryDate(isset($ppe['validity_months']) ? (int)$ppe['validity_months'] : null);
$stmtInsert->execute([
'employee_id' => $employeeId,
'ppe_item_id' => $ppeId,
'assigned_date' => $assignedDate,
'expiry_date' => $expiryDate,
'delivered_by' => $deliveredBy,
'notes' => $notes !== '' ? $notes : null,
'created_by' => $createdBy,
]);
$inserted++;
}
return $inserted;
}
/* ==========================================
AJAX HANDLERS
========================================== */
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['ajax'] == '1') {
$action = $_POST['action'] ?? '';
try {
if ($action === 'add') {
$employee_code = trim($_POST['employee_code'] ?? '');
$first_name = trim($_POST['first_name'] ?? '');
$last_name = trim($_POST['last_name'] ?? '');
$address = trim($_POST['address'] ?? '');
$phone = trim($_POST['phone'] ?? '');
$email = trim($_POST['email'] ?? '');
$department_id = normalizeNullableInt($_POST['department_id'] ?? '');
$job_sub_role_ids = validateJobSubRoles($pdo, $_POST['job_sub_role_ids'] ?? []);
[$job_role_id, $job_sub_role_id] = getPrimaryJobRoleAndSubRole($pdo, $job_sub_role_ids);
$hire_date = trim($_POST['hire_date'] ?? '');
$status = trim($_POST['status'] ?? 'active');
$auth_user_id = normalizeNullableInt($_POST['auth_user_id'] ?? '');
$role_id = normalizeNullableInt($_POST['role_id'] ?? '');
if ($first_name === '' || $last_name === '') {
jsonResponse(['success' => false, 'message' => 'First name and Last name are required.']);
}
if ($email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
jsonResponse(['success' => false, 'message' => 'Email non valida.']);
}
if (!in_array($status, ['active', 'inactive', 'suspended'], true)) {
$status = 'active';
}
$sql = "INSERT INTO employees
(auth_user_id, employee_code, first_name, last_name, address, phone, email,
department_id, job_role_id, job_sub_role_id, hire_date, status, created_at, updated_at)
VALUES
(:auth_user_id, :employee_code, :first_name, :last_name, :address, :phone, :email,
:department_id, :job_role_id, :job_sub_role_id, :hire_date, :status, NOW(), NOW())";
$stmt = $pdo->prepare($sql);
$stmt->execute([
'auth_user_id' => $auth_user_id,
'employee_code' => $employee_code !== '' ? $employee_code : null,
'first_name' => $first_name,
'last_name' => $last_name,
'address' => $address !== '' ? $address : null,
'phone' => $phone !== '' ? $phone : null,
'email' => $email !== '' ? $email : null,
'department_id' => $department_id,
'job_role_id' => $job_role_id,
'job_sub_role_id' => $job_sub_role_id,
'hire_date' => $hire_date !== '' ? $hire_date : null,
'status' => $status,
]);
$employeeId = (int)$pdo->lastInsertId();
saveEmployeeSubRoles($pdo, $employeeId, $job_sub_role_ids);
if ($auth_user_id !== null && $role_id !== null) {
$checkRole = $pdo->prepare("SELECT COUNT(*) FROM auth_roles WHERE id = ?");
$checkRole->execute([$role_id]);
if ((int)$checkRole->fetchColumn() > 0) {
$stmtRole = $pdo->prepare("UPDATE auth_users SET role_id = :role_id, updated_at = NOW() WHERE id = :auth_user_id");
$stmtRole->execute([
'role_id' => $role_id,
'auth_user_id' => $auth_user_id,
]);
}
}
jsonResponse(['success' => true]);
}
if ($action === 'edit') {
$id = (int)($_POST['id'] ?? 0);
$employee_code = trim($_POST['employee_code'] ?? '');
$first_name = trim($_POST['first_name'] ?? '');
$last_name = trim($_POST['last_name'] ?? '');
$address = trim($_POST['address'] ?? '');
$phone = trim($_POST['phone'] ?? '');
$email = trim($_POST['email'] ?? '');
$department_id = normalizeNullableInt($_POST['department_id'] ?? '');
$job_sub_role_ids = validateJobSubRoles($pdo, $_POST['job_sub_role_ids'] ?? []);
[$job_role_id, $job_sub_role_id] = getPrimaryJobRoleAndSubRole($pdo, $job_sub_role_ids);
$hire_date = trim($_POST['hire_date'] ?? '');
$status = trim($_POST['status'] ?? 'active');
$auth_user_id = normalizeNullableInt($_POST['auth_user_id'] ?? '');
$role_id = normalizeNullableInt($_POST['role_id'] ?? '');
if ($id <= 0) {
jsonResponse(['success' => false, 'message' => 'Invalid employee ID.']);
}
if ($first_name === '' || $last_name === '') {
jsonResponse(['success' => false, 'message' => 'First name and Last name are required.']);
}
if ($email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
jsonResponse(['success' => false, 'message' => 'Email non valida.']);
}
if (!in_array($status, ['active', 'inactive', 'suspended'], true)) {
$status = 'active';
}
$sql = "UPDATE employees
SET auth_user_id = :auth_user_id,
employee_code = :employee_code,
first_name = :first_name,
last_name = :last_name,
address = :address,
phone = :phone,
email = :email,
department_id = :department_id,
job_role_id = :job_role_id,
job_sub_role_id = :job_sub_role_id,
hire_date = :hire_date,
status = :status,
updated_at = NOW()
WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute([
'auth_user_id' => $auth_user_id,
'employee_code' => $employee_code !== '' ? $employee_code : null,
'first_name' => $first_name,
'last_name' => $last_name,
'address' => $address !== '' ? $address : null,
'phone' => $phone !== '' ? $phone : null,
'email' => $email !== '' ? $email : null,
'department_id' => $department_id,
'job_role_id' => $job_role_id,
'job_sub_role_id' => $job_sub_role_id,
'hire_date' => $hire_date !== '' ? $hire_date : null,
'status' => $status,
'id' => $id,
]);
saveEmployeeSubRoles($pdo, $id, $job_sub_role_ids);
if ($auth_user_id !== null && $role_id !== null) {
$checkRole = $pdo->prepare("SELECT COUNT(*) FROM auth_roles WHERE id = ?");
$checkRole->execute([$role_id]);
if ((int)$checkRole->fetchColumn() > 0) {
$stmtRole = $pdo->prepare("UPDATE auth_users SET role_id = :role_id, updated_at = NOW() WHERE id = :auth_user_id");
$stmtRole->execute([
'role_id' => $role_id,
'auth_user_id' => $auth_user_id,
]);
}
}
jsonResponse(['success' => true]);
}
if ($action === 'delete') {
$id = (int)($_POST['id'] ?? 0);
if ($id <= 0) {
jsonResponse(['success' => false, 'message' => 'Invalid employee ID.']);
}
$stmt = $pdo->prepare("DELETE FROM employees WHERE id = :id");
$stmt->execute(['id' => $id]);
jsonResponse(['success' => true]);
}
if ($action === 'get_employee_skills') {
$id = (int)$_POST['id'];
if ($id <= 0) {
jsonResponse(['success' => false, 'message' => 'Invalid ID']);
}
$stmt = $pdo->prepare("SELECT skill_id, level FROM employee_skills WHERE employee_id = ?");
$stmt->execute([$id]);
$skills = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$skills[$row['skill_id']] = $row['level'];
}
jsonResponse(['success' => true, 'skills' => $skills]);
}
if ($action === 'save_employee_skills') {
$id = (int)$_POST['id'];
$skills_json = $_POST['skills'] ?? '';
$skills = json_decode($skills_json, true);
if ($id <= 0 || !is_array($skills)) {
jsonResponse(['success' => false, 'message' => 'Invalid data']);
}
$pdo->beginTransaction();
$stmtDelete = $pdo->prepare("DELETE FROM employee_skills WHERE employee_id = ?");
$stmtDelete->execute([$id]);
$stmtInsert = $pdo->prepare("INSERT INTO employee_skills (employee_id, skill_id, level) VALUES (?, ?, ?)");
foreach ($skills as $skill_id => $level) {
$stmtInsert->execute([$id, (int)$skill_id, $level]);
}
$pdo->commit();
jsonResponse(['success' => true]);
}
if ($action === 'get_employee_ppe') {
$id = (int)($_POST['id'] ?? 0);
if ($id <= 0) {
jsonResponse(['success' => false, 'message' => 'Invalid employee ID.']);
}
$stmtEmp = $pdo->prepare("
SELECT
e.id,
e.first_name,
e.last_name,
COALESCE(ejm.job_sub_role_ids, IF(e.job_sub_role_id IS NULL, '', CAST(e.job_sub_role_id AS CHAR))) AS job_sub_role_ids,
COALESCE(ejm.job_sub_role_names, jsr.name) AS job_sub_role_name
FROM employees e
LEFT JOIN (
SELECT
ejs.employee_id,
GROUP_CONCAT(DISTINCT jsr2.id ORDER BY jr2.name, jsr2.name SEPARATOR ',') AS job_sub_role_ids,
GROUP_CONCAT(DISTINCT jsr2.name ORDER BY jr2.name, jsr2.name SEPARATOR ', ') AS job_sub_role_names
FROM employee_job_sub_roles ejs
INNER JOIN job_sub_roles jsr2 ON jsr2.id = ejs.job_sub_role_id
INNER JOIN job_roles jr2 ON jr2.id = jsr2.job_role_id
GROUP BY ejs.employee_id
) ejm ON ejm.employee_id = e.id
LEFT JOIN job_sub_roles jsr ON jsr.id = e.job_sub_role_id
WHERE e.id = ?
LIMIT 1
");
$stmtEmp->execute([$id]);
$employee = $stmtEmp->fetch(PDO::FETCH_ASSOC);
if (!$employee) {
jsonResponse(['success' => false, 'message' => 'Dipendente non trovato.']);
}
$jobSubRoleIds = [];
if (!empty($employee['job_sub_role_ids'])) {
$jobSubRoleIds = array_values(array_unique(array_filter(array_map('intval', explode(',', $employee['job_sub_role_ids'])))));
}
$requiredPpe = [];
if ($jobSubRoleIds) {
$placeholders = implode(',', array_fill(0, count($jobSubRoleIds), '?'));
$stmtReq = $pdo->prepare("
SELECT
p.id AS ppe_item_id,
p.name AS ppe_name,
p.category,
p.photo,
p.standard_reference,
p.validity_months,
GROUP_CONCAT(DISTINCT jsr.name ORDER BY jsr.name SEPARATOR ', ') AS required_by_subroles
FROM job_sub_role_ppe_items jsp
INNER JOIN job_sub_roles jsr ON jsr.id = jsp.job_sub_role_id
INNER JOIN ppe_items p ON p.id = jsp.ppe_item_id
WHERE jsp.job_sub_role_id IN ($placeholders)
AND jsp.is_active = 1
AND p.is_active = 1
GROUP BY p.id, p.name, p.category, p.photo, p.standard_reference, p.validity_months
ORDER BY p.category ASC, p.name ASC
");
$stmtReq->execute($jobSubRoleIds);
$requiredPpe = $stmtReq->fetchAll(PDO::FETCH_ASSOC);
}
$stmtAssigned = $pdo->prepare("
SELECT
epi.id AS assignment_id,
epi.ppe_item_id,
epi.assigned_date,
epi.expiry_date,
epi.delivered_by,
epi.quantity,
epi.status,
epi.notes,
p.name AS ppe_name,
p.category,
p.photo,
p.standard_reference
FROM employee_ppe_items epi
INNER JOIN ppe_items p ON p.id = epi.ppe_item_id
WHERE epi.employee_id = ?
ORDER BY FIELD(epi.status, 'assigned', 'expired', 'damaged', 'lost', 'returned'), p.name ASC
");
$stmtAssigned->execute([$id]);
$assignedPpe = $stmtAssigned->fetchAll(PDO::FETCH_ASSOC);
$assignedActiveMap = [];
foreach ($assignedPpe as $a) {
$isActiveAssignment = ($a['status'] === 'assigned') && (empty($a['expiry_date']) || $a['expiry_date'] >= date('Y-m-d'));
if ($isActiveAssignment) {
$assignedActiveMap[(int)$a['ppe_item_id']] = $a;
}
}
$requiredStatus = [];
foreach ($requiredPpe as $r) {
$ppeId = (int)$r['ppe_item_id'];
$assignedRow = $assignedActiveMap[$ppeId] ?? null;
$requiredStatus[] = [
'ppe_item_id' => $ppeId,
'ppe_name' => $r['ppe_name'],
'category' => $r['category'],
'standard_reference' => $r['standard_reference'],
'validity_months' => $r['validity_months'],
'required_by_subroles' => $r['required_by_subroles'] ?? '',
'is_assigned' => $assignedRow !== null,
'assignment' => $assignedRow,
];
}
jsonResponse([
'success' => true,
'employee' => $employee,
'required_ppe' => $requiredStatus,
'assigned_ppe' => $assignedPpe,
]);
}
if ($action === 'assign_missing_employee_ppe') {
$id = (int)($_POST['id'] ?? 0);
$selectedPpeIds = $_POST['ppe_ids'] ?? [];
if ($id <= 0) {
jsonResponse(['success' => false, 'message' => 'Invalid employee ID.']);
}
$stmtEmp = $pdo->prepare("SELECT id FROM employees WHERE id = ? LIMIT 1");
$stmtEmp->execute([$id]);
$employee = $stmtEmp->fetch(PDO::FETCH_ASSOC);
if (!$employee) {
jsonResponse(['success' => false, 'message' => 'Dipendente non trovato.']);
}
$jobSubRoleIds = getEmployeeSubRoleIds($pdo, $id);
if (!$jobSubRoleIds) {
$stmtLegacy = $pdo->prepare("SELECT job_sub_role_id FROM employees WHERE id = ? AND job_sub_role_id IS NOT NULL LIMIT 1");
$stmtLegacy->execute([$id]);
$legacySubRoleId = $stmtLegacy->fetchColumn();
if ($legacySubRoleId) {
$jobSubRoleIds = [(int)$legacySubRoleId];
}
}
if (!$jobSubRoleIds) {
jsonResponse(['success' => false, 'message' => 'Il dipendente non ha sottomansioni collegate.']);
}
$placeholders = implode(',', array_fill(0, count($jobSubRoleIds), '?'));
$stmtReq = $pdo->prepare("
SELECT DISTINCT p.id
FROM job_sub_role_ppe_items jsp
INNER JOIN ppe_items p ON p.id = jsp.ppe_item_id
WHERE jsp.job_sub_role_id IN ($placeholders)
AND jsp.is_active = 1
AND p.is_active = 1
");
$stmtReq->execute($jobSubRoleIds);
$requiredIds = array_map('intval', $stmtReq->fetchAll(PDO::FETCH_COLUMN));
if (!$selectedPpeIds) {
$selectedPpeIds = $requiredIds;
} else {
$selectedPpeIds = array_values(array_intersect(array_map('intval', $selectedPpeIds), $requiredIds));
}
$assignedDate = trim($_POST['assigned_date'] ?? '') ?: date('Y-m-d');
$deliveredBy = trim($_POST['delivered_by'] ?? '');
$notes = trim($_POST['notes'] ?? '');
$inserted = assignPpeToEmployee(
$pdo,
$id,
$selectedPpeIds,
$notes !== '' ? $notes : 'Assegnato automaticamente dalle sottomansioni.',
$assignedDate,
$deliveredBy
);
jsonResponse(['success' => true, 'message' => 'DPI obbligatori assegnati: ' . $inserted]);
}
if ($action === 'assign_employee_ppe') {
$id = (int)($_POST['id'] ?? 0);
$ppeIds = $_POST['ppe_ids'] ?? [];
$assignedDate = trim($_POST['assigned_date'] ?? '') ?: date('Y-m-d');
$deliveredBy = trim($_POST['delivered_by'] ?? '');
$notes = trim($_POST['notes'] ?? '');
if ($id <= 0) {
jsonResponse(['success' => false, 'message' => 'Invalid employee ID.']);
}
$stmtEmp = $pdo->prepare("SELECT id FROM employees WHERE id = ? LIMIT 1");
$stmtEmp->execute([$id]);
if (!$stmtEmp->fetchColumn()) {
jsonResponse(['success' => false, 'message' => 'Dipendente non trovato.']);
}
$inserted = assignPpeToEmployee(
$pdo,
$id,
$ppeIds,
$notes !== '' ? $notes : 'Assegnato manualmente.',
$assignedDate,
$deliveredBy
);
jsonResponse(['success' => true, 'message' => 'DPI assegnati: ' . $inserted]);
}
if ($action === 'remove_employee_ppe') {
$assignmentId = (int)($_POST['assignment_id'] ?? 0);
$employeeId = (int)($_POST['employee_id'] ?? 0);
if ($assignmentId <= 0 || $employeeId <= 0) {
jsonResponse(['success' => false, 'message' => 'Dati DPI non validi.']);
}
$stmt = $pdo->prepare("
UPDATE employee_ppe_items
SET status = 'returned',
updated_at = NOW()
WHERE id = ?
AND employee_id = ?
AND status = 'assigned'
");
$stmt->execute([$assignmentId, $employeeId]);
jsonResponse(['success' => true, 'message' => 'DPI rimosso dal dipendente.']);
}
if ($action === 'assign_bulk_employee_ppe') {
$employeeIds = $_POST['employee_ids'] ?? [];
$ppeIds = $_POST['ppe_ids'] ?? [];
$assignedDate = trim($_POST['assigned_date'] ?? '') ?: date('Y-m-d');
$deliveredBy = trim($_POST['delivered_by'] ?? '');
$notes = trim($_POST['notes'] ?? '');
$employeeIds = array_values(array_unique(array_filter(array_map('intval', $employeeIds))));
if (!$employeeIds || !$ppeIds) {
jsonResponse(['success' => false, 'message' => 'Seleziona almeno un dipendente e almeno un DPI.']);
}
$totalInserted = 0;
foreach ($employeeIds as $employeeId) {
$totalInserted += assignPpeToEmployee(
$pdo,
$employeeId,
$ppeIds,
$notes !== '' ? $notes : 'Assegnazione DPI multipla.',
$assignedDate,
$deliveredBy
);
}
jsonResponse(['success' => true, 'message' => 'Assegnazioni DPI create: ' . $totalInserted]);
}
jsonResponse(['success' => false, 'message' => 'Unknown action.']);
} catch (Exception $e) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
jsonResponse(['success' => false, 'message' => $e->getMessage()]);
}
}
/* ==========================================
PAGE DATA
========================================== */
$sql = "
SELECT e.*,
d.name AS department_name,
d.color AS department_color,
COALESCE(ejm.job_role_names, jr.name) AS job_role_name,
COALESCE(ejm.job_sub_role_names, jsr.name) AS job_sub_role_name,
COALESCE(ejm.job_sub_role_ids, IF(e.job_sub_role_id IS NULL, '', CAST(e.job_sub_role_id AS CHAR))) AS job_sub_role_ids,
au.email AS user_email,
au.role_id AS user_role_id,
ar.display_name AS role_display_name,
ar.name AS role_name,
CONCAT(COALESCE(au.first_name, ''), ' ', COALESCE(au.last_name, '')) AS user_fullname
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id
LEFT JOIN (
SELECT
ejs.employee_id,
GROUP_CONCAT(DISTINCT jr2.name ORDER BY jr2.name SEPARATOR ', ') AS job_role_names,
GROUP_CONCAT(DISTINCT jsr2.name ORDER BY jr2.name, jsr2.name SEPARATOR ', ') AS job_sub_role_names,
GROUP_CONCAT(DISTINCT jsr2.id ORDER BY jr2.name, jsr2.name SEPARATOR ',') AS job_sub_role_ids
FROM employee_job_sub_roles ejs
INNER JOIN job_sub_roles jsr2 ON jsr2.id = ejs.job_sub_role_id
INNER JOIN job_roles jr2 ON jr2.id = jsr2.job_role_id
GROUP BY ejs.employee_id
) ejm ON ejm.employee_id = e.id
LEFT JOIN job_roles jr ON jr.id = e.job_role_id
LEFT JOIN job_sub_roles jsr ON jsr.id = e.job_sub_role_id
LEFT JOIN auth_users au ON e.auth_user_id = au.id
LEFT JOIN auth_roles ar ON ar.id = au.role_id
ORDER BY e.id DESC
";
$stmtEmployees = $pdo->query($sql);
$employees = $stmtEmployees->fetchAll(PDO::FETCH_ASSOC);
$employeesForSelect = $pdo->query("
SELECT id, first_name, last_name, employee_code, department_id
FROM employees
ORDER BY last_name, first_name
")->fetchAll(PDO::FETCH_ASSOC);
$jobRoles = $pdo->query("
SELECT id, name FROM job_roles WHERE is_active = 1 ORDER BY sort_order, name
")->fetchAll(PDO::FETCH_ASSOC);
$jobSubRoles = $pdo->query("
SELECT jsr.id, jsr.job_role_id, jsr.name, jr.name AS job_role_name
FROM job_sub_roles jsr
INNER JOIN job_roles jr ON jr.id = jsr.job_role_id
WHERE jsr.is_active = 1
AND jr.is_active = 1
ORDER BY jr.sort_order ASC, jr.name ASC, jsr.sort_order ASC, jsr.name ASC
")->fetchAll(PDO::FETCH_ASSOC);
$jobSubRolesByRole = [];
foreach ($jobSubRoles as $subRole) {
$jobSubRolesByRole[(int)$subRole['job_role_id']][] = [
'id' => (int)$subRole['id'],
'name' => $subRole['name'],
'job_role_name' => $subRole['job_role_name'],
];
}
$ppeItems = $pdo->query("
SELECT id, name, category, standard_reference
FROM ppe_items
WHERE is_active = 1
ORDER BY category ASC, name ASC
")->fetchAll(PDO::FETCH_ASSOC);
$sqlUsers = "
SELECT id,
role_id,
CONCAT(
COALESCE(first_name, ''),
' ',
COALESCE(last_name, ''),
' (',
email,
')'
) AS label
FROM auth_users
ORDER BY first_name, last_name, email
";
$users = $pdo->query($sqlUsers)->fetchAll(PDO::FETCH_ASSOC);
$sqlRoles = "
SELECT id, name, display_name
FROM auth_roles
ORDER BY display_name, name
";
$authRoles = $pdo->query($sqlRoles)->fetchAll(PDO::FETCH_ASSOC);
$sqlDepartments = "
SELECT id, name, code, color
FROM departments
WHERE is_active = 1
ORDER BY sort_order ASC, name ASC
";
$departments = $pdo->query($sqlDepartments)->fetchAll(PDO::FETCH_ASSOC);
$sqlSkills = "
SELECT s.id, s.name, pl.name as line_name, pl.line_number
FROM skills s
LEFT JOIN production_lines pl ON s.production_line_id = pl.id
ORDER BY IFNULL(pl.line_number, 999), s.name
";
$allSkills = $pdo->query($sqlSkills)->fetchAll(PDO::FETCH_ASSOC);
?>
Gestione Dipendenti - = htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?>
Elenco Completo
| Codice |
Nome |
Contatti |
Reparto |
Mansioni / Sottomansioni |
Data Assunzione |
Stato |
Azioni |
| = htmlspecialchars($row['employee_code'] ?? '') ?> |
= htmlspecialchars($fullName) ?>
|
✉️ = htmlspecialchars($row['email']) ?>
📞 = htmlspecialchars($row['phone']) ?>
-
|
= htmlspecialchars($row['department_name']) ?>
-
|
= !empty($row['job_role_name']) ? htmlspecialchars($row['job_role_name']) : '-' ?>
= !empty($row['job_sub_role_name']) ? htmlspecialchars($row['job_sub_role_name']) : 'Nessuna sottomansione' ?>
|
= $hireDate ?> |
= htmlspecialchars($statusLabel) ?>
|
|