From 8fbb356c34978655939fc2d55d3133efb3bd9e72 Mon Sep 17 00:00:00 2001 From: patrick Date: Sat, 5 Sep 2026 13:42:28 +0200 Subject: [PATCH] =?UTF-8?q?feat(mangel):=20Leitungsverantwortliche=20d?= =?UTF-8?q?=C3=BCrfen=20Mangel-Status=20=C3=A4ndern/erledigen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nutzer-Entscheidung: Status ändern/Erledigen bleibt nicht nur Materialverant- wortlichen+Admin vorbehalten, Leitungsverantwortliche gehören ebenfalls dazu. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01KC8HYvv6UkCVYheYiTw9DD --- DEVLOG.md | 32 ++++++++++++++++++++++++++ backend/app/api/v1/endpoints/mangel.py | 4 +++- backend/tests/test_mangel.py | 30 ++++++++++++++++++++++++ frontend/src/pages/MangelListePage.tsx | 4 ++-- 4 files changed, 67 insertions(+), 3 deletions(-) diff --git a/DEVLOG.md b/DEVLOG.md index 3c7f0b9..80dad2f 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -4019,3 +4019,35 @@ Keine Commits in dieser Session. - frontend/src/pages/admin/ObjektSection.tsx | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- --- +## 2026-09-05 13:36 – 13:39 (2m) +**Beschreibung:** Claude Code Session +**Projekt:** asb-material + +### Commits +- e9904d5 feat(dashboard): drei fehlende Kacheln (Kennzahlen, Mängel, Qualifikationsablauf) + +### Geänderte Dateien +- DEVLOG.md | 22 ++++++++++++++++ +- backend/app/api/v1/endpoints/dashboard.py | 13 ++++++++++ +- backend/app/schemas/dashboard.py | 14 ++++++++++ +- backend/app/services/dashboard.py | 35 +++++++++++++++++++++++++ +- backend/tests/test_personal.py | 59 ++++++++++++++++++++++++++++++++++++++++++ +- frontend/src/pages/DashboardPage.tsx | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- + +--- +## 2026-09-05 13:41 – 13:41 (0m) +**Beschreibung:** Claude Code Session +**Projekt:** asb-material + +### Commits +Keine Commits in dieser Session. + +### Geänderte Dateien +- DEVLOG.md | 22 ++++++++++++++++ +- backend/app/api/v1/endpoints/dashboard.py | 13 ++++++++++ +- backend/app/schemas/dashboard.py | 14 ++++++++++ +- backend/app/services/dashboard.py | 35 +++++++++++++++++++++++++ +- backend/tests/test_personal.py | 59 ++++++++++++++++++++++++++++++++++++++++++ +- frontend/src/pages/DashboardPage.tsx | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- + +--- diff --git a/backend/app/api/v1/endpoints/mangel.py b/backend/app/api/v1/endpoints/mangel.py index 8ae59ff..02d0366 100644 --- a/backend/app/api/v1/endpoints/mangel.py +++ b/backend/app/api/v1/endpoints/mangel.py @@ -21,7 +21,9 @@ _mitarbeiter_plus = require_roles( RolleTyp.leitungsverantwortlicher, RolleTyp.administration, ) -_materialverantwortliche = require_roles(RolleTyp.administration, RolleTyp.materialverantwortlicher) +_materialverantwortliche = require_roles( + RolleTyp.administration, RolleTyp.materialverantwortlicher, RolleTyp.leitungsverantwortlicher +) @router.get("/maengel", response_model=list[MangelRead]) diff --git a/backend/tests/test_mangel.py b/backend/tests/test_mangel.py index a43506a..d807928 100644 --- a/backend/tests/test_mangel.py +++ b/backend/tests/test_mangel.py @@ -113,3 +113,33 @@ async def test_niedrige_prioritaet_blockiert_einsatzbereitschaft_nicht( "/api/v1/dashboard/einsatzbereitschaft", headers=auth_header(verantwortlicher_token) ) assert response.json()["einsatzbereit"] == 1 + + +@pytest.mark.asyncio +async def test_leitungsverantwortlicher_kann_status_aendern(client, objekt_mit_position, mitarbeiter_user, db_session): + from app.core.security import hash_password + from app.models.auth import Benutzer, BenutzerRolle, RolleTyp + + benutzer = Benutzer( + name="Test Leitung", login="leitung1", passwort_hash=hash_password("test-passwort-123"), aktiv=True + ) + db_session.add(benutzer) + await db_session.flush() + db_session.add(BenutzerRolle(benutzer_id=benutzer.id, rolle=RolleTyp.leitungsverantwortlicher)) + await db_session.flush() + + objekt, _material = objekt_mit_position + mitarbeiter_token = await login(client, "mitarbeiter1") + gemeldet = await client.post( + "/api/v1/maengel", + json={"objekt_id": objekt.id, "beschreibung": "Scheinwerfer defekt"}, + headers=auth_header(mitarbeiter_token), + ) + mangel_id = gemeldet.json()["id"] + + leitung_token = await login(client, "leitung1") + response = await client.patch( + f"/api/v1/maengel/{mangel_id}", json={"status": "erledigt"}, headers=auth_header(leitung_token) + ) + assert response.status_code == 200 + assert response.json()["status"] == "erledigt" diff --git a/frontend/src/pages/MangelListePage.tsx b/frontend/src/pages/MangelListePage.tsx index 56b1eed..eed1005 100644 --- a/frontend/src/pages/MangelListePage.tsx +++ b/frontend/src/pages/MangelListePage.tsx @@ -24,8 +24,8 @@ const STATUS_OPTIONEN: MangelStatus[] = [ // Erledigung verfolgen - jeder Mitarbeiter darf melden/lesen, Status ändern // bleibt Materialverantwortlichen+ vorbehalten (Backend erzwingt das). export function MangelListePage() { - const { istMaterialverantwortlich, istAdmin } = useAuth(); - const darfStatusAendern = istMaterialverantwortlich || istAdmin; + const { istMaterialverantwortlich, istLeitungsverantwortlich, istAdmin } = useAuth(); + const darfStatusAendern = istMaterialverantwortlich || istLeitungsverantwortlich || istAdmin; const [maengel, setMaengel] = useState([]); const [objekte, setObjekte] = useState([]);