"""Чтение версионированных правил элиминации и счетов их сторон.""" import uuid from collections.abc import Collection from datetime import date from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from src.models.accounting import ChartOfAccount, EliminationRule, EliminationRuleAccount async def list_rules_with_accounts( session: AsyncSession, version_no: int ) -> list[tuple[EliminationRule, EliminationRuleAccount | None]]: """Правила §4 заданной версии.""" stmt = ( select(EliminationRule, EliminationRuleAccount) .outerjoin(EliminationRuleAccount, EliminationRuleAccount.rule_id == EliminationRule.id) .where(EliminationRule.version_no == version_no) .order_by( EliminationRule.statement_type, EliminationRule.rule_no, EliminationRuleAccount.company_no, ) ) return [(rule, account) for rule, account in (await session.execute(stmt)).all()] async def latest_effective_version_no(session: AsyncSession, as_of: date) -> int | None: """Максимальный номер версии правил, действующей на дату создания""" return await session.scalar( select(func.max(EliminationRule.version_no)).where( EliminationRule.valid_from <= as_of, (EliminationRule.valid_to.is_(None) | (EliminationRule.valid_to >= as_of)), ) ) def is_valid_for_version(rule: EliminationRule | None, version_no: int) -> bool: """Правило §4 из зафиксированной версии правил версии консолидации.""" return rule is not None and rule.version_no == version_no async def list_rules(session: AsyncSession, version_no: int) -> list[EliminationRule]: """Все правила заданной версии, включая ББ и ОФР, в порядке типа отчётности и номера.""" stmt = ( select(EliminationRule) .where(EliminationRule.version_no == version_no) .order_by(EliminationRule.statement_type, EliminationRule.rule_no) ) return list((await session.scalars(stmt)).all()) async def list_rule_accounts( session: AsyncSession, rule_ids: Collection[uuid.UUID] ) -> list[tuple[EliminationRuleAccount, str]]: """Счета правил с кодами из плана счетов; `company_no` задаёт сторону, `is_excluded` — исключение.""" if not rule_ids: return [] stmt = ( select(EliminationRuleAccount, ChartOfAccount.code) .join(ChartOfAccount, ChartOfAccount.id == EliminationRuleAccount.account_id) .where(EliminationRuleAccount.rule_id.in_(rule_ids)) .order_by(EliminationRuleAccount.rule_id, EliminationRuleAccount.company_no, ChartOfAccount.code) ) return [(account, code) for account, code in (await session.execute(stmt)).all()] async def rule_with_account( session: AsyncSession, rule_id: uuid.UUID ) -> tuple[EliminationRule | None, list[EliminationRuleAccount]]: """Правило §4 и его счета; `company_no` задаёт сторону, `is_excluded` — исключение.""" rule = await session.get(EliminationRule, rule_id) if rule is None: return None, [] stmt = ( select(EliminationRuleAccount) .join(ChartOfAccount, ChartOfAccount.id == EliminationRuleAccount.account_id) .where(EliminationRuleAccount.rule_id == rule_id) .order_by(EliminationRuleAccount.company_no, ChartOfAccount.code) ) return rule, list((await session.scalars(stmt)).all())