"""Create Mixin.""" from typing import Any from sqlalchemy import Connection, event from sqlalchemy.orm import Mapper from ..contexts import get_user_id from ..utils import current_timestamp, try_creatable class CreateMixin: """Mixin for models with creation tracking. AUTOMATIC BEHAVIOR on any model creation: - created_at: Set to current timestamp in SYSTEM_TIMEZONE - created_by: Set from ctx_user_id context To control automatic updates: ```python disable_on_create() enable_on_create() ``` The actual columns are defined in the model itself based on what exists in the database schema. A model using this mixin may have one or more of: - created_at: When the record was created - created_by: User ID who created the record """ def _on_create(self) -> None: """Automatically set creation fields.""" try_creatable(self) if hasattr(self, 'created_at') and self.created_at is None: self.created_at = current_timestamp() if hasattr(self, 'created_by') and self.created_by is None: self.created_by = get_user_id() _on_create_enabled = True def disable_on_create() -> None: """Disable automatic creation fields.""" global _on_create_enabled if not _on_create_enabled: return try: event.remove(CreateMixin, 'before_insert', _on_create) except Exception: pass _on_create_enabled = False def enable_on_create() -> None: """Enable automatic creation fields.""" global _on_create_enabled if _on_create_enabled: return event.listen(CreateMixin, 'before_insert', _on_create, propagate=True) _on_create_enabled = True def _on_create(mapper: Mapper, connection: Connection, target: Any) -> None: """Automatically set creation fields.""" target._on_create() # Register listener at module import time event.listen(CreateMixin, 'before_insert', _on_create, propagate=True)