load();
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$today = date('Y-m-d');
$appUrl = rtrim($_ENV['APP_URL'] ?? 'http://localhost:8001', '/');
$sent = 0;
$skipped = 0;
$errors = 0;
// Get active deadlines that are approaching or overdue
$stmt = $pdo->query("
SELECT d.id, d.topic, s.name AS subject_name, d.due_date, d.notification_days
FROM scad_deadlines d
LEFT JOIN scad_subjects s ON s.id = d.subject_id
WHERE d.status = 'active'
AND d.due_date <= DATE_ADD(CURDATE(), INTERVAL d.notification_days DAY)
");
$deadlines = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($deadlines)) {
echo date('Y-m-d H:i:s') . " — Nessuna scadenza da notificare.\n";
exit(0);
}
// Prepare statements
$getRecipients = $pdo->prepare("
SELECT DISTINCT e.id as employee_id, au.email, e.first_name, e.last_name
FROM scad_deadline_employee de
JOIN employees e ON e.id = de.employee_id
JOIN auth_users au ON au.id = e.auth_user_id
WHERE de.deadline_id = ?
AND e.auth_user_id IS NOT NULL
AND au.email IS NOT NULL
AND au.email != ''
");
// Also get employees from assigned departments
$getDeptRecipients = $pdo->prepare("
SELECT DISTINCT e.id as employee_id, au.email, e.first_name, e.last_name
FROM employees e
JOIN auth_users au ON au.id = e.auth_user_id
WHERE e.department IN (SELECT TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(d.departments, ',', n.n), ',', -1))
FROM scad_deadlines d
CROSS JOIN (SELECT 1 n UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) n
WHERE d.id = ?
AND d.departments IS NOT NULL
AND n.n <= 1 + LENGTH(d.departments) - LENGTH(REPLACE(d.departments, ',', '')))
AND e.auth_user_id IS NOT NULL
AND au.email IS NOT NULL
AND au.email != ''
");
$checkSent = $pdo->prepare("
SELECT COUNT(*) FROM scad_deadline_notifications
WHERE deadline_id = ? AND employee_id = ? AND type = ? AND DATE(sent_at) = CURDATE()
");
$insertNotif = $pdo->prepare("
INSERT INTO scad_deadline_notifications (deadline_id, employee_id, type) VALUES (?, ?, ?)
");
$insertHistory = $pdo->prepare("
INSERT INTO scad_deadline_histories (deadline_id, user_id, action, notes) VALUES (?, NULL, 'notification_sent', ?)
");
foreach ($deadlines as $dl) {
$isOverdue = $dl['due_date'] < $today;
$type = $isOverdue ? 'overdue' : 'approaching';
$daysLeft = (int)((strtotime($dl['due_date']) - strtotime($today)) / 86400);
// Collect all recipients (direct + department)
$recipients = [];
$getRecipients->execute([$dl['id']]);
foreach ($getRecipients->fetchAll(PDO::FETCH_ASSOC) as $r) {
$recipients[$r['employee_id']] = $r;
}
$getDeptRecipients->execute([$dl['id']]);
foreach ($getDeptRecipients->fetchAll(PDO::FETCH_ASSOC) as $r) {
$recipients[$r['employee_id']] = $r;
}
if (empty($recipients)) {
continue;
}
foreach ($recipients as $emp) {
// Check if already sent today
$checkSent->execute([$dl['id'], $emp['employee_id'], $type]);
if ($checkSent->fetchColumn() > 0) {
$skipped++;
continue;
}
// Send email
try {
$mail = new PHPMailer(true);
// SMTP config from .env
$mailer = $_ENV['MAIL_MAILER'] ?? 'mail';
if ($mailer === 'smtp') {
$mail->isSMTP();
$mail->Host = $_ENV['MAIL_HOST'] ?? 'localhost';
$mail->Port = (int)($_ENV['MAIL_PORT'] ?? 587);
if (!empty($_ENV['MAIL_USERNAME']) && $_ENV['MAIL_USERNAME'] !== 'null') {
$mail->SMTPAuth = true;
$mail->Username = $_ENV['MAIL_USERNAME'];
$mail->Password = $_ENV['MAIL_PASSWORD'] ?? '';
}
$enc = $_ENV['MAIL_ENCRYPTION'] ?? '';
if ($enc && $enc !== 'null') {
$mail->SMTPSecure = $enc;
}
}
$mail->CharSet = 'UTF-8';
$mail->setFrom(
$_ENV['MAIL_FROM_ADDRESS'] ?? 'noreply@zibogomma.it',
$_ENV['MAIL_FROM_NAME'] ?? 'Scadenzario ZIBOGOMMA'
);
$mail->addAddress($emp['email'], trim($emp['first_name'] . ' ' . $emp['last_name']));
$detailUrl = $appUrl . '/userarea/scadenzario/detail.php?id=' . $dl['id'];
$topicText = (!empty($dl['subject_name']) ? $dl['subject_name'] . ' — ' : '') . $dl['topic'];
if ($isOverdue) {
$mail->Subject = '⚠️ Scadenza superata: ' . $dl['topic'];
$mail->Body = buildHtml(
'Scadenza superata',
$topicText,
'La scadenza era prevista per il ' . date('d/m/Y', strtotime($dl['due_date'])) . ' ed è stata superata da ' . abs($daysLeft) . ' giorni.',
'#dc3545',
$detailUrl
);
} else {
$mail->Subject = '📅 Scadenza in arrivo: ' . $dl['topic'];
$daysText = $daysLeft === 0 ? 'oggi' : 'tra ' . $daysLeft . ' giorni';
$mail->Body = buildHtml(
'Scadenza in arrivo',
$topicText,
'La scadenza è prevista per il ' . date('d/m/Y', strtotime($dl['due_date'])) . ' (' . $daysText . ').',
'#e8930c',
$detailUrl
);
}
$mail->isHTML(true);
$mail->AltBody = strip_tags(str_replace('
', "\n", $mail->Body));
$mail->send();
// Record notification
$insertNotif->execute([$dl['id'], $emp['employee_id'], $type]);
$sent++;
echo date('H:i:s') . " ✓ {$type} → {$emp['email']} — {$dl['topic']}\n";
} catch (Exception $e) {
$errors++;
echo date('H:i:s') . " ✗ Errore {$emp['email']}: {$e->getMessage()}\n";
}
}
// History (one per deadline, not per recipient)
$recipientNames = implode(', ', array_map(fn($r) => trim($r['first_name'] . ' ' . $r['last_name']), $recipients));
$insertHistory->execute([$dl['id'], "Notifica {$type} inviata a: {$recipientNames}"]);
}
echo "\n" . date('Y-m-d H:i:s') . " — Completato. Inviate: {$sent}, Saltate: {$skipped}, Errori: {$errors}\n";
// --- HTML email template ---
function buildHtml(string $title, string $topic, string $message, string $accentColor, string $url): string
{
return '