wag-managment-api-service-v.../Services/Postgres/Models/base.py

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