diff --git a/openspec/changes/intercompany-matrix-totals-ui/design.md b/openspec/changes/archive/2026-11-06-intercompany-matrix-totals-ui/design.md similarity index 100% rename from openspec/changes/intercompany-matrix-totals-ui/design.md rename to openspec/changes/archive/2026-11-06-intercompany-matrix-totals-ui/design.md diff --git a/openspec/changes/intercompany-matrix-totals-ui/proposal.md b/openspec/changes/archive/2026-11-06-intercompany-matrix-totals-ui/proposal.md similarity index 100% rename from openspec/changes/intercompany-matrix-totals-ui/proposal.md rename to openspec/changes/archive/2026-11-06-intercompany-matrix-totals-ui/proposal.md diff --git a/openspec/changes/intercompany-matrix-totals-ui/specs/intercompany-matrix-ui/spec.md b/openspec/changes/archive/2026-11-06-intercompany-matrix-totals-ui/specs/intercompany-matrix-ui/spec.md similarity index 100% rename from openspec/changes/intercompany-matrix-totals-ui/specs/intercompany-matrix-ui/spec.md rename to openspec/changes/archive/2026-11-06-intercompany-matrix-totals-ui/specs/intercompany-matrix-ui/spec.md diff --git a/openspec/changes/intercompany-matrix-totals-ui/tasks.md b/openspec/changes/archive/2026-11-06-intercompany-matrix-totals-ui/tasks.md similarity index 82% rename from openspec/changes/intercompany-matrix-totals-ui/tasks.md rename to openspec/changes/archive/2026-11-06-intercompany-matrix-totals-ui/tasks.md index f14caf9..904ead8 100644 --- a/openspec/changes/intercompany-matrix-totals-ui/tasks.md +++ b/openspec/changes/archive/2026-11-06-intercompany-matrix-totals-ui/tasks.md @@ -5,4 +5,4 @@ - [x] 1.3 Матрица: «Итого Дт» / «Итого Кт» из ответа - [x] 1.4 Фильтр «Компании» в запросе, варианты из периметра; выгрузка с выбором компаний - [x] 1.5 Результирующая таблица без строки «Итого» -- [ ] 1.6 Сценарий на стенде (Playwright) и сверка с макетом 31-01 / 31-01-01 +- [x] 1.6 Сценарий на стенде (Playwright, РБ 2024 К3) diff --git a/openspec/changes/intercompany-matrix-totals/design.md b/openspec/changes/archive/2026-11-06-intercompany-matrix-totals/design.md similarity index 100% rename from openspec/changes/intercompany-matrix-totals/design.md rename to openspec/changes/archive/2026-11-06-intercompany-matrix-totals/design.md diff --git a/openspec/changes/intercompany-matrix-totals/proposal.md b/openspec/changes/archive/2026-11-06-intercompany-matrix-totals/proposal.md similarity index 100% rename from openspec/changes/intercompany-matrix-totals/proposal.md rename to openspec/changes/archive/2026-11-06-intercompany-matrix-totals/proposal.md diff --git a/openspec/changes/intercompany-matrix-totals/specs/audit-trail/spec.md b/openspec/changes/archive/2026-11-06-intercompany-matrix-totals/specs/audit-trail/spec.md similarity index 100% rename from openspec/changes/intercompany-matrix-totals/specs/audit-trail/spec.md rename to openspec/changes/archive/2026-11-06-intercompany-matrix-totals/specs/audit-trail/spec.md diff --git a/openspec/changes/intercompany-matrix-totals/specs/consolidated-osv/spec.md b/openspec/changes/archive/2026-11-06-intercompany-matrix-totals/specs/consolidated-osv/spec.md similarity index 100% rename from openspec/changes/intercompany-matrix-totals/specs/consolidated-osv/spec.md rename to openspec/changes/archive/2026-11-06-intercompany-matrix-totals/specs/consolidated-osv/spec.md diff --git a/openspec/changes/intercompany-matrix-totals/specs/consolidations-api/spec.md b/openspec/changes/archive/2026-11-06-intercompany-matrix-totals/specs/consolidations-api/spec.md similarity index 100% rename from openspec/changes/intercompany-matrix-totals/specs/consolidations-api/spec.md rename to openspec/changes/archive/2026-11-06-intercompany-matrix-totals/specs/consolidations-api/spec.md diff --git a/openspec/changes/intercompany-matrix-totals/tasks.md b/openspec/changes/archive/2026-11-06-intercompany-matrix-totals/tasks.md similarity index 79% rename from openspec/changes/intercompany-matrix-totals/tasks.md rename to openspec/changes/archive/2026-11-06-intercompany-matrix-totals/tasks.md index e62850b..4f1d010 100644 --- a/openspec/changes/intercompany-matrix-totals/tasks.md +++ b/openspec/changes/archive/2026-11-06-intercompany-matrix-totals/tasks.md @@ -9,4 +9,4 @@ ## 2. Фронт (AURORA-1757, отдельный PR) -- [ ] 2.1 Клиент на единый маршрут, итоги из API, фильтр «Компании» в запрос +- [x] 2.1 (PR #225) Клиент на единый маршрут, итоги из API, фильтр «Компании» в запрос diff --git a/openspec/specs/audit-trail/spec.md b/openspec/specs/audit-trail/spec.md index 5c626e4..fb817ec 100644 --- a/openspec/specs/audit-trail/spec.md +++ b/openspec/specs/audit-trail/spec.md @@ -147,14 +147,13 @@ 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/preset/{rule_id}/export` +Каждый успешный `POST …/intercompany-matrix/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}`; для `PRESET` в `after_value` SHALL быть дополнительно `rule_id`, `rule_no` и +credit_account_ids, legal_entity_ids, cells}`; для `PRESET` в `after_value` SHALL быть дополнительно `rule_id`, `rule_no` и `rule_version_no` (фактическая версия применённого правила, в том числе при незафиксированной версии правил). `mode` — `ALL`, -`MANUAL` или `PRESET`, массивы счетов — ID из запроса (в ALL и PRESET пустые), `cells` — число ячеек. Выгрузка +`MANUAL` или `PRESET`, массивы счетов и ЮЛ — ID из запроса (счета в ALL и PRESET пустые), `cells` — число ячеек. Выгрузка сводной ОСВ продолжает писать собственное событие `EXPORT`. #### Scenario: Две выгрузки diff --git a/openspec/specs/consolidated-osv/spec.md b/openspec/specs/consolidated-osv/spec.md index 61a9661..b5bce9d 100644 --- a/openspec/specs/consolidated-osv/spec.md +++ b/openspec/specs/consolidated-osv/spec.md @@ -175,17 +175,20 @@ filename="svod-osv.xlsx"; filename*=UTF-8''svod-osv_<ГК>_<год>-<кварт — одну строку с `Q2`; `audit_event(EXPORT)` с `after_value.rows = 3` ### Requirement: Шахматка по сводной ОСВ версии -`GET /api/v1/consolidations/versions/{version_id}/intercompany-matrix/all` и -`POST /api/v1/consolidations/versions/{version_id}/intercompany-matrix/manual` -(`CONSOLIDATION_VIEW`, policy) SHALL рассчитывать матрицу без сохранения в БД, из строк сводной ОСВ версии -и её периметра. ALL включает балансовые счета (`is_off_balance = false`) вида `A`/`AP` для дебета и `P`/`AP` для -кредита; забалансовые счета (001–012) в ALL MUST NOT входить. MANUAL принимает обязательные непустые -`debit_account_ids: UUID[]` и `credit_account_ids: UUID[]`, раскрывает выбранные счета по иерархии и оставляет -подходящий вид; забалансовые счета в MANUAL допускаются. Неизвестный счёт SHALL давать 422 `ACCOUNT_NOT_FOUND`, неверный -вид — 422 `ACCOUNT_KIND_MISMATCH`; пустой массив — 422 валидации тела. Невидимая и несуществующая версия SHALL +`POST /api/v1/consolidations/versions/{version_id}/intercompany-matrix` принимает +`{debit_account_ids?: UUID[], credit_account_ids?: UUID[], legal_entity_ids?: UUID[]}`. Если список стороны отсутствует или пуст, +для неё выбираются все подходящие балансовые счета (`is_off_balance = false`); непустой список раскрывается +по иерархии и может содержать забалансовые счета. Пустые списки обеих сторон эквивалентны режиму ALL, +хотя бы один непустой список — MANUAL. Маршрут (`CONSOLIDATION_VIEW`, policy) SHALL рассчитывать матрицу +без сохранения в БД, из строк сводной ОСВ версии и её периметра. Для пустой стороны выбираются счета вида +`A`/`AP` для дебета или `P`/`AP` для кредита; забалансовые счета (001–012) MUST NOT входить в такую выборку. +Неизвестный счёт SHALL давать 422 `ACCOUNT_NOT_FOUND`, неверный вид — 422 `ACCOUNT_KIND_MISMATCH`. +Пустой `legal_entity_ids` выбирает все ЮЛ периметра; непустой ограничивает обе оси матрицы и суммы выбранными ЮЛ. +ID вне периметра SHALL давать 422 `ENTITY_NOT_IN_PERIMETER`. Невидимая и несуществующая версия SHALL отвечать одинаковым 404 `NOT_FOUND`. -Ответ SHALL содержать `companies[] {id, name}` для всего периметра и `cells[]` для каждой упорядоченной пары +Ответ SHALL содержать `companies[] {id, name}` для периметра (при непустом `legal_entity_ids` — только выбранные ЮЛ в порядке периметра), `total_debit` и `total_credit` +с суммой по каждому ЮЛ (ключ — ID ЮЛ, значение — десятичная строка с двумя знаками), и `cells[]` для каждой упорядоченной пары разных компаний: `company_a_id`, `company_b_id`, `amount_a`, `amount_b`, `variance_amount`, `variance_percent`, `exceeds_threshold`, `one_sided`, `skipped_osv_entry_count`, `osv_entry_ids_debit`, `osv_entry_ids_credit`. Для пары `(A, B)` `amount_a` — сумма `closing_debit` строк A с контрагентом B по дебетовым счетам, @@ -197,10 +200,15 @@ filename="svod-osv.xlsx"; filename*=UTF-8''svod-osv_<ГК>_<год>-<кварт сальдо на признак не влияет. Пара подсвечивается, если `exceeds_threshold` или `one_sided`. `skipped_osv_entry_count` SHALL считать исходные строки ОСВ пары с `account_id = null` на обеих сторонах; они не входят в суммы. Массивы `osv_entry_ids_debit/credit` SHALL содержать ID исходных записей соответствующей стороны. +`total_debit` («Итого Дт», колонка справа) суммирует `amount_a` ячеек строки по `company_a_id`, `total_credit` +(«Итого Кт», строка снизу) — `amount_b` ячеек столбца по `company_b_id`; ключи — ID всех ЮЛ из `companies`. +Диагональ не участвует, отрицательные суммы входят со знаком, суммы ячеек точные (`numeric(18,2)`). Для ЮЛ без +подходящих строк, в том числе когда в выборке одно ЮЛ, итог равен `"0.00"` (правило аналитика, DOC-221277 +«Итоги шахматки», 03.11.2026). #### Scenario: Пустой периметр и отсутствие ОСВ - **WHEN** у версии нет членов периметра -- **THEN** `companies = []`, `cells = []`; если компании есть, но ОСВ по выбранным счетам нет, ячейки присутствуют с нулевыми суммами +- **THEN** `companies = []`, `cells = []`, `total_debit = {}`, `total_credit = {}`; если компании есть, но ОСВ по выбранным счетам нет, ячейки присутствуют с нулевыми суммами #### Scenario: Только одна сторона пары - **WHEN** у A есть строка ОСВ с контрагентом B и ненулевым сальдо, а у B встречной строки нет @@ -230,12 +238,31 @@ SHALL считать исходные строки ОСВ пары с `account_i - **WHEN** матрица строится по ОСВ РБ и Пекарни Счастливочной из эталонных фикстур - **THEN** суммы сравниваются с эталоном только для точных пар счетов и компаний; общая сумма элиминации эталона не приравнивается к минимуму по паре в API (решение владельца 08.10.2026) +#### Scenario: Итоги Дт и Кт +- **WHEN** в периметре A, B, C; `amount_a` ячеек (A, B) = 100 и (A, C) = 20, `amount_b` ячеек (A, B) = 70 и (C, B) = 5 +- **THEN** `total_debit[A] = "120.00"`, `total_credit[B] = "75.00"` + +#### Scenario: Фильтр по ЮЛ +- **WHEN** запрос с `legal_entity_ids = [A, B]` при периметре A, B, C +- **THEN** `companies` и обе оси — только A и B, ячейки и итоги не учитывают C; ID вне периметра — 422 `ENTITY_NOT_IN_PERIMETER` + +#### Scenario: Пустая одна сторона +- **WHEN** `debit_account_ids = [62]`, `credit_account_ids` пуст +- **THEN** дебет — счёт 62 с потомками, кредит — все балансовые счета вида `P`/`AP`; режим выгрузки и аудита — `MANUAL` + ### Requirement: XLSX шахматки -`GET …/intercompany-matrix/all/export` и `POST …/intercompany-matrix/manual/export` SHALL использовать -те же режимы, тело и права, что и соответствующие JSON-маршруты. Ответ — XLSX с именем +`POST …/intercompany-matrix/export` принимает то же тело, что единый JSON-маршрут, и строит XLSX +по той же выборке ЮЛ и счетов. В шапке пустая сторона обозначается «Все балансовые счета»; аудит сохраняет +`legal_entity_ids` из запроса и использует +`mode = ALL`, когда пусты обе стороны, иначе `mode = MANUAL`. + +Ответ — XLSX с именем `intercompany-matrix_<ГК>_<год>-<квартал>_v.xlsx`, шапкой (ГК, период, версия, единицы, режим, выбранные счета; для ALL — «Все балансовые счета») и строками разницы, дебета, кредита и процента расхождения для каждой пары. Пара SHALL заливаться цветом порога, если `exceeds_threshold` или `one_sided` — так же, как в API. +Справа от колонок компаний SHALL быть колонка «Итого Дт» с `total_debit` по каждому ЮЛ строки (ячейка объединена +на строки пары); под матрицей SHALL быть строка «Итого Кт» с `total_credit` по каждому ЮЛ колонки; ячейка на +пересечении пустая. Значения — те же, что в JSON. #### Scenario: Экспорт выбранных счетов - **WHEN** пользователь выгружает MANUAL для ГК «Русский бисквит» за 2024 Q1, версия 1 diff --git a/openspec/specs/consolidations-api/spec.md b/openspec/specs/consolidations-api/spec.md index 15004ba..a6633a4 100644 --- a/openspec/specs/consolidations-api/spec.md +++ b/openspec/specs/consolidations-api/spec.md @@ -260,7 +260,8 @@ account, status, missing_quarters, document_ids}`: `document_type` и `account` из конечного сальдо нужной стороны и выбранных счетов статьи; `group_total` — сумма по компаниям. `amount` и `group_total` SHALL возвращаться строками с двумя знаками после округления `ROUND_HALF_UP` (например, `"0.00"`). -Отсутствие любого необходимого кода счёта SHALL давать 422 `RESULT_ACCOUNTS_MISSING` с перечнем кодов. +Итоговой строки по всем статьям (по компании или по группе) в ответе нет: суммы разных статей не складываются +(решение аналитика 03.11.2026, согласовано с заказчиком). Отсутствие любого необходимого кода счёта SHALL давать 422 `RESULT_ACCOUNTS_MISSING` с перечнем кодов. #### Scenario: Компания без ОСВ - **WHEN** в периметре есть компания без подходящих строк ОСВ @@ -270,6 +271,10 @@ account, status, missing_quarters, document_ids}`: `document_type` и `account` - **WHEN** в плане счетов отсутствует счёт 58.03 - **THEN** ответ 422 `RESULT_ACCOUNTS_MISSING`, сообщение содержит `58.03` +#### Scenario: Нет итога по статьям +- **WHEN** запрашивается результирующая таблица +- **THEN** в ответе нет `grand_total` и итогов по компании через все статьи; в XLSX под статьями нет строки «Итого» + ### Requirement: XLSX результирующей таблицы ВГО `GET /api/v1/consolidations/versions/{version_id}/intercompany-matrix/result-table/export` (`CONSOLIDATION_VIEW`, policy) SHALL возвращать XLSX с теми же статьями, компаниями и итогами, что `GET …/intercompany-matrix/result-table`, diff --git a/openspec/specs/intercompany-matrix-ui/spec.md b/openspec/specs/intercompany-matrix-ui/spec.md index ca24852..11ffa8c 100644 --- a/openspec/specs/intercompany-matrix-ui/spec.md +++ b/openspec/specs/intercompany-matrix-ui/spec.md @@ -39,16 +39,17 @@ - **THEN** одним нажатием открыт список консолидаций ГК ### Requirement: Таблица шахматки ЮЛ × ЮЛ -Экран SHALL загружать матрицу при открытии вкладки (`GET /consolidations/versions/{id}/intercompany-matrix/all`) и показывать +Экран SHALL загружать матрицу при открытии вкладки (`POST /consolidations/versions/{id}/intercompany-matrix`, тело — по требованию «Фильтр счетов Дт и Кт и режимы расчёта») и показывать таблицу: первая колонка «ДБ / КТ» (закреплена слева) — компании периметра в порядке ответа (`companies[]`), остальные колонки — те же компании. В ячейке пары (строка A, колонка Б) SHALL быть три числа друг под другом: сумма `amount_a`, сумма `amount_b` и расхождение `variance_amount` в скобках; расхождение выделяется красным, если `exceeds_threshold = true` или `one_sided = true` (пара без встречной стороны; правило подсветки — как в API и xlsx, AURORA-1651). Если у пары есть строки ОСВ без сопоставленного счёта (`skipped_osv_entry_count > 0`), рядом с первым числом SHALL показываться значок предупреждения с подсказкой «Строк ОСВ без сопоставленного счёта: N; в суммы не вошли». Если ячейки пары в ответе нет -(в том числе на диагонали), SHALL показываться прочерк «—» на приглушённом фоне. Ниже таблицы закреплена строка «Итого»: до -появления итогов в API (AURORA-1756, AURORA-1757) она временно считается на клиенте точным сложением десятичных строк — сумма -`amount_a` по колонке видимых ячеек; итог, который не удалось сложить, показывается прочерком «—», а не нулём. Пока идёт +(в том числе на диагонали), SHALL показываться прочерк «—» на приглушённом фоне. Справа закреплена колонка «Итого Дт» — +`total_debit` ответа для компании строки; ниже таблицы закреплена строка «Итого Кт» — `total_credit` для компании колонки; +ячейка на их пересечении пустая. Итоги считает сервер (DOC-221277 «Итоги шахматки», AURORA-1756), клиент их только форматирует +(«Единицы и знаки»); отсутствующий в ответе итог — прочерк «—». Пока идёт загрузка, таблица показывает индикатор загрузки; ошибка API показывается уведомлением с текстом сервера. Панель фильтров показывает год и квартал версии неактивными полями «Год» и «Период» (например, `2024` и `К1`): версия задаётся адресом. @@ -68,19 +69,22 @@ - **WHEN** у ячейки `skipped_osv_entry_count = 2` - **THEN** у первого числа ячейки виден значок предупреждения, подсказка — «Строк ОСВ без сопоставленного счёта: 2; в суммы не вошли» +#### Scenario: Итоги из ответа +- **WHEN** сервер вернул `total_debit[A] = "120000.00"` и `total_credit[Б] = "75000.00"`, выбраны «тыс. руб.» и 2 знака +- **THEN** в колонке «Итого Дт» строки A показано `120,00`, в строке «Итого Кт» под колонкой Б — `75,00`, пересечение итогов пустое + ### Requirement: Результирующая таблица ВГО Под матрицей экран SHALL показывать результирующую таблицу ВГО, загруженную при открытии вкладки (`GET /consolidations/versions/{id}/intercompany-matrix/result-table`): первая колонка «Статья» — статьи ответа (`articles[]`, `name`) в порядке ответа, далее колонки компаний (`companies[]`) с суммой статьи по компании (`amounts[]` по `company_id`) и -колонка «Итого» со значением `group_total` из ответа; пустая сумма — прочерк «—». Ниже таблицы закреплена строка «Итого»: до -появления итогов в API (AURORA-1756, AURORA-1757) она временно считается на клиенте точным сложением сумм всех статей по -колонке (итог, который не удалось сложить, — «—»). У таблицы свои выбор единиц и знаков (по правилам требования «Единицы и знаки», независимо от +колонка «Итого по группе» со значением `group_total` из ответа; пустая сумма — прочерк «—». Строки итога по всем статьям под +таблицей нет: суммы разных статей не складываются (аналитик, 03.11.2026). У таблицы свои выбор единиц и знаков (по правилам требования «Единицы и знаки», независимо от матрицы), кнопка «Экспорт» и кнопка «На весь экран». Пока идёт загрузка, таблица показывает индикатор; ошибка API (в том числе 422 `RESULT_ACCOUNTS_MISSING`) показывается уведомлением с текстом сервера. #### Scenario: Колонка «Итого» из ответа - **WHEN** сервер вернул статью «Дебиторская задолженность» с `group_total = "1296510.00"`, выбраны «тыс. руб.» и 2 знака -- **THEN** в колонке «Итого» этой статьи показано `1 296,51` +- **THEN** в колонке «Итого по группе» этой статьи показано `1 296,51` #### Scenario: Нет обязательного счёта - **WHEN** сервер ответил 422 `RESULT_ACCOUNTS_MISSING` @@ -107,14 +111,15 @@ - **THEN** показано `0,00`, а не `-0,00` ### Requirement: Фильтр компаний -Выбор «Компании» (множественный, пустой выбор — «Все компании») SHALL ограничивать матрицу на клиенте: остаются строки и -колонки выбранных компаний и ячейки, у которых обе компании выбраны. Запрос на сервер при этом не отправляется. Список -вариантов — компании последнего загруженного ответа. Выпадающее окно выбора — дерево с поиском по названию, кнопками +Выбор «Компании» (множественный, пустой выбор — «Все компании») SHALL передаваться в запрос матрицы +`legal_entity_ids`: сервер возвращает только выбранные компании, ячейки между ними и итоги «Итого Дт» / «Итого Кт» по ним. +Каждое изменение выбора перезапрашивает матрицу (в состоянии «выбрана одна сторона» — нет). Список вариантов — компании +последнего ответа, полученного без выбора компаний (весь периметр версии); ответы с выбором его не меняют. Выпадающее окно выбора — дерево с поиском по названию, кнопками применения и сброса. #### Scenario: Две компании из периметра - **WHEN** выбраны две компании из пяти -- **THEN** матрица содержит две строки и две колонки, «Итого» считается по оставшимся ячейкам +- **THEN** запрос содержит `legal_entity_ids` этих двух компаний, матрица содержит две строки и две колонки, итоги — из ответа, в списке вариантов по-прежнему пять компаний ### Requirement: Фильтр счетов Дт и Кт и режимы расчёта Экран SHALL загружать план счетов `GET /directories/accounts` один раз при открытии и строить из него два дерева по иерархии @@ -127,21 +132,22 @@ отметки при отметке видимых узлов сохраняются. Режим расчёта определяется выбором: -- ничего не выбрано ни в Дт, ни в Кт — SHALL выполняться `GET …/intercompany-matrix/all` (режим `all`); -- выбраны счета и в Дт, и в Кт — SHALL выполняться `POST …/intercompany-matrix/manual` с `{debit_account_ids, - credit_account_ids}` (режим `manual`); +- ничего не выбрано ни в Дт, ни в Кт — SHALL выполняться `POST …/intercompany-matrix` с пустыми `debit_account_ids` и + `credit_account_ids` (режим `all`); +- выбраны счета и в Дт, и в Кт — SHALL выполняться `POST …/intercompany-matrix` с выбранными `debit_account_ids` и + `credit_account_ids` (режим `manual`); - выбрана только одна сторона — запрос SHALL NOT отправляться, таблица матрицы SHALL быть пустой и вместо данных показывать текст «Для расчёта по счетам выберите счета и в Дт, и в Кт»; тот же текст SHALL показываться у фильтров Дт/Кт (не всплывающим уведомлением) и только в этом состоянии; кнопка «Экспорт» матрицы SHALL быть недоступна. -Каждое изменение выбора счетов, приводящее к режиму `all` или `manual`, перезапрашивает матрицу; на экране остаётся ответ на +В тело всегда входит `legal_entity_ids` (требование «Фильтр компаний»). Каждое изменение выбора счетов, приводящее к режиму `all` или `manual`, перезапрашивает матрицу; на экране остаётся ответ на последний запрос, индикатор загрузки снимается и при переходе в состояние «выбрана одна сторона». Кнопка «Сбросить фильтры» появляется, когда выбрано что-либо в компаниях, Дт или Кт, и очищает все три выбора. Выбор единиц и знаков кнопкой не сбрасывается. Ошибка загрузки плана счетов показывается уведомлением. #### Scenario: Обе стороны выбраны - **WHEN** выбран счёт 60.01 в Дт и счёт 62.01 в Кт -- **THEN** отправляется `POST …/intercompany-matrix/manual` с идентификаторами этих счетов и таблица показывает ответ +- **THEN** отправляется `POST …/intercompany-matrix` с идентификаторами этих счетов и таблица показывает ответ #### Scenario: Выбрана одна сторона - **WHEN** выбран счёт только в Дт @@ -165,17 +171,16 @@ - **THEN** все три выбора пусты, матрица перезапрошена в режиме `all`, кнопка исчезла ### Requirement: Экспорт в XLSX -Кнопка «Экспорт» матрицы SHALL скачивать XLSX в том же режиме, что и таблица: в режиме `manual` — -`POST …/intercompany-matrix/manual/export` с телом `{debit_account_ids, credit_account_ids}`, в режиме `all` — -`GET …/intercompany-matrix/all/export`; при выбранной одной стороне кнопка недоступна. Кнопка «Экспорт» результирующей таблицы +Кнопка «Экспорт» матрицы SHALL скачивать XLSX в том же режиме, что и таблица: `POST …/intercompany-matrix/export` с тем же +телом, что запрос таблицы (`debit_account_ids`, `credit_account_ids`, `legal_entity_ids`), — итоги в файле совпадают с экраном; при выбранной одной стороне кнопка недоступна. Кнопка «Экспорт» результирующей таблицы SHALL скачивать `GET …/intercompany-matrix/result-table/export`. Файл сохраняется под именем из `Content-Disposition`, при его отсутствии — `Шахматка_<ГК>_<год>_<квартал>.xlsx` и `Результирующая_таблица_ВГО_<ГК>_<год>_<квартал>.xlsx` соответственно. -Пока идёт выгрузка, в состоянии загрузки только нажатая кнопка; ошибка API показывается уведомлением. Фильтр компаний, единицы и -знаки в запрос экспорта не передаются. +Пока идёт выгрузка, в состоянии загрузки только нажатая кнопка; ошибка API показывается уведомлением. Единицы и знаки в запрос экспорта +не передаются. #### Scenario: Экспорт по всем счетам - **WHEN** счета не выбраны и нажато «Экспорт» матрицы -- **THEN** отправлен `GET …/intercompany-matrix/all/export`, браузер сохраняет файл `intercompany-matrix_….xlsx` +- **THEN** отправлен `POST …/intercompany-matrix/export` с пустыми списками, браузер сохраняет файл `intercompany-matrix_….xlsx` #### Scenario: Экспорт результирующей таблицы - **WHEN** нажато «Экспорт» результирующей таблицы