-- ===================================================================== -- aether-medical / Modul: Intensivstation -- -- Ein Intensivaufenthalt ist hier eine Akte, kein Monitor. -- -- Das System misst nichts. Es kennt keinen Blutdruck, keine Sättigung -- und keinen Alarm. Der Zustand eines Patienten steht genau deshalb -- im Datensatz, weil ein Mediziner ihn dort eingetragen hat — er -- ändert sich nie von selbst, weder durch Zeitablauf noch durch -- irgendeine Rechnung. -- -- Auch Geräte werden nur benannt, nicht gesteuert. Und ein Aufenthalt -- endet erst, wenn jemand ihn beendet: nicht mit der Entlassung, -- nicht mit dem Bett und nicht mit dem Dienstende. -- ===================================================================== Kern.RegistriereModul({ id = 'intensiv', name = 'Intensiv', icon = '📈', reihenfolge = 10, recht = 'intensiv.sehen', beschreibung = 'Intensivaufenthalte, Zustand, Geräte und Verlauf', }) -- --------------------------------------------------------------------- -- Hilfsfunktionen -- --------------------------------------------------------------------- --- Begrenzt einen Text und liefert nil bei leerer Eingabe --- @param wert any Eingabe --- @param laenge number Maximale Zeichenzahl --- @return string|nil local function Text(wert, laenge) if type(wert) ~= 'string' then return nil end local sauber = wert:gsub('^%s+', ''):gsub('%s+$', '') if sauber == '' then return nil end return sauber:sub(1, laenge) end --- Name eines Mitarbeiters für die Anzeige --- @param charakterId number|nil Charakter --- @return string local function NameVon(charakterId) if not charakterId then return 'unbekannt' end local zeilen = MySQL.query.await( 'SELECT firstname, lastname FROM aether_characters WHERE id = ?', { charakterId }) if not zeilen or not zeilen[1] then return 'unbekannt' end return zeilen[1].firstname .. ' ' .. zeilen[1].lastname end --- Prüft einen Zustand gegen die Konfiguration --- @param wert any Eingabe --- @return string|nil Gültige Kennung local function Zustand(wert) local gesucht = tostring(wert or '') for _, eintrag in ipairs(Medizin.Config.Intensivzustaende) do if eintrag.id == gesucht then return eintrag.id end end return nil end --- Anzeigename eines Zustands --- @param kennung string Zustand --- @return string local function ZustandName(kennung) for _, eintrag in ipairs(Medizin.Config.Intensivzustaende) do if eintrag.id == kennung then return eintrag.name end end return tostring(kennung) end --- Baut die Sortierreihenfolge der Zustände für MySQL. --- Sortiert wird nach dem, was Menschen eingetragen haben — das System --- bewertet dabei nichts, es stellt nur das Eingetragene nach oben. --- @return string FIELD(...)-Ausdruck local function ZustandSortierung() local teile = {} for _, eintrag in ipairs(Medizin.Config.Intensivzustaende) do -- Die Kennungen stammen aus der eigenen Konfiguration teile[#teile + 1] = ("'%s'"):format(eintrag.id:gsub("'", '')) end return ('FIELD(i.zustand, %s)'):format(table.concat(teile, ', ')) end --- Lädt einen Intensivaufenthalt mit allen Begleitdaten --- @param intensivId number Aufenthalt --- @return table|nil Zeile local function LadeAufenthalt(intensivId) local zeilen = MySQL.query.await([[ SELECT i.*, TIMESTAMPDIFF(MINUTE, i.aufgenommen_am, COALESCE(i.beendet_am, NOW())) AS liegtSeit, c.firstname, c.lastname, c.dob, z.kennung AS zimmerKennung, z.art AS zimmerArt, s.name AS stationName, a.status AS aufnahmeStatus, a.grund AS aufnahmeGrund FROM medical_intensiv i JOIN aether_characters c ON c.id = i.patient LEFT JOIN medical_zimmer z ON z.id = i.zimmer LEFT JOIN medical_station s ON s.id = z.station LEFT JOIN medical_aufnahme a ON a.id = i.aufnahme WHERE i.id = ? ]], { intensivId }) return zeilen and zeilen[1] or nil end --- Schreibt einen Verlaufseintrag. --- Der Text stammt immer von einem Menschen — das System formuliert --- hier nichts und fasst nichts zusammen. --- @param intensivId number Aufenthalt --- @param text string Wortlaut --- @param charakterId number Verfasser --- @return number Eintrag local function SchreibeVerlauf(intensivId, text, charakterId) return MySQL.insert.await( 'INSERT INTO medical_intensiv_verlauf (intensiv, text, von) VALUES (?, ?, ?)', { intensivId, text, charakterId }) end -- ===================================================================== -- ÜBERSICHT -- ===================================================================== Kern.RegistriereAktion('intensiv', 'uebersicht', nil, function(quelle, mitarbeiter, daten) local ordner = tostring(daten.ordner or 'laufend') local beendet = ordner == 'beendet' local liste = MySQL.query.await(([[ SELECT i.id, i.patient, i.aufnahme, i.zimmer, i.zustand, i.geraete, i.notiz, i.verantwortlich, i.aufgenommen_am, i.aufgenommen_von, i.beendet_am, i.beendet_von, TIMESTAMPDIFF(MINUTE, i.aufgenommen_am, COALESCE(i.beendet_am, NOW())) AS liegtSeit, TIMESTAMPDIFF(MINUTE, COALESCE( (SELECT MAX(v.am) FROM medical_intensiv_verlauf v WHERE v.intensiv = i.id), i.aufgenommen_am), NOW()) AS stillSeit, (SELECT COUNT(*) FROM medical_intensiv_verlauf v WHERE v.intensiv = i.id) AS eintraege, c.firstname, c.lastname, c.dob, p.blutgruppe, p.allergien, p.hinweis AS warnhinweis, z.kennung AS zimmerKennung, s.name AS stationName FROM medical_intensiv i JOIN aether_characters c ON c.id = i.patient LEFT JOIN medical_patient p ON p.`character` = i.patient LEFT JOIN medical_zimmer z ON z.id = i.zimmer LEFT JOIN medical_station s ON s.id = z.station WHERE i.beendet_am IS %s NULL ORDER BY %s LIMIT 100 ]]):format(beendet and 'NOT' or '', beendet and 'i.beendet_am DESC' or (ZustandSortierung() .. ', i.aufgenommen_am'))) or {} local stille = Medizin.Config.Erinnerungen.intensivStilleNach for _, eintrag in ipairs(liste) do eintrag.name = eintrag.firstname .. ' ' .. eintrag.lastname eintrag.geburt = tostring(eintrag.dob):sub(1, 10) eintrag.zustandName = ZustandName(eintrag.zustand) eintrag.liegtSeit = tonumber(eintrag.liegtSeit) or 0 eintrag.stillSeit = tonumber(eintrag.stillSeit) or 0 eintrag.eintraege = tonumber(eintrag.eintraege) or 0 eintrag.verantwortlichName = eintrag.verantwortlich and NameVon(eintrag.verantwortlich) or nil eintrag.aufgenommenVon = NameVon(eintrag.aufgenommen_von) eintrag.beendetVon = eintrag.beendet_von and NameVon(eintrag.beendet_von) or nil -- Nur eine Erinnerung, keine Bewertung der Betreuung eintrag.langeStill = not beendet and eintrag.stillSeit >= stille eintrag.firstname, eintrag.lastname, eintrag.dob = nil, nil, nil eintrag.aufgenommen_von, eintrag.beendet_von = nil, nil end -- Zählwerte über die laufenden Aufenthalte local zaehler = { laufend = tonumber(MySQL.scalar.await( 'SELECT COUNT(*) FROM medical_intensiv WHERE beendet_am IS NULL')) or 0, kritisch = tonumber(MySQL.scalar.await([[ SELECT COUNT(*) FROM medical_intensiv WHERE beendet_am IS NULL AND zustand = 'kritisch' ]])) or 0, ohneArzt = tonumber(MySQL.scalar.await([[ SELECT COUNT(*) FROM medical_intensiv WHERE beendet_am IS NULL AND verantwortlich IS NULL ]])) or 0, beendetHeute = tonumber(MySQL.scalar.await([[ SELECT COUNT(*) FROM medical_intensiv WHERE beendet_am IS NOT NULL AND DATE(beendet_am) = CURDATE() ]])) or 0, } -- Wie viele laufende Aufenthalte haben lange keinen Eintrag bekommen? zaehler.langeStill = tonumber(MySQL.scalar.await(([[ SELECT COUNT(*) FROM medical_intensiv i WHERE i.beendet_am IS NULL AND COALESCE( (SELECT MAX(v.am) FROM medical_intensiv_verlauf v WHERE v.intensiv = i.id), i.aufgenommen_am) < DATE_SUB(NOW(), INTERVAL ? MINUTE) ]]), { stille })) or 0 return { ordner = ordner, liste = liste, zaehler = zaehler, zustaende = Medizin.Config.Intensivzustaende, stilleNach = stille, rechte = { betreuen = Rechte.Hat(mitarbeiter, 'intensiv.betreuen'), }, } end) -- ===================================================================== -- EINZELANSICHT -- ===================================================================== Kern.RegistriereAktion('intensiv', 'oeffnen', nil, function(quelle, mitarbeiter, daten) local intensivId = tonumber(daten.id) if not intensivId then return nil, 'Ungültige Kennung.' end local eintrag = LadeAufenthalt(intensivId) if not eintrag then return nil, 'Intensivaufenthalt nicht gefunden.' end -- Stammdaten, die am Bett gebraucht werden local stamm = MySQL.query.await([[ SELECT blutgruppe, allergien, vorerkrankungen, dauermedikation, hinweis, notfallkontakt, lichtbild FROM medical_patient WHERE `character` = ? ]], { eintrag.patient }) stamm = stamm and stamm[1] or {} -- Der Verlauf — jüngster Eintrag zuerst local verlauf = MySQL.query.await([[ SELECT v.id, v.text, v.am, v.von, c.firstname, c.lastname FROM medical_intensiv_verlauf v LEFT JOIN aether_characters c ON c.id = v.von WHERE v.intensiv = ? ORDER BY v.id DESC LIMIT 100 ]], { intensivId }) or {} for _, zeile in ipairs(verlauf) do zeile.autor = zeile.firstname and (zeile.firstname .. ' ' .. zeile.lastname) or 'unbekannt' zeile.firstname, zeile.lastname, zeile.von = nil, nil, nil end return { aufenthalt = { id = eintrag.id, patient = eintrag.patient, aufnahme = eintrag.aufnahme, name = eintrag.firstname .. ' ' .. eintrag.lastname, geburt = tostring(eintrag.dob):sub(1, 10), zustand = eintrag.zustand, zustandName = ZustandName(eintrag.zustand), geraete = eintrag.geraete, notiz = eintrag.notiz, zimmer = eintrag.zimmer, zimmerKennung = eintrag.zimmerKennung, zimmerArt = eintrag.zimmerArt, stationName = eintrag.stationName, aufnahmeStatus = eintrag.aufnahmeStatus, aufnahmeGrund = eintrag.aufnahmeGrund, liegtSeit = tonumber(eintrag.liegtSeit) or 0, verantwortlich = eintrag.verantwortlich, verantwortlichName = eintrag.verantwortlich and NameVon(eintrag.verantwortlich) or nil, aufgenommenAm = eintrag.aufgenommen_am, aufgenommenVon = NameVon(eintrag.aufgenommen_von), beendetAm = eintrag.beendet_am, beendetVon = eintrag.beendet_von and NameVon(eintrag.beendet_von) or nil, laufend = eintrag.beendet_am == nil, }, stamm = stamm, verlauf = verlauf, zustaende = Medizin.Config.Intensivzustaende, geraeteliste = Medizin.Config.Intensivgeraete, rechte = { betreuen = Rechte.Hat(mitarbeiter, 'intensiv.betreuen'), }, } end) -- ===================================================================== -- AUFNAHME AUF DIE INTENSIVSTATION -- -- Wer auf Intensiv kommt, entscheidet ein Arzt. Kein Zustand, keine -- Diagnose und kein Wert bringt jemanden von selbst hierher. -- ===================================================================== --- Aufgenommene Patienten ohne laufenden Intensivaufenthalt --- sowie die Zimmer, in denen eine Betreuung stattfinden könnte. Kern.RegistriereAktion('intensiv', 'kandidaten', 'intensiv.betreuen', function(quelle, mitarbeiter, daten) local patienten = MySQL.query.await([[ SELECT a.id AS aufnahme, a.patient, a.grund, a.prioritaet, a.station, TIMESTAMPDIFF(MINUTE, a.aufgenommen_am, NOW()) AS imHausSeit, c.firstname, c.lastname, c.dob, p.blutgruppe, p.allergien, p.hinweis AS warnhinweis, z.id AS zimmer, z.kennung AS zimmerKennung, s.name AS stationName FROM medical_aufnahme a JOIN aether_characters c ON c.id = a.patient LEFT JOIN medical_patient p ON p.`character` = a.patient LEFT JOIN medical_zimmer z ON z.id = a.zimmer LEFT JOIN medical_station s ON s.id = z.station WHERE a.status = 'aufgenommen' AND NOT EXISTS ( SELECT 1 FROM medical_intensiv i WHERE i.patient = a.patient AND i.beendet_am IS NULL) ORDER BY a.prioritaet, a.aufgenommen_am LIMIT 100 ]]) or {} for _, eintrag in ipairs(patienten) do eintrag.name = eintrag.firstname .. ' ' .. eintrag.lastname eintrag.geburt = tostring(eintrag.dob):sub(1, 10) eintrag.imHausSeit = tonumber(eintrag.imHausSeit) or 0 eintrag.firstname, eintrag.lastname, eintrag.dob = nil, nil, nil end -- Intensivplätze zur Auswahl. Das Bett selbst verwaltet die -- Stationsverwaltung — hier wird nur festgehalten, wo betreut wird. local zimmer = MySQL.query.await([[ SELECT z.id, z.kennung, z.art, z.status, z.betten, z.hinweis, s.name AS stationName, (SELECT COUNT(*) FROM medical_belegung b WHERE b.zimmer = z.id AND b.frei_am IS NULL) AS belegt FROM medical_zimmer z JOIN medical_station s ON s.id = z.station WHERE s.aktiv = 1 AND z.art IN ('intensiv', 'isolierung') ORDER BY s.sortierung, z.kennung ]]) or {} for _, eintrag in ipairs(zimmer) do eintrag.belegt = tonumber(eintrag.belegt) or 0 eintrag.betten = tonumber(eintrag.betten) or 1 end return { patienten = patienten, zimmer = zimmer } end) Kern.RegistriereAktion('intensiv', 'aufnehmen', 'intensiv.betreuen', function(quelle, mitarbeiter, daten) local aufnahmeId = tonumber(daten.aufnahme) if not aufnahmeId then return nil, 'Kein Patient gewählt.' end local zustand = Zustand(daten.zustand) if not zustand then return nil, 'Bitte einen Zustand eintragen.' end local notiz = Text(daten.notiz, 1000) if not notiz or #notiz < 5 then return nil, 'Bitte festhalten, warum der Patient auf die Intensivstation kommt.' end local aufnahmen = MySQL.query.await([[ SELECT a.id, a.patient, a.status, a.zimmer, c.firstname, c.lastname FROM medical_aufnahme a JOIN aether_characters c ON c.id = a.patient WHERE a.id = ? ]], { aufnahmeId }) if not aufnahmen or not aufnahmen[1] then return nil, 'Aufnahme nicht gefunden.' end local aufnahme = aufnahmen[1] if aufnahme.status ~= 'aufgenommen' then return nil, 'Nur aufgenommene Patienten lassen sich auf die Intensivstation legen.' end -- Zwei laufende Aufenthalte für denselben Patienten ergeben keinen Sinn local laufend = MySQL.scalar.await( 'SELECT id FROM medical_intensiv WHERE patient = ? AND beendet_am IS NULL', { aufnahme.patient }) if laufend then return nil, 'Für diesen Patienten läuft bereits ein Intensivaufenthalt.' end -- Zimmer ist freiwillig: die Betreuung kann auch ohne festen Platz beginnen local zimmerId = tonumber(daten.zimmer) if zimmerId then local zimmer = MySQL.query.await( 'SELECT id FROM medical_zimmer WHERE id = ?', { zimmerId }) if not zimmer or not zimmer[1] then return nil, 'Unbekanntes Zimmer.' end end -- Die Verantwortung übernimmt nur, wer das ausdrücklich angibt local verantwortlich = daten.selbst == true and mitarbeiter.charakterId or nil local geraete = Text(daten.geraete, 512) local intensivId = MySQL.insert.await([[ INSERT INTO medical_intensiv (patient, aufnahme, zimmer, geraete, verantwortlich, zustand, notiz, aufgenommen_von) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ]], { aufnahme.patient, aufnahmeId, zimmerId, geraete, verantwortlich, zustand, notiz, mitarbeiter.charakterId }) Protokoll.Schreibe(mitarbeiter, 'intensiv', 'Intensivaufenthalt eröffnet', { typ = 'intensiv', id = intensivId }, { patient = aufnahme.patient, aufnahme = aufnahmeId, zimmer = zimmerId, zustand = zustand, verantwortlich = verantwortlich }, notiz) Hinweise.Erstelle(nil, { kategorie = 'patient', prioritaet = zustand == 'kritisch' and 'hoch' or 'normal', titel = ('Intensivaufnahme · %s'):format(ZustandName(zustand)), text = ('%s %s wird ab jetzt auf der Intensivstation betreut.') :format(aufnahme.firstname, aufnahme.lastname), zielTyp = 'intensiv', zielId = intensivId, }) -- Ohne zuständigen Arzt bleibt der Aufenthalt sichtbar offen if not verantwortlich then Hinweise.Erstelle(nil, { kategorie = 'patient', prioritaet = 'hoch', titel = 'Intensivpatient ohne zuständigen Arzt', text = ('Für %s %s ist noch niemand eingetragen.') :format(aufnahme.firstname, aufnahme.lastname), zielTyp = 'intensiv', zielId = intensivId, }) end Kern.Loese('intensiv.aufgenommen', intensivId, mitarbeiter) return { id = intensivId } end) -- ===================================================================== -- ZUSTAND -- -- Der Zustand ist eine ärztliche Einschätzung und sonst nichts. Er -- wird von Hand gesetzt, mit Begründung, und der Wortlaut dieser -- Begründung wandert unverändert in den Verlauf. -- ===================================================================== Kern.RegistriereAktion('intensiv', 'zustand', 'intensiv.betreuen', function(quelle, mitarbeiter, daten) local intensivId = tonumber(daten.id) if not intensivId then return nil, 'Ungültige Kennung.' end local neu = Zustand(daten.zustand) if not neu then return nil, 'Unbekannter Zustand.' end local begruendung = Text(daten.grund, 1000) if not begruendung or #begruendung < 3 then return nil, 'Bitte begründen, worauf sich die Einschätzung stützt.' end local eintrag = LadeAufenthalt(intensivId) if not eintrag then return nil, 'Intensivaufenthalt nicht gefunden.' end if eintrag.beendet_am then return nil, 'Dieser Aufenthalt ist bereits beendet.' end MySQL.update.await('UPDATE medical_intensiv SET zustand = ? WHERE id = ?', { neu, intensivId }) -- Der Wortlaut des Arztes bleibt der Wortlaut des Arztes SchreibeVerlauf(intensivId, begruendung, mitarbeiter.charakterId) Protokoll.Schreibe(mitarbeiter, 'intensiv', 'Zustand eingetragen', { typ = 'intensiv', id = intensivId }, { patient = eintrag.patient, von = eintrag.zustand, nach = neu }, begruendung) -- Eine Verschlechterung auf kritisch erfährt das ganze Haus if neu == 'kritisch' and eintrag.zustand ~= 'kritisch' then Hinweise.Erstelle(nil, { kategorie = 'patient', prioritaet = 'kritisch', titel = 'Intensivpatient als kritisch eingetragen', text = ('%s %s — eingetragen von %s.') :format(eintrag.firstname, eintrag.lastname, mitarbeiter.name), zielTyp = 'intensiv', zielId = intensivId, }) end Kern.Loese('intensiv.zustand', intensivId, neu, mitarbeiter) return { ok = true } end) -- ===================================================================== -- VERLAUF -- ===================================================================== Kern.RegistriereAktion('intensiv', 'verlauf', 'intensiv.betreuen', function(quelle, mitarbeiter, daten) local intensivId = tonumber(daten.id) if not intensivId then return nil, 'Ungültige Kennung.' end local text = Text(daten.text, 1000) if not text or #text < 3 then return nil, 'Bitte einen Text eingeben.' end local eintrag = LadeAufenthalt(intensivId) if not eintrag then return nil, 'Intensivaufenthalt nicht gefunden.' end if eintrag.beendet_am then return nil, 'Zu einem beendeten Aufenthalt lässt sich nichts mehr nachtragen.' end local verlaufId = SchreibeVerlauf(intensivId, text, mitarbeiter.charakterId) Protokoll.Schreibe(mitarbeiter, 'intensiv', 'Verlaufseintrag geschrieben', { typ = 'intensiv', id = intensivId }, { patient = eintrag.patient, eintrag = verlaufId }) Kern.Loese('intensiv.verlauf', intensivId, verlaufId, mitarbeiter) return { id = verlaufId } end) -- ===================================================================== -- GERÄTE -- -- Eine Liste von Namen. Das System schliesst nichts an, trennt nichts -- und überwacht nichts — es weiss nur, was jemand notiert hat. -- ===================================================================== Kern.RegistriereAktion('intensiv', 'geraete', 'intensiv.betreuen', function(quelle, mitarbeiter, daten) local intensivId = tonumber(daten.id) if not intensivId then return nil, 'Ungültige Kennung.' end local eintrag = LadeAufenthalt(intensivId) if not eintrag then return nil, 'Intensivaufenthalt nicht gefunden.' end if eintrag.beendet_am then return nil, 'Dieser Aufenthalt ist bereits beendet.' end -- Leere Eingabe heisst: es ist nichts mehr angeschlossen local geraete = Text(daten.geraete, 512) MySQL.update.await('UPDATE medical_intensiv SET geraete = ? WHERE id = ?', { geraete, intensivId }) Protokoll.Schreibe(mitarbeiter, 'intensiv', 'Geräte eingetragen', { typ = 'intensiv', id = intensivId }, { patient = eintrag.patient, vorher = eintrag.geraete, nachher = geraete }) return { ok = true } end) -- ===================================================================== -- ZUSTÄNDIGKEIT -- -- Verantwortung wird übernommen oder übertragen, nie zugeteilt. -- ===================================================================== --- Wer im Dienst darf einen Intensivaufenthalt verantworten? Kern.RegistriereAktion('intensiv', 'betreuer', 'intensiv.betreuen', function(quelle, mitarbeiter, daten) local liste = {} for _, eintrag in pairs(Dienst.AlleImDienst()) do if Rechte.Hat(eintrag, 'intensiv.betreuen') then liste[#liste + 1] = { charakterId = eintrag.charakterId, name = eintrag.name, rolleName = eintrag.rolleName, personalnummer = eintrag.personalnummer, funktion = eintrag.funktion, status = eintrag.status, selbst = eintrag.charakterId == mitarbeiter.charakterId, } end end table.sort(liste, function(a, b) return tostring(a.name) < tostring(b.name) end) return { liste = liste } end) Kern.RegistriereAktion('intensiv', 'verantwortlich', 'intensiv.betreuen', function(quelle, mitarbeiter, daten) local intensivId = tonumber(daten.id) if not intensivId then return nil, 'Ungültige Kennung.' end local eintrag = LadeAufenthalt(intensivId) if not eintrag then return nil, 'Intensivaufenthalt nicht gefunden.' end if eintrag.beendet_am then return nil, 'Dieser Aufenthalt ist bereits beendet.' end -- Ohne Ziel wird die Zuständigkeit niedergelegt local zielId = tonumber(daten.charakter) if zielId then local zielQuelle = Dienst.QuelleVonCharakter(zielId) local ziel = zielQuelle and Dienst.Hole(zielQuelle) if not ziel then return nil, 'Diese Person ist nicht im Dienst.' end if not Rechte.Hat(ziel, 'intensiv.betreuen') then return nil, 'Diese Person darf keinen Intensivaufenthalt verantworten.' end else local grund = Text(daten.grund, 255) if not grund then return nil, 'Bitte angeben, warum die Zuständigkeit niedergelegt wird.' end end MySQL.update.await('UPDATE medical_intensiv SET verantwortlich = ? WHERE id = ?', { zielId, intensivId }) Protokoll.Schreibe(mitarbeiter, 'intensiv', zielId and 'Zuständigkeit übernommen oder übertragen' or 'Zuständigkeit niedergelegt', { typ = 'intensiv', id = intensivId }, { patient = eintrag.patient, vorher = eintrag.verantwortlich, nachher = zielId }, Text(daten.grund, 255)) if zielId and zielId ~= mitarbeiter.charakterId then -- Die betroffene Person erfährt es unmittelbar Hinweise.Erstelle({ charakterId = zielId }, { kategorie = 'patient', prioritaet = 'hoch', titel = 'Du bist jetzt für einen Intensivpatienten zuständig', text = ('%s %s — eingetragen von %s.') :format(eintrag.firstname, eintrag.lastname, mitarbeiter.name), zielTyp = 'intensiv', zielId = intensivId, }) end if not zielId then Hinweise.Erstelle(nil, { kategorie = 'patient', prioritaet = 'hoch', titel = 'Intensivpatient ohne zuständigen Arzt', text = ('Für %s %s ist niemand mehr eingetragen.') :format(eintrag.firstname, eintrag.lastname), zielTyp = 'intensiv', zielId = intensivId, }) end return { ok = true } end) -- ===================================================================== -- AUFENTHALT BEENDEN -- -- Beendet ausschliesslich die Intensivbetreuung. Der Patient bleibt -- aufgenommen, sein Bett bleibt belegt, und keine Behandlung wird -- dadurch abgeschlossen. -- ===================================================================== Kern.RegistriereAktion('intensiv', 'beenden', 'intensiv.betreuen', function(quelle, mitarbeiter, daten) local intensivId = tonumber(daten.id) if not intensivId then return nil, 'Ungültige Kennung.' end local grund = Text(daten.grund, 1000) if not grund or #grund < 5 then return nil, 'Das Ende der Intensivbetreuung erfordert eine Begründung.' end local eintrag = LadeAufenthalt(intensivId) if not eintrag then return nil, 'Intensivaufenthalt nicht gefunden.' end if eintrag.beendet_am then return nil, 'Dieser Aufenthalt ist bereits beendet.' end -- Ein kritischer Zustand hält nicht auf, wird aber festgehalten local warKritisch = eintrag.zustand == 'kritisch' MySQL.update.await([[ UPDATE medical_intensiv SET beendet_am = NOW(), beendet_von = ? WHERE id = ? ]], { mitarbeiter.charakterId, intensivId }) -- Die Begründung schliesst den Verlauf mit den Worten des Arztes ab SchreibeVerlauf(intensivId, grund, mitarbeiter.charakterId) Protokoll.Schreibe(mitarbeiter, 'intensiv', 'Intensivaufenthalt beendet', { typ = 'intensiv', id = intensivId }, { patient = eintrag.patient, zustand = eintrag.zustand, warKritisch = warKritisch }, grund) Hinweise.Erstelle(nil, { kategorie = 'patient', prioritaet = warKritisch and 'hoch' or 'normal', titel = 'Intensivbetreuung beendet', text = ('%s %s — der Patient bleibt aufgenommen, Bett und Behandlungen sind unberührt.') :format(eintrag.firstname, eintrag.lastname), zielTyp = eintrag.aufnahme and 'aufnahme' or 'intensiv', zielId = eintrag.aufnahme or intensivId, }) Kern.Loese('intensiv.beendet', intensivId, mitarbeiter) return { ok = true, warKritisch = warKritisch } end) -- --------------------------------------------------------------------- -- Schnittstelle für andere Ressourcen -- --------------------------------------------------------------------- --- Liegt dieser Patient gerade auf der Intensivstation? --- Reine Auskunft — keine Ressource kann darüber jemanden aufnehmen, --- entlassen oder seinen Zustand ändern. --- @param patientId number Charakter --- @return table|nil { id, zustand, zimmer, seit, verantwortlich } exports('HoleIntensivaufenthalt', function(patientId) if not tonumber(patientId) then return nil end local zeilen = MySQL.query.await([[ SELECT i.id, i.zustand, i.aufgenommen_am, i.verantwortlich, z.kennung AS zimmer FROM medical_intensiv i LEFT JOIN medical_zimmer z ON z.id = i.zimmer WHERE i.patient = ? AND i.beendet_am IS NULL ORDER BY i.id DESC LIMIT 1 ]], { tonumber(patientId) }) if not zeilen or not zeilen[1] then return nil end return { id = zeilen[1].id, zustand = zeilen[1].zustand, zimmer = zeilen[1].zimmer, seit = zeilen[1].aufgenommen_am, verantwortlich = zeilen[1].verantwortlich and NameVon(zeilen[1].verantwortlich) or nil, } end)