Files
bakery-ia/services/notification/app/models/notifications.py
2025-07-21 22:44:11 +02:00

184 lines
6.6 KiB
Python

# ================================================================
# services/notification/app/models/notifications.py
# ================================================================
"""
Notification models for the notification service
"""
from sqlalchemy import Column, String, Text, Boolean, DateTime, JSON, Integer, Enum
from sqlalchemy.dialects.postgresql import UUID
from datetime import datetime
import uuid
import enum
from shared.database.base import Base
class NotificationType(enum.Enum):
"""Notification types supported by the service"""
EMAIL = "email"
WHATSAPP = "whatsapp"
PUSH = "push"
SMS = "sms"
class NotificationStatus(enum.Enum):
"""Notification delivery status"""
PENDING = "pending"
SENT = "sent"
DELIVERED = "delivered"
FAILED = "failed"
CANCELLED = "cancelled"
class NotificationPriority(enum.Enum):
"""Notification priority levels"""
LOW = "low"
NORMAL = "normal"
HIGH = "high"
URGENT = "urgent"
class Notification(Base):
"""Main notification record"""
__tablename__ = "notifications"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True)
sender_id = Column(UUID(as_uuid=True), nullable=False)
recipient_id = Column(UUID(as_uuid=True), nullable=True) # Null for broadcast
# Notification details
type = Column(Enum(NotificationType), nullable=False)
status = Column(Enum(NotificationStatus), default=NotificationStatus.PENDING, index=True)
priority = Column(Enum(NotificationPriority), default=NotificationPriority.NORMAL)
# Content
subject = Column(String(255), nullable=True)
message = Column(Text, nullable=False)
html_content = Column(Text, nullable=True)
template_id = Column(String(100), nullable=True)
template_data = Column(JSON, nullable=True)
# Delivery details
recipient_email = Column(String(255), nullable=True)
recipient_phone = Column(String(20), nullable=True)
delivery_channel = Column(String(50), nullable=True)
# Scheduling
scheduled_at = Column(DateTime, nullable=True)
sent_at = Column(DateTime, nullable=True)
delivered_at = Column(DateTime, nullable=True)
# Metadata
log_metadata = Column(JSON, nullable=True)
error_message = Column(Text, nullable=True)
retry_count = Column(Integer, default=0)
max_retries = Column(Integer, default=3)
# Tracking
broadcast = Column(Boolean, default=False)
read = Column(Boolean, default=False)
read_at = Column(DateTime, nullable=True)
# Timestamps
created_at = Column(DateTime, default=datetime.utcnow, index=True)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
class NotificationTemplate(Base):
"""Email and notification templates"""
__tablename__ = "notification_templates"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
tenant_id = Column(UUID(as_uuid=True), nullable=True, index=True) # Null for system templates
# Template identification
template_key = Column(String(100), nullable=False, unique=True)
name = Column(String(255), nullable=False)
description = Column(Text, nullable=True)
category = Column(String(50), nullable=False) # alert, marketing, transactional
# Template content
type = Column(Enum(NotificationType), nullable=False)
subject_template = Column(String(255), nullable=True)
body_template = Column(Text, nullable=False)
html_template = Column(Text, nullable=True)
# Configuration
language = Column(String(2), default="es")
is_active = Column(Boolean, default=True)
is_system = Column(Boolean, default=False) # System templates can't be deleted
# Metadata
default_priority = Column(Enum(NotificationPriority), default=NotificationPriority.NORMAL)
required_variables = Column(JSON, nullable=True) # List of required template variables
# Timestamps
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
class NotificationPreference(Base):
"""User notification preferences"""
__tablename__ = "notification_preferences"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
user_id = Column(UUID(as_uuid=True), nullable=False, unique=True, index=True)
tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True)
# Email preferences
email_enabled = Column(Boolean, default=True)
email_alerts = Column(Boolean, default=True)
email_marketing = Column(Boolean, default=False)
email_reports = Column(Boolean, default=True)
# WhatsApp preferences
whatsapp_enabled = Column(Boolean, default=False)
whatsapp_alerts = Column(Boolean, default=False)
whatsapp_reports = Column(Boolean, default=False)
# Push notification preferences
push_enabled = Column(Boolean, default=True)
push_alerts = Column(Boolean, default=True)
push_reports = Column(Boolean, default=False)
# Timing preferences
quiet_hours_start = Column(String(5), default="22:00") # HH:MM format
quiet_hours_end = Column(String(5), default="08:00")
timezone = Column(String(50), default="Europe/Madrid")
# Frequency preferences
digest_frequency = Column(String(20), default="daily") # none, daily, weekly
max_emails_per_day = Column(Integer, default=10)
# Language preference
language = Column(String(2), default="es")
# Timestamps
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
class NotificationLog(Base):
"""Detailed logging for notification delivery attempts"""
__tablename__ = "notification_logs"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
notification_id = Column(UUID(as_uuid=True), nullable=False, index=True)
# Attempt details
attempt_number = Column(Integer, nullable=False)
status = Column(Enum(NotificationStatus), nullable=False)
# Provider details
provider = Column(String(50), nullable=True) # e.g., "gmail", "twilio"
provider_message_id = Column(String(255), nullable=True)
provider_response = Column(JSON, nullable=True)
# Timing
attempted_at = Column(DateTime, default=datetime.utcnow)
response_time_ms = Column(Integer, nullable=True)
# Error details
error_code = Column(String(50), nullable=True)
error_message = Column(Text, nullable=True)
# Additional metadata
log_metadata = Column(JSON, nullable=True)