feat(maintenance): MAINT-Epic (Wartungspläne/-aufträge, Werkstatt) + Akte-Redesign
Neues Wartungskonzept: Wartungsplan+Position+Intervall (zeit/km/ Betriebsstunden, kombinierbar - fällig sobald ein Kriterium erreicht ist), Wartungsauftrag mit intern/externer Werkstatt, Status offen/ in_arbeit/erledigt, Kosten, Historie, Dokument-Anhang. Ad-hoc-Aufträge ohne Plan möglich (z.B. kleinere Reparatur). Admin-Tab "Wartungspläne". Objektakte-Redesign (Epic 21, Nutzer-Feedback "wirkt nicht modern"): CSS-Grid statt Karten-Stapel, einspaltig mobil, zweispaltig ab 900px; Fahrzeug-Objekte zeigen Wartung/Fahrzeugdaten prominent, Geräte/ Rucksäcke die Beladung. Dabei gefundene Lücke: Beladung (Soll/Ist je Position) fehlte in der Akte komplett, nur über eine laufende Kontrolle sichtbar - jetzt eigene Karte. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
This commit is contained in:
@@ -9,9 +9,10 @@ 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 Objekttyp, Standort
|
||||
from app.models.stammdaten import Material, Objekttyp, Standort
|
||||
from app.models.vorlage import Vorlagenposition
|
||||
from app.models.zustaendigkeit import Kontrollverantwortung, Zustaendigkeit
|
||||
from app.schemas.akte import AkteRead, ZustaendigerBenutzer
|
||||
from app.schemas.akte import AkteRead, BeladungsPosition, ZustaendigerBenutzer
|
||||
from app.schemas.dokument import DokumentRead
|
||||
from app.schemas.geraet_instanz import GeraetInstanzRead
|
||||
from app.schemas.historie import HistorieRead
|
||||
@@ -19,7 +20,7 @@ from app.schemas.mangel import MangelRead
|
||||
from app.schemas.objekt import FahrzeugdetailsRead, ObjektRead
|
||||
from app.schemas.zustaendigkeit import KontrollverantwortungRead
|
||||
from app.services.dashboard import objekt_readiness
|
||||
from app.services.objekte import letzte_kontrollen_map
|
||||
from app.services.objekte import letzte_kontrollen_map, sollmenge_effektiv
|
||||
|
||||
|
||||
async def _zustaendige_benutzer(db: AsyncSession, objekt: Objekt) -> list[ZustaendigerBenutzer]:
|
||||
@@ -90,6 +91,31 @@ async def akte_fuer_objekt(db: AsyncSession, objekt_id: int) -> AkteRead | None:
|
||||
|
||||
maengel_result = await db.execute(select(Mangel).where(Mangel.objekt_id == objekt_id))
|
||||
|
||||
fach_by_material_id: dict[int, str | None] = {}
|
||||
if objekt.vorlage_id is not None:
|
||||
vorlagenpositionen_result = await db.execute(
|
||||
select(Vorlagenposition).where(Vorlagenposition.vorlage_id == objekt.vorlage_id)
|
||||
)
|
||||
fach_by_material_id = {vp.material_id: vp.fach for vp in vorlagenpositionen_result.scalars().all()}
|
||||
|
||||
beladung_result = await db.execute(
|
||||
select(Objektposition, Material)
|
||||
.join(Material, Objektposition.material_id == Material.id)
|
||||
.where(Objektposition.objekt_id == objekt_id)
|
||||
)
|
||||
beladung = [
|
||||
BeladungsPosition(
|
||||
objektposition_id=position.id,
|
||||
material_id=material.id,
|
||||
material_name=material.name,
|
||||
einheit=material.einheit,
|
||||
fach=fach_by_material_id.get(material.id),
|
||||
sollmenge=sollmenge_effektiv(position),
|
||||
istmenge=position.istmenge,
|
||||
)
|
||||
for position, material in beladung_result.all()
|
||||
]
|
||||
|
||||
readiness = await objekt_readiness(db, objekt_id)
|
||||
|
||||
objekt_read = ObjektRead.model_validate(objekt).model_copy(
|
||||
@@ -115,4 +141,5 @@ async def akte_fuer_objekt(db: AsyncSession, objekt_id: int) -> AkteRead | None:
|
||||
dokumente=[DokumentRead.model_validate(d) for d in dokumente_result.scalars().all()],
|
||||
geraete=[GeraetInstanzRead.model_validate(g) for g in geraete],
|
||||
maengel=[MangelRead.model_validate(m) for m in maengel_result.scalars().all()],
|
||||
beladung=beladung,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user