aether-framework/resources/[aether]/aether-admin/server/module/staat.lua
Jerrit Fritzsche e4b82dd685 Aether-Framework: Fachmodule, Admin-Panel und Docker-Datenbank
- 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>
2026-07-27 18:55:32 +02:00

78 lines
3.2 KiB
Lua

-- =====================================================================
-- aether-admin / Modul: Staatsprojekte
--
-- Projekte, über die (später aus einer Handy-App) abgestimmt wird. Ein
-- Projekt lässt sich umsetzen, sobald die Abstimmung beendet ist und
-- genug Zustimmung erreicht wurde — die Kosten kommen aus der Staatskasse.
-- =====================================================================
Admin = Admin or {}
local ZUSTIMMUNG_MIN = 0.6
Admin.Kern.Registriere('staat', 'laden', function(handelnder, daten)
local liste = MySQL.query.await([[
SELECT id, titel, beschreibung, kosten, ja, nein, abstimmung_offen, aktiviert, erstellt_am
FROM aether_admin_projects ORDER BY aktiviert, id DESC
]]) or {}
for _, p in ipairs(liste) do
local gesamt = (tonumber(p.ja) or 0) + (tonumber(p.nein) or 0)
p.zustimmung = gesamt > 0 and math.floor(tonumber(p.ja) / gesamt * 100) or 0
p.offen = tonumber(p.abstimmung_offen) == 1
p.aktiviert = tonumber(p.aktiviert) == 1
end
return {
projekte = liste,
staatskasse = Admin.DB.EinstellungZahl('staatskasse', 0),
zustimmungMin = ZUSTIMMUNG_MIN * 100,
rechte = Admin.Kern.RechteAbbild(handelnder.quelle),
}
end)
Admin.Kern.Registriere('staat', 'beenden', function(handelnder, daten)
local id = tonumber(daten.id)
if not id then return nil, 'Ungültige Kennung.' end
MySQL.update.await('UPDATE aether_admin_projects SET abstimmung_offen = 0 WHERE id = ?', { id })
Admin.Log.Schreibe(handelnder, 'Abstimmung beendet', 'Projekt #' .. id)
return { ok = true }
end)
Admin.Kern.Registriere('staat', 'aktivieren', function(handelnder, daten)
local id = tonumber(daten.id)
if not id then return nil, 'Ungültige Kennung.' end
local zeilen = MySQL.query.await([[
SELECT titel, kosten, ja, nein, abstimmung_offen, aktiviert
FROM aether_admin_projects WHERE id = ?
]], { id })
if not zeilen or not zeilen[1] then return nil, 'Projekt nicht gefunden.' end
local p = zeilen[1]
if tonumber(p.aktiviert) == 1 then return nil, 'Bereits umgesetzt.' end
if tonumber(p.abstimmung_offen) == 1 then return nil, 'Die Abstimmung läuft noch.' end
local gesamt = (tonumber(p.ja) or 0) + (tonumber(p.nein) or 0)
local quote = gesamt > 0 and (tonumber(p.ja) / gesamt) or 0
if quote < ZUSTIMMUNG_MIN then return nil, 'Nicht genug Zustimmung.' end
local kosten = tonumber(p.kosten) or 0
local kasse = Admin.DB.EinstellungZahl('staatskasse', 0)
if kosten > kasse then return nil, 'Staatskasse nicht gedeckt.' end
Admin.DB.SetzeEinstellung('staatskasse', kasse - kosten)
MySQL.update.await('UPDATE aether_admin_projects SET aktiviert = 1 WHERE id = ?', { id })
Admin.Log.Schreibe(handelnder, 'Staatsprojekt aktiviert', p.titel, tostring(kosten))
return { ok = true }
end)
Admin.Kern.Registriere('staat', 'archivieren', function(handelnder, daten)
local id = tonumber(daten.id)
if not id then return nil, 'Ungültige Kennung.' end
MySQL.update.await('DELETE FROM aether_admin_projects WHERE id = ?', { id })
Admin.Log.Schreibe(handelnder, 'Staatsprojekt archiviert', 'Projekt #' .. id)
return { ok = true }
end)