Files
Vorrania/backend/tests/test_locations.py
Scarriffle d518b4aa23 Lagerorte per 10-Zeichen-Code statt fortlaufender ID; iOS-Einlagern ohne Kamerazwang
Lagerort-IDs sind jetzt ein zufaelliger 10-Zeichen-Code (wie die Einzelstueck-UIDs) statt einer fortlaufenden Zahl - so kollidiert die Stammdaten-Sicherung zwischen zwei Instanzen praktisch nie mehr, und der Code ist zugleich der Inhalt des QR /l/<code>. Alle Fremdschluessel (lots, movements, items, Mindestbestaende, parent_id) ziehen mit; die Umstellung laeuft einmalig und transaktional beim Serverstart (_migrate_locations_to_code) und rollt bei Fehlern komplett zurueck. Vor dem Deploy ein DB-Backup machen.

iOS-Einlagern oeffnet nicht mehr sofort die Kamera, sondern ein Formular mit Artikelsuche; die Kamera kommt erst per Button. Im Formular laesst sich der Lagerort zusaetzlich per /l/-QR scannen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 12:15:25 +02:00

83 lines
2.6 KiB
Python
Raw 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.
"""Lagerorte: Umbenennen und Umhängen (mit Schutz vor Ringen)."""
import pytest
from fastapi import HTTPException
from app.models import Location, Role, User
from app.routers.locations import update_location
from app.schemas import LocationUpdate
@pytest.fixture()
def admin(db):
person = User(username="admin", password_hash="x", role=Role.admin)
db.add(person)
db.commit()
db.refresh(person)
return person
def _orte(db):
"""Keller → Regal → Fach."""
keller = Location(name="Keller")
db.add(keller)
db.flush()
regal = Location(name="Regal", parent_id=keller.id)
db.add(regal)
db.flush()
fach = Location(name="Fach", parent_id=regal.id)
db.add(fach)
db.commit()
return keller, regal, fach
def test_neuer_ort_bekommt_10_zeichen_code_als_id(db):
ort = Location(name="Speisekammer")
db.add(ort)
db.commit()
# Statt fortlaufender Zahl trägt der Lagerort einen zufälligen Code das
# macht Sicherung/Import zwischen zwei Instanzen konfliktfrei.
assert isinstance(ort.id, str)
assert len(ort.id) == 10
assert set(ort.id) <= set("ABCDEFGHJKMNPQRSTUVWXYZ23456789")
def test_umbenennen_ohne_parent_bleibt_hierarchie(db, admin):
keller, regal, _ = _orte(db)
out = update_location(regal.id, LocationUpdate(name="Regal links"), db=db, _=admin)
assert out.name == "Regal links"
assert out.parent_id == keller.id # Umhängen war nicht gemeint
def test_umhaengen_setzt_neuen_parent(db, admin):
keller, _, fach = _orte(db)
out = update_location(fach.id, LocationUpdate(parent_id=keller.id), db=db, _=admin)
assert out.parent_id == keller.id
def test_umhaengen_auf_oberste_ebene(db, admin):
_, regal, _ = _orte(db)
out = update_location(regal.id, LocationUpdate(parent_id=None), db=db, _=admin)
assert out.parent_id is None
def test_umhaengen_auf_sich_selbst_wird_abgelehnt(db, admin):
keller, _, _ = _orte(db)
with pytest.raises(HTTPException) as ex:
update_location(keller.id, LocationUpdate(parent_id=keller.id), db=db, _=admin)
assert ex.value.status_code == 400
def test_umhaengen_in_eigenen_unterort_wird_abgelehnt(db, admin):
keller, _, fach = _orte(db)
with pytest.raises(HTTPException) as ex:
update_location(keller.id, LocationUpdate(parent_id=fach.id), db=db, _=admin)
assert ex.value.status_code == 400
def test_umhaengen_auf_unbekannten_ort_ist_404(db, admin):
_, _, fach = _orte(db)
with pytest.raises(HTTPException) as ex:
update_location(fach.id, LocationUpdate(parent_id="ZZZZZZZZZZ"), db=db, _=admin)
assert ex.value.status_code == 404