Files
Task_Reporter/app/modules/realtime/models.py
egg 92834dbe0e feat: Migrate to MySQL and add unified environment configuration
## Database Migration (SQLite → MySQL)
- Add Alembic migration framework
- Add 'tr_' prefix to all tables to avoid conflicts in shared database
- Remove SQLite support, use MySQL exclusively
- Add pymysql driver dependency
- Change ad_token column to Text type for long JWT tokens

## Unified Environment Configuration
- Centralize all hardcoded settings to environment variables
- Backend: Extend Settings class in app/core/config.py
- Frontend: Use Vite environment variables (import.meta.env)
- Docker: Move credentials to environment variables
- Update .env.example files with comprehensive documentation

## Test Organization
- Move root-level test files to tests/ directory:
  - test_chat_room.py → tests/test_chat_room.py
  - test_websocket.py → tests/test_websocket.py
  - test_realtime_implementation.py → tests/test_realtime_implementation.py
- Fix path references in test_realtime_implementation.py

Breaking Changes:
- CORS now requires explicit origins (no more wildcard)
- All database tables renamed with 'tr_' prefix
- SQLite no longer supported

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 14:15:11 +08:00

105 lines
3.8 KiB
Python

"""SQLAlchemy models for realtime messaging
Tables:
- tr_messages: Stores all messages sent in incident rooms
- tr_message_reactions: User reactions to messages (emoji)
- tr_message_edit_history: Audit trail for message edits
Note: All tables use 'tr_' prefix to avoid conflicts in shared database.
"""
from sqlalchemy import Column, Integer, String, Text, DateTime, Enum, ForeignKey, UniqueConstraint, Index, BigInteger, JSON
from sqlalchemy.orm import relationship
from datetime import datetime
import enum
import uuid
from app.core.database import Base
class MessageType(str, enum.Enum):
"""Types of messages in incident rooms"""
TEXT = "text"
IMAGE_REF = "image_ref"
FILE_REF = "file_ref"
SYSTEM = "system"
INCIDENT_DATA = "incident_data"
class Message(Base):
"""Message model for incident room communications"""
__tablename__ = "tr_messages"
message_id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
room_id = Column(String(36), ForeignKey("tr_incident_rooms.room_id", ondelete="CASCADE"), nullable=False)
sender_id = Column(String(255), nullable=False) # User email/ID
content = Column(Text, nullable=False)
message_type = Column(Enum(MessageType), default=MessageType.TEXT, nullable=False)
# Message metadata for structured data, mentions, file references, etc.
message_metadata = Column(JSON)
# Timestamps
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
edited_at = Column(DateTime) # Last edit timestamp
deleted_at = Column(DateTime) # Soft delete timestamp
# Sequence number for FIFO ordering within a room
sequence_number = Column(BigInteger, nullable=False)
# Relationships
reactions = relationship("MessageReaction", back_populates="message", cascade="all, delete-orphan")
edit_history = relationship("MessageEditHistory", back_populates="message", cascade="all, delete-orphan")
# Indexes for common queries
__table_args__ = (
Index("ix_tr_messages_room_created", "room_id", "created_at"),
Index("ix_tr_messages_room_sequence", "room_id", "sequence_number"),
Index("ix_tr_messages_sender", "sender_id"),
)
class MessageReaction(Base):
"""Message reaction model for emoji reactions"""
__tablename__ = "tr_message_reactions"
reaction_id = Column(Integer, primary_key=True, autoincrement=True)
message_id = Column(String(36), ForeignKey("tr_messages.message_id", ondelete="CASCADE"), nullable=False)
user_id = Column(String(255), nullable=False) # User email/ID who reacted
emoji = Column(String(10), nullable=False) # Emoji character or code
# Timestamp
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
# Relationships
message = relationship("Message", back_populates="reactions")
# Constraints and indexes
__table_args__ = (
# Ensure unique reaction per user per message
UniqueConstraint("message_id", "user_id", "emoji", name="uq_tr_message_reaction"),
Index("ix_tr_message_reactions_message", "message_id"),
)
class MessageEditHistory(Base):
"""Message edit history model for audit trail"""
__tablename__ = "tr_message_edit_history"
edit_id = Column(Integer, primary_key=True, autoincrement=True)
message_id = Column(String(36), ForeignKey("tr_messages.message_id", ondelete="CASCADE"), nullable=False)
original_content = Column(Text, nullable=False) # Content before edit
edited_by = Column(String(255), nullable=False) # User who made the edit
# Timestamp
edited_at = Column(DateTime, default=datetime.utcnow, nullable=False)
# Relationships
message = relationship("Message", back_populates="edit_history")
# Indexes
__table_args__ = (
Index("ix_tr_message_edit_history_message", "message_id", "edited_at"),
)