## 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>
103 lines
2.9 KiB
Python
103 lines
2.9 KiB
Python
"""SQLAlchemy models for report generation
|
|
|
|
Tables:
|
|
- tr_generated_reports: Stores report metadata and generation status
|
|
|
|
Note: All tables use 'tr_' prefix to avoid conflicts in shared database.
|
|
"""
|
|
from sqlalchemy import Column, String, Text, DateTime, Integer, ForeignKey, Index, JSON
|
|
from sqlalchemy.orm import relationship
|
|
from datetime import datetime
|
|
import uuid
|
|
import enum
|
|
from app.core.database import Base
|
|
|
|
|
|
class ReportStatus(str, enum.Enum):
|
|
"""Report generation status"""
|
|
PENDING = "pending"
|
|
COLLECTING_DATA = "collecting_data"
|
|
GENERATING_CONTENT = "generating_content"
|
|
ASSEMBLING_DOCUMENT = "assembling_document"
|
|
COMPLETED = "completed"
|
|
FAILED = "failed"
|
|
|
|
|
|
class GeneratedReport(Base):
|
|
"""Generated report model for incident reports"""
|
|
|
|
__tablename__ = "tr_generated_reports"
|
|
|
|
report_id = Column(
|
|
String(36), primary_key=True, default=lambda: str(uuid.uuid4()),
|
|
comment="Unique report identifier (UUID)"
|
|
)
|
|
room_id = Column(
|
|
String(36), ForeignKey("tr_incident_rooms.room_id", ondelete="CASCADE"),
|
|
nullable=False, comment="Reference to incident room"
|
|
)
|
|
|
|
# Generation metadata
|
|
generated_by = Column(
|
|
String(255), nullable=False,
|
|
comment="User email who triggered report generation"
|
|
)
|
|
generated_at = Column(
|
|
DateTime, default=datetime.utcnow, nullable=False,
|
|
comment="Report generation timestamp"
|
|
)
|
|
|
|
# Status tracking
|
|
status = Column(
|
|
String(30), default=ReportStatus.PENDING.value, nullable=False,
|
|
comment="Current generation status"
|
|
)
|
|
error_message = Column(
|
|
Text, nullable=True,
|
|
comment="User-friendly error message if generation failed"
|
|
)
|
|
|
|
# DIFY AI metadata
|
|
dify_message_id = Column(
|
|
String(100), nullable=True,
|
|
comment="DIFY API message ID for tracking"
|
|
)
|
|
dify_conversation_id = Column(
|
|
String(100), nullable=True,
|
|
comment="DIFY conversation ID"
|
|
)
|
|
prompt_tokens = Column(
|
|
Integer, nullable=True,
|
|
comment="Number of prompt tokens used"
|
|
)
|
|
completion_tokens = Column(
|
|
Integer, nullable=True,
|
|
comment="Number of completion tokens used"
|
|
)
|
|
|
|
# Report content
|
|
report_title = Column(
|
|
String(255), nullable=True,
|
|
comment="Generated report title"
|
|
)
|
|
report_json = Column(
|
|
JSON, nullable=True,
|
|
comment="Parsed AI output as JSON"
|
|
)
|
|
docx_storage_path = Column(
|
|
String(500), nullable=True,
|
|
comment="Path to generated .docx file in MinIO or local storage"
|
|
)
|
|
|
|
# Relationship
|
|
room = relationship("IncidentRoom", backref="reports")
|
|
|
|
# Indexes
|
|
__table_args__ = (
|
|
Index("ix_tr_generated_reports_room_date", "room_id", "generated_at"),
|
|
Index("ix_tr_generated_reports_status", "status"),
|
|
)
|
|
|
|
def __repr__(self):
|
|
return f"<GeneratedReport {self.report_id} status={self.status}>"
|