"""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, ItemLoan from ..schemas import ItemOut from .loans import loan_to_out # 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 _offener(item: Item) -> ItemLoan | None: """Der laufende Verleih aus den schon geladenen Verleihen des Stücks. Bewusst über die Beziehung statt per eigener Abfrage: So bleibt die Einzelstück-Liste bei einer Abfrage, wenn der Aufrufer ``loans`` mitlädt. """ for loan in item.loans: if loan.returned_on is None: return loan return None def item_to_out(item: Item) -> ItemOut: """ItemOut inkl. Lagerort-/Shop-/Produktnamen und laufendem Verleih.""" 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 loan = _offener(item) out.loan = loan_to_out(loan) if loan is not None else None return out