"""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 _group_to_out, update_group from app.routers.views import group_shopping_list, shopping_list from app.schemas import GroupUpdate from app.services.min_stock import schreibe_ueberall @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 _ueberall(db, besitzer, menge_base: float) -> None: """Mindestbestand „Überall" setzen – Mengen immer in Basiseinheiten.""" schreibe_ueberall(db, besitzer, menge_base) db.commit() 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")) pesto = Product(name="Pesto", base_unit=BaseUnit.gram, package_size=195, package_label="Glas") db.add(pesto) db.commit() # kein Bestand -> es fehlt der volle Mindestbestand _ueberall(db, pesto, 500) (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_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) _ueberall(db, gruppe, 3 * 150) # 3 Gläser à 150 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_unit=_gramm(db)) db.add(gruppe) db.add(Product(name="Mehl 405", base_unit=BaseUnit.gram, group=gruppe)) db.commit() _ueberall(db, gruppe, 500) (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 laesst den physischen Bedarf unveraendert. Gespeichert wird in Basiseinheiten, deshalb bleiben die 500 g stehen und es ist NUR die Anzeige, die auf ~3,33 Glaeser wechselt. Frueher musste der gespeicherte Wert dafuer umgerechnet werden. """ gruppe = Group(name="Pesto", min_stock_unit=_gramm(db)) db.add(gruppe) db.add(Product(name="Pesto Barilla", base_unit=BaseUnit.gram, group=gruppe)) db.commit() _ueberall(db, gruppe, 500) 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 # Gespeichert unveraendert in Basiseinheiten … assert gruppe.location_min_stocks[0].min_stock == pytest.approx(500) # … angezeigt jetzt in Glaesern. assert _group_to_out(db, gruppe).min_stock == pytest.approx(500 / 150, abs=0.01)