97 lines
2.5 KiB
Python
97 lines
2.5 KiB
Python
"""Base classes for VoIdea models and services."""
|
|
|
|
from datetime import datetime
|
|
from typing import Any, Generic, TypeVar
|
|
from uuid import UUID, uuid4
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field
|
|
from sqlalchemy import DateTime, func
|
|
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
|
|
|
|
|
|
T = TypeVar("T")
|
|
|
|
|
|
class SQLBase(DeclarativeBase):
|
|
"""Base class for all SQLAlchemy models."""
|
|
|
|
type_annotation_map = {
|
|
datetime: DateTime(timezone=True),
|
|
}
|
|
|
|
|
|
class CoreModel(BaseModel):
|
|
"""Base Pydantic model with common fields."""
|
|
|
|
model_config = ConfigDict(
|
|
from_attributes=True,
|
|
populate_by_name=True,
|
|
)
|
|
|
|
|
|
class TimestampMixin:
|
|
"""Mixin for timestamp fields."""
|
|
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True),
|
|
server_default=func.now(),
|
|
)
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True),
|
|
server_default=func.now(),
|
|
onupdate=func.now(),
|
|
)
|
|
|
|
|
|
class UUIDMixin:
|
|
"""Mixin for UUID primary key."""
|
|
|
|
id: Mapped[UUID] = mapped_column(primary_key=True, default=uuid4)
|
|
|
|
|
|
class BaseRepository(Generic[T]):
|
|
"""Base repository for data access."""
|
|
|
|
model: type[T]
|
|
|
|
def __init__(self, session: Any):
|
|
self.session = session
|
|
|
|
async def get_by_id(self, id: UUID) -> T | None:
|
|
"""Get entity by ID."""
|
|
return await self.session.get(self.model, id)
|
|
|
|
async def get_all(self, limit: int = 100, offset: int = 0) -> list[T]:
|
|
"""Get all entities with pagination."""
|
|
result = await self.session.execute(
|
|
select(self.model).limit(limit).offset(offset)
|
|
)
|
|
return list(result.scalars().all())
|
|
|
|
async def create(self, **kwargs: Any) -> T:
|
|
"""Create new entity."""
|
|
entity = self.model(**kwargs)
|
|
self.session.add(entity)
|
|
await self.session.commit()
|
|
await self.session.refresh(entity)
|
|
return entity
|
|
|
|
async def update(self, entity: T, **kwargs: Any) -> T:
|
|
"""Update entity."""
|
|
for key, value in kwargs.items():
|
|
setattr(entity, key, value)
|
|
await self.session.commit()
|
|
await self.session.refresh(entity)
|
|
return entity
|
|
|
|
async def delete(self, entity: T) -> None:
|
|
"""Delete entity."""
|
|
await self.session.delete(entity)
|
|
await self.session.commit()
|
|
|
|
|
|
class BaseService:
|
|
"""Base service class."""
|
|
|
|
def __init__(self, repository: BaseRepository):
|
|
self.repository = repository |