fix(dashboard): "nie kontrolliert" ging bei zusätzlichen Gründen verloren
_kategorie_und_gruende() zählte "noch_nie_kontrolliert" bisher nur, wenn es der EINZIGE Grund war - ein Objekt mit z.B. offenem Fehlbestand UND nie kontrolliert verlor den Hinweis komplett, landete nur unter "nicht einsatzbereit" ohne diesen Grund zu nennen. Jetzt immer als Zusatzgrund angehängt. Neues Feld nie_kontrolliert_gesamt liefert die tatsächliche Gesamtzahl über alle Kategorien hinweg, Dashboard nutzt sie statt der (bewusst engeren) "unbekannt"-Kategorie. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
This commit is contained in:
@@ -34,6 +34,7 @@ class EinsatzbereitschaftRead(BaseModel):
|
||||
unbekannt: int
|
||||
nicht_einsatzbereit: int
|
||||
gesamt: int
|
||||
nie_kontrolliert_gesamt: int
|
||||
details: list[ObjektMangelRead]
|
||||
|
||||
|
||||
|
||||
@@ -197,6 +197,7 @@ async def einsatzbereitschaft(db: AsyncSession) -> dict:
|
||||
)
|
||||
|
||||
bereit = eingeschraenkt = unbekannt = 0
|
||||
nie_kontrolliert_gesamt = 0
|
||||
details: list[dict] = []
|
||||
for objekt in objekte:
|
||||
kategorie, gruende = _kategorie_und_gruende(
|
||||
@@ -210,6 +211,8 @@ async def einsatzbereitschaft(db: AsyncSession) -> dict:
|
||||
objekt_ids_kritischer_mangel,
|
||||
objekt_ids_hu_uvv_ueberfaellig,
|
||||
)
|
||||
if "noch_nie_kontrolliert" in gruende:
|
||||
nie_kontrolliert_gesamt += 1
|
||||
if kategorie == "ready":
|
||||
bereit += 1
|
||||
else:
|
||||
@@ -225,6 +228,10 @@ async def einsatzbereitschaft(db: AsyncSession) -> dict:
|
||||
"unbekannt": unbekannt,
|
||||
"nicht_einsatzbereit": len(objekte) - bereit - eingeschraenkt - unbekannt,
|
||||
"gesamt": len(objekte),
|
||||
# Bug-Fund 2026-09-06: "unbekannt" zählt nur Objekte OHNE jeden anderen
|
||||
# Grund - diese Zahl zählt "nie kontrolliert" unabhängig von sonstigen
|
||||
# Problemen mit, damit sie beim manuellen Nachzählen stimmt.
|
||||
"nie_kontrolliert_gesamt": nie_kontrolliert_gesamt,
|
||||
"details": details,
|
||||
}
|
||||
|
||||
@@ -260,12 +267,23 @@ def _kategorie_und_gruende(
|
||||
if objekt.id in objekt_ids_hu_uvv_ueberfaellig:
|
||||
gruende.append("hu_uvv_ueberfaellig")
|
||||
|
||||
# Bug-Fund 2026-09-06 (Nutzer: "beim genauen Schauen sind es mehr"):
|
||||
# "noch nie kontrolliert" wurde bisher nur gezählt, wenn es der EINZIGE
|
||||
# Grund war - ein Objekt mit z.B. offenem Fehlbestand UND nie kontrolliert
|
||||
# verlor den Hinweis komplett (fiel unter "nicht einsatzbereit" ohne
|
||||
# diesen Grund zu nennen). Jetzt immer als Zusatzgrund angehängt, wenn
|
||||
# zutreffend, unabhängig von anderen Gründen.
|
||||
nie_kontrolliert = letzte_kontrolle is None
|
||||
|
||||
if not gruende and fehlbestand_ids and fehlbestand_ids <= fehlbestand_ids_genehmigt:
|
||||
return "limited", ["mindermenge_genehmigt"]
|
||||
if not gruende and letzte_kontrolle is None:
|
||||
zusatz = ["noch_nie_kontrolliert"] if nie_kontrolliert else []
|
||||
return "limited", ["mindermenge_genehmigt"] + zusatz
|
||||
if not gruende and nie_kontrolliert:
|
||||
return "unknown", ["noch_nie_kontrolliert"]
|
||||
if not gruende:
|
||||
return "ready", []
|
||||
if nie_kontrolliert:
|
||||
gruende = gruende + ["noch_nie_kontrolliert"]
|
||||
return "not-ready", gruende
|
||||
|
||||
|
||||
|
||||
@@ -186,6 +186,7 @@ async def test_nie_kontrolliertes_objekt_ist_unbekannt(
|
||||
assert body["unbekannt"] == 1
|
||||
assert body["nicht_einsatzbereit"] == 0
|
||||
assert body["details"][0]["gruende"] == ["noch_nie_kontrolliert"]
|
||||
assert body["nie_kontrolliert_gesamt"] == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -203,7 +204,11 @@ async def test_offener_fehlbestand_macht_objekt_nicht_einsatzbereit(
|
||||
body = response.json()
|
||||
assert body["einsatzbereit"] == 0
|
||||
assert body["nicht_einsatzbereit"] == 1
|
||||
assert body["details"][0]["gruende"] == ["fehlbestand_offen"]
|
||||
# Bug-Fund 2026-09-06: "nie kontrolliert" darf nicht verloren gehen, nur
|
||||
# weil das Objekt zusätzlich einen anderen Grund hat (objekt_mit_position
|
||||
# hat nie eine abgeschlossene Kontrolle).
|
||||
assert body["details"][0]["gruende"] == ["fehlbestand_offen", "noch_nie_kontrolliert"]
|
||||
assert body["nie_kontrolliert_gesamt"] == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -230,7 +235,8 @@ async def test_genehmigte_mindermenge_macht_objekt_eingeschraenkt_einsatzbereit(
|
||||
assert body["einsatzbereit"] == 0
|
||||
assert body["eingeschraenkt_einsatzbereit"] == 1
|
||||
assert body["nicht_einsatzbereit"] == 0
|
||||
assert body["details"][0]["gruende"] == ["mindermenge_genehmigt"]
|
||||
assert body["details"][0]["gruende"] == ["mindermenge_genehmigt", "noch_nie_kontrolliert"]
|
||||
assert body["nie_kontrolliert_gesamt"] == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -257,7 +263,8 @@ async def test_ueberfaellige_pruefung_macht_objekt_nicht_einsatzbereit(
|
||||
response = await client.get("/api/v1/dashboard/einsatzbereitschaft", headers=auth_header(token))
|
||||
body = response.json()
|
||||
assert body["nicht_einsatzbereit"] == 1
|
||||
assert body["details"][0]["gruende"] == ["pruefung_ueberfaellig"]
|
||||
assert body["details"][0]["gruende"] == ["pruefung_ueberfaellig", "noch_nie_kontrolliert"]
|
||||
assert body["nie_kontrolliert_gesamt"] == 1
|
||||
|
||||
prueftermine = await client.get("/api/v1/dashboard/prueftermine", headers=auth_header(token))
|
||||
prueftermine_body = prueftermine.json()
|
||||
|
||||
@@ -42,6 +42,7 @@ interface Einsatzbereitschaft {
|
||||
unbekannt: number;
|
||||
nicht_einsatzbereit: number;
|
||||
gesamt: number;
|
||||
nie_kontrolliert_gesamt: number;
|
||||
details: ObjektMangel[];
|
||||
}
|
||||
|
||||
@@ -130,8 +131,8 @@ export function DashboardPage() {
|
||||
ablaufdatenAbgelaufen > 0
|
||||
? { text: `${ablaufdatenAbgelaufen} Chargen abgelaufen`, ziel: null }
|
||||
: null,
|
||||
bereitschaft && bereitschaft.unbekannt > 0
|
||||
? { text: `${bereitschaft.unbekannt} Objekte noch nie kontrolliert`, ziel: "/objekte" }
|
||||
bereitschaft && bereitschaft.nie_kontrolliert_gesamt > 0
|
||||
? { text: `${bereitschaft.nie_kontrolliert_gesamt} Objekte noch nie kontrolliert`, ziel: "/objekte" }
|
||||
: null,
|
||||
].filter((a): a is { text: string; ziel: string | null } => a !== null);
|
||||
|
||||
@@ -176,6 +177,12 @@ export function DashboardPage() {
|
||||
<ReadinessBadge status="not-ready" label={`${bereitschaft.nicht_einsatzbereit} nicht bereit`} />
|
||||
)}
|
||||
</div>
|
||||
{bereitschaft.nie_kontrolliert_gesamt > bereitschaft.unbekannt && (
|
||||
<p className="text-muted" style={{ fontSize: "0.85rem" }}>
|
||||
Davon {bereitschaft.nie_kontrolliert_gesamt} insgesamt noch nie kontrolliert (auch bei Objekten mit
|
||||
weiteren Problemen).
|
||||
</p>
|
||||
)}
|
||||
{bereitschaft.details.length > 0 && (
|
||||
<>
|
||||
<button className="btn btn-secondary" onClick={() => setDetailsOffen(!detailsOffen)}>
|
||||
|
||||
Reference in New Issue
Block a user