munch-ease-backend/ingredients/db.py

81 lines
3.3 KiB
Python
Raw Normal View History

2024-01-17 07:21:16 +00:00
from products import Product
from pydantic import BaseModel
2024-05-13 03:59:46 +00:00
from typing import AsyncIterator, List, ClassVar, Optional
2024-01-17 07:21:16 +00:00
class Ingredient(BaseModel):
KEYS: ClassVar[List[str]] = ['id', 'name', 'line', 'preparation', 'unit', 'quantity', 'product_id', 'recipe_id', 'meal_id']
2024-05-20 10:09:57 +00:00
id: int = -1
2024-01-17 07:21:16 +00:00
name: str
line: str
unit: str
quantity: float
preparation: str
product_id: Optional[int] = None
recipe_id: Optional[int] = None
meal_id: Optional[int] = None
product: Optional[Product] = None
2024-01-17 07:21:16 +00:00
async def create(conn):
await conn.execute('''
CREATE TABLE IF NOT EXISTS Ingredient (
id INTEGER PRIMARY KEY,
name TEXT,
line TEXT,
preparation TEXT,
unit TEXT,
quantity REAL,
product_id INTEGER,
recipe_id INTEGER,
meal_id INTEGER,
FOREIGN KEY (product_id) REFERENCES Product(id),
FOREIGN KEY (recipe_id) REFERENCES Recipe(id),
FOREIGN KEY (meal_id) REFERENCES Meal(id)
);''')
async def insert_ingredient(conn, ingredient: Ingredient):
2024-05-20 10:09:57 +00:00
if ingredient.product:
2024-04-25 04:57:39 +00:00
ingredient.product_id = ingredient.product.id
2024-05-20 10:09:57 +00:00
if ingredient.product_id < 0:
2024-04-25 04:57:39 +00:00
raise ValueError('Product must be inserted before ingredient')
2024-01-17 07:21:16 +00:00
async with conn.execute('''
INSERT INTO Ingredient (name, line, preparation, unit, quantity, product_id, recipe_id, meal_id)
2024-01-17 08:36:54 +00:00
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
2024-01-17 07:21:16 +00:00
''', (ingredient.name, ingredient.line, ingredient.preparation, ingredient.unit, ingredient.quantity, ingredient.product_id, ingredient.recipe_id, ingredient.meal_id)) as cursor:
ingredient.id = cursor.lastrowid
2024-05-13 03:59:46 +00:00
async def find_ingredients_by_recipe_id(conn, recipe_id: int) -> AsyncIterator[Ingredient]:
ingredient_keys = [f'ingredient.{key}' for key in Ingredient.KEYS]
product_keys = [f'product.{key}' for key in Product.KEYS]
2024-01-17 07:21:16 +00:00
async with conn.execute(f'''
SELECT {','.join(ingredient_keys + product_keys)} FROM Ingredient
LEFT JOIN Product ON Ingredient.product_id = Product.id
2024-01-17 07:21:16 +00:00
WHERE recipe_id = ?
''', (recipe_id,)) as cursor:
async for row in cursor:
product_keys = {k:v for k,v in zip(Product.KEYS, row[len(Ingredient.KEYS):])}
product = Product(**product_keys) if product_keys['id'] else None
yield Ingredient(**{k:v for k,v in zip(Ingredient.KEYS, row[:len(Ingredient.KEYS)])}, product=product)
2024-01-17 07:21:16 +00:00
2024-05-13 03:59:46 +00:00
async def find_ingredients_by_meal_id(conn, meal_id: int) -> AsyncIterator[Ingredient]:
ingredient_keys = [f'ingredient.{key}' for key in Ingredient.KEYS]
product_keys = [f'product.{key}' for key in Product.KEYS]
2024-01-17 07:21:16 +00:00
async with conn.execute(f'''
SELECT {','.join(ingredient_keys + product_keys)} FROM Ingredient
LEFT JOIN Product ON Ingredient.product_id = Product.id
2024-01-17 07:21:16 +00:00
WHERE meal_id = ?
''', (meal_id,)) as cursor:
async for row in cursor:
product_keys = {k:v for k,v in zip(Product.KEYS, row[len(Ingredient.KEYS):])}
product = Product(**product_keys) if product_keys['id'] else None
2024-05-02 11:20:52 +00:00
yield Ingredient(**{k:v for k,v in zip(Ingredient.KEYS, row[:len(Ingredient.KEYS)])}, product=product)
async def delete_ingredients_by_meal_id(conn, meal_id: int):
await conn.execute('''
DELETE FROM Ingredient
WHERE meal_id = ?
''', (meal_id,))