feat: Implement Step 10-11 - Statistics and Notification Services
Step 10: Data Analytics and Statistics Service - Created comprehensive statistics service with real-time metrics collection - Implemented time-series data storage interface (InfluxDB compatible) - Added data aggregation and analytics endpoints - Integrated Redis caching for performance optimization - Made Kafka connection optional for resilience Step 11: Real-time Notification System - Built multi-channel notification service (Email, SMS, Push, In-App) - Implemented priority-based queue management with Redis - Created template engine for dynamic notifications - Added user preference management for personalized notifications - Integrated WebSocket server for real-time updates - Fixed pymongo/motor compatibility issues (motor 3.5.1) Testing: - Created comprehensive test suites for both services - Added integration test script to verify cross-service communication - All services passing health checks and functional tests 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
201
services/notifications/backend/models.py
Normal file
201
services/notifications/backend/models.py
Normal file
@ -0,0 +1,201 @@
|
||||
"""
|
||||
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()
|
||||
}
|
||||
Reference in New Issue
Block a user