Initial commit - production deployment
This commit is contained in:
0
services/notification/app/schemas/__init__.py
Normal file
0
services/notification/app/schemas/__init__.py
Normal file
291
services/notification/app/schemas/notifications.py
Normal file
291
services/notification/app/schemas/notifications.py
Normal file
@@ -0,0 +1,291 @@
|
||||
# ================================================================
|
||||
# services/notification/app/schemas/notifications.py
|
||||
# ================================================================
|
||||
"""
|
||||
Notification schemas for API validation and serialization
|
||||
"""
|
||||
|
||||
from pydantic import BaseModel, EmailStr, Field, validator
|
||||
from typing import Optional, Dict, Any, List
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
|
||||
# Reuse enums from models
|
||||
class NotificationType(str, Enum):
|
||||
EMAIL = "email"
|
||||
WHATSAPP = "whatsapp"
|
||||
PUSH = "push"
|
||||
SMS = "sms"
|
||||
|
||||
class NotificationStatus(str, Enum):
|
||||
PENDING = "pending"
|
||||
SENT = "sent"
|
||||
DELIVERED = "delivered"
|
||||
FAILED = "failed"
|
||||
CANCELLED = "cancelled"
|
||||
|
||||
class NotificationPriority(str, Enum):
|
||||
LOW = "low"
|
||||
NORMAL = "normal"
|
||||
HIGH = "high"
|
||||
URGENT = "urgent"
|
||||
|
||||
# ================================================================
|
||||
# REQUEST SCHEMAS
|
||||
# ================================================================
|
||||
|
||||
class NotificationCreate(BaseModel):
|
||||
"""Schema for creating a new notification"""
|
||||
type: NotificationType
|
||||
recipient_id: Optional[str] = None # For individual notifications
|
||||
recipient_email: Optional[EmailStr] = None
|
||||
recipient_phone: Optional[str] = None
|
||||
|
||||
# Content
|
||||
subject: Optional[str] = None
|
||||
message: str = Field(..., min_length=1, max_length=5000)
|
||||
html_content: Optional[str] = None
|
||||
|
||||
# Template-based content
|
||||
template_id: Optional[str] = None
|
||||
template_data: Optional[Dict[str, Any]] = None
|
||||
|
||||
# Configuration
|
||||
priority: NotificationPriority = NotificationPriority.NORMAL
|
||||
scheduled_at: Optional[datetime] = None
|
||||
broadcast: bool = False
|
||||
|
||||
# Internal fields (set by service)
|
||||
tenant_id: Optional[str] = None
|
||||
sender_id: Optional[str] = None
|
||||
|
||||
@validator('recipient_phone')
|
||||
def validate_phone(cls, v):
|
||||
"""Validate Spanish phone number format"""
|
||||
if v and not v.startswith(('+34', '6', '7', '9')):
|
||||
raise ValueError('Invalid Spanish phone number format')
|
||||
return v
|
||||
|
||||
@validator('scheduled_at')
|
||||
def validate_scheduled_at(cls, v):
|
||||
"""Ensure scheduled time is in the future"""
|
||||
if v and v <= datetime.utcnow():
|
||||
raise ValueError('Scheduled time must be in the future')
|
||||
return v
|
||||
|
||||
class NotificationUpdate(BaseModel):
|
||||
"""Schema for updating notification status"""
|
||||
status: Optional[NotificationStatus] = None
|
||||
error_message: Optional[str] = None
|
||||
delivered_at: Optional[datetime] = None
|
||||
read: Optional[bool] = None
|
||||
read_at: Optional[datetime] = None
|
||||
|
||||
class BulkNotificationCreate(BaseModel):
|
||||
"""Schema for creating bulk notifications"""
|
||||
type: NotificationType
|
||||
recipients: List[str] = Field(..., min_items=1, max_items=1000) # User IDs or emails
|
||||
|
||||
# Content
|
||||
subject: Optional[str] = None
|
||||
message: str = Field(..., min_length=1, max_length=5000)
|
||||
html_content: Optional[str] = None
|
||||
|
||||
# Template-based content
|
||||
template_id: Optional[str] = None
|
||||
template_data: Optional[Dict[str, Any]] = None
|
||||
|
||||
# Configuration
|
||||
priority: NotificationPriority = NotificationPriority.NORMAL
|
||||
scheduled_at: Optional[datetime] = None
|
||||
|
||||
# ================================================================
|
||||
# RESPONSE SCHEMAS
|
||||
# ================================================================
|
||||
|
||||
class NotificationResponse(BaseModel):
|
||||
"""Schema for notification response"""
|
||||
id: str
|
||||
tenant_id: str
|
||||
sender_id: str
|
||||
recipient_id: Optional[str]
|
||||
|
||||
type: NotificationType
|
||||
status: NotificationStatus
|
||||
priority: NotificationPriority
|
||||
|
||||
subject: Optional[str]
|
||||
message: str
|
||||
recipient_email: Optional[str]
|
||||
recipient_phone: Optional[str]
|
||||
|
||||
scheduled_at: Optional[datetime]
|
||||
sent_at: Optional[datetime]
|
||||
delivered_at: Optional[datetime]
|
||||
|
||||
broadcast: bool
|
||||
read: bool
|
||||
read_at: Optional[datetime]
|
||||
|
||||
retry_count: int
|
||||
error_message: Optional[str]
|
||||
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
class NotificationHistory(BaseModel):
|
||||
"""Schema for notification history"""
|
||||
notifications: List[NotificationResponse]
|
||||
total: int
|
||||
page: int
|
||||
per_page: int
|
||||
has_next: bool
|
||||
has_prev: bool
|
||||
|
||||
class NotificationStats(BaseModel):
|
||||
"""Schema for notification statistics"""
|
||||
total_sent: int
|
||||
total_delivered: int
|
||||
total_failed: int
|
||||
delivery_rate: float
|
||||
avg_delivery_time_minutes: Optional[float]
|
||||
by_type: Dict[str, int]
|
||||
by_status: Dict[str, int]
|
||||
recent_activity: List[Dict[str, Any]]
|
||||
|
||||
# ================================================================
|
||||
# PREFERENCE SCHEMAS
|
||||
# ================================================================
|
||||
|
||||
class NotificationPreferences(BaseModel):
|
||||
"""Schema for user notification preferences"""
|
||||
user_id: str
|
||||
tenant_id: str
|
||||
|
||||
# Email preferences
|
||||
email_enabled: bool = True
|
||||
email_alerts: bool = True
|
||||
email_marketing: bool = False
|
||||
email_reports: bool = True
|
||||
|
||||
# WhatsApp preferences
|
||||
whatsapp_enabled: bool = False
|
||||
whatsapp_alerts: bool = False
|
||||
whatsapp_reports: bool = False
|
||||
|
||||
# Push notification preferences
|
||||
push_enabled: bool = True
|
||||
push_alerts: bool = True
|
||||
push_reports: bool = False
|
||||
|
||||
# Timing preferences
|
||||
quiet_hours_start: str = Field(default="22:00", pattern=r"^([01]?[0-9]|2[0-3]):[0-5][0-9]$")
|
||||
quiet_hours_end: str = Field(default="08:00", pattern=r"^([01]?[0-9]|2[0-3]):[0-5][0-9]$")
|
||||
timezone: str = "Europe/Madrid"
|
||||
|
||||
# Frequency preferences
|
||||
digest_frequency: str = Field(default="daily", pattern=r"^(none|daily|weekly)$")
|
||||
max_emails_per_day: int = Field(default=10, ge=1, le=100)
|
||||
|
||||
# Language preference
|
||||
language: str = Field(default="es", pattern=r"^(es|en)$")
|
||||
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
class PreferencesUpdate(BaseModel):
|
||||
"""Schema for updating notification preferences"""
|
||||
email_enabled: Optional[bool] = None
|
||||
email_alerts: Optional[bool] = None
|
||||
email_marketing: Optional[bool] = None
|
||||
email_reports: Optional[bool] = None
|
||||
|
||||
whatsapp_enabled: Optional[bool] = None
|
||||
whatsapp_alerts: Optional[bool] = None
|
||||
whatsapp_reports: Optional[bool] = None
|
||||
|
||||
push_enabled: Optional[bool] = None
|
||||
push_alerts: Optional[bool] = None
|
||||
push_reports: Optional[bool] = None
|
||||
|
||||
quiet_hours_start: Optional[str] = Field(None, pattern=r"^([01]?[0-9]|2[0-3]):[0-5][0-9]$")
|
||||
quiet_hours_end: Optional[str] = Field(None, pattern=r"^([01]?[0-9]|2[0-3]):[0-5][0-9]$")
|
||||
timezone: Optional[str] = None
|
||||
|
||||
digest_frequency: Optional[str] = Field(None, pattern=r"^(none|daily|weekly)$")
|
||||
max_emails_per_day: Optional[int] = Field(None, ge=1, le=100)
|
||||
language: Optional[str] = Field(None, pattern=r"^(es|en)$")
|
||||
|
||||
# ================================================================
|
||||
# TEMPLATE SCHEMAS
|
||||
# ================================================================
|
||||
|
||||
class TemplateCreate(BaseModel):
|
||||
"""Schema for creating notification templates"""
|
||||
template_key: str = Field(..., min_length=3, max_length=100)
|
||||
name: str = Field(..., min_length=3, max_length=255)
|
||||
description: Optional[str] = None
|
||||
category: str = Field(..., pattern=r"^(alert|marketing|transactional)$")
|
||||
|
||||
type: NotificationType
|
||||
subject_template: Optional[str] = None
|
||||
body_template: str = Field(..., min_length=10)
|
||||
html_template: Optional[str] = None
|
||||
|
||||
language: str = Field(default="es", pattern=r"^(es|en)$")
|
||||
default_priority: NotificationPriority = NotificationPriority.NORMAL
|
||||
required_variables: Optional[List[str]] = None
|
||||
|
||||
class TemplateResponse(BaseModel):
|
||||
"""Schema for template response"""
|
||||
id: str
|
||||
tenant_id: Optional[str]
|
||||
template_key: str
|
||||
name: str
|
||||
description: Optional[str]
|
||||
category: str
|
||||
|
||||
type: NotificationType
|
||||
subject_template: Optional[str]
|
||||
body_template: str
|
||||
html_template: Optional[str]
|
||||
|
||||
language: str
|
||||
is_active: bool
|
||||
is_system: bool
|
||||
default_priority: NotificationPriority
|
||||
required_variables: Optional[List[str]]
|
||||
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
# ================================================================
|
||||
# WEBHOOK SCHEMAS
|
||||
# ================================================================
|
||||
|
||||
class DeliveryWebhook(BaseModel):
|
||||
"""Schema for delivery status webhooks"""
|
||||
notification_id: str
|
||||
status: NotificationStatus
|
||||
provider: str
|
||||
provider_message_id: Optional[str] = None
|
||||
delivered_at: Optional[datetime] = None
|
||||
error_code: Optional[str] = None
|
||||
error_message: Optional[str] = None
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
|
||||
class ReadReceiptWebhook(BaseModel):
|
||||
"""Schema for read receipt webhooks"""
|
||||
notification_id: str
|
||||
read_at: datetime
|
||||
user_agent: Optional[str] = None
|
||||
ip_address: Optional[str] = None
|
||||
370
services/notification/app/schemas/whatsapp.py
Normal file
370
services/notification/app/schemas/whatsapp.py
Normal file
@@ -0,0 +1,370 @@
|
||||
"""
|
||||
WhatsApp Business Cloud API Schemas
|
||||
"""
|
||||
|
||||
from pydantic import BaseModel, Field, validator
|
||||
from typing import Optional, List, Dict, Any
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Enums
|
||||
# ============================================================
|
||||
|
||||
class WhatsAppMessageType(str, Enum):
|
||||
"""WhatsApp message types"""
|
||||
TEMPLATE = "template"
|
||||
TEXT = "text"
|
||||
IMAGE = "image"
|
||||
DOCUMENT = "document"
|
||||
INTERACTIVE = "interactive"
|
||||
|
||||
|
||||
class WhatsAppMessageStatus(str, Enum):
|
||||
"""WhatsApp message delivery status"""
|
||||
PENDING = "pending"
|
||||
SENT = "sent"
|
||||
DELIVERED = "delivered"
|
||||
READ = "read"
|
||||
FAILED = "failed"
|
||||
|
||||
|
||||
class TemplateCategory(str, Enum):
|
||||
"""WhatsApp template categories"""
|
||||
MARKETING = "MARKETING"
|
||||
UTILITY = "UTILITY"
|
||||
AUTHENTICATION = "AUTHENTICATION"
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Template Message Schemas
|
||||
# ============================================================
|
||||
|
||||
class TemplateParameter(BaseModel):
|
||||
"""Template parameter for dynamic content"""
|
||||
type: str = Field(default="text", description="Parameter type (text, currency, date_time)")
|
||||
text: Optional[str] = Field(None, description="Text value for the parameter")
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
"example": {
|
||||
"type": "text",
|
||||
"text": "PO-2024-001"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TemplateComponent(BaseModel):
|
||||
"""Template component (header, body, buttons)"""
|
||||
type: str = Field(..., description="Component type (header, body, button)")
|
||||
parameters: Optional[List[TemplateParameter]] = Field(None, description="Component parameters")
|
||||
sub_type: Optional[str] = Field(None, description="Button sub_type (quick_reply, url)")
|
||||
index: Optional[int] = Field(None, description="Button index")
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
"example": {
|
||||
"type": "body",
|
||||
"parameters": [
|
||||
{"type": "text", "text": "PO-2024-001"},
|
||||
{"type": "text", "text": "100.50"}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TemplateMessageRequest(BaseModel):
|
||||
"""Request to send a template message"""
|
||||
template_name: str = Field(..., description="WhatsApp template name")
|
||||
language: str = Field(default="es", description="Template language code")
|
||||
components: List[TemplateComponent] = Field(..., description="Template components with parameters")
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
"example": {
|
||||
"template_name": "po_notification",
|
||||
"language": "es",
|
||||
"components": [
|
||||
{
|
||||
"type": "body",
|
||||
"parameters": [
|
||||
{"type": "text", "text": "PO-2024-001"},
|
||||
{"type": "text", "text": "Supplier XYZ"},
|
||||
{"type": "text", "text": "€1,250.00"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Send Message Schemas
|
||||
# ============================================================
|
||||
|
||||
class SendWhatsAppMessageRequest(BaseModel):
|
||||
"""Request to send a WhatsApp message"""
|
||||
tenant_id: str = Field(..., description="Tenant ID")
|
||||
recipient_phone: str = Field(..., description="Recipient phone number (E.164 format)")
|
||||
recipient_name: Optional[str] = Field(None, description="Recipient name")
|
||||
message_type: WhatsAppMessageType = Field(..., description="Message type")
|
||||
template: Optional[TemplateMessageRequest] = Field(None, description="Template details (required for template messages)")
|
||||
text: Optional[str] = Field(None, description="Text message body (for text messages)")
|
||||
media_url: Optional[str] = Field(None, description="Media URL (for image/document messages)")
|
||||
metadata: Optional[Dict[str, Any]] = Field(None, description="Additional metadata (PO number, order ID, etc.)")
|
||||
notification_id: Optional[str] = Field(None, description="Link to existing notification")
|
||||
|
||||
@validator('recipient_phone')
|
||||
def validate_phone(cls, v):
|
||||
"""Validate E.164 phone format"""
|
||||
if not v.startswith('+'):
|
||||
raise ValueError('Phone number must be in E.164 format (starting with +)')
|
||||
if len(v) < 10 or len(v) > 16:
|
||||
raise ValueError('Phone number length must be between 10 and 16 characters')
|
||||
return v
|
||||
|
||||
@validator('template')
|
||||
def validate_template(cls, v, values):
|
||||
"""Validate template is provided for template messages"""
|
||||
if values.get('message_type') == WhatsAppMessageType.TEMPLATE and not v:
|
||||
raise ValueError('Template details required for template messages')
|
||||
return v
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
"example": {
|
||||
"tenant_id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"recipient_phone": "+34612345678",
|
||||
"recipient_name": "Supplier ABC",
|
||||
"message_type": "template",
|
||||
"template": {
|
||||
"template_name": "po_notification",
|
||||
"language": "es",
|
||||
"components": [
|
||||
{
|
||||
"type": "body",
|
||||
"parameters": [
|
||||
{"type": "text", "text": "PO-2024-001"},
|
||||
{"type": "text", "text": "€1,250.00"}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"po_number": "PO-2024-001",
|
||||
"po_id": "123e4567-e89b-12d3-a456-426614174111"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SendWhatsAppMessageResponse(BaseModel):
|
||||
"""Response after sending a WhatsApp message"""
|
||||
success: bool = Field(..., description="Whether message was sent successfully")
|
||||
message_id: str = Field(..., description="Internal message ID")
|
||||
whatsapp_message_id: Optional[str] = Field(None, description="WhatsApp's message ID")
|
||||
status: WhatsAppMessageStatus = Field(..., description="Message status")
|
||||
error_message: Optional[str] = Field(None, description="Error message if failed")
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
"example": {
|
||||
"success": True,
|
||||
"message_id": "123e4567-e89b-12d3-a456-426614174222",
|
||||
"whatsapp_message_id": "wamid.HBgNMzQ2MTIzNDU2Nzg5FQIAERgSMzY5RTFFNTdEQzZBRkVCODdBAA==",
|
||||
"status": "sent",
|
||||
"error_message": None
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Webhook Schemas
|
||||
# ============================================================
|
||||
|
||||
class WebhookValue(BaseModel):
|
||||
"""Webhook notification value"""
|
||||
messaging_product: str
|
||||
metadata: Dict[str, Any]
|
||||
contacts: Optional[List[Dict[str, Any]]] = None
|
||||
messages: Optional[List[Dict[str, Any]]] = None
|
||||
statuses: Optional[List[Dict[str, Any]]] = None
|
||||
|
||||
|
||||
class WebhookEntry(BaseModel):
|
||||
"""Webhook entry"""
|
||||
id: str
|
||||
changes: List[Dict[str, Any]]
|
||||
|
||||
|
||||
class WhatsAppWebhook(BaseModel):
|
||||
"""WhatsApp webhook payload"""
|
||||
object: str
|
||||
entry: List[WebhookEntry]
|
||||
|
||||
|
||||
class WebhookVerification(BaseModel):
|
||||
"""Webhook verification request"""
|
||||
mode: str = Field(..., alias="hub.mode")
|
||||
token: str = Field(..., alias="hub.verify_token")
|
||||
challenge: str = Field(..., alias="hub.challenge")
|
||||
|
||||
class Config:
|
||||
populate_by_name = True
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Message Status Schemas
|
||||
# ============================================================
|
||||
|
||||
class MessageStatusUpdate(BaseModel):
|
||||
"""Message status update"""
|
||||
whatsapp_message_id: str = Field(..., description="WhatsApp message ID")
|
||||
status: WhatsAppMessageStatus = Field(..., description="New status")
|
||||
timestamp: datetime = Field(..., description="Status update timestamp")
|
||||
error_code: Optional[str] = Field(None, description="Error code if failed")
|
||||
error_message: Optional[str] = Field(None, description="Error message if failed")
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Template Management Schemas
|
||||
# ============================================================
|
||||
|
||||
class WhatsAppTemplateCreate(BaseModel):
|
||||
"""Create a WhatsApp template"""
|
||||
tenant_id: Optional[str] = Field(None, description="Tenant ID (null for system templates)")
|
||||
template_name: str = Field(..., description="Template name in WhatsApp")
|
||||
template_key: str = Field(..., description="Internal template key")
|
||||
display_name: str = Field(..., description="Display name")
|
||||
description: Optional[str] = Field(None, description="Template description")
|
||||
category: TemplateCategory = Field(..., description="Template category")
|
||||
language: str = Field(default="es", description="Template language")
|
||||
header_type: Optional[str] = Field(None, description="Header type (TEXT, IMAGE, DOCUMENT, VIDEO)")
|
||||
header_text: Optional[str] = Field(None, max_length=60, description="Header text (max 60 chars)")
|
||||
body_text: str = Field(..., description="Body text with {{1}}, {{2}} placeholders")
|
||||
footer_text: Optional[str] = Field(None, max_length=60, description="Footer text (max 60 chars)")
|
||||
parameters: Optional[List[Dict[str, Any]]] = Field(None, description="Parameter definitions")
|
||||
buttons: Optional[List[Dict[str, Any]]] = Field(None, description="Button definitions")
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
"example": {
|
||||
"template_name": "po_notification",
|
||||
"template_key": "po_notification_v1",
|
||||
"display_name": "Purchase Order Notification",
|
||||
"description": "Notify supplier of new purchase order",
|
||||
"category": "UTILITY",
|
||||
"language": "es",
|
||||
"body_text": "Hola {{1}}, has recibido una nueva orden de compra {{2}} por un total de {{3}}.",
|
||||
"parameters": [
|
||||
{"name": "supplier_name", "example": "Proveedor ABC"},
|
||||
{"name": "po_number", "example": "PO-2024-001"},
|
||||
{"name": "total_amount", "example": "€1,250.00"}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class WhatsAppTemplateResponse(BaseModel):
|
||||
"""WhatsApp template response"""
|
||||
id: str
|
||||
tenant_id: Optional[str]
|
||||
template_name: str
|
||||
template_key: str
|
||||
display_name: str
|
||||
description: Optional[str]
|
||||
category: str
|
||||
language: str
|
||||
status: str
|
||||
body_text: str
|
||||
parameter_count: int
|
||||
is_active: bool
|
||||
sent_count: int
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
json_schema_extra = {
|
||||
"example": {
|
||||
"id": "123e4567-e89b-12d3-a456-426614174333",
|
||||
"tenant_id": None,
|
||||
"template_name": "po_notification",
|
||||
"template_key": "po_notification_v1",
|
||||
"display_name": "Purchase Order Notification",
|
||||
"description": "Notify supplier of new purchase order",
|
||||
"category": "UTILITY",
|
||||
"language": "es",
|
||||
"status": "APPROVED",
|
||||
"body_text": "Hola {{1}}, has recibido una nueva orden de compra {{2}} por un total de {{3}}.",
|
||||
"parameter_count": 3,
|
||||
"is_active": True,
|
||||
"sent_count": 125,
|
||||
"created_at": "2024-01-15T10:30:00",
|
||||
"updated_at": "2024-01-15T10:30:00"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Message Query Schemas
|
||||
# ============================================================
|
||||
|
||||
class WhatsAppMessageResponse(BaseModel):
|
||||
"""WhatsApp message response"""
|
||||
id: str
|
||||
tenant_id: str
|
||||
notification_id: Optional[str]
|
||||
whatsapp_message_id: Optional[str]
|
||||
recipient_phone: str
|
||||
recipient_name: Optional[str]
|
||||
message_type: str
|
||||
status: str
|
||||
template_name: Optional[str]
|
||||
template_language: Optional[str]
|
||||
message_body: Optional[str]
|
||||
sent_at: Optional[datetime]
|
||||
delivered_at: Optional[datetime]
|
||||
read_at: Optional[datetime]
|
||||
failed_at: Optional[datetime]
|
||||
error_message: Optional[str]
|
||||
metadata: Optional[Dict[str, Any]]
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class WhatsAppDeliveryStats(BaseModel):
|
||||
"""WhatsApp delivery statistics"""
|
||||
total_messages: int
|
||||
sent: int
|
||||
delivered: int
|
||||
read: int
|
||||
failed: int
|
||||
pending: int
|
||||
unique_recipients: int
|
||||
total_conversations: int
|
||||
delivery_rate: float
|
||||
period: Dict[str, str]
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
"example": {
|
||||
"total_messages": 1500,
|
||||
"sent": 1480,
|
||||
"delivered": 1450,
|
||||
"read": 1200,
|
||||
"failed": 20,
|
||||
"pending": 0,
|
||||
"unique_recipients": 350,
|
||||
"total_conversations": 400,
|
||||
"delivery_rate": 96.67,
|
||||
"period": {
|
||||
"start": "2024-01-01T00:00:00",
|
||||
"end": "2024-01-31T23:59:59"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user