Einkaufsliste: Fehlmenge als Gebinde (Glaeser/Dosen), Basiseinheit klein

Statt 'fehlt 500 Gramm' jetzt die Produktgroesse als Leitangabe:
'fehlt 3 Glaeser (500 g)'. Auf ganze Gebinde aufgerundet, weil man nur
ganze Glaeser/Dosen kauft; Basiseinheit als kleiner Hinweis.

Backend: neues ShoppingNeed-Objekt an jeder Einkaufslisten-Zeile (Produkte
+ Gruppen, gesamt + je Ort) - damit die Angabe auch direkt ueber die API
kommt ('x Glaeser (y g)'), inkl. Pluralisierung aus der Gebinde-Tabelle.
Gruppen leiten das Gebinde ab, wenn alle passenden Produkte dasselbe haben,
sonst bleibt es bei der Basiseinheit. Bestehende Felder unveraendert.

Frontend: gemeinsame Komponente ShoppingNeedText fuer Karte und volle Seite.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-08-07 18:03:37 +02:00
parent e214bb76a9
commit f2c657ff31
6 changed files with 294 additions and 29 deletions

View File

@@ -665,11 +665,29 @@ class ItemOut(BaseModel):
# ---- Views ----
class ShoppingNeed(BaseModel):
"""Fehlmenge als Gebinde-Leitangabe bei zaehlbaren Packungen (Glas/Dose)
auf ganze aufgerundet, weil man nur ganze Gebinde kauft mit der
Basiseinheit als kleinem Hinweis. So bekommen auch API-Konsumenten direkt
„1 Glas (500 g)", ohne selbst Packungsgroessen umzurechnen."""
text: str # Leitangabe: "1 Glas", "4 Dosen", "500 g"
hint: str = "" # Basiseinheit klein: "500 g" / "2 l" leer wenn identisch
count: float # aufgerundete Gebindezahl (zum Weiterrechnen)
label: str # zur count passendes, pluralisiertes Label
singular: str # Einzahl-Label ("Glas", "Gramm", …)
is_package: bool = False # zaehlbares Gebinde (Glas/Dose) vs. Basis-/Anzeigeeinheit
base_amount: float | None = None
base_unit: BaseUnit | None = None
stock: float # Bestand in derselben Leitangabe
min_stock: float # Mindestbestand in derselben Leitangabe
class ShoppingItem(BaseModel):
product_id: int
name: str
base_unit: BaseUnit
package_size: float | None = None
need: ShoppingNeed | None = None
stock: float
min_stock: float
deficit: float
@@ -699,6 +717,7 @@ class GroupShoppingItem(BaseModel):
deficit: float
unit_name: str = ""
product_count: int
need: ShoppingNeed | None = None
class LocationNeedProduct(BaseModel):
@@ -709,6 +728,7 @@ class LocationNeedProduct(BaseModel):
stock: float
min_stock: float
deficit: float
need: ShoppingNeed | None = None
class LocationNeedGroup(BaseModel):
@@ -718,6 +738,7 @@ class LocationNeedGroup(BaseModel):
stock: float
min_stock: float
deficit: float
need: ShoppingNeed | None = None
class LocationNeeds(BaseModel):