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) metadata = 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) whatsapp_account = relationship("WhatsAppAccount", back_populates="conversations") contact = relationship("Contact", back_populates="conversations") messages = relationship("Message", back_populates="conversation", order_by="Message.created_at") 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) metadata = 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")