-- ===================================================================== -- aether-medical / Modul: Leitstelle und Einsatzverwaltung -- -- Ein Notruf erzeugt einen OFFENEN Einsatz. Mehr nicht. -- -- Das System alarmiert niemanden gezielt, schickt keine Einheit los -- und schliesst keinen Einsatz ab. Die Leitstelle entscheidet, wen sie -- anfragt — und selbst eine Anfrage ist nur eine Bitte: die Kraft muss -- dem Einsatz weiterhin selbst beitreten. -- -- Der Status „laufend" ist keine Entscheidung, sondern die Aufzeichnung -- einer Tatsache: es ist jemand gebunden. Abgeschlossen wird immer -- von Hand. -- ===================================================================== Kern.RegistriereModul({ id = 'einsatz', name = 'Leitstelle', icon = '🚑', reihenfolge = 4, recht = 'einsatz.erstellen', beschreibung = 'Notrufe, Einsätze und Disposition', }) -- --------------------------------------------------------------------- -- Hilfsfunktionen -- --------------------------------------------------------------------- --- Begrenzt einen Text und liefert nil bei leerer Eingabe 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 --- Prüft eine Prioritätsstufe local function Prioritaet(wert) local stufe = tonumber(wert) or 3 if stufe < 1 or stufe > 4 then return 3 end return math.floor(stufe) end --- Prüft eine Einsatzkategorie --- @param kennung any Eingabe --- @return string local function Kategorie(kennung) for _, eintrag in ipairs(Medizin.Config.Einsatzkategorien) do if eintrag.id == kennung then return eintrag.id end end return 'sonstiges' end --- Name eines Mitarbeiters für die Anzeige local function NameVon(charakterId) if not charakterId then return 'System' end local zeilen = MySQL.query.await([[ SELECT c.firstname, c.lastname, p.personalnummer FROM aether_characters c LEFT JOIN medical_personal p ON p.`character` = c.id WHERE c.id = ? ]], { charakterId }) if not zeilen or not zeilen[1] then return 'unbekannt' end return zeilen[1].firstname .. ' ' .. zeilen[1].lastname end --- Wie viele Kräfte sind einem Einsatz gerade zugeordnet? --- @param einsatzId number Einsatz --- @return number local function AnzahlKraefte(einsatzId) return tonumber(MySQL.scalar.await( 'SELECT COUNT(*) FROM medical_einsatz_kraft WHERE einsatz = ? AND bis IS NULL', { einsatzId })) or 0 end --- Hält den Status im Einklang mit der Tatsache, ob jemand gebunden ist. --- Das ist Buchführung, keine Entscheidung: ein abgeschlossener Einsatz --- wird hier nie wieder geöffnet. --- @param einsatzId number Einsatz local function StatusNachKraeften(einsatzId) local zeilen = MySQL.query.await( 'SELECT status FROM medical_einsatz WHERE id = ?', { einsatzId }) if not zeilen or not zeilen[1] then return end if zeilen[1].status == 'abgeschlossen' then return end local neu = AnzahlKraefte(einsatzId) > 0 and 'laufend' or 'offen' if neu ~= zeilen[1].status then MySQL.update.await('UPDATE medical_einsatz SET status = ? WHERE id = ?', { neu, einsatzId }) end end --- Meldet allen im Dienst, dass sich etwas geändert hat local function Melden() for quelle in pairs(Dienst.AlleImDienst()) do TriggerClientEvent('aether:medical:einsatzAenderung', quelle) end end -- ===================================================================== -- EINGANG -- -- Einziger Weg, auf dem ein Einsatz von aussen entsteht. Global, damit -- server/main.lua und andere Ressourcen ihn erreichen. -- ===================================================================== --- Nimmt einen Notfall entgegen und legt ihn als offenen Einsatz ab --- @param daten table { titel, kategorie?, prioritaet?, ort?, beschreibung?, position?, quelle? } --- @return number|nil Einsatz-ID function EinsatzEingang(daten) if type(daten) ~= 'table' or not daten.titel then return nil end local nummer = Kern.ErzeugeKennung('EIN', 'medical_einsatz', 'nummer') local position = daten.position or {} local prioritaet = Prioritaet(daten.prioritaet) local kategorie = Kategorie(daten.kategorie) local id = MySQL.insert.await([[ INSERT INTO medical_einsatz (nummer, titel, kategorie, prioritaet, ort, pos_x, pos_y, pos_z, beschreibung, status, quelle, erstellt_von) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'offen', ?, ?) ]], { nummer, tostring(daten.titel):sub(1, 160), kategorie, prioritaet, daten.ort and tostring(daten.ort):sub(1, 160) or nil, position.x, position.y, position.z, daten.beschreibung and tostring(daten.beschreibung):sub(1, 4000) or nil, daten.quelle or 'system', daten.erstelltVon, }) -- Alle im Dienst erfahren davon. Ausgewählt wird niemand. Hinweise.Erstelle(nil, { kategorie = 'einsatz', prioritaet = prioritaet == 1 and 'kritisch' or prioritaet == 2 and 'hoch' or 'normal', titel = ('Neuer Einsatz · %s'):format(nummer), text = ('%s%s'):format(daten.titel, daten.ort and (' — ' .. daten.ort) or ''), zielTyp = 'einsatz', zielId = id, }) Kern.Loese('einsatz.eingegangen', id, kategorie) Melden() return id end -- --------------------------------------------------------------------- -- Notruf aus dem Verletztenzustand (aether-death) -- -- Ein am Boden liegender Spieler setzt einen Notruf ab. Daraus wird -- ein offener Einsatz — niemand wird alarmiert oder hingeschickt. -- --------------------------------------------------------------------- AddEventHandler('aether:death:notruf', function(quelle, daten) if type(daten) ~= 'table' then return end EinsatzEingang({ titel = 'Bewusstlose Person', kategorie = 'bewusstlos', prioritaet = 1, ort = 'Position des Anrufers', beschreibung = ('%s liegt verletzt am Boden und hat den Rettungsdienst gerufen.') :format(daten.name or 'Eine Person'), position = daten.position, quelle = 'notruf', }) end) -- ===================================================================== -- ÜBERSICHT UND LEITSTELLE -- ===================================================================== Kern.RegistriereAktion('einsatz', 'uebersicht', nil, function(quelle, mitarbeiter, daten) local ordner = tostring(daten.ordner or 'aktuell') local bedingung if ordner == 'archiv' then bedingung = "e.status = 'abgeschlossen'" else bedingung = "e.status IN ('offen', 'laufend')" end local einsaetze = MySQL.query.await(([[ SELECT e.id, e.nummer, e.titel, e.kategorie, e.prioritaet, e.ort, e.pos_x, e.pos_y, e.pos_z, e.status, e.quelle, e.erstellt_am, e.erstellt_von, e.geschlossen_am, e.geschlossen_von, TIMESTAMPDIFF(MINUTE, e.erstellt_am, NOW()) AS offenSeit, (SELECT COUNT(*) FROM medical_einsatz_kraft k WHERE k.einsatz = e.id AND k.bis IS NULL) AS kraefte, (SELECT COUNT(*) FROM medical_einsatz_kraft k WHERE k.einsatz = e.id AND k.bis IS NULL AND k.`character` = ?) AS ichDabei FROM medical_einsatz e WHERE %s ORDER BY e.prioritaet, e.id DESC LIMIT 120 ]]):format(bedingung), { mitarbeiter.charakterId }) or {} local kategorieNamen, kategorieFarben = {}, {} for _, eintrag in ipairs(Medizin.Config.Einsatzkategorien) do kategorieNamen[eintrag.id] = eintrag.name kategorieFarben[eintrag.id] = eintrag.farbe end for _, einsatz in ipairs(einsaetze) do einsatz.kategorieName = kategorieNamen[einsatz.kategorie] or einsatz.kategorie einsatz.farbe = kategorieFarben[einsatz.kategorie] einsatz.kraefte = tonumber(einsatz.kraefte) or 0 einsatz.ichDabei = tonumber(einsatz.ichDabei) > 0 einsatz.erstelltVon = NameVon(einsatz.erstellt_von) einsatz.geschlossenVon = einsatz.geschlossen_von and NameVon(einsatz.geschlossen_von) or nil einsatz.erstellt_von, einsatz.geschlossen_von = nil, nil end -- Verfügbare Kräfte für die Disposition local kraefte = {} for zielQuelle, eintrag in pairs(Dienst.AlleImDienst()) do -- Woran ist diese Kraft gerade gebunden? local gebunden = MySQL.query.await([[ SELECT e.id, e.nummer FROM medical_einsatz_kraft k JOIN medical_einsatz e ON e.id = k.einsatz WHERE k.`character` = ? AND k.bis IS NULL AND e.status <> 'abgeschlossen' LIMIT 1 ]], { eintrag.charakterId }) kraefte[#kraefte + 1] = { quelle = zielQuelle, charakterId = eintrag.charakterId, name = eintrag.name, personalnummer = eintrag.personalnummer, rolleName = eintrag.rolleName, station = eintrag.station, funktion = eintrag.funktion, status = eintrag.status, leitstelle = Dienst.Leitstelle() == zielQuelle, gebundenAn = gebunden and gebunden[1] and gebunden[1].nummer or nil, gebundenId = gebunden and gebunden[1] and gebunden[1].id or nil, } end table.sort(kraefte, function(a, b) return a.personalnummer < b.personalnummer end) return { ordner = ordner, einsaetze = einsaetze, kraefte = kraefte, kategorien = Medizin.Config.Einsatzkategorien, status = Medizin.Config.Dienststatus, funktionen = Medizin.Config.Dienstfunktionen, istLeitstelle = Dienst.Leitstelle() == quelle, leitstelleName = (function() local leit = Dienst.Leitstelle() local eintrag = leit and Dienst.Hole(leit) return eintrag and eintrag.name or nil end)(), zaehler = { offen = tonumber(MySQL.scalar.await( "SELECT COUNT(*) FROM medical_einsatz WHERE status = 'offen'")) or 0, laufend = tonumber(MySQL.scalar.await( "SELECT COUNT(*) FROM medical_einsatz WHERE status = 'laufend'")) or 0, heute = tonumber(MySQL.scalar.await([[ SELECT COUNT(*) FROM medical_einsatz WHERE status = 'abgeschlossen' AND DATE(geschlossen_am) = CURDATE() ]])) or 0, }, rechte = { erstellen = Rechte.Hat(mitarbeiter, 'einsatz.erstellen'), zuweisen = Rechte.Hat(mitarbeiter, 'einsatz.zuweisen'), schliessen = Rechte.Hat(mitarbeiter, 'einsatz.schliessen'), leitstelle = Rechte.Hat(mitarbeiter, 'dienst.leitstelle'), }, } end) Kern.RegistriereAktion('einsatz', 'oeffnen', nil, function(quelle, mitarbeiter, daten) local einsatzId = tonumber(daten.id) if not einsatzId then return nil, 'Ungültige Kennung.' end local zeilen = MySQL.query.await('SELECT * FROM medical_einsatz WHERE id = ?', { einsatzId }) if not zeilen or not zeilen[1] then return nil, 'Einsatz nicht gefunden.' end local einsatz = zeilen[1] local kategorieName = einsatz.kategorie for _, eintrag in ipairs(Medizin.Config.Einsatzkategorien) do if eintrag.id == einsatz.kategorie then kategorieName = eintrag.name end end -- Beteiligte Kräfte, auch die bereits abgerückten local kraefte = MySQL.query.await([[ SELECT k.`character`, k.seit, k.bis, c.firstname, c.lastname, p.personalnummer, p.rolle FROM medical_einsatz_kraft k LEFT JOIN aether_characters c ON c.id = k.`character` LEFT JOIN medical_personal p ON p.`character` = k.`character` WHERE k.einsatz = ? ORDER BY k.seit ]], { einsatzId }) or {} local ichDabei = false for _, kraft in ipairs(kraefte) do kraft.name = (kraft.firstname or 'Unbekannt') .. ' ' .. (kraft.lastname or '') local rolle = Medizin.HoleRolle(kraft.rolle) kraft.rolleName = rolle and rolle.name or kraft.rolle kraft.aktiv = kraft.bis == nil kraft.firstname, kraft.lastname = nil, nil if kraft.aktiv and kraft.character == mitarbeiter.charakterId then ichDabei = true end end -- Notizen zum Einsatzverlauf local notizen = MySQL.query.await([[ SELECT n.id, n.text, n.am, n.von, c.firstname, c.lastname FROM medical_einsatz_notiz n LEFT JOIN aether_characters c ON c.id = n.von WHERE n.einsatz = ? ORDER BY n.id DESC LIMIT 60 ]], { einsatzId }) or {} for _, notiz in ipairs(notizen) do notiz.autor = (notiz.firstname or 'Unbekannt') .. ' ' .. (notiz.lastname or '') notiz.firstname, notiz.lastname = nil, nil end -- Dokumentation, die auf diesen Einsatz verweist local behandlungen = MySQL.query.await([[ SELECT b.id, b.kennung, b.status, b.diagnose, b.erstellt_am, c.firstname, c.lastname FROM medical_behandlung b LEFT JOIN aether_characters c ON c.id = b.patient WHERE b.einsatz = ? ORDER BY b.id DESC LIMIT 20 ]], { einsatzId }) or {} for _, behandlung in ipairs(behandlungen) do behandlung.patientName = (behandlung.firstname or 'Unbekannt') .. ' ' .. (behandlung.lastname or '') behandlung.firstname, behandlung.lastname = nil, nil end return { einsatz = { id = einsatz.id, nummer = einsatz.nummer, titel = einsatz.titel, kategorie = einsatz.kategorie, kategorieName = kategorieName, prioritaet = einsatz.prioritaet, ort = einsatz.ort, beschreibung = einsatz.beschreibung, status = einsatz.status, quelle = einsatz.quelle, position = einsatz.pos_x and { x = einsatz.pos_x, y = einsatz.pos_y, z = einsatz.pos_z } or nil, erstelltAm = einsatz.erstellt_am, erstelltVon = NameVon(einsatz.erstellt_von), geschlossenAm = einsatz.geschlossen_am, geschlossenVon = einsatz.geschlossen_von and NameVon(einsatz.geschlossen_von) or nil, }, kraefte = kraefte, notizen = notizen, behandlungen = behandlungen, ichDabei = ichDabei, rechte = { zuweisen = Rechte.Hat(mitarbeiter, 'einsatz.zuweisen'), schliessen = Rechte.Hat(mitarbeiter, 'einsatz.schliessen'), }, } end) -- ===================================================================== -- EINSATZ ANLEGEN -- ===================================================================== Kern.RegistriereAktion('einsatz', 'erstellen', 'einsatz.erstellen', function(quelle, mitarbeiter, daten) local titel = Text(daten.titel, 160) if not titel or #titel < 3 then return nil, 'Bitte einen Einsatztitel angeben.' end local id = EinsatzEingang({ titel = titel, kategorie = daten.kategorie, prioritaet = daten.prioritaet, ort = Text(daten.ort, 160), beschreibung = Text(daten.beschreibung, 4000), position = daten.position, quelle = 'manuell', erstelltVon = mitarbeiter.charakterId, }) if not id then return nil, 'Der Einsatz konnte nicht angelegt werden.' end Protokoll.Schreibe(mitarbeiter, 'einsatz', 'Einsatz angelegt', { typ = 'einsatz', id = id }, { kategorie = Kategorie(daten.kategorie), prioritaet = Prioritaet(daten.prioritaet) }) return { id = id } end) -- ===================================================================== -- BEITRETEN UND VERLASSEN -- -- Jede Kraft entscheidet selbst. Auch eine Anfrage der Leitstelle -- bindet niemanden — sie muss angenommen werden. -- ===================================================================== Kern.RegistriereAktion('einsatz', 'beitreten', nil, function(quelle, mitarbeiter, daten) local einsatzId = tonumber(daten.id) if not einsatzId then return nil, 'Ungültige Kennung.' end local zeilen = MySQL.query.await( 'SELECT id, nummer, titel, status FROM medical_einsatz WHERE id = ?', { einsatzId }) if not zeilen or not zeilen[1] then return nil, 'Einsatz nicht gefunden.' end if zeilen[1].status == 'abgeschlossen' then return nil, 'Dieser Einsatz ist bereits abgeschlossen.' end -- Erneutes Beitreten nach dem Abrücken ist erlaubt MySQL.query.await([[ INSERT INTO medical_einsatz_kraft (einsatz, `character`) VALUES (?, ?) ON DUPLICATE KEY UPDATE bis = NULL, seit = NOW() ]], { einsatzId, mitarbeiter.charakterId }) StatusNachKraeften(einsatzId) Protokoll.Schreibe(mitarbeiter, 'einsatz', 'Einsatz übernommen', { typ = 'einsatz', id = einsatzId }, { nummer = zeilen[1].nummer }) Kern.Loese('einsatz.beigetreten', einsatzId, mitarbeiter) Melden() return { ok = true, position = true } end) Kern.RegistriereAktion('einsatz', 'verlassen', nil, function(quelle, mitarbeiter, daten) local einsatzId = tonumber(daten.id) if not einsatzId then return nil, 'Ungültige Kennung.' end MySQL.update.await([[ UPDATE medical_einsatz_kraft SET bis = NOW() WHERE einsatz = ? AND `character` = ? AND bis IS NULL ]], { einsatzId, mitarbeiter.charakterId }) StatusNachKraeften(einsatzId) Protokoll.Schreibe(mitarbeiter, 'einsatz', 'Einsatz verlassen', { typ = 'einsatz', id = einsatzId }, nil, Text(daten.grund, 255)) Kern.Loese('einsatz.verlassen', einsatzId, mitarbeiter) Melden() return { ok = true } end) -- ===================================================================== -- DISPOSITION -- -- Die Leitstelle FRAGT eine Kraft an. Sie zwingt niemanden — der -- Einsatz erscheint beim Angefragten mit Wegpunkt, beitreten muss -- er selbst. -- ===================================================================== Kern.RegistriereAktion('einsatz', 'anfragen', 'einsatz.zuweisen', function(quelle, mitarbeiter, daten) local einsatzId = tonumber(daten.id) local zielQuelle = tonumber(daten.quelle) if not einsatzId or not zielQuelle then return nil, 'Unvollständige Angaben.' end local ziel = Dienst.Hole(zielQuelle) if not ziel then return nil, 'Diese Kraft ist nicht im Dienst.' end local zeilen = MySQL.query.await( 'SELECT id, nummer, titel, ort, pos_x, pos_y, pos_z, status FROM medical_einsatz WHERE id = ?', { einsatzId }) if not zeilen or not zeilen[1] then return nil, 'Einsatz nicht gefunden.' end local einsatz = zeilen[1] if einsatz.status == 'abgeschlossen' then return nil, 'Dieser Einsatz ist bereits abgeschlossen.' end -- Bereits dabei? Dann ist eine Anfrage sinnlos local dabei = MySQL.scalar.await([[ SELECT 1 FROM medical_einsatz_kraft WHERE einsatz = ? AND `character` = ? AND bis IS NULL ]], { einsatzId, ziel.charakterId }) if dabei then return nil, 'Diese Kraft ist dem Einsatz bereits zugeordnet.' end TriggerClientEvent('aether:medical:einsatzZuweisung', zielQuelle, { id = einsatz.id, nummer = einsatz.nummer, titel = einsatz.titel, ort = einsatz.ort, von = mitarbeiter.name, position = einsatz.pos_x and { x = einsatz.pos_x, y = einsatz.pos_y, z = einsatz.pos_z } or nil, }) Hinweise.Erstelle({ charakterId = ziel.charakterId }, { kategorie = 'einsatz', prioritaet = 'hoch', titel = ('Anfrage der Leitstelle · %s'):format(einsatz.nummer), text = ('%s bittet dich um Übernahme: %s%s') :format(mitarbeiter.name, einsatz.titel, einsatz.ort and (' — ' .. einsatz.ort) or ''), zielTyp = 'einsatz', zielId = einsatz.id, }) Protokoll.Schreibe(mitarbeiter, 'einsatz', 'Kraft angefragt', { typ = 'einsatz', id = einsatzId }, { nummer = einsatz.nummer, ziel = ziel.personalnummer }) return { ok = true, name = ziel.name } end) -- ===================================================================== -- VERLAUF UND ABSCHLUSS -- ===================================================================== Kern.RegistriereAktion('einsatz', 'notiz', nil, function(quelle, mitarbeiter, daten) local einsatzId = tonumber(daten.id) local text = Text(daten.text, 1000) if not einsatzId then return nil, 'Ungültige Kennung.' end if not text or #text < 2 then return nil, 'Die Notiz ist zu kurz.' end local vorhanden = MySQL.scalar.await( 'SELECT id FROM medical_einsatz WHERE id = ?', { einsatzId }) if not vorhanden then return nil, 'Einsatz nicht gefunden.' end local id = MySQL.insert.await( 'INSERT INTO medical_einsatz_notiz (einsatz, text, von) VALUES (?, ?, ?)', { einsatzId, text, mitarbeiter.charakterId }) Melden() return { id = id } end) --- Priorität nachträglich ändern — immer mit Begründung Kern.RegistriereAktion('einsatz', 'prioritaet', 'einsatz.zuweisen', function(quelle, mitarbeiter, daten) local einsatzId = tonumber(daten.id) if not einsatzId then return nil, 'Ungültige Kennung.' end local zeilen = MySQL.query.await( 'SELECT id, nummer, prioritaet, status FROM medical_einsatz WHERE id = ?', { einsatzId }) if not zeilen or not zeilen[1] then return nil, 'Einsatz nicht gefunden.' end if zeilen[1].status == 'abgeschlossen' then return nil, 'Dieser Einsatz ist abgeschlossen.' end local neu = Prioritaet(daten.prioritaet) local grund = Text(daten.grund, 255) if not grund then return nil, 'Bitte begründen, warum sich die Priorität ändert.' end MySQL.update.await('UPDATE medical_einsatz SET prioritaet = ? WHERE id = ?', { neu, einsatzId }) Protokoll.Schreibe(mitarbeiter, 'einsatz', 'Priorität geändert', { typ = 'einsatz', id = einsatzId }, { nummer = zeilen[1].nummer, von = zeilen[1].prioritaet, nach = neu }, grund) Melden() return { ok = true } end) Kern.RegistriereAktion('einsatz', 'schliessen', 'einsatz.schliessen', function(quelle, mitarbeiter, daten) local einsatzId = tonumber(daten.id) if not einsatzId then return nil, 'Ungültige Kennung.' end local vermerk = Text(daten.vermerk, 4000) if not vermerk or #vermerk < 5 then return nil, 'Ein Abschluss erfordert einen Abschlussvermerk.' end local zeilen = MySQL.query.await( 'SELECT id, nummer, titel, status FROM medical_einsatz WHERE id = ?', { einsatzId }) if not zeilen or not zeilen[1] then return nil, 'Einsatz nicht gefunden.' end local einsatz = zeilen[1] if einsatz.status == 'abgeschlossen' then return nil, 'Dieser Einsatz ist bereits abgeschlossen.' end -- Der Abschlussvermerk wird als Notiz Teil des Verlaufs MySQL.insert.await( 'INSERT INTO medical_einsatz_notiz (einsatz, text, von) VALUES (?, ?, ?)', { einsatzId, 'Abschluss: ' .. vermerk, mitarbeiter.charakterId }) -- Noch gebundene Kräfte werden abgemeldet — der Einsatz ist vorbei MySQL.update.await( 'UPDATE medical_einsatz_kraft SET bis = NOW() WHERE einsatz = ? AND bis IS NULL', { einsatzId }) MySQL.update.await([[ UPDATE medical_einsatz SET status = 'abgeschlossen', geschlossen_von = ?, geschlossen_am = NOW() WHERE id = ? ]], { mitarbeiter.charakterId, einsatzId }) -- Gibt es schon eine Dokumentation zu diesem Einsatz? local dokumentiert = tonumber(MySQL.scalar.await( 'SELECT COUNT(*) FROM medical_behandlung WHERE einsatz = ?', { einsatzId })) or 0 Protokoll.Schreibe(mitarbeiter, 'einsatz', 'Einsatz abgeschlossen', { typ = 'einsatz', id = einsatzId }, { nummer = einsatz.nummer, dokumentationen = dokumentiert }, vermerk) -- Erinnern, nicht anlegen: das System erzeugt keine Behandlungsdoku if dokumentiert == 0 then Hinweise.Erstelle({ charakterId = mitarbeiter.charakterId }, { kategorie = 'doku', prioritaet = 'normal', titel = 'Dokumentation fehlt', text = ('Zu %s (%s) ist noch keine Behandlung dokumentiert.') :format(einsatz.nummer, einsatz.titel), zielTyp = 'einsatz', zielId = einsatzId, }) end Kern.Loese('einsatz.abgeschlossen', einsatzId, mitarbeiter) Melden() return { ok = true, dokumentiert = dokumentiert } end) -- --------------------------------------------------------------------- -- Schnittstelle für andere Ressourcen -- --------------------------------------------------------------------- --- Liefert die offenen und laufenden Einsätze --- @return table exports('HoleOffeneEinsaetze', function() return MySQL.query.await([[ SELECT id, nummer, titel, kategorie, prioritaet, ort, status, pos_x, pos_y, pos_z, erstellt_am FROM medical_einsatz WHERE status IN ('offen', 'laufend') ORDER BY prioritaet, id DESC ]]) or {} end)