diff --git a/admin/impfworkflow.php b/admin/impfworkflow.php index 86f8342..6e77124 100644 --- a/admin/impfworkflow.php +++ b/admin/impfworkflow.php @@ -235,7 +235,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } else { $dosen = (int)$rule['dosen_pro_flasche']; - $stCount = $pdo->prepare("SELECT COUNT(*) + $stCount = $pdo->prepare("SELECT COUNT(DISTINCT userid) FROM warteliste WHERE checked = 1 AND (impfstoff = :iid OR impfstoff = 0) @@ -291,16 +291,27 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { WHERE checked = 1 AND (impfstoff = :iid OR impfstoff = 0) AND (zeitraum_id = :zid OR zeitraum_id IS NULL) - ORDER BY date_created ASC, warteid ASC - LIMIT :lim"); + ORDER BY date_created ASC, warteid ASC"); $stW->bindValue(':iid', $impfstoffId, PDO::PARAM_INT); $stW->bindValue(':zid', $planId, PDO::PARAM_INT); - $stW->bindValue(':lim', $dosen, PDO::PARAM_INT); $stW->execute(); - $warteRows = $stW->fetchAll(PDO::FETCH_ASSOC); + $warteRowsRaw = $stW->fetchAll(PDO::FETCH_ASSOC); + $warteRows = []; + $seenUserIds = []; + foreach ($warteRowsRaw as $warteRow) { + $warteUserId = (int)$warteRow['userid']; + if (isset($seenUserIds[$warteUserId])) { + continue; + } + $seenUserIds[$warteUserId] = true; + $warteRows[] = $warteRow; + if (count($warteRows) >= $dosen) { + break; + } + } if (count($warteRows) < $dosen) { - throw new RuntimeException("Warteliste während Verarbeitung zu klein geworden."); + throw new RuntimeException("Warteliste waehrend Verarbeitung zu klein geworden."); } $stInsTermin = $pdo->prepare("INSERT INTO impftermin @@ -540,7 +551,7 @@ $eventOverview = []; try { $stRules = $pdo->prepare("SELECT r.impfstoff_id, r.dosen_pro_flasche, i.impfname, - COALESCE((SELECT COUNT(*) FROM warteliste w WHERE w.checked = 1 AND (w.impfstoff = r.impfstoff_id OR w.impfstoff = 0)),0) AS wartende + COALESCE((SELECT COUNT(DISTINCT w.userid) FROM warteliste w WHERE w.checked = 1 AND (w.impfstoff = r.impfstoff_id OR w.impfstoff = 0)),0) AS wartende 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) diff --git a/admin/impfworkflow_stammdaten.php b/admin/impfworkflow_stammdaten.php index d25a6ce..65eb402 100644 --- a/admin/impfworkflow_stammdaten.php +++ b/admin/impfworkflow_stammdaten.php @@ -411,7 +411,7 @@ $allImpforte = getImpforte($pdo, false); $zeitraeume = impfGetZeitraumRows($pdo, true); $stRules = $pdo->prepare("SELECT r.impfstoff_id, r.dosen_pro_flasche, i.impfname, - COALESCE((SELECT COUNT(*) FROM warteliste w WHERE w.checked = 1 AND (w.impfstoff = r.impfstoff_id OR w.impfstoff = 0)),0) AS wartende + COALESCE((SELECT COUNT(DISTINCT w.userid) FROM warteliste w WHERE w.checked = 1 AND (w.impfstoff = r.impfstoff_id OR w.impfstoff = 0)),0) AS wartende 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) diff --git a/inc/functions.impfen.inc.php b/inc/functions.impfen.inc.php index d11df9a..ceb70d8 100644 --- a/inc/functions.impfen.inc.php +++ b/inc/functions.impfen.inc.php @@ -358,3 +358,145 @@ if (!function_exists('impfGetZeitraeumeByImpfstoff')) { return $result; } } + +if (!function_exists('impfGetWartelistenFormOptions')) { + function impfGetWartelistenFormOptions(PDO $pdo): array + { + $impfstoffe = []; + $zeitfenster = []; + + $stImpfstoffe = $pdo->prepare("SELECT r.impfstoff_id, 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) + AND r.dosen_pro_flasche > 0 + ORDER BY i.impfname"); + $stImpfstoffe->execute(); + foreach ($stImpfstoffe->fetchAll(PDO::FETCH_ASSOC) as $row) { + $impfstoffe[(int)$row['impfstoff_id']] = (string)$row['impfname']; + } + + $zeitraeumeByImpfstoff = impfGetZeitraeumeByImpfstoff($pdo, true); + foreach ($zeitraeumeByImpfstoff as $impfstoffId => $zeitraeume) { + if (!isset($impfstoffe[$impfstoffId])) { + continue; + } + + foreach ($zeitraeume as $zeitraum) { + if (!isset($zeitfenster[$impfstoffId])) { + $zeitfenster[$impfstoffId] = []; + } + $zeitfenster[$impfstoffId][] = [ + 'id' => (int)$zeitraum['zeitraum_id'], + 'label' => (string)$zeitraum['label'], + ]; + } + } + + foreach (array_keys($impfstoffe) as $impfstoffId) { + if (empty($zeitfenster[$impfstoffId])) { + unset($impfstoffe[$impfstoffId]); + } + } + + return [ + 'impfstoffe' => $impfstoffe, + 'zeitfenster' => $zeitfenster, + ]; + } +} + +if (!function_exists('impfCreateWaitlistEntryForPerson')) { + function impfCreateWaitlistEntryForPerson( + PDO $pdo, + int $personId, + int $impfstoffId, + int $zeitraumId, + int $impfart, + ?string $letzteImpfung = null, + int $checked = 1 + ): array { + if ($personId <= 0) { + return [false, 'Keine gueltige Person uebergeben.', null]; + } + if ($impfstoffId <= 0) { + return [false, 'Bitte einen Impfstoff auswaehlen.', null]; + } + if ($zeitraumId <= 0) { + return [false, 'Bitte ein Zeitfenster auswaehlen.', null]; + } + if ($impfart < 1 || $impfart > 4) { + return [false, 'Bitte eine gueltige Impfungsart auswaehlen.', null]; + } + + $letzteImpfung = $letzteImpfung !== null ? trim($letzteImpfung) : null; + if ($impfart === 1) { + $letzteImpfung = null; + } elseif ($letzteImpfung === null || $letzteImpfung === '') { + return [false, 'Bitte das Datum der letzten Impfung angeben.', null]; + } elseif (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $letzteImpfung)) { + return [false, 'Das Datum der letzten Impfung ist ungueltig.', null]; + } + + $stPerson = $pdo->prepare("SELECT person_id, patientenart, vorname, nachname + FROM persons + WHERE person_id = :pid + LIMIT 1"); + $stPerson->execute(['pid' => $personId]); + $person = $stPerson->fetch(PDO::FETCH_ASSOC); + if (!$person) { + return [false, 'Die Person wurde nicht gefunden.', null]; + } + + $zeitraum = impfLoadZeitraumById($pdo, $zeitraumId, true); + if (!$zeitraum) { + return [false, 'Das ausgewaehlte Zeitfenster ist nicht mehr verfuegbar.', null]; + } + if (!in_array($impfstoffId, $zeitraum['impfstoff_id_list'] ?? [], true)) { + return [false, 'Impfstoff und Zeitfenster passen nicht zusammen.', null]; + } + + $stDup = $pdo->prepare("SELECT warteid + FROM warteliste + WHERE userid = :uid + AND checked IN (0, 1) + AND impfstoff = :impfstoff + AND COALESCE(zeitraum_id, 0) = :zeitraum_id + AND impfart = :impfart + LIMIT 1"); + $stDup->execute([ + 'uid' => $personId, + 'impfstoff' => $impfstoffId, + 'zeitraum_id' => $zeitraumId, + 'impfart' => $impfart, + ]); + if ($stDup->fetchColumn()) { + return [false, 'Diese Anfrage ist fuer diese Person bereits auf der aktiven Warteliste vorhanden.', null]; + } + + $patientenart = ((int)($person['patientenart'] ?? 0) === 1) ? 1 : 0; + $hash = bin2hex(random_bytes(16)); + $checkedValue = ($checked === 0) ? 0 : 1; + + $stInsert = $pdo->prepare("INSERT INTO warteliste + (userid, checked, hash, impfenangebot, impfstoff, Patientenart, Impfaufklaerung, WeitereFragen, impfart, impfenmit, letzteimpfung, impfenzeitraum, zeitraum_id, date_created) + VALUES + (:userid, :checked, :hash, 1, :impfstoff, :patientenart, 0, 0, :impfart, '', :letzteimpfung, :impfenzeitraum, :zeitraum_id, NOW())"); + $stInsert->execute([ + 'userid' => $personId, + 'checked' => $checkedValue, + 'hash' => $hash, + 'impfstoff' => $impfstoffId, + 'patientenart' => $patientenart, + 'impfart' => $impfart, + 'letzteimpfung' => $letzteImpfung, + 'impfenzeitraum' => (string)$zeitraum['label'], + 'zeitraum_id' => $zeitraumId, + ]); + + $warteid = (int)$pdo->lastInsertId(); + $personName = trim((string)$person['vorname'] . ' ' . (string)$person['nachname']); + + return [true, 'Wartelistenplatz fuer ' . $personName . ' wurde gespeichert.', $warteid]; + } +} diff --git a/intern/impfwarteliste.php b/intern/impfwarteliste.php new file mode 100644 index 0000000..11516ee --- /dev/null +++ b/intern/impfwarteliste.php @@ -0,0 +1,283 @@ +"; +echo "
"; + +echo "

Impfwarteliste

"; +echo "

Hallo " . e((string)($user['vorname'] ?? '')) . ",

"; + +if (!check_mailreg()) { + echo "

"; + echo "Es fehlt die Authentifizierung Ihres Kontos per E-Mail. Bitte authentifizieren Sie Ihre E-Mail-Adresse.
"; + echo "
"; + echo ""; + echo "
"; + echo "
"; +} + +if (!check_userdatenvorhanden()) { + echo "

"; + echo "Es fehlen noch Informationen in Ihren Stammdaten. Bitte pflegen Sie die Daten nach.
"; + echo "
"; + echo ""; + echo "
"; + echo "
"; +} + +if (!(check_mailreg() && check_userdatenvorhanden())) { + echo "


"; + echo ""; + echo "
"; + echo "
"; + include(__DIR__ . "/templates/footer.inc.php"); + exit; +} + +try { + impfWorkflowEnsureTables($pdo); + $internUserId = isset($_SESSION['userid']) ? (int)$_SESSION['userid'] : null; + $personId = ensurePersonFromInternUsersByEmail($pdo, (string)($user['email'] ?? ''), $internUserId); +} catch (Throwable $t) { + echo "
Fehler: " . e($t->getMessage()) . "
"; + echo ""; + include(__DIR__ . "/templates/footer.inc.php"); + exit; +} + +$options = impfGetWartelistenFormOptions($pdo); +$verfuegbareImpfstoffe = $options['impfstoffe']; +$zeitOptionenByImpfstoff = $options['zeitfenster']; +$zeitOptionenJson = json_encode($zeitOptionenByImpfstoff, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + +$form = [ + 'impfstoff_id' => (int)($_POST['impfstoff_id'] ?? 0), + 'zeitraum_id' => (int)($_POST['zeitraum_id'] ?? 0), + 'impfart' => (int)($_POST['impfart'] ?? 0), + 'letzteimpfung' => trim((string)($_POST['letzteimpfung'] ?? '')), +]; + +$successMessage = ''; +$errorMessage = ''; + +$stActive = $pdo->prepare("SELECT w.warteid, w.checked, w.impfart, w.letzteimpfung, w.impfenzeitraum, i.impfname + FROM warteliste w + LEFT JOIN impfstoff i ON i.impfid = w.impfstoff + WHERE w.userid = :pid + AND w.checked IN (0, 1) + ORDER BY w.date_created DESC, w.warteid DESC"); +$stActive->execute(['pid' => $personId]); +$activeWaitRows = $stActive->fetchAll(PDO::FETCH_ASSOC); + +if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST' && (string)($_POST['aktion'] ?? '') === 'create_waitlist') { + try { + [$ok, $message, $warteid] = impfCreateWaitlistEntryForPerson( + $pdo, + $personId, + (int)$form['impfstoff_id'], + (int)$form['zeitraum_id'], + (int)$form['impfart'], + $form['letzteimpfung'] !== '' ? $form['letzteimpfung'] : null, + 1 + ); + + if ($ok) { + try { + SendMailMessageVorlage($pdo, "2", (int)$warteid, "9"); + $successMessage = $message . ' Eine Bestaetigung wurde per E-Mail versendet.'; + } catch (Throwable $mailError) { + $successMessage = $message . ' Der Eintrag wurde gespeichert, aber die E-Mail konnte nicht automatisch versendet werden.'; + error_log('Intern waitlist mail failed: ' . $mailError->getMessage()); + } + + $stActive->execute(['pid' => $personId]); + $activeWaitRows = $stActive->fetchAll(PDO::FETCH_ASSOC); + } else { + $errorMessage = (string)$message; + } + } catch (Throwable $t) { + $errorMessage = 'Der Wartelisteneintrag konnte nicht gespeichert werden: ' . $t->getMessage(); + } +} + +echo "

Hier koennen Sie sich direkt aus dem internen Bereich in die Impfwarteliste eintragen lassen. Ihre Stammdaten werden aus Ihrem Kundenkonto uebernommen.

"; + +echo "

Ihre hinterlegten Stammdaten

"; +echo "Name: " . e(trim((string)($user['vorname'] ?? '') . ' ' . (string)($user['nachname'] ?? ''))) . "
"; +echo "Geburtstag: " . e((string)($user['geburtstag'] ?? '')) . "
"; +echo "Adresse: " . e(trim((string)($user['strasse'] ?? '') . ', ' . (string)($user['plz'] ?? '') . ', ' . (string)($user['ort'] ?? ''))) . "
"; +echo "E-Mail: " . e((string)($user['email'] ?? '')) . "

"; + +if ($successMessage !== '') { + echo "
" . e($successMessage) . "
"; +} +if ($errorMessage !== '') { + echo "
" . e($errorMessage) . "
"; +} + +if (!empty($activeWaitRows)) { + $impfartLabels = [ + 1 => 'Erstimpfung', + 2 => 'Zweitimpfung', + 3 => 'Drittimpfung', + 4 => 'Viertimpfung', + ]; + echo "
"; + echo "Ihre aktiven Wartelisteneintraege.
"; + echo "Sie koennen im internen Bereich mehrere verschiedene Wartelistenanfragen anlegen. Exakte Duplikate werden weiterhin geblockt."; + echo "
"; + echo ""; + echo ""; + foreach ($activeWaitRows as $activeWaitRow) { + $statusText = ((int)$activeWaitRow['checked'] === 1) ? 'Bestaetigt' : 'Unbestaetigt'; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + } + echo "
ImpfstoffZeitraumImpfungsartStatusLetzte Impfung
" . e((string)($activeWaitRow['impfname'] ?? 'Unbekannt')) . "" . e((string)($activeWaitRow['impfenzeitraum'] ?? '')) . "" . e((string)($impfartLabels[(int)$activeWaitRow['impfart']] ?? ('Status ' . (int)$activeWaitRow['impfart']))) . "" . e($statusText) . "" . e((string)($activeWaitRow['letzteimpfung'] ?? '')) . "
"; +} + +if (empty($verfuegbareImpfstoffe)) { + echo "
Aktuell stehen im internen Bereich keine konfigurierten Impfstoffe mit Zeitfenstern zur Verfuegung.
"; +} else { + ?> +
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ + + +
+
+ + Zum Hauptmenue +
+
+
+ + + "; +include(__DIR__ . "/templates/footer.inc.php"); + +?> diff --git a/intern/index.php b/intern/index.php index 017d1f4..f314fa3 100644 --- a/intern/index.php +++ b/intern/index.php @@ -53,7 +53,10 @@ if( is_checked_in_index() ){ ?>

Neue Anfragen können Sie über diesen Button einreichen:

Neue Anfragen erstellen



- + +

Wenn Sie sich für eine Impfung vormerken lassen möchten, können Sie sich hier direkt in die Warteliste eintragen:

+

Zur Impfwarteliste



+

Hier können Sie Ihre Anfragen einsehen. Die Antwort erhalten Sie per E-Mail.

Meine Anfragen einsehen



@@ -120,4 +123,4 @@ if( is_checked_in_index() ){ \ No newline at end of file +?> diff --git a/intern/templates/header.inc.php b/intern/templates/header.inc.php index 69bca98..5743138 100644 --- a/intern/templates/header.inc.php +++ b/intern/templates/header.inc.php @@ -68,6 +68,7 @@ @@ -93,4 +94,4 @@ -?> \ No newline at end of file +?>