MukeshKapoor25's picture
refactor(notification-ms): migrate templates to company-level and integrate merchant context
f773f54
"""
Notification models and Pydantic schemas.
"""
import uuid
from datetime import datetime
from typing import Optional, List, Dict, Any
from enum import Enum
from pydantic import BaseModel, Field
class NotificationChannel(str, Enum):
WHATSAPP = "whatsapp"
EMAIL = "email"
SMS = "sms"
PUSH = "push"
class NotificationStatus(str, Enum):
PENDING = "pending"
QUEUED = "queued"
SENDING = "sending"
SENT = "sent"
DELIVERED = "delivered"
FAILED = "failed"
class NotificationPriority(str, Enum):
LOW = "low"
NORMAL = "normal"
HIGH = "high"
CRITICAL = "critical"
# --- Request Schemas ---
class SendNotificationRequest(BaseModel):
"""Send a notification via one or more channels."""
recipient: str = Field(..., description="Phone number (with country code) or email")
channels: List[NotificationChannel] = Field(
default=[NotificationChannel.WHATSAPP],
description="Delivery channels"
)
template_name: str = Field(..., description="Template identifier")
template_data: Dict[str, Any] = Field(default_factory=dict)
priority: NotificationPriority = Field(default=NotificationPriority.NORMAL)
source: Optional[str] = Field(None, description="Originating microservice")
merchant_id: str = Field(..., description="Merchant ID (required for credential lookup)")
merchant_name: Optional[str] = Field("", description="Merchant name (injected into template variables at dispatch)")
metadata: Optional[Dict[str, Any]] = None
class SendBatchRequest(BaseModel):
"""Send notifications to multiple recipients."""
notifications: List[SendNotificationRequest] = Field(
..., min_length=1, max_length=100
)
class ListNotificationsRequest(BaseModel):
"""List notifications with filters and projection support."""
filters: Optional[Dict[str, Any]] = Field(default_factory=dict)
skip: int = Field(default=0, ge=0)
limit: int = Field(default=50, ge=1, le=200)
projection_list: Optional[List[str]] = Field(
None, description="List of fields to include in response"
)
# --- Response Schemas ---
class SendNotificationResponse(BaseModel):
success: bool
notification_id: str
message: str
channels: List[str]
class SendBatchResponse(BaseModel):
success: bool
total: int
queued: int
failed: int
results: List[SendNotificationResponse]
class NotificationDetail(BaseModel):
notification_id: str
recipient: str
channels: List[str]
template_name: str
template_data: Dict[str, Any] = {}
status: str
priority: str = "normal"
source: Optional[str] = None
merchant_id: Optional[str] = None
merchant_name: Optional[str] = None
channel_results: Dict[str, Any] = {}
retry_count: int = 0
created_at: Optional[datetime] = None
updated_at: Optional[datetime] = None
sent_at: Optional[datetime] = None
class ListNotificationsResponse(BaseModel):
success: bool = True
total: int
skip: int
limit: int
data: List[Any]
# --- MongoDB Document Shape ---
def new_notification_doc(req: SendNotificationRequest) -> Dict[str, Any]:
now = datetime.utcnow()
return {
"notification_id": str(uuid.uuid4()),
"recipient": req.recipient,
"channels": [ch.value for ch in req.channels],
"template_name": req.template_name,
"template_data": req.template_data,
"priority": req.priority.value,
"status": NotificationStatus.QUEUED.value,
"source": req.source,
"merchant_id": req.merchant_id,
"merchant_name": req.merchant_name or "",
"metadata": req.metadata or {},
"channel_results": {},
"retry_count": 0,
"created_at": now,
"updated_at": now,
"sent_at": None,
}