feat: move all remaining inline logic from routers to services (Tier 2)
This commit is contained in:
@@ -13,6 +13,7 @@ from datetime import datetime, timedelta
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy import func
|
||||
|
||||
from app.domain.errors import EntityNotFoundError
|
||||
from app.models.notification import Notification
|
||||
from app.models.user import User
|
||||
|
||||
@@ -22,6 +23,71 @@ from app.models.user import User
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def list_notifications(
|
||||
db: Session,
|
||||
user_id: uuid.UUID,
|
||||
*,
|
||||
offset: int = 0,
|
||||
limit: int = 20,
|
||||
) -> list[Notification]:
|
||||
"""Return paginated notifications for a user, newest first."""
|
||||
return (
|
||||
db.query(Notification)
|
||||
.filter(Notification.user_id == user_id)
|
||||
.order_by(Notification.created_at.desc())
|
||||
.offset(offset)
|
||||
.limit(limit)
|
||||
.all()
|
||||
)
|
||||
|
||||
|
||||
def get_notification_or_raise(
|
||||
db: Session,
|
||||
notification_id: uuid.UUID,
|
||||
user_id: uuid.UUID,
|
||||
) -> Notification:
|
||||
"""Fetch a notification by ID and user, or raise EntityNotFoundError."""
|
||||
notif = (
|
||||
db.query(Notification)
|
||||
.filter(
|
||||
Notification.id == notification_id,
|
||||
Notification.user_id == user_id,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if notif is None:
|
||||
raise EntityNotFoundError("Notification", str(notification_id))
|
||||
return notif
|
||||
|
||||
|
||||
def notify_role(
|
||||
db: Session,
|
||||
*,
|
||||
role: str,
|
||||
type: str,
|
||||
title: str,
|
||||
message: str,
|
||||
entity_type: str,
|
||||
entity_id: uuid.UUID,
|
||||
) -> None:
|
||||
"""Send notifications to all active users with a given role."""
|
||||
users = (
|
||||
db.query(User)
|
||||
.filter(User.role == role, User.is_active == True) # noqa: E712
|
||||
.all()
|
||||
)
|
||||
for user in users:
|
||||
create_notification(
|
||||
db,
|
||||
user_id=user.id,
|
||||
type=type,
|
||||
title=title,
|
||||
message=message,
|
||||
entity_type=entity_type,
|
||||
entity_id=entity_id,
|
||||
)
|
||||
|
||||
|
||||
def create_notification(
|
||||
db: Session,
|
||||
user_id: uuid.UUID,
|
||||
@@ -45,17 +111,13 @@ def create_notification(
|
||||
return notif
|
||||
|
||||
|
||||
def mark_as_read(db: Session, notification_id: uuid.UUID, user_id: uuid.UUID) -> bool:
|
||||
"""Mark a single notification as read. Returns True if updated."""
|
||||
notif = (
|
||||
db.query(Notification)
|
||||
.filter(Notification.id == notification_id, Notification.user_id == user_id)
|
||||
.first()
|
||||
)
|
||||
if notif is None:
|
||||
return False
|
||||
def mark_as_read(
|
||||
db: Session, notification_id: uuid.UUID, user_id: uuid.UUID
|
||||
) -> Notification:
|
||||
"""Mark a single notification as read. Returns the notification. Raises EntityNotFoundError if not found."""
|
||||
notif = get_notification_or_raise(db, notification_id, user_id)
|
||||
notif.read = True
|
||||
return True
|
||||
return notif
|
||||
|
||||
|
||||
def mark_all_as_read(db: Session, user_id: uuid.UUID) -> int:
|
||||
|
||||
Reference in New Issue
Block a user