From f19c490f44da175485fa2bb2db863e8d0fe5574b Mon Sep 17 00:00:00 2001 From: Clemens Creutzburg Date: Tue, 8 Sep 2026 12:56:45 +0200 Subject: [PATCH] Telefon-Anfragen ohne Personenbezug wieder anzeigen Seit dem 02.09.2026 legt die Telefonanlage Anfragen mit source='telefon' an. Von 309 solchen Zeilen haben 207 keine requester_person_id, weil der Anrufer nicht zugeordnet werden konnte - darunter alle 33 offenen. Saemtliche Anzeigepfade haengen per INNER JOIN an persons, wodurch genau diese Zeilen kommentarlos aus dem Ergebnis fielen. Die Ansicht "Unbeantwortete Anfragen" zeigte dadurch 2 statt 35 Eintraege. Bei mail- und portal-Anfragen konnte das nicht auffallen: die Formulare legen die Person vorher in persons an und brechen sonst ab (rezepte.php), entsprechend hat dort keine einzige Zeile eine fehlende Person. personid und userid stehen zwar auch bei mail auf 0, sind aber tote Legacy-Spalten und tragen den Personenbezug nicht. Die Anzeigepfade verwenden jetzt LEFT JOIN und zeigen ohne Treffer "Kein Patient zugeordnet" statt einer leeren Zeile: Liste, Antworten, Loesch-Dialog, Loeschen ohne Mail und Antwort einsehen. Die beiden Knoepfe, die zwingend eine Mailadresse brauchen - Antworten und Loeschen mit Mail - erscheinen nur noch mit zugeordneter Person; wer das Antwortformular direkt aufruft, bekommt einen Hinweis samt Transkript statt eines Abbruchs. "Telefonisch beantwortet" brauchte keine Aenderung, dieser Weg fragt nur die anfrageid ab. Der Mailversand in functions.inc.php und die patientenbezogene Historie behalten ihren INNER JOIN - dort ist eine Person Voraussetzung. Neu ist GetAnfrageHerkunft(). Die Liste leitete die Herkunft bisher aus sicherenachricht ab, was Telefonanfragen mangels Wert als "Mailanfrage" etikettierte. Nur dieser dritte Fall kommt aus source. Die Unterscheidung intern/Mail bleibt bewusst an sicherenachricht haengen, weil insertAnfrage() kein source setzt und 304 interne Anfragen deshalb als source='mail' in der Tabelle stehen; ueber source vergeben haette das Label 9871 Bestandszeilen umetikettiert, darunter die datenschutzrelevante Unterscheidung. Nachgeprueft gegen die Datenbank: die Ansicht liefert statt 2 nun 35 Zeilen mit allen 33 offenen Telefon-Anfragen. Der Renderblock ueber alle 12784 Zeilen simuliert, error_reporting=E_ALL als Exception, ohne Warnung; das Herkunfts-Label bleibt fuer 12475 Bestandszeilen unveraendert und aendert sich nur fuer die 309 Telefon-Zeilen. Alle fuenf von der Liste erreichbaren Aktionen laden fuer eine Zeile ohne Person. Co-Authored-By: Claude Opus 5 --- admin/anfragen.php | 93 +++++++++++++++++++++++++++++++------------ inc/functions.inc.php | 22 ++++++++++ 2 files changed, 90 insertions(+), 25 deletions(-) diff --git a/admin/anfragen.php b/admin/anfragen.php index 53aef17..541ecc2 100644 --- a/admin/anfragen.php +++ b/admin/anfragen.php @@ -115,8 +115,8 @@ if(!check_worker()){ p.ort, p.plz, p.strasse, aa.artname FROM anfragen a - JOIN persons p ON a.requester_person_id = p.person_id - JOIN anfrageart aa ON a.anforderungart = aa.artid + LEFT JOIN persons p ON a.requester_person_id = p.person_id + LEFT JOIN anfrageart aa ON a.anforderungart = aa.artid "; $params = []; @@ -201,16 +201,18 @@ if(!check_worker()){ $dateiname = e((string)$row["dateiname"]); - $anfrageart = e((string)$row["artname"]); + // artname kann seit dem LEFT JOIN leer sein. + $anfrageart = e((string)($row["artname"] ?? "")); + if($anfrageart === ""){ + $anfrageart = "unbekannte Art"; + } $ordnungsid = $row["ordnungsid"]; $ordnungsstring = GetOrdnungsid($ordnungsid); $WeitereInfos= ""; $sicherenachricht = $row["sicherenachricht"]; - if($sicherenachricht == "1"){ - $WeitereInfos .= "Interne Anfrage
"; - }else{ - $WeitereInfos .= "Mailanfrage
"; - } + // Telefonanfragen liessen sicherenachricht NULL und wurden + // dadurch faelschlich als Mailanfrage etikettiert. + $WeitereInfos .= GetAnfrageHerkunft($row["source"] ?? "mail", $sicherenachricht) . "
"; if($medikamenteins){ $WeitereInfos .= "Medikament1: $medikamenteins
"; } @@ -244,17 +246,34 @@ if(!check_worker()){ $farbe = GetStatusFarbe($checked); $checkausgabe = GetStatus($checked); - $userausgabe = $vorname . " " . $nachname . "
" . $ausgabegeburstag; - $adresse = $plz . " " . $ort . "
" . $strasse ; - $adresse = $adresse; - echo "$userausgabe
$mail
Tel:$tel$adresse$ordnungsstring - $anfrageart
$WeitereInfos$datumausgabe$update_time
$checkausgabe
$ausgabeworker + // Ohne Treffer im LEFT JOIN gibt es keine Personendaten - + // typisch fuer Telefonanfragen, deren Anrufer nicht zugeordnet + // werden konnte. Frueher fielen diese Zeilen durch den INNER + // JOIN komplett aus der Liste. + $hatPerson = ($row["vorname"] !== null || $row["nachname"] !== null); + if($hatPerson){ + $userausgabe = $vorname . " " . $nachname . "
" . $ausgabegeburstag; + $adresse = $plz . " " . $ort . "
" . $strasse ; + $kontakt = "$mail
Tel:$tel"; + }else{ + $userausgabe = "Kein Patient zugeordnet"; + $adresse = "-"; + $kontakt = "Kontaktdaten siehe Nachricht"; + } + echo "$userausgabe
$kontakt$adresse$ordnungsstring - $anfrageart
$WeitereInfos$datumausgabe$update_time
$checkausgabe
$ausgabeworker"; + // "Antworten" verschickt eine Mailvorlage. Ohne zugeordnete Person + // gibt es keine Adresse, der Knopf wuerde ins Leere laufen. + if($hatPerson){ + echo "
-
+ "; + } + echo "
@@ -308,8 +327,8 @@ if(!check_worker()){ p.ort, p.plz, p.strasse, aa.artname FROM anfragen a - INNER JOIN persons p ON a.requester_person_id = p.person_id - INNER JOIN anfrageart aa ON a.anforderungart = aa.artid + LEFT JOIN persons p ON a.requester_person_id = p.person_id + LEFT JOIN anfrageart aa ON a.anforderungart = aa.artid WHERE a.anfrageid = ? LIMIT 1 "; @@ -323,6 +342,24 @@ if(!check_worker()){ exit; } + // Ohne zugeordnete Person gibt es keine Mailadresse - die + // Antwortvorlagen unten wuerden ins Leere laufen. Betrifft vor + // allem Telefonanfragen ohne erkannten Anrufer. + if ($row["vorname"] === null && $row["nachname"] === null) { + echo ""; + echo "Nachricht:
" . nl2br(e((string)$row["nachricht"])) . "

"; + ZuruckzumAnfrageOverView(); + echo "
"; + include(__DIR__ . "/templates/footer.inc.php"); + exit; + } + // Ticket und Antwort ansehen. $abholort = $row["abholort"] ?? null; $sicherenachricht = $row["sicherenachricht"] ?? null; @@ -858,7 +895,7 @@ if(!check_worker()){ $stmt = $pdo->prepare(" SELECT * FROM anfragen a - INNER JOIN persons p ON p.person_id = a.requester_person_id + LEFT JOIN persons p ON p.person_id = a.requester_person_id WHERE a.anfrageid = :anfrageid LIMIT 1 "); @@ -875,16 +912,22 @@ if(!check_worker()){ $vorname = $rowtime["vorname"]; $nachname = $rowtime["nachname"]; - $userausgabe = $vorname . " " . $nachname; + // Telefonanfragen ohne erkannten Anrufer haben keine Person. + $hatPerson = ($vorname !== null || $nachname !== null); + $userausgabe = $hatPerson ? ($vorname . " " . $nachname) : "Kein Patient zugeordnet"; echo "Name:
$userausgabe
Anforderung: $impfstofftext
"; echo "Wollen Sie wirklich diesen Eintrag löschen?
Dieses ist nicht rückgängig zu machen!
Dann bestätigen Sie die Abmeldung:
"; - echo "
"; - echo ''; - echo '
'; - echo ''; - echo "
"; + // Loeschen mit Mail setzt eine Mailadresse voraus. + if ($hatPerson) { + echo ""; + echo ''; + echo '
'; + echo ''; + echo "
"; + echo "
"; + } echo "
"; echo ''; echo '
'; @@ -971,7 +1014,7 @@ if(!check_worker()){ p.tele, p.geburtstag FROM anfragen a - INNER JOIN persons p ON p.person_id = a.requester_person_id + LEFT JOIN persons p ON p.person_id = a.requester_person_id WHERE a.anfrageid = :anfrageid LIMIT 1 "); @@ -1051,8 +1094,8 @@ if(!check_worker()){ aa.artname AS anfrageart_name FROM anfragen a - INNER JOIN persons p ON p.person_id = a.requester_person_id - INNER JOIN anfrageart aa ON a.anforderungart = aa.artid + LEFT JOIN persons p ON p.person_id = a.requester_person_id + LEFT JOIN anfrageart aa ON a.anforderungart = aa.artid WHERE a.anfrageid = :anfrageid LIMIT 1 "); diff --git a/inc/functions.inc.php b/inc/functions.inc.php index c37031a..59ccac6 100644 --- a/inc/functions.inc.php +++ b/inc/functions.inc.php @@ -611,6 +611,28 @@ function GetOrdnungsid($wert){ } +/** + * Herkunft einer Anfrage als Text. + * + * Nur der Fall "telefon" kommt aus anfragen.source. Die Unterscheidung + * intern/Mail bleibt bewusst an sicherenachricht haengen: source="portal" + * ist dafuer unbrauchbar, weil insertAnfrage() kein source setzt und interne + * Anfragen deshalb als source="mail" in der Tabelle stehen. + * Seit 02.09.2026 legt die Telefonanlage Anfragen mit source="telefon" an; + * diese haben oft keine requester_person_id, weil der Anrufer nicht + * zugeordnet werden konnte. + */ +function GetAnfrageHerkunft($source, $sicherenachricht){ + if($source == "telefon"){ + $text = "Telefonanfrage"; + }else if($sicherenachricht == "1"){ + $text = "Interne Anfrage"; + }else{ + $text = "Mailanfrage"; + } + return $text; +} + function GetPatientenartName($Patientenart){ if($Patientenart == "0"){ $impfenangebot = "Neupatient";