This commit is contained in:
jableader 2024-01-13 18:42:23 +11:00
parent 671db1b4eb
commit ebab422869
3 changed files with 83 additions and 9 deletions

44
main.py
View file

@ -1,5 +1,6 @@
import sqlite3 import sqlite3
import product, recipe, db import product, recipe, db, meals
import datetime
from pydantic import BaseModel from pydantic import BaseModel
from typing import List, Annotated from typing import List, Annotated
@ -51,19 +52,26 @@ class ProductUrl(BaseModel):
async def create_product(url: ProductUrl, conn: sqlite3.Connection = Depends(get_db)) -> product.Product: async def create_product(url: ProductUrl, conn: sqlite3.Connection = Depends(get_db)) -> product.Product:
return await product.get_or_create(conn, url.url, url.tags) return await product.get_or_create(conn, url.url, url.tags)
@app.get("/recipes/{recipe_id}") async def load_full_recipe(conn: sqlite3.Connection, id: int) -> recipe.Recipe:
async def get_recipe(recipe_id: int, conn: sqlite3.Connection = Depends(get_db)) -> recipe.Recipe: r = await recipe.find_recipe_by_id(conn, id)
r = await recipe.find_recipe_by_id(conn, recipe_id)
if not r: if not r:
return JSONResponse(status_code=404, content={'message': 'Recipe not found'}) return None
r.ingredients = [] r.ingredients = []
async for ingredient in recipe.find_ingredients_by_recipe_id(conn, recipe_id): async for ingredient in recipe.find_ingredients_by_recipe_id(conn, id):
ingredient.product = await product.find_product_by_id(conn, ingredient.product_id) ingredient.product = await product.find_product_by_id(conn, ingredient.product_id)
r.ingredients.append(ingredient) r.ingredients.append(ingredient)
return r return r
@app.get("/recipes/{recipe_id}")
async def get_recipe(recipe_id: int, conn: sqlite3.Connection = Depends(get_db)) -> recipe.Recipe:
r = await load_full_recipe(conn, recipe_id)
if not r:
return JSONResponse(status_code=404, content={'message': 'Recipe not found'})
return r
@app.post('/recipes/') @app.post('/recipes/')
async def create_recipe(item: recipe.Recipe, conn: sqlite3.Connection = Depends(get_db)) -> recipe.Recipe: async def create_recipe(item: recipe.Recipe, conn: sqlite3.Connection = Depends(get_db)) -> recipe.Recipe:
if not item.ingredients: if not item.ingredients:
@ -81,3 +89,27 @@ async def create_recipe(item: recipe.Recipe, conn: sqlite3.Connection = Depends(
await conn.commit() await conn.commit()
return item return item
@app.get("/meals/")
async def get_meals(start: datetime.datetime, end: datetime.datetime, conn: sqlite3.Connection = Depends(get_db)) -> List[meals.Meal]:
result = []
async for meal in meals.find_meals_by_date_range(conn, start, end):
meal.recipe = await load_full_recipe(conn, meal.recipe_id)
result.append(meal)
return result
@app.post("/meals/")
async def create_meal(meal: meals.Meal, conn: sqlite3.Connection = Depends(get_db)) -> meals.Meal:
if not meal.chef:
return JSONResponse(status_code=400, content={'message': 'Meal must have at least one chef'})
if not meal.cleanup:
return JSONResponse(status_code=400, content={'message': 'Meal must have at least one cleanup person'})
if not meal.consumers:
return JSONResponse(status_code=400, content={'message': 'Meal must have at least one consumer'})
await meals.insert_meal(conn, meal)
await conn.commit()
return meal

View file

@ -0,0 +1 @@
from meals.db import *

View file

@ -37,12 +37,27 @@ async def create(conn):
FOREIGN KEY(recipe_id) REFERENCES Recipe(id) FOREIGN KEY(recipe_id) REFERENCES Recipe(id)
);''') );''')
async def insert_meal_participant(conn, meal_id: int, person_id: int, role: str):
await conn.execute('''
INSERT INTO MealParticipant (meal_id, person_id, role)
VALUES (?, ?, ?)
''', (meal_id, person_id, role))
async def insert_meal(conn, meal: Meal): async def insert_meal(conn, meal: Meal):
async with conn.execute(''' async with conn.execute('''
INSERT INTO Meal (date) INSERT INTO Meal (date)
VALUES (?) VALUES (?)
''', (meal.date,)) as cursor: ''', (meal.date,)) as cursor:
return cursor.lastrowid meal.id = cursor.lastrowid
for person in meal.chef:
await insert_meal_participant(conn, meal.id, person.id, 'chef')
for person in meal.cleanup:
await insert_meal_participant(conn, meal.id, person.id, 'cleanup')
for person in meal.consumers:
await insert_meal_participant(conn, meal.id, person.id, 'consumer')
async def find_meal_by_id(conn, meal_id: int) -> Meal: async def find_meal_by_id(conn, meal_id: int) -> Meal:
async with conn.execute(f''' async with conn.execute(f'''
@ -61,3 +76,29 @@ async def find_meal_by_date(conn, date: datetime) -> Meal:
''', (date,)) as cursor: ''', (date,)) as cursor:
async for row in cursor: async for row in cursor:
return Meal(**{k:v for k,v in zip(Meal.KEYS, row)}) return Meal(**{k:v for k,v in zip(Meal.KEYS, row)})
async def find_meals_by_date_range(conn, start: datetime, end: datetime) -> List[Meal]:
async with conn.execute(f'''
SELECT {','.join(Meal.KEYS)} FROM Meal
WHERE date >= ? AND date <= ?
''', (start, end)) as cursor:
result = []
async for row in cursor:
result.append(Meal(**{k:v for k,v in zip(Meal.KEYS, row)}))
return result
async def load_participants(conn, meal: Meal) -> None:
async with conn.execute(f'''
SELECT person_id, role FROM MealParticipant
WHERE meal_id = ?
''', (meal.id,)) as cursor:
async for row in cursor:
person = await Person.find_person_by_id(conn, row[0])
if row[1] == 'chef':
meal.chef.append(person)
elif row[1] == 'cleanup':
meal.cleanup.append(person)
elif row[1] == 'consumer':
meal.consumers.append(person)
else:
raise Exception(f'Unknown role: {row[1]}')