No duplicates in meal roles

This commit is contained in:
jableader 2024-05-04 15:06:48 +10:00
parent 37ae73ef1f
commit c241b8dd8d
2 changed files with 87 additions and 3 deletions

36
main.py
View file

@ -152,8 +152,16 @@ async def get_meal(meal_id: int, conn: sqlite3.Connection = Depends(get_db)) ->
return meal
@app.post("/meals/")
async def create_meal(meal: meals.Meal, conn: sqlite3.Connection = Depends(get_db)) -> meals.Meal:
def get_duplicates(items: List[meals.Person]) -> set[str]:
seen : set[int] = set()
duplicates : set[str] = set()
for item in items:
if item.id in seen:
duplicates.add(item.name)
seen.add(item.id)
return duplicates
def validate_meal(meal : meals.Meal) -> JSONResponse | None:
if not meal.chefs:
return JSONResponse(status_code=400, content={'message': 'Meal must have at least one chef'})
@ -165,6 +173,26 @@ async def create_meal(meal: meals.Meal, conn: sqlite3.Connection = Depends(get_d
if len(meal.recipes) == 0 and len(meal.extra_ingredients) == 0:
return JSONResponse(status_code=400, content={'message': 'Meal must have at least one recipe or ingredient'})
duplicates = get_duplicates(meal.chefs)
if duplicates:
return JSONResponse(status_code=400, content={'message': f'Duplicate chef: {", ".join(duplicates)}'})
duplicates = get_duplicates(meal.cleanup)
if duplicates:
return JSONResponse(status_code=400, content={'message': f'Duplicate cleanup person: {", ".join(duplicates)}'})
duplicates = get_duplicates(meal.consumers)
if duplicates:
return JSONResponse(status_code=400, content={'message': f'Duplicate consumer: {", ".join(duplicates)}'})
return None
@app.post("/meals/")
async def create_meal(meal: meals.Meal, conn: sqlite3.Connection = Depends(get_db)) -> meals.Meal:
validation_response = validate_meal(meal)
if validation_response:
return validation_response
await meals.insert_meal(conn, meal)
await conn.commit()
@ -178,6 +206,10 @@ async def update_meal(meal_id: int, meal: meals.Meal, conn: sqlite3.Connection =
existing = await meals.find_meal_by_id(conn, meal_id)
if not existing:
return JSONResponse(status_code=404, content={'message': 'Meal not found'})
validation_response = validate_meal(meal)
if validation_response:
return validation_response
await meals.update_meal(conn, meal)
await conn.commit()

View file

@ -1,7 +1,13 @@
import unittest
import test_data
import datetime
import test_data
import importlib
def reload_test_data():
global test_data
test_data = importlib.reload(test_data)
import pathlib
from db import connect, create
@ -20,6 +26,7 @@ class TestProducts(unittest.IsolatedAsyncioTestCase):
async def asyncSetUp(self):
self.conn = await connect('./testdb.db')
await create(self.conn)
reload_test_data()
return await super().asyncSetUp()
async def asyncTearDown(self) -> None:
@ -49,6 +56,8 @@ class TestRecipe(unittest.IsolatedAsyncioTestCase):
self.conn = await connect('./testdb.db')
await create(self.conn)
await test_data.create_persons(self.conn)
reload_test_data()
return await super().asyncSetUp()
async def asyncTearDown(self) -> None:
@ -113,6 +122,7 @@ class TestMeals(unittest.IsolatedAsyncioTestCase):
self.conn = await connect('./testdb.db')
await create(self.conn)
await test_data.create_persons(self.conn)
reload_test_data()
return await super().asyncSetUp()
async def asyncTearDown(self) -> None:
@ -120,6 +130,48 @@ class TestMeals(unittest.IsolatedAsyncioTestCase):
pathlib.Path('./testdb.db').unlink(missing_ok=True)
return await super().asyncTearDown()
async def testMultiplePariticpants(self) -> None:
meal = test_data.Meals.broccoli_soup_for_jacob
recipe = meal.recipes[0]
recipe_ingredient = recipe.ingredients[0]
recipe_product = recipe_ingredient.product
extra_ingredient = meal.extra_ingredients[0]
extra_product = extra_ingredient.product
person = test_data.Persons.jacob
await products_db.insert_product(self.conn, recipe_product, {})
await products_db.insert_product(self.conn, extra_product, {})
created_recipe = await main.create_recipe(recipe, self.conn, person)
recipe.id = created_recipe.id
meal.chefs = [test_data.Persons.ryan, test_data.Persons.chris, test_data.Persons.ryan]
error_response = await main.create_meal(meal, self.conn)
self.assertIsNotNone(error_response)
self.assertEqual(error_response.status_code, 400)
self.assertEqual(error_response.body, b'{"message":"Duplicate chef: Ryan"}')
meal.chefs = [test_data.Persons.ryan, test_data.Persons.chris]
meal.consumers = [test_data.Persons.ryan, test_data.Persons.chris, test_data.Persons.ryan]
error_response = await main.create_meal(meal, self.conn)
self.assertIsNotNone(error_response)
self.assertEqual(error_response.status_code, 400)
self.assertEqual(error_response.body, b'{"message":"Duplicate consumer: Ryan"}')
meal.consumers = [test_data.Persons.ryan, test_data.Persons.chris]
meal.cleanup = [test_data.Persons.ryan, test_data.Persons.chris, test_data.Persons.ryan]
error_response = await main.create_meal(meal, self.conn)
self.assertIsNotNone(error_response)
self.assertEqual(error_response.status_code, 400)
self.assertEqual(error_response.body, b'{"message":"Duplicate cleanup person: Ryan"}')
meal.cleanup = [test_data.Persons.ryan, test_data.Persons.chris]
response = await main.create_meal(meal, self.conn)
self.assertIsNotNone(response)
self.assertIsInstance(response, meals.Meal, msg=response.body if hasattr(response, 'body') else response)
async def testCreateAndFind(self) -> None:
meal = test_data.Meals.broccoli_soup_for_jacob
recipe = meal.recipes[0]