TorbatYar/backend/services/accounting/app/repositories/base.py
Mortezakoohjani 12c8615615 Ship enterprise Accounting FE/API with CRUD parity and production wiring.
Adds accounting-service PATCH/archive, fiscal helpers, COA templates and setup status, plus SuperApp Accounting UI (DS, scoreboard, masters, vouchers, ledger, ops modules) with session refresh and HTTPS public API URLs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 15:26:43 +03:30

58 lines
1.9 KiB
Python

"""Tenant-aware base repository."""
from __future__ import annotations
from typing import Generic, Sequence, TypeVar
from uuid import UUID
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.database import Base
ModelT = TypeVar("ModelT", bound=Base)
class TenantBaseRepository(Generic[ModelT]):
model: type[ModelT]
def __init__(self, session: AsyncSession) -> None:
self.session = session
async def get(self, tenant_id: UUID, entity_id: UUID) -> ModelT | None:
stmt = select(self.model).where(
self.model.tenant_id == tenant_id, # type: ignore[attr-defined]
self.model.id == entity_id, # type: ignore[attr-defined]
)
result = await self.session.execute(stmt)
return result.scalar_one_or_none()
async def add(self, entity: ModelT) -> ModelT:
self.session.add(entity)
await self.session.flush()
return entity
async def delete(self, entity: ModelT) -> None:
await self.session.delete(entity)
await self.session.flush()
async def list_by_tenant(
self, tenant_id: UUID, *, offset: int = 0, limit: int = 20
) -> Sequence[ModelT]:
stmt = (
select(self.model)
.where(self.model.tenant_id == tenant_id) # type: ignore[attr-defined]
.offset(offset)
.limit(limit)
)
result = await self.session.execute(stmt)
return result.scalars().all()
async def count_by_tenant(self, tenant_id: UUID) -> int:
stmt = (
select(func.count())
.select_from(self.model)
.where(self.model.tenant_id == tenant_id) # type: ignore[attr-defined]
)
result = await self.session.execute(stmt)
return int(result.scalar_one())