69 lines
2.2 KiB
Python
69 lines
2.2 KiB
Python
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
|