FELIX Befehlsreferenz

<< Klicken Sie, um das Inhaltsverzeichnis anzuzeigen >>

Navigation:  Scripts >

FELIX Befehlsreferenz

Die folgenden Funktionen stehen in FELIX-Scripts zur Verfügung, jeweils mit einem kurzen Beispiel. Den grundsätzlichen Aufbau eines Scripts beschreibt FELIX Scripts.

 

Nachrichten- und Segmentverarbeitung

function NextSegment(var aName: String): Boolean;

Liest das nächste Segment aus der Quellnachricht. Die Segmentidentifikation (z.B. msh, pid, obx) wird in aName zurückgegeben. Liefert false, wenn kein Segment mehr verfügbar ist.

while NextSegment(aSegment) do

   if aSegment = 'pid' then ...;

function GetData(const aPosition: String): String;

Liefert aus dem aktuell gelesenen Segment die Daten einer Position. Die Position wird als Kette von Indexangaben für Feld, Subfeld, Komponente und Subkomponente angegeben.

aLastName := GetData('5-1-1-1');

procedure First;

Setzt den Segment-Zeiger an den Anfang der Quelldatenmenge zurück. Damit kann die Nachricht ein zweites Mal durchlaufen werden.

First;

while NextSegment(s) do ...;

procedure SaveAndClose(keepMessage: Boolean);

Schreibt die Ergebnisse in die Datenbank und löscht die Nachricht aus dem Puffer (siehe Pufferverhalten), wenn keepMessage = false ist. Im Testmodus wird üblicherweise debugging übergeben, damit die Nachricht erhalten bleibt.

SaveAndClose(debugging);

function Debugging: Boolean;

Liefert in der Testumgebung (Client/Kanaleditor) true zurück und im Produktivbetrieb false. Damit kann das Script Testlogik (z.B. zusätzliche Ausgaben) bedingt aktivieren.

if Debugging then writeln('PID = ' + aPID);

procedure WriteLn(content: Variant);

Schreibt eine Zeile mit dem angegebenen Inhalt in die Log-Datei und in die Debug-Ausgabe. Im Produktivbetrieb erscheint die Zeile im Protokoll.

writeln('Nachricht verarbeitet für: ' + aLastName);

procedure Debug(content: Variant);

Schreibt eine Zeile nur in die Debug-Ausgabe (Konsole des Kanaleditors). Im Produktivbetrieb wirkungslos.

debug(aSegment + ' - Feld 3: ' + GetData('3-1-1-1'));

Hilfsfunktionen

function StrToDateTime(const s, format: string): TDateTime;

Wandelt eine Zeitangabe im angegebenen Format in einen Zeittypen um. Format-Platzhalter: yyyy, mm, dd, hh, nn (Minuten), ss. Bei nicht parsebarem Inhalt wird 0 zurückgegeben.

aBirthDate := StrToDateTime(GetData('7-1-1-1'), 'yyyymmdd');

aTimeStamp := StrToDateTime(GetData('7-1-1-1'), 'yyyymmddhhnn');

function RemoveText(const Source, ToBeRemoved: String): String;

Beseitigt alle Vorkommen einer Teilzeichenkette aus einem String.

s := RemoveText(GetData('5-1-1-1'), 'Dr. ');

function ReplaceText(const Source, ToBeReplaced, ReplaceWith: String): String;

Ersetzt alle Vorkommen einer Teilzeichenkette in einem String durch eine andere.

s := ReplaceText(aText, ',', '.');

function WhichIdentifier(const NewPID, OldPID, firstname, lastname: String): String;

Hilfsfunktion für die Umstellung eines KIS-Systems auf neue Patientennummern. Wenn unter der neuen PID bereits eine Akte mit passendem Namen existiert, wird NewPID geliefert; andernfalls wird auf OldPID zurückgegriffen, sofern dort eine Akte existiert. Sonst immer NewPID.

aPID := WhichIdentifier(GetData('3-1-1-1'), GetData('3-2-1-1'), aFirstName, aLastName);

Patientenakte suchen, anlegen, zusammenführen

function FindSubject(const PID: String): Boolean;

Prüft, ob es einen Patienteneintrag unter der angegebenen KIS-ID (PID) gibt; legt keine Akte an. Wichtig für die Laborzuordnung, um keine unnötigen Akten anzulegen. Wenn die Funktion true liefert, arbeiten alle folgenden Funktionen auf der gefundenen Akte. Liefert sie false, bleibt die Nachricht zur Wiedervorlage im Puffer (siehe Pufferverhalten).

if not FindSubject(aPID) then exit;

function FindSubjectWithBirthdate(const PID: String; birthdate: TDateTime): Boolean;

Arbeitet wie FindSubject, prüft aber zusätzlich das Geburtsdatum. Kann Zuordnungen über die PID sicherer machen.

if not FindSubjectWithBirthdate(aPID, aBirthDate) then exit;

function FindOrCreateSubject(const PID, firstname, lastname: String; birthdate: TDateTime): Boolean;

Sucht einen Patienteneintrag über die KIS-ID (PID) und legt ihn gegebenenfalls an. Alle folgenden Aktionen beziehen sich auf diesen Patienten. Liefert false, wenn die KIS-ID bereits zu einer Akte mit abweichendem Vor- und Nachnamen und abweichendem Geburtsdatum gehört; die Nachricht wird dann verworfen. Ablauf der Suche: FELIX Scripts.

if not FindOrCreateSubject(aPID, aFirstname, aLastName, aBirthDate) then exit;

procedure MergeSubject(const aObsoleteKISID: String);

Kopiert die Daten der mit aObsoleteKISID bezeichneten Akte (KIS-ID) zur aktuellen, über FindSubject bzw. FindOrCreateSubject aktivierten Akte. Stammdaten werden zusammengeführt, bei Items werden nur neuere ins Ziel kopiert. Die abgebende Akte wird archiviert. Im Script kann dies direkt aus dem MRG-Segment von Nachrichten wie A34 und A40 aufgerufen werden. Es wird geprüft, ob Geburtsdatum und wenigstens Vor- oder Nachname zusammenpassen, sonst wird das Kommando abgebrochen.

if (aSegment = 'mrg') and (GetData('1-1-1-1') <> '') then

   MergeSubject(GetData('1-1-1-1'));

Stammdaten und Versicherung

procedure SetSubjectInfo(const aField: String; aContent: variant);

Setzt ein Feld des Stammdatenblattes über seinen Feldnamen. Gängige Feldnamen sind z.B. lastname, firstname, street, zip, city, phone, email.

setSubjectInfo('lastname', aLastName);

Die folgende Tabelle listet die Feldnamen, die in der Stammdatenmaske hinterlegt sind, zusammen mit der dortigen Beschriftung. Sie gelten ebenso für SetSubjectInfoIfEmpty.

Feldname

Maskenbeschriftung

Bedeutung

title

Titel

Akademischer Titel, z.B. Dr., Prof.

name_header

Vorsatzwort

Vorsatzwort des Nachnamens, z.B. von, van der

firstname

Vorname

Vorname

lastname

Nachname

Nachname

name_add

Namenzus.

Namenszusatz, z.B. Freiherr, Graf, jr.

maidenname

Geburtsname

Geburtsname

birthplace

Geboren in

Geburtsort

street

Straße

Straße mit Hausnummer

address_add

Adr.-Zusatz

Adresszusatz, z.B. c/o, Wohnbereich, Etage

address_country_code

Land

Länderkennzeichen vor der PLZ, z.B. D, A, CH

zip

PLZ

Postleitzahl

city

Ort

Wohnort

country

Staatsangehörigkeit

Staatsangehörigkeit des Patienten

phone

Telefon

Telefon privat/Festnetz

remindsms

Mobil

Mobil-/SMS-Nummer für Terminerinnerungen

email

Email

E-Mail-Adresse des Patienten

job

Tätigkeit

Ausgeübte Tätigkeit/Beruf

work

Bei

Arbeitgeber

phone_work

Telefon (dienstlich)

Telefon dienstlich

pvs_ident

PVS-ID

Patienten-ID im Praxisverwaltungssystem

kis_ident

KIS-ID

Patienten-ID im Krankenhausinformationssystem

other_ident

Sonst-ID1

Freie Fremd-ID 1, bei Profil r: Rheumadok-ID

paper_ident

Sonst-ID2

Freie Fremd-ID 2, bei Profil r: DocuMed.Rh-ID

procedure SetSubjectInfoIfEmpty(const aField: String; aContent: variant);

Wie SetSubjectInfo, aber überschreibt nur, wenn das Zielfeld leer ist. Damit bleiben manuell gepflegte Daten erhalten.

setSubjectInfoIfEmpty('phone', GetData('13-1-1-1'));

procedure SetGender(const aValue: String);

Setzt das Geschlecht der aktiven Akte. Übliche Werte: M, W, D.

SetGender(GetData('8-1-1-1'));

procedure SetBirthDate(aValue: TDateTime);

Setzt das Geburtsdatum der aktiven Akte.

SetBirthDate(StrToDateTime(GetData('7-1-1-1'), 'yyyymmdd'));

procedure SetASVStatus(enrolled: Boolean);

Setzt den ASV-Status der aktiven Akte. Das Feld ASV-Status ist per Vorgabe ausgeblendet und muss im Datendictionary sichtbar gemacht werden.

SetASVStatus(true);

procedure AddRelatives(const Line: String);

Fügt eine Zeile zum Stammdaten-Feld Angehörige hinzu. Bestehende Zeilen bleiben erhalten.

AddRelatives('Ehepartner: ' + GetData('3-1-1-1'));

procedure AddDiagnoses(const Line: String);

Fügt eine Zeile zu Dauerdiagnosen hinzu, wenn diese noch nicht enthalten ist bzw. der ICD-10-Code noch nicht in den Dauerdiagnosen vorkommt.

AddDiagnoses('M05.9 G - Rheumatoide Arthritis');

procedure SetInsurance(const IK, aInsNum, MemberNum, InsKind, DMP, VIP, WOP: String);

Setzt die Versicherteninformationen. Vorherige Daten werden ersetzt. Die Versicherung wird wahlweise über das IK oder über die Nummer der Versicherung ermittelt; der Name wird automatisch aus den offiziellen Kostenträger-Stammdaten ausgefüllt, die mit den Programmaktualisierungen mitgepflegt werden.

SetInsurance(GetData('3-1-1-1'), '', GetData('9-1-1-1'), '1', '', '', '');

procedure AssignAddress(const aExternalNum, aTitle, aFirstname, aLastname, aStreet, aZip, aCity, aPhone, aFax, aEmail, aSalutationShort, aSalutationLong, aRoleTitle: String);

Ordnet dem aktuellen Patienten einen mitbehandelnden Arzt zu, allgemeiner: eine beliebige Adresse aus dem Adressbuch. Der Eintrag wird bei Bedarf im Adressbuch angelegt und erscheint anschließend in der Stammdatenmaske unter Pat-Kontakte.

Ein vorhandener Adresseintrag wird in dieser Reihenfolge gesucht:

1.Über aExternalNum, also die Arztnummer des sendenden Systems. Das ist der empfohlene Weg, weil die Nummer eindeutig und stabil ist.

2.Über Vor- und Nachname zusammen mit PLZ und Ort, sofern die Nachricht diese liefert.

3.Über Vor- und Nachname allein. Gibt es mehrere gleichnamige Einträge, wird der älteste verwendet und ein Hinweis ins Schnittstellenprotokoll geschrieben.

Wird nichts gefunden, wird ein neuer Adresseintrag angelegt. Leere Parameter überschreiben dabei nie vorhandene Inhalte, damit manuell gepflegte Angaben wie Telefonnummer oder Anrede nicht von jeder eingehenden Nachricht überschrieben werden. Wird beim Namensabgleich eine externe Nummer mitgeliefert, wird sie am gefundenen Eintrag nachgetragen und steht damit künftig als eindeutiger Schlüssel bereit.

Die Rolle wird über aRoleTitle gesucht, Groß- und Kleinschreibung spielt keine Rolle. Rollen werden hier nie neu angelegt: Ist die Bezeichnung leer oder unbekannt, wird die Rolle Hausarzt verwendet. Eine Umsetzung der Rollenschlüssel des sendenden Systems auf die eigenen Rollenbezeichnungen gehört deshalb ins Script.

Ein Arzt kann in mehreren Rollen geführt werden, jede Rolle ergibt eine eigene Zuordnung. Eine bereits bestehende Zuordnung wird nicht verändert, ein manuell gesetzter Haken für den Briefversand bleibt also bei jeder weiteren Nachricht erhalten.

aSalutationShort und aSalutationLong füllen die Felder Kurzanrede und Lange Anrede des Adresseintrags, also die Anreden, die im Briefkopf und in der Briefanrede verwendet werden. Beide werden von den gängigen Nachrichtenformaten nicht geliefert und bleiben daher meist leer, damit die manuell gepflegten Anreden erhalten bleiben. Sie können im Script aber aus den Namensbestandteilen zusammengesetzt werden, wenn Adressen automatisch angelegt werden sollen.

AssignAddress(GetData('9-1-1-1'), '', GetData('9-1-3-1'),

   GetData('9-1-2-1'), '', '', '', '', '', '',

   '', '', 'Rheumatologe');

Verlaufsdaten und Items

function FindOrCreateVisit(aTimeStamp: TDateTime): Boolean;

Sucht oder erstellt einen Verlaufsdaten-Visit zum aktuellen Patienten. Die Uhrzeit des Zeitstempels wird nicht beachtet - so entsteht nie mehr als ein Visit pro Tag. Dieser Visit ist anschließend Basis für alle Aufrufe von InsertOrUpdateItem mit Verlaufsdaten-Items.

if FindOrCreateVisit(aVisitDate) then

   InsertOrUpdateItem(12345, '160', true);

function FindOrCreateVisitWithTime(aTimeStamp: TDateTime): Boolean;

Wie FindOrCreateVisit, beachtet aber die Uhrzeit - liefert also bei mehreren Zeitstempeln am selben Tag mehrere Visits.

if FindOrCreateVisitWithTime(aVisitDateTime) then ...

function FindOrCreateVisitWithID(aTimeStamp: TDateTime; const aCaseNum: String): Boolean;

Wie FindOrCreateVisitWithTime, bezieht aber zusätzlich die KIS-Fallnummer in die Suche ein. Damit erhält jede Fallnummer ihre eigene Spalte, auch wenn zu einem Besuch mehrere Fallnummern gehören. Gesucht wird in dieser Reihenfolge:

1.Ein Visit mit genau dieser Fallnummer. Ist ein Zeitstempel angegeben, muss zusätzlich der Tag übereinstimmen - Schlüssel ist also Tag + Fallnummer. Dieselbe Fallnummer an einem anderen Tag ergibt somit eine weitere Spalte.

2.Andernfalls eine an diesem Tag bereits vorhandene Spalte ohne Fallnummer. Sie wird übernommen und mit der Fallnummer versehen. Das verhindert eine doppelte Spalte, wenn der Visit schon angelegt war, bevor das KIS ihn geschickt hat.

3.Andernfalls wird ein neuer Visit angelegt.

Der Zeitstempel ist optional: Wird 0 übergeben, entscheidet allein die Fallnummer, unabhängig vom Datum - dieselbe Fallnummer trifft dann immer dieselbe Spalte. Ein in diesem Fall neu angelegter Visit bekommt das heutige Datum.

Die Fallnummer wird von der Funktion selbst in das Item KIS Fallnummer (Typ 10361) geschrieben, ein InsertOrUpdateItem(10361, ...) im Script ist also nicht mehr nötig. Ein bereits gefüllter Wert wird nie überschrieben. Verglichen wird so, wie EMIL die Fallnummer speichert: ohne führende Nullen, ohne Groß-/Kleinschreibung, auf 50 Zeichen gekürzt. Eine leere Fallnummer verhält sich exakt wie FindOrCreateVisitWithTime.

Treffen zwei verschiedene Fallnummern auf dieselbe Minute, bekommt der zweite Visit einen Zähler - eine Akte kann pro Zeitstempel nur einen Visit führen. Der Spaltenkopf zeigt ihn hinter dem Datum an, also 07.08.2026 (1), 07.08.2026 (2) und so weiter. Mehr als 59 Fallnummern auf derselben Minute sind nicht möglich; in diesem Fall liefert die Funktion False und es wird nichts geschrieben.

if FindOrCreateVisitWithID(aVisitDateTime, GetData('19-1-1-1')) then

   InsertOrUpdateItem(12345, '160', true);

procedure InsertOrUpdateItem(aTypeID: Int64; const aStringValue: String; updateExisting: Boolean);

Fügt ein Item ein oder aktualisiert ein vorhandenes, wenn updateExisting wahr ist. Der Wert wird als aStringValue angegeben und wie eine Eingabe über das Eingabegitter in EMIL behandelt. Wenn der angegebene Typ ein Feste-Daten-Item ist, wird es dort verortet und nicht am letzten durch FindOrCreateVisit erzeugten Visit. Labordaten werden hier ignoriert - diese sind über SetOrLearnResult anzulegen.

InsertOrUpdateItem(40001, GetData('5-1-1-1'), true);

procedure InsertOrUpdateChoiceItem(aTypeID: Int64; const aDecodes: String; updateExisting: Boolean);

Wie InsertOrUpdateItem, jedoch für Auswahllisten (Einfach- und Mehrfachauswahl). Statt des internen Codes wird der Decode - also der angezeigte Text - übergeben; die Funktion ermittelt daraus den passenden Code aus der Codeliste des Item-Typs (Groß-/Kleinschreibung und umgebende Leerzeichen werden ignoriert). Bei Mehrfachauswahl-Listen (mlist) kann eine kommagetrennte Liste von Decodes angegeben werden. Nur Auswahllisten (slist/mlist) werden unterstützt. Die Funktion löst nie eine Ausnahme aus: Ein nicht gefundener Decode wird übersprungen; kann kein einziger Decode aufgelöst werden, wird stattdessen ein leerer Wert übertragen.

InsertOrUpdateChoiceItem(12345, GetData('5-1-1-1'), true);

InsertOrUpdateChoiceItem(10031, 'Rheumatoide Arthritis, Osteoporose', true);

Befunde / Labor

procedure SetOrLearnResult(aDate: TDateTime; const aIdent, aValue, aRange, aUnit, aTitle: String);

Setzt ein Befundergebnis. Wird der Ident keinem EMIL-Feld zugeordnet, wird er gelernt und steht künftig zur Zuordnung bereit.

SetOrLearnResult(aResultDate, aResultIdent, aResultValue,

   aResultRange, aResultUnit, aResultTitle);

procedure SetOrLearnOrderResult(aDate: TDateTime; const aIdent, aValue, aRange, aUnit, aTitle, aOrderNum: String);

Analog zu SetOrLearnResult, jedoch mit Auftragsnummer. Dies dient für Fälle, in denen sich die gelieferten Zeitstempel eines Laborauftrags zwischen Initialbefund und Nachlieferung unterscheiden können und Nachlieferungen sonst in einer falschen Spalte landen würden. EMIL speichert mit dem ersten Wert der Auftragsnummer das Datum und nutzt es bei allen folgenden Befunden der Auftragsnummer wieder. Aus Sicherheitsgründen spricht dieser Mechanismus nur an, wenn der gespeicherte und der gelieferte Zeitstempel weniger als 24 h auseinanderliegen. Die Nutzung der Funktion setzt voraus, dass sich Auftragsnummern nie wiederholen! Ggf. sind im Script Merkmale hinzuzufügen, um sie eindeutig zu machen.

SetOrLearnOrderResult(aResultDate, aResultIdent, aResultValue,

   aResultRange, aResultUnit, aResultTitle, aOrderNum);

Eingebettete Dokumente und Bilder

function ImportDocument(const aBase64, aSubtype, aTitle, aCatTitle, aSourceKey: String; aDocDate: TDateTime): Boolean;

Speichert ein in einem OBX-Segment vom Typ ED eingebettetes, base64-kodiertes Dokument oder Bild in die Patientenakte. Bilder (jpeg, png, tiff usw.) werden nach JPEG gewandelt, auf eine Maximalgröße verkleinert und unter Bilder abgelegt; alles andere - insbesondere PDF - unter Scans. Für beide wird automatisch ein Vorschaubild erzeugt. aBase64 sind die Daten (OBX-5.5), aSubtype der MIME-Untertyp (OBX-5.3, z.B. pdf, jpeg, png). aCatTitle ist die Zielkategorie, die bei Bedarf angelegt wird (z.B. Vom KIS). aSourceKey ist ein stabiler Schlüssel zur Dublettenvermeidung (leer = kein Abgleich; empfohlen wird die Auftrags- oder Dokumentnummer). aDocDate ist das Dokumentdatum (0 = heute). Die Funktion liefert true, wenn das Dokument abgelegt wurde oder bereits vorhanden war.

if GetData('2-1-1-1') = 'ED' then

   ImportDocument(GetData('5-1-5-1'), GetData('5-1-3-1'),

     GetData('3-1-2-1'), 'Vom KIS', '', aResultDate);