Neuer Endpoint GET /items liefert alle Einzelstuecke ueber alle Produkte, angereichert mit Produkt-, Kategorie-, Lagerort- und Shop-Angaben (Beziehungen vorgeladen). ItemOut bekommt category_id/category_name. ProductOut bekommt image_version (Epoch der letzten Bildaenderung, None ohne Bild) - identisch zum ETag der Bild-Route, damit Clients Bilder cachen und nur bei Aenderung neu laden. Grundlage fuer die neue Einzelstueck-Liste (Web+iOS) und den iOS-Bild-Cache. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
35 lines
1.2 KiB
Python
35 lines
1.2 KiB
Python
"""Einzelstücke (Items): UID-Erzeugung und Anreicherung für die Ausgabe."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import secrets
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
from ..models import Item
|
|
from ..schemas import ItemOut
|
|
|
|
# Ohne 0/O/1/I/L, damit die UID auf einem Etikett eindeutig lesbar bleibt.
|
|
_ALPHABET = "ABCDEFGHJKMNPQRSTUVWXYZ23456789"
|
|
|
|
|
|
def generate_uid(db: Session, length: int = 8) -> str:
|
|
"""Kurze, eindeutige UID erzeugen (bei Kollision neu würfeln)."""
|
|
while True:
|
|
code = "".join(secrets.choice(_ALPHABET) for _ in range(length))
|
|
if db.query(Item).filter(Item.uid == code).first() is None:
|
|
return code
|
|
|
|
|
|
def item_to_out(item: Item) -> ItemOut:
|
|
"""ItemOut inkl. Lagerort-/Shop-/Produktnamen für die Anzeige."""
|
|
out = ItemOut.model_validate(item)
|
|
out.location_name = item.location.name if item.location else None
|
|
out.shop_name = item.shop.name if item.shop else None
|
|
out.product_name = item.product.name if item.product else None
|
|
out.product_brand = item.product.brand if item.product else None
|
|
kategorie = item.product.category if item.product else None
|
|
out.category_id = kategorie.id if kategorie else None
|
|
out.category_name = kategorie.name if kategorie else None
|
|
return out
|