exec("CREATE TABLE IF NOT EXISTS impf_workflow_meta ( meta_key VARCHAR(100) NOT NULL, meta_value VARCHAR(255) NOT NULL DEFAULT '', updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (meta_key) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); } } if (!function_exists('impfWorkflowNotificationGetMeta')) { function impfWorkflowNotificationGetMeta(PDO $pdo, string $key): ?string { impfWorkflowNotificationEnsureMetaTable($pdo); $st = $pdo->prepare("SELECT meta_value FROM impf_workflow_meta WHERE meta_key = :meta_key LIMIT 1"); $st->execute(['meta_key' => $key]); $value = $st->fetchColumn(); return ($value === false) ? null : (string)$value; } } if (!function_exists('impfWorkflowNotificationSetMeta')) { function impfWorkflowNotificationSetMeta(PDO $pdo, string $key, string $value): void { impfWorkflowNotificationEnsureMetaTable($pdo); $st = $pdo->prepare("INSERT INTO impf_workflow_meta (meta_key, meta_value) VALUES (:meta_key, :meta_value) ON DUPLICATE KEY UPDATE meta_value = VALUES(meta_value)"); $st->execute([ 'meta_key' => $key, 'meta_value' => $value, ]); } } if (!function_exists('impfWorkflowNotificationGetEmail')) { function impfWorkflowNotificationGetEmail(PDO $pdo): string { return trim((string)(impfWorkflowNotificationGetMeta($pdo, 'benachrichtigung_email') ?? '')); } } if (!function_exists('impfWorkflowNotificationSetEmail')) { function impfWorkflowNotificationSetEmail(PDO $pdo, string $email): void { $email = trim($email); impfWorkflowNotificationSetMeta($pdo, 'benachrichtigung_email', $email); } } if (!function_exists('impfWorkflowNotificationIsReady')) { function impfWorkflowNotificationIsReady(PDO $pdo): bool { return impfWorkflowNotificationGetEmail($pdo) !== ''; } } if (!function_exists('impfWorkflowNotificationShouldTrigger')) { function impfWorkflowNotificationShouldTrigger(int $wartende, int $dosen): bool { if ($wartende < 5) { return false; } if ($dosen > 5) { return $wartende >= $dosen; } return true; } } if (!function_exists('impfWorkflowNotificationStateKey')) { function impfWorkflowNotificationStateKey(int $impfstoffId, int $zeitraumId): string { return 'notification_sent_' . $impfstoffId . '_' . $zeitraumId; } } if (!function_exists('impfWorkflowNotificationCountWaitersForPlan')) { function impfWorkflowNotificationCountWaitersForPlan(PDO $pdo, int $impfstoffId, int $zeitraumId): int { if ($impfstoffId <= 0 || $zeitraumId <= 0) { return 0; } $st = $pdo->prepare("SELECT COUNT(DISTINCT w.userid) FROM warteliste w WHERE w.checked = 1 AND (w.impfstoff = :iid OR w.impfstoff = 0) AND ( EXISTS ( SELECT 1 FROM warteliste_zeitraum wz WHERE wz.warteid = w.warteid AND wz.zeitraum_id = :zid ) OR ( NOT EXISTS ( SELECT 1 FROM warteliste_zeitraum wz_none WHERE wz_none.warteid = w.warteid ) AND (w.zeitraum_id = :zid OR w.zeitraum_id IS NULL) ) )"); $st->execute([ 'iid' => $impfstoffId, 'zid' => $zeitraumId, ]); return (int)$st->fetchColumn(); } } if (!function_exists('impfWorkflowNotificationSendForPlan')) { function impfWorkflowNotificationSendForPlan( PDO $pdo, int $impfstoffId, string $impfstoffName, int $zeitraumId, string $zeitraumLabel, int $wartende, int $dosen ): array { if ($impfstoffId <= 0 || $zeitraumId <= 0) { return []; } $stateKey = impfWorkflowNotificationStateKey($impfstoffId, $zeitraumId); $alreadySent = impfWorkflowNotificationGetMeta($pdo, $stateKey) === '1'; $shouldTrigger = impfWorkflowNotificationShouldTrigger($wartende, $dosen); if (!$shouldTrigger) { if ($alreadySent) { impfWorkflowNotificationSetMeta($pdo, $stateKey, '0'); } return []; } if ($alreadySent) { return []; } $email = impfWorkflowNotificationGetEmail($pdo); if ($email === '') { return []; } $thresholdText = ($dosen > 5) ? 'Die Flasche hat mehr als 5 Dosen, daher wird erst bei einer vollen Flasche benachrichtigt.' : 'Es sind mindestens 5 Interessenten fuer dieses Zeitfenster vorhanden.'; $subject = 'Impfworkflow: Warteliste ist bereit fuer ' . $impfstoffName; $body = '
Fuer den Impfworkflow ist ein Zeitfenster benachrichtigungsreif.
' . 'Impfstoff: ' . htmlspecialchars($impfstoffName, ENT_QUOTES, 'UTF-8') . '
'
. 'Zeitfenster: ' . htmlspecialchars($zeitraumLabel, ENT_QUOTES, 'UTF-8') . '
'
. 'Interessenten: ' . $wartende . '
'
. 'Dosen pro Flasche: ' . $dosen . '
' . htmlspecialchars($thresholdText, ENT_QUOTES, 'UTF-8') . '
'; if (!SendMailMessage($pdo, $email, $subject, $body)) { throw new RuntimeException('Benachrichtigungs-E-Mail konnte nicht versendet werden.'); } impfWorkflowNotificationSetMeta($pdo, $stateKey, '1'); return [[ 'impfstoff_id' => $impfstoffId, 'zeitraum_id' => $zeitraumId, 'email' => $email, 'impfstoff' => $impfstoffName, 'zeitraum' => $zeitraumLabel, 'wartende' => $wartende, 'dosen' => $dosen, ]]; } } if (!function_exists('impfWorkflowNotificationProcess')) { function impfWorkflowNotificationProcess(PDO $pdo, int $impfstoffId = 0, array $zeitraumIds = []): array { if (!function_exists('impfGetZeitraeumeByImpfstoff') || !function_exists('impfLoadZeitraumById')) { return []; } $zeitraumIds = array_values(array_unique(array_filter(array_map('intval', $zeitraumIds), static function (int $zeitraumId): bool { return $zeitraumId > 0; }))); $sql = "SELECT r.impfstoff_id, r.dosen_pro_flasche, i.impfname FROM impfstoff_workflow r INNER JOIN impfstoff i ON i.impfid = r.impfstoff_id WHERE (i.aktiv = 1 OR i.aktivwarteliste = 1 OR i.aktivtermin = 1 OR i.aktivgrippe = 1)"; $params = []; if ($impfstoffId > 0) { $sql .= " AND r.impfstoff_id = :iid"; $params['iid'] = $impfstoffId; } $sql .= " ORDER BY i.impfname"; $stRules = $pdo->prepare($sql); $stRules->execute($params); $rules = $stRules->fetchAll(PDO::FETCH_ASSOC); if (empty($rules)) { return []; } $zeitraeumeByImpfstoff = impfGetZeitraeumeByImpfstoff($pdo, true); $sent = []; foreach ($rules as $rule) { $currentImpfstoffId = (int)$rule['impfstoff_id']; $dosen = (int)$rule['dosen_pro_flasche']; if ($currentImpfstoffId <= 0 || $dosen <= 0 || empty($zeitraeumeByImpfstoff[$currentImpfstoffId])) { continue; } foreach ($zeitraeumeByImpfstoff[$currentImpfstoffId] as $zeitraum) { $currentZeitraumId = (int)($zeitraum['zeitraum_id'] ?? 0); if ($currentZeitraumId <= 0) { continue; } if (!empty($zeitraumIds) && !in_array($currentZeitraumId, $zeitraumIds, true)) { continue; } $wartende = impfWorkflowNotificationCountWaitersForPlan($pdo, $currentImpfstoffId, $currentZeitraumId); $sent = array_merge( $sent, impfWorkflowNotificationSendForPlan( $pdo, $currentImpfstoffId, (string)$rule['impfname'], $currentZeitraumId, (string)($zeitraum['label'] ?? ''), $wartende, $dosen ) ); } } return $sent; } }