- aether-medical: Stationen/Belegung, Intensivstation, Blutbank, Fuhrpark, Nachrichten/Aushänge, Berichte und Textbausteine (server + NUI) - aether-admin: vollständiges Server-Admin-Panel als echtes FiveM-Resource, an aether-core gekoppelt (Rechte über aether_users.admin_group), mit WebRTC-Live-Kameras (Bildschirmfreigabe) und separatem Media-Server (SFU) - Prototypen admin/ vervollständigt - SQL-Schema aether_admin.sql - Docker-Compose mit MariaDB und idempotenter Auto-Migration (schema_migrations) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
485 lines
22 KiB
Lua
485 lines
22 KiB
Lua
-- =====================================================================
|
|
-- aether-medical — Hinweise und Fristenüberwachung
|
|
--
|
|
-- Dies ist der einzige Teil des Systems, der von selbst tätig wird —
|
|
-- und er tut ausschliesslich eines: ERINNERN.
|
|
--
|
|
-- Kein Hinweis nimmt einen Patienten auf, entlässt ihn, gibt ein
|
|
-- Medikament aus, wirft eine Blutkonserve weg oder schliesst eine
|
|
-- Dokumentation ab. Jede Frist läuft ab, ohne dass etwas passiert,
|
|
-- bis ein Mensch entscheidet.
|
|
-- =====================================================================
|
|
|
|
Hinweise = {}
|
|
|
|
-- Bereits gemeldete Fristen, damit nicht im Minutentakt gewarnt wird:
|
|
-- [schluessel] = { [stufe] = true }
|
|
local gemeldet = {}
|
|
|
|
--- Erstellt einen Hinweis
|
|
--- @param ziel table|nil { charakterId? } — ohne charakterId geht er an alle im Dienst
|
|
--- @param daten table { kategorie, prioritaet?, titel, text?, zielTyp?, zielId? }
|
|
function Hinweise.Erstelle(ziel, daten)
|
|
local id = MySQL.insert.await([[
|
|
INSERT INTO medical_hinweis
|
|
(`character`, kategorie, prioritaet, titel, text, ziel_typ, ziel_id)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
]], {
|
|
ziel and ziel.charakterId or nil,
|
|
daten.kategorie or 'system',
|
|
daten.prioritaet or 'normal',
|
|
daten.titel,
|
|
daten.text,
|
|
daten.zielTyp,
|
|
daten.zielId and tostring(daten.zielId) or nil,
|
|
})
|
|
|
|
-- Betroffene Clients sofort informieren.
|
|
-- Die Feldnamen entsprechen bewusst denen aus Hinweise.Lade, damit ein
|
|
-- frisch gemeldeter Hinweis genauso anklickbar ist wie ein geladener.
|
|
local paket = {
|
|
id = id,
|
|
kategorie = daten.kategorie or 'system',
|
|
prioritaet = daten.prioritaet or 'normal',
|
|
titel = daten.titel,
|
|
text = daten.text,
|
|
zielTyp = daten.zielTyp,
|
|
zielId = daten.zielId,
|
|
}
|
|
|
|
if ziel and ziel.charakterId then
|
|
local quelle = Dienst.QuelleVonCharakter(ziel.charakterId)
|
|
if quelle then
|
|
TriggerClientEvent('aether:medical:hinweis', quelle, paket)
|
|
end
|
|
else
|
|
for quelle in pairs(Dienst.AlleImDienst()) do
|
|
TriggerClientEvent('aether:medical:hinweis', quelle, paket)
|
|
end
|
|
end
|
|
|
|
return id
|
|
end
|
|
|
|
--- Lädt die letzten Hinweise eines Mitarbeiters
|
|
--- @param charakterId number Charakter
|
|
--- @param limit number|nil Anzahl
|
|
--- @return table
|
|
function Hinweise.Lade(charakterId, limit)
|
|
local zeilen = MySQL.query.await([[
|
|
SELECT * FROM medical_hinweis
|
|
WHERE (`character` = ? OR `character` IS NULL)
|
|
ORDER BY id DESC LIMIT ?
|
|
]], { charakterId, limit or 30 }) or {}
|
|
|
|
-- Sprungziel auf die Schreibweise der Oberfläche bringen
|
|
for _, eintrag in ipairs(zeilen) do
|
|
eintrag.zielTyp = eintrag.ziel_typ
|
|
eintrag.zielId = eintrag.ziel_id
|
|
eintrag.ziel_typ, eintrag.ziel_id = nil, nil
|
|
end
|
|
|
|
return zeilen
|
|
end
|
|
|
|
--- Markiert einen Hinweis als gelesen
|
|
function Hinweise.MarkiereGelesen(charakterId, hinweisId)
|
|
MySQL.update([[
|
|
UPDATE medical_hinweis SET gelesen = 1
|
|
WHERE id = ? AND (`character` = ? OR `character` IS NULL)
|
|
]], { hinweisId, charakterId })
|
|
end
|
|
|
|
--- Meldet eine Frist genau einmal je Stufe
|
|
--- @param schluessel string Eindeutige Kennung des Vorgangs
|
|
--- @param stufe any Stufe der Erinnerung
|
|
--- @return boolean true, wenn jetzt gemeldet werden soll
|
|
local function ErstmalsMelden(schluessel, stufe)
|
|
gemeldet[schluessel] = gemeldet[schluessel] or {}
|
|
if gemeldet[schluessel][stufe] then return false end
|
|
gemeldet[schluessel][stufe] = true
|
|
return true
|
|
end
|
|
|
|
--- Merkt eine Erinnerung als bereits erledigt vor.
|
|
--- Ein Modul, das selbst sofort benachrichtigt, verhindert damit, dass
|
|
--- die Fristenprüfung die gleiche Sache kurz darauf noch einmal meldet.
|
|
--- @param schluessel string Eindeutige Kennung des Vorgangs
|
|
--- @param stufe any Stufe der Erinnerung
|
|
function Hinweise.AlsGemeldet(schluessel, stufe)
|
|
gemeldet[schluessel] = gemeldet[schluessel] or {}
|
|
gemeldet[schluessel][stufe] = true
|
|
end
|
|
|
|
-- ---------------------------------------------------------------------
|
|
-- Fristenüberwachung
|
|
--
|
|
-- Läuft im Hintergrund. Jeder Block hier endet mit einem Hinweis —
|
|
-- niemals mit einem UPDATE auf einen medizinischen Vorgang.
|
|
-- ---------------------------------------------------------------------
|
|
CreateThread(function()
|
|
Wait(5000)
|
|
|
|
while true do
|
|
Wait(Medizin.Config.Erinnerungen.pruefIntervall)
|
|
|
|
-- --- Wartende Patienten ---
|
|
local wartend = MySQL.query.await([[
|
|
SELECT a.id, a.patient, a.prioritaet, a.grund,
|
|
TIMESTAMPDIFF(MINUTE, a.aufgenommen_am, NOW()) AS wartet,
|
|
c.firstname, c.lastname
|
|
FROM medical_aufnahme a
|
|
JOIN aether_characters c ON c.id = a.patient
|
|
WHERE a.status = 'wartend'
|
|
]]) or {}
|
|
|
|
for _, eintrag in ipairs(wartend) do
|
|
local wartet = tonumber(eintrag.wartet) or 0
|
|
local schluessel = 'warte_' .. eintrag.id
|
|
|
|
-- Höchste erreichte Stufe melden, nicht jede einzeln
|
|
local stufe = nil
|
|
for _, grenze in ipairs(Medizin.Config.Erinnerungen.warteZeitStufen) do
|
|
if wartet >= grenze then stufe = grenze end
|
|
end
|
|
|
|
if stufe and ErstmalsMelden(schluessel, stufe) then
|
|
Hinweise.Erstelle(nil, {
|
|
kategorie = 'patient',
|
|
prioritaet = tonumber(eintrag.prioritaet) <= 2 and 'hoch' or 'normal',
|
|
titel = ('Patient wartet seit %d Minuten'):format(stufe),
|
|
text = ('%s %s — %s'):format(eintrag.firstname, eintrag.lastname,
|
|
tostring(eintrag.grund):sub(1, 80)),
|
|
zielTyp = 'aufnahme', zielId = eintrag.id,
|
|
})
|
|
end
|
|
end
|
|
|
|
-- --- Geplante Operationen ---
|
|
local operationen = MySQL.query.await([[
|
|
SELECT o.id, o.kennung, o.art, o.patient,
|
|
TIMESTAMPDIFF(MINUTE, NOW(), o.geplant_fuer) AS rest,
|
|
c.firstname, c.lastname
|
|
FROM medical_operation o
|
|
JOIN aether_characters c ON c.id = o.patient
|
|
WHERE o.status = 'geplant' AND o.geplant_fuer IS NOT NULL
|
|
AND o.geplant_fuer > DATE_SUB(NOW(), INTERVAL 2 HOUR)
|
|
]]) or {}
|
|
|
|
for _, operation in ipairs(operationen) do
|
|
local rest = tonumber(operation.rest) or 0
|
|
local schluessel = 'op_' .. operation.id
|
|
|
|
for _, vorlauf in ipairs(Medizin.Config.Erinnerungen.opVorlauf) do
|
|
if rest <= vorlauf and rest > 0 and ErstmalsMelden(schluessel, vorlauf) then
|
|
Hinweise.Erstelle(nil, {
|
|
kategorie = 'op', prioritaet = 'normal',
|
|
titel = ('Operation beginnt in %d Minuten'):format(vorlauf),
|
|
text = ('%s — %s (%s %s)'):format(operation.kennung, operation.art,
|
|
operation.firstname, operation.lastname),
|
|
zielTyp = 'operation', zielId = operation.id,
|
|
})
|
|
break
|
|
end
|
|
end
|
|
|
|
-- Der geplante Zeitpunkt ist erreicht — die OP startet trotzdem nicht
|
|
if rest <= 0 and ErstmalsMelden(schluessel, 'faellig') then
|
|
Hinweise.Erstelle(nil, {
|
|
kategorie = 'op', prioritaet = 'hoch',
|
|
titel = 'Geplante Operation ist fällig',
|
|
text = ('%s — %s. Beginn muss vom OP-Team eingetragen werden.')
|
|
:format(operation.kennung, operation.art),
|
|
zielTyp = 'operation', zielId = operation.id,
|
|
})
|
|
end
|
|
end
|
|
|
|
-- --- Offene Behandlungsdokumentationen ---
|
|
local offeneDoku = MySQL.query.await([[
|
|
SELECT b.id, b.kennung, b.erstellt_von, c.firstname, c.lastname
|
|
FROM medical_behandlung b
|
|
JOIN aether_characters c ON c.id = b.patient
|
|
WHERE b.status = 'laufend'
|
|
AND b.erstellt_am < DATE_SUB(NOW(), INTERVAL ? MINUTE)
|
|
]], { Medizin.Config.Erinnerungen.dokuOffenNach }) or {}
|
|
|
|
for _, doku in ipairs(offeneDoku) do
|
|
if ErstmalsMelden('doku_' .. doku.id, 'offen') then
|
|
Hinweise.Erstelle({ charakterId = doku.erstellt_von }, {
|
|
kategorie = 'doku', prioritaet = 'normal',
|
|
titel = 'Dokumentation fehlt',
|
|
text = ('%s (%s %s) ist noch nicht abgeschlossen.')
|
|
:format(doku.kennung, doku.firstname, doku.lastname),
|
|
zielTyp = 'behandlung', zielId = doku.id,
|
|
})
|
|
end
|
|
end
|
|
|
|
-- --- Intensivpatienten ohne frischen Verlaufseintrag ---
|
|
--
|
|
-- Erinnert daran, dass jemand nachschauen sollte. Das System
|
|
-- schaut nicht nach, misst nichts und ändert keinen Zustand.
|
|
local intensiv = MySQL.query.await([[
|
|
SELECT i.id, i.patient, i.zustand, i.verantwortlich,
|
|
c.firstname, c.lastname,
|
|
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
|
|
FROM medical_intensiv i
|
|
JOIN aether_characters c ON c.id = i.patient
|
|
WHERE i.beendet_am IS NULL
|
|
]]) or {}
|
|
|
|
for _, aufenthalt in ipairs(intensiv) do
|
|
local still = tonumber(aufenthalt.stillSeit) or 0
|
|
|
|
-- Die Stufe enthält die Anzahl der Einträge: nach jedem neuen
|
|
-- Eintrag beginnt die Erinnerung von vorn.
|
|
local stufe = 'still_' .. tostring(aufenthalt.eintraege)
|
|
|
|
if still >= Medizin.Config.Erinnerungen.intensivStilleNach
|
|
and ErstmalsMelden('intensiv_' .. aufenthalt.id, stufe) then
|
|
-- Wer zuständig ist, wird persönlich erinnert; sonst das ganze Haus
|
|
local ziel = aufenthalt.verantwortlich
|
|
and { charakterId = aufenthalt.verantwortlich } or nil
|
|
|
|
Hinweise.Erstelle(ziel, {
|
|
kategorie = 'patient',
|
|
prioritaet = aufenthalt.zustand == 'kritisch' and 'hoch' or 'normal',
|
|
titel = ('Intensivverlauf seit %d Minuten ohne Eintrag'):format(still),
|
|
text = ('%s %s — zuletzt dokumentiert vor %d Minuten.')
|
|
:format(aufenthalt.firstname, aufenthalt.lastname, still),
|
|
zielTyp = 'intensiv', zielId = aufenthalt.id,
|
|
})
|
|
end
|
|
end
|
|
|
|
-- --- Laborergebnisse ohne Bewertung ---
|
|
local befunde = MySQL.query.await([[
|
|
SELECT l.id, l.kennung, l.art, l.auftrag_von, c.firstname, c.lastname
|
|
FROM medical_labor l
|
|
JOIN aether_characters c ON c.id = l.patient
|
|
WHERE l.status = 'fertig' AND l.befund IS NULL
|
|
]]) or {}
|
|
|
|
for _, labor in ipairs(befunde) do
|
|
if ErstmalsMelden('labor_' .. labor.id, 'fertig') then
|
|
Hinweise.Erstelle({ charakterId = labor.auftrag_von }, {
|
|
kategorie = 'labor', prioritaet = 'normal',
|
|
titel = 'Laborergebnis verfügbar',
|
|
text = ('%s (%s) für %s %s — Bewertung steht aus.')
|
|
:format(labor.kennung, labor.art, labor.firstname, labor.lastname),
|
|
zielTyp = 'labor', zielId = labor.id,
|
|
})
|
|
end
|
|
end
|
|
|
|
-- --- Medikamente: Mindestbestand und Verfall ---
|
|
local medikamente = MySQL.query.await([[
|
|
SELECT id, kennung, name, bestand, mindestbestand, einheit,
|
|
DATEDIFF(verfaellt_am, CURDATE()) AS tage
|
|
FROM medical_medikament
|
|
WHERE aktiv = 1
|
|
AND (bestand <= mindestbestand
|
|
OR (verfaellt_am IS NOT NULL
|
|
AND verfaellt_am <= DATE_ADD(CURDATE(), INTERVAL ? DAY)))
|
|
]], { Medizin.Config.Erinnerungen.medikamentVorlaufTage }) or {}
|
|
|
|
for _, medikament in ipairs(medikamente) do
|
|
local schluessel = 'med_' .. medikament.id
|
|
|
|
if medikament.bestand <= medikament.mindestbestand
|
|
and ErstmalsMelden(schluessel, 'bestand') then
|
|
Hinweise.Erstelle(nil, {
|
|
kategorie = 'medikament',
|
|
prioritaet = medikament.bestand <= 0 and 'hoch' or 'normal',
|
|
titel = medikament.bestand <= 0 and 'Medikament nicht vorrätig'
|
|
or 'Medikament fast leer',
|
|
text = ('%s — Bestand %d %s (Mindestbestand %d).')
|
|
:format(medikament.name, medikament.bestand,
|
|
medikament.einheit, medikament.mindestbestand),
|
|
zielTyp = 'medikament', zielId = medikament.id,
|
|
})
|
|
end
|
|
|
|
local tage = tonumber(medikament.tage)
|
|
if tage and tage <= Medizin.Config.Erinnerungen.medikamentVorlaufTage
|
|
and ErstmalsMelden(schluessel, 'verfall') then
|
|
Hinweise.Erstelle(nil, {
|
|
kategorie = 'medikament', prioritaet = 'normal',
|
|
titel = tage <= 0 and 'Medikament abgelaufen' or 'Medikament läuft ab',
|
|
text = ('%s — %s. Entscheidung über die Entnahme trifft die Apotheke.')
|
|
:format(medikament.name,
|
|
tage <= 0 and 'Verfallsdatum überschritten'
|
|
or ('noch ' .. tage .. ' Tage')),
|
|
zielTyp = 'medikament', zielId = medikament.id,
|
|
})
|
|
end
|
|
end
|
|
|
|
-- --- Blutkonserven kurz vor Ablauf ---
|
|
local konserven = MySQL.query.await([[
|
|
SELECT id, konserve, blutgruppe,
|
|
DATEDIFF(verfaellt_am, CURDATE()) AS tage
|
|
FROM medical_blut
|
|
WHERE status IN ('vorraetig', 'reserviert')
|
|
AND verfaellt_am IS NOT NULL
|
|
AND verfaellt_am <= DATE_ADD(CURDATE(), INTERVAL ? DAY)
|
|
]], { Medizin.Config.Erinnerungen.blutVorlaufTage }) or {}
|
|
|
|
for _, konserve in ipairs(konserven) do
|
|
local tage = tonumber(konserve.tage) or 0
|
|
if ErstmalsMelden('blut_' .. konserve.id, tage <= 0 and 'abgelaufen' or 'bald') then
|
|
Hinweise.Erstelle(nil, {
|
|
kategorie = 'blut',
|
|
prioritaet = tage <= 0 and 'hoch' or 'normal',
|
|
titel = tage <= 0 and 'Blutkonserve abgelaufen' or 'Blutkonserve läuft ab',
|
|
text = ('%s (%s) — %s. Verwerfen muss jemand von Hand.')
|
|
:format(konserve.konserve, konserve.blutgruppe,
|
|
tage <= 0 and 'Ablaufdatum überschritten'
|
|
or ('noch ' .. tage .. ' Tage')),
|
|
zielTyp = 'blut', zielId = konserve.id,
|
|
})
|
|
end
|
|
end
|
|
|
|
-- --- Blutgruppen mit knappem Bestand ---
|
|
--
|
|
-- Erinnert, dass nachbestellt werden sollte. Das System
|
|
-- bestellt nichts und gibt nichts frei.
|
|
for _, gruppe in ipairs(Medizin.Config.Blutgruppen) do
|
|
local vorraetig = tonumber(MySQL.scalar.await([[
|
|
SELECT COUNT(*) FROM medical_blut
|
|
WHERE blutgruppe = ? AND status = 'vorraetig'
|
|
]], { gruppe })) or 0
|
|
|
|
-- Die Stufe ist der Bestand selbst: jede neue Tiefe meldet sich
|
|
-- einmal, ein wieder aufgefüllter Bestand meldet sich nicht.
|
|
if vorraetig <= Medizin.Config.Erinnerungen.blutMindestbestand
|
|
and ErstmalsMelden('blutbestand_' .. gruppe, tostring(vorraetig)) then
|
|
Hinweise.Erstelle(nil, {
|
|
kategorie = 'blut',
|
|
prioritaet = vorraetig <= 0 and 'hoch' or 'normal',
|
|
titel = vorraetig <= 0 and ('Blutgruppe %s nicht vorrätig'):format(gruppe)
|
|
or ('Blutgruppe %s wird knapp'):format(gruppe),
|
|
text = ('Noch %d Konserve(n) im Bestand (Mindestbestand %d).')
|
|
:format(vorraetig, Medizin.Config.Erinnerungen.blutMindestbestand),
|
|
})
|
|
end
|
|
end
|
|
|
|
-- --- Fahrzeuge mit gemeldeten Auffälligkeiten ---
|
|
--
|
|
-- Erinnert an das, was der Fahrer gemeldet hat. Kein Hinweis
|
|
-- setzt den Status, schickt ein Fahrzeug in die Werkstatt oder
|
|
-- nimmt es aus dem Dienst — das trägt ein Mensch ein.
|
|
local fahrzeuge = MySQL.query.await([[
|
|
SELECT id, kennzeichen, bezeichnung, tank, zustand
|
|
FROM medical_fahrzeug
|
|
WHERE status IN ('verfuegbar', 'im_einsatz')
|
|
AND gemeldet_am IS NOT NULL
|
|
AND gemeldet_am > DATE_SUB(NOW(), INTERVAL 1 HOUR)
|
|
]]) or {}
|
|
|
|
for _, fahrzeug in ipairs(fahrzeuge) do
|
|
local tank = tonumber(fahrzeug.tank)
|
|
local zustand = tonumber(fahrzeug.zustand)
|
|
|
|
-- Die Stufe ist ein Zehnerband: so meldet sich ein sinkender
|
|
-- Wert höchstens zweimal und nicht bei jedem Prozentpunkt.
|
|
if tank and tank <= Medizin.Config.Erinnerungen.fahrzeugTankUnter
|
|
and ErstmalsMelden('fahrzeug_' .. fahrzeug.id,
|
|
'tank_' .. tostring(math.floor(tank / 10))) then
|
|
Hinweise.Erstelle(nil, {
|
|
kategorie = 'system',
|
|
prioritaet = tank <= 5 and 'hoch' or 'normal',
|
|
titel = ('Tankstand gemeldet · %s'):format(fahrzeug.bezeichnung),
|
|
text = ('%s (%s) — zuletzt %d %% gemeldet.')
|
|
:format(fahrzeug.bezeichnung, fahrzeug.kennzeichen, math.floor(tank)),
|
|
zielTyp = 'fahrzeug', zielId = fahrzeug.id,
|
|
})
|
|
end
|
|
|
|
if zustand and zustand <= Medizin.Config.Erinnerungen.fahrzeugZustandUnter
|
|
and ErstmalsMelden('fahrzeug_' .. fahrzeug.id,
|
|
'zustand_' .. tostring(math.floor(zustand / 10))) then
|
|
Hinweise.Erstelle(nil, {
|
|
kategorie = 'system',
|
|
prioritaet = zustand <= 25 and 'hoch' or 'normal',
|
|
titel = ('Fahrzeugschaden gemeldet · %s'):format(fahrzeug.bezeichnung),
|
|
text = ('%s (%s) — Zustand zuletzt %d %%. Ob es in die Werkstatt muss, entscheidet die Wartung.')
|
|
:format(fahrzeug.bezeichnung, fahrzeug.kennzeichen, math.floor(zustand)),
|
|
zielTyp = 'fahrzeug', zielId = fahrzeug.id,
|
|
})
|
|
end
|
|
end
|
|
|
|
-- --- Aushänge mit Kenntnisnahmefrist ---
|
|
local fristen = MySQL.query.await([[
|
|
SELECT a.id, a.titel, a.station,
|
|
TIMESTAMPDIFF(MINUTE, NOW(), a.frist) AS rest
|
|
FROM medical_aushang a
|
|
WHERE a.aktiv = 1 AND a.kenntnispflicht = 1 AND a.frist IS NOT NULL
|
|
AND a.frist > DATE_SUB(NOW(), INTERVAL 1 DAY)
|
|
]]) or {}
|
|
|
|
for _, aushang in ipairs(fristen) do
|
|
local rest = tonumber(aushang.rest) or 0
|
|
local stufe = rest <= 0 and 'abgelaufen'
|
|
or (rest <= Medizin.Config.Erinnerungen.aushangVorwarnung and 'bald')
|
|
or nil
|
|
|
|
if stufe and ErstmalsMelden('aushang_' .. aushang.id, stufe) then
|
|
-- Nur ansprechen, wer noch nicht bestätigt hat
|
|
for _, mitarbeiter in pairs(Dienst.AlleImDienst()) do
|
|
local passt = aushang.station == nil or aushang.station == mitarbeiter.station
|
|
if passt then
|
|
local schon = MySQL.scalar.await([[
|
|
SELECT 1 FROM medical_aushang_kenntnis
|
|
WHERE aushang = ? AND `character` = ?
|
|
]], { aushang.id, mitarbeiter.charakterId })
|
|
|
|
if not schon then
|
|
Hinweise.Erstelle({ charakterId = mitarbeiter.charakterId }, {
|
|
kategorie = 'system',
|
|
prioritaet = stufe == 'abgelaufen' and 'hoch' or 'normal',
|
|
titel = stufe == 'abgelaufen'
|
|
and 'Kenntnisnahme überfällig' or 'Kenntnisnahme offen',
|
|
text = ('„%s" — bitte zur Kenntnis nehmen.'):format(aushang.titel),
|
|
zielTyp = 'aushang', zielId = aushang.id,
|
|
})
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
-- ---------------------------------------------------------------------
|
|
-- Aufräumen abgeschlossener Vorgänge
|
|
-- ---------------------------------------------------------------------
|
|
Kern.Abonniere('aufnahme.entlassen', function(aufnahmeId)
|
|
gemeldet['warte_' .. tostring(aufnahmeId)] = nil
|
|
end)
|
|
|
|
Kern.Abonniere('aufnahme.aufgenommen', function(aufnahmeId)
|
|
gemeldet['warte_' .. tostring(aufnahmeId)] = nil
|
|
end)
|
|
|
|
Kern.Abonniere('operation.abgeschlossen', function(operationId)
|
|
gemeldet['op_' .. tostring(operationId)] = nil
|
|
end)
|
|
|
|
Kern.Abonniere('behandlung.abgeschlossen', function(behandlungId)
|
|
gemeldet['doku_' .. tostring(behandlungId)] = nil
|
|
end)
|
|
|
|
Kern.Abonniere('labor.befundet', function(laborId)
|
|
gemeldet['labor_' .. tostring(laborId)] = nil
|
|
end)
|