Seed Users from legacy Persons for tests; remove Person fallback in meals; fix migration memberships; add indices; remove cookie helpers; spec updated
This commit is contained in:
parent
d41c09d1a3
commit
7b82cca5e3
4 changed files with 41 additions and 68 deletions
|
|
@ -248,20 +248,7 @@ async def load_participants(conn, meal: Meal) -> None:
|
|||
setattr(obj, "display_name", dname)
|
||||
setattr(obj, "name", dname)
|
||||
people[uid] = obj
|
||||
# Fallback to legacy Person table for tests/legacy data
|
||||
if unique_ids and not people:
|
||||
placeholders = ",".join(["?"] * len(unique_ids))
|
||||
async with conn.execute(
|
||||
f"SELECT id, name FROM Person WHERE id IN ({placeholders})",
|
||||
unique_ids,
|
||||
) as c:
|
||||
async for row in c:
|
||||
uid, name = int(row[0]), str(row[1])
|
||||
obj = type("_M", (), {})()
|
||||
setattr(obj, "id", uid)
|
||||
setattr(obj, "display_name", name)
|
||||
setattr(obj, "name", name)
|
||||
people[uid] = obj
|
||||
# No legacy Person fallback: tests should seed User rows via fixtures
|
||||
|
||||
for pid, role in links:
|
||||
person = people.get(pid)
|
||||
|
|
@ -340,20 +327,7 @@ async def bulk_load_participants(conn, meals: List[Meal]) -> None:
|
|||
setattr(obj, "display_name", dname)
|
||||
setattr(obj, "name", dname)
|
||||
people[uid] = obj
|
||||
# Fallback to legacy Person when no users found
|
||||
if unique_ids and not people:
|
||||
placeholders = ",".join(["?"] * len(unique_ids))
|
||||
async with conn.execute(
|
||||
f"SELECT id, name FROM Person WHERE id IN ({placeholders})",
|
||||
unique_ids,
|
||||
) as c:
|
||||
async for row in c:
|
||||
uid, name = int(row[0]), str(row[1])
|
||||
obj = type("_M", (), {})()
|
||||
setattr(obj, "id", uid)
|
||||
setattr(obj, "display_name", name)
|
||||
setattr(obj, "name", name)
|
||||
people[uid] = obj
|
||||
# No legacy Person fallback: tests should seed User rows via fixtures
|
||||
|
||||
# Assign per meal
|
||||
by_id = {m.id: m for m in meals}
|
||||
|
|
|
|||
|
|
@ -105,26 +105,20 @@ async def run_migration(conn: Optional[aiosqlite.Connection] = None):
|
|||
f"CREATE INDEX IF NOT EXISTS idx_{table.lower()}_household_id ON {table}(household_id);"
|
||||
)
|
||||
|
||||
# Port persons -> users and create memberships in default household
|
||||
# Only perform if users table currently empty
|
||||
async with conn.execute("SELECT COUNT(1) FROM User;") as c:
|
||||
row = await c.fetchone()
|
||||
user_count = int(row[0]) if row else 0
|
||||
if user_count == 0:
|
||||
# Port persons -> users (idempotent) and ensure memberships in default household
|
||||
async with conn.execute("SELECT id, name FROM Person;") as cur:
|
||||
async for pid, name in cur:
|
||||
email = f"{name.lower()}@example.com"
|
||||
display_name = name
|
||||
# Insert user
|
||||
await conn.execute(
|
||||
"INSERT INTO User (id, email, display_name) VALUES (?, ?, ?)\n ON CONFLICT(id) DO NOTHING;",
|
||||
"INSERT OR IGNORE INTO User (id, email, display_name) VALUES (?, ?, ?);",
|
||||
(pid, email, display_name),
|
||||
)
|
||||
# Create membership
|
||||
await conn.execute(
|
||||
"INSERT OR IGNORE INTO HouseholdMember (user_id, household_id, role) VALUES (?, ?, ?);",
|
||||
(pid, default_hid, "admin"),
|
||||
)
|
||||
# Ensure all users are members of default household (idempotent)
|
||||
await conn.execute(
|
||||
"INSERT OR IGNORE INTO HouseholdMember (user_id, household_id, role)\n SELECT id, ?, 'admin' FROM User;",
|
||||
(default_hid,),
|
||||
)
|
||||
|
||||
await conn.commit()
|
||||
finally:
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ class Persons:
|
|||
|
||||
|
||||
import products
|
||||
from api.dtos import MemberRef
|
||||
|
||||
|
||||
class Products:
|
||||
|
|
@ -25,7 +26,6 @@ class Products:
|
|||
link="https://www.woolworths.com.au/shop/productdetails/134681/fresh-broccoli",
|
||||
img_small="https://cdn0.woolworths.media/content/wowproductimages/small/134681.jpg",
|
||||
img_large="https://cdn0.woolworths.media/content/wowproductimages/large/134681.jpg",
|
||||
raw_data={},
|
||||
)
|
||||
|
||||
garlic_bread = products.Product(
|
||||
|
|
@ -38,7 +38,6 @@ class Products:
|
|||
link="https://www.woolworths.com.au/shop/productdetails/294517/la-famiglia-garlic-bread",
|
||||
img_small="https://cdn0.woolworths.media/content/wowproductimages/small/294517.jpg",
|
||||
img_large="https://cdn0.woolworths.media/content/wowproductimages/large/294517.jpg",
|
||||
raw_data={},
|
||||
)
|
||||
|
||||
beans_round = products.Product(
|
||||
|
|
@ -51,7 +50,6 @@ class Products:
|
|||
link="https://www.woolworths.com.au/shop/productdetails/134072/beans-round",
|
||||
img_small="https://cdn0.woolworths.media/content/wowproductimages/small/134072.jpg",
|
||||
img_large="https://cdn0.woolworths.media/content/wowproductimages/large/134072.jpg",
|
||||
raw_data={},
|
||||
)
|
||||
|
||||
western_star_unsalted_butter_chefs_choice = products.Product(
|
||||
|
|
@ -64,7 +62,6 @@ class Products:
|
|||
link="https://www.woolworths.com.au/shop/productdetails/712251/western-star-unsalted-butter-chef-s-choice",
|
||||
img_small="https://cdn0.woolworths.media/content/wowproductimages/small/712251.jpg",
|
||||
img_large="https://cdn0.woolworths.media/content/wowproductimages/large/712251.jpg",
|
||||
raw_data={},
|
||||
)
|
||||
|
||||
saxa_iodised_table_salt_shaker = products.Product(
|
||||
|
|
@ -77,7 +74,6 @@ class Products:
|
|||
link="https://www.woolworths.com.au/shop/productdetails/33245/saxa-iodised-table-salt-shaker",
|
||||
img_small="https://cdn0.woolworths.media/content/wowproductimages/small/033245.jpg",
|
||||
img_large="https://cdn0.woolworths.media/content/wowproductimages/large/033245.jpg",
|
||||
raw_data={},
|
||||
)
|
||||
|
||||
mckenzies_pepper_black_ground = products.Product(
|
||||
|
|
@ -90,7 +86,6 @@ class Products:
|
|||
link="https://www.woolworths.com.au/shop/productdetails/75194/mckenzie-s-pepper-black-ground",
|
||||
img_small="https://cdn0.woolworths.media/content/wowproductimages/small/075194.jpg",
|
||||
img_large="https://cdn0.woolworths.media/content/wowproductimages/large/075194.jpg",
|
||||
raw_data={},
|
||||
)
|
||||
|
||||
apple = products.Product(
|
||||
|
|
@ -103,7 +98,6 @@ class Products:
|
|||
link="https://www.woolworths.com.au/shop/productdetails/0/apple",
|
||||
img_small="https://cdn0.woolworths.media/content/wowproductimages/small/0.jpg",
|
||||
img_large="https://cdn0.woolworths.media/content/wowproductimages/large/0.jpg",
|
||||
raw_data={},
|
||||
)
|
||||
|
||||
banana = products.Product(
|
||||
|
|
@ -116,7 +110,6 @@ class Products:
|
|||
link="https://www.woolworths.com.au/shop/productdetails/0/banana",
|
||||
img_small="https://cdn0.woolworths.media/content/wowproductimages/small/0.jpg",
|
||||
img_large="https://cdn0.woolworths.media/content/wowproductimages/large/0.jpg",
|
||||
raw_data={},
|
||||
)
|
||||
|
||||
_tags = {
|
||||
|
|
@ -149,7 +142,7 @@ class Ingredients:
|
|||
line="1 Apple",
|
||||
name="Apple",
|
||||
unit="Items",
|
||||
quantity="1",
|
||||
quantity=1.0,
|
||||
preparation="",
|
||||
product=Products.apple,
|
||||
)
|
||||
|
|
@ -159,7 +152,7 @@ class Ingredients:
|
|||
line="1kg Broccoli, Chopped",
|
||||
name="Broccoli",
|
||||
unit="kg",
|
||||
quantity="1",
|
||||
quantity=1.0,
|
||||
preparation="Chopped",
|
||||
product=Products.broccoli,
|
||||
)
|
||||
|
|
@ -169,7 +162,7 @@ class Ingredients:
|
|||
line="1 Loaf Garlic Bread",
|
||||
name="Garlic Bread",
|
||||
unit="Loaf",
|
||||
quantity="1",
|
||||
quantity=1.0,
|
||||
preparation="",
|
||||
product=Products.garlic_bread,
|
||||
)
|
||||
|
|
@ -256,12 +249,13 @@ from datetime import datetime
|
|||
class Meals:
|
||||
broccoli_soup_for_jacob = meals_db.Meal(
|
||||
id=0,
|
||||
create_date=datetime(2021, 12, 25),
|
||||
created_by=Persons.jacob,
|
||||
suggested_date=datetime(2021, 12, 25),
|
||||
chefs=[Persons.jacob],
|
||||
cleanup=[Persons.ryan],
|
||||
consumers=[Persons.ellie, Persons.chris],
|
||||
chefs=[MemberRef(id=Persons.jacob.id, display_name=Persons.jacob.name)],
|
||||
cleanup=[MemberRef(id=Persons.ryan.id, display_name=Persons.ryan.name)],
|
||||
consumers=[
|
||||
MemberRef(id=Persons.ellie.id, display_name=Persons.ellie.name),
|
||||
MemberRef(id=Persons.chris.id, display_name=Persons.chris.name),
|
||||
],
|
||||
recipes=[
|
||||
meals_db.MealRecipe(meal_id=-1, recipe_id=-1, servings=2, recipe=Recipes.broccoli_soup)
|
||||
],
|
||||
|
|
@ -280,6 +274,13 @@ async def create_persons(conn):
|
|||
|
||||
async def create_test_data(conn):
|
||||
await create_persons(conn)
|
||||
# Seed User/HouseholdMember from legacy Persons to support v2 code paths
|
||||
try:
|
||||
from tests.user_fixtures import seed_users_from_legacy_persons
|
||||
|
||||
await seed_users_from_legacy_persons(conn)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
for product in class_fields(Products).values():
|
||||
await products.insert_product(conn, product, {})
|
||||
|
|
@ -299,7 +300,7 @@ async def create_test_data(conn):
|
|||
"""
|
||||
import re
|
||||
def to_name(thing):
|
||||
return re.sub(r'\W', '', thing['name'].lower().replace(' ', '_'))
|
||||
return re.sub(r"\\W", "", thing["name"].lower().replace(" ", "_"))
|
||||
|
||||
products_order= ['id', 'name', 'product_id', 'link', 'tags', 'img_small', 'img_large', 'raw_data']
|
||||
ingredients_order = 'id line name unit quantity preparation product'.split(' ')
|
||||
|
|
|
|||
|
|
@ -22,12 +22,15 @@ async def seed_users_from_legacy_persons(conn: aiosqlite.Connection):
|
|||
if row and int(row[0]) > 0:
|
||||
return
|
||||
|
||||
# Default household id (created by migration/bootstrap)
|
||||
async with conn.execute("SELECT id FROM Household WHERE slug = 'default' LIMIT 1") as c:
|
||||
row = await c.fetchone()
|
||||
if not row:
|
||||
return
|
||||
hid = int(row[0])
|
||||
# Default household id (if present)
|
||||
hid: int | None = None
|
||||
try:
|
||||
async with conn.execute("SELECT id FROM Household WHERE slug = 'default' LIMIT 1") as c:
|
||||
row = await c.fetchone()
|
||||
if row:
|
||||
hid = int(row[0])
|
||||
except Exception:
|
||||
hid = None
|
||||
|
||||
# Copy over Person rows into User and create membership
|
||||
try:
|
||||
|
|
@ -38,10 +41,11 @@ async def seed_users_from_legacy_persons(conn: aiosqlite.Connection):
|
|||
"INSERT OR IGNORE INTO User (id, email, display_name) VALUES (?, ?, ?)",
|
||||
(int(pid), email, str(name)),
|
||||
)
|
||||
await conn.execute(
|
||||
"INSERT OR IGNORE INTO HouseholdMember (user_id, household_id, role) VALUES (?, ?, 'admin')",
|
||||
(int(pid), hid),
|
||||
)
|
||||
if hid is not None:
|
||||
await conn.execute(
|
||||
"INSERT OR IGNORE INTO HouseholdMember (user_id, household_id, role) VALUES (?, ?, 'admin')",
|
||||
(int(pid), hid),
|
||||
)
|
||||
except Exception:
|
||||
# Person table may not exist in some contexts; ignore
|
||||
return
|
||||
|
|
|
|||
Loading…
Reference in a new issue