push notifications
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* push-certificati-cron.php
|
||||
* --------------------------------------------------------------------------
|
||||
* Notifica push per i certificati medici in scadenza.
|
||||
* Di default: una settimana prima (7 giorni) e 5 giorni prima.
|
||||
* Giorni e testi si cambiano dal pannello admin (notificationsetting,
|
||||
* tipo 'certificate').
|
||||
*
|
||||
* Da mettere in cron OGNI ORA:
|
||||
* 0 * * * * /usr/bin/php /percorso/public/push-certificati-cron.php
|
||||
*
|
||||
* Prova immediata: php push-certificati-cron.php --force
|
||||
*
|
||||
* Due regole importanti:
|
||||
* 1. Se l'utente ha rinnovato il certificato (ne esiste uno con scadenza
|
||||
* piu' lontana) NON viene avvisato: il documento vecchio e' gia' stato
|
||||
* sostituito e ricordarne la scadenza sarebbe solo fastidioso.
|
||||
* 2. Se pero' ha piu' documenti validi con la STESSA scadenza (capita con
|
||||
* caricamenti doppi) riceve una notifica sola, non una per documento
|
||||
* (title_multi / body_multi, segnaposti {count} e {documents}).
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/class/db-functions.php';
|
||||
require_once __DIR__ . '/class/push-functions.php';
|
||||
|
||||
$logFile = __DIR__ . '/logs/push_certificati_cron.log';
|
||||
$forza = in_array('--force', $argv ?? [], true) || isset($_GET['force']);
|
||||
|
||||
function scriviLog(string $file, string $messaggio): void
|
||||
{
|
||||
file_put_contents($file, date('Y-m-d H:i:s') . " - $messaggio\n", FILE_APPEND);
|
||||
}
|
||||
|
||||
$db = DBHandlerSelect::getInstance()->getConnection();
|
||||
|
||||
$impostazioni = pushSettings($db, 'certificate');
|
||||
|
||||
if (!$impostazioni) {
|
||||
scriviLog($logFile, 'Nessuna impostazione attiva per i certificati, esco.');
|
||||
exit;
|
||||
}
|
||||
|
||||
$sender = null;
|
||||
|
||||
foreach ($impostazioni as $impostazione) {
|
||||
$giorniPrima = (int) $impostazione['daysbefore'];
|
||||
$oraPrevista = (int) substr((string) $impostazione['sendhour'], 0, 2);
|
||||
|
||||
if (!$forza && (int) date('G') !== $oraPrevista) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$dataScadenza = date('Y-m-d', strtotime("+$giorniPrima days"));
|
||||
|
||||
scriviLog($logFile, "Controllo certificati con scadenza $dataScadenza (anticipo $giorniPrima giorni).");
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Prendiamo solo i certificati "in corso": la sottoquery cerca la scadenza
|
||||
// piu' lontana dell'utente e la confronta con quella della riga. Se non
|
||||
// coincidono vuol dire che il documento e' gia' stato rinnovato.
|
||||
// Se piu' righe hanno la stessa scadenza massima escono tutte e vengono
|
||||
// poi raggruppate in un unico messaggio.
|
||||
// ----------------------------------------------------------------------
|
||||
$stmt = $db->prepare("
|
||||
SELECT
|
||||
c.idcertificateuserprofile,
|
||||
c.iduser,
|
||||
c.documentdescription,
|
||||
c.expirydatedocument,
|
||||
u.first_name,
|
||||
u.last_name
|
||||
FROM certificateuserprofile c
|
||||
INNER JOIN auth_users u ON c.iduser = u.id
|
||||
WHERE c.expirydatedocument = :scadenza
|
||||
AND c.expirydatedocument = (
|
||||
SELECT MAX(c2.expirydatedocument)
|
||||
FROM certificateuserprofile c2
|
||||
WHERE c2.iduser = c.iduser
|
||||
)
|
||||
AND u.pushnotification = 'Y'
|
||||
AND u.status = 'Active'
|
||||
");
|
||||
$stmt->execute([':scadenza' => $dataScadenza]);
|
||||
$certificati = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
scriviLog($logFile, 'Certificati trovati: ' . count($certificati));
|
||||
|
||||
if (!$certificati) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Raggruppiamo per utente: piu' documenti con la stessa scadenza -> una
|
||||
// notifica sola.
|
||||
// ----------------------------------------------------------------------
|
||||
$perUtente = [];
|
||||
$saltate = 0;
|
||||
|
||||
foreach ($certificati as $certificato) {
|
||||
$iduser = (int) $certificato['iduser'];
|
||||
$idcertificato = (int) $certificato['idcertificateuserprofile'];
|
||||
|
||||
if (pushGiaInviata($db, $iduser, 'certificate', $idcertificato, $giorniPrima)) {
|
||||
$saltate++;
|
||||
continue;
|
||||
}
|
||||
|
||||
$perUtente[$iduser][] = $certificato;
|
||||
}
|
||||
|
||||
if (!$perUtente) {
|
||||
scriviLog($logFile, "Anticipo $giorniPrima gg -> niente da inviare (saltati: $saltate).");
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($sender === null) {
|
||||
try {
|
||||
$sender = new PushSender();
|
||||
} catch (Throwable $e) {
|
||||
scriviLog($logFile, 'ERRORE configurazione FCM: ' . $e->getMessage());
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$inviate = 0;
|
||||
$fallite = 0;
|
||||
$senzaApp = 0;
|
||||
|
||||
foreach ($perUtente as $iduser => $certificatiUtente) {
|
||||
$primo = $certificatiUtente[0];
|
||||
$quanti = count($certificatiUtente);
|
||||
|
||||
$elenco = [];
|
||||
foreach ($certificatiUtente as $c) {
|
||||
$elenco[] = trim((string) ($c['documentdescription'] ?? 'Certificato medico'));
|
||||
}
|
||||
|
||||
$valori = [
|
||||
'first_name' => $primo['first_name'] ?? '',
|
||||
'last_name' => $primo['last_name'] ?? '',
|
||||
'expiredate' => date('d/m/Y', strtotime((string) $primo['expirydatedocument'])),
|
||||
'count' => $quanti,
|
||||
'documents' => implode(', ', $elenco),
|
||||
];
|
||||
|
||||
$titolo = $impostazione['title'];
|
||||
$testo = $impostazione['body'];
|
||||
|
||||
if ($quanti > 1) {
|
||||
if (!empty($impostazione['title_multi'])) {
|
||||
$titolo = $impostazione['title_multi'];
|
||||
}
|
||||
if (!empty($impostazione['body_multi'])) {
|
||||
$testo = $impostazione['body_multi'];
|
||||
}
|
||||
}
|
||||
|
||||
$esito = $sender->sendToUser(
|
||||
$db,
|
||||
(int) $iduser,
|
||||
pushRender($titolo, $valori),
|
||||
pushRender($testo, $valori),
|
||||
[
|
||||
'type' => 'certificate',
|
||||
'idcertificate' => (int) $primo['idcertificateuserprofile'],
|
||||
'count' => $quanti,
|
||||
]
|
||||
);
|
||||
|
||||
// Utente senza dispositivi registrati: non ha ancora aperto l'app.
|
||||
if ($esito['no_devices']) {
|
||||
$senzaApp++;
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($certificatiUtente as $c) {
|
||||
pushRegistraInvio(
|
||||
$db,
|
||||
(int) $iduser,
|
||||
'certificate',
|
||||
(int) $c['idcertificateuserprofile'],
|
||||
$giorniPrima,
|
||||
$esito
|
||||
);
|
||||
}
|
||||
|
||||
if ($esito['sent'] > 0) {
|
||||
$inviate++;
|
||||
} else {
|
||||
$fallite++;
|
||||
if ($esito['errors']) {
|
||||
scriviLog($logFile, "Utente $iduser: " . implode(' | ', $esito['errors']));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scriviLog(
|
||||
$logFile,
|
||||
"Anticipo $giorniPrima gg -> inviate: $inviate, saltate: $saltate, "
|
||||
. "fallite: $fallite, senza app: $senzaApp."
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user