arm-ka-docs/analyst/eliminations-vgo.md
Andrey Epifancev 68e944166b docs(#136): слияние main, OQ-169 этой ветки перенумерован в OQ-173
В main (#138) номера OQ-169…172 заняты вопросами ОСВ; пересечение счетов правил
элиминации — OQ-173 (закрыт решением владельца 19.10.2026).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 14:39:30 +04:00

28 KiB
Raw Blame History

Элиминация ВГО: правила, расчёт, корректировки

Документ для аналитика, 19.10.2026 (RSHB/arm-ka-docs#132; сопоставление — по решениям OQ-07 и OQ-173, #136). Основа — модель данных model/data-model-v5.19.dbml и правила предметной области context/05-domain-rules.md §3–§6, §8. Источник истины — они: при расхождении прав DBML и 05-domain-rules.md, а этот документ поправь следом. Где написано наше прочтение ТЗ, а не прямая цитата, это помечено; такие места собраны в раздел 6 вопросами.

Что нужно от аналитика: подтвердить разделы 1–4 (или поправить) и ответить на вопросы раздела 6. Ответы попадают в 05-domain-rules.md и 07-open-questions.md, затем — сюда.


1. Что хранится в БД, а что считается

Главный принцип модели (DECISION-5): производные консолидации не хранятся, пока версия в работе. Они каждый раз считаются заново из первички, периметра версии и правил. В БД лежат только исходные данные и ручные решения аналитика.

Хранится Что это
osv_entry строки ОСВ как пришли из файла + сопоставленный контрагент (counterparty_id, counterparty_match_kind)
consolidation_member, consolidation_document периметр версии и привязанные к ней документы
elimination_rule, elimination_rule_account правила элиминации Прил. 3 / Прил. 4 (раздел 2)
consolidation_version.elimination_rules_version по какой версии правил считалась версия консолидации
correction ручные корректировки аналитика (раздел 4)
goodwill гудвилл: доля владения, решение «учитывать в КФО», комментарий
kfo_result, kfo_result_line результат КФО
Не хранится, считается на лету Почему
сводная ОСВ, признак контрагента ГСК / ГК / Внешний функция от osv_entry и периметра версии
пары ВГО (кто с кем сопоставлен, по какому правилу, суммы сторон, расхождение, id строк ОСВ) функция от osv_entry × периметр × правила
шахматка функция от osv_entry × периметр × выбранный набор счетов
суммы «с учётом корректировок» сумма пары ± применённые корректировки

Таблиц сопоставления в модели нет: vgo_match (строки 1:1) убрана в v5.3 — её нет ни в ТЗ, ни в UI; агрегат vgo_pair_match убран в v5.10 по DECISION-5.

Заморозка. При переходе версии в VERIFIED всё посчитанное фиксируется один раз в ex_snapshot_item.payload (jsonb, item_type = vgo_pairs, chess, corrections, goodwill, kfo_balance, kfo_income, summary_osv). Срез самодостаточен и не ссылается на таблицы консолидации. Версия после VERIFIED — только чтение; изменения — через новую версию консолидации.


2. Как разложены правила элиминации

Правила — данные, а не код: две таблицы, версионируются.

2.1. elimination_rule — одна строка приложения

Поле Значение
statement_type balance — Прил. 3 (ББ), income — Прил. 4 (ОФР)
rule_no № строки приложения
article_1_line статья Компании 1 — код строки ББ/ОФР (например, 1230)
article_2_line статья Компании 2 (например, 1520)
side_1 сторона Компании 1: D или K (у Компании 2 — противоположная)
measure closing — сальдо на конец (ББ), turnover — оборот (ОФР)
elimination_mode min — min(A, B); full — вся сумма стороны А (выручка ОФР); manual — только вручную
vat_handling только ОФР: none / check_90_01_vs_2110 / weighted_rate
excise_adjust учитывать акциз
version_no, valid_from, valid_to версия набора правил; уникально (statement_type, rule_no, version_no)

2.2. elimination_rule_account — счета сторон правила

Поле Значение
rule_id правило
company_no 1 или 2 — сторона
account_id счёт или субсчёт из плана счетов (chart_of_account)
is_excluded true — исключение внутри маски («76 кроме 76.07.1»)

Счёт-родитель покрывает свои субсчета (иерархия chart_of_account.parent_id), исключения перечисляются отдельными строками с is_excluded = true.

Пример — правило № 6 ББ (основная пара «дебиторка ↔ кредиторка»):

company_no account is_excluded
1 60.02, 60.22, 60.32, 62.01, 62.03, 62.21, 62.31 false
1 76 false
1 76.07.5, 76.07.9 true
2 60.01, 60.03, 60.21, 60.31, 62.02, 62.22, 62.32 false
2 76 false
2 76.07.1 true

(каждый счёт — отдельная строка таблицы; в примере сгруппированы для краткости)

2.3. Версии правил

Правила меняются выпуском новой версии (version_no), старая не правится. Версия, по которой посчитана версия консолидации, фиксируется в consolidation_version.elimination_rules_version при первом расчёте и замораживается при VERIFIED — так расчёт верифицированной версии объясним и воспроизводим, даже если правила потом поменялись.

2.4. Стартовый набор — Прил. 3 (ББ, measure = closing)

№ Статья А (Дт) Счета А Статья Б (Кт) Счета Б mode Примечание
1 1150 ОС 03, 76.07.9 (01 — резервный) 1450 / 1550 76.07.1 manual лизинг/аренда внутри группы; у Б: 76.07.1 − 76.07.5 − 76.07.9
2 1170 ФВ долгосрочные 58.01 1310 / 1350 80, 83 manual гудвилл (раздел 4.5)
3 1170 ФВ долгосрочные 58.03 1410 Займы долгосрочные 67.03 min
4 1240 ФВ краткосрочные 58.03 1510 Займы краткосрочные 66.03 min
5 1230 Дебиторка 76 (кроме 76.07.5, 76.07.9) 1510 66.04, 67.04 min проценты
6 1230 Дебиторка 60.02, 60.22, 60.32, 62.01, 62.03, 62.21, 62.31, 76 (кроме 76.07.5, 76.07.9) 1520 Кредиторка 60.01, 60.03, 60.21, 60.31, 62.02, 62.22, 62.32, 76 (кроме 76.07.1) min основная пара
7 1230 Дебиторка те же, что № 6 1410 67 min
8 1230 Дебиторка те же, что № 6 1510 66 min

2.5. Прил. 4 (ОФР, measure = turnover) — не формализовано

Статья Сторона А Сторона Б mode / НДС
2110 Выручка Кт 90.01 (с НДС, приоритет) либо Дт 62.01/62.21/62.31 Кт 60.01/60.21/60.31 + 76 (кроме 76.07., 76.03., плюс 76.07.2) full; без НДС = с НДС / (1 + средневзвешенная ставка / 100)
2120 Себестоимость — — = ВГО по 2110, зеркально, без НДС
2310 Доходы от участия Дт 76.03 Кт 76.03 сторона А
2320 Проценты к получению Дт 76.03/76.05/76.08/76.09 Кт 66.02/.04/.06/.22/.24/.26, 67.02/.04/.06/.22/.24/.26 min
2330 Проценты к уплате Кт чётных субсчетов 66/67 + 76.07.5/76.08/76.28/76.38 Дт 76.03/.05/.08/.09 min

Это выжимка из FNR03; в правила-данные её можно превратить только после формализации с методологами (вопрос В-8).


3. Как считаем

3.1. Вход

  • Периметр — consolidation_member версии (не текущий состав ГСК).
  • ОСВ — документы, привязанные к версии (consolidation_document), только CONFIRMED.
  • Строки — group_type = COUNTERPARTY, data_type ∈ (BU, SUM), контрагент сопоставлен с ЮЛ из периметра.
  • Для ББ — только сальдо на конец (closing_debit / closing_credit).

3.2. Автоматическое сопоставление пар (DOC-223044, 05-domain-rules.md §5)

Единица расчёта — тройка (правило, компания A, компания B). Правила считаются для каждой упорядоченной пары компаний — и (A, B), и (B, A), поэтому зеркальные правила № 9–16 Прил. 3 отдельно не заводятся (№ 14 для (A, B) — это № 6 для (B, A)). У тройки два уровня (решения владельца 19.10.2026, OQ-07 и OQ-173):

Сумма элиминации — агрегат, идёт в КФО. Считается каскадом по остатку: правила пары (A, B) идут по порядку rule_no, каждое берёт min из того, что осталось после предыдущих правил:

для правил по возрастанию rule_no:
  ΣA = Σ остатка строк A с контрагентом B по счетам стороны 1 (с исключениями)
  ΣB = Σ остатка строк B с контрагентом A по счетам стороны 2
  deviation_amount = |ΣA − ΣB|; deviation_percent = deviation_amount / min(ΣA, ΣB) × 100
  элиминация = min(ΣA, ΣB) при расхождении ≤ 5 % (раздел 3.3); остатки сторон уменьшаются на неё

Зачем каскад: счета правил пересекаются (дебиторка у № 5–8 общая; 67.03 входит и в № 3, и в маску 67 у № 7; 66.03 — в № 4 и в № 8). По буквальным формулам Прил. 3 одна дебиторка элиминировалась бы несколько раз. Порядок rule_no в Прил. 3 уже идёт от частного к общему (№ 3/4 раньше № 7/8, № 5 раньше № 6, № 6 → 7 → 8), а сам принцип «списывать по очереди до обнуления» Прил. 3 задаёт в правиле № 1.

Пример: у A дебиторка на B 100; у B кредиторка на A 70 и долгосрочный заём (67) на A 50. Буквально: № 6 = 70, № 7 = 50, итого 120 — больше самой дебиторки. Каскадом: № 6 = 70, остаток A = 30; № 7 = min(30, 50) = 30; итого 100; 20 по 67 у B — расхождение, разбирается корректировкой.

Упаковка строк — какие строки ОСВ с какими сопоставлены (детализация и строки без пары). Правило охватывает несколько счетов, поэтому строки сопоставляются группами 1:1, 1:N, N:1; N:M нет, N ≤ 5. Выбирается минимальная упаковка — группа с меньшим числом строк: если сумму закрывают и «1 Дт ↔ 2 Кт», и «1 Дт ↔ 3 Кт», берётся 1:2.

правила пары — по возрастанию rule_no; строка, сопоставленная в раннем правиле, в следующих не участвует
для k = 2 … 6 (число строк группы: 1:1, затем 1:2 и 2:1, … до 1:5 и 5:1):
  кандидаты размера k из ещё не сопоставленных строк, закрывающие сумму:
    сначала точные, затем с расхождением ≤ 5 % к меньшей — по возрастанию расхождения
  группа без соперников → пара, её строки выбывают
  две и более группы с тем же k и тем же расхождением, делящие строку → на ручное (между правилами ничьей нет)
строки, не сопоставленные ни одним правилом → «без пары»

Способ упаковки сумму элиминации не меняет: в КФО идёт агрегат тройки.

Результат (структура в памяти, в БД не пишется): правило, компания A, компания B, ΣA, ΣB, расхождение; пары упаковки с id строк osv_entry обеих сторон; строки без пары.

3.3. Сколько элиминируется по тройке

Ситуация Что происходит
ΣA = ΣB элиминируется сумма
расхождение ≤ 5 % (к меньшей) элиминируется min(ΣA, ΣB)
расхождение > 5 % подсветка, автоматически не элиминируется, ждёт корректировки
нет второй стороны (ΣB = 0) элиминируется 0, строки — «без пары» (вопрос В-4)
правило с mode = manual (№ 1, № 2) автоматически не элиминируется, только корректировкой / гудвиллом

Суммы сторон — остатки после предыдущих правил пары (каскад, раздел 3.2), поэтому двойной элиминации по общим счетам нет.

Алгоритм — по ТЗ (решение владельца 08.10.2026, OQ-155): пары, min, порог 5 %. Эталонный Excel «Консолидация_Группа РБ» элиминирует у каждой компании полную сумму её строк на группу — это сознательное расхождение с эталоном.

Куда идёт сумма (наше прочтение — подтвердить, В-3): элиминируемая сумма тройки уменьшает статью article_1_line у Компании 1 и статью article_2_line у Компании 2.

3.4. Шахматка (DOC-221277, 05-domain-rules.md §6)

Шахматка — сверочный инструмент, она ничего не элиминирует. Строки и столбцы — компании периметра, диагональ пуста.

amount_a(A,B) = Σ closing_debit  строк A с контрагентом B по выбранным дебетовым счетам  (kind ∈ A, AP)
amount_b(A,B) = Σ closing_credit строк B с контрагентом A по выбранным кредитовым счетам (kind ∈ P, AP)
variance = |amount_a − amount_b|; variance_pct = variance / min(amount_a, amount_b) × 100; > 5 % — подсветка

Предустановки — наборы счетов: «58.03 vs 67.03 + 66.03», «60 + 62 + 76 vs 60 + 62 + 76», «все счета». Так решено 15.10.2026 и так сделано в arm-core (AURORA-1537): шахматка — по наборам счетов, а пары по правилам Прил. 3, элиминируемая сумма и версия правил — отдельная задача AURORA-1536 (§5). Шахматка по правилу элиминации — вопрос В-1.

Результирующая таблица «компания против группы» по статьям: Дебиторка, Кредиторка, ФВ, Долгосрочные займы, Краткосрочные займы; колонка «Итого по группе» (состав счетов — §6).

3.5. Путь до КФО (05-domain-rules.md §8)

По каждому коду строки ББ/ОФР:

sum_amount         = Σ по компаниям периметра (отчётная колонка ББ / ОФР, тыс. руб.)
eliminated_auto    = Σ сумм элиминации троек (3.2–3.3), в тыс. руб.
eliminated_manual  = Σ корректировок со статусом APPLIED
goodwill_adjust    = гудвилл, если «учитывать в КФО»
consolidated       = sum_amount − eliminated_auto − eliminated_manual ± goodwill_adjust
vgo_amount         = eliminated_auto + eliminated_manual

Единицы: ОСВ — рубли, ББ/ОФР — тыс. руб.; считаем в рублях, округляем до тыс. на выходе (допущение OQ-26, В-10). Пороги существенности (ТЗ 6.8): ББ — 1 % валюты баланса или 10 % ЧА; ОФР — 1 % выручки или 10 % валовой прибыли; превышение требует обоснования (threshold_justification).


4. Как производятся корректировки

4.1. Принцип

Корректировка — наложение поверх первички: строки ОСВ и формы не меняются, итог = свод первички − Σ применённых корректировок. Корректировка — единственное, что аналитик хранит по паре ВГО; сама пара не хранится.

4.2. Привязка к паре

Корректировка ссылается на пару по естественному ключу, а не на id строк ОСВ:

(consolidation_version_id, rule_id, legal_entity_id, counterparty_id) + statement_type

  • rule_id — правило; NULL — ручная корректировка без пары;
  • legal_entity_id — компания 1 (чья первичка корректируется);
  • counterparty_id — компания 2.

Благодаря этому корректировка переживает пересчёт: пары каждый раз строятся заново, а корректировка находит свою пару по ключу. Что делать, если пара после перезагрузки ОСВ исчезла, — вопрос В-6.

4.3. Поля correction

Поле Значение
statement_type ББ или ОФР (ТЗ 6.8 — отдельные формы)
debit_line_code, debit_account_id, debit_adjustment дебетовая сторона: строка формы, счёт, сумма
credit_line_code, credit_account_id, credit_adjustment кредитовая сторона
deviation_amount, deviation_percent расхождение пары — справочно, пересчитывается
reason_code ТЗ 6.4: нереализованная выручка, акциз, агентское вознаграждение, амортизация по внутригрупповой аренде, проценты по внутригрупповым займам, доходы от участия, прочее
comment обязателен (ТЗ 6.8)
status DRAFT → APPLIED / REVOKED; в расчёт входят только APPLIED
parent_correction_id распределение суммы одной стороны по нескольким статьям — дочерние записи, глубина 1
version_no растёт при каждом изменении

4.4. Правила

  • Контроль полноты: Σ debit_adjustment ≈ Σ credit_adjustment (±5 %), иначе ВГО распределено не полностью.
  • История: каждое изменение — audit_event(CORRECTION_*) со значениями до/после, version_no++ (сноска 22 ТЗ).
  • Кто и когда: право CONSOLIDATION_EDIT, версия «в работе», своя блокировка версии. После VERIFIED — только чтение.
  • Типичный сценарий: пара с расхождением > 5 % → аналитик разбирается в причине → создаёт корректировку по паре с причиной и комментарием → применяет (APPLIED) → КФО пересчитывается.

4.5. Гудвилл (правило № 2) — отдельно от корректировок

Таблица goodwill, по каждой паре ГО → ДО периметра: FV = Σ closing_debit 58.01 (контрагент ДО), UK = 1310 ББ ДО (FNR03: Кт 80 + Кт 83, при отсутствии — 1310), share — ручной ввод, participation = 1310 × share / 100, goodwill = FV − participation (может быть < 0), include_in_kfo + обязательный комментарий. Положительный итог — строка «Гудвилл» в разделе I КФО.


5. Сквозной пример: «Пекарня Счастливочная» ↔ «Русский бисквит», 30.09.2024

Данные — фикстуры, ОСВ Q3 2024. Строки Счастливочной с контрагентом «Русский бисквит» на дебетовых счетах правила № 6:

Счёт Аналитика Сумма, руб.
62.01 «БП Производство» 106 311 116,46
62.01 «БП Аренда» 1 401 330,00
76.06 350 000,00
76.АВ НДС по авансам 2 366 666,69

У «Русского бисквита» — одна строка 60.01 (кредиторка) на Счастливочную: 106 311 116,46.

Упаковка: 62.01 «БП Производство» 106 311 116,46 ↔ 60.01 РБ 106 311 116,46 — точная пара 1:1 (минимальная упаковка; вариант 2:1 «БП Производство + БП Аренда» = 107 712 446,46, расхождение 1,32 %, больше по числу строк и не выбирается). 62.01 «БП Аренда», 76.06, 76.АВ — без пары.

Сумма элиминации (правило № 6): ΣA = 110 429 113,15, ΣB = 106 311 116,46, расхождение 3,87 % ≤ 5 % → элиминируется min = 106 311 116,46: статья 1230 у Счастливочной, 1520 у РБ. Это при условии, что у РБ нет 66.04 / 67.04 на Счастливочную: иначе по каскаду 76.06 и 76.АВ сначала уйдут в правило № 5, и ΣA правила № 6 уменьшится.

76.АВ (НДС по авансам) сейчас входит в дебиторку по правилу «76 кроме 76.07.5/76.07.9». Эталон его исключает — вопрос OQ-164 (В-9).

Эталон («Консолидация_Группа РБ.xlsx», лист 01.10.2024) элиминирует у Счастливочной 108 062 тыс. — всё, кроме 76.АВ. Разница с нашим расчётом (1 751 тыс. = 1 401 330 + 350 000) — ожидаемая (OQ-155).


6. Вопросы к аналитику

№ Вопрос Что сейчас
В-1 Шахматка: предустановки — наборы счетов (§6) или правила элиминации? Если правила — как быть с «58.03 vs 67.03 + 66.03» (это правила № 3 и № 4 сразу) и «все счета» (не правило)? решено 15.10: наборы счетов, сделано (AURORA-1537); правила — в сопоставлении пар (AURORA-1536)
В-2 Сопоставление строго 1:1 по строкам или с агрегацией? решено 19.10.2026 (OQ-07): агрегат тройки в КФО, упаковка 1:1 / 1:N / N:1 — минимальная (раздел 3.2)
В-3 Элиминация списывается со статей article_1_line / article_2_line правила? Как выбирать статью у правил с двумя статьями: «1450 / 1550» (№ 1), «1310 / 1350» (№ 2)? наше прочтение, не подтверждено
В-4 Строка без встречной стороны (у второй компании нет строки на первую): не элиминируется до корректировки, элиминируется целиком или показывается как отдельная категория? в упаковке — «без пары»; в сумме тройки элиминируется 0, если ΣB = 0
В-5 Корректировка по паре добавляется к автоматической элиминации или заменяет её? Как проводится корректировка «односторонней» пары, если контроль требует Σ Дт ≈ Σ Кт (±5 %)? по §8: добавляется (eliminated_manual отдельно от eliminated_auto)
В-6 Пара исчезла после перезагрузки ОСВ (суммы изменились, пара не собралась) — что с её корректировками: остаются, помечаются, снимаются? не описано
В-7 Средневзвешенная ставка НДС для выручки ОФР: ставка считается из ОСВ (по какому правилу) или вводится вручную? Хранить её негде: в модели она жила в vgo_pair_match, убранной в v5.10 не описано
В-8 Правила ОФР (Прил. 4): нужна формализация с методологами — счета сторон, режимы, НДС, акциз открыто
В-9 76.АВ / 76.ВА (НДС по авансам) — исключать из ДЗ / КЗ? Есть ли ещё такие субсчета 76? OQ-164 открыт, вопрос в AURORA-1373
В-10 Округление при элиминации: рубли → тыс. руб. на выходе, ROUND_HALF_UP? допущение OQ-26
В-11 Правило № 1: если у компании А нет ОСВ по 03 — результат в строку «ППА»? открыто в §4
В-12 Счета правил пересекаются — как избежать двойной элиминации? решено 19.10.2026 (OQ-173): каскад по остатку в порядке rule_no (раздел 3.2)