feat(shopping): listShoppingList mit Aggregation + Skalierung
All checks were successful
Build & Publish Docker Image / build-and-push (push) Successful in 2m14s

This commit is contained in:
hsiegeln
2026-04-21 23:02:05 +02:00
parent 85bf197084
commit c31a9c6110
2 changed files with 98 additions and 4 deletions

View File

@@ -67,7 +67,9 @@ export function setCartServings(
).run(servings, recipeId);
}
export function listShoppingList(db: Database.Database): ShoppingListSnapshot {
export function listShoppingList(
db: Database.Database
): ShoppingListSnapshot {
const recipes = db
.prepare(
`SELECT cr.recipe_id, r.title, r.image_path, cr.servings,
@@ -77,9 +79,31 @@ export function listShoppingList(db: Database.Database): ShoppingListSnapshot {
ORDER BY cr.added_at ASC`
)
.all() as ShoppingCartRecipe[];
// TODO(Task 6): rows + uncheckedCount are populated by the aggregation query.
// Until then, callers must not rely on these fields.
return { recipes, rows: [], uncheckedCount: 0 };
const rows = db
.prepare(
`SELECT
LOWER(TRIM(i.name)) AS name_key,
LOWER(TRIM(COALESCE(i.unit, ''))) AS unit_key,
MIN(i.name) AS display_name,
MIN(i.unit) AS display_unit,
SUM(i.quantity * cr.servings * 1.0 / COALESCE(r.servings_default, cr.servings)) AS total_quantity,
GROUP_CONCAT(DISTINCT r.title) AS from_recipes,
EXISTS(
SELECT 1 FROM shopping_cart_check c
WHERE c.name_key = LOWER(TRIM(i.name))
AND c.unit_key = LOWER(TRIM(COALESCE(i.unit, '')))
) AS checked
FROM shopping_cart_recipe cr
JOIN recipe r ON r.id = cr.recipe_id
JOIN ingredient i ON i.recipe_id = r.id
GROUP BY name_key, unit_key
ORDER BY checked ASC, display_name COLLATE NOCASE`
)
.all() as ShoppingListRow[];
const uncheckedCount = rows.reduce((n, r) => n + (r.checked ? 0 : 1), 0);
return { recipes, rows, uncheckedCount };
}
export function toggleCheck(