123 lines
4.9 KiB
PHP
123 lines
4.9 KiB
PHP
<?php
|
|
|
|
require_once __DIR__ . '/auth_check.php';
|
|
|
|
/**
|
|
* Cumulative calendar feed: deadlines + trainings + maintenances.
|
|
* Each layer is returned only if the user may see that module, and only
|
|
* if the layer is requested via ?layers=deadlines,trainings,maintenances
|
|
*/
|
|
try {
|
|
$pdo = mnt_pdo();
|
|
|
|
$start = substr((string)($_GET['start'] ?? date('Y-m-01', strtotime('-6 months'))), 0, 10);
|
|
$end = substr((string)($_GET['end'] ?? date('Y-m-t', strtotime('+12 months'))), 0, 10);
|
|
|
|
$requested = array_filter(explode(',', (string)($_GET['layers'] ?? 'deadlines,trainings,maintenances')));
|
|
$wants = fn(string $layer): bool => in_array($layer, $requested, true);
|
|
|
|
$events = [];
|
|
|
|
// ---- Maintenances --------------------------------------------------
|
|
if ($wants('maintenances') && mnt_user_can('maintenance.calendar.view')) {
|
|
$stmt = $pdo->prepare("
|
|
SELECT m.id, m.title, m.code, m.next_due_date, m.alert_days, m.is_critical,
|
|
e.id AS equipment_id, e.name AS equipment_name
|
|
FROM maint_maintenances m
|
|
INNER JOIN inv_equipment e ON e.id = m.equipment_id
|
|
WHERE m.is_active = 1
|
|
AND e.status = 'active'
|
|
AND m.next_due_date BETWEEN ? AND ?
|
|
");
|
|
$stmt->execute([$start, $end]);
|
|
|
|
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
|
|
$state = mnt_due_state($row['next_due_date'], (int)$row['alert_days']);
|
|
$color = $state === 'overdue' ? '#dc3545' : '#2f7d8f';
|
|
|
|
$events[] = [
|
|
'id' => 'maint-' . $row['id'],
|
|
'title' => '🔧 ' . $row['equipment_name'] . ': ' . $row['title'],
|
|
'start' => $row['next_due_date'],
|
|
'allDay' => true,
|
|
'backgroundColor' => $color,
|
|
'borderColor' => $color,
|
|
'extendedProps' => [
|
|
'layer' => 'maintenances',
|
|
'url' => 'manutenzioni/equipment.php?id=' . (int)$row['equipment_id'],
|
|
'state' => $state,
|
|
],
|
|
];
|
|
}
|
|
}
|
|
|
|
// ---- Deadlines (scadenzario) --------------------------------------
|
|
if ($wants('deadlines') && mnt_user_can('deadlines.view')) {
|
|
$stmt = $pdo->prepare("
|
|
SELECT d.id, d.topic, d.due_date, d.status, d.notification_days, s.name AS subject_name
|
|
FROM scad_deadlines d
|
|
LEFT JOIN scad_subjects s ON s.id = d.subject_id
|
|
WHERE d.due_date BETWEEN ? AND ?
|
|
");
|
|
$stmt->execute([$start, $end]);
|
|
|
|
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
|
|
$isCompleted = $row['status'] === 'completed';
|
|
$state = $isCompleted ? 'ok' : mnt_due_state($row['due_date'], (int)$row['notification_days']);
|
|
$color = $isCompleted ? '#6c757d' : ($state === 'overdue' ? '#b02a37' : '#6f42c1');
|
|
|
|
$events[] = [
|
|
'id' => 'scad-' . $row['id'],
|
|
'title' => '📅 ' . $row['topic'],
|
|
'start' => $row['due_date'],
|
|
'allDay' => true,
|
|
'backgroundColor' => $color,
|
|
'borderColor' => $color,
|
|
'extendedProps' => [
|
|
'layer' => 'deadlines',
|
|
'url' => 'scadenzario/detail.php?id=' . (int)$row['id'],
|
|
'state' => $state,
|
|
],
|
|
];
|
|
}
|
|
}
|
|
|
|
// ---- Trainings (formazione) ---------------------------------------
|
|
if ($wants('trainings') && mnt_user_can('hr.trainings.view')) {
|
|
$stmt = $pdo->prepare("
|
|
SELECT t.id, t.next_due_date, t.reminder_days,
|
|
tt.name AS topic_name,
|
|
CONCAT(e.first_name, ' ', e.last_name) AS employee_name
|
|
FROM employee_trainings t
|
|
INNER JOIN training_topics tt ON tt.id = t.training_topic_id
|
|
INNER JOIN employees e ON e.id = t.employee_id
|
|
WHERE t.next_due_date IS NOT NULL AND t.next_due_date BETWEEN ? AND ?
|
|
");
|
|
$stmt->execute([$start, $end]);
|
|
|
|
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
|
|
$state = mnt_due_state($row['next_due_date'], (int)($row['reminder_days'] ?? 0));
|
|
$color = $state === 'overdue' ? '#a94442' : '#198754';
|
|
|
|
$events[] = [
|
|
'id' => 'train-' . $row['id'],
|
|
'title' => '🎓 ' . $row['topic_name'] . ' — ' . $row['employee_name'],
|
|
'start' => $row['next_due_date'],
|
|
'allDay' => true,
|
|
'backgroundColor' => $color,
|
|
'borderColor' => $color,
|
|
'extendedProps' => [
|
|
'layer' => 'trainings',
|
|
'url' => 'trainings.php',
|
|
'state' => $state,
|
|
],
|
|
];
|
|
}
|
|
}
|
|
|
|
echo json_encode($events);
|
|
} catch (Throwable $e) {
|
|
http_response_code(500);
|
|
echo json_encode(['error' => $e->getMessage()]);
|
|
}
|