203 lines
10 KiB
PHP
203 lines
10 KiB
PHP
<?php include('../include/headscript.php'); ?>
|
|
<?php
|
|
$db = DBHandlerSelect::getInstance();
|
|
$pdo = $db->getConnection();
|
|
|
|
$sql = "
|
|
SELECT d.*,
|
|
s.name AS subject_name,
|
|
s.color AS subject_color,
|
|
GROUP_CONCAT(DISTINCT CONCAT(e.first_name, ' ', e.last_name) ORDER BY e.first_name SEPARATOR ', ') as responsabili,
|
|
GROUP_CONCAT(DISTINCT e.department ORDER BY e.department SEPARATOR ', ') as reparti_persone,
|
|
d.departments as reparti_assegnati
|
|
FROM scad_deadlines d
|
|
LEFT JOIN scad_subjects s ON s.id = d.subject_id
|
|
LEFT JOIN scad_deadline_employee de ON de.deadline_id = d.id
|
|
LEFT JOIN employees e ON e.id = de.employee_id
|
|
";
|
|
|
|
$where = [];
|
|
$params = [];
|
|
|
|
$filterStatus = $_GET['status'] ?? '';
|
|
$filterDept = $_GET['department'] ?? '';
|
|
$filterEmployee = $_GET['employee'] ?? '';
|
|
|
|
if ($filterStatus === 'non-completata') {
|
|
$where[] = "d.status != 'completed'";
|
|
} elseif ($filterStatus === 'completata') {
|
|
$where[] = "d.status = 'completed'";
|
|
} elseif ($filterStatus === 'scaduta') {
|
|
$where[] = "d.status = 'active' AND d.due_date < CURDATE()";
|
|
} elseif ($filterStatus === 'in-scadenza') {
|
|
$where[] = "d.status = 'active' AND d.due_date >= CURDATE() AND d.due_date <= DATE_ADD(CURDATE(), INTERVAL d.notification_days DAY)";
|
|
} elseif ($filterStatus === 'attiva') {
|
|
$where[] = "d.status = 'active' AND d.due_date > DATE_ADD(CURDATE(), INTERVAL d.notification_days DAY)";
|
|
}
|
|
|
|
if ($filterEmployee) {
|
|
$where[] = "EXISTS (SELECT 1 FROM scad_deadline_employee de2 JOIN employees e2 ON e2.id = de2.employee_id WHERE de2.deadline_id = d.id AND CONCAT(e2.first_name, ' ', e2.last_name) = ?)";
|
|
$params[] = $filterEmployee;
|
|
}
|
|
|
|
$dueFrom = $_GET['due_from'] ?? '';
|
|
$dueTo = $_GET['due_to'] ?? '';
|
|
$checkFrom = $_GET['check_from'] ?? '';
|
|
$checkTo = $_GET['check_to'] ?? '';
|
|
|
|
if ($dueFrom) { $where[] = "d.due_date >= ?"; $params[] = $dueFrom; }
|
|
if ($dueTo) { $where[] = "d.due_date <= ?"; $params[] = $dueTo; }
|
|
if ($checkFrom) { $where[] = "d.check_date >= ?"; $params[] = $checkFrom; }
|
|
if ($checkTo) { $where[] = "d.check_date <= ?"; $params[] = $checkTo; }
|
|
|
|
if (!empty($where)) {
|
|
$sql .= " WHERE " . implode(' AND ', $where);
|
|
}
|
|
|
|
$sql .= " GROUP BY d.id ORDER BY (d.status = 'completed') ASC, d.due_date ASC";
|
|
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute($params);
|
|
$deadlines = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
$today = date('Y-m-d');
|
|
$recurrenceLabels = ['once'=>'Una tantum','monthly'=>'Mensile','quarterly'=>'Trimestrale','semiannual'=>'Semestrale','annual'=>'Annuale','biennial'=>'Biennale','triennial'=>'Triennale','quadriennial'=>'Quadriennale','quinquennial'=>'Quinquennale','decennial'=>'Decennale','quindecennial'=>'Quindicennale'];
|
|
|
|
$filterLabel = '';
|
|
if ($filterStatus) {
|
|
$statusLabels = ['non-completata'=>'Non completate','attiva'=>'Attive','in-scadenza'=>'In scadenza','scaduta'=>'Scadute','completata'=>'Completate'];
|
|
$filterLabel = $statusLabels[$filterStatus] ?? '';
|
|
}
|
|
if ($filterDept) {
|
|
$filterLabel .= ($filterLabel ? ' — ' : '') . 'Reparto: ' . $filterDept;
|
|
}
|
|
if ($filterEmployee) {
|
|
$filterLabel .= ($filterLabel ? ' — ' : '') . 'Responsabile: ' . $filterEmployee;
|
|
}
|
|
if ($dueFrom || $dueTo) {
|
|
$filterLabel .= ($filterLabel ? ' — ' : '') . 'Scadenza: ' . ($dueFrom ? date('d/m/Y', strtotime($dueFrom)) : '...') . ' → ' . ($dueTo ? date('d/m/Y', strtotime($dueTo)) : '...');
|
|
}
|
|
if ($checkFrom || $checkTo) {
|
|
$filterLabel .= ($filterLabel ? ' — ' : '') . 'Controllo: ' . ($checkFrom ? date('d/m/Y', strtotime($checkFrom)) : '...') . ' → ' . ($checkTo ? date('d/m/Y', strtotime($checkTo)) : '...');
|
|
}
|
|
?>
|
|
<!doctype html>
|
|
<html lang="it">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Stampa Scadenzario</title>
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; font-size: 11px; color: #222; background: #fff; }
|
|
.print-header { padding: 20px 20px 10px; border-bottom: 2px solid #2c3e6b; margin-bottom: 10px; }
|
|
.print-header h1 { font-size: 18px; color: #2c3e6b; margin: 0; }
|
|
.print-header .print-meta { font-size: 10px; color: #666; margin-top: 4px; }
|
|
.print-actions { padding: 10px 20px; display: flex; gap: 10px; }
|
|
.print-actions button { padding: 8px 20px; font-size: 13px; font-weight: 600; border-radius: 6px; cursor: pointer; border: none; }
|
|
.btn-print { background: #5a8fd8; color: #fff; }
|
|
.btn-back { background: #f0f0f0; color: #333; }
|
|
table { width: 100%; border-collapse: collapse; margin: 0 20px; }
|
|
table { width: calc(100% - 40px); }
|
|
th { background: #2c3e6b; color: #fff; font-weight: 600; font-size: 10px; text-transform: uppercase; letter-spacing: 0.03em; padding: 6px 8px; text-align: left; white-space: nowrap; }
|
|
td { padding: 5px 8px; border-bottom: 1px solid #e0e0e0; vertical-align: top; font-size: 10.5px; line-height: 1.4; }
|
|
tr:nth-child(even) { background: #f9fafb; }
|
|
tr.row-overdue { background: #fff5f5; }
|
|
tr.row-overdue td { color: #991b1b; }
|
|
tr.row-approaching { background: #fffbeb; }
|
|
tr.row-completed { opacity: 0.5; }
|
|
.status-badge { font-size: 9px; font-weight: 700; padding: 2px 6px; border-radius: 10px; white-space: nowrap; }
|
|
.st-attiva { background: #e8eeff; color: #3a6bb5; }
|
|
.st-scaduta { background: #fde8e8; color: #b91c1c; }
|
|
.st-in-scadenza { background: #fef3cd; color: #92600a; }
|
|
.st-completata { background: #d1f2e0; color: #0f5132; }
|
|
.print-footer { padding: 10px 20px; font-size: 9px; color: #999; border-top: 1px solid #e0e0e0; margin-top: 10px; text-align: right; }
|
|
@media print {
|
|
.print-actions { display: none; }
|
|
body { font-size: 9px; }
|
|
th { font-size: 8.5px; padding: 4px 6px; }
|
|
td { font-size: 9px; padding: 3px 6px; }
|
|
@page { size: landscape; margin: 0.8cm; }
|
|
}
|
|
@media screen {
|
|
table { margin: 0 auto; width: calc(100% - 40px); }
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="print-header">
|
|
<h1>ELENCO PRESCRIZIONI LEGALI ED ALTRE PRESCRIZIONI APPLICABILI<br>SICUREZZA ED AMBIENTE CON VERIFICA DEL RISPETTO DELLE STESSE</h1>
|
|
<div class="print-meta">
|
|
Stampato il <?= date('d/m/Y H:i') ?>
|
|
<?php if ($filterLabel): ?> — Filtro: <?= htmlspecialchars($filterLabel, ENT_QUOTES, 'UTF-8') ?><?php endif; ?>
|
|
— Totale: <?= count($deadlines) ?> scadenze
|
|
</div>
|
|
</div>
|
|
|
|
<div class="print-actions">
|
|
<button class="btn-print" onclick="window.print()"><i class="fa-solid fa-print"></i> Stampa</button>
|
|
<button class="btn-back" onclick="window.close()">Chiudi</button>
|
|
</div>
|
|
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Argomento</th>
|
|
<th>Legge / Art.</th>
|
|
<th>Dettaglio</th>
|
|
<th>Periodicità Scadenza</th>
|
|
<th>Data Documento</th>
|
|
<th>Data Scadenza</th>
|
|
<th>Data Ultimo Controllo</th>
|
|
<th>Responsabilità</th>
|
|
<th>Luogo di Archiviazione</th>
|
|
<th>Note</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($deadlines as $row):
|
|
$dueDate = $row['due_date'];
|
|
$nDays = (int)$row['notification_days'];
|
|
$approachDate = date('Y-m-d', strtotime($today . ' + ' . $nDays . ' days'));
|
|
$isCompleted = $row['status'] === 'completed';
|
|
$isOverdue = !$isCompleted && $dueDate < $today;
|
|
$isApproaching = !$isCompleted && !$isOverdue && $dueDate <= $approachDate;
|
|
|
|
if ($isCompleted) { $statusLabel = 'Completata'; $stClass = 'st-completata'; $rowClass = 'row-completed'; }
|
|
elseif ($isOverdue) { $statusLabel = 'Scaduta'; $stClass = 'st-scaduta'; $rowClass = 'row-overdue'; }
|
|
elseif ($isApproaching) { $statusLabel = 'In scadenza'; $stClass = 'st-in-scadenza'; $rowClass = 'row-approaching'; }
|
|
else { $statusLabel = 'Attiva'; $stClass = 'st-attiva'; $rowClass = ''; }
|
|
|
|
// Merge departments
|
|
$allDepts = [];
|
|
if (!empty($row['reparti_assegnati'])) $allDepts = array_map('trim', explode(',', $row['reparti_assegnati']));
|
|
if (!empty($row['reparti_persone'])) $allDepts = array_merge($allDepts, array_map('trim', explode(',', $row['reparti_persone'])));
|
|
$reparti = implode(', ', array_unique(array_filter($allDepts)));
|
|
?>
|
|
<tr class="<?= $rowClass ?>"<?= !empty($row['subject_color']) ? ' style="border-left: 4px solid ' . htmlspecialchars($row['subject_color'], ENT_QUOTES, 'UTF-8') . '"' : '' ?>>
|
|
<td><strong><?= htmlspecialchars($row['subject_name'] ?? '', ENT_QUOTES, 'UTF-8') ?></strong></td>
|
|
<td><?= htmlspecialchars($row['law_regulation'] ?? '', ENT_QUOTES, 'UTF-8') ?></td>
|
|
<td><?= htmlspecialchars($row['topic'], ENT_QUOTES, 'UTF-8') ?></td>
|
|
<td><?= htmlspecialchars($recurrenceLabels[$row['recurrence_type']] ?? $row['recurrence_type'], ENT_QUOTES, 'UTF-8') ?></td>
|
|
<td style="white-space:nowrap"><?= $row['document_date'] ? date('d/m/Y', strtotime($row['document_date'])) : '' ?></td>
|
|
<td style="white-space:nowrap"><?= date('d/m/Y', strtotime($dueDate)) ?></td>
|
|
<td style="white-space:nowrap"><?= $row['check_date'] ? date('d/m/Y', strtotime($row['check_date'])) : '' ?></td>
|
|
<td><?php
|
|
$resp = [];
|
|
if ($reparti) $resp[] = $reparti;
|
|
if ($row['responsabili']) $resp[] = $row['responsabili'];
|
|
echo htmlspecialchars(implode(', ', $resp), ENT_QUOTES, 'UTF-8');
|
|
?></td>
|
|
<td><?= htmlspecialchars($row['storage_location'] ?? '', ENT_QUOTES, 'UTF-8') ?></td>
|
|
<td><?= htmlspecialchars($row['notes'] ?? '', ENT_QUOTES, 'UTF-8') ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
|
|
<div class="print-footer">
|
|
ZIBOGOMMA — Scadenzario — <?= date('d/m/Y') ?>
|
|
</div>
|
|
</body>
|
|
</html>
|