app.routes.notifications
Notification routing module.
Provides authenticated endpoints for retrieving notifications, checking the unread badge count, and marking a notification as read.
1""" 2Notification routing module. 3 4Provides authenticated endpoints for retrieving notifications, checking the 5unread badge count, and marking a notification as read. 6""" 7 8from __future__ import annotations 9 10from datetime import datetime 11from uuid import UUID 12 13from fastapi import APIRouter, Depends, HTTPException, status 14from pydantic import BaseModel, ConfigDict 15from sqlmodel.ext.asyncio.session import AsyncSession 16 17from app.database import get_session 18from app.models import User 19from app.services.auth import current_active_user 20from app.services.notification_service import ( 21 NotificationNotFoundError, 22 get_notification_for_user, 23 get_notifications, 24 get_unread_count, 25 mark_read, 26) 27 28router = APIRouter(prefix="/api/notifications", tags=["notifications"]) 29 30 31class NotificationRead(BaseModel): 32 model_config = ConfigDict(from_attributes=True) 33 34 id: int 35 bookingID: int 36 message: str 37 type: str 38 isRead: bool 39 createdAt: datetime 40 41 42class UnreadCountRead(BaseModel): 43 count: int 44 45 46 47@router.get("", response_model=list[NotificationRead]) 48async def list_notifications( 49 user: User = Depends(current_active_user), 50 session: AsyncSession = Depends(get_session), 51): 52 return await session.run_sync(lambda sync_session: get_notifications(user.id, sync_session)) 53 54 55@router.get("/unread-count", response_model=UnreadCountRead) 56async def unread_count( 57 user: User = Depends(current_active_user), 58 session: AsyncSession = Depends(get_session), 59): 60 count = await session.run_sync(lambda sync_session: get_unread_count(user.id, sync_session)) 61 return UnreadCountRead(count=count) 62 63 64@router.patch("/{notification_id}/read", response_model=NotificationRead) 65async def read_notification( 66 notification_id: int, 67 user: User = Depends(current_active_user), 68 session: AsyncSession = Depends(get_session), 69): 70 try: 71 await session.run_sync( 72 lambda sync_session: get_notification_for_user( 73 notification_id, user.id, sync_session 74 ) 75 ) 76 return await session.run_sync( 77 lambda sync_session: mark_read(notification_id, sync_session) 78 ) 79 except NotificationNotFoundError as exc: 80 raise HTTPException( 81 status_code=status.HTTP_404_NOT_FOUND, 82 detail=str(exc), 83 ) from exc
32class NotificationRead(BaseModel): 33 model_config = ConfigDict(from_attributes=True) 34 35 id: int 36 bookingID: int 37 message: str 38 type: str 39 isRead: bool 40 createdAt: datetime
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
__class_vars__: The names of the class variables defined on the model.
__private_attributes__: Metadata about the private attributes of the model.
__signature__: The synthesized __init__ [Signature][inspect.Signature] of the model.
__pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
__pydantic_core_schema__: The core schema of the model.
__pydantic_custom_init__: Whether the model has a custom `__init__` function.
__pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces `Model.__validators__` and `Model.__root_validators__` from Pydantic V1.
__pydantic_generic_metadata__: Metadata for generic models; contains data used for a similar purpose to
__args__, __origin__, __parameters__ in typing-module generics. May eventually be replaced by these.
__pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
__pydantic_post_init__: The name of the post-init method for the model, if defined.
__pydantic_root_model__: Whether the model is a [`RootModel`][pydantic.root_model.RootModel].
__pydantic_serializer__: The `pydantic-core` `SchemaSerializer` used to dump instances of the model.
__pydantic_validator__: The `pydantic-core` `SchemaValidator` used to validate instances of the model.
__pydantic_fields__: A dictionary of field names and their corresponding [`FieldInfo`][pydantic.fields.FieldInfo] objects.
__pydantic_computed_fields__: A dictionary of computed field names and their corresponding [`ComputedFieldInfo`][pydantic.fields.ComputedFieldInfo] objects.
__pydantic_extra__: A dictionary containing extra values, if [`extra`][pydantic.config.ConfigDict.extra]
is set to `'allow'`.
__pydantic_fields_set__: The names of fields explicitly set during instantiation.
__pydantic_private__: Values of private attributes set on the model instance.
!!! abstract "Usage Documentation" Models
A base class for creating Pydantic models.
Attributes:
__class_vars__: The names of the class variables defined on the model.
__private_attributes__: Metadata about the private attributes of the model.
__signature__: The synthesized __init__ [Signature][inspect.Signature] of the model.
__pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
__pydantic_core_schema__: The core schema of the model.
__pydantic_custom_init__: Whether the model has a custom `__init__` function.
__pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces `Model.__validators__` and `Model.__root_validators__` from Pydantic V1.
__pydantic_generic_metadata__: Metadata for generic models; contains data used for a similar purpose to
__args__, __origin__, __parameters__ in typing-module generics. May eventually be replaced by these.
__pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
__pydantic_post_init__: The name of the post-init method for the model, if defined.
__pydantic_root_model__: Whether the model is a [`RootModel`][pydantic.root_model.RootModel].
__pydantic_serializer__: The `pydantic-core` `SchemaSerializer` used to dump instances of the model.
__pydantic_validator__: The `pydantic-core` `SchemaValidator` used to validate instances of the model.
__pydantic_fields__: A dictionary of field names and their corresponding [`FieldInfo`][pydantic.fields.FieldInfo] objects.
__pydantic_computed_fields__: A dictionary of computed field names and their corresponding [`ComputedFieldInfo`][pydantic.fields.ComputedFieldInfo] objects.
__pydantic_extra__: A dictionary containing extra values, if [`extra`][pydantic.config.ConfigDict.extra]
is set to `'allow'`.
__pydantic_fields_set__: The names of fields explicitly set during instantiation.
__pydantic_private__: Values of private attributes set on the model instance.
56@router.get("/unread-count", response_model=UnreadCountRead) 57async def unread_count( 58 user: User = Depends(current_active_user), 59 session: AsyncSession = Depends(get_session), 60): 61 count = await session.run_sync(lambda sync_session: get_unread_count(user.id, sync_session)) 62 return UnreadCountRead(count=count)
65@router.patch("/{notification_id}/read", response_model=NotificationRead) 66async def read_notification( 67 notification_id: int, 68 user: User = Depends(current_active_user), 69 session: AsyncSession = Depends(get_session), 70): 71 try: 72 await session.run_sync( 73 lambda sync_session: get_notification_for_user( 74 notification_id, user.id, sync_session 75 ) 76 ) 77 return await session.run_sync( 78 lambda sync_session: mark_read(notification_id, sync_session) 79 ) 80 except NotificationNotFoundError as exc: 81 raise HTTPException( 82 status_code=status.HTTP_404_NOT_FOUND, 83 detail=str(exc), 84 ) from exc