2026-04-23 19:26:12 +02:00
import csv
import json
2026-04-26 13:18:19 +02:00
import math
2026-04-23 19:26:12 +02:00
import os
import pprint
import re
import sys
2026-04-26 13:18:19 +02:00
2026-04-23 19:26:12 +02:00
from collections import defaultdict
from datetime import timedelta
from pathlib import Path
from openpyxl import load_workbook
from tabulate import tabulate
from tqdm import tqdm
from config import *
from lib import read_recipes , markdown_link , recipe_url , markdown_alert
def read_plan ( ) :
wb = load_workbook ( " data/Planung + Einkauf Brotaufstriche.xlsx " )
sheet = wb . active
plan = { }
for row in sheet . iter_rows ( values_only = True ) :
r_name = row [ 0 ]
# Ansprechpartner*in = row[1]
r_total_net_weight = row [ 2 ]
# gpn23 = row[3]
r_serving_net_weight = row [ 4 ]
# (Formula) = row[5]
r_recipe_url = row [ 6 ]
# We simply skip over any rows that do not have the recipe url
if not r_recipe_url :
continue
if m := re . match ( r " https://.*/( \ d+)$ " , r_recipe_url ) :
r_recipe_id = int ( m . group ( 1 ) )
else :
continue # skip
r_wanted_servings = r_total_net_weight / r_serving_net_weight
plan [ r_name ] = {
" total_net_weight " : r_total_net_weight ,
" serving_net_weight " : r_serving_net_weight ,
" recipe_id " : r_recipe_id ,
" wanted_servings " : r_wanted_servings ,
}
return plan
plan = read_plan ( )
# XXX move to lib
def grams ( ingredient ) :
conversion = None
2026-04-26 13:18:19 +02:00
warnings = [ ]
if not ingredient [ " unit " ] and ingredient [ " food " ] [ " name " ] not in FOOD_NO_UNIT_OK :
warnings . append ( f " 🟡 No unit for { ingredient [ " food " ] [ " name " ] } " )
2026-04-23 19:26:12 +02:00
for c in ingredient [ " conversions " ] :
if c [ " unit " ] in [ " g / Gramm " , " g " ] :
conversion = c
if conversion :
2026-04-26 13:18:19 +02:00
return conversion . get ( " amount " ) , warnings
else :
if ingredient [ " unit " ] :
warnings . append ( f " 🟡 No conversion to grams for unit { ingredient [ " unit " ] [ " name " ] } " )
return None , warnings
2026-04-23 19:26:12 +02:00
def main ( ) :
recipes = read_recipes ( keyword = " Frühstück " )
inventory = { }
for recipe in recipes :
scale_factor = plan [ recipe [ " name " ] ] [ " wanted_servings " ] / recipe [ " servings " ]
r_name = recipe [ " name " ]
for step in recipe [ " steps " ] :
for ingredient in step [ " ingredients " ] :
2026-04-26 13:18:19 +02:00
i_name = ingredient [ " food " ] [ " name " ]
2026-04-23 19:26:12 +02:00
if not ingredient . get ( " food " ) :
raise ValueError ( " No food in ingredient " )
continue
2026-04-26 13:18:19 +02:00
g , warnings = grams ( ingredient )
if warnings :
print ( r_name , " - " , i_name )
for w in warnings :
print ( f " - { w } " )
i_grams = scale_factor * ( g or 0 )
2026-04-23 19:26:12 +02:00
i_description = ingredient [ " food " ] [
" description "
] # XXX probably not what i wanted
inventory . setdefault ( i_name , [ ] ) . append ( ( i_grams , r_name ) )
# gross ingredient weight per serving
r_gross_weight = 0.0
for step in recipe [ " steps " ] :
for ingredient in step [ " ingredients " ] :
if not ingredient . get ( " food " ) :
raise ValueError ( " No food in ingredient " )
continue
2026-04-26 13:18:19 +02:00
r_gross_weight + = ( grams ( ingredient ) [ 0 ] or 0 )
2026-04-23 19:26:12 +02:00
r_gross_weight / = recipe [ " servings " ]
recipe [ " total_net_weight " ] = plan [ r_name ] [ " total_net_weight " ]
recipe [ " wanted_servings " ] = plan [ r_name ] [ " wanted_servings " ]
recipe [ " total_gross_weight " ] = r_gross_weight * plan [ r_name ] [ " wanted_servings " ]
2026-04-26 13:18:19 +02:00
print ( " --- " )
print ( " tags: GPN24, Fruehstueck " )
print ( " --- " )
print ( " # GPN24 Frühstück Aufstriche Inventar + Bestellung " )
2026-04-23 19:26:12 +02:00
print ( markdown_alert ( " automatisch erstellt, nicht editieren... " ) )
print ( )
print ( " ## Rezepte und Portionen " )
data = [ ]
for recipe in recipes :
row = [ markdown_link ( recipe [ " name " ] , recipe_url ( recipe [ " id " ] ) ) ,
int ( recipe [ " wanted_servings " ] ) ,
int ( recipe [ " total_net_weight " ] ) ,
int ( recipe [ " total_gross_weight " ] ) ]
data . append ( row )
headers = [ " Rezept " , " Portionen " , " Gewicht Netto (Soll) " , " Gewicht Brutto Zutaten " ]
print ( tabulate ( data , headers = headers , tablefmt = " github " ) )
print ( )
print ( )
print ( " ## Zutaten " )
for ingredient , entries in inventory . items ( ) :
total = sum ( amount for amount , _ in entries )
print ( f " ### { ingredient } " )
print ( f " - ** { total : .1f } g** **Total** " )
for i_grams , r_name in entries :
print ( f " - { i_grams : .1f } g { r_name } " )
2026-04-26 13:18:19 +02:00
print ( )
print ( )
print ( " ## Für die Bestellung nochmal als Tabelle " )
table_data = [ ]
for ingredient , entries in inventory . items ( ) :
total = sum ( amount for amount , _ in entries )
table_data . append ( ( math . ceil ( total ) , ingredient ) )
table_headers = ( " Gewicht (g) " , " Zutat " )
print ( tabulate ( table_data , headers = table_headers , tablefmt = " github " ) )
print ( )
print ( )
2026-04-23 19:26:12 +02:00
2026-04-26 13:18:19 +02:00
print ( " ## Notes " )
with open ( " fruehstueck_bestellung+inventar-notes.md " ) as notes_fd :
print ( notes_fd . read ( ) )
2026-04-23 19:26:12 +02:00
if __name__ == " __main__ " :
main ( )