Gruppen bekommen ein eigenes Richt-Gebinde (package_size/label) plus min_stock_in_packages. Weil die Produkte einer Gruppe unterschiedlich große Packungen haben können (Pesto 99 g vs. 160 g), legt die Gruppe einen gemeinsamen Richtwert fest (1 Glas ≈ X g). - Neuer Helfer group_min_context() zentralisiert, in welcher Einheit der Gruppen-Mindestbestand zaehlt (Gebinde ODER verwaltete Einheit). - Einkaufsliste (gesamt + je Ort), Dashboard-Bedarf und GroupOut nutzen ihn; need.text kommt so als 'x Glaeser (y g)'. - update_group rechnet bestehende Werte beim Umschalten der Einheit um, damit der physische Bedarf gleich bleibt. - Migration: groups.package_size/package_label/min_stock_in_packages. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
91 lines
3.4 KiB
Python
91 lines
3.4 KiB
Python
"""Einkaufsliste: Fehlmenge als Gebinde-Leitangabe (auf ganze Packungen
|
||
aufgerundet) mit der Basiseinheit als kleinem Hinweis – „3 Gläser (450 g)".
|
||
|
||
Produkte tragen ihre eigene Packungsgröße; Gruppen legen ein eigenes
|
||
Gruppen-Gebinde als Richtwert fest (weil ihre Produkte unterschiedlich große
|
||
Packungen haben können).
|
||
"""
|
||
|
||
import pytest
|
||
|
||
from app.models import BaseUnit, Group, PackageType, Product, Role, Unit, User
|
||
from app.routers.groups import update_group
|
||
from app.routers.views import group_shopping_list, shopping_list
|
||
from app.schemas import GroupUpdate
|
||
|
||
|
||
@pytest.fixture()
|
||
def user(db):
|
||
person = User(username="tester", password_hash="x", role=Role.admin)
|
||
db.add(person)
|
||
db.commit()
|
||
db.refresh(person)
|
||
return person
|
||
|
||
|
||
def _gramm(db) -> Unit:
|
||
return db.query(Unit).filter(Unit.name == "Gramm").one()
|
||
|
||
|
||
def test_produkt_bedarf_in_ganzen_gebinden(db, user):
|
||
"""500 g fehlen bei 195-g-Gläsern -> 3 Gläser (aufgerundet), 500 g als Hinweis."""
|
||
db.add(PackageType(singular="Glas", plural="Gläser"))
|
||
db.add(Product(name="Pesto", base_unit=BaseUnit.gram, package_size=195,
|
||
package_label="Glas", min_stock=500))
|
||
db.commit() # kein Bestand -> es fehlt der volle Mindestbestand
|
||
|
||
(item,) = shopping_list(db=db, _=user)
|
||
assert item.need is not None
|
||
assert item.need.is_package is True
|
||
assert item.need.count == 3 # ceil(500 / 195)
|
||
assert item.need.text == "3 Gläser"
|
||
assert item.need.hint == "500 g"
|
||
|
||
|
||
def test_gruppe_mit_gruppen_gebinde(db, user):
|
||
"""Gruppe mit eigenem Richt-Gebinde (1 Glas ≈ 150 g), Mindestbestand 3 Gläser."""
|
||
db.add(PackageType(singular="Glas", plural="Gläser"))
|
||
gruppe = Group(name="Pesto alla Genovese", min_stock=3, min_stock_unit=_gramm(db),
|
||
package_size=150, package_label="Glas", min_stock_in_packages=True)
|
||
db.add(gruppe)
|
||
db.add(Product(name="Pesto Barilla", base_unit=BaseUnit.gram, package_size=99, group=gruppe))
|
||
db.commit() # kein Bestand -> es fehlen 3 Gläser (450 g)
|
||
|
||
(item,) = group_shopping_list(db=db, _=user)
|
||
assert item.need is not None
|
||
assert item.need.is_package is True
|
||
assert item.need.count == 3
|
||
assert item.need.text == "3 Gläser"
|
||
assert item.need.hint == "450 g" # 3 * 150 g
|
||
|
||
|
||
def test_gruppe_ohne_gebinde_bleibt_basiseinheit(db, user):
|
||
"""Ohne aktives Gruppen-Gebinde bleibt es bei der verwalteten Einheit."""
|
||
gruppe = Group(name="Mehl", min_stock=500, min_stock_unit=_gramm(db))
|
||
db.add(gruppe)
|
||
db.add(Product(name="Mehl 405", base_unit=BaseUnit.gram, group=gruppe))
|
||
db.commit()
|
||
|
||
(item,) = group_shopping_list(db=db, _=user)
|
||
assert item.need is not None
|
||
assert item.need.is_package is False
|
||
assert item.need.text == "500 Gramm"
|
||
assert item.need.hint == ""
|
||
|
||
|
||
def test_gruppe_umschalten_haelt_physischen_bedarf(db, user):
|
||
"""Umschalten g -> Gebinde rechnet den gespeicherten Wert um (500 g / 150 = 3,33 Glas)."""
|
||
gruppe = Group(name="Pesto", min_stock=500, min_stock_unit=_gramm(db))
|
||
db.add(gruppe)
|
||
db.add(Product(name="Pesto Barilla", base_unit=BaseUnit.gram, group=gruppe))
|
||
db.commit()
|
||
|
||
update_group(
|
||
group_id=gruppe.id,
|
||
payload=GroupUpdate(min_stock_in_packages=True, package_size=150, package_label="Glas"),
|
||
db=db, _=user,
|
||
)
|
||
db.refresh(gruppe)
|
||
assert gruppe.min_stock_in_packages is True
|
||
assert gruppe.min_stock == pytest.approx(500 / 150, abs=0.01) # ~3,33 Gläser
|