"""SQLAlchemy models for chat room management Tables: - incident_rooms: Stores room metadata and configuration - room_members: User-room associations with roles - room_templates: Predefined templates for common incident types """ from sqlalchemy import Column, Integer, String, Text, DateTime, Enum, ForeignKey, UniqueConstraint, Index from sqlalchemy.orm import relationship from datetime import datetime import enum import uuid from app.core.database import Base class IncidentType(str, enum.Enum): """Types of production incidents""" EQUIPMENT_FAILURE = "equipment_failure" MATERIAL_SHORTAGE = "material_shortage" QUALITY_ISSUE = "quality_issue" OTHER = "other" class SeverityLevel(str, enum.Enum): """Incident severity levels""" LOW = "low" MEDIUM = "medium" HIGH = "high" CRITICAL = "critical" class RoomStatus(str, enum.Enum): """Room lifecycle status""" ACTIVE = "active" RESOLVED = "resolved" ARCHIVED = "archived" class MemberRole(str, enum.Enum): """Room member roles""" OWNER = "owner" EDITOR = "editor" VIEWER = "viewer" class IncidentRoom(Base): """Incident room model for production incidents""" __tablename__ = "incident_rooms" room_id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) title = Column(String(255), nullable=False) incident_type = Column(Enum(IncidentType), nullable=False) severity = Column(Enum(SeverityLevel), nullable=False) status = Column(Enum(RoomStatus), default=RoomStatus.ACTIVE, nullable=False) location = Column(String(255)) description = Column(Text) resolution_notes = Column(Text) # User tracking created_by = Column(String(255), nullable=False) # User email/ID who created the room # Timestamps created_at = Column(DateTime, default=datetime.utcnow, nullable=False) resolved_at = Column(DateTime) archived_at = Column(DateTime) last_activity_at = Column(DateTime, default=datetime.utcnow, nullable=False) last_updated_at = Column(DateTime, default=datetime.utcnow, nullable=False) # Ownership transfer tracking ownership_transferred_at = Column(DateTime) ownership_transferred_by = Column(String(255)) # Denormalized count for performance member_count = Column(Integer, default=0, nullable=False) # Relationships members = relationship("RoomMember", back_populates="room", cascade="all, delete-orphan") files = relationship("RoomFile", back_populates="room", cascade="all, delete-orphan") # Indexes for common queries __table_args__ = ( Index("ix_incident_rooms_status_created", "status", "created_at"), Index("ix_incident_rooms_created_by", "created_by"), ) class RoomMember(Base): """Room membership model""" __tablename__ = "room_members" id = Column(Integer, primary_key=True, autoincrement=True) room_id = Column(String(36), ForeignKey("incident_rooms.room_id", ondelete="CASCADE"), nullable=False) user_id = Column(String(255), nullable=False) # User email/ID role = Column(Enum(MemberRole), nullable=False) # Tracking added_by = Column(String(255), nullable=False) # Who added this member added_at = Column(DateTime, default=datetime.utcnow, nullable=False) removed_at = Column(DateTime) # Soft delete timestamp # Relationships room = relationship("IncidentRoom", back_populates="members") # Constraints and indexes __table_args__ = ( # Ensure unique active membership (where removed_at IS NULL) UniqueConstraint("room_id", "user_id", "removed_at", name="uq_room_member_active"), Index("ix_room_members_room_user", "room_id", "user_id"), Index("ix_room_members_user", "user_id"), ) class RoomTemplate(Base): """Predefined templates for common incident types""" __tablename__ = "room_templates" template_id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(100), unique=True, nullable=False) description = Column(Text) incident_type = Column(Enum(IncidentType), nullable=False) default_severity = Column(Enum(SeverityLevel), nullable=False) default_members = Column(Text) # JSON array of user roles metadata_fields = Column(Text) # JSON schema for additional fields