From 6b948debc059b0d5712f2dd6dd75db408097b4bb Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Thu, 12 Nov 2026 01:37:06 +0400 Subject: [PATCH] =?UTF-8?q?test:=20=D1=88=D0=B0=D0=BF=D0=BA=D0=B0=20XLSX?= =?UTF-8?q?=20=D0=BF=D1=80=D0=B5=D1=81=D0=B5=D1=82=D0=B0=20=D1=81=D0=BE=20?= =?UTF-8?q?=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0=D0=BC=D0=B8=20=C2=AB=D0=BA?= =?UTF-8?q?=D1=80=D0=BE=D0=BC=D0=B5=C2=BB=20=D0=B2=20=D0=B8=D0=BD=D1=82?= =?UTF-8?q?=D0=B5=D0=B3=D1=80=D0=B0=D1=86=D0=B8=D0=BE=D0=BD=D0=BD=D0=BE?= =?UTF-8?q?=D0=BC=20=D1=82=D0=B5=D1=81=D1=82=D0=B5=20(AURORA-1761,=20PR=20?= =?UTF-8?q?#223)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- api/tests/test_api_intercompany_matrix.py | 37 ++++++++++++++----- .../tasks.md | 2 + 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/api/tests/test_api_intercompany_matrix.py b/api/tests/test_api_intercompany_matrix.py index 44050cd..773b3cf 100644 --- a/api/tests/test_api_intercompany_matrix.py +++ b/api/tests/test_api_intercompany_matrix.py @@ -13,7 +13,7 @@ from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from src.models.access import AppUser -from src.models.accounting import ChartOfAccount, EliminationRule +from src.models.accounting import ChartOfAccount, EliminationRule, EliminationRuleAccount from src.models.audit_ex import AuditEvent from src.models.consolidation import ConsolidationDocument, ConsolidationVersion from src.models.directories import CompanyGroup, LegalEntity, RegionalOffice @@ -67,6 +67,19 @@ async def _request(client: AsyncClient, version_id: uuid.UUID, suffix: str, sele return await client.get(f"{base}/{suffix}") +async def _rule_codes(session: AsyncSession, rule: EliminationRule) -> dict[tuple[int, bool], str]: + """Коды сторон правила как в шапке XLSX пресета: (company_no, is_excluded) → «код, код».""" + rows = await session.execute( + select(EliminationRuleAccount.company_no, EliminationRuleAccount.is_excluded, ChartOfAccount.code) + .join(ChartOfAccount, ChartOfAccount.id == EliminationRuleAccount.account_id) + .where(EliminationRuleAccount.rule_id == rule.id) + ) + grouped: dict[tuple[int, bool], list[str]] = {} + for company_no, is_excluded, code in rows: + grouped.setdefault((company_no, is_excluded), []).append(code) + return {key: ", ".join(sorted(values)) for key, values in grouped.items()} + + async def _source( session: AsyncSession, world: World, *, credit: bool, amount: str, account: str | None = None ) -> uuid.UUID: @@ -204,16 +217,22 @@ async def test_preset_uses_rule_sides_and_exclusions(auth_client: AuthClientFact assert exported.status_code == OK, exported.text assert f"_rule-balance-{rule.rule_no}.xlsx" in unquote(exported.headers["content-disposition"]) sheet = load_workbook(BytesIO(exported.content))["Шахматка"] + codes = await _rule_codes(seeded, rule) assert sheet["B6"].value == "Пресет" + assert (sheet["A7"].value, sheet["B7"].value) == ("Счета дебета", codes[(1, False)]) + assert (sheet["A8"].value, sheet["B8"].value) == ("кроме", codes[(1, True)]) + assert (sheet["A9"].value, sheet["B9"].value) == ("Счета кредита", codes[(2, False)]) + assert (sheet["A10"].value, sheet["B10"].value) == ("кроме", codes[(2, True)]) + assert "76" in codes[(1, False)].split(", ") assert "76.07.5" not in sheet["B7"].value - assert "76.07.1" not in sheet["B8"].value - assert sheet["B9"].value == "Сальдо" - assert sheet["B10"].value == f"ББ № {rule.rule_no}" - assert sheet["B11"].value == rule.article_1_line - assert sheet["B12"].value == rule.article_2_line - assert sheet["B13"].value == f"v{rule.version_no}" - assert Decimal(str(sheet["D16"].value)) == Decimal("100") - assert Decimal(str(sheet["D17"].value)) == Decimal("90") + assert "76.07.1" in sheet["B10"].value + assert sheet["B11"].value == "Сальдо" + assert sheet["B12"].value == f"ББ № {rule.rule_no}" + assert sheet["B13"].value == rule.article_1_line + assert sheet["B14"].value == rule.article_2_line + assert sheet["B15"].value == f"v{rule.version_no}" + assert Decimal(str(sheet["D18"].value)) == Decimal("100") + assert Decimal(str(sheet["D19"].value)) == Decimal("90") audit = (await seeded.scalars(select(AuditEvent).where(AuditEvent.action == AuditAction.EXPORT))).one() assert audit.after_value["mode"] == "PRESET" assert audit.after_value["rule_id"] == str(rule.id) diff --git a/openspec/changes/intercompany-matrix-preset-header/tasks.md b/openspec/changes/intercompany-matrix-preset-header/tasks.md index 3c1266a..5fef465 100644 --- a/openspec/changes/intercompany-matrix-preset-header/tasks.md +++ b/openspec/changes/intercompany-matrix-preset-header/tasks.md @@ -8,3 +8,5 @@ - [x] 1.4 Тесты: шапка правила № 6 с исключениями, `side_1 = K`, описания ошибок маршрутов preset (PR #223, автор) - [x] 1.5 Ревью: влит main (объединённые ALL/MANUAL, AURORA-2034), пустая сторона MANUAL в шапке — «Все балансовые счета»; правка спеки перенесена из `openspec/specs` в этот change +- [x] 1.6 Ревью: интеграционный `test_preset_uses_rule_sides_and_exclusions` переведён на новую шапку (строки «кроме» + под сторонами, коды правила сверяются с `elimination_rule_account` из seed, данные матрицы сдвинуты на две строки)