from sqlalchemy import Column, Integer, String, DateTime, Boolean, Text, Enum, ForeignKey, JSON from sqlalchemy.orm import relationship from datetime import datetime import enum from ..config.database import Base class NotificationChannel(str, enum.Enum): email = 'email' sms = 'sms' push = 'push' whatsapp = 'whatsapp' in_app = 'in_app' class NotificationStatus(str, enum.Enum): pending = 'pending' sent = 'sent' delivered = 'delivered' failed = 'failed' read = 'read' class NotificationType(str, enum.Enum): booking_confirmation = 'booking_confirmation' payment_receipt = 'payment_receipt' pre_arrival_reminder = 'pre_arrival_reminder' check_in_reminder = 'check_in_reminder' check_out_reminder = 'check_out_reminder' marketing_campaign = 'marketing_campaign' loyalty_update = 'loyalty_update' system_alert = 'system_alert' custom = 'custom' class Notification(Base): __tablename__ = 'notifications' id = Column(Integer, primary_key=True, index=True, autoincrement=True) user_id = Column(Integer, ForeignKey('users.id'), nullable=True) # Nullable for system-wide notifications notification_type = Column(Enum(NotificationType), nullable=False) channel = Column(Enum(NotificationChannel), nullable=False) subject = Column(String(255), nullable=True) # For email/push content = Column(Text, nullable=False) template_id = Column(Integer, ForeignKey('notification_templates.id'), nullable=True) status = Column(Enum(NotificationStatus), nullable=False, default=NotificationStatus.pending) priority = Column(String(20), nullable=False, default='normal') # low, normal, high, urgent scheduled_at = Column(DateTime, nullable=True) # For scheduled notifications sent_at = Column(DateTime, nullable=True) delivered_at = Column(DateTime, nullable=True) read_at = Column(DateTime, nullable=True) error_message = Column(Text, nullable=True) external_id = Column(String(255), nullable=True) # ID from external service (e.g., Twilio, SendGrid) meta_data = Column(JSON, nullable=True) # Additional data (recipient info, attachments, etc.) booking_id = Column(Integer, ForeignKey('bookings.id'), nullable=True) payment_id = Column(Integer, ForeignKey('payments.id'), nullable=True) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) user = relationship('User') template = relationship('NotificationTemplate') booking = relationship('Booking') payment = relationship('Payment') delivery_logs = relationship('NotificationDeliveryLog', back_populates='notification', cascade='all, delete-orphan') class NotificationTemplate(Base): __tablename__ = 'notification_templates' id = Column(Integer, primary_key=True, index=True, autoincrement=True) name = Column(String(255), nullable=False) notification_type = Column(Enum(NotificationType), nullable=False) channel = Column(Enum(NotificationChannel), nullable=False) subject = Column(String(255), nullable=True) content = Column(Text, nullable=False) variables = Column(JSON, nullable=True) # Available template variables is_active = Column(Boolean, nullable=False, default=True) created_by = Column(Integer, ForeignKey('users.id'), nullable=False) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) creator = relationship('User', foreign_keys=[created_by]) notifications = relationship('Notification', back_populates='template') class NotificationPreference(Base): __tablename__ = 'notification_preferences' id = Column(Integer, primary_key=True, index=True, autoincrement=True) user_id = Column(Integer, ForeignKey('users.id'), nullable=False, unique=True) email_enabled = Column(Boolean, nullable=False, default=True) sms_enabled = Column(Boolean, nullable=False, default=True) push_enabled = Column(Boolean, nullable=False, default=True) whatsapp_enabled = Column(Boolean, nullable=False, default=False) in_app_enabled = Column(Boolean, nullable=False, default=True) # Per-type preferences booking_confirmation_email = Column(Boolean, nullable=False, default=True) booking_confirmation_sms = Column(Boolean, nullable=False, default=False) payment_receipt_email = Column(Boolean, nullable=False, default=True) payment_receipt_sms = Column(Boolean, nullable=False, default=False) pre_arrival_reminder_email = Column(Boolean, nullable=False, default=True) pre_arrival_reminder_sms = Column(Boolean, nullable=False, default=True) check_in_reminder_email = Column(Boolean, nullable=False, default=True) check_in_reminder_sms = Column(Boolean, nullable=False, default=True) check_out_reminder_email = Column(Boolean, nullable=False, default=True) check_out_reminder_sms = Column(Boolean, nullable=False, default=True) marketing_campaign_email = Column(Boolean, nullable=False, default=True) marketing_campaign_sms = Column(Boolean, nullable=False, default=False) loyalty_update_email = Column(Boolean, nullable=False, default=True) loyalty_update_sms = Column(Boolean, nullable=False, default=False) system_alert_email = Column(Boolean, nullable=False, default=True) system_alert_push = Column(Boolean, nullable=False, default=True) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) user = relationship('User') class NotificationDeliveryLog(Base): __tablename__ = 'notification_delivery_logs' id = Column(Integer, primary_key=True, index=True, autoincrement=True) notification_id = Column(Integer, ForeignKey('notifications.id'), nullable=False) channel = Column(Enum(NotificationChannel), nullable=False) status = Column(Enum(NotificationStatus), nullable=False) external_id = Column(String(255), nullable=True) error_message = Column(Text, nullable=True) response_data = Column(JSON, nullable=True) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) notification = relationship('Notification', back_populates='delivery_logs')