Files
Task_Reporter/app/modules/chat_room/models.py
egg 599802b818 feat: Add Chat UX improvements with notifications and @mention support
- Add ActionBar component with expandable toolbar for mobile
- Add @mention functionality with autocomplete dropdown
- Add browser notification system (push, sound, vibration)
- Add NotificationSettings modal for user preferences
- Add mention badges on room list cards
- Add ReportPreview with Markdown rendering and copy/download
- Add message copy functionality with hover actions
- Add backend mentions field to messages with Alembic migration
- Add lots field to rooms, remove templates
- Optimize WebSocket database session handling
- Various UX polish (animations, accessibility)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 08:20:37 +08:00

114 lines
3.8 KiB
Python

"""SQLAlchemy models for chat room management
Tables:
- tr_incident_rooms: Stores room metadata and configuration
- tr_room_members: User-room associations with roles
Note: All tables use 'tr_' prefix to avoid conflicts in shared database.
"""
from sqlalchemy import Column, Integer, String, Text, DateTime, Enum, ForeignKey, UniqueConstraint, Index, JSON
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__ = "tr_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)
lots = Column(JSON, default=list, nullable=False, comment="LOT batch numbers (JSON array)")
# 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_tr_incident_rooms_status_created", "status", "created_at"),
Index("ix_tr_incident_rooms_created_by", "created_by"),
)
class RoomMember(Base):
"""Room membership model"""
__tablename__ = "tr_room_members"
id = Column(Integer, primary_key=True, autoincrement=True)
room_id = Column(String(36), ForeignKey("tr_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_tr_room_member_active"),
Index("ix_tr_room_members_room_user", "room_id", "user_id"),
Index("ix_tr_room_members_user", "user_id"),
)