feat(notruf): Alarmpause pro Nutzer im Notfall-Profil (Minuten, 0=aus, leer=global)
Bisher war die Wiederauslöse-Sperre nur global einstellbar. Jetzt zusätzlich pro Nutzer im Notfall-Profil (Admin), hinter „Standort im Notfall mitsenden": „Pause bis zum erneuten Alarm: [n] Minuten" (leer = globaler Standard, 0 = aus). - Auflösung serverseitig: Nutzer-Pref > globale Einstellung > 5 (_resolve_cooldown_minutes in emergency.py; emergency_cooldown_status nutzt sie, die Notruf-UI/der Status-Endpunkt liefern dadurch automatisch den per-User-Wert). - Schema AdminUserPrefsUpdate.emergency_cooldown_minutes (String) mit Validator (leer/0–60, sonst 422). /api/admin/users gibt das Feld jetzt mit aus (sonst lädt das Formular leer). - Frontend: Zahlenfeld + Hinweis im Notfall-Profil, über PROF_KEYS/PROF_VALIDATORS verdrahtet. Bump app.js v=51 -> v=52. - Doku: BEDIENUNGSANLEITUNG § Nutzer › Verwalten. Tests: per-User-Override/Erben/Aus + Schema-Validierung. 254 Offline-Tests grün. Live verifiziert: PUT prefs -> /status spiegelt 300->120s, 99 -> 422, Formular zeigt/lädt das Feld hinter der Standort-Checkbox. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
f3dbd434b0
commit
904f7db82c
7 changed files with 97 additions and 8 deletions
|
|
@ -6,6 +6,7 @@ Nach einem Alarm ist ein erneuter Alarm für emergency_cooldown_minutes blockier
|
|||
import asyncio
|
||||
from datetime import datetime, timezone, timedelta
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
import app.safety.emergency as em
|
||||
|
|
@ -87,3 +88,46 @@ def test_status_endpoint(monkeypatch):
|
|||
st = client.get("/api/emergency/status").json()
|
||||
assert st["active"] is True
|
||||
assert st["cooldown_seconds"] == 300
|
||||
|
||||
|
||||
def _user_with(prefs):
|
||||
u = FakeUser()
|
||||
u.prefs = prefs
|
||||
return u
|
||||
|
||||
|
||||
def test_per_user_override(monkeypatch):
|
||||
# Nutzer-Pref (2 Min) schlägt die globale Einstellung (5 Min).
|
||||
monkeypatch.setattr(em.settings, "emergency_cooldown_minutes", 5)
|
||||
s = em.emergency_cooldown_status(_user_with({"emergency_cooldown_minutes": "2"}),
|
||||
FakeStore(last=_iso_ago(60)))
|
||||
assert s["cooldown_seconds"] == 120
|
||||
assert s["active"] is True # 60s < 120s
|
||||
|
||||
|
||||
def test_per_user_empty_inherits_global(monkeypatch):
|
||||
monkeypatch.setattr(em.settings, "emergency_cooldown_minutes", 5)
|
||||
s = em.emergency_cooldown_status(_user_with({"emergency_cooldown_minutes": ""}),
|
||||
FakeStore(last=_iso_ago(60)))
|
||||
assert s["cooldown_seconds"] == 300 # globaler Standard
|
||||
|
||||
|
||||
def test_per_user_zero_disables(monkeypatch):
|
||||
monkeypatch.setattr(em.settings, "emergency_cooldown_minutes", 5)
|
||||
s = em.emergency_cooldown_status(_user_with({"emergency_cooldown_minutes": "0"}),
|
||||
FakeStore(last=_iso_ago(5)))
|
||||
assert s["active"] is False
|
||||
assert s["cooldown_seconds"] == 0
|
||||
|
||||
|
||||
def test_schema_validates_cooldown():
|
||||
from app.schemas import AdminUserPrefsUpdate
|
||||
# gültig: leer (erben), "0" (aus), kleine Zahl
|
||||
assert AdminUserPrefsUpdate(emergency_cooldown_minutes="").emergency_cooldown_minutes == ""
|
||||
assert AdminUserPrefsUpdate(emergency_cooldown_minutes="0").emergency_cooldown_minutes == "0"
|
||||
assert AdminUserPrefsUpdate(emergency_cooldown_minutes="10").emergency_cooldown_minutes == "10"
|
||||
# ungültig: > 60 und nicht-numerisch
|
||||
with pytest.raises(ValueError):
|
||||
AdminUserPrefsUpdate(emergency_cooldown_minutes="61")
|
||||
with pytest.raises(ValueError):
|
||||
AdminUserPrefsUpdate(emergency_cooldown_minutes="abc")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue