7.3 KiB
MODIFIED Requirements
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
отвечать одинаковым 404 NOT_FOUND.
Ответ SHALL содержать companies[] {id, name} для всего периметра и 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 по дебетовым счетам,
amount_b — сумма closing_credit строк B с контрагентом A по кредитовым. Расхождение — модуль разности;
процент — расхождение / меньшую сумму × 100 или null при нуле. exceeds_threshold SHALL быть true при точном
проценте > 5, до округления; суммы и процент в JSON SHALL быть десятичными строками с двумя знаками после
запятой (ROUND_HALF_UP). one_sided (пара без встречной стороны) SHALL быть true тогда и только тогда, когда
ровно одна из сумм amount_a, amount_b равна нулю (знак ненулевой суммы не важен); наличие строк ОСВ с нулевым
сальдо на признак не влияет. Пара подсвечивается, если exceeds_threshold или one_sided. skipped_osv_entry_count
SHALL считать исходные строки ОСВ пары с account_id = null на обеих сторонах; они не входят в суммы. Массивы
osv_entry_ids_debit/credit SHALL содержать ID исходных записей соответствующей стороны.
Scenario: Пустой периметр и отсутствие ОСВ
- WHEN у версии нет членов периметра
- THEN
companies = [],cells = []; если компании есть, но ОСВ по выбранным счетам нет, ячейки присутствуют с нулевыми суммами
Scenario: Только одна сторона пары
- WHEN у A есть строка ОСВ с контрагентом B и ненулевым сальдо, а у B встречной строки нет
- THEN для
(A, B)one_sided = true,variance_percent = null, соответствующий массивosv_entry_ids_*пуст
Scenario: Встречная строка с нулевым сальдо
- WHEN у A по B сальдо 100 000 000, а у B по A есть строка ОСВ с нулевым сальдо (одни обороты)
- THEN
one_sided = true,exceeds_threshold = false, пара подсвечивается
Scenario: Обе стороны нулевые
- WHEN у A и у B есть строки ОСВ друг на друга, но обе суммы равны 0
- THEN
one_sided = false,exceeds_threshold = false, пара не подсвечивается
Scenario: Отрицательное сальдо
- WHEN у A по B сальдо −50, у B по A — 0
- THEN
one_sided = true
Scenario: Забалансовые счета
- WHEN у A по B есть сальдо на счёте 001 (
is_off_balance = true) - THEN в режиме ALL оно в суммы не входит; в MANUAL с выбранным счётом 001 — входит
Scenario: Счёт не сопоставлен
- WHEN у пары есть строка свода с
account_id = nullи двумяentry_ids - THEN она не входит в суммы,
skipped_osv_entry_countобеих направленных ячеек пары увеличивается на 2
Scenario: Эталон «Русский бисквит»
- WHEN матрица строится по ОСВ РБ и Пекарни Счастливочной из эталонных фикстур
- THEN суммы сравниваются с эталоном только для точных пар счетов и компаний; общая сумма элиминации эталона не приравнивается к минимуму по паре в API (решение владельца 08.10.2026)
Requirement: XLSX шахматки
GET …/intercompany-matrix/all/export и POST …/intercompany-matrix/manual/export SHALL использовать
те же режимы, тело и права, что и соответствующие JSON-маршруты. Ответ — XLSX с именем
intercompany-matrix_<ГК>_<год>-<квартал>_v<n>.xlsx, шапкой (ГК, период, версия, единицы, режим,
выбранные счета; для ALL — «Все балансовые счета») и строками разницы, дебета, кредита и процента расхождения для
каждой пары. Пара SHALL заливаться цветом порога, если exceeds_threshold или one_sided — так же, как в API.
Scenario: Экспорт выбранных счетов
- WHEN пользователь выгружает MANUAL для ГК «Русский бисквит» за 2024 Q1, версия 1
- THEN имя содержит
Русский бисквит_2024-Q1_v1.xlsx, шапка содержит выбранные счета, ячейки процента показывают два знака и символ%без повторного масштабирования
Scenario: Подсветка пары без встречной стороны
- WHEN выгружается ALL, у пары
amount_a = 100000000,amount_b = 0 - THEN все строки пары залиты цветом порога, в шапке «Режим» и «Счета дебета/кредита» — «Все балансовые счета»