Merge pull request 'Архив OpenSpec intercompany-matrix-presets (PR #141)' (#167) from chore/141-archive-matrix-presets into main

This commit is contained in:
aep 2026-10-22 23:05:21 +03:00
commit c187580738
9 changed files with 76 additions and 6 deletions

View File

@ -20,4 +20,4 @@
- [x] 3.3 Мелкие замечания раунда 2 (шапка xlsx пресета — счета правила и «кроме», подписи статей при `side_1 = K`,
лишняя проверка в `_export_response`, реквизиты правила в `MatrixExportInfo` и `_filename`, описания ошибок preset в
OpenAPI, проверка правила до расчёта свода) вынесены в технический долг AURORA-1761 (решение владельца 22.10.2026) — см. design.md.
- [ ] 3.4 После слияния: архив change.
- [x] 3.4 После слияния: архив change.

View File

@ -147,17 +147,24 @@ ORM-модель `audit_event` MUST NOT использоваться для `UPD
- **THEN** событие `CONSOLIDATION_STATUS_CHANGE` с `user_id` подтвердившего, `before_value.status = INITIATED`
### Requirement: Аудит экспорта шахматки
Каждый успешный `GET …/intercompany-matrix/all/export` и `POST …/intercompany-matrix/manual/export`
Каждый успешный `GET …/intercompany-matrix/all/export`, `POST …/intercompany-matrix/manual/export` и
`GET …/intercompany-matrix/preset/{rule_id}/export`
SHALL добавлять отдельное неизменяемое событие `audit_event` с `action = EXPORT`, `section = EXPORT`,
`object_type = consolidation_version`, `object_id = consolidation_version_id`, `user_id` инициатора,
`before_value = null` и `after_value = {report: "intercompany_matrix", mode, debit_account_ids,
credit_account_ids, cells}`. `mode` — `ALL` или `MANUAL`, массивы счетов — ID из запроса (в ALL пустые),
`cells` — число ячеек. Выгрузка сводной ОСВ продолжает писать собственное событие `EXPORT`.
credit_account_ids, cells}`; для `PRESET` в `after_value` SHALL быть дополнительно `rule_id`, `rule_no` и
`rule_version_no` (фактическая версия применённого правила, в том числе при незафиксированной версии правил). `mode` — `ALL`,
`MANUAL` или `PRESET`, массивы счетов — ID из запроса (в ALL и PRESET пустые), `cells` — число ячеек. Выгрузка
сводной ОСВ продолжает писать собственное событие `EXPORT`.
#### Scenario: Две выгрузки
- **WHEN** пользователь дважды выгружает ту же шахматку
- **THEN** в `audit_event` две разные записи `EXPORT`, каждая со своим payload и числом ячеек
#### Scenario: Выгрузка пресета
- **WHEN** пользователь выгружает `GET …/intercompany-matrix/preset/{rule_id}/export`
- **THEN** событие `EXPORT` содержит `mode = PRESET`, `rule_id`, `rule_no`, `rule_version_no`, пустые массивы счетов и число ячеек
### Requirement: Аудит экспорта результирующей таблицы ВГО
Каждый успешный `GET …/intercompany-matrix/result-table/export` SHALL добавлять отдельное неизменяемое событие
`audit_event` с `action = EXPORT`, `section = EXPORT`, `object_type = consolidation_version`,

View File

@ -210,3 +210,50 @@ filename="svod-osv.xlsx"; filename*=UTF-8''svod-osv_<ГК>_<год>-<кварт
#### Scenario: Экспорт выбранных счетов
- **WHEN** пользователь выгружает MANUAL для ГК «Русский бисквит» за 2024 Q1, версия 1
- **THEN** имя содержит `Русский бисквит_2024-Q1_v1.xlsx`, шапка содержит выбранные счета, ячейки процента показывают два знака и символ `%` без повторного масштабирования
### Requirement: Шахматка по правилу-пресету
`GET /api/v1/consolidations/versions/{version_id}/intercompany-matrix/preset/{rule_id}`
(`CONSOLIDATION_VIEW`, policy) SHALL рассчитывать шахматку в режиме PRESET с тем же ответом, что ALL и MANUAL.
Счета дебета и кредита SHALL браться из правила элиминации `rule_id`: дебет — сторона `company_1`, если
`side_1 = D`, иначе `company_2`; кредит — вторая сторона; исключения (`excluded`) вычитаются, выбранные счета
раскрываются по иерархии и фильтруются по виду, как в MANUAL. Показатель SHALL браться из `measure` правила:
`closing` — конечное сальдо (`closing_debit`/`closing_credit`), `turnover` — обороты (`turnover_debit`/`turnover_credit`).
Правило SHALL быть действительным для версии консолидации: при заданном `elimination_rules_version` — с тем же
`version_no`, иначе — без `valid_to` и с максимальным открытым `version_no`; несуществующее или недействительное правило SHALL давать 404. Ошибки 422:
`RULE_REQUIRED` — правило не выбрано, `INVALID_RULE` — правило ОФР либо неверные `side_1`, `measure` или сторона счёта правила,
`ACCOUNTS_REQUIRED` — у одной из сторон нет счетов. Невидимая и несуществующая версия SHALL отвечать 404 `NOT_FOUND`.
#### Scenario: Пресет по сальдо
- **WHEN** правило с `side_1 = D`, `measure = closing` содержит дебетовые счета на стороне 1 и кредитовые на стороне 2
- **THEN** `amount_a` пары — сумма `closing_debit` по счетам стороны 1, `amount_b` — сумма `closing_credit` по счетам стороны 2
#### Scenario: Пресет по оборотам
- **WHEN** у правила `measure = turnover`
- **THEN** суммы считаются по `turnover_debit`/`turnover_credit`
#### Scenario: Правило другой версии
- **WHEN** у версии `elimination_rules_version = 2`, а `rule_id` принадлежит правилу версии 1
- **THEN** 404 для расчёта и выгрузки
#### Scenario: Неизвестное правило
- **WHEN** `rule_id` не существует
- **THEN** 404
#### Scenario: Правило ОФР
- **WHEN** у правила `statement_type = income`
- **THEN** расчёт и выгрузка возвращают 422 `INVALID_RULE`
### Requirement: XLSX шахматки пресета
`GET …/intercompany-matrix/preset/{rule_id}/export` SHALL возвращать XLSX с теми же строками, что JSON-расчёт
пресета. Имя файла SHALL иметь вид `intercompany-matrix_<ГК>_<год>-<квартал>_v<n>_rule-balance-<rule_no>.xlsx`. Шапка SHALL
содержать режим «Пресет», коды счетов дебета и кредита (раскрытые по иерархии, с учётом исключений правила), номер
правила, статьи А и Б (`article_1_line` / `article_2_line`), фактическую версию правил и строку «Показатель» со значением «Сальдо» для `closing` или «Оборот» для `turnover`. Строка «Показатель» SHALL присутствовать и в выгрузках ALL и MANUAL (значение
«Сальдо»).
#### Scenario: Выгрузка по оборотам
- **WHEN** пользователь выгружает пресет с `measure = turnover`
- **THEN** шапка содержит «Режим — Пресет», «Показатель — Оборот», номер, статьи и версию правила; имя файла заканчивается на `_rule-balance-<rule_no>.xlsx`
#### Scenario: Правило не найдено
- **WHEN** `rule_id` не существует
- **THEN** 404, файл не отдаётся, событие аудита не пишется

View File

@ -226,8 +226,12 @@ account, status, missing_quarters, document_ids}`: `document_type` и `account`
### Requirement: Правила элиминации версии
`GET /api/v1/consolidations/versions/{version_id}/elimination-rules` (`CONSOLIDATION_VIEW`, policy по ГК)
SHALL возвращать все правила версии массивом. Каждое правило SHALL содержать `rule_no`, `version_no`,
`statement_type`, `side_1` (`D`/`K`), `measure` (`closing`/`turnover`), `company_1`, `company_2`;
SHALL возвращать объект `{version_no, is_version_fixed, rules}`. Если у версии задан
`consolidation_version.elimination_rules_version`, `version_no` SHALL равняться ему, `is_version_fixed = true`, а
`rules` — правилами этой версии. Если он не задан, `is_version_fixed = false`, а `rules` —
открытые правила (`valid_to IS NULL`) только с максимальным `version_no`; ответ SHALL содержать этот фактический
`version_no`. При отсутствии открытых правил `version_no = null`, `rules = []`. Каждое правило SHALL содержать `id`, `rule_no`,
`version_no`, `statement_type`, `side_1` (`D`/`K`), `measure` (`closing`/`turnover`), `company_1`, `company_2`;
каждая сторона SHALL содержать `accounts: UUID[]` и `excluded: UUID[]` до раскрытия иерархии счетов.
Невидимая и несуществующая версия SHALL отвечать одинаковым 404 `NOT_FOUND`.
@ -235,6 +239,18 @@ SHALL возвращать все правила версии массивом.
- **WHEN** у правила первая сторона включает счёт 76 и исключает 76.07.5
- **THEN** ID 76 находится в `company_1.accounts`, ID 76.07.5 — в `company_1.excluded`
#### Scenario: Версия правил зафиксирована
- **WHEN** у версии консолидации `elimination_rules_version = 1`
- **THEN** ответ содержит `is_version_fixed = true`, `version_no = 1` и только правила с `version_no = 1`
#### Scenario: Версия правил не зафиксирована
- **WHEN** у версии консолидации `elimination_rules_version` пуст
- **THEN** ответ содержит `is_version_fixed = false`, фактический `version_no` и открытые правила только этой версии
#### Scenario: Открыты две версии правил
- **WHEN** открыты правила с `version_no = 1` и `version_no = 2`, в том числе с одинаковым `rule_no`
- **THEN** ответ содержит только правила версии 2 и `version_no = 2`
### Requirement: Результирующая таблица ВГО
`GET /api/v1/consolidations/versions/{version_id}/intercompany-matrix/result-table`
(`CONSOLIDATION_VIEW`, policy) SHALL возвращать `{companies[], articles[]}`. Компании — все члены периметра