from datetime import datetime from typing import Any, Dict, List, Optional, TypeVar, Union from sqlalchemy import Column, DateTime, Integer, inspect from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.orm import Session from Services.Postgres.database import Base, get_db T = TypeVar('T') class PostgresBase(Base): """Base class for all PostgreSQL models.""" __abstract__ = True id = Column(Integer, primary_key=True, index=True) created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) deleted_at = Column(DateTime, nullable=True) @declared_attr def __tablename__(cls) -> str: """Generate table name automatically from class name.""" return cls.__name__.lower() def as_dict(self) -> Dict[str, Any]: """Convert model instance to dictionary.""" return {c.key: getattr(self, c.key) for c in inspect(self).mapper.column_attrs} @classmethod def filter_non_deleted(cls, db: Session): """Filter out soft-deleted records.""" return db.query(cls).filter(cls.deleted_at.is_(None)) @classmethod def get_by_id(cls, db: Session, id: int) -> Optional['PostgresBase']: """Get record by ID if not deleted.""" return cls.filter_non_deleted(db).filter(cls.id == id).first() def soft_delete(self) -> None: """Soft delete the record.""" self.deleted_at = datetime.utcnow() with get_db() as db: self.save(db) def save(self, db: Session) -> None: """Save the current record.""" if not self.id: db.add(self) db.commit() db.refresh(self) def update(self, **kwargs: Dict[str, Any]) -> None: """Update record with given values.""" for key, value in kwargs.items(): if hasattr(self, key): setattr(self, key, value) with get_db() as db: self.save(db) @classmethod def create(cls, **kwargs: Dict[str, Any]) -> 'PostgresBase': """Create a new record.""" instance = cls(**kwargs) with get_db() as db: instance.save(db) return instance