fix(akte): Beladung zeigt bei Geräten mit SN falsche Ist-Menge
CI / backend-tests (push) Failing after 2m2s
CI / frontend-build (push) Successful in 18s

Objektposition.istmenge bleibt bei materialtyp='geraet_sn' auf 0 -
die tatsächliche Ist-Menge ergibt sich aus der Anzahl einsatzbereiter
geraet_instanz-Zeilen (Karte 14). Die neue Beladung-Karte in der Akte
zeigte den rohen istmenge-Wert, also immer 0 statt z.B. 1 Defibrillator
oder 2 Sauerstoffflaschen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
This commit is contained in:
2026-09-06 23:31:18 +02:00
co-authored by Claude Sonnet 5
parent a12dfb305e
commit 300b30e0b1
2 changed files with 77 additions and 3 deletions
+14 -3
View File
@@ -4,12 +4,12 @@ from sqlalchemy.ext.asyncio import AsyncSession
from app.models.auth import Benutzer
from app.models.dokument import Dokument
from app.models.fahrzeugdetails import Fahrzeugdetails
from app.models.geraet_instanz import GeraetInstanz
from app.models.geraet_instanz import GeraetInstanz, GeraetStatus
from app.models.historie import Historie
from app.models.mangel import Mangel
from app.models.objekt import Objekt
from app.models.objektposition import Objektposition
from app.models.stammdaten import Material, Objekttyp, Standort
from app.models.stammdaten import Material, MaterialTyp, Objekttyp, Standort
from app.models.vorlage import Vorlagenposition
from app.models.zustaendigkeit import Kontrollverantwortung, Zustaendigkeit
from app.schemas.akte import AkteRead, BeladungsPosition, ZustaendigerBenutzer
@@ -98,6 +98,13 @@ async def akte_fuer_objekt(db: AsyncSession, objekt_id: int) -> AkteRead | None:
)
fach_by_material_id = {vp.material_id: vp.fach for vp in vorlagenpositionen_result.scalars().all()}
einsatzbereite_geraete_je_position: dict = {}
for geraet in geraete:
if geraet.status == GeraetStatus.einsatzbereit:
einsatzbereite_geraete_je_position[geraet.objektposition_id] = (
einsatzbereite_geraete_je_position.get(geraet.objektposition_id, 0) + 1
)
beladung_result = await db.execute(
select(Objektposition, Material)
.join(Material, Objektposition.material_id == Material.id)
@@ -111,7 +118,11 @@ async def akte_fuer_objekt(db: AsyncSession, objekt_id: int) -> AkteRead | None:
einheit=material.einheit,
fach=fach_by_material_id.get(material.id),
sollmenge=sollmenge_effektiv(position),
istmenge=position.istmenge,
istmenge=(
einsatzbereite_geraete_je_position.get(position.id, 0)
if material.materialtyp == MaterialTyp.geraet_sn
else position.istmenge
),
)
for position, material in beladung_result.all()
]
+63
View File
@@ -69,6 +69,69 @@ async def test_akte_readiness_unbekannt_bei_nie_kontrolliert(client, objekt_mit_
assert body["einsatzbereitschaft_status"] != "ready"
@pytest.mark.asyncio
async def test_beladung_zeigt_einsatzbereite_geraete_als_istmenge(client, db_session, admin_user, hauptserver_id):
"""Ein Objektposition.istmenge bleibt bei materialtyp='geraet_sn' auf 0
stehen (nie über Kontroll-Zähler erfasst) - die Akte muss stattdessen die
Anzahl einsatzbereiter geraet_instanz-Zeilen zeigen."""
from sqlalchemy import select
from app.models.geraet_instanz import GeraetInstanz, GeraetStatus
from app.models.objektposition import Objektposition
from app.models.stammdaten import Bereich, MaterialTyp, Objekttyp, Standort
from app.models.stammdaten import Material as MaterialModel
from app.services.objekte import objekt_aus_vorlage
from app.services.vorlagen import erstelle_vorlage
from app.schemas.vorlage import VorlagenpositionCreate
bereich = Bereich(name="Bereich-Geraet")
db_session.add(bereich)
await db_session.flush()
objekttyp = Objekttyp(bereich_id=bereich.id, name="Typ-Geraet")
db_session.add(objekttyp)
await db_session.flush()
material = MaterialModel(name="Defibrillator", einheit="Stück", materialtyp=MaterialTyp.geraet_sn)
db_session.add(material)
await db_session.flush()
standort = Standort(name="Standort-Geraet")
db_session.add(standort)
await db_session.flush()
vorlage = await erstelle_vorlage(
db_session,
objekttyp_id=objekttyp.id,
name="Vorlage-Geraet",
positionen=[VorlagenpositionCreate(material_id=material.id, sollmenge=1)],
)
objekt = await objekt_aus_vorlage(
db_session,
code="GERAET-01",
name="Geraet-Objekt",
standort_id=standort.id,
vorlage=vorlage,
zustaendiger_server_id=hauptserver_id,
)
result = await db_session.execute(
select(Objektposition).where(
Objektposition.objekt_id == objekt.id, Objektposition.material_id == material.id
)
)
position = result.scalar_one()
db_session.add(
GeraetInstanz(objektposition_id=position.id, seriennummer="SN-1", status=GeraetStatus.einsatzbereit)
)
db_session.add(
GeraetInstanz(objektposition_id=position.id, seriennummer="SN-2", status=GeraetStatus.defekt)
)
await db_session.flush()
token = await login(client, "admin1")
antwort = await client.get(f"/api/v1/akte/objekt/{objekt.id}", headers=auth_header(token))
body = antwort.json()
assert body["beladung"][0]["istmenge"] == "1"
@pytest.mark.asyncio
async def test_akte_unbekanntes_objekt_ist_404(client, admin_user):
token = await login(client, "admin1")