""" Data models for Notification Service """ from pydantic import BaseModel, Field from datetime import datetime from typing import Optional, List, Dict, Any, Literal from enum import Enum class NotificationChannel(str, Enum): """Notification delivery channels""" EMAIL = "email" SMS = "sms" PUSH = "push" IN_APP = "in_app" class NotificationStatus(str, Enum): """Notification status""" PENDING = "pending" SENT = "sent" DELIVERED = "delivered" READ = "read" FAILED = "failed" CANCELLED = "cancelled" class NotificationPriority(str, Enum): """Notification priority levels""" LOW = "low" NORMAL = "normal" HIGH = "high" URGENT = "urgent" class NotificationCategory(str, Enum): """Notification categories""" SYSTEM = "system" MARKETING = "marketing" TRANSACTION = "transaction" SOCIAL = "social" SECURITY = "security" UPDATE = "update" class Notification(BaseModel): """Notification model""" id: Optional[str] = Field(None, description="Unique notification ID") user_id: str = Field(..., description="Target user ID") title: str = Field(..., description="Notification title") message: str = Field(..., description="Notification message") channel: NotificationChannel = Field(..., description="Delivery channel") status: NotificationStatus = Field(default=NotificationStatus.PENDING) priority: NotificationPriority = Field(default=NotificationPriority.NORMAL) category: NotificationCategory = Field(default=NotificationCategory.SYSTEM) data: Optional[Dict[str, Any]] = Field(default=None, description="Additional data") template_id: Optional[str] = Field(None, description="Template ID if using template") scheduled_at: Optional[datetime] = Field(None, description="Scheduled delivery time") sent_at: Optional[datetime] = Field(None, description="Actual sent time") delivered_at: Optional[datetime] = Field(None, description="Delivery confirmation time") read_at: Optional[datetime] = Field(None, description="Read time") retry_count: int = Field(default=0, description="Number of retry attempts") error_message: Optional[str] = Field(None, description="Error message if failed") created_at: datetime = Field(default_factory=datetime.now) updated_at: datetime = Field(default_factory=datetime.now) class Config: json_encoders = { datetime: lambda v: v.isoformat() } class NotificationTemplate(BaseModel): """Notification template model""" id: Optional[str] = Field(None, description="Template ID") name: str = Field(..., description="Template name") channel: NotificationChannel = Field(..., description="Target channel") category: NotificationCategory = Field(..., description="Template category") subject_template: Optional[str] = Field(None, description="Subject template (for email)") body_template: str = Field(..., description="Body template with variables") variables: List[str] = Field(default_factory=list, description="List of required variables") metadata: Dict[str, Any] = Field(default_factory=dict, description="Template metadata") is_active: bool = Field(default=True, description="Template active status") created_at: datetime = Field(default_factory=datetime.now) updated_at: datetime = Field(default_factory=datetime.now) class Config: json_encoders = { datetime: lambda v: v.isoformat() } class NotificationPreference(BaseModel): """User notification preferences""" user_id: str = Field(..., description="User ID") channels: Dict[NotificationChannel, bool] = Field( default_factory=lambda: { NotificationChannel.EMAIL: True, NotificationChannel.SMS: False, NotificationChannel.PUSH: True, NotificationChannel.IN_APP: True } ) categories: Dict[NotificationCategory, bool] = Field( default_factory=lambda: { NotificationCategory.SYSTEM: True, NotificationCategory.MARKETING: False, NotificationCategory.TRANSACTION: True, NotificationCategory.SOCIAL: True, NotificationCategory.SECURITY: True, NotificationCategory.UPDATE: True } ) quiet_hours: Optional[Dict[str, str]] = Field( default=None, description="Quiet hours configuration {start: 'HH:MM', end: 'HH:MM'}" ) timezone: str = Field(default="UTC", description="User timezone") language: str = Field(default="en", description="Preferred language") email_frequency: Literal["immediate", "daily", "weekly"] = Field(default="immediate") updated_at: datetime = Field(default_factory=datetime.now) class Config: json_encoders = { datetime: lambda v: v.isoformat() } class NotificationHistory(BaseModel): """Notification history entry""" notification_id: str user_id: str channel: NotificationChannel status: NotificationStatus title: str message: str sent_at: Optional[datetime] delivered_at: Optional[datetime] read_at: Optional[datetime] error_message: Optional[str] metadata: Dict[str, Any] = Field(default_factory=dict) class Config: json_encoders = { datetime: lambda v: v.isoformat() } class CreateNotificationRequest(BaseModel): """Request model for creating notification""" user_id: str title: str message: str channels: List[NotificationChannel] = Field(default=[NotificationChannel.IN_APP]) priority: NotificationPriority = Field(default=NotificationPriority.NORMAL) category: NotificationCategory = Field(default=NotificationCategory.SYSTEM) data: Optional[Dict[str, Any]] = None template_id: Optional[str] = None schedule_at: Optional[datetime] = None class BulkNotificationRequest(BaseModel): """Request model for bulk notifications""" user_ids: List[str] title: str message: str channels: List[NotificationChannel] = Field(default=[NotificationChannel.IN_APP]) priority: NotificationPriority = Field(default=NotificationPriority.NORMAL) category: NotificationCategory = Field(default=NotificationCategory.SYSTEM) data: Optional[Dict[str, Any]] = None template_id: Optional[str] = None class DeviceToken(BaseModel): """Device token for push notifications""" user_id: str token: str device_type: Literal["ios", "android", "web"] app_version: Optional[str] = None created_at: datetime = Field(default_factory=datetime.now) updated_at: datetime = Field(default_factory=datetime.now) class Config: json_encoders = { datetime: lambda v: v.isoformat() } class NotificationStats(BaseModel): """Notification statistics""" total_sent: int total_delivered: int total_read: int total_failed: int delivery_rate: float read_rate: float channel_stats: Dict[str, Dict[str, int]] category_stats: Dict[str, Dict[str, int]] period: str class NotificationEvent(BaseModel): """Notification event for tracking""" event_type: Literal["sent", "delivered", "read", "failed", "clicked"] notification_id: str user_id: str channel: NotificationChannel timestamp: datetime = Field(default_factory=datetime.now) metadata: Dict[str, Any] = Field(default_factory=dict) class Config: json_encoders = { datetime: lambda v: v.isoformat() }