Repository navigation
Entwickler Datenmodell
Alle Tabellen haben: id BIGINT PK AUTO_INCREMENT, created_at DATETIME UTC. MariaDB 12.3, InnoDB, UTF8MB4.
TenantScoped-Modelle erhalten automatisch ein org_id-Feld und werden via SQLAlchemy do_orm_execute-Event auf die aktive Org gefiltert.
fire_dept
id, slug (UNIQUE), name, color
is_home_org, is_active
deleted_at (NULL = aktiv, gesetzt = Soft-Delete)
logo_path, contact_email, contact_phone, street, city
timezone (IANA, NULL = DEFAULT_TIMEZONE)
fallback_lat, fallback_lng
short_code (max. 3 Zeichen, z.B. "WOL")
storage_quota_bytes (NULL = unbegrenzt)
withdraw_press_factor, withdraw_press_reserve
org_settings ← 1:1 zu fire_dept
id, org_id FK (UNIQUE)
primary_color, footer_text
mi_auto_adopt
autoclose_enabled (NULL = global), autoclose_after_hours, autoclose_grace_minutes
weather_enabled (BOOL, Default 1) ← Wetter-Opt-out je Org
uas_module_enabled (BOOL, Default 0) ← UAS-Modul je Org (zusätzlich zu SystemSettings)
gsl_lagemeldung_enabled (BOOL) ← SKKM-Regelkreis aktivieren
gsl_lagemeldung_interval_min ← Fälligkeitsintervall in Minuten
gsl_verleih_enabled (BOOL) ← Geräteverleih-Modul aktivieren
vehicle_master
id, dept_id FK → fire_dept, code, name, type
is_first_train, display_order, active, deleted
bos_override
member [TenantScoped: org_id]
id, org_id FK, lastname, firstname, phone, email, active
qualification
id, code (AGT|MA|GK|ZK|EL|TF|TM|JF), label
is_einsatzleiter, is_gruppenkommandant
member_qualification (m:n)
member_id FK, qualification_id FK, valid_until
alarm_type [TenantScoped: org_id]
id PK (bigint), org_id FK
code (T1..T9, F1..F4)
category (Technik|Feuer)
default_first_train_only, notify_neighbors
task_suggestion [TenantScoped: org_id]
id, org_id FK, alarm_type_id FK, text, display_order
message_suggestion [TenantScoped: org_id]
id, org_id FK, alarm_type_id FK, text
lage_hint [TenantScoped: org_id]
id, org_id FK, text, display_order
default_message [TenantScoped: org_id]
id, org_id FK, alarm_type_id FK, text, due_after_sec
seed_template
id, profile (UNIQUE), label, bos
(JSON-Speicher für Alarmtypen, Vorlagen, Lage-Hinweise)
user
id, username (UNIQUE), password_hash (bcrypt)
display_name, email, active, last_login_at
org_id FK → fire_dept (NULL = system_admin ohne Org)
failed_login_count, locked_until
role
id, code (UNIQUE: system_admin|org_admin|admin|incident_leader|...), label
user_role (m:n)
user_id FK, role_id FK
api_key
id, key_hash (SHA-256), label
org_id FK → fire_dept
created_by_user_id FK?, expires_at, revoked_at, last_used_at
device_token ← Tablet/Geräte-Auto-Login
id, user_id FK, token_hash, label, revoked_at, last_used_at
audit_log
id, user_id FK?, api_key_id FK?
org_id FK?
action, entity_type, entity_id, payload_json, ip
push_subscription
id, user_id FK, endpoint, p256dh, auth
org_invitation
id, org_id FK, token_hash (UNIQUE), email, admin_name
created_by_user_id FK, expires_at, used_at
incident
id, external_key
UNIQUE(primary_org_id, external_key) ← Idempotenz je Org
primary_org_id FK → fire_dept
nummer, alarm_type_id FK
status (active|closed|archived)
started_at, closed_at
incident_leader_user_id FK?, is_exercise
address_street, address_no, address_city, address_lat, address_lng
report_text, reason
incident_org (m:n: Kollaboration)
incident_id FK, org_id FK
added_at, added_by_user_id FK?
incident_column
id, incident_id FK, code, title, is_fixed, display_order
incident_vehicle
id, incident_id FK, column_id FK?
vehicle_master_id FK, commander_member_id FK?
display_order, removed_at, org_color_override
task
id, incident_id FK, column_id FK?, vehicle_id FK?
title, detail
is_done, done_at, is_cancelled, cancelled_at, display_order
source (manual|api|ai_suggestion|template)
task_media
id, task_id FK, incident_id FK
file_type (image|pdf|video), original_filename
stored_path, thumb_path, width, height, duration_sec, file_size_bytes
message
id, incident_id FK
title, detail, due_after_sec, due_at
popup_shown, is_done, is_cancelled, display_order
rescued_person
id, incident_id FK
gender, person_group, age_range, name, location, vehicle_id FK?
incident_log ← sichtbares Verlaufsprotokoll
id, incident_id FK, ts, level (info|warn|alert)
user_id FK?, text, entity_type?, entity_id?
incident_change ← granulares Änderungslog (Zeitreise)
id, incident_id FK, ts, action
entity_type, entity_id?
before_json (LONGTEXT), after_json (LONGTEXT)
user_id FK?, api_key_id FK?, ip
incident_token ← QR-Login-Tokens
id, incident_id FK, token_hash
issued_by_user_id FK?, target_user_id FK?, revoked_at
breathing_troop
id, incident_id FK, vehicle_id FK?
name, status (bereit|im_einsatz|rueckzug|zurueck|erholt)
task_text, start_press_avg
entry_at, withdraw_press_calc, withdraw_at, back_at, notes
troop_member
id, troop_id FK, member_id FK?, free_text_name
role (truppfuehrer|truppmann)
start_press, withdraw_press, back_press
pressure_log
id, troop_id FK, ts, member_id FK?
pressure_bar, recorded_by_user_id FK?
ai_prompt_version [TenantScoped: org_id]
id, org_id FK
prompt_key (report|task_suggestions|lage_hints|situation|mi_prioritize|katplan_import|…)
content (LONGTEXT), version_number
created_by_user_id FK?, is_active
system_settings ← Key-Value-Store für globale Werte
id, key (UNIQUE), value (TEXT)
(smtp_host, smtp_password, vapid_*, ai_enabled, incident_autoclose_*, ...)
lagekarte_token ← Read-only GeoJSON-Feed-Tokens
id, org_id FK, token_hash, label, revoked_at
major_incident_* ← Großschadenslage (Phasen-Kanban, Einsatzstellen, Stab, ...)
(siehe app/models/major_incident.py)
lage_einheit ← GSL-Ressourcen/Einheiten
id, major_incident_id FK, org_id FK
bezeichnung, typ (feuerwehr|rettung|polizei|technisch|sonstig)
fremdorg_name, tetra_rufname, bemerkungen
display_order
lage_dispatch ← Mehrfach-Disposition (m:n Einheit ↔ Einsatzstelle)
id, einheit_id FK, site_id FK, major_incident_id FK
assigned_at, assigned_by_user_id FK?
cross_site_marker ← Übergreifende Meldungen
id, major_incident_id FK
titel, status (meldung|achtung|hinweis|information)
notizen, lat, lng, address
is_done, done_at
org_sso_config ← SSO-Konfiguration je Org
id, org_id FK (UNIQUE)
tenant_id, client_id
client_secret_enc (Fernet-verschlüsselt)
allowed_domains (CSV), default_role_code
enforce_sso (BOOL), sso_enabled (BOOL)
org_sso_group_map ← Gruppen-Rollen-Mapping
id, org_id FK, group_object_id, role_code, label
Felder in user:
user.entra_oid ← Azure Object-ID des Benutzers
user.entra_tid ← Azure Tenant-ID
user.auth_provider ← 'local' oder 'entra'
user.password_hash ← NULL wenn nur SSO
Fallback-Kette (siehe app/services/mail_service.py::deliver()): Office 365 →
eigener SMTP der Org → globaler SMTP (system_settings, s.o.).
org_smtp_config ← eigener SMTP-Server je Org
id, org_id FK (UNIQUE), enabled (BOOL)
host, port, user, password_enc (Fernet-verschlüsselt)
from_addr, starttls (BOOL), timeout
imap_enabled, imap_host, imap_port, imap_use_ssl ← Vorbereitung Posteingang, KEINE Verarbeitung implementiert
org_o365_mail_config ← Microsoft Graph App-only-Mailversand je Org
id, org_id FK (UNIQUE), enabled (BOOL)
tenant_id, client_id
client_secret_enc (Fernet-verschlüsselt)
sender_address
read_enabled ← Vorbereitung Posteingang (Mail.Read), KEINE Verarbeitung implementiert
uas_device [TenantScoped: org_id]
id, org_id FK
bezeichnung, hersteller, typ_modell, registriernummer
ce_klasse, unterkategorie, mtom_g, leergewicht_g
waermebildkamera, allwettertauglich
versicherungspolizze, versicherung_gueltig_bis
sybos_id, beschaffungsdatum, tauschintervall_jahre
status (aktiv|ausser_betrieb|ausgemustert)
notizen
uas_wartung ← Wartungsbuch je Gerät
id, device_id FK, wartungsart, pruefdatum, pruefer
ergebnis (io|nicht_io|bedingt_io)
naechste_faelligkeit, bemerkungen
positionen (JSON: Checklisten-Punkte)
uas_pilot [TenantScoped: org_id]
id, org_id FK, member_id FK?
nachname, vorname, geburtsdatum
a1a3_nr, a1a3_gueltig_bis
a2_nr, a2_gueltig_bis
bos_stufe, bos_datum, bos_rezertifizierung_bis
lfv_zugelassen (BOOL), ist_truppfuehrer (BOOL), aktiv (BOOL)
qualifikationen (JSON)
uas_flugbewegung ← Manuelle Flugbewegungen (Pilot-Profil)
id, pilot_id FK, datum, art, dauer_min, bemerkungen
uas_einsatz ← UAS-Einsatz verknüpft mit Incident
id, incident_id FK, org_id FK
status (alarmiert|angemeldet|im_einsatz|abgemeldet|abgeschlossen)
tetra_rufname, betreibernummer, einsatzgrund
gesamteinsatzleiter, datenschutz_bestaetigt
alarmierungszeitpunkt, startzeit, endzeit
uas_einsatz_rolle ← Teambesetzung je UAS-Einsatz
id, einsatz_id FK, pilot_id FK?
rolle (teamleiter|pilot|operator|luftraumbeobachter|...)
helfer_name, override_begruendung
uas_flug ← Flugbuch
id, einsatz_id FK, device_id FK, pilot_id FK
startzeit, landezeit, luftraum, hoehe_m
durchfuehrungsgrundlage, wetterdaten (JSON)
missionsziel, besonderheiten
uas_checkliste ← Vor-/Nachflug-Checkliste (4-Augen)
id, flug_id FK, art (vor|nach)
abgehakt (JSON), sign1_name, sign1_at, sign2_name, sign2_at
uas_ereignis ← Notfall-/Unfall-Workflow
id, einsatz_id FK, art (notfall|unfall)
beschreibung, meldekette_stufe (1-4)
acg_meldung_at, nachbericht_at
uas_kartenobjekt ← Karte des UAS-Einsatzes
id, einsatz_id FK, typ, geojson (TEXT)
bezeichnung, farbe
uas_medien ← DSGVO-Medien-Verwaltung
id, einsatz_id FK
dateiname, stored_path, mime_type, file_size_bytes
dsgvo_status (erfasst|begruendet|zur_loeschung|geloescht)
rechtsgrundlage, loeschfrist_datum, geloescht_at
verleih_artikel [TenantScoped: org_id]
id, org_id FK
bezeichnung, barcode, einheit (stk|satz|karton|kg|l)
bestand, beschreibung, aktiv
verleih_stueckliste [TenantScoped: org_id]
id, org_id FK, bezeichnung, beschreibung
verleih_stueckliste_position
id, stueckliste_id FK, artikel_id FK, menge
verleih_ausleihe [TenantScoped: org_id]
id, org_id FK, lage_id FK
site_id FK? (Einsatzstelle), quelle (verleih|board|einheit)
einheit_id FK? (lage_einheit), created_by_name
artikel_id FK? / stueckliste_id FK?
status (offen|teilweise|zurueck)
ausgeliehen_at, zurueck_at
notizen, ausgegeben_von_user_id FK?
verleih_position ← Einzelpositionen einer Ausleihe
id, ausleihe_id FK, artikel_id FK
menge_ausgegeben, menge_zurueck, zurueck_at
verleih_foto
id, ausleihe_id FK, stored_path, thumb_path
created_at, created_by_user_id FK?, author_name
Die Wetterstation nutzt zwei getrennte Datenbanken — die operative DB enthält nur den Snapshot, die Zeitreihe liegt in einer separaten Wetter-DB.
Haupt-DB (einsatzleiter):
weather_station [TenantScoped: org_id]
id, org_id FK → fire_dept
name (VARCHAR 100)
ingest_token_hash (VARCHAR 64 UNIQUE) ← SHA-256 des wxst_-Tokens
active (BOOL, Default 1)
lat, lng (Dezimalgrad, optional)
last_seen_at ← Zeitstempel letzter erfolgreicher Push
last_measured_at ← Zeitstempel des gemessenen Zeitpunkts
last_temp_c, last_hum_pct
last_wind_ms, last_gust_ms, last_wind_dir (VARCHAR 3, z.B. "NW")
last_pressure_hpa
last_rain_rate_mmh, last_rain_day_mm
last_dew_c, last_solar_wm2, last_uv_index
Wetter-DB (einsatzleiter_weather) — eigener Connection-Pool:
weather_reading
id, org_id, station_id (kein FK-Constraint in separater DB)
ts (DATETIME UTC)
temp_c, hum_pct, wind_ms, gust_ms, wind_dir
pressure_hpa, rain_rate_mmh, rain_day_mm
dew_c, solar_wm2, uv_index
INDEX (org_id, station_id, ts) ← Haupt-Abfrage-Index
Die Zeitreihe wird täglich um 03:30 (Europe/Vienna) bereinigt — Retention konfigurierbar via WEATHER_READING_RETENTION_DAYS.
Details und Services: Entwickler-Katastrophenplaene. Alle Tabellen sind TenantScoped (Migrationen 0294–0299).
katplan_plan uuid, titel, gefahrenarten_json, beschreibung_html, geltungsbereich,
verantwortliche_stelle, verantwortlich_kontakt_id, status (entwurf|
in_pruefung|freigegeben|in_ueberarbeitung|archiviert),
aktuelle_version_id, wiedervorlage_am, wiedervorlage_erinnert_am, version
katplan_abschnitt plan_id FK, parent_id FK? (Kapitelbaum), titel, beschreibung_html, sort
katplan_phase plan_id FK, name, beschreibung, ausloeser, farbe, sort
katplan_element plan_id FK, abschnitt_id FK?, uuid (stabil über Versionen), kennung, typ,
titel, beschreibung_html, daten_json (typspezifisch), prioritaet,
tags_json, vertraulich, gueltig_bis, pruefen_am,
strasse/hausnummer/plz/ort, lat/lng, geometry_json,
geo_status (keine|ungeprueft|geprueft), herkunft (manual|imported|
ai_suggested), quelle_dokument_id (ohne FK), quelle_seiten,
gsl_* (vorbereitet), suchtext, version
katplan_element_phase element_id FK, phase_id FK
katplan_aenderung Protokoll: entitaet, aktion, feld, alt, neu, element_id, user_id,
quelle (ui|mcp), zeit
katplan_pruefung Workflowprotokoll: version_id?, aktion (eingereicht|zurueckgewiesen|
freigegeben|archiviert|reaktiviert), kommentar, user_id, zeit
katplan_version plan_id FK, versionsnummer, plan_json (Kopf, Kapitel, Phasen,
Links, Anhänge, Quellen), inhalt_hash, anzahl_elemente, aenderungsnotiz,
freigegeben_am, freigegeben_von_id ← unveränderlich
katplan_version_element version_id FK, element_uuid, Elementfelder als Snapshot,
phasen_json, links_json, relationen_json, anhaenge_json, gsl_json
katplan_link plan_id, element_id? (null = Plan-Link), ziel_typ (kontakt|
kontakt_organisation|objekt|fahrzeug|wasserstelle), ziel_id, rolle, hinweis
katplan_relation von_element_id FK, zu_element_uuid, art, hinweis
katplan_anhang plan_id, element_id?/abschnitt_id?, uuid, art (foto|datei|link|
objekt_dokument), dateiname, pfad, thumb_pfad, mime, groesse_bytes,
url, objekt_dokument_id, seiten, beschriftung, urheber,
aufnahme_datum, vertraulich, sort,
geloescht_am (soft delete, Versionen referenzieren weiter)
katplan_dokument plan_id FK, uuid, titel, pfad, seitenzahl, status, dokument_gruppe_id,
versionsnummer, ist_aktuelle_version, archiviert, belegt_bytes,
ki_status, ki_fehler, ki_analysiert_am
katplan_dokument_seite dokument_id FK, seiten_nr, einzel_pdf_pfad, bild_pfad, thumb_pfad,
volltext, text_quelle, titel
katplan_import_vorschlag plan_id, dokument_id, seite_id?, seiten_nr, typ, titel,
beschreibung_html, daten_json, kapitel, phase, Adresse,
kontakte_json, objekt_name/objekt_id, status (offen|uebernommen|
verworfen), element_id
-- Idempotenz-Check (je Org):
UNIQUE INDEX ON incident(primary_org_id, external_key)
-- Aktive Einsätze schnell finden:
INDEX ON incident(status, started_at)
INDEX ON incident(primary_org_id, status)
-- Änderungslog zeitlich sortiert:
INDEX ON incident_change(incident_id, ts)
-- Pressure-Log je Trupp:
INDEX ON pressure_log(troop_id, ts)
-- Tenant-Filter:
INDEX ON member(org_id)
INDEX ON alarm_type(org_id)
INDEX ON task_suggestion(org_id)Einsatz führen
Im Einsatz
Einsatzbegleitend
Verwaltung & Planung
Auswertung
Großschadenslage
Verwaltung
Systemadministration
- Überblick und Inbetriebnahme
- Systemdiagnose
- Datenbank: Snapshot-Isolation
- System-Admin-MCP
- Zwei-Faktor-Authentifizierung
Mehr