From ef9200f65b4123bd2ef6a65dc134f40192d4d27b Mon Sep 17 00:00:00 2001 From: Claus Dethlefsen Date: Wed, 22 Apr 2026 16:12:23 +0200 Subject: [PATCH] Fix Mealie shopping refresh flow with bulk recipe import and Bilka outputs --- dashboards/views/04c_madplan.yaml | 2 +- include/automations/mealie.yaml | 6 +- include/scripts/mealie_shopping.yaml | 8 + python_scripts/mealie_shopping_merge.py | 135 +++++- www/bilka_togo_checklist.json | 607 ++++++++++++++++++++++++ www/bilka_togo_checklist.md | 102 ++++ www/bilka_togo_checklist_bilka.md | 102 ++++ www/mealie.json | 2 +- 8 files changed, 949 insertions(+), 15 deletions(-) create mode 100644 include/scripts/mealie_shopping.yaml create mode 100644 www/bilka_togo_checklist.json create mode 100644 www/bilka_togo_checklist.md create mode 100644 www/bilka_togo_checklist_bilka.md diff --git a/dashboards/views/04c_madplan.yaml b/dashboards/views/04c_madplan.yaml index 3d646f7..a2a92c6 100644 --- a/dashboards/views/04c_madplan.yaml +++ b/dashboards/views/04c_madplan.yaml @@ -144,7 +144,7 @@ cards: icon: mdi:cart-check tap_action: action: call-service - service: shell_command.mealie_shopping_merge + service: script.mealie_shopping_refresh - type: iframe url: /local/bilka_togo_checklist_bilka.md diff --git a/include/automations/mealie.yaml b/include/automations/mealie.yaml index 93239d8..bb7b9bf 100644 --- a/include/automations/mealie.yaml +++ b/include/automations/mealie.yaml @@ -18,8 +18,4 @@ weekday: - wed action: - - service: shell_command.mealie_shopping_merge - - service: notify.mobile_app_claus_iphone_15pro - data: - title: "Bilka ToGo liste er klar" - message: "Kryds-af listen er opdateret. Åbn Madplan-dashboardet for at gennemgå hvad I mangler." + - service: script.mealie_shopping_refresh diff --git a/include/scripts/mealie_shopping.yaml b/include/scripts/mealie_shopping.yaml new file mode 100644 index 0000000..0a26b6e --- /dev/null +++ b/include/scripts/mealie_shopping.yaml @@ -0,0 +1,8 @@ +mealie_shopping_refresh: + alias: Mealie shopping refresh + sequence: + - service: shell_command.mealie_shopping_merge + - service: notify.mobile_app_claus_iphone_15pro + data: + title: "Bilka ToGo liste opdateret" + message: "Mealie-indkøb (fredag til torsdag) er flettet med Keep-basislisten." diff --git a/python_scripts/mealie_shopping_merge.py b/python_scripts/mealie_shopping_merge.py index 968426b..a61a8c6 100644 --- a/python_scripts/mealie_shopping_merge.py +++ b/python_scripts/mealie_shopping_merge.py @@ -1,5 +1,9 @@ #!/usr/bin/env python3 -"""Merge Mealie shopping items with a local Google Keep base list. +"""Build and merge shopping list for Bilka ToGo. + +Flow: +1) Build Mealie shopping list from meal plan entries in the Friday-Thursday window. +2) Merge those Mealie shopping items with a local Google Keep base list. Output: - /www/bilka_togo_checklist.md @@ -13,10 +17,13 @@ import json import re import urllib.request from collections import defaultdict +from datetime import date, timedelta from pathlib import Path ROOT_CANDIDATES = [Path('/Volumes/homeassistant'), Path('/config')] +MEALIE_BASE_URL = 'http://10.0.0.142:9925' +TARGET_SHOPPING_LIST_NAME = 'Bilka ToGo' CATEGORY_RULES = { 'frugt & grønt': ['banan', 'aeble', 'æble', 'citron', 'lime', 'tomat', 'salat', 'agurk', 'gulerod', 'kartoffel', 'log', 'løg', 'hvidlog', 'hvidløg', 'broccoli', 'spidskal', 'spidskål', 'avocado', 'peberfrugt'], 'kød & fisk': ['kylling', 'oksekød', 'hakket', 'ribeye', 'bacon', 'laks', 'fisk', 'skinke', 'pølse'], @@ -53,6 +60,30 @@ def api_get(url: str, token: str) -> dict: return json.loads(raw) if raw else {} +def api_request( + base_url: str, + path: str, + token: str, + method: str = 'GET', + payload: dict | list | None = None, + timeout: int = 90, +): + data = None + headers = {'Authorization': token} + if payload is not None: + data = json.dumps(payload).encode('utf-8') + headers['Content-Type'] = 'application/json' + req = urllib.request.Request(f'{base_url}{path}', headers=headers, data=data, method=method) + with urllib.request.urlopen(req, timeout=timeout) as resp: + raw = resp.read() + if not raw: + return {} + try: + return json.loads(raw) + except json.JSONDecodeError: + return {} + + def normalize_name(value: str) -> str: value = value.lower().strip() value = value.replace('å', 'aa').replace('æ', 'ae').replace('ø', 'oe') @@ -82,9 +113,83 @@ def read_keep_items(keep_path: Path) -> list[str]: return items -def fetch_mealie_items(base_url: str, token: str) -> list[dict]: - data = api_get(f'{base_url}/api/households/shopping/items?perPage=500', token) - return data.get('items', []) or [] +def friday_to_thursday_window(today: date) -> tuple[date, date]: + days_until_friday = (4 - today.weekday()) % 7 + start = today + timedelta(days=days_until_friday) + end = start + timedelta(days=6) + return start, end + + +def ensure_shopping_list(base_url: str, token: str, name: str) -> str: + lists = api_request(base_url, '/api/households/shopping/lists?perPage=200', token).get('items', []) or [] + for shopping_list in lists: + if (shopping_list.get('name') or '').strip().lower() == name.lower(): + return shopping_list['id'] + + created = api_request( + base_url, + '/api/households/shopping/lists', + token, + method='POST', + payload={'name': name}, + ) + return created['id'] + + +def clear_shopping_list_items(base_url: str, token: str, shopping_list_id: str) -> None: + items = api_request(base_url, '/api/households/shopping/items?perPage=1000', token).get('items', []) or [] + for item in items: + if item.get('shoppingListId') == shopping_list_id and item.get('id'): + api_request(base_url, f"/api/households/shopping/items/{item['id']}", token, method='DELETE') + + +def get_mealplan_recipe_ids(base_url: str, token: str, start_date: date, end_date: date) -> list[str]: + entries: list[dict] = [] + current = start_date + while current <= end_date: + path = ( + f"/api/households/mealplans?start_date={current.isoformat()}" + f"&end_date={current.isoformat()}&perPage=100" + ) + day_payload = api_request(base_url, path, token) + day_items = day_payload.get('items', []) if isinstance(day_payload, dict) else [] + entries.extend(day_items or []) + current = current + timedelta(days=1) + + result: list[str] = [] + seen: set[str] = set() + for entry in entries: + recipe_id = entry.get('recipeId') + if not recipe_id: + continue + if recipe_id in seen: + continue + seen.add(recipe_id) + result.append(recipe_id) + return result + + +def add_recipes_to_shopping_list(base_url: str, token: str, shopping_list_id: str, recipe_ids: list[str]) -> int: + if not recipe_ids: + return 0 + + payload = [{'recipeId': rid, 'recipeIncrementQuantity': 1} for rid in recipe_ids] + api_request( + base_url, + f'/api/households/shopping/lists/{shopping_list_id}/recipe', + token, + method='POST', + payload=payload, + ) + return len(recipe_ids) + + +def fetch_mealie_items(base_url: str, token: str, shopping_list_id: str | None = None) -> list[dict]: + data = api_request(base_url, '/api/households/shopping/items?perPage=1000', token) + items = data.get('items', []) or [] + if not shopping_list_id: + return items + return [item for item in items if item.get('shoppingListId') == shopping_list_id] def extract_item_name(item: dict) -> str: @@ -135,7 +240,7 @@ def merge_items(mealie_items: list[dict], keep_items: list[str]) -> list[dict]: return result -def write_outputs(root: Path, items: list[dict]) -> None: +def write_outputs(root: Path, items: list[dict], start_date: date, end_date: date) -> None: www = root / 'www' www.mkdir(parents=True, exist_ok=True) @@ -150,6 +255,7 @@ def write_outputs(root: Path, items: list[dict]) -> None: '# Bilka ToGo - Kryds-af-liste', '', 'Gå listen igennem derhjemme først, og bestil kun de varer du mangler.', + f'Plan-vindue: {start_date.isoformat()} til {end_date.isoformat()}', '', ] @@ -167,6 +273,7 @@ def write_outputs(root: Path, items: list[dict]) -> None: '# Bilka ToGo - Klar til bestilling', '', 'Kryds af hvad I allerede har i huset, og bestil resten.', + f'Plan-vindue: {start_date.isoformat()} til {end_date.isoformat()}', '', ] @@ -184,13 +291,25 @@ def main() -> None: token = read_bearer_token(root / 'secrets.yaml') keep_path = root / 'dokumenter' / 'google_keep_indkoeb.txt' - mealie_items = fetch_mealie_items('http://10.0.0.142:9925', token) + start_date, end_date = friday_to_thursday_window(date.today()) + + shopping_list_id = ensure_shopping_list(MEALIE_BASE_URL, token, TARGET_SHOPPING_LIST_NAME) + clear_shopping_list_items(MEALIE_BASE_URL, token, shopping_list_id) + + recipe_ids = get_mealplan_recipe_ids(MEALIE_BASE_URL, token, start_date, end_date) + added_recipes = add_recipes_to_shopping_list(MEALIE_BASE_URL, token, shopping_list_id, recipe_ids) + + mealie_items = fetch_mealie_items(MEALIE_BASE_URL, token, shopping_list_id=shopping_list_id) keep_items = read_keep_items(keep_path) merged = merge_items(mealie_items, keep_items) - write_outputs(root, merged) + write_outputs(root, merged, start_date, end_date) - print(f'OK: merged {len(merged)} items') + print( + 'OK: ' + f'window={start_date.isoformat()}..{end_date.isoformat()} ' + f'recipes_added={added_recipes} merged_items={len(merged)}' + ) if __name__ == '__main__': diff --git a/www/bilka_togo_checklist.json b/www/bilka_togo_checklist.json new file mode 100644 index 0000000..56bd606 --- /dev/null +++ b/www/bilka_togo_checklist.json @@ -0,0 +1,607 @@ +{ + "count": 86, + "items": [ + { + "name": "0,50 squash", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "0,50 tsk mediumstærk karry", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "0,50 tsk tørret rosmarin", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 dl cremefraiche 38%", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 dl grøntsagsbouillon", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 dl pickles", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 dl rødvin, eller grøntsagsboullion", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 dl tør hvidvin", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 fed hvidløg, presset", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 gulerødder, Groftrevet", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 kg kartofler", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 knivspids muskatnød, fintrevet", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 knivspids sød paprika", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 rødløg", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 spsk dijon sennep", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 spsk hampefrø", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 spsk honning", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 spsk ingefær, fintrevet", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 spsk majsstivelse", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 spsk smør, til stegning", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 spsk solsikkekerner", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 squash, groftrevet", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 tsk tørret timian", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "10 g smør, til stegning", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "100 g parmesan, fintrevet", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "2 æg", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "2 dl hønsebouillon", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "2 spsk grov sennep", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "2 spsk rosiner", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "2 spsk smør", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "2 tsk tørret oregano", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "200 g lasagneplader", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "25 g smør, til stegning", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "3 dl mælk", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "3 gulerødder, groftrevet", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "30 forårsrulleplader", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "300 g torskefilet", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "35 g glasnudler", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "4 fed hvidløg, fintrevet", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "4 gulerødder, groftrevet", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "5 stængler bladselleri, groftrevet", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "vand til pensling", + "category": "andet", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 dl piskefløde", + "category": "frost", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 spsk fishsauce", + "category": "frost", + "sources": [ + "Mealie" + ] + }, + { + "name": "2 spsk mayonnaise", + "category": "frost", + "sources": [ + "Mealie" + ] + }, + { + "name": "2,50 dl piskefløde", + "category": "frost", + "sources": [ + "Mealie" + ] + }, + { + "name": "0,50 citron, saft herfra", + "category": "frugt & grønt", + "sources": [ + "Mealie" + ] + }, + { + "name": "0,50 øko citron", + "category": "frugt & grønt", + "sources": [ + "Mealie" + ] + }, + { + "name": "15 g koncentreret tomatpuré", + "category": "frugt & grønt", + "sources": [ + "Mealie" + ] + }, + { + "name": "2 æble, groftrevet", + "category": "frugt & grønt", + "sources": [ + "Mealie" + ] + }, + { + "name": "50 g koncentreret tomatpuré", + "category": "frugt & grønt", + "sources": [ + "Mealie" + ] + }, + { + "name": "75 g soltørrede tomater i olie, finthakket", + "category": "frugt & grønt", + "sources": [ + "Mealie" + ] + }, + { + "name": "800 g hakkede tomater på dåse", + "category": "frugt & grønt", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 håndfuld frisk basilikum", + "category": "kolonial", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 håndfuld frisk dild", + "category": "kolonial", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 liter fritureolie", + "category": "kolonial", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 spsk olivenolie", + "category": "kolonial", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 spsk olivenolie, til stegning", + "category": "kolonial", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 spsk soja", + "category": "kolonial", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 tsk olivenolie", + "category": "kolonial", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 tsk sesamolie, eller anden olie til stegning", + "category": "kolonial", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 tsk sukker", + "category": "kolonial", + "sources": [ + "Mealie" + ] + }, + { + "name": "2 spsk hvedemel", + "category": "kolonial", + "sources": [ + "Mealie" + ] + }, + { + "name": "2 spsk olivenolie", + "category": "kolonial", + "sources": [ + "Mealie" + ] + }, + { + "name": "25 g hvedemel", + "category": "kolonial", + "sources": [ + "Mealie" + ] + }, + { + "name": "3 dl basmati ris, kogt efter anvisning på emballagen", + "category": "kolonial", + "sources": [ + "Mealie" + ] + }, + { + "name": "30 g hvedemel", + "category": "kolonial", + "sources": [ + "Mealie" + ] + }, + { + "name": "40 g hvedemel", + "category": "kolonial", + "sources": [ + "Mealie" + ] + }, + { + "name": "400 g pasta", + "category": "kolonial", + "sources": [ + "Mealie" + ] + }, + { + "name": "flagesalt", + "category": "kolonial", + "sources": [ + "Mealie" + ] + }, + { + "name": "salt og friskkværnet peber", + "category": "kolonial", + "sources": [ + "Mealie" + ] + }, + { + "name": "0,50 dl frisk estragon, finthakket", + "category": "kød & fisk", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 løg, finthakket", + "category": "kød & fisk", + "sources": [ + "Mealie" + ] + }, + { + "name": "1 tsk rød chili, finthakket", + "category": "kød & fisk", + "sources": [ + "Mealie" + ] + }, + { + "name": "2 løg, finthakket", + "category": "kød & fisk", + "sources": [ + "Mealie" + ] + }, + { + "name": "250 g champignon, finthakket", + "category": "kød & fisk", + "sources": [ + "Mealie" + ] + }, + { + "name": "3 fed hvidløg, finthakket", + "category": "kød & fisk", + "sources": [ + "Mealie" + ] + }, + { + "name": "300 g laks, uden skind", + "category": "kød & fisk", + "sources": [ + "Mealie" + ] + }, + { + "name": "4 fed hvidløg, finthakket", + "category": "kød & fisk", + "sources": [ + "Mealie" + ] + }, + { + "name": "4 kyllingebryst", + "category": "kød & fisk", + "sources": [ + "Mealie" + ] + }, + { + "name": "400 g hakket oksekød", + "category": "kød & fisk", + "sources": [ + "Mealie" + ] + }, + { + "name": "400 g hakket svinekød", + "category": "kød & fisk", + "sources": [ + "Mealie" + ] + }, + { + "name": "600 g kyllingebryst", + "category": "kød & fisk", + "sources": [ + "Mealie" + ] + }, + { + "name": "75 g bacon, i skiver", + "category": "kød & fisk", + "sources": [ + "Mealie" + ] + }, + { + "name": "125 g frisk mozzarella", + "category": "mejeri & æg", + "sources": [ + "Mealie" + ] + }, + { + "name": "400 g haricots verts, fra frost", + "category": "mejeri & æg", + "sources": [ + "Mealie" + ] + } + ] +} \ No newline at end of file diff --git a/www/bilka_togo_checklist.md b/www/bilka_togo_checklist.md new file mode 100644 index 0000000..2ab0b8b --- /dev/null +++ b/www/bilka_togo_checklist.md @@ -0,0 +1,102 @@ +# Bilka ToGo - Kryds-af-liste + +Gå listen igennem derhjemme først, og bestil kun de varer du mangler. +Plan-vindue: 2026-04-24 til 2026-04-30 + +## Andet +- [ ] 0,50 squash (Mealie) +- [ ] 0,50 tsk mediumstærk karry (Mealie) +- [ ] 0,50 tsk tørret rosmarin (Mealie) +- [ ] 1 dl cremefraiche 38% (Mealie) +- [ ] 1 dl grøntsagsbouillon (Mealie) +- [ ] 1 dl pickles (Mealie) +- [ ] 1 dl rødvin, eller grøntsagsboullion (Mealie) +- [ ] 1 dl tør hvidvin (Mealie) +- [ ] 1 fed hvidløg, presset (Mealie) +- [ ] 1 gulerødder, Groftrevet (Mealie) +- [ ] 1 kg kartofler (Mealie) +- [ ] 1 knivspids muskatnød, fintrevet (Mealie) +- [ ] 1 knivspids sød paprika (Mealie) +- [ ] 1 rødløg (Mealie) +- [ ] 1 spsk dijon sennep (Mealie) +- [ ] 1 spsk hampefrø (Mealie) +- [ ] 1 spsk honning (Mealie) +- [ ] 1 spsk ingefær, fintrevet (Mealie) +- [ ] 1 spsk majsstivelse (Mealie) +- [ ] 1 spsk smør, til stegning (Mealie) +- [ ] 1 spsk solsikkekerner (Mealie) +- [ ] 1 squash, groftrevet (Mealie) +- [ ] 1 tsk tørret timian (Mealie) +- [ ] 10 g smør, til stegning (Mealie) +- [ ] 100 g parmesan, fintrevet (Mealie) +- [ ] 2 æg (Mealie) +- [ ] 2 dl hønsebouillon (Mealie) +- [ ] 2 spsk grov sennep (Mealie) +- [ ] 2 spsk rosiner (Mealie) +- [ ] 2 spsk smør (Mealie) +- [ ] 2 tsk tørret oregano (Mealie) +- [ ] 200 g lasagneplader (Mealie) +- [ ] 25 g smør, til stegning (Mealie) +- [ ] 3 dl mælk (Mealie) +- [ ] 3 gulerødder, groftrevet (Mealie) +- [ ] 30 forårsrulleplader (Mealie) +- [ ] 300 g torskefilet (Mealie) +- [ ] 35 g glasnudler (Mealie) +- [ ] 4 fed hvidløg, fintrevet (Mealie) +- [ ] 4 gulerødder, groftrevet (Mealie) +- [ ] 5 stængler bladselleri, groftrevet (Mealie) +- [ ] vand til pensling (Mealie) + +## Frost +- [ ] 1 dl piskefløde (Mealie) +- [ ] 1 spsk fishsauce (Mealie) +- [ ] 2 spsk mayonnaise (Mealie) +- [ ] 2,50 dl piskefløde (Mealie) + +## Frugt & Grønt +- [ ] 0,50 citron, saft herfra (Mealie) +- [ ] 0,50 øko citron (Mealie) +- [ ] 15 g koncentreret tomatpuré (Mealie) +- [ ] 2 æble, groftrevet (Mealie) +- [ ] 50 g koncentreret tomatpuré (Mealie) +- [ ] 75 g soltørrede tomater i olie, finthakket (Mealie) +- [ ] 800 g hakkede tomater på dåse (Mealie) + +## Kolonial +- [ ] 1 håndfuld frisk basilikum (Mealie) +- [ ] 1 håndfuld frisk dild (Mealie) +- [ ] 1 liter fritureolie (Mealie) +- [ ] 1 spsk olivenolie (Mealie) +- [ ] 1 spsk olivenolie, til stegning (Mealie) +- [ ] 1 spsk soja (Mealie) +- [ ] 1 tsk olivenolie (Mealie) +- [ ] 1 tsk sesamolie, eller anden olie til stegning (Mealie) +- [ ] 1 tsk sukker (Mealie) +- [ ] 2 spsk hvedemel (Mealie) +- [ ] 2 spsk olivenolie (Mealie) +- [ ] 25 g hvedemel (Mealie) +- [ ] 3 dl basmati ris, kogt efter anvisning på emballagen (Mealie) +- [ ] 30 g hvedemel (Mealie) +- [ ] 40 g hvedemel (Mealie) +- [ ] 400 g pasta (Mealie) +- [ ] flagesalt (Mealie) +- [ ] salt og friskkværnet peber (Mealie) + +## Kød & Fisk +- [ ] 0,50 dl frisk estragon, finthakket (Mealie) +- [ ] 1 løg, finthakket (Mealie) +- [ ] 1 tsk rød chili, finthakket (Mealie) +- [ ] 2 løg, finthakket (Mealie) +- [ ] 250 g champignon, finthakket (Mealie) +- [ ] 3 fed hvidløg, finthakket (Mealie) +- [ ] 300 g laks, uden skind (Mealie) +- [ ] 4 fed hvidløg, finthakket (Mealie) +- [ ] 4 kyllingebryst (Mealie) +- [ ] 400 g hakket oksekød (Mealie) +- [ ] 400 g hakket svinekød (Mealie) +- [ ] 600 g kyllingebryst (Mealie) +- [ ] 75 g bacon, i skiver (Mealie) + +## Mejeri & Æg +- [ ] 125 g frisk mozzarella (Mealie) +- [ ] 400 g haricots verts, fra frost (Mealie) diff --git a/www/bilka_togo_checklist_bilka.md b/www/bilka_togo_checklist_bilka.md new file mode 100644 index 0000000..2e105be --- /dev/null +++ b/www/bilka_togo_checklist_bilka.md @@ -0,0 +1,102 @@ +# Bilka ToGo - Klar til bestilling + +Kryds af hvad I allerede har i huset, og bestil resten. +Plan-vindue: 2026-04-24 til 2026-04-30 + +## Andet +- [ ] 0,50 squash +- [ ] 0,50 tsk mediumstærk karry +- [ ] 0,50 tsk tørret rosmarin +- [ ] 1 dl cremefraiche 38% +- [ ] 1 dl grøntsagsbouillon +- [ ] 1 dl pickles +- [ ] 1 dl rødvin, eller grøntsagsboullion +- [ ] 1 dl tør hvidvin +- [ ] 1 fed hvidløg, presset +- [ ] 1 gulerødder, Groftrevet +- [ ] 1 kg kartofler +- [ ] 1 knivspids muskatnød, fintrevet +- [ ] 1 knivspids sød paprika +- [ ] 1 rødløg +- [ ] 1 spsk dijon sennep +- [ ] 1 spsk hampefrø +- [ ] 1 spsk honning +- [ ] 1 spsk ingefær, fintrevet +- [ ] 1 spsk majsstivelse +- [ ] 1 spsk smør, til stegning +- [ ] 1 spsk solsikkekerner +- [ ] 1 squash, groftrevet +- [ ] 1 tsk tørret timian +- [ ] 10 g smør, til stegning +- [ ] 100 g parmesan, fintrevet +- [ ] 2 æg +- [ ] 2 dl hønsebouillon +- [ ] 2 spsk grov sennep +- [ ] 2 spsk rosiner +- [ ] 2 spsk smør +- [ ] 2 tsk tørret oregano +- [ ] 200 g lasagneplader +- [ ] 25 g smør, til stegning +- [ ] 3 dl mælk +- [ ] 3 gulerødder, groftrevet +- [ ] 30 forårsrulleplader +- [ ] 300 g torskefilet +- [ ] 35 g glasnudler +- [ ] 4 fed hvidløg, fintrevet +- [ ] 4 gulerødder, groftrevet +- [ ] 5 stængler bladselleri, groftrevet +- [ ] vand til pensling + +## Frost +- [ ] 1 dl piskefløde +- [ ] 1 spsk fishsauce +- [ ] 2 spsk mayonnaise +- [ ] 2,50 dl piskefløde + +## Frugt & Grønt +- [ ] 0,50 citron, saft herfra +- [ ] 0,50 øko citron +- [ ] 15 g koncentreret tomatpuré +- [ ] 2 æble, groftrevet +- [ ] 50 g koncentreret tomatpuré +- [ ] 75 g soltørrede tomater i olie, finthakket +- [ ] 800 g hakkede tomater på dåse + +## Kolonial +- [ ] 1 håndfuld frisk basilikum +- [ ] 1 håndfuld frisk dild +- [ ] 1 liter fritureolie +- [ ] 1 spsk olivenolie +- [ ] 1 spsk olivenolie, til stegning +- [ ] 1 spsk soja +- [ ] 1 tsk olivenolie +- [ ] 1 tsk sesamolie, eller anden olie til stegning +- [ ] 1 tsk sukker +- [ ] 2 spsk hvedemel +- [ ] 2 spsk olivenolie +- [ ] 25 g hvedemel +- [ ] 3 dl basmati ris, kogt efter anvisning på emballagen +- [ ] 30 g hvedemel +- [ ] 40 g hvedemel +- [ ] 400 g pasta +- [ ] flagesalt +- [ ] salt og friskkværnet peber + +## Kød & Fisk +- [ ] 0,50 dl frisk estragon, finthakket +- [ ] 1 løg, finthakket +- [ ] 1 tsk rød chili, finthakket +- [ ] 2 løg, finthakket +- [ ] 250 g champignon, finthakket +- [ ] 3 fed hvidløg, finthakket +- [ ] 300 g laks, uden skind +- [ ] 4 fed hvidløg, finthakket +- [ ] 4 kyllingebryst +- [ ] 400 g hakket oksekød +- [ ] 400 g hakket svinekød +- [ ] 600 g kyllingebryst +- [ ] 75 g bacon, i skiver + +## Mejeri & Æg +- [ ] 125 g frisk mozzarella +- [ ] 400 g haricots verts, fra frost diff --git a/www/mealie.json b/www/mealie.json index 1dc81cf..deb332f 100644 --- a/www/mealie.json +++ b/www/mealie.json @@ -1 +1 @@ -{"count": 44, "items": [{"date": "2026-04-28", "recipe": {"name": "Hjemmelavet pizza", "slug": "hjemmelavet-pizza"}}, {"date": "2026-04-29", "recipe": {"name": "M\u00fcsli", "slug": "musli-opskrift"}}, {"date": "2026-04-30", "recipe": {"name": "Lakselasagne med spinat", "slug": "lakselasagne"}}, {"date": "2026-05-01", "recipe": {"name": "Mexicansk burger med guacamole", "slug": "mexicansk-burger-med-hjemmelavet-guacamole"}}, {"date": "2026-05-02", "recipe": {"name": "Gr\u00f8ntsagsfad", "slug": "grontsagsfad"}}, {"date": "2026-05-03", "recipe": {"name": "Hummus", "slug": "humus"}}, {"date": "2026-05-04", "recipe": {"name": "Indisk Curry med kylling", "slug": "indisk_curry_med_kylling"}}, {"date": "2026-05-05", "recipe": {"name": "Pariserbøf", "slug": "pariserbof"}}, {"date": "2026-05-06", "recipe": {"name": "Skipperlabskovs", "slug": "skipperlabskovs"}}, {"date": "2026-05-07", "recipe": {"name": "Pizzasnegle", "slug": "pizzasnegle"}}, {"date": "2026-05-08", "recipe": {"name": "Luksus stjerneskud", "slug": "luksus-stjerneskud"}}, {"date": "2026-05-09", "recipe": {"name": "Jordbærsalat med feta og pekan", "slug": "jordbaer-og-fetasalat-med-glaserede-pecannoedder"}}, {"date": "2026-05-10", "recipe": {"name": "Spaghetti Bolognese", "slug": "spaghetti-bolognese"}}, {"date": "2026-05-11", "recipe": {"name": "Kylling med cornflakes", "slug": "kylling-med-cornflakes"}}, {"date": "2026-05-12", "recipe": {"name": "Tarteletter med høns", "slug": "tarteletter-hoens-asparges"}}, {"date": "2026-05-13", "recipe": {"name": "One pot pasta", "slug": "one-pot-pasta"}}, {"date": "2026-05-14", "recipe": {"name": "Cacio e Pepe", "slug": "cacio-e-pepe"}}, {"date": "2026-05-15", "recipe": {"name": "Citronpasta", "slug": "citronpasta"}}, {"date": "2026-05-16", "recipe": {"name": "Blomk\u00e5lssalat", "slug": "blomkaalssalat"}}, {"date": "2026-05-17", "recipe": {"name": "One Pot Pasta med kødsovs", "slug": "koedsovs-onepotpasta"}}, {"date": "2026-05-18", "recipe": {"name": "Kikærtegryde", "slug": "kikaertegryde"}}, {"date": "2026-05-19", "recipe": {"name": "Mørbradbøffer", "slug": "moerbradboeffer-med-bloede-loeg"}}, {"date": "2026-05-20", "recipe": {"name": "Stegt spidskål", "slug": "stegt-spidskaal"}}, {"date": "2026-05-21", "recipe": {"name": "Bagt kylling", "slug": "bagt-kylling"}}, {"date": "2026-05-22", "recipe": {"name": "Ristede kartoffelskiver", "slug": "ristede-kartoffelskiver-fad"}}, {"date": "2026-05-23", "recipe": {"name": "Vikingegryde", "slug": "vikingegryde"}}, {"date": "2026-05-24", "recipe": {"name": "Spidskålssalat", "slug": "spidskaalssalat-opskrift"}}, {"date": "2026-05-25", "recipe": {"name": "Kylling med parmesan", "slug": "kylling-med-parmesan"}}, {"date": "2026-05-26", "recipe": {"name": "Bagt broccoli", "slug": "bagt-broccoli"}}, {"date": "2026-05-27", "recipe": {"name": "Pastasalat med pesto", "slug": "pastasalat-med-pesto"}}, {"date": "2026-05-28", "recipe": {"name": "Nachos bowl", "slug": "nachos-bowl"}}, {"date": "2026-05-29", "recipe": {"name": "Barbecuesauce", "slug": "barbecuesauce"}}, {"date": "2026-05-30", "recipe": {"name": "Congee Rissuppe", "slug": "congee-rissuppe-kylling"}}, {"date": "2026-05-31", "recipe": {"name": "Macaroni and Cheese", "slug": "macaroni-and-cheese"}}, {"date": "2026-06-01", "recipe": {"name": "Halloween dessert", "slug": "halloween-dessert"}}, {"date": "2026-06-02", "recipe": {"name": "Feta pasta", "slug": "feta-pasta-med-tomat"}}, {"date": "2026-06-03", "recipe": {"name": "Tortellini i fad", "slug": "tortellini-i-fad"}}, {"date": "2026-06-04", "recipe": {"name": "Flyvende Jacob", "slug": "flyvende-jacob"}}, {"date": "2026-04-26", "recipe": {"name": "Lasagne", "slug": "lasagne"}}, {"date": "2026-04-24", "recipe": {"name": "Fiskefrikadeller med remoulade og r\u00e5kost", "slug": "fiskefrikadeller-med-remoulade-og-rakost"}}, {"date": "2026-04-27", "recipe": {"name": "Marry Me Chicken", "slug": "marry-me-chicken"}}, {"date": "2026-04-25", "recipe": {"name": "Cheeseburger Tacos", "slug": "cheeseburger-tacos"}}, {"date": "2026-04-23", "recipe": {"name": "K\u00e5lfad med hakket oksek\u00f8d", "slug": "kalfad-med-hakket-oksekod"}}, {"date": "2026-04-22", "recipe": {"name": "Kylling med honning og sennep", "slug": "kylling-i-fad-med-honning-og-sennep"}}]} \ No newline at end of file +{"count": 7, "items": [{"date": "2026-04-28", "recipe": {"name": "Lasagne", "slug": "lasagne"}}, {"date": "2026-04-27", "recipe": {"name": "Kylling i cremet sennepssauce", "slug": "kylling-i-cremet-sennepssauce"}}, {"date": "2026-04-26", "recipe": {"name": "Lasagne", "slug": "lasagne"}}, {"date": "2026-04-25", "recipe": {"name": "Spr\u00f8de for\u00e5rsruller", "slug": "sprode-forarsruller"}}, {"date": "2026-04-24", "recipe": {"name": "Marry Me Chicken", "slug": "marry-me-chicken"}}, {"date": "2026-04-22", "recipe": {"name": "Kylling i cremet sennepssauce", "slug": "kylling-i-cremet-sennepssauce"}}, {"date": "2026-04-23", "recipe": {"name": "K\u00e5lfad med hakket oksek\u00f8d", "slug": "kalfad-med-hakket-oksekod"}}]} \ No newline at end of file