Einkauf: Abhaken legt Produkte in den Wagen, "Einkauf beenden" übernimmt sie
- Abgehakte Produkte bleiben auf der Einkaufsliste, rutschen durchgestrichen
nach unten ("Im Wagen") und lassen sich zurücknehmen
- Button "Einkauf beenden (n)" verschiebt alle abgehakten Produkte auf einmal
in den Vorrat derselben Liste (Mengen werden zusammengeführt)
- Haken wird gespeichert (Spalte checked, Migration ergänzt sie) und ist für
alle sichtbar, die die Liste sehen; erneut hinzugefügte Produkte verlieren
den Haken
- Einträge gleiten per View Transition an ihren neuen Platz (aus bei
"Animation: aus")
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b30acb652a
commit
f0e17b06b5
6 files changed
+109
-13
No files matched your search
+34
-2
@@ -34,6 +34,7 @@ def _item(row) -> dict:
|
||||
"listId": row["list_id"],
|
||||
"quantity": _out_quantity(row["quantity"], row["unit"]),
|
||||
"unit": row["unit"],
|
||||
"checked": bool(row["checked"]),
|
||||
"updatedAt": row["updated_at"],
|
||||
"updatedBy": {"id": row["updated_by"], "name": row["updated_by_name"]} if row["updated_by"] else None,
|
||||
}
|
||||
@@ -102,12 +103,16 @@ def _canonical_name(conn, name: str) -> str:
|
||||
|
||||
|
||||
def _add(conn, name: str, list_: str, list_id: int, quantity, unit: str, user_id: int) -> None:
|
||||
"""Produkt in den Vorrat bzw. Einkauf einer Liste setzen; steht es dort schon in derselben Einheit, wird die Menge erhöht."""
|
||||
"""Produkt in den Vorrat bzw. Einkauf einer Liste setzen; steht es dort schon in derselben Einheit, wird die Menge erhöht.
|
||||
|
||||
Kommt ein schon abgehaktes Produkt erneut auf die Einkaufsliste, ist der Haken wieder weg (es fehlt ja noch etwas).
|
||||
"""
|
||||
conn.execute(
|
||||
"""INSERT INTO household_items (key, name, list, list_id, quantity, unit, updated_at, updated_by)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT (list_id, key, list, unit) DO UPDATE SET
|
||||
quantity = MIN(ROUND(quantity + excluded.quantity, 2), ?),
|
||||
checked = 0,
|
||||
updated_at = excluded.updated_at,
|
||||
updated_by = excluded.updated_by""",
|
||||
(_key(name), name, list_, list_id, quantity, unit, now_iso(), user_id, MAX_QUANTITY),
|
||||
@@ -237,9 +242,20 @@ def add_item(data: dict = Body(...), user: dict = Depends(current_user)):
|
||||
|
||||
@router.patch("/api/haushalt/items/{item_id}")
|
||||
def update_item(item_id: int, data: dict = Body(...), user: dict = Depends(current_user)):
|
||||
"""Menge und/oder Einheit ändern. Beim Einheitenwechsel wird mit einer bestehenden Zeile zusammengeführt."""
|
||||
"""Menge und/oder Einheit ändern bzw. abhaken. Beim Einheitenwechsel wird mit einer bestehenden Zeile zusammengeführt."""
|
||||
with transaction() as conn:
|
||||
row = _get_item(conn, item_id, user)
|
||||
if "checked" in data:
|
||||
# Abhaken: liegt im Wagen, bleibt aber bis "Einkauf beenden" auf der Einkaufsliste
|
||||
if not isinstance(data["checked"], bool) or row["list"] != "einkauf":
|
||||
raise ValidationError("Nur Einträge auf der Einkaufsliste lassen sich abhaken.")
|
||||
conn.execute(
|
||||
"UPDATE household_items SET checked = ?, updated_at = ?, updated_by = ? WHERE id = ?",
|
||||
(int(data["checked"]), now_iso(), user["id"], item_id),
|
||||
)
|
||||
if len(data) == 1:
|
||||
return _state(conn, user)
|
||||
row = _get_item(conn, item_id, user)
|
||||
unit = _unit(data.get("unit", row["unit"]))
|
||||
if "quantity" in data:
|
||||
quantity = _quantity(data["quantity"], unit)
|
||||
@@ -274,6 +290,22 @@ def move_item(item_id: int, user: dict = Depends(current_user)):
|
||||
return _state(conn, user)
|
||||
|
||||
|
||||
@router.post("/api/haushalt/listen/{list_id}/einkauf-beenden")
|
||||
def finish_shopping(list_id: int, user: dict = Depends(current_user)):
|
||||
"""Alle abgehakten Einträge der Einkaufsliste auf einmal in den Vorrat dieser Liste übernehmen."""
|
||||
with transaction() as conn:
|
||||
_get_list(conn, list_id, user)
|
||||
rows = conn.execute(
|
||||
"SELECT * FROM household_items WHERE list_id = ? AND list = 'einkauf' AND checked = 1", (list_id,)
|
||||
).fetchall()
|
||||
if not rows:
|
||||
raise ValidationError("Nichts abgehakt – vielleicht hat gerade jemand anderes den Einkauf beendet.")
|
||||
for row in rows:
|
||||
conn.execute("DELETE FROM household_items WHERE id = ?", (row["id"],))
|
||||
_add(conn, row["name"], "vorrat", list_id, row["quantity"], row["unit"], user["id"])
|
||||
return {**_state(conn, user), "moved": len(rows)}
|
||||
|
||||
|
||||
@router.delete("/api/haushalt/items/{item_id}")
|
||||
def delete_item(item_id: int, user: dict = Depends(current_user)):
|
||||
with transaction() as conn:
|
||||
|
||||
Reference in new issue
Block a user