maintaince module
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Manutenzioni — email notifications
|
||||
* Run daily, e.g.: 0 7 * * * php /var/www/html/public/userarea/manutenzioni/cron/send_notifications.php
|
||||
*
|
||||
* Sends:
|
||||
* - "advance" when next_due_date <= today + alert_days
|
||||
* - "overdue" when next_due_date < today
|
||||
*
|
||||
* Recipients are the assignee and the supervisor of the maintenance
|
||||
* (employees.auth_user_id -> auth_users.email). Deduplicated per
|
||||
* maintenance + email + type + day by maint_notifications.
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../../class/db-functions.php';
|
||||
require_once __DIR__ . '/../include/functions.php';
|
||||
require_once __DIR__ . '/../../../../vendor/autoload.php';
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
|
||||
$dotenv = Dotenv::createImmutable(__DIR__ . '/../../../../');
|
||||
$dotenv->safeLoad();
|
||||
|
||||
$pdo = mnt_pdo();
|
||||
|
||||
$today = date('Y-m-d');
|
||||
$appUrl = rtrim($_ENV['APP_URL'] ?? 'http://localhost:8001', '/');
|
||||
|
||||
/**
|
||||
* --dry-run (or MNT_MAIL_DRYRUN=1) works out the queue and prints it without
|
||||
* sending anything and without writing to maint_notifications, so a run leaves
|
||||
* no trace and can be repeated. Useful before a change to see what tonight
|
||||
* would deliver, and it is what the test suite drives.
|
||||
*
|
||||
* One line per queued message, tab separated:
|
||||
* QUEUE <type> <email> <maintenance_id> <label>
|
||||
*/
|
||||
$dryRun = in_array('--dry-run', $argv ?? [], true) || !empty($_ENV['MNT_MAIL_DRYRUN']);
|
||||
if ($dryRun) {
|
||||
echo "DRY-RUN — nothing is sent, nothing is recorded\n";
|
||||
}
|
||||
|
||||
$sent = 0;
|
||||
$skipped = 0;
|
||||
$errors = 0;
|
||||
|
||||
// Only active maintenances of active equipment, with a real due date
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT m.id, m.code, m.title, m.next_due_date, m.alert_days, m.is_critical,
|
||||
e.id AS equipment_id, e.name AS equipment_name,
|
||||
m.assignee_employee_id, m.supervisor_employee_id
|
||||
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 IS NOT NULL
|
||||
AND m.next_due_date <= DATE_ADD(?, INTERVAL m.alert_days DAY)
|
||||
");
|
||||
$stmt->execute([$today]);
|
||||
$maintenances = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$maintenances) {
|
||||
echo date('Y-m-d H:i:s') . " — Nessuna manutenzione da notificare.\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$getRecipient = $pdo->prepare("
|
||||
SELECT e.id AS employee_id, e.first_name, e.last_name, u.email
|
||||
FROM employees e
|
||||
INNER JOIN auth_users u ON u.id = e.auth_user_id
|
||||
WHERE e.id = ?
|
||||
AND e.auth_user_id IS NOT NULL
|
||||
AND u.email IS NOT NULL
|
||||
AND u.email <> ''
|
||||
");
|
||||
|
||||
$checkSent = $pdo->prepare("
|
||||
SELECT COUNT(*) FROM maint_notifications
|
||||
WHERE maintenance_id = ? AND email = ? AND type = ? AND sent_date = ?
|
||||
");
|
||||
|
||||
$insertNotification = $pdo->prepare("
|
||||
INSERT INTO maint_notifications (maintenance_id, employee_id, email, type, sent_date)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
");
|
||||
|
||||
// mnt_mail_body() and mnt_notification_mail() live in include/functions.php,
|
||||
// so that the preview renders the very same markup this cron sends.
|
||||
|
||||
foreach ($maintenances as $maintenance) {
|
||||
$isOverdue = $maintenance['next_due_date'] < $today;
|
||||
$type = $isOverdue ? 'overdue' : 'advance';
|
||||
$daysLeft = (int)((strtotime($maintenance['next_due_date']) - strtotime($today)) / 86400);
|
||||
|
||||
// Assignee + supervisor, de-duplicated by employee id
|
||||
$recipients = [];
|
||||
foreach ([$maintenance['assignee_employee_id'], $maintenance['supervisor_employee_id']] as $employeeId) {
|
||||
if (!$employeeId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$getRecipient->execute([(int)$employeeId]);
|
||||
$recipient = $getRecipient->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($recipient) {
|
||||
$recipients[(int)$recipient['employee_id']] = $recipient;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$recipients) {
|
||||
$skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
$label = ($maintenance['code'] ? $maintenance['code'] . ' — ' : '') . $maintenance['title'];
|
||||
$detailUrl = $appUrl . '/userarea/manutenzioni/equipment.php?id=' . (int)$maintenance['equipment_id'];
|
||||
|
||||
foreach ($recipients as $recipient) {
|
||||
$checkSent->execute([$maintenance['id'], $recipient['email'], $type, $today]);
|
||||
if ((int)$checkSent->fetchColumn() > 0) {
|
||||
$skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($dryRun) {
|
||||
printf("QUEUE\t%s\t%s\t%d\t%s\n", $type, $recipient['email'], (int)$maintenance['id'], $label);
|
||||
$sent++;
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$mail = new PHPMailer(true);
|
||||
|
||||
if (($_ENV['MAIL_MAILER'] ?? 'mail') === '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'] ?? '';
|
||||
}
|
||||
|
||||
$encryption = $_ENV['MAIL_ENCRYPTION'] ?? '';
|
||||
if ($encryption && $encryption !== 'null') {
|
||||
$mail->SMTPSecure = $encryption;
|
||||
}
|
||||
}
|
||||
|
||||
$mail->CharSet = 'UTF-8';
|
||||
$mail->isHTML(true);
|
||||
$mail->setFrom(
|
||||
$_ENV['MAIL_FROM_ADDRESS'] ?? 'noreply@zibogomma.it',
|
||||
$_ENV['MAIL_FROM_NAME'] ?? 'Manutenzioni ZIBOGOMMA'
|
||||
);
|
||||
$mail->addAddress($recipient['email'], trim($recipient['first_name'] . ' ' . $recipient['last_name']));
|
||||
|
||||
$composed = mnt_notification_mail($maintenance, $label, $daysLeft, $detailUrl, $today);
|
||||
$mail->Subject = $composed['subject'];
|
||||
$mail->Body = $composed['body'];
|
||||
|
||||
$mail->send();
|
||||
|
||||
$insertNotification->execute([
|
||||
$maintenance['id'],
|
||||
(int)$recipient['employee_id'],
|
||||
$recipient['email'],
|
||||
$type,
|
||||
$today,
|
||||
]);
|
||||
|
||||
mnt_log(
|
||||
$pdo,
|
||||
'notification_sent',
|
||||
(int)$maintenance['equipment_id'],
|
||||
(int)$maintenance['id'],
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$type . ' → ' . $recipient['email']
|
||||
);
|
||||
|
||||
$sent++;
|
||||
} catch (Throwable $e) {
|
||||
$errors++;
|
||||
echo date('Y-m-d H:i:s') . ' — Errore invio a ' . $recipient['email'] . ': ' . $e->getMessage() . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo date('Y-m-d H:i:s')
|
||||
. ($dryRun ? " — In coda: $sent" : " — Inviate: $sent")
|
||||
. ", saltate: $skipped, errori: $errors\n";
|
||||
Reference in New Issue
Block a user