fix(akte): Beladung zeigt bei Geräten mit SN falsche Ist-Menge
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:
@@ -4,12 +4,12 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
|||||||
from app.models.auth import Benutzer
|
from app.models.auth import Benutzer
|
||||||
from app.models.dokument import Dokument
|
from app.models.dokument import Dokument
|
||||||
from app.models.fahrzeugdetails import Fahrzeugdetails
|
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.historie import Historie
|
||||||
from app.models.mangel import Mangel
|
from app.models.mangel import Mangel
|
||||||
from app.models.objekt import Objekt
|
from app.models.objekt import Objekt
|
||||||
from app.models.objektposition import Objektposition
|
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.vorlage import Vorlagenposition
|
||||||
from app.models.zustaendigkeit import Kontrollverantwortung, Zustaendigkeit
|
from app.models.zustaendigkeit import Kontrollverantwortung, Zustaendigkeit
|
||||||
from app.schemas.akte import AkteRead, BeladungsPosition, ZustaendigerBenutzer
|
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()}
|
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(
|
beladung_result = await db.execute(
|
||||||
select(Objektposition, Material)
|
select(Objektposition, Material)
|
||||||
.join(Material, Objektposition.material_id == Material.id)
|
.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,
|
einheit=material.einheit,
|
||||||
fach=fach_by_material_id.get(material.id),
|
fach=fach_by_material_id.get(material.id),
|
||||||
sollmenge=sollmenge_effektiv(position),
|
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()
|
for position, material in beladung_result.all()
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -69,6 +69,69 @@ async def test_akte_readiness_unbekannt_bei_nie_kontrolliert(client, objekt_mit_
|
|||||||
assert body["einsatzbereitschaft_status"] != "ready"
|
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
|
@pytest.mark.asyncio
|
||||||
async def test_akte_unbekanntes_objekt_ist_404(client, admin_user):
|
async def test_akte_unbekanntes_objekt_ist_404(client, admin_user):
|
||||||
token = await login(client, "admin1")
|
token = await login(client, "admin1")
|
||||||
|
|||||||
Reference in New Issue
Block a user