"""Base SQLAlchemy declarative base for all database models. This module provides the base class that all ORM models inherit from, along with common functionality and mixins. """ from datetime import datetime, timezone from typing import Any from sqlalchemy import DateTime, func from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column class Base(DeclarativeBase): """Base class for all SQLAlchemy ORM models. Provides common functionality and type annotations for all models. All models should inherit from this class. """ pass class TimestampMixin: """Mixin to add created_at and updated_at timestamp columns. Automatically tracks when records are created and updated. Use this mixin for models that need audit timestamps. Attributes: created_at: Timestamp when record was created updated_at: Timestamp when record was last updated """ created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), nullable=False, doc="Timestamp when record was created" ) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False, doc="Timestamp when record was last updated" ) class SoftDeleteMixin: """Mixin to add soft delete functionality. Instead of deleting records, marks them as deleted with a timestamp. Useful for maintaining audit trails and allowing recovery. Attributes: deleted_at: Timestamp when record was soft deleted, None if active """ deleted_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, default=None, doc="Timestamp when record was soft deleted" ) @property def is_deleted(self) -> bool: """Check if record is soft deleted.""" return self.deleted_at is not None def soft_delete(self) -> None: """Mark record as deleted without removing from database.""" self.deleted_at = datetime.now(timezone.utc) def restore(self) -> None: """Restore a soft deleted record.""" self.deleted_at = None