Files
Vorrania/backend/app/routers/units.py
Scarriffle 794a81f58b Lagerorte und Einheiten umbenennen
Beide kannte die API bisher nur als Anlegen und Loeschen. Wer sich vertippt
hatte, musste den Eintrag wegwerfen und neu anlegen - und verlor dabei genau
das, was daran haengt: Chargen zeigen auf die Lagerort-ID, Produkte und Gruppen
auf die Einheiten-ID. Ein Tippfehler kostete also Zuordnungen.

Neu ist je ein PATCH nach dem Vorbild der Gebinde, samt Pruefung auf doppelte
Namen ohne Ruecksicht auf Gross- und Kleinschreibung. Anders als beim Loeschen
duerfen auch eingebaute Einheiten umbenannt werden - auch das wie bei den
Gebinden. Art und Faktor einer Einheit bleiben dagegen fest: Sie stecken in
bereits umgerechneten Bestaenden, eine Aenderung wuerde die still verfaelschen.

Die Tests halten fest, worum es eigentlich geht - dass die Verweise das
Umbenennen ueberleben.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 18:23:51 +02:00

85 lines
2.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy import func
from sqlalchemy.orm import Session
from ..database import get_db
from ..deps import get_current_user, require_admin
from ..models import Group, Product, Unit, User
from ..schemas import UnitCreate, UnitOut, UnitUpdate
router = APIRouter(prefix="/units", tags=["units"])
@router.get("", response_model=list[UnitOut])
def list_units(
db: Session = Depends(get_db), _: User = Depends(get_current_user)
) -> list[Unit]:
return db.query(Unit).order_by(Unit.kind, Unit.factor).all()
@router.post("", response_model=UnitOut, status_code=status.HTTP_201_CREATED)
def create_unit(
payload: UnitCreate,
db: Session = Depends(get_db),
_: User = Depends(require_admin),
) -> Unit:
exists = db.query(Unit).filter(func.lower(Unit.name) == payload.name.lower()).first()
if exists:
raise HTTPException(status.HTTP_409_CONFLICT, "Einheit existiert bereits")
unit = Unit(name=payload.name, kind=payload.kind, factor=payload.factor, is_builtin=False)
db.add(unit)
db.commit()
db.refresh(unit)
return unit
@router.patch("/{unit_id}", response_model=UnitOut)
def update_unit(
unit_id: int,
payload: UnitUpdate,
db: Session = Depends(get_db),
_: User = Depends(require_admin),
) -> Unit:
"""Umbenennen auch bei eingebauten Einheiten, wie bei den Gebinden.
Produkte und Gruppen verweisen ueber die ID und bleiben unberuehrt."""
unit = db.get(Unit, unit_id)
if unit is None:
raise HTTPException(status.HTTP_404_NOT_FOUND, "Einheit nicht gefunden")
name = payload.name.strip()
doppelt = (
db.query(Unit)
.filter(func.lower(Unit.name) == name.lower(), Unit.id != unit_id)
.first()
)
if doppelt is not None:
raise HTTPException(status.HTTP_409_CONFLICT, "Einheit existiert bereits")
unit.name = name
db.commit()
db.refresh(unit)
return unit
@router.delete("/{unit_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_unit(
unit_id: int,
db: Session = Depends(get_db),
_: User = Depends(require_admin),
) -> None:
unit = db.get(Unit, unit_id)
if unit is None:
raise HTTPException(status.HTTP_404_NOT_FOUND, "Einheit nicht gefunden")
if unit.is_builtin:
raise HTTPException(status.HTTP_400_BAD_REQUEST, "Eingebaute Einheiten können nicht gelöscht werden")
in_use = (
db.query(Product).filter(Product.display_unit_id == unit_id).first()
or db.query(Group).filter(Group.min_stock_unit_id == unit_id).first()
)
if in_use:
raise HTTPException(
status.HTTP_409_CONFLICT, "Einheit wird noch von Produkten/Gruppen verwendet"
)
db.delete(unit)
db.commit()