Refactor household models and repository queries to use dynamic column selection; remove email from invitation schema in OpenAPI
This commit is contained in:
parent
3e4e4fc2ae
commit
e8f44c839a
3 changed files with 15 additions and 39 deletions
|
|
@ -6,15 +6,13 @@ from common import ApiModel
|
||||||
|
|
||||||
class Household(ApiModel):
|
class Household(ApiModel):
|
||||||
KEYS: ClassVar[list[str]] = ["id", "name", "slug"]
|
KEYS: ClassVar[list[str]] = ["id", "name", "slug"]
|
||||||
|
|
||||||
id: int
|
id: int
|
||||||
name: str
|
name: str
|
||||||
slug: str
|
slug: str
|
||||||
|
|
||||||
|
|
||||||
class HouseholdMember(ApiModel):
|
class HouseholdMember(ApiModel):
|
||||||
KEYS: ClassVar[list[str]] = ["user_id", "household_id", "role"]
|
KEYS: ClassVar[list[str]] = ["id", "display_name", "role"]
|
||||||
|
|
||||||
id: int
|
id: int
|
||||||
display_name: str
|
display_name: str
|
||||||
role: str
|
role: str
|
||||||
|
|
@ -24,16 +22,13 @@ class HouseholdInvitation(ApiModel):
|
||||||
KEYS: ClassVar[list[str]] = [
|
KEYS: ClassVar[list[str]] = [
|
||||||
"id",
|
"id",
|
||||||
"household_id",
|
"household_id",
|
||||||
"email",
|
|
||||||
"invited_by_user_id",
|
"invited_by_user_id",
|
||||||
"token",
|
"token",
|
||||||
"expires_at",
|
"expires_at",
|
||||||
"status",
|
"status",
|
||||||
]
|
]
|
||||||
|
|
||||||
id: int
|
id: int
|
||||||
household_id: int
|
household_id: int
|
||||||
email: str
|
|
||||||
invited_by_user_id: int
|
invited_by_user_id: int
|
||||||
token: str
|
token: str
|
||||||
expires_at: str
|
expires_at: str
|
||||||
|
|
|
||||||
|
|
@ -83,9 +83,10 @@ async def are_members(conn, household_id: int, user_ids: list[int]) -> bool:
|
||||||
|
|
||||||
async def list_for_user(conn, user_id: int) -> List[Household]:
|
async def list_for_user(conn, user_id: int) -> List[Household]:
|
||||||
results: List[Household] = []
|
results: List[Household] = []
|
||||||
|
cols = ", ".join([f"h.{k}" for k in Household.KEYS])
|
||||||
async with conn.execute(
|
async with conn.execute(
|
||||||
"""
|
f"""
|
||||||
SELECT h.id, h.name, h.slug FROM Household h
|
SELECT {cols} FROM Household h
|
||||||
JOIN HouseholdMember m ON m.household_id = h.id
|
JOIN HouseholdMember m ON m.household_id = h.id
|
||||||
WHERE m.user_id = ?
|
WHERE m.user_id = ?
|
||||||
ORDER BY h.id
|
ORDER BY h.id
|
||||||
|
|
@ -93,7 +94,7 @@ async def list_for_user(conn, user_id: int) -> List[Household]:
|
||||||
(user_id,),
|
(user_id,),
|
||||||
) as c:
|
) as c:
|
||||||
async for row in c:
|
async for row in c:
|
||||||
results.append(Household(id=int(row[0]), name=row[1], slug=row[2]))
|
results.append(Household(**{k: v for k, v in zip(Household.KEYS, row)}))
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -117,9 +118,10 @@ async def create_for_user(conn, name: str, slug: str, user_id: int) -> Household
|
||||||
|
|
||||||
async def list_members(conn, household_id: int) -> List[HouseholdMember]:
|
async def list_members(conn, household_id: int) -> List[HouseholdMember]:
|
||||||
members: List[HouseholdMember] = []
|
members: List[HouseholdMember] = []
|
||||||
|
cols = ", ".join([f"u.{k}" for k in ["id", "display_name"]] + ["m.role"])
|
||||||
async with conn.execute(
|
async with conn.execute(
|
||||||
"""
|
f"""
|
||||||
SELECT u.id, u.display_name, m.role
|
SELECT {cols}
|
||||||
FROM HouseholdMember m
|
FROM HouseholdMember m
|
||||||
JOIN User u ON u.id = m.user_id
|
JOIN User u ON u.id = m.user_id
|
||||||
WHERE m.household_id = ?
|
WHERE m.household_id = ?
|
||||||
|
|
@ -129,7 +131,7 @@ async def list_members(conn, household_id: int) -> List[HouseholdMember]:
|
||||||
) as c:
|
) as c:
|
||||||
async for row in c:
|
async for row in c:
|
||||||
members.append(
|
members.append(
|
||||||
HouseholdMember(id=int(row[0]), display_name=row[1], role=row[2])
|
HouseholdMember(**{k: v for k, v in zip(HouseholdMember.KEYS, row)})
|
||||||
)
|
)
|
||||||
return members
|
return members
|
||||||
|
|
||||||
|
|
@ -151,14 +153,15 @@ async def create_invitation(
|
||||||
|
|
||||||
|
|
||||||
async def get_invitation_by_token(conn, token: str) -> HouseholdInvitation | None:
|
async def get_invitation_by_token(conn, token: str) -> HouseholdInvitation | None:
|
||||||
|
cols = ", ".join(HouseholdInvitation.KEYS)
|
||||||
async with conn.execute(
|
async with conn.execute(
|
||||||
"SELECT id, household_id, status FROM HouseholdInvitation WHERE token = ?",
|
f"SELECT {cols} FROM HouseholdInvitation WHERE token = ?",
|
||||||
(token,),
|
(token,),
|
||||||
) as c:
|
) as c:
|
||||||
row = await c.fetchone()
|
row = await c.fetchone()
|
||||||
if not row:
|
if not row:
|
||||||
return None
|
return None
|
||||||
return HouseholdInvitation(id=int(row[0]), household_id=int(row[1]), status=row[2])
|
return HouseholdInvitation(**{k: v for k, v in zip(HouseholdInvitation.KEYS, row)})
|
||||||
|
|
||||||
|
|
||||||
async def accept_invitation(conn, invitation_id: int, user_id: int, household_id: int):
|
async def accept_invitation(conn, invitation_id: int, user_id: int, household_id: int):
|
||||||
|
|
@ -173,11 +176,12 @@ async def accept_invitation(conn, invitation_id: int, user_id: int, household_id
|
||||||
|
|
||||||
|
|
||||||
async def get_household_by_id(conn, household_id: int) -> Household | None:
|
async def get_household_by_id(conn, household_id: int) -> Household | None:
|
||||||
|
cols = ", ".join(Household.KEYS)
|
||||||
async with conn.execute(
|
async with conn.execute(
|
||||||
"SELECT id, name, slug FROM Household WHERE id = ?",
|
f"SELECT {cols} FROM Household WHERE id = ?",
|
||||||
(household_id,),
|
(household_id,),
|
||||||
) as c:
|
) as c:
|
||||||
row = await c.fetchone()
|
row = await c.fetchone()
|
||||||
if not row:
|
if not row:
|
||||||
return None
|
return None
|
||||||
return Household(id=int(row[0]), name=row[1], slug=row[2])
|
return Household(**{k: v for k, v in zip(Household.KEYS, row)})
|
||||||
|
|
|
||||||
23
openapi.json
23
openapi.json
|
|
@ -381,16 +381,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"requestBody": {
|
|
||||||
"required": true,
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/CreateInvitationBody"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "Successful Response",
|
"description": "Successful Response",
|
||||||
|
|
@ -1764,19 +1754,6 @@
|
||||||
],
|
],
|
||||||
"title": "CreateHouseholdBody"
|
"title": "CreateHouseholdBody"
|
||||||
},
|
},
|
||||||
"CreateInvitationBody": {
|
|
||||||
"properties": {
|
|
||||||
"email": {
|
|
||||||
"type": "string",
|
|
||||||
"title": "Email"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"email"
|
|
||||||
],
|
|
||||||
"title": "CreateInvitationBody"
|
|
||||||
},
|
|
||||||
"CurrentShoppingList": {
|
"CurrentShoppingList": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"outstandingItems": {
|
"outstandingItems": {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue