refactor: Code-Review-Fixes (Reuse/Simplification/Efficiency) aus dieser Session
CI / backend-tests (push) Successful in 1m57s
CI / frontend-build (push) Successful in 18s

4 parallele Review-Agenten (Reuse/Simplification/Efficiency/Altitude) gegen den
Diff dieser Session (c7dd47f...HEAD) laufen lassen, echte Funde angewendet:

- lager.py: 5x wiederholtes "db.get(...) or 404 raisen" durch _get_or_404()-
  Helper ersetzt
- akte.py: zwei Queries für Geräte-Instanzen (erst Positions-IDs, dann Geräte)
  zu einer Query mit Subquery zusammengefasst
- akte.py: manuelle Feld-für-Feld-Rekonstruktion von ObjektRead/HistorieRead
  durch model_validate()+model_copy() ersetzt (HistorieRead.benutzer_name
  bekommt dafür einen Default, harmlos für den bestehenden Endpunkt)
- vorlagen.py: doppelte "Positionen löschen + flush"-Logik (Vorlage-Löschen
  und Positionen-Ersetzen) in loesche_alle_positionen() zusammengeführt

Bewusst nicht angewendet:
- Zentrale Session-Rollback-Vereinheitlichung für die drei Pre-Check-Stellen
  (objekte.py Selbstbezug, geraet_instanz.py SN-Duplikat, lager.py Eltern-
  Selbstbezug) - der Altitude-Review schlug das vor, aber get_db() rollt in
  Produktion bei jeder Exception bereits korrekt zurück (jede Anfrage hat eine
  eigene Session); das PendingRollbackError-Problem trat nur in der geteilten
  Test-Session auf und wurde bereits gezielt per Pre-Check vermieden - eine
  zusätzliche zentrale Rollback-Schicht würde nichts mehr reparieren, was
  nicht schon repariert ist.
- Postgres-Cluster-Encoding (template1) auf beiden Hosts fixen, nicht nur in
  CI/für die eine migrierte DB - echter Infra-Eingriff, braucht Rücksprache.
- LagerSection.tsx "inkonsistente" Formular-Resets - beim genaueren Hinsehen
  gewolltes UX (Ort/Typ bleiben ausgewählt für mehrere Anlagen hintereinander).

140 Tests weiterhin grün.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
This commit is contained in:
2026-09-05 23:49:28 +02:00
co-authored by Claude Sonnet 5
parent a6f0c51842
commit 0c8f375a51
5 changed files with 51 additions and 62 deletions
+9 -10
View File
@@ -6,9 +6,15 @@ from app.api.deps import get_current_user, require_roles
from app.db.session import get_db
from app.models.auth import RolleTyp
from app.models.objekt import Objekt
from app.models.vorlage import Beladungsvorlage, Vorlagenposition
from app.models.vorlage import Beladungsvorlage
from app.schemas.vorlage import BeladungsvorlageCreate, BeladungsvorlageRead, VorlagenAenderung
from app.services.vorlagen import aktualisiere_positionen, erstelle_vorlage, hole_positionen, neue_version
from app.services.vorlagen import (
aktualisiere_positionen,
erstelle_vorlage,
hole_positionen,
loesche_alle_positionen,
neue_version,
)
router = APIRouter()
@@ -117,12 +123,5 @@ async def loesche_vorlage(
detail="Vorlage wird von mindestens einem Objekt verwendet und kann nicht gelöscht werden",
)
positionen = await db.execute(select(Vorlagenposition).where(Vorlagenposition.vorlage_id == vorlage_id))
for position in positionen.scalars().all():
await db.delete(position)
# Flush zwischen den Deletes nötig: Beladungsvorlage/Vorlagenposition haben
# keine ORM-relationship() (nur rohe FK-Spalten), SQLAlchemy kennt die
# Abhängigkeit also nicht automatisch und könnte beide DELETEs in falscher
# Reihenfolge absetzen (FK-Verletzung, beim echten Löschversuch gefunden).
await db.flush()
await loesche_alle_positionen(db, vorlage_id)
await db.delete(vorlage)