Files
orion/app/api/v1/admin/notifications.py
Samir Boulahtit eeafe6389f fix: resolve all remaining legacy import issues
- Update models/database/__init__.py to import from module locations
- Update models/schema/__init__.py to remove deleted modules
- Update models/__init__.py to import Inventory from module
- Remove duplicate AdminNotification from models/database/admin.py
- Fix monitoring module to import AdminNotification from messaging
- Update stats schema imports in admin/vendor API
- Update notification schema imports
- Add order_item_exception.py schema to orders module
- Fix app/api/v1/__init__.py to use storefront instead of shop
- Add cms_admin_pages import to main.py
- Fix password_reset_token imports
- Fix AdminNotification test imports

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 09:21:29 +01:00

328 lines
11 KiB
Python

# app/api/v1/admin/notifications.py
"""
Admin notifications and platform alerts endpoints.
Provides endpoints for:
- Viewing admin notifications
- Managing platform alerts
- System health monitoring
"""
import logging
from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session
from app.api.deps import get_current_admin_api
from app.core.database import get_db
from app.services.admin_notification_service import (
admin_notification_service,
platform_alert_service,
)
from models.database.user import User
from models.schema.admin import (
AdminNotificationCreate,
AdminNotificationListResponse,
AdminNotificationResponse,
PlatformAlertCreate,
PlatformAlertListResponse,
PlatformAlertResolve,
PlatformAlertResponse,
)
from app.modules.messaging.schemas import (
AlertStatisticsResponse,
MessageResponse,
UnreadCountResponse,
)
router = APIRouter(prefix="/notifications")
logger = logging.getLogger(__name__)
# ============================================================================
# ADMIN NOTIFICATIONS
# ============================================================================
@router.get("", response_model=AdminNotificationListResponse)
def get_notifications(
priority: str | None = Query(None, description="Filter by priority"),
notification_type: str | None = Query(None, description="Filter by type"),
is_read: bool | None = Query(None, description="Filter by read status"),
skip: int = Query(0, ge=0),
limit: int = Query(50, ge=1, le=100),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
) -> AdminNotificationListResponse:
"""Get admin notifications with filtering."""
notifications, total, unread_count = admin_notification_service.get_notifications(
db=db,
priority=priority,
is_read=is_read,
notification_type=notification_type,
skip=skip,
limit=limit,
)
return AdminNotificationListResponse(
notifications=[
AdminNotificationResponse(
id=n.id,
type=n.type,
priority=n.priority,
title=n.title,
message=n.message,
is_read=n.is_read,
read_at=n.read_at,
read_by_user_id=n.read_by_user_id,
action_required=n.action_required,
action_url=n.action_url,
metadata=n.notification_metadata,
created_at=n.created_at,
)
for n in notifications
],
total=total,
unread_count=unread_count,
skip=skip,
limit=limit,
)
@router.post("", response_model=AdminNotificationResponse)
def create_notification(
notification_data: AdminNotificationCreate,
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
) -> AdminNotificationResponse:
"""Create a new admin notification (manual)."""
notification = admin_notification_service.create_from_schema(
db=db, data=notification_data
)
db.commit()
logger.info(f"Admin {current_admin.username} created notification: {notification.title}")
return AdminNotificationResponse(
id=notification.id,
type=notification.type,
priority=notification.priority,
title=notification.title,
message=notification.message,
is_read=notification.is_read,
read_at=notification.read_at,
read_by_user_id=notification.read_by_user_id,
action_required=notification.action_required,
action_url=notification.action_url,
metadata=notification.notification_metadata,
created_at=notification.created_at,
)
@router.get("/recent")
def get_recent_notifications(
limit: int = Query(5, ge=1, le=10),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
) -> dict:
"""Get recent unread notifications for header dropdown."""
notifications = admin_notification_service.get_recent_notifications(
db=db, limit=limit
)
unread_count = admin_notification_service.get_unread_count(db)
return {
"notifications": [
{
"id": n.id,
"type": n.type,
"priority": n.priority,
"title": n.title,
"message": n.message[:100] + "..." if len(n.message) > 100 else n.message,
"action_url": n.action_url,
"created_at": n.created_at.isoformat(),
}
for n in notifications
],
"unread_count": unread_count,
}
@router.get("/unread-count", response_model=UnreadCountResponse)
def get_unread_count(
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
) -> UnreadCountResponse:
"""Get count of unread notifications."""
count = admin_notification_service.get_unread_count(db)
return UnreadCountResponse(unread_count=count)
@router.put("/{notification_id}/read", response_model=MessageResponse)
def mark_as_read(
notification_id: int,
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
) -> MessageResponse:
"""Mark notification as read."""
notification = admin_notification_service.mark_as_read(
db=db, notification_id=notification_id, user_id=current_admin.id
)
db.commit()
if notification:
return MessageResponse(message="Notification marked as read")
return MessageResponse(message="Notification not found")
@router.put("/mark-all-read", response_model=MessageResponse)
def mark_all_as_read(
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
) -> MessageResponse:
"""Mark all notifications as read."""
count = admin_notification_service.mark_all_as_read(
db=db, user_id=current_admin.id
)
db.commit()
return MessageResponse(message=f"Marked {count} notifications as read")
@router.delete("/{notification_id}", response_model=MessageResponse)
def delete_notification(
notification_id: int,
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
) -> MessageResponse:
"""Delete a notification."""
deleted = admin_notification_service.delete_notification(
db=db, notification_id=notification_id
)
db.commit()
if deleted:
return MessageResponse(message="Notification deleted")
return MessageResponse(message="Notification not found")
# ============================================================================
# PLATFORM ALERTS
# ============================================================================
@router.get("/alerts", response_model=PlatformAlertListResponse)
def get_platform_alerts(
severity: str | None = Query(None, description="Filter by severity"),
alert_type: str | None = Query(None, description="Filter by alert type"),
is_resolved: bool | None = Query(None, description="Filter by resolution status"),
skip: int = Query(0, ge=0),
limit: int = Query(50, ge=1, le=100),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
) -> PlatformAlertListResponse:
"""Get platform alerts with filtering."""
alerts, total, active_count, critical_count = platform_alert_service.get_alerts(
db=db,
severity=severity,
alert_type=alert_type,
is_resolved=is_resolved,
skip=skip,
limit=limit,
)
return PlatformAlertListResponse(
alerts=[
PlatformAlertResponse(
id=a.id,
alert_type=a.alert_type,
severity=a.severity,
title=a.title,
description=a.description,
affected_vendors=a.affected_vendors,
affected_systems=a.affected_systems,
is_resolved=a.is_resolved,
resolved_at=a.resolved_at,
resolved_by_user_id=a.resolved_by_user_id,
resolution_notes=a.resolution_notes,
auto_generated=a.auto_generated,
occurrence_count=a.occurrence_count,
first_occurred_at=a.first_occurred_at,
last_occurred_at=a.last_occurred_at,
created_at=a.created_at,
)
for a in alerts
],
total=total,
active_count=active_count,
critical_count=critical_count,
skip=skip,
limit=limit,
)
@router.post("/alerts", response_model=PlatformAlertResponse)
def create_platform_alert(
alert_data: PlatformAlertCreate,
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
) -> PlatformAlertResponse:
"""Create new platform alert (manual)."""
alert = platform_alert_service.create_from_schema(db=db, data=alert_data)
db.commit()
logger.info(f"Admin {current_admin.username} created alert: {alert.title}")
return PlatformAlertResponse(
id=alert.id,
alert_type=alert.alert_type,
severity=alert.severity,
title=alert.title,
description=alert.description,
affected_vendors=alert.affected_vendors,
affected_systems=alert.affected_systems,
is_resolved=alert.is_resolved,
resolved_at=alert.resolved_at,
resolved_by_user_id=alert.resolved_by_user_id,
resolution_notes=alert.resolution_notes,
auto_generated=alert.auto_generated,
occurrence_count=alert.occurrence_count,
first_occurred_at=alert.first_occurred_at,
last_occurred_at=alert.last_occurred_at,
created_at=alert.created_at,
)
@router.put("/alerts/{alert_id}/resolve", response_model=MessageResponse)
def resolve_platform_alert(
alert_id: int,
resolve_data: PlatformAlertResolve,
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
) -> MessageResponse:
"""Resolve platform alert."""
alert = platform_alert_service.resolve_alert(
db=db,
alert_id=alert_id,
user_id=current_admin.id,
resolution_notes=resolve_data.resolution_notes,
)
db.commit()
if alert:
logger.info(f"Admin {current_admin.username} resolved alert {alert_id}")
return MessageResponse(message="Alert resolved successfully")
return MessageResponse(message="Alert not found or already resolved")
@router.get("/alerts/stats", response_model=AlertStatisticsResponse)
def get_alert_statistics(
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
) -> AlertStatisticsResponse:
"""Get alert statistics for dashboard."""
stats = platform_alert_service.get_statistics(db)
return AlertStatisticsResponse(**stats)