munch-ease-backend/households/repository.py

78 lines
2.5 KiB
Python
Raw Normal View History

async def create(conn):
# Households table
await conn.execute(
"""
CREATE TABLE IF NOT EXISTS Household (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
slug TEXT NOT NULL UNIQUE
);
"""
)
# Membership table
await conn.execute(
"""
CREATE TABLE IF NOT EXISTS HouseholdMember (
user_id INTEGER NOT NULL,
household_id INTEGER NOT NULL,
role TEXT NOT NULL,
PRIMARY KEY (user_id, household_id),
FOREIGN KEY(user_id) REFERENCES User(id) ON DELETE CASCADE,
FOREIGN KEY(household_id) REFERENCES Household(id) ON DELETE CASCADE
);
"""
)
# Invitations table
await conn.execute(
"""
CREATE TABLE IF NOT EXISTS HouseholdInvitation (
id INTEGER PRIMARY KEY,
household_id INTEGER NOT NULL,
email TEXT NOT NULL,
invited_by_user_id INTEGER NOT NULL,
token TEXT NOT NULL UNIQUE,
expires_at DATETIME NOT NULL,
status TEXT NOT NULL,
FOREIGN KEY(household_id) REFERENCES Household(id) ON DELETE CASCADE,
FOREIGN KEY(invited_by_user_id) REFERENCES User(id) ON DELETE SET NULL
);
"""
)
# Indices
2025-11-01 04:34:01 +00:00
await conn.execute("CREATE INDEX IF NOT EXISTS idx_household_slug ON Household(slug);")
await conn.execute(
"CREATE INDEX IF NOT EXISTS idx_household_member_household ON HouseholdMember(household_id);"
)
2025-11-02 06:45:12 +00:00
async def member_ids_in_household(conn, household_id: int, user_ids: list[int]) -> set[int]:
"""Return the subset of user_ids that are members of the given household.
Uses HouseholdMember join User to ensure users exist.
"""
if not user_ids:
return set()
placeholders = ",".join(["?"] * len(user_ids))
query = f"""
SELECT u.id
FROM HouseholdMember hm
JOIN User u ON u.id = hm.user_id
WHERE hm.household_id = ? AND u.id IN ({placeholders})
"""
valid: set[int] = set()
async with conn.execute(query, (household_id, *sorted(user_ids))) as c:
async for row in c:
valid.add(int(row[0]))
return valid
async def are_members(conn, household_id: int, user_ids: list[int]) -> bool:
"""True only if all provided user_ids are members of the household."""
if not user_ids:
return True
found = await member_ids_in_household(conn, household_id, user_ids)
return found == set(user_ids)