Bei Telefonanfragen den Patienten zur Rufnummer vorschlagen

Die Telefonanlage fuellt anfragen.anrufernummer inzwischen - die erste
Anfrage damit ist #13037. Wenn die Anlage den Anrufer nicht selbst zuordnen
konnte, wird die Nummer jetzt gegen persons.tele gesucht und der Treffer
angezeigt.

NormalisiereRufnummer() vergleicht ziffernweise und fuehrt +49 und 0049 auf
die nationale Schreibweise mit fuehrender 0 zurueck. Nur so finden die
Anzeige der Anlage und die von Hand gepflegten Nummern zusammen: von 2972
gepflegten Nummern stehen 2941 als reine Ziffern da, 22 mit Bindestrich,
6 international.

Bewusst nur ein Vorschlag, keine Zuordnung. 521 der 2972 Nummern gehoeren zu
mehr als einer Person - Familien teilen sich einen Anschluss, zwei Nummern
haengen sogar an 16 bzw. 18 Personen. Bei mehreren Treffern werden deshalb
die Namen aufgezaehlt statt einer ausgewaehlt, und auch der eindeutige Fall
ist als "nicht bestaetigt - nur ueber die Rufnummer erkannt" ausgewiesen.
Eine falsche Zuordnung haette die Daten des falschen Patienten neben die
Anfrage gestellt.

Nummern unter 7 Ziffern werden nicht gesucht: in persons stehen ein paar
Platzhalter mit 1 bis 5 Ziffern, die sonst wahllos zusammenfallen.

Der Index wird beim ersten Treffer einmal je Seitenaufruf aufgebaut und
danach wiederverwendet - die Liste zeigt bis zu einige tausend Zeilen, eine
Abfrage je Zeile waere zu teuer. Gemessen ueber 12800 Zeilen: genau eine
Abfrage gegen persons. Ohne Telefonanfrage mit brauchbarer Nummer wird der
Index gar nicht erst gebaut.

Angezeigt in der Anfrageliste (Kontaktspalte), auf der Hinweisseite fuer
Anfragen ohne zugeordneten Patienten und unter Antwort einsehen.

Geprueft: Normalisierung gegen internationale, geklammerte und mit
Leerzeichen geschriebene Nummern; Vorschlag bleibt aus bei Mail- und
Portalanfragen, bei fehlender, zu kurzer und unterdrueckter Nummer sowie
bei bereits zugeordnetem Patienten. Listenlogik ueber alle 12793 Anfragen
mit erzwungenen Treffern durchgerechnet - der Vorschlag steht nie bei einer
Anfrage, die schon einen Patienten hat. Fuer #13037 selbst gibt es keinen
Treffer, die Nummer ist in persons nicht gepflegt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-08 19:24:25 +02:00
co-authored by Claude Opus 5
parent 4dabad0b22
commit 53cff55ac2
2 changed files with 122 additions and 0 deletions
+6
View File
@@ -255,6 +255,9 @@ if(!check_worker()){
// Die Anlage haelt die Rufnummer des Anrufers getrennt von den
// Stammdaten - sie kann von der hinterlegten abweichen.
$anruferzeile = GetAnruferZeile($row["source"] ?? "mail", $row["anrufernummer"] ?? null);
// Wer koennte angerufen haben? Nur ein Vorschlag anhand der
// Rufnummer, die Auswahl trifft die Mitarbeiterin.
$anrufervorschlag = GetPatientZuRufnummerAusgabe($pdo, $row["source"] ?? "mail", $row["anrufernummer"] ?? null, $row["requester_person_id"] ?? null);
if($hatPerson){
$userausgabe = $vorname . " " . $nachname . "<br>" . $ausgabegeburstag;
$adresse = $plz . " " . $ort . "<br>" . $strasse ;
@@ -266,6 +269,7 @@ if(!check_worker()){
$userausgabe = "<i>Kein Patient zugeordnet</i>";
$adresse = "-";
$kontakt = ($anruferzeile !== "") ? $anruferzeile : "<i>Kontaktdaten siehe Nachricht</i>";
$kontakt .= $anrufervorschlag;
}
echo "<tr style='background-color:". $farbe. ";'><td>$userausgabe <br> $kontakt</td><td>$adresse</td><td>$ordnungsstring - $anfrageart <br>$WeitereInfos</td><td>$datumausgabe</td><td>$update_time<br>$checkausgabe<br>$ausgabeworker</td><td>";
// "Antworten" verschickt eine Mailvorlage. Ohne zugeordnete Person
@@ -361,6 +365,7 @@ if(!check_worker()){
echo "ueber <b>Telefonisch beantwortet</b> abschliessen.";
echo "</div>";
echo GetAnruferZeile($row["source"] ?? "mail", $row["anrufernummer"] ?? null);
echo GetPatientZuRufnummerAusgabe($pdo, $row["source"] ?? "mail", $row["anrufernummer"] ?? null, $row["requester_person_id"] ?? null);
echo GetSprachnachrichtHinweis($row["source"] ?? "mail");
echo "<b>Nachricht:</b><br>" . nl2br(e((string)$row["nachricht"])) . "<br><br>";
ZuruckzumAnfrageOverView();
@@ -1151,6 +1156,7 @@ if(!check_worker()){
/* --- Anzeige-Strings --- */
$WeitereInfos = "";
$WeitereInfos .= GetAnruferZeile($row["source"] ?? "mail", $row["anrufernummer"] ?? null);
$WeitereInfos .= GetPatientZuRufnummerAusgabe($pdo, $row["source"] ?? "mail", $row["anrufernummer"] ?? null, $row["person_id"] ?? null);
$WeitereInfos .= GetSprachnachrichtHinweis($row["source"] ?? "mail");
if (!empty($medikamenteins)) {
$WeitereInfos .= "Medikament1: " . htmlspecialchars($medikamenteins, ENT_QUOTES, 'UTF-8') . "<br>";
+116
View File
@@ -692,6 +692,122 @@ function GetAnruferZeile($source, $anrufernummer){
return "Anruf von: " . $link . "<br>";
}
/**
* Rufnummer auf eine vergleichbare Form bringen.
*
* Nur Ziffern; +49 und 0049 werden zur nationalen Schreibweise mit
* fuehrender 0, damit die Anzeige der Telefonanlage und die von Hand
* gepflegten Nummern in persons zusammenfinden.
*/
function NormalisiereRufnummer($nummer){
$ziffern = preg_replace('/[^0-9]/', '', (string)$nummer);
if($ziffern === ""){
return "";
}
if(strpos($ziffern, "0049") === 0){
$ziffern = "0" . substr($ziffern, 4);
}elseif(strpos(trim((string)$nummer), "+") === 0 && strpos($ziffern, "49") === 0){
$ziffern = "0" . substr($ziffern, 2);
}
return $ziffern;
}
/**
* Patienten zu einer Rufnummer suchen.
*
* Liefert alle passenden Zeilen aus persons - bewusst alle, denn 521 der
* 2972 gepflegten Nummern gehoeren zu mehr als einer Person (Familien, zwei
* Nummern sogar zu 16 bzw. 18). Die Auswahl trifft die Mitarbeiterin, nicht
* der Code.
*
* Nummern mit weniger als 7 Ziffern werden nicht gesucht: in persons stehen
* ein paar Platzhalter mit 1 bis 5 Ziffern, die sonst wahllos zusammenfallen.
*
* Der Index wird beim ersten Treffer einmal je Seitenaufruf aufgebaut und
* danach wiederverwendet - die Anfrageliste zeigt bis zu einige tausend
* Zeilen, eine Abfrage je Zeile waere zu teuer.
*/
function FindePatientenZuRufnummer($pdo, $nummer){
static $index = null;
$gesucht = NormalisiereRufnummer($nummer);
if(strlen($gesucht) < 7){
return array();
}
if($index === null){
$index = array();
$stmt = $pdo->query("SELECT person_id, vorname, nachname, geburtstag, email, tele
FROM persons WHERE tele IS NOT NULL AND tele <> ''");
foreach($stmt as $p){
$n = NormalisiereRufnummer($p["tele"]);
if(strlen($n) < 7){
continue;
}
$index[$n][] = $p;
}
}
return isset($index[$gesucht]) ? $index[$gesucht] : array();
}
/**
* Zu einer Telefonanfrage ohne zugeordneten Patienten anzeigen, wer hinter
* der Rufnummer stecken koennte.
*
* Bewusst nur ein Vorschlag: die Rufnummer beweist nicht, wer angerufen hat.
* Bei mehreren Treffern werden die Namen aufgezaehlt, statt einen zu waehlen.
* Leer, sobald die Anfrage bereits einen Patienten hat oder nichts passt.
*/
function GetPatientZuRufnummerAusgabe($pdo, $source, $anrufernummer, $personId = null){
if($source != "telefon"){
return "";
}
if(!empty($personId)){
return "";
}
$treffer = FindePatientenZuRufnummer($pdo, $anrufernummer);
if(!$treffer){
return "";
}
$namen = array();
foreach($treffer as $p){
$name = trim(((string)$p["vorname"]) . " " . ((string)$p["nachname"]));
$namen[] = htmlspecialchars($name, ENT_QUOTES, 'UTF-8');
}
if(count($treffer) === 1){
$p = $treffer[0];
$text = "Rufnummer passt zu: <b>" . $namen[0] . "</b>";
$geburtstag = (string)($p["geburtstag"] ?? "");
if($geburtstag !== "" && $geburtstag !== "0000-00-00"){
$zeit = strtotime($geburtstag);
if($zeit !== false){
$geburtstag = date("d.m.Y", $zeit);
}
$text .= ", geb. " . htmlspecialchars($geburtstag, ENT_QUOTES, 'UTF-8');
}
$mail = trim((string)($p["email"] ?? ""));
if($mail !== ""){
$text .= "<br>" . htmlspecialchars($mail, ENT_QUOTES, 'UTF-8');
}
return $text . "<br><i>nicht bestätigt - nur über die Rufnummer erkannt</i><br>";
}
$gezeigt = array_slice($namen, 0, 6);
$text = "Rufnummer passt zu " . count($treffer) . " Patienten: " . implode(", ", $gezeigt);
if(count($namen) > count($gezeigt)){
$text .= " und " . (count($namen) - count($gezeigt)) . " weiteren";
}
return $text . "<br><i>nicht zugeordnet - bitte selbst prüfen</i><br>";
}
function GetPatientenartName($Patientenart){
if($Patientenart == "0"){
$impfenangebot = "Neupatient";