import arrow from sqlalchemy import ( TIMESTAMP, func, text, UUID, String, Integer, Boolean, SmallInteger, ) from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy_mixins.serialize import SerializeMixin from sqlalchemy_mixins.repr import ReprMixin from sqlalchemy_mixins.smartquery import SmartQueryMixin from base import BaseAlchemyModel from crud import CRUDModel from filter import QueryModel from database import Base class BasicMixin( Base, BaseAlchemyModel, CRUDModel, SerializeMixin, ReprMixin, SmartQueryMixin, QueryModel, ): __abstract__ = True __repr__ = ReprMixin.__repr__ class CrudMixin(BasicMixin): """ Base mixin providing CRUD operations and common fields for PostgreSQL models. Features: - Automatic timestamps (created_at, updated_at) - Soft delete capability - User tracking (created_by, updated_by) - Data serialization - Multi-language support """ __abstract__ = True # Primary and reference fields id: Mapped[int] = mapped_column(Integer, primary_key=True) uu_id: Mapped[str] = mapped_column( UUID, server_default=text("gen_random_uuid()"), index=True, unique=True, comment="Unique identifier UUID", ) # Common timestamp fields for all models expiry_starts: Mapped[TIMESTAMP] = mapped_column( TIMESTAMP(timezone=True), server_default=func.now(), comment="Record validity start timestamp", ) expiry_ends: Mapped[TIMESTAMP] = mapped_column( TIMESTAMP(timezone=True), default=str(arrow.get("2099-12-31")), server_default=func.now(), comment="Record validity end timestamp", ) class CrudCollection(CrudMixin): """ Full-featured model class with all common fields. Includes: - UUID and reference ID - Timestamps - User tracking - Confirmation status - Soft delete - Notification flags """ __abstract__ = True __repr__ = ReprMixin.__repr__ ref_id: Mapped[str] = mapped_column( String(100), nullable=True, index=True, comment="External reference ID" ) # Timestamps created_at: Mapped[TIMESTAMP] = mapped_column( TIMESTAMP(timezone=True), server_default=func.now(), nullable=False, index=True, comment="Record creation timestamp", ) updated_at: Mapped[TIMESTAMP] = mapped_column( TIMESTAMP(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False, index=True, comment="Last update timestamp", ) # Cryptographic and user tracking cryp_uu_id: Mapped[str] = mapped_column( String, nullable=True, index=True, comment="Cryptographic UUID" ) created_by: Mapped[str] = mapped_column( String, nullable=True, comment="Creator name" ) created_by_id: Mapped[int] = mapped_column( Integer, nullable=True, comment="Creator ID" ) updated_by: Mapped[str] = mapped_column( String, nullable=True, comment="Last modifier name" ) updated_by_id: Mapped[int] = mapped_column( Integer, nullable=True, comment="Last modifier ID" ) confirmed_by: Mapped[str] = mapped_column( String, nullable=True, comment="Confirmer name" ) confirmed_by_id: Mapped[int] = mapped_column( Integer, nullable=True, comment="Confirmer ID" ) # Status flags is_confirmed: Mapped[bool] = mapped_column( Boolean, server_default="0", comment="Record confirmation status" ) replication_id: Mapped[int] = mapped_column( SmallInteger, server_default="0", comment="Replication identifier" ) deleted: Mapped[bool] = mapped_column( Boolean, server_default="0", comment="Soft delete flag" ) active: Mapped[bool] = mapped_column( Boolean, server_default="1", comment="Record active status" ) is_notification_send: Mapped[bool] = mapped_column( Boolean, server_default="0", comment="Notification sent flag" ) is_email_send: Mapped[bool] = mapped_column( Boolean, server_default="0", comment="Email sent flag" )