Use iso format date stamps

This commit is contained in:
jableader 2024-10-14 16:59:05 +11:00
parent ff2d348ec9
commit 809de13ed8
6 changed files with 44 additions and 36 deletions

View file

@ -228,11 +228,14 @@ async def update_meal(meal_id: int, meal: meals.Meal, conn: sqlite3.Connection =
@app.post("/api/meals/{meal_id}/consumed") @app.post("/api/meals/{meal_id}/consumed")
async def mark_consumed(meal_id: int, consumed_date: Optional[datetime.datetime] = None, conn: sqlite3.Connection = Depends(get_db), person: persons.Person = Depends(cookie_person)) -> meals.Meal: async def mark_consumed(meal_id: int, consumed_date: Optional[datetime.datetime] = None, conn: sqlite3.Connection = Depends(get_db), person: persons.Person = Depends(cookie_person)) -> meals.Meal:
if consumed_date and not consumed_date.tzinfo:
return JSONResponse(status_code=400, content={'message': 'Consumed date must include timezone'})
meal = await meals.find_meal_by_id(conn, meal_id) meal = await meals.find_meal_by_id(conn, meal_id)
if not meal: if not meal:
return JSONResponse(status_code=404, content={'message': 'Meal not found'}) return JSONResponse(status_code=404, content={'message': 'Meal not found'})
await meals.mark_consumed(conn, meal, consumed_date or datetime.datetime.now()) await meals.mark_consumed(conn, meal, consumed_date or datetime.datetime.now().astimezone())
await shopping.unrequest_meal(conn, meal) await shopping.unrequest_meal(conn, meal)
await conn.commit() await conn.commit()

View file

@ -35,8 +35,8 @@ async def create(conn):
await conn.execute(''' await conn.execute('''
CREATE TABLE IF NOT EXISTS Meal ( CREATE TABLE IF NOT EXISTS Meal (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
suggested_date TEXT, suggested_date DATETIME,
consumed_date TEXT, consumed_date DATETIME DEFAULT NULL,
deleted_date TEXT DEFAULT NULL, deleted_date TEXT DEFAULT NULL,
purchase_date TEXT DEFAULT NULL purchase_date TEXT DEFAULT NULL
);''') );''')
@ -93,7 +93,7 @@ async def insert_meal(conn, meal: Meal):
async with conn.execute(''' async with conn.execute('''
INSERT INTO Meal (suggested_date) INSERT INTO Meal (suggested_date)
VALUES (?) VALUES (?)
''', (meal.suggested_date,)) as cursor: ''', (meal.suggested_date.isoformat(),)) as cursor:
meal.id = cursor.lastrowid meal.id = cursor.lastrowid
await sync_meal_participants(conn, meal.id, meal.chefs, 'chef') await sync_meal_participants(conn, meal.id, meal.chefs, 'chef')
@ -167,7 +167,7 @@ async def delete_meal(conn, meal_id: int) -> None:
UPDATE Meal UPDATE Meal
SET deleted_date = ? SET deleted_date = ?
WHERE id = ? WHERE id = ?
''', (datetime.datetime.now(), meal_id)) ''', (datetime.datetime.now().astimezone().isoformat(), meal_id))
async def sync_extra_ingredients(conn, meal_id: int, ingredients: List[Ingredient]) -> None: async def sync_extra_ingredients(conn, meal_id: int, ingredients: List[Ingredient]) -> None:
await delete_ingredients_by_meal_id(conn, meal_id) await delete_ingredients_by_meal_id(conn, meal_id)
@ -196,7 +196,7 @@ async def update_meal(conn, meal: Meal) -> None:
UPDATE Meal UPDATE Meal
SET suggested_date = ? SET suggested_date = ?
WHERE id = ? WHERE id = ?
''', (meal.suggested_date, meal.id)) ''', (meal.suggested_date.isoformat(), meal.id))
await sync_meal_participants(conn, meal.id, meal.chefs, 'chef') await sync_meal_participants(conn, meal.id, meal.chefs, 'chef')
await sync_meal_participants(conn, meal.id, meal.cleanup, 'cleanup') await sync_meal_participants(conn, meal.id, meal.cleanup, 'cleanup')
@ -205,22 +205,22 @@ async def update_meal(conn, meal: Meal) -> None:
await sync_extra_ingredients(conn, meal.id, meal.extra_ingredients) await sync_extra_ingredients(conn, meal.id, meal.extra_ingredients)
await sync_meal_recipes(conn, meal.id, meal.recipes) await sync_meal_recipes(conn, meal.id, meal.recipes)
async def mark_consumed(conn, meal: Meal, date: datetime.datetime = datetime.datetime.now()) -> None: async def mark_consumed(conn, meal: Meal, date: datetime.datetime) -> None:
meal.consumed_date = date meal.consumed_date = date
await conn.execute(''' await conn.execute('''
UPDATE Meal UPDATE Meal
SET consumed_date = ? SET consumed_date = ?
WHERE id = ? WHERE id = ?
''', (date, meal.id)) ''', (date.isoformat(), meal.id))
async def mark_purchased(conn, meal: Meal) -> Meal: async def mark_purchased(conn, meal: Meal) -> Meal:
meal.purchase_date = datetime.datetime.now() meal.purchase_date = datetime.datetime.now().astimezone()
await conn.execute(''' await conn.execute('''
UPDATE Meal UPDATE Meal
SET purchase_date = ? SET purchase_date = ?
WHERE id = ? WHERE id = ?
''', (meal.purchase_date, meal.id)) ''', (meal.purchase_date.isoformat(), meal.id))
return meal return meal

View file

@ -18,7 +18,7 @@ class Recipe(BaseModel):
ingredients: List[Ingredient] = [] ingredients: List[Ingredient] = []
based_on_recipe: Optional[int] = None based_on_recipe: Optional[int] = None
date_created: datetime.datetime = datetime.datetime.now() date_created: datetime.datetime = datetime.datetime.now().astimezone()
created_by_id: Optional[int] created_by_id: Optional[int]
created_by: Optional[Person] = None created_by: Optional[Person] = None
@ -36,7 +36,7 @@ async def create(conn):
image_urls TEXT NOT NULL, image_urls TEXT NOT NULL,
based_on_recipe INTEGER NULL, based_on_recipe INTEGER NULL,
date_created DATETIME DEFAULT CURRENT_TIMESTAMP, date_created DATETIME NOT NULL,
created_by_id INTEGER NOT NULL, created_by_id INTEGER NOT NULL,
date_hidden DATETIME DEFAULT NULL, date_hidden DATETIME DEFAULT NULL,
@ -51,6 +51,9 @@ def _as_insert_field(recipe: Recipe, name: str):
value = getattr(recipe, name) value = getattr(recipe, name)
if name == 'image_urls': if name == 'image_urls':
return json.dumps(value) return json.dumps(value)
if isinstance(value, datetime.datetime):
return value.isoformat()
return value return value
async def insert_recipe(conn, recipe: Recipe): async def insert_recipe(conn, recipe: Recipe):
@ -68,9 +71,9 @@ async def insert_recipe(conn, recipe: Recipe):
async def hide_recipe(conn, recipe_id: int, person: Person): async def hide_recipe(conn, recipe_id: int, person: Person):
await conn.execute(''' await conn.execute('''
UPDATE Recipe UPDATE Recipe
SET date_hidden = CURRENT_TIMESTAMP, hidden_by_id = ? SET date_hidden = ?, hidden_by_id = ?
WHERE id = ? WHERE id = ?
''', (person.id, recipe_id)) ''', (datetime.datetime.now().astimezone().isoformat(), person.id, recipe_id))
def row_to_recipe(col_tuples: List[Tuple[str, ...]]) -> Recipe: def row_to_recipe(col_tuples: List[Tuple[str, ...]]) -> Recipe:
d = {k:v for k,v in col_tuples} d = {k:v for k,v in col_tuples}

View file

@ -22,7 +22,7 @@ class ShoppingListRequest(BaseModel):
meal_id: Optional[int] = None meal_id: Optional[int] = None
meal: Optional[Meal] = None meal: Optional[Meal] = None
created_date: datetime = datetime.now() created_date: datetime = datetime.now().astimezone()
class ShoppingListResult(BaseModel): class ShoppingListResult(BaseModel):
KEYS: ClassVar[List[str]] = ['id', 'product_id', 'list_id', 'quantity', 'unit' ] KEYS: ClassVar[List[str]] = ['id', 'product_id', 'list_id', 'quantity', 'unit' ]
@ -44,7 +44,7 @@ class StoreEnum(str, Enum):
class ShoppingList(BaseModel): class ShoppingList(BaseModel):
KEYS: ClassVar[List[str]] = ['id', 'created_date', 'store_name'] KEYS: ClassVar[List[str]] = ['id', 'created_date', 'store_name']
id: int = -1 id: int = -1
created_date: datetime = datetime.now() created_date: datetime = datetime.now().astimezone()
store_name: StoreEnum = '' store_name: StoreEnum = ''
requests: List[ShoppingListRequest] = [] requests: List[ShoppingListRequest] = []
@ -54,8 +54,8 @@ async def create(conn):
await conn.execute(''' await conn.execute('''
CREATE TABLE IF NOT EXISTS ShoppingList ( CREATE TABLE IF NOT EXISTS ShoppingList (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
created_date TEXT, created_date DATETIME,
store_name TEXT, store_name TEXT
);''') );''')
await conn.execute(''' await conn.execute('''
@ -100,10 +100,12 @@ def validate_request(request: ShoppingListRequest) -> None:
raise ValueError('Ingredient requests must have a person') raise ValueError('Ingredient requests must have a person')
async def insert_shopping_list(conn, shopping_list: ShoppingList): async def insert_shopping_list(conn, shopping_list: ShoppingList):
shopping_list.created_date = datetime.now().astimezone()
async with conn.execute(''' async with conn.execute('''
INSERT INTO ShoppingList (created_date, store_name) INSERT INTO ShoppingList (created_date, store_name)
VALUES (CURRENT_TIMESTAMP, ?) VALUES (?, ?)
''', (shopping_list.store_name,)) as cursor: ''', (shopping_list.created_date.isoformat(), shopping_list.store_name,)) as cursor:
shopping_list.id = cursor.lastrowid shopping_list.id = cursor.lastrowid
for request in shopping_list.requests: for request in shopping_list.requests:
@ -123,7 +125,7 @@ async def insert_shopping_list(conn, shopping_list: ShoppingList):
async with conn.execute(''' async with conn.execute('''
INSERT INTO ShoppingListRequest (ingredient_id, list_id, person_id, meal_id, created_date) INSERT INTO ShoppingListRequest (ingredient_id, list_id, person_id, meal_id, created_date)
VALUES (?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?)
''', (request.ingredient_id, shopping_list.id, request.person_id, request.meal_id, request.created_date)) as cursor: ''', (request.ingredient_id, shopping_list.id, request.person_id, request.meal_id, request.created_date.isoformat())) as cursor:
request.id = cursor.lastrowid request.id = cursor.lastrowid
for item in shopping_list.results: for item in shopping_list.results:
@ -244,22 +246,22 @@ async def request_ingredient(conn, person: Person, ingredient: Ingredient) -> Sh
await insert_ingredient(conn, ingredient) await insert_ingredient(conn, ingredient)
request = ShoppingListRequest(ingredient_id=ingredient.id, ingredient=ingredient, person_id=person.id, created_date=datetime.now()) request = ShoppingListRequest(ingredient_id=ingredient.id, ingredient=ingredient, person_id=person.id, created_date=datetime.now().astimezone())
async with conn.execute(''' async with conn.execute('''
INSERT INTO ShoppingListRequest (ingredient_id, person_id, created_date) INSERT INTO ShoppingListRequest (ingredient_id, person_id, created_date)
VALUES (?, ?, ?) VALUES (?, ?, ?)
''', (request.ingredient_id, request.person_id, request.created_date)) as cursor: ''', (request.ingredient_id, request.person_id, request.created_date.isoformat())) as cursor:
request.id = cursor.lastrowid request.id = cursor.lastrowid
return request return request
async def request_meal(conn, person: Person, meal: Meal) -> ShoppingListRequest: async def request_meal(conn, person: Person, meal: Meal) -> ShoppingListRequest:
request = ShoppingListRequest(meal_id=meal.id, meal=meal, person_id=person.id, created_date=datetime.now()) request = ShoppingListRequest(meal_id=meal.id, meal=meal, person_id=person.id, created_date=datetime.now().astimezone())
async with conn.execute(''' async with conn.execute('''
INSERT INTO ShoppingListRequest (meal_id, person_id, created_date) INSERT INTO ShoppingListRequest (meal_id, person_id, created_date)
VALUES (?, ?, ?) VALUES (?, ?, ?)
''', (request.meal_id, request.person_id, request.created_date)) as cursor: ''', (request.meal_id, request.person_id, request.created_date.isoformat())) as cursor:
request.id = cursor.lastrowid request.id = cursor.lastrowid
return request return request

View file

@ -235,11 +235,11 @@ class TestMeals(unittest.IsolatedAsyncioTestCase):
self.assertIsInstance(meal_by_id, meals.Meal, msg=meal_by_id.body if hasattr(meal_by_id, 'body') else meal_by_id) self.assertIsInstance(meal_by_id, meals.Meal, msg=meal_by_id.body if hasattr(meal_by_id, 'body') else meal_by_id)
self.assertIsNone(meal_by_id.consumed_date) self.assertIsNone(meal_by_id.consumed_date)
updated_meal = await main.mark_consumed(meal_id=meal.id, conn=self.conn) updated_meal = await main.mark_consumed(meal_id=meal.id, consumed_date=datetime.datetime.now().astimezone(), conn=self.conn)
self.assertIsNotNone(updated_meal) self.assertIsNotNone(updated_meal)
self.assertIsInstance(updated_meal, meals.Meal, msg=updated_meal.body if hasattr(updated_meal, 'body') else updated_meal) self.assertIsInstance(updated_meal, meals.Meal, msg=updated_meal.body if hasattr(updated_meal, 'body') else updated_meal)
self.assertIsNotNone(updated_meal.consumed_date) self.assertIsNotNone(updated_meal.consumed_date)
self.assertLessEqual(datetime.datetime.now() - updated_meal.consumed_date, datetime.timedelta(seconds=1)) self.assertLessEqual(datetime.datetime.now().astimezone() - updated_meal.consumed_date, datetime.timedelta(seconds=1))
upcoming_meals = await main.get_upcoming_meals(meal.suggested_date, meal.suggested_date, self.conn) upcoming_meals = await main.get_upcoming_meals(meal.suggested_date, meal.suggested_date, self.conn)
self.assertIsNotNone(upcoming_meals) self.assertIsNotNone(upcoming_meals)
@ -250,7 +250,7 @@ class TestMeals(unittest.IsolatedAsyncioTestCase):
self.assertIsNotNone(meal_by_id) self.assertIsNotNone(meal_by_id)
self.assertIsInstance(meal_by_id, meals.Meal, msg=meal_by_id.body if hasattr(meal_by_id, 'body') else meal_by_id) self.assertIsInstance(meal_by_id, meals.Meal, msg=meal_by_id.body if hasattr(meal_by_id, 'body') else meal_by_id)
self.assertIsNotNone(meal_by_id.consumed_date) self.assertIsNotNone(meal_by_id.consumed_date)
self.assertLessEqual(datetime.datetime.now() - meal_by_id.consumed_date, datetime.timedelta(seconds=1)) self.assertLessEqual(datetime.datetime.now().astimezone() - meal_by_id.consumed_date, datetime.timedelta(seconds=1))
async def testUpdate(self) -> None: async def testUpdate(self) -> None:

View file

@ -46,7 +46,7 @@ class TestShopping(unittest.IsolatedAsyncioTestCase):
await recipes.insert_recipe(self.conn, mr.recipe) await recipes.insert_recipe(self.conn, mr.recipe)
mr.recipe_id = mr.recipe.id mr.recipe_id = mr.recipe.id
meal.suggested_date = datetime.now() + timedelta(days=1) meal.suggested_date = datetime.now().astimezone() + timedelta(days=1)
await meals.insert_meal(self.conn, meal) await meals.insert_meal(self.conn, meal)
shopping_list = await shopping.current_shopping_list(self.conn) shopping_list = await shopping.current_shopping_list(self.conn)
@ -109,7 +109,7 @@ class TestShopping(unittest.IsolatedAsyncioTestCase):
await products.insert_product(self.conn, ingredient.product, {}) await products.insert_product(self.conn, ingredient.product, {})
shopping_list = await shopping.current_shopping_list(self.conn) shopping_list = await shopping.current_shopping_list(self.conn)
await shopping.mark_found(self.conn, ingredient, date_found=datetime.now()) await shopping.mark_found(self.conn, ingredient, date_found=datetime.now().astimezone())
shopping_list = await shopping.current_shopping_list(self.conn) shopping_list = await shopping.current_shopping_list(self.conn)
self.assertEqual(len(shopping_list.results), 1) self.assertEqual(len(shopping_list.results), 1)
@ -118,7 +118,7 @@ class TestShopping(unittest.IsolatedAsyncioTestCase):
self.assertEqual(shopping_list.results[0].unit, ingredient.unit) self.assertEqual(shopping_list.results[0].unit, ingredient.unit)
ingredient.quantity = 2 ingredient.quantity = 2
await shopping.mark_found(self.conn, ingredient, date_found=datetime.now()) await shopping.mark_found(self.conn, ingredient, date_found=datetime.now().astimezone())
shopping_list = await shopping.current_shopping_list(self.conn) shopping_list = await shopping.current_shopping_list(self.conn)
self.assertEqual(len(shopping_list.results), 1) self.assertEqual(len(shopping_list.results), 1)
@ -127,7 +127,7 @@ class TestShopping(unittest.IsolatedAsyncioTestCase):
self.assertEqual(shopping_list.results[0].unit, ingredient.unit) self.assertEqual(shopping_list.results[0].unit, ingredient.unit)
ingredient.unit = 'kg' ingredient.unit = 'kg'
await shopping.mark_found(self.conn, ingredient, date_found=datetime.now()) await shopping.mark_found(self.conn, ingredient, date_found=datetime.now().astimezone())
shopping_list = await shopping.current_shopping_list(self.conn) shopping_list = await shopping.current_shopping_list(self.conn)
self.assertEqual(len(shopping_list.results), 2) self.assertEqual(len(shopping_list.results), 2)
@ -149,7 +149,7 @@ class TestShopping(unittest.IsolatedAsyncioTestCase):
shopping_list = await shopping.mark_purchased(self.conn) shopping_list = await shopping.mark_purchased(self.conn)
self.assertIsNotNone(shopping_list.purchased_date) self.assertIsNotNone(shopping_list.purchased_date)
self.assertLessEqual(shopping_list.purchased_date - datetime.now(), timedelta(seconds=1)) self.assertLessEqual(shopping_list.purchased_date - datetime.now().astimezone(), timedelta(seconds=1))
new_shopping_list = await shopping.current_shopping_list(self.conn) new_shopping_list = await shopping.current_shopping_list(self.conn)
self.assertNotEqual(shopping_list.id, new_shopping_list.id) self.assertNotEqual(shopping_list.id, new_shopping_list.id)