import uuid from datetime import datetime from sqlalchemy import Column, String, Boolean, DateTime, Text, Integer, ForeignKey, Enum as SQLEnum from sqlalchemy.dialects.postgresql import UUID, JSONB, ARRAY from sqlalchemy.orm import relationship import enum from app.core.database import Base class AccountStatus(str, enum.Enum): CONNECTING = "connecting" CONNECTED = "connected" DISCONNECTED = "disconnected" class ConversationStatus(str, enum.Enum): BOT = "bot" WAITING = "waiting" ACTIVE = "active" RESOLVED = "resolved" class MessageDirection(str, enum.Enum): INBOUND = "inbound" OUTBOUND = "outbound" class MessageType(str, enum.Enum): TEXT = "text" IMAGE = "image" AUDIO = "audio" VIDEO = "video" DOCUMENT = "document" LOCATION = "location" CONTACT = "contact" STICKER = "sticker" BUTTONS = "buttons" LIST = "list" class MessageStatus(str, enum.Enum): PENDING = "pending" SENT = "sent" DELIVERED = "delivered" READ = "read" FAILED = "failed" class WhatsAppAccount(Base): __tablename__ = "whatsapp_accounts" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) phone_number = Column(String(20), nullable=True) name = Column(String(100), nullable=False) status = Column(SQLEnum(AccountStatus), default=AccountStatus.DISCONNECTED, nullable=False) session_data = Column(JSONB, nullable=True) qr_code = Column(Text, nullable=True) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) conversations = relationship("Conversation", back_populates="whatsapp_account") class Contact(Base): __tablename__ = "contacts" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) phone_number = Column(String(20), unique=True, nullable=False, index=True) name = Column(String(100), nullable=True) email = Column(String(255), nullable=True) company = Column(String(100), nullable=True) extra_data = Column(JSONB, default=dict) tags = Column(ARRAY(String), default=list) odoo_partner_id = Column(Integer, nullable=True) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) conversations = relationship("Conversation", back_populates="contact") class Conversation(Base): __tablename__ = "conversations" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) whatsapp_account_id = Column(UUID(as_uuid=True), ForeignKey("whatsapp_accounts.id"), nullable=False) contact_id = Column(UUID(as_uuid=True), ForeignKey("contacts.id"), nullable=False) assigned_to = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True) status = Column(SQLEnum(ConversationStatus), default=ConversationStatus.BOT, nullable=False) last_message_at = Column(DateTime, nullable=True) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) queue_id = Column(UUID(as_uuid=True), ForeignKey("queues.id"), nullable=True) priority = Column(String(20), default="normal", nullable=False) sla_first_response_at = Column(DateTime, nullable=True) sla_first_response_met = Column(Boolean, nullable=True) resolved_at = Column(DateTime, nullable=True) csat_score = Column(Integer, nullable=True) csat_feedback = Column(String(500), nullable=True) whatsapp_account = relationship("WhatsAppAccount", back_populates="conversations") contact = relationship("Contact", back_populates="conversations") messages = relationship("Message", back_populates="conversation", order_by="Message.created_at") queue = relationship("Queue", back_populates="conversations") class Message(Base): __tablename__ = "messages" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) conversation_id = Column(UUID(as_uuid=True), ForeignKey("conversations.id"), nullable=False) whatsapp_message_id = Column(String(100), nullable=True) direction = Column(SQLEnum(MessageDirection), nullable=False) type = Column(SQLEnum(MessageType), default=MessageType.TEXT, nullable=False) content = Column(Text, nullable=True) media_url = Column(String(500), nullable=True) extra_data = Column(JSONB, default=dict) sent_by = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True) is_internal_note = Column(Boolean, default=False, nullable=False) status = Column(SQLEnum(MessageStatus), default=MessageStatus.PENDING, nullable=False) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) conversation = relationship("Conversation", back_populates="messages")