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>
108 lines
3.4 KiB
Python
108 lines
3.4 KiB
Python
"""Foundation repositories."""
|
|
from __future__ import annotations
|
|
|
|
from uuid import UUID
|
|
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.models.foundation import (
|
|
Account,
|
|
ChartOfAccounts,
|
|
CostCenter,
|
|
Currency,
|
|
FiscalPeriod,
|
|
FiscalYear,
|
|
Project,
|
|
TenantAccountingConfiguration,
|
|
)
|
|
from app.repositories.base import TenantBaseRepository
|
|
|
|
|
|
class ChartOfAccountsRepository(TenantBaseRepository[ChartOfAccounts]):
|
|
model = ChartOfAccounts
|
|
|
|
async def get_by_code(self, tenant_id: UUID, code: str) -> ChartOfAccounts | None:
|
|
stmt = select(ChartOfAccounts).where(
|
|
ChartOfAccounts.tenant_id == tenant_id,
|
|
ChartOfAccounts.code == code,
|
|
)
|
|
result = await self.session.execute(stmt)
|
|
return result.scalar_one_or_none()
|
|
|
|
|
|
class AccountRepository(TenantBaseRepository[Account]):
|
|
model = Account
|
|
|
|
async def get_by_code(self, tenant_id: UUID, code: str) -> Account | None:
|
|
stmt = select(Account).where(
|
|
Account.tenant_id == tenant_id, Account.code == code
|
|
)
|
|
result = await self.session.execute(stmt)
|
|
return result.scalar_one_or_none()
|
|
|
|
async def list_by_chart(
|
|
self, tenant_id: UUID, chart_id: UUID, *, offset: int = 0, limit: int = 100
|
|
):
|
|
stmt = (
|
|
select(Account)
|
|
.where(Account.tenant_id == tenant_id, Account.chart_id == chart_id)
|
|
.offset(offset)
|
|
.limit(limit)
|
|
)
|
|
result = await self.session.execute(stmt)
|
|
return result.scalars().all()
|
|
|
|
|
|
class CurrencyRepository(TenantBaseRepository[Currency]):
|
|
model = Currency
|
|
|
|
|
|
class FiscalYearRepository(TenantBaseRepository[FiscalYear]):
|
|
model = FiscalYear
|
|
|
|
async def get_current(self, tenant_id: UUID) -> FiscalYear | None:
|
|
stmt = select(FiscalYear).where(
|
|
FiscalYear.tenant_id == tenant_id, FiscalYear.is_current.is_(True)
|
|
)
|
|
result = await self.session.execute(stmt)
|
|
return result.scalar_one_or_none()
|
|
|
|
|
|
class FiscalPeriodRepository(TenantBaseRepository[FiscalPeriod]):
|
|
model = FiscalPeriod
|
|
|
|
async def get_current(self, tenant_id: UUID) -> FiscalPeriod | None:
|
|
stmt = select(FiscalPeriod).where(
|
|
FiscalPeriod.tenant_id == tenant_id, FiscalPeriod.is_current.is_(True)
|
|
)
|
|
result = await self.session.execute(stmt)
|
|
return result.scalar_one_or_none()
|
|
|
|
async def list_by_year(self, tenant_id: UUID, fiscal_year_id: UUID):
|
|
stmt = select(FiscalPeriod).where(
|
|
FiscalPeriod.tenant_id == tenant_id,
|
|
FiscalPeriod.fiscal_year_id == fiscal_year_id,
|
|
)
|
|
result = await self.session.execute(stmt)
|
|
return result.scalars().all()
|
|
|
|
|
|
class CostCenterRepository(TenantBaseRepository[CostCenter]):
|
|
model = CostCenter
|
|
|
|
|
|
class ProjectRepository(TenantBaseRepository[Project]):
|
|
model = Project
|
|
|
|
|
|
class TenantAccountingConfigRepository(TenantBaseRepository[TenantAccountingConfiguration]):
|
|
model = TenantAccountingConfiguration
|
|
|
|
async def get_for_tenant(self, tenant_id: UUID) -> TenantAccountingConfiguration | None:
|
|
stmt = select(TenantAccountingConfiguration).where(
|
|
TenantAccountingConfiguration.tenant_id == tenant_id
|
|
)
|
|
result = await self.session.execute(stmt)
|
|
return result.scalar_one_or_none()
|