Support getting all invited events /w pending ones

This commit is contained in:
Peter Vacho 2025-01-04 18:11:01 +01:00
parent 516bac573a
commit 82e82b9317
Signed by: school
GPG key ID: 8CFC3837052871B4
2 changed files with 30 additions and 7 deletions

View file

@ -1,7 +1,8 @@
from datetime import datetime from datetime import datetime
from typing import Annotated, cast, final from typing import Annotated, Literal, cast, final
from beanie import Link, PydanticObjectId from beanie import Link, PydanticObjectId
from beanie.odm.operators.find.comparison import In
from fastapi import APIRouter, Body, HTTPException, Query, status from fastapi import APIRouter, Body, HTTPException, Query, status
from fastapi.responses import Response from fastapi.responses import Response
from pydantic import BaseModel, StringConstraints, field_serializer, field_validator from pydantic import BaseModel, StringConstraints, field_serializer, field_validator
@ -232,16 +233,21 @@ async def get_user_invited_events(
start_to: Annotated[datetime | None, Query()] = None, start_to: Annotated[datetime | None, Query()] = None,
end_from: Annotated[datetime | None, Query()] = None, end_from: Annotated[datetime | None, Query()] = None,
end_to: Annotated[datetime | None, Query()] = None, end_to: Annotated[datetime | None, Query()] = None,
invite_status: Annotated[Literal["pending", "accepted"] | None, Query()] = None,
) -> list[EventData]: ) -> list[EventData]:
"""Get all events that given user was invited to. """Get all events that given user was invited to.
These are the events that the user has already accepted the invite for. These are the events that the user has already accepted the invite for
Events pending acceptance are not included. and the events that the user has a pending invite for.
Optionally, it's possible to use query params to filter the events Optionally, it's possible to use query params to filter the events
based on the date-time of the event. The dates are specified in ISO 8601 format. based on the date-time of the event. The dates are specified in ISO 8601 format.
E.g.: /users/{user_id}/events/invited?start_from=2024-12-29T13:48:53.228234Z E.g.: /users/{user_id}/events/invited?start_from=2024-12-29T13:48:53.228234Z
It's also possible to filter the events based on the invite status.
E.g.: /users/{user_id}/events/invited?invite_status=accepted
""" """
if user_id != user.id: if user_id != user.id:
raise HTTPException( raise HTTPException(
@ -250,7 +256,17 @@ async def get_user_invited_events(
) )
# Initial query (all events the user is attending) # Initial query (all events the user is attending)
query = Event.find(expr(Event.attendees).id == user_id) query = Event.find()
if invite_status is None or invite_status == "accepted":
query = query.find(expr(Event.attendees).id == user_id)
if invite_status is None or invite_status == "pending":
invitations = await Invitation.find(
expr(Invitation.invitee).id == user_id,
expr(Invitation.status) == "pending",
).to_list()
event_ids = get_id_list([invite.event for invite in invitations], allow_links=True)
query = Event.find(In(expr(Event.id), event_ids))
# Filter by date-time # Filter by date-time
if start_from is not None: if start_from is not None:

View file

@ -41,12 +41,19 @@ class IdNotFoundError[T: Document](ValueError):
super().__init__(f"Item with id {item_id} of type {typ.__name__} not found") super().__init__(f"Item with id {item_id} of type {typ.__name__} not found")
def get_id_list[T: Document](items: Sequence[T | Link[T]]) -> list[PydanticObjectId]: def get_id_list[T: Document](items: Sequence[T | Link[T]], *, allow_links: bool = False) -> list[PydanticObjectId]:
"""Extracts the ids from a list of db items.""" """Extracts the ids from a list of db items.
:param items: List of db items.
:param allow_links: If True, allows returning reference ids of unfetched Link objects.
"""
id_list: list[PydanticObjectId] = [] id_list: list[PydanticObjectId] = []
for item in items: for item in items:
if isinstance(item, Link): if isinstance(item, Link):
if not allow_links:
raise UnfetchedLinkError(item) raise UnfetchedLinkError(item)
id_list.append(item.ref.id)
continue
if item.id is None: if item.id is None:
raise MissingIdError(item) raise MissingIdError(item)