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." ); }