Backend: globale Einzelstueck-Liste (GET /items) + Bild-Version an Produkten
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>
This commit is contained in:
@@ -2,8 +2,17 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from app.models import Category, CategoryTracking, Item, ItemDocument, Product, Role, User
|
||||
from app.routers.items import _safe_filename, create_items, get_item
|
||||
from app.models import (
|
||||
Category,
|
||||
CategoryTracking,
|
||||
Item,
|
||||
ItemDocument,
|
||||
Location,
|
||||
Product,
|
||||
Role,
|
||||
User,
|
||||
)
|
||||
from app.routers.items import _safe_filename, create_items, get_item, list_all_items
|
||||
from app.schemas import ItemCreate
|
||||
|
||||
|
||||
@@ -49,6 +58,28 @@ def test_item_out_listet_belege(db, admin):
|
||||
assert fresh.documents[0].content_type == "application/pdf"
|
||||
|
||||
|
||||
def test_list_all_items_angereichert(db, admin):
|
||||
cat = Category(name="Elektronik", tracking=CategoryTracking.object.value)
|
||||
db.add(cat)
|
||||
db.flush()
|
||||
product = Product(name="Kamera", brand="Sony", category_id=cat.id, individual=True)
|
||||
db.add(product)
|
||||
db.flush()
|
||||
ort = Location(name="Keller")
|
||||
db.add(ort)
|
||||
db.commit()
|
||||
create_items(product.id, ItemCreate(count=2, location_id=ort.id), db=db, _=admin)
|
||||
|
||||
alle = list_all_items(db=db, _=admin)
|
||||
assert len(alle) == 2
|
||||
e = alle[0]
|
||||
assert e.product_name == "Kamera"
|
||||
assert e.product_brand == "Sony"
|
||||
assert e.category_name == "Elektronik"
|
||||
assert e.location_id == ort.id
|
||||
assert e.location_name == "Keller"
|
||||
|
||||
|
||||
def test_safe_filename_entfernt_header_zeichen():
|
||||
assert _safe_filename('a"b\r\nc.pdf') == "abc.pdf"
|
||||
assert _safe_filename(" ") == "beleg"
|
||||
|
||||
@@ -17,6 +17,18 @@ def _artikel(db, url=None):
|
||||
return p
|
||||
|
||||
|
||||
def test_image_version_spiegelt_bildzeitstempel(db):
|
||||
from app.crud import product_to_out
|
||||
|
||||
p = _artikel(db)
|
||||
assert product_to_out(db, p).image_version is None # kein Bild
|
||||
img = ProductImage(product_id=p.id, content_type="image/png", data=EIN_PIXEL)
|
||||
db.add(img)
|
||||
db.commit()
|
||||
db.refresh(img)
|
||||
assert product_to_out(db, p).image_version == int(img.updated_at.timestamp())
|
||||
|
||||
|
||||
def test_ohne_bildadresse_gibt_es_nichts_zu_holen(db, monkeypatch):
|
||||
monkeypatch.setattr(images, "fetch", lambda url: (_ for _ in ()).throw(AssertionError))
|
||||
assert images.ensure(db, _artikel(db)) is None
|
||||
|
||||
Reference in New Issue
Block a user