Fix Mealie shopping refresh flow with bulk recipe import and Bilka outputs

This commit is contained in:
2026-04-22 16:12:23 +02:00
parent 83f8908a3f
commit ef9200f65b
8 changed files with 949 additions and 15 deletions
+1 -1
View File
@@ -144,7 +144,7 @@ cards:
icon: mdi:cart-check icon: mdi:cart-check
tap_action: tap_action:
action: call-service action: call-service
service: shell_command.mealie_shopping_merge service: script.mealie_shopping_refresh
- type: iframe - type: iframe
url: /local/bilka_togo_checklist_bilka.md url: /local/bilka_togo_checklist_bilka.md
+1 -5
View File
@@ -18,8 +18,4 @@
weekday: weekday:
- wed - wed
action: action:
- service: shell_command.mealie_shopping_merge - service: script.mealie_shopping_refresh
- 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."
+8
View File
@@ -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."
+127 -8
View File
@@ -1,5 +1,9 @@
#!/usr/bin/env python3 #!/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: Output:
- /www/bilka_togo_checklist.md - /www/bilka_togo_checklist.md
@@ -13,10 +17,13 @@ import json
import re import re
import urllib.request import urllib.request
from collections import defaultdict from collections import defaultdict
from datetime import date, timedelta
from pathlib import Path from pathlib import Path
ROOT_CANDIDATES = [Path('/Volumes/homeassistant'), Path('/config')] ROOT_CANDIDATES = [Path('/Volumes/homeassistant'), Path('/config')]
MEALIE_BASE_URL = 'http://10.0.0.142:9925'
TARGET_SHOPPING_LIST_NAME = 'Bilka ToGo'
CATEGORY_RULES = { 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'], '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'], '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 {} 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: def normalize_name(value: str) -> str:
value = value.lower().strip() value = value.lower().strip()
value = value.replace('å', 'aa').replace('æ', 'ae').replace('ø', 'oe') value = value.replace('å', 'aa').replace('æ', 'ae').replace('ø', 'oe')
@@ -82,9 +113,83 @@ def read_keep_items(keep_path: Path) -> list[str]:
return items return items
def fetch_mealie_items(base_url: str, token: str) -> list[dict]: def friday_to_thursday_window(today: date) -> tuple[date, date]:
data = api_get(f'{base_url}/api/households/shopping/items?perPage=500', token) days_until_friday = (4 - today.weekday()) % 7
return data.get('items', []) or [] 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: 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 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 = root / 'www'
www.mkdir(parents=True, exist_ok=True) 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', '# Bilka ToGo - Kryds-af-liste',
'', '',
'Gå listen igennem derhjemme først, og bestil kun de varer du mangler.', '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', '# Bilka ToGo - Klar til bestilling',
'', '',
'Kryds af hvad I allerede har i huset, og bestil resten.', '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') token = read_bearer_token(root / 'secrets.yaml')
keep_path = root / 'dokumenter' / 'google_keep_indkoeb.txt' 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) keep_items = read_keep_items(keep_path)
merged = merge_items(mealie_items, keep_items) 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__': if __name__ == '__main__':
+607
View File
@@ -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"
]
}
]
}
+102
View File
@@ -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)
+102
View File
@@ -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
+1 -1
View File
@@ -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"}}]} {"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"}}]}