Files
resolutionflow/backend/app/models/attachment.py
Michael Chihlas 7d96807fb1 Add production logging, datetime fixes, and session tests
DateTime Timezone Handling (Critical Bug Fix):
- Updated all models to use DateTime(timezone=True) for PostgreSQL
- Changed datetime defaults to lambda: datetime.now(timezone.utc)
- Fixed mixing of timezone-aware and timezone-naive datetime objects
- Resolved Internal Server Errors in session completion endpoint
- Affected models: User, Team, Tree, Session, Attachment

Production Logging System:
- Created logging_config.py with structured logging setup
- Added log rotation (10MB files, 10 backups) for production
- Implemented RequestLoggingMiddleware with correlation IDs
- Added ErrorLoggingMiddleware for comprehensive error tracking
- Integrated logging into main.py application startup
- Supports dev/prod modes with appropriate log levels

Integration Tests - Session Workflow:
- Created test_sessions.py with 12 comprehensive tests
- Session lifecycle: create, update, complete
- Session export in multiple formats (markdown, text, HTML)
- Error handling and authorization checks
- Added pytest.ini with coverage configuration
- Added requirements-dev.txt with pytest dependencies

Following 2026 FastAPI best practices for timezone handling and structured logging.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 20:39:09 -05:00

35 lines
1.2 KiB
Python

import uuid
from datetime import datetime, timezone
from typing import Optional
from sqlalchemy import String, Integer, DateTime, ForeignKey
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.dialects.postgresql import UUID
from app.core.database import Base
class Attachment(Base):
__tablename__ = "attachments"
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
primary_key=True,
default=uuid.uuid4
)
session_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
ForeignKey("sessions.id"),
nullable=False
)
node_id: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
file_name: Mapped[str] = mapped_column(String(255), nullable=False)
file_type: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
file_size: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
storage_path: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
uploaded_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc)
)
# Relationships
session: Mapped["Session"] = relationship("Session", back_populates="attachments")