merge: влить origin/main в feat/202-quality-metrics-dbml
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
75f5b52cd4
@ -828,7 +828,8 @@ one_sided = ровно одна из amount_a, amount_b равна 0 (знак
|
|||||||
`1200 = 1210 + 1220 + 1230 + 1240 + 1250 + 1260`; `1300 = 1310 + 1320 + 1340 + 1350 + 1360 + 1370`;
|
`1200 = 1210 + 1220 + 1230 + 1240 + 1250 + 1260`; `1300 = 1310 + 1320 + 1340 + 1350 + 1360 + 1370`;
|
||||||
`1400 = 1410 + 1420 + 1430 + 1450`; `1500 = 1510 + 1520 + 1540 + 1550`; `1600 = 1100 + 1200`; `1700 = 1300 + 1400 + 1500`.
|
`1400 = 1410 + 1420 + 1430 + 1450`; `1500 = 1510 + 1520 + 1540 + 1550`; `1600 = 1100 + 1200`; `1700 = 1300 + 1400 + 1500`.
|
||||||
ОФР: `2100 = 2110 − 2120`; `2200 = 2100 − 2210 − 2220`; `2300 = 2200 + 2310 + 2320 − 2330 + 2340 − 2350`;
|
ОФР: `2100 = 2110 − 2120`; `2200 = 2100 − 2210 − 2220`; `2300 = 2200 + 2310 + 2320 − 2330 + 2340 − 2350`;
|
||||||
`2400 = 2300 − 2410 + 2420` (знаки 2410/2420/2430 — по ФСБУ 4/2023 уточнить [открыто]).
|
`2400 = 2300 − 2410 + 2420` или `2400 = 2300 + 2410 + 2460` (знак 2410 не определяется — см. группу альтернатив ниже;
|
||||||
|
знаки 2420/2430 по ФСБУ 4/2023 — OQ-12 [открыто]).
|
||||||
Межформенная: `1370(отчётная дата) − 1370(начало года) = 2400(ОФР за период)` — при расхождении КА может акцептовать
|
Межформенная: `1370(отчётная дата) − 1370(начало года) = 2400(ОФР за период)` — при расхождении КА может акцептовать
|
||||||
с комментарием (`financial_statement_meta.checks_accepted_*`).
|
с комментарием (`financial_statement_meta.checks_accepted_*`).
|
||||||
|
|
||||||
@ -839,9 +840,9 @@ one_sided = ровно одна из amount_a, amount_b равна 0 (знак
|
|||||||
пересчитывает тем же кодом только после правок аналитика; своей копии словаря у ядра нет. Правила счёта:
|
пересчитывает тем же кодом только после правок аналитика; своей копии словаря у ядра нет. Правила счёта:
|
||||||
|
|
||||||
- **Жёсткие** (нарушение → `needs_check`): ББ — `1100`, `1200` (+1215), `1300`, `1400`, `1500`, `1600 = 1100 + 1200`,
|
- **Жёсткие** (нарушение → `needs_check`): ББ — `1100`, `1200` (+1215), `1300`, `1400`, `1500`, `1600 = 1100 + 1200`,
|
||||||
`1700 = 1300 + 1400 + 1500`, `1600 = 1700`; ОФР — `2100`, `2200`, `2300`. **Мягкие** (`info`, `ASSUMPTION(OQ-12)`): `2400 =
|
`1700 = 1300 + 1400 + 1500`, `1600 = 1700`; ОФР — `2100`, `2200`, `2300`. **Мягкие** (`info`): `2400 =
|
||||||
2300 − 2410 + 2420` и варианты ФСБУ 4/2023 (`2400 = 2300 + 2410 + 2460`, `2410 = 2411 + 2412`), `2500 = 2400 + 2510 +
|
2300 − 2410 + 2420` и `2400 = 2300 + 2410 + 2460` (группа альтернатив, ниже), `2410 = 2411 + 2412`, `2500 = 2400 +
|
||||||
2520 + 2530`, «сумма пятизначных подстрок = родитель» (по колонке — только если хотя бы одна подстрока родителя в ней
|
2510 + 2520 + 2530`, «сумма пятизначных подстрок = родитель» (по колонке — только если хотя бы одна подстрока родителя в ней
|
||||||
непуста: `amount` не `null`, ноль — значение; AURORA-1527). Мягкое соотношение на статус и подсветку не влияет, но
|
непуста: `amount` не `null`, ноль — значение; AURORA-1527). Мягкое соотношение на статус и подсветку не влияет, но
|
||||||
**сошедшееся точно** (расхождение в пределах допуска ±1, без «округления») подтверждает неуверенные значения своих
|
**сошедшееся точно** (расхождение в пределах допуска ±1, без «округления») подтверждает неуверенные значения своих
|
||||||
кодов (Р-21, §11.9): так покрываются 2400, 2410, 2411, 2412, 2460, 25xx и пятизначные подстроки.
|
кодов (Р-21, §11.9): так покрываются 2400, 2410, 2411, 2412, 2460, 25xx и пятизначные подстроки.
|
||||||
@ -862,12 +863,21 @@ one_sided = ровно одна из amount_a, amount_b равна 0 (знак
|
|||||||
с этими членами по модулю (1С выгружает расходы со знаком минус, 66н — в скобках). Такое соотношение сходится при
|
с этими членами по модулю (1С выгружает расходы со знаком минус, 66н — в скобках). Такое соотношение сходится при
|
||||||
любом знаке члена и потому **подтверждает величину, но не знак**: знак сомнительной ячейки подтверждается конвенцией
|
любом знаке члена и потому **подтверждает величину, но не знак**: знак сомнительной ячейки подтверждается конвенцией
|
||||||
колонки (§11.9).
|
колонки (§11.9).
|
||||||
|
- **Группа альтернатив** (`group` в `statement_checks.yaml`; AURORA-1864, решение владельца 27.10.2026). Мягкие
|
||||||
|
соотношения одной цели одной формы и варианта могут быть альтернативами: в колонке сошлась хоть одна — нарушений
|
||||||
|
группы нет; не сошлась ни одна — в `soft_relations_failed` одно нарушение, ближайшая к цели альтернатива (при пустой
|
||||||
|
цели или пустых членах — первая по словарю). `group` только у мягких и с одной целью — иначе словарь не загружается.
|
||||||
|
Группы — соотношения 2400 обоих наборов: **знак 2410 не определяется**, принимается любой вариант (расход —
|
||||||
|
`2300 − 2410`, со знаком минус, в скобках или без знака; доход по налогу ФСБУ 4/2023 — `2300 + 2410`). Жёсткие
|
||||||
|
проверки, подсветка, `needs_check` и подтверждение значений (Р-21) группой не меняются; каждая альтернатива
|
||||||
|
подтверждает свои коды, как отдельное мягкое соотношение. Формула старого бланка с 2430/2450 не добавляется.
|
||||||
- **Упрощённый набор.** Набор выбирается по `form_variant` документа (§11.7): у упрощённой формы нет подытогов 1100 /
|
- **Упрощённый набор.** Набор выбирается по `form_variant` документа (§11.7): у упрощённой формы нет подытогов 1100 /
|
||||||
1200 (ББ) и 2100 / 2200 / 2300 (ОФР), свои равенства по бланку упрощённой формы (приказ 66н, прил. 5;
|
1200 (ББ) и 2100 / 2200 / 2300 (ОФР), свои равенства по бланку упрощённой формы (приказ 66н, прил. 5;
|
||||||
`ASSUMPTION` до первого образца в fixtures): ББ — `1600 = 1150 + 1170 + 1210 + 1230 + 1250` (жёсткое), `1700 = 1300 +
|
`ASSUMPTION` до первого образца в fixtures): ББ — `1600 = 1150 + 1170 + 1210 + 1230 + 1250` (жёсткое), `1700 = 1300 +
|
||||||
1350 + 1360 + 1410 + 1450 + 1510 + 1520 + 1550` (жёсткое), `1600 = 1700` (жёсткое); ОФР — `2400 = 2110 − 2120 − 2330 +
|
1350 + 1360 + 1410 + 1450 + 1510 + 1520 + 1550` (жёсткое), `1600 = 1700` (жёсткое); ОФР — `2400 = 2110 − 2120 − 2330 +
|
||||||
2340 − 2350 − 2410` (**мягкое**, как `2400` полного набора: знак 2410 не определён, OQ-12; `abs_terms` те же; решение
|
2340 − 2350 − 2410` и `2400 = 2110 − 2120 − 2330 + 2340 − 2350 + 2410` (**мягкие**, группа альтернатив, как `2400`
|
||||||
владельца 18.10.2026, Р-22 / S-5). Оба набора — в одном словаре `statement_checks.yaml`. Без упрощённого набора полный
|
полного набора; `abs_terms` — 2120, 2330, 2350, у первого ещё 2410; решение владельца 18.10.2026, Р-22 / S-5;
|
||||||
|
вторая альтернатива — AURORA-1864). Оба набора — в одном словаре `statement_checks.yaml`. Без упрощённого набора полный
|
||||||
дал бы нарушения «пустой цели» на каждой упрощённой форме. `form_variant = null` (документ, оставшийся в БД с времён до
|
дал бы нарушения «пустой цели» на каждой упрощённой форме. `form_variant = null` (документ, оставшийся в БД с времён до
|
||||||
v5.19, если база не очищена) — полный набор; у результата 1.x вариант определяется по структуре кодов при приёме.
|
v5.19, если база не очищена) — полный набор; у результата 1.x вариант определяется по структуре кодов при приёме.
|
||||||
- **Родитель пятизначной подстроки** — ближайшая четырёхзначная строка выше с теми же первыми тремя цифрами, иначе код
|
- **Родитель пятизначной подстроки** — ближайшая четырёхзначная строка выше с теми же первыми тремя цифрами, иначе код
|
||||||
@ -951,11 +961,31 @@ OQ-145); тем же правилом сервисы разрешают ничь
|
|||||||
409 `CORRECTION_VERSION_CONFLICT`, кто-то сохранил раньше, фронт перечитывает таблицу.
|
409 `CORRECTION_VERSION_CONFLICT`, кто-то сохранил раньше, фронт перечитывает таблицу.
|
||||||
- История — `audit_event(CORRECTION_CREATE`/`CORRECTION_EDIT)`, `before`/`after`, `version_no++` при каждом сохранении.
|
- История — `audit_event(CORRECTION_CREATE`/`CORRECTION_EDIT)`, `before`/`after`, `version_no++` при каждом сохранении.
|
||||||
|
|
||||||
**Гудвилл** (DOC-259025, ТЗ 6.7): по каждой паре ГО→ДО периметра:
|
**Гудвилл** (DOC-259025 «Гудвилл», версия 03.11.2026; ТЗ 6.7; AURORA-1543/1544, реализовано — `arm-core#222/#220`,
|
||||||
`FV = Σ closing_debit (58.01, контрагент ДО)`; `UK = 1310 ББ ДО на отчётную дату` (FNR03: Кт 80 + Кт 83, при
|
контракт `dev/api-contract-goodwill.md`). Единица — направленная пара ГО → ДО версии:
|
||||||
отсутствии — 1310); `share` — ручной ввод; `participation = (1310 [+ 1350?]) × share / 100`;
|
|
||||||
`goodwill = FV − participation` (может быть < 0); `include_in_kfo` + комментарий обязателен. Положительный итог —
|
- **Пары.** ГО — владелец строк ОСВ счёта `58.01` и его потомков (`chart_of_account.parent_id`) в сводной ОСВ версии
|
||||||
строка `GOODWILL` в разделе I КФО.
|
(общие правила §2–§3: выбор источников, периоды, дорезолв), ДО — сопоставленный контрагент этих строк из периметра.
|
||||||
|
`is_head_entity` не используется; встречные направления — разные пары; пустой контрагент, вложение в себя и
|
||||||
|
контрагент вне периметра пары не дают. `ФВ = Σ closing_debit` заполненных строк пары, пара есть при `ФВ ≠ 0`.
|
||||||
|
- **«Нет вложений».** Сохранённая пара, которая больше не находится (замена ОСВ, нулевое сальдо, выход из периметра),
|
||||||
|
остаётся строкой таблицы с ручным вводом, но без сумм, вне итогов и КФО; вернулась — расчёт по текущим данным.
|
||||||
|
- **УК** — стр. `1310` подтверждённого ББ ДО, привязанного к версии, по колонке конца отчётного квартала (не по
|
||||||
|
`is_current`), повторы кода суммируются, единицы формы — словарём единиц `arm_statements`, в рублях. Нет
|
||||||
|
однозначного ББ/строки/колонки — УК не рассчитан (`null`, предупреждение), а не 0. **1350 в базу не входит**
|
||||||
|
(ASSUMPTION OQ-10 по DOC-259025 §6), хранится справочно.
|
||||||
|
- **Ввод.** Доля владения `d` — 0–100 %, не больше **двух** знаков (лишние — ошибка, не округление); галочка «Учёт в
|
||||||
|
отчёте» (`include_in_kfo`); у отмеченной действующей строки обязательны доля и комментарий. Снятие галочки ввод не
|
||||||
|
стирает. Сохранение — набором строк в одной транзакции; строки без изменений не перезаписываются.
|
||||||
|
- **Формулы** (только у действующей отмеченной строки с долей и УК, иначе не рассчитано): `P = round(УК × d / 100, 2)`
|
||||||
|
(`ROUND_HALF_UP`), `G = ФВ − P` (может быть < 0 и = 0).
|
||||||
|
- **Итоги** блока ГО и листа: ФВ и УК — все действующие строки независимо от галочки; P и G — отмеченные (отрицательные
|
||||||
|
тоже); в КФО — `Σ G > 0` строк, где `use_goodwill` = действующая ∧ отмечена ∧ доля и комментарий заполнены ∧ `G > 0`, и
|
||||||
|
только при `consolidation_version.goodwill_enabled` (переключатель на вкладке, OQ-27). Доли в итогах не складываются;
|
||||||
|
сумма заполненных долей разных ГО в одной ДО > 100 % — предупреждение, не ошибка.
|
||||||
|
- **КФО** (AURORA-1546, ещё не реализовано): для пары с `use_goodwill` — ГО `1170 − ФВ`, ДО `1310 − P`, ГО строка
|
||||||
|
`GOODWILL` `+ G` (служебный код, ASSUMPTION OQ-37), обычный ББ-2 по этой паре не применяется; при `G ≤ 0` — обычный
|
||||||
|
ББ-2, разница в 1370 не переносится. Изменение ввода, переключателя или источников делает результат КФО устаревшим.
|
||||||
|
|
||||||
**КФО** (ТЗ 6.4, Прил. 10): по каждому коду строки ББ/ОФР:
|
**КФО** (ТЗ 6.4, Прил. 10): по каждому коду строки ББ/ОФР:
|
||||||
`sum_amount = Σ по компаниям` (значения отчётной колонки ББ / ОФР за период, в тыс. руб.) →
|
`sum_amount = Σ по компаниям` (значения отчётной колонки ББ / ОФР за период, в тыс. руб.) →
|
||||||
|
|||||||
@ -15,9 +15,9 @@
|
|||||||
| OQ-07 | Матчинг ВГО: одна строка = одна позиция (DOC-223044) или агрегировать по (компания, контрагент, счёт) (FNR03)? | DOC-223044 vs FNR03 | срез 5 | **закрыт решением владельца 19.10.2026 (docs #136):** внутри тройки «правило × компания A × компания B» строки сопоставляются группами **1:1, 1:N, N:1** (правило охватывает несколько счетов), N:M нет; выбирается **минимальная упаковка** — меньше строк (закрывается и 1:2, и 1:3 → 1:2); закрытие — точно или ≤ 5 % к меньшей; N ≤ 5; ничья → ручное. Упаковка — детализация; в КФО — агрегат min(ΣA, ΣB) по тройке, на него способ упаковки не влияет. Алгоритм — `05-domain-rules.md` §5 |
|
| OQ-07 | Матчинг ВГО: одна строка = одна позиция (DOC-223044) или агрегировать по (компания, контрагент, счёт) (FNR03)? | DOC-223044 vs FNR03 | срез 5 | **закрыт решением владельца 19.10.2026 (docs #136):** внутри тройки «правило × компания A × компания B» строки сопоставляются группами **1:1, 1:N, N:1** (правило охватывает несколько счетов), N:M нет; выбирается **минимальная упаковка** — меньше строк (закрывается и 1:2, и 1:3 → 1:2); закрытие — точно или ≤ 5 % к меньшей; N ≤ 5; ничья → ручное. Упаковка — детализация; в КФО — агрегат min(ΣA, ΣB) по тройке, на него способ упаковки не влияет. Алгоритм — `05-domain-rules.md` §5 |
|
||||||
| OQ-08 | Знак порога 5 % в правиле пары (≤ или <), и к чему считать % — к меньшей сумме (Методика сноска 14) | FNR03 (знак потерян) | срез 5 | допущение: `≤ 5 %` к меньшей |
|
| OQ-08 | Знак порога 5 % в правиле пары (≤ или <), и к чему считать % — к меньшей сумме (Методика сноска 14) | FNR03 (знак потерян) | срез 5 | допущение: `≤ 5 %` к меньшей |
|
||||||
| OQ-09 | Правила элиминации ОФР (2110/2120/2310/2320/2330): точный состав субсчетов, источник средневзвешенной ставки НДС, выбор субсчетов «работником ПА самостоятельно» | FNR03 | срез 6 | не реализовывать авто-элиминацию ОФР до решения; только ручные `correction` |
|
| OQ-09 | Правила элиминации ОФР (2110/2120/2310/2320/2330): точный состав субсчетов, источник средневзвешенной ставки НДС, выбор субсчетов «работником ПА самостоятельно» | FNR03 | срез 6 | не реализовывать авто-элиминацию ОФР до решения; только ручные `correction` |
|
||||||
| OQ-10 | Гудвилл: входит ли стр. 1350 (добавочный капитал) в базу участия; УК из ББ (1310) или из ОСВ 80/83 | DBML, DOC-259025, FNR03 | срез 6 | допущение: 1310 из ББ; 1350 — настраиваемый флаг, по умолчанию выключен |
|
| OQ-10 | Гудвилл: входит ли стр. 1350 (добавочный капитал) в базу участия; УК из ББ (1310) или из ОСВ 80/83 | DBML, DOC-259025, FNR03 | срез 6 | допущение: 1310 из ББ; 1350 — настраиваемый флаг, по умолчанию выключен. **06.11:** DOC-259025 (Лысенко, 03.11) — «для УК используется 1310», 1350 в формулу не входит; так реализовано (arm-core #222), флага нет; подтверждение методологов (AURORA-1369) не получено |
|
||||||
| OQ-11 | Строка «ППА» в КФО (правило № 1, когда у А нет ОСВ 03) — что это и куда | FNR03 | срез 6 | не реализовывать |
|
| OQ-11 | Строка «ППА» в КФО (правило № 1, когда у А нет ОСВ 03) — что это и куда | FNR03 | срез 6 | не реализовывать |
|
||||||
| OQ-12 | Формулы ОФР: знаки 2410/2420/2430 по ФСБУ 4/2023 vs 66н; состав 1100 (1120–1140) | DOC-221281 | срез 3 | допущение: формулы §7, строки без значения = 0; **расширение 07.10.2026:** формулы и справочники по редакциям форм (`66n` / `fsbu4`) — OQ-146 |
|
| OQ-12 | Формулы ОФР: знаки 2410/2420/2430 по ФСБУ 4/2023 vs 66н; состав 1100 (1120–1140) | DOC-221281 | срез 3 | допущение: формулы §7, строки без значения = 0; **06.11.2026 закрыт в части 2410** (AURORA-1864, решение владельца 27.10.2026): знак 2410 не определяется, соотношения 2400 — группа альтернатив §7 (`2300 − 2410` и `2300 + 2410`); 2420/2430 и состав 1100 — открыты; **расширение 07.10.2026:** формулы и справочники по редакциям форм (`66n` / `fsbu4`) — OQ-146 |
|
||||||
| OQ-13 | `confidence` от ИС Сканирование — доли 0..1 или проценты 0..100; имя поля организации (`full_name` vs `form_name`) | FNR02 vs `aep_*.json` | срез 3 (scan-gateway) | **закрыт для scan-gateway (04.10.2026, по `aep_3.json`, `aep_6.json`):** `confidence` — числа 0–100 (не доли); название организации — `data_ocr.organization.form_name` (шумный OCR-текст), ИНН — `inn.form_name`, единицы — `units.form_name`, дата — `date.form_name` (в `aep_6.json` мусор); `full_name`/`inn.inn`/`units.measurement` из ТЗ в реальных файлах нет. Нормализация — Срез 3 |
|
| OQ-13 | `confidence` от ИС Сканирование — доли 0..1 или проценты 0..100; имя поля организации (`full_name` vs `form_name`) | FNR02 vs `aep_*.json` | срез 3 (scan-gateway) | **закрыт для scan-gateway (04.10.2026, по `aep_3.json`, `aep_6.json`):** `confidence` — числа 0–100 (не доли); название организации — `data_ocr.organization.form_name` (шумный OCR-текст), ИНН — `inn.form_name`, единицы — `units.form_name`, дата — `date.form_name` (в `aep_6.json` мусор); `full_name`/`inn.inn`/`units.measurement` из ТЗ в реальных файлах нет. Нормализация — Срез 3 |
|
||||||
| OQ-14 | `reporting_date` в JSON ИС Сканирование — «ждём обновлённый JSON» | FNR01 | срез 3 | **уточнено (04.10.2026):** отдельного поля `reporting_date` в ответе нет; `date.form_name` ненадёжен (в `aep_6.json` — «Общество с ограниченной ответственностью», в `aep_3.json` — «2\|0\|2\|4\|»); даты колонок — в строке-шапке `rows[0]` таблицы («На 30 июня 2025 г» в `aep_6.json`), в `aep_3.json` шапки нет. Допущение прежнее: парсить из шапки таблицы, при её отсутствии — `NEEDS_CHECK`; решение — Срез 3 |
|
| OQ-14 | `reporting_date` в JSON ИС Сканирование — «ждём обновлённый JSON» | FNR01 | срез 3 | **уточнено (04.10.2026):** отдельного поля `reporting_date` в ответе нет; `date.form_name` ненадёжен (в `aep_6.json` — «Общество с ограниченной ответственностью», в `aep_3.json` — «2\|0\|2\|4\|»); даты колонок — в строке-шапке `rows[0]` таблицы («На 30 июня 2025 г» в `aep_6.json`), в `aep_3.json` шапки нет. Допущение прежнее: парсить из шапки таблицы, при её отсутствии — `NEEDS_CHECK`; решение — Срез 3 |
|
||||||
| OQ-15 | Таймаут OCR 5 мин / 0 повторов (ТЗ 3) vs outbox с повторами (DBML) | DOC-037736 | срез 3 | решено DBML: `max_attempts` OCR = 1, парсер = 3 |
|
| OQ-15 | Таймаут OCR 5 мин / 0 повторов (ТЗ 3) vs outbox с повторами (DBML) | DOC-037736 | срез 3 | решено DBML: `max_attempts` OCR = 1, парсер = 3 |
|
||||||
@ -42,7 +42,7 @@
|
|||||||
| OQ-34 | «Удалить» ГСК в меню строки (`77-01`): физическое удаление или закрытие с историей? В DBML у `related_group` нет флага/истории удаления | макет [77-01] | срез 1 | **закрыт реализацией Среза 1 (ASSUMPTION подтверждено отсутствием возражений):** удаляется только пустая ГСК/ГСЗ (409 `GROUP_NOT_EMPTY`), состав сохраняется в `before_value` аудита; группа с FK из консолидаций — follow-up `GROUP_IN_USE` (arm-core#8, T8.1) |
|
| OQ-34 | «Удалить» ГСК в меню строки (`77-01`): физическое удаление или закрытие с историей? В DBML у `related_group` нет флага/истории удаления | макет [77-01] | срез 1 | **закрыт реализацией Среза 1 (ASSUMPTION подтверждено отсутствием возражений):** удаляется только пустая ГСК/ГСЗ (409 `GROUP_NOT_EMPTY`), состав сохраняется в `before_value` аудита; группа с FK из консолидаций — follow-up `GROUP_IN_USE` (arm-core#8, T8.1) |
|
||||||
| OQ-35 | База процента отклонения: в таблице корректировки % считается к сумме стороны ЮЛ-1 (−79,77 % для 1 000 ↔ 202,32, `31-02-02`), в «Подтверждении КФО клиента» — к версии банка (ст. 2, `31-06`); DBML и Методика (сноска 14) — к **меньшей** сумме. Что считать правильным для `correction.deviation_percent` и `client_kfo_line.deviation_percent`? | макет [31-02] [31-06] vs DBML, Методика | срезы 5–6 | допущение: к меньшей (Методика); макет считать неточным |
|
| OQ-35 | База процента отклонения: в таблице корректировки % считается к сумме стороны ЮЛ-1 (−79,77 % для 1 000 ↔ 202,32, `31-02-02`), в «Подтверждении КФО клиента» — к версии банка (ст. 2, `31-06`); DBML и Методика (сноска 14) — к **меньшей** сумме. Что считать правильным для `correction.deviation_percent` и `client_kfo_line.deviation_percent`? | макет [31-02] [31-06] vs DBML, Методика | срезы 5–6 | допущение: к меньшей (Методика); макет считать неточным |
|
||||||
| OQ-36 | Экран проверки показывает строки формы **без кода** («в том числе: Основные средства, пригодные к использованию…», `41`); DBML хранит только строки с кодом (`financial_statement_line`), контракт требует `line_code`. Хранить ли расшифровочные строки без кода (и как их показывать)? | макет [41] vs DBML, контракт | срез 3, контракт v1.x | допущение: строки без кода не хранить и не показывать в первой очереди; **Срез 3b: допущение реализовано** — `financial_statement_line` пишется только для строк с кодом (строк без кода в результате нет), экран их не получает. **Закрыт решением владельца 17.10.2026 (Р-8, change `unified-statement-normalization`, контракт v2.0):** строки без кода отдаются сервисами со статусом `detail` (расшифровка под строкой с кодом), `missing` или `unreadable`, хранятся ядром (`financial_statement_line.line_status`, `line_code` nullable, DBML v5.19); в проверки §7, агрегаты и `done` `detail` не входит; экран по умолчанию прячет расшифровки под переключателем «Показать расшифровки (N)». Правила — `05-domain-rules.md` §11.4. Действует с переходом сервисов на v2.0 |
|
| OQ-36 | Экран проверки показывает строки формы **без кода** («в том числе: Основные средства, пригодные к использованию…», `41`); DBML хранит только строки с кодом (`financial_statement_line`), контракт требует `line_code`. Хранить ли расшифровочные строки без кода (и как их показывать)? | макет [41] vs DBML, контракт | срез 3, контракт v1.x | допущение: строки без кода не хранить и не показывать в первой очереди; **Срез 3b: допущение реализовано** — `financial_statement_line` пишется только для строк с кодом (строк без кода в результате нет), экран их не получает. **Закрыт решением владельца 17.10.2026 (Р-8, change `unified-statement-normalization`, контракт v2.0):** строки без кода отдаются сервисами со статусом `detail` (расшифровка под строкой с кодом), `missing` или `unreadable`, хранятся ядром (`financial_statement_line.line_status`, `line_code` nullable, DBML v5.19); в проверки §7, агрегаты и `done` `detail` не входит; экран по умолчанию прячет расшифровки под переключателем «Показать расшифровки (N)». Правила — `05-domain-rules.md` §11.4. Действует с переходом сервисов на v2.0 |
|
||||||
| OQ-37 | Строка «Гудвилл 1105» (ФСБУ 4/2023) в распознанной форме (`41`) vs строка `kfo_result_line.line_code = 'GOODWILL'` в разделе I КФО: использовать код 1105 или служебный GOODWILL? Влияет на шаблон строк на фронте и на формулы §7 (1100 = … + 1105?) | макет [41], ФСБУ 4/2023 | срез 3, 6 | допущение: хранить код 1105 как пришёл; строка КФО «GOODWILL» — отдельная, уточнить у методологов |
|
| OQ-37 | Строка «Гудвилл 1105» (ФСБУ 4/2023) в распознанной форме (`41`) vs строка `kfo_result_line.line_code = 'GOODWILL'` в разделе I КФО: использовать код 1105 или служебный GOODWILL? Влияет на шаблон строк на фронте и на формулы §7 (1100 = … + 1105?) | макет [41], ФСБУ 4/2023 | срез 3, 6 | допущение: хранить код 1105 как пришёл; строка КФО «GOODWILL» — отдельная, уточнить у методологов. **06.11:** DOC-259025 §7 — технический `line_code = GOODWILL` отдельной строкой раздела I; применение — AURORA-1546 |
|
||||||
| OQ-38 | ЕХ в макете показывает и **неверифицированные** консолидации («Консолидация 2025 К4», без даты верификации, `62` [83-01]); ЕХ ТЗ 6.2 — срез пишется только после «Верифицирован». Показывать ли в ЛК ЕХ незавершённые консолидации (как «в работе») или только `ex_snapshot`? | макет [62] [83-01] vs ЕХ ТЗ 6.2 | срез 7 | допущение: только срезы `ex_snapshot`; незавершённые — в разделе «Отчётность» |
|
| OQ-38 | ЕХ в макете показывает и **неверифицированные** консолидации («Консолидация 2025 К4», без даты верификации, `62` [83-01]); ЕХ ТЗ 6.2 — срез пишется только после «Верифицирован». Показывать ли в ЛК ЕХ незавершённые консолидации (как «в работе») или только `ex_snapshot`? | макет [62] [83-01] vs ЕХ ТЗ 6.2 | срез 7 | допущение: только срезы `ex_snapshot`; незавершённые — в разделе «Отчётность» |
|
||||||
| OQ-39 | Состав «сформированной отчётности» в ЕХ (`83-01`): КФО .xlsx, Шахматка .xlsx и «Консолидированная отчетность .pdf» с датой «Сформирован» и подписями Утвердил/Верифицировал. Нужен ли PDF-экспорт КФО и какие ещё артефакты (сводная ОСВ, корректировки, гудвилл — ЕХ ТЗ 5.2) показывать? | макет [83-01] vs ЕХ ТЗ 5.2 | срез 7 | допущение: xlsx из `payload` на лету для всех `item_type`; PDF — не делать до решения |
|
| OQ-39 | Состав «сформированной отчётности» в ЕХ (`83-01`): КФО .xlsx, Шахматка .xlsx и «Консолидированная отчетность .pdf» с датой «Сформирован» и подписями Утвердил/Верифицировал. Нужен ли PDF-экспорт КФО и какие ещё артефакты (сводная ОСВ, корректировки, гудвилл — ЕХ ТЗ 5.2) показывать? | макет [83-01] vs ЕХ ТЗ 5.2 | срез 7 | допущение: xlsx из `payload` на лету для всех `item_type`; PDF — не делать до решения |
|
||||||
| OQ-40 | «Квартальная дата» в журнале для консолидации 2024 К1 показана как 01.01.2024 (`43-02`); по правилам банка 1 квартал 2024 = отчётная дата 01.04.2024 (`consolidation.reporting_date`). Что выводить? | макет [43-02] | срез 4, 7 | **допущение принято и реализовано в Срезе 4 (06.10.2026):** `consolidation.reporting_date` по правилу банка (Q1 → 01.04.Y, Q2 → 01.07.Y, Q3 → 01.10.Y, Q4 → 01.01.Y+1), `domain/consolidation_periods.reporting_date`; макет неточен |
|
| OQ-40 | «Квартальная дата» в журнале для консолидации 2024 К1 показана как 01.01.2024 (`43-02`); по правилам банка 1 квартал 2024 = отчётная дата 01.04.2024 (`consolidation.reporting_date`). Что выводить? | макет [43-02] | срез 4, 7 | **допущение принято и реализовано в Срезе 4 (06.10.2026):** `consolidation.reporting_date` по правилу банка (Q1 → 01.04.Y, Q2 → 01.07.Y, Q3 → 01.10.Y, Q4 → 01.01.Y+1), `domain/consolidation_periods.reporting_date`; макет неточен |
|
||||||
|
|||||||
@ -1,160 +1,184 @@
|
|||||||
# Контракт API таблицы гудвилла (AURORA-1543 / AURORA-1544)
|
# Контракт API таблицы гудвилла (AURORA-1543 / AURORA-1544)
|
||||||
|
|
||||||
Черновик контракта для бэкенда (AURORA-1543, Цыганков) и фронта (AURORA-1544, Голов) — по аналогии с
|
Контракт таблицы гудвилла версии консолидации — по факту реализации arm-core (#222, OpenSpec change `goodwill-table`).
|
||||||
`dev/api-contract-corrections.md`: фронт строит экран по контракту на фейковых данных, не дожидаясь бэкенда, подключение
|
Машиночитаемая копия — `dev/api-contract-goodwill.openapi.yaml`: она выгружена из `app.openapi()` и сверяется с
|
||||||
к реальным ручкам — потом. Машиночитаемая копия — `dev/api-contract-goodwill.openapi.yaml`; при расхождении двух файлов
|
приложением тестом `arm-core/api/tests/test_goodwill_contract.py`. Если файлы расходятся, прав код, а оба файла
|
||||||
правится тот, что ошибся, и оба держатся одинаковыми.
|
правятся вслед за ним.
|
||||||
|
|
||||||
Источники, в порядке приоритета:
|
Источники, в порядке приоритета:
|
||||||
1. **AURORA-1369** (решение методологов, срок 02.11.2026) — формула ещё не подтверждена, см. §5 «Открытые вопросы». Пока
|
1. **DOC-259025 «Гудвилл»** (вики аналитики, версия 03.11.2026, Лысенко) — пары, жизненный цикл строк, формулы, итоги,
|
||||||
не закрыта, бэкенд не считает по-настоящему — но контракт (форма ответа, поля, эндпоинты) этим не затронут: методологи
|
проверки ввода.
|
||||||
могут поменять *формулу* (входит ли 1350, источник УК), а не *набор полей* (поля `charter_capital_amount` /
|
2. `05-domain-rules.md` §8 «Гудвилл» — выжимка того же с решениями по допущениям.
|
||||||
`additional_capital_amount` под обе ветки уже есть в DBML).
|
3. DBML v5.24: `Table goodwill`, `consolidation_version.goodwill_enabled`.
|
||||||
2. `05-domain-rules.md` §8 «Гудвилл» — текущий рабочий алгоритм (допущения OQ-10, OQ-37).
|
4. Макет `[31-03]` «Гудвилл» (таблица, режим «Редактировать»).
|
||||||
3. DBML v5.24, `Table goodwill`, `Table kfo_result_line` (`line_code = 'GOODWILL'`), `consolidation_version.goodwill_enabled`.
|
|
||||||
4. Макет: `[31-03]` «Гудвилл» (таблица, режим «Редактировать»), `[31-04]` «КФО» (строка «В т.ч. Гудвилл» под 1170).
|
|
||||||
5. ТЗ 6.7, Прил. 3 п. 2, Прил. 8 — только там, где остальное молчит.
|
|
||||||
|
|
||||||
## 1. Общее
|
## 1. Общее
|
||||||
|
|
||||||
Всё как в `dev/api-contract-slice-4.md` §1 и `dev/api-contract-corrections.md` §1:
|
Всё как в `dev/api-contract-slice-4.md` §1 и `dev/api-contract-corrections.md` §1:
|
||||||
- префикс `/api/v1`, `Authorization: Bearer <JWT>`;
|
- префикс `/api/v1`, `Authorization: Bearer <JWT>`;
|
||||||
- чтение — право `CONSOLIDATION_VIEW`, правки — `CONSOLIDATION_EDIT`;
|
- чтение и экспорт — право `CONSOLIDATION_VIEW`, правки — `CONSOLIDATION_EDIT`;
|
||||||
- версия вне видимости — 404 `NOT_FOUND`, как несуществующая;
|
- версия вне видимости — 404 `NOT_FOUND`, как несуществующая;
|
||||||
- доменные ошибки — `{"detail": {"code", "message", ...}}`, 422 валидации тела — массив pydantic;
|
- доменные ошибки — `{"detail": {"code", "message", ...}}`, 422 валидации тела — массив pydantic;
|
||||||
- **деньги — строки с двумя знаками** (`"1000000.00"`), всегда в **рублях**; перевод в тыс. руб. — на фронте;
|
- **деньги — строки с двумя знаками в рублях** (`"1000000.00"`) или `null`; `null` — «не рассчитано», а не ноль.
|
||||||
- порядок проверок правок: право (403) → видимость (404) → версия редактируема (409) → операция; коды — те же, что везде:
|
Перевод в тыс./млн руб. — на фронте, после суммирования;
|
||||||
409 `VERSION_NOT_EDITABLE`, `LOCK_REQUIRED`, `LOCKED_BY_OTHER`. Фронт читает `editable` / `read_only_reason` из ответа
|
- **доля владения — строка с двумя знаками** (`"80.00"`) или `null`;
|
||||||
таблицы, правило не повторяет.
|
- порядок проверок правок: право (403) → видимость (404) → версия редактируема (409 `VERSION_NOT_EDITABLE`,
|
||||||
|
`LOCK_REQUIRED`, `LOCKED_BY_OTHER`) → операция. Фронт берёт `editable` и `read_only_reason` из ответа таблицы и правило
|
||||||
|
сам не повторяет; у пользователя без `CONSOLIDATION_EDIT` — `read_only_reason = "VERSION_NOT_EDITABLE"`.
|
||||||
|
|
||||||
## 2. Понятия
|
## 2. Понятия
|
||||||
|
|
||||||
- **Головная организация периметра (ГО)** — член версии консолидации с `is_head_entity = true` (как в `VersionCard.members[]`,
|
- **Пара ГО → ДО.** ГО — компания периметра, у которой в сводной ОСВ версии есть строки счёта `58.01` или его потомков
|
||||||
`dev/api-contract-slice-4.md` §3). **Дочерняя организация (ДО)** — любой другой член периметра. Таблица гудвилла — по
|
(по `chart_of_account.parent_id`) с сопоставленным контрагентом из периметра; этот контрагент — ДО. Признак
|
||||||
одной строке на каждую пару (ГО, ДО); строки не создаются и не удаляются пользователем, их состав определяется
|
`is_head_entity` **не используется**: одна компания может быть ГО в одном блоке и ДО в другом, встречные направления —
|
||||||
составом периметра (`PUT …/members`) на момент запроса. **Если в периметре несколько `is_head_entity`** — строки
|
разные пары. Пустой контрагент, вложение в себя и контрагент вне периметра пару не дают. Ручного добавления пар нет.
|
||||||
считаются для каждой ГО отдельно (как для независимых голов); на реальных данных такого пока не встречалось —
|
- **Финансовые вложения (`financial_investment_amount`, ФВ)** — сумма заполненных `closing_debit` подходящих строк
|
||||||
ASSUMPTION, уточнить при первом расхождении.
|
пары; ФВ = 0 — пары нет.
|
||||||
- **Фондовые вложения (`financial_investment_amount`, FV)** — `Σ closing_debit` счёта `58.01` ГО по контрагенту ДО
|
- **«Нет вложений» (`has_investments = false`).** Сохранённая пара, которая больше не находится (замена ОСВ, нулевое
|
||||||
(сводная ОСВ версии). Может быть `0.00` — строка всё равно показывается (полный список ДО периметра под каждой ГО,
|
сальдо, компания вышла из периметра). Строка остаётся с сохранёнными долей, комментарием и галочкой, все денежные поля
|
||||||
как в макете `[31-03]`).
|
— `null`, в итоги и КФО не входит. Повторное появление пары восстанавливает расчёт по текущим данным.
|
||||||
- **Уставный капитал ДО (`charter_capital_amount`, УК)** — стр. `1310` ББ ДО на отчётную дату; при наличии ОСВ ДО —
|
- **Уставный капитал ДО (`charter_capital_amount`, УК)** — стр. `1310` подтверждённого ББ ДО, привязанного к версии,
|
||||||
`Кт 80 + Кт 83`, иначе `1310` из формы (§8 domain-rules, уточняет первую часть OQ-10). **Добавочный капитал
|
по колонке **конца отчётного квартала** (не по `is_current`), в рублях: единицы формы читаются словарём единиц
|
||||||
(`additional_capital_amount`)** — стр. `1350` ББ ДО, считается и хранится всегда, независимо от того, участвует ли
|
`arm_statements` («тыс.руб.», «в тысячах рублей» → тыс. руб.). Повторы кода 1310 суммируются. Ноль — допустимое значение.
|
||||||
в формуле (см. OQ-10 ниже).
|
Нет ББ, строки 1310 или колонки даты, единицы не распознаны — `null` и предупреждение `CAPITAL_SOURCE_MISSING`;
|
||||||
- **Доля владения (`ownership_share`)** — ручной ввод аналитика, % (`numeric(7,4)`); единственное обязательное поле
|
у ДО несколько подходящих ББ — `null` и `CAPITAL_SOURCE_AMBIGUOUS`.
|
||||||
правки наряду с `comment`.
|
- **Добавочный капитал (`additional_capital_amount`)** — стр. `1350` того же ББ, справочно; в формулу не входит
|
||||||
- **Доля участия (`participation_amount`)** = `(charter_capital_amount [+ additional_capital_amount, если решение
|
(ASSUMPTION OQ-10).
|
||||||
методологов это подтвердит]) × ownership_share / 100`.
|
- **Доля владения (`ownership_share`)** — ручной ввод, % от `0` до `100`, не больше двух знаков после запятой.
|
||||||
- **Гудвилл (`goodwill_amount`)** = `financial_investment_amount − participation_amount`; может быть отрицательным.
|
- **Доля участия (`participation_amount`, P)** = `round(УК × доля / 100, 2)` (`ROUND_HALF_UP`), **гудвилл
|
||||||
- **Учёт в КФО (`include_in_kfo`)** — чекбокс «Учёт в отчёте» строки (макет `[31-03]`, с «Выделить все» по ГО на
|
(`goodwill_amount`, G)** = `ФВ − P`, может быть отрицательным и нулевым. P и G считаются **только у действующей
|
||||||
фронте — пакетное действие фронта, не отдельная ручка). Комментарий обязателен **только** когда `include_in_kfo = true`
|
отмеченной строки** (`include_in_kfo = true`) с заполненными долей и УК, иначе `null`.
|
||||||
(ТЗ 6.7). Положительная сумма отмеченных строк уходит в `kfo_result_line` с `line_code = 'GOODWILL'`
|
- **Учёт в отчёте (`include_in_kfo`)** — галочка строки. У отмеченной действующей строки обязательны доля и непустой
|
||||||
(раздел I КФО, допущение OQ-37) — расчёт и запись при построении результата КФО, не в этом контракте.
|
комментарий. Снятие галочки не стирает долю и комментарий.
|
||||||
- **Признак расчёта гудвилла (`goodwill_enabled`)** — переключатель версии (`consolidation_version.goodwill_enabled`,
|
- **Признак учёта гудвилла (`goodwill_enabled`)** — переключатель версии (решение OQ-27: на вкладке «Гудвилл», не в
|
||||||
решено OQ-27: живёт на вкладке «Гудвилл», не в модалке создания). Сейчас в контракте нет ручки, которая бы его
|
модалке создания). Выключен — таблица и ручной ввод не меняются, но в КФО ничего не уходит
|
||||||
выставляла (только чтение через `VersionCard`, `dev/api-contract-slice-4.md`) — добавляется здесь (§3.2).
|
(`goodwill_in_kfo_amount = "0.00"`).
|
||||||
Выключен — таблица показывается как есть (доли и комментарии не теряются), но ничего не уходит в КФО.
|
- **Предупреждения (`warnings[]`)** — `{code, message}`, не блокируют сохранение:
|
||||||
|
`CAPITAL_SOURCE_MISSING`, `CAPITAL_SOURCE_AMBIGUOUS` (см. УК), `OWNERSHIP_TOTAL_EXCEEDED` — сумма заполненных долей
|
||||||
|
действующих пар разных ГО в одной ДО больше 100 % (показывается у всех строк этой ДО).
|
||||||
|
|
||||||
## 3. Эндпоинты
|
## 3. Эндпоинты
|
||||||
|
|
||||||
| Метод и путь | Право | Запрос | Ответ | Ошибки |
|
| Метод и путь | Право | Запрос | Ответ | Ошибки |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| `GET /consolidations/versions/{version_id}/goodwill` | VIEW | — | 200 `GoodwillTableOut` | 404 `NOT_FOUND` |
|
| `GET /consolidations/versions/{version_id}/goodwill` | VIEW | — | 200 `GoodwillTableOut` | 404 `NOT_FOUND` |
|
||||||
|
| `PUT /consolidations/versions/{version_id}/goodwill` | EDIT | `GoodwillBatchIn` | 200 `GoodwillTableOut` | 404 `NOT_FOUND` (версия или пара), 409 правок версии, 422 `INVALID_SHARE`, `COMMENT_REQUIRED`, `MONEY_OUT_OF_RANGE`, `DUPLICATE_ROW`, 422 валидации тела |
|
||||||
| `PUT /consolidations/versions/{version_id}/goodwill-settings` | EDIT | `GoodwillSettingsIn` | 200 `GoodwillTableOut` | 404, 409 правок версии |
|
| `PUT /consolidations/versions/{version_id}/goodwill-settings` | EDIT | `GoodwillSettingsIn` | 200 `GoodwillTableOut` | 404, 409 правок версии |
|
||||||
| `PUT /consolidations/versions/{version_id}/goodwill/{head_legal_entity_id}/{subsidiary_legal_entity_id}` | EDIT | `GoodwillRowIn` | 200 `GoodwillRowOut` | 404 `NOT_FOUND` (версия или пара не из периметра), 409 правок версии, 422 `COMMENT_REQUIRED`, 422 `INVALID_SHARE` |
|
| `GET /consolidations/versions/{version_id}/goodwill/export?sign=all\|positive\|negative\|zero` | VIEW | — | файл xlsx | 404 `NOT_FOUND`, 422 неизвестный `sign` |
|
||||||
| `GET /consolidations/versions/{version_id}/goodwill/export` | VIEW | — | файл xlsx | 404 `NOT_FOUND` |
|
|
||||||
|
|
||||||
### 3.1 `GET …/goodwill` — таблица
|
### 3.1 `GET …/goodwill` — таблица
|
||||||
|
|
||||||
Все строки одним ответом (пар — единицы, не десятки; без страниц). Порядок: по имени ГО, внутри — по имени ДО.
|
Все строки одним ответом, без страниц. Порядок строк — имя ГО, имя ДО, затем id; `groups` — в том же порядке ГО.
|
||||||
Группировку по ГО и подсчёт «Выделить все» делает фронт. Пустой периметр (только ГО, без ДО) — `rows = []`, это не ошибка.
|
Чтение ничего не пишет (записи `goodwill` создаются только сохранением). Нет пар и сохранённых строк — `rows = []`,
|
||||||
|
`groups = []`, итоги `"0.00"`.
|
||||||
|
|
||||||
### 3.2 `PUT …/goodwill-settings` — переключатель версии
|
### 3.2 `PUT …/goodwill` — сохранить набор строк
|
||||||
|
|
||||||
Меняет `consolidation_version.goodwill_enabled`. Аудит — новое действие в `audit_action` (например,
|
Тело — изменённые аналитиком строки целиком (`ownership_share`, `include_in_kfo`, `comment` каждой строки приходят
|
||||||
`GOODWILL_ENABLED_CHANGE`), результат КФО помечается устаревшим при любом изменении значения (как в AURORA-1417).
|
каждый раз). **Пакет сохраняется в одной транзакции**: сначала проверяются все строки, ошибка любой — ответ с её ключом
|
||||||
Выключение не трогает сохранённые строки (`ownership_share`, `comment`, `include_in_kfo` остаются).
|
(`detail.head_legal_entity_id`, `detail.subsidiary_legal_entity_id`) и ничего не сохраняется.
|
||||||
|
|
||||||
### 3.3 `PUT …/goodwill/{head_legal_entity_id}/{subsidiary_legal_entity_id}` — сохранить строку
|
- Пара должна быть в текущей таблице (действующая или «Нет вложений»), иначе 404 `NOT_FOUND` с ключом пары.
|
||||||
|
- Одна пара дважды в пакете — 422 `DUPLICATE_ROW`.
|
||||||
|
- `ownership_share` — `null` или строка `0`…`100`, не больше двух знаков после запятой, запятая или точка
|
||||||
|
(`"80,5"` = `"80.5"`). Лишние знаки, отрицательные, экспонента — 422 `INVALID_SHARE` (без округления). У отмеченной
|
||||||
|
строки доля обязательна — `null` даёт `INVALID_SHARE`.
|
||||||
|
- `comment` — до 1000 символов; у отмеченной строки пустой после обрезки — 422 `COMMENT_REQUIRED`.
|
||||||
|
- У строки «Нет вложений» `null` в доле или комментарии не стирает сохранённое значение.
|
||||||
|
- Строка, ввод которой совпадает с сохранённым (или для пары без записи — с умолчанием «не отмечена, доли и комментария
|
||||||
|
нет»), не перезаписывается: `updated_by/updated_at` не меняются, аудита нет. Поэтому фронт может отправлять весь набор
|
||||||
|
отмеченных строк, но лучше — только изменённые.
|
||||||
|
- У изменённой действующей строки вместе с вводом сохраняется снимок сумм (ФВ, УК, 1350, P, G); сумма вне
|
||||||
|
`numeric(18,2)` — 422 `MONEY_OUT_OF_RANGE`.
|
||||||
|
- Аудит — `GOODWILL_EDIT` на каждую изменённую строку (`object_type = goodwill`, `before`/`after` — строка ответа).
|
||||||
|
|
||||||
Сохраняет **все поля строки целиком** (как в `PUT …/corrections/aggregates/…` — текущие `ownership_share`,
|
Ответ — пересчитанная таблица целиком (строки, итоги по ГО и общие).
|
||||||
`include_in_kfo` и `comment` приходят каждый раз, частичного `PATCH` нет).
|
|
||||||
|
|
||||||
- `head_legal_entity_id` должен быть членом периметра с `is_head_entity = true`, `subsidiary_legal_entity_id` — любым
|
### 3.3 `PUT …/goodwill-settings` — переключатель версии
|
||||||
другим членом периметра; иначе 404 `NOT_FOUND` (пары не существует).
|
|
||||||
- `ownership_share` — строка `0`…`100`, до 4 знаков после запятой (`numeric(7,4)`); вне диапазона или больше 4 знаков —
|
|
||||||
422 `INVALID_SHARE`.
|
|
||||||
- `comment` обязателен, если `include_in_kfo = true`; пустой после обрезки в этом случае — 422 `COMMENT_REQUIRED`
|
|
||||||
(как `COMMENT_REQUIRED` в контракте корректировок); не длиннее 1000 символов. При `include_in_kfo = false` комментарий
|
|
||||||
необязателен и может быть `null`.
|
|
||||||
- `financial_investment_amount`, `charter_capital_amount`, `additional_capital_amount`, `participation_amount`,
|
|
||||||
`goodwill_amount` в тело **не входят** — это вычисляемые поля, пересчитываются сервером из текущей ОСВ версии при
|
|
||||||
каждом ответе, в запросе их нет.
|
|
||||||
- Аудит `GOODWILL_ROW_EDIT` (поле нужно добавить в `audit_action`, как `CORRECTION_*` для корректировок) с `before`/`after`;
|
|
||||||
результат КФО помечается устаревшим.
|
|
||||||
|
|
||||||
Ответ — пересчитанная строка (а не вся таблица — в отличие от корректировок, строки гудвилла друг на друга не влияют).
|
Меняет `consolidation_version.goodwill_enabled`. Повтор прежнего значения ничего не пишет. Изменение — аудит
|
||||||
|
`GOODWILL_EDIT` (`object_type = consolidation_version`, `changed_field = goodwill_enabled`). Ручной ввод строк не
|
||||||
|
трогается.
|
||||||
|
|
||||||
### 3.4 `GET …/export` — xlsx
|
### 3.4 `GET …/goodwill/export` — xlsx
|
||||||
|
|
||||||
Таблица гудвилла одним листом, группировка по ГО, итоговая строка «Всего» (макет `[31-03]`). Имя файла —
|
Лист «Гудвилл»: восемь колонок экранной таблицы (Учёт в отчёте, Наименование дочерней организации, Доля владения,
|
||||||
`Гудвилл_<название ГК>_<год>_<квартал>.xlsx` в `Content-Disposition` (как в экспорте корректировок). Аудит `EXPORT`.
|
Фондовые вложения головной организации, Доля участия ГО в УК, Уставный капитал, Гудвилл (+/−), Комментарий), блок на
|
||||||
|
каждую ГО со строкой «Всего», в конце — «Итого по листу». Деньги — в рублях, `null` — пустая ячейка; у строки «Нет
|
||||||
|
вложений» в колонке ФВ — текст «Нет вложений». `sign` оставляет
|
||||||
|
строки с гудвиллом нужного знака (нерассчитанные в фильтры по знаку не попадают), итоги остаются по полному составу.
|
||||||
|
Выгружается последнее сохранённое состояние. Имя — `Гудвилл_<ГК>_<год>_<квартал>.xlsx` в `Content-Disposition`
|
||||||
|
(`filename*`). Аудит `EXPORT` с `{report: "goodwill", rows: <число строк в файле>}`.
|
||||||
|
|
||||||
## 4. Схемы
|
## 4. Схемы
|
||||||
|
|
||||||
Поля без `?` есть всегда; `null` указан явно.
|
Поля без `?` есть всегда; `null` указан явно. `money` — строка с двумя знаками, `share` — строка с двумя знаками.
|
||||||
|
|
||||||
**`GoodwillTableOut`**
|
**`GoodwillTableOut`**
|
||||||
```
|
```
|
||||||
version_id uuid
|
version_id uuid
|
||||||
goodwill_enabled bool
|
goodwill_enabled bool
|
||||||
editable bool
|
editable bool
|
||||||
read_only_reason null | "VERSION_NOT_EDITABLE" | "LOCK_REQUIRED" | "LOCKED_BY_OTHER"
|
read_only_reason null | "VERSION_NOT_EDITABLE" | "LOCK_REQUIRED" | "LOCKED_BY_OTHER"
|
||||||
rows[] GoodwillRowOut
|
rows[] GoodwillRowOut
|
||||||
totals GoodwillTotalsOut
|
groups[] GoodwillGroupOut итог «Всего» по каждой ГО
|
||||||
|
totals GoodwillTotalsOut «Итого по листу»
|
||||||
```
|
```
|
||||||
|
|
||||||
**`GoodwillRowOut`**
|
**`GoodwillRowOut`**
|
||||||
```
|
```
|
||||||
head_legal_entity Ref {id, name}
|
head_legal_entity Ref {id, name}
|
||||||
subsidiary_legal_entity Ref
|
subsidiary_legal_entity Ref
|
||||||
ownership_share share | null % 4 знака; null — ещё не введена
|
ownership_share share | null
|
||||||
financial_investment_amount money
|
financial_investment_amount money | null null у «Нет вложений»
|
||||||
charter_capital_amount money
|
charter_capital_amount money | null null — нет однозначного 1310 или «Нет вложений»
|
||||||
additional_capital_amount money
|
additional_capital_amount money | null справочно, в формулу не входит
|
||||||
participation_amount money
|
participation_amount money | null только у действующей отмеченной строки
|
||||||
goodwill_amount money может быть отрицательным
|
goodwill_amount money | null может быть < 0 и = 0
|
||||||
include_in_kfo bool
|
include_in_kfo bool
|
||||||
comment string | null
|
comment string | null
|
||||||
updated_by Ref | null
|
has_investments bool
|
||||||
updated_at datetime | null
|
warnings[] {code, message}
|
||||||
|
updated_by Ref | null
|
||||||
|
updated_at datetime | null
|
||||||
```
|
```
|
||||||
|
|
||||||
**`GoodwillTotalsOut`** — сумма по всем строкам ответа: `{financial_investment_amount, participation_amount,
|
**`GoodwillGroupOut`** `{head_legal_entity: Ref, totals: GoodwillTotalsOut}`.
|
||||||
goodwill_amount}`, плюс `goodwill_in_kfo_amount` — сумма `goodwill_amount` только по строкам с `include_in_kfo = true`
|
|
||||||
и положительным `goodwill_amount` (то, что реально уйдёт в `kfo_result_line.line_code = 'GOODWILL'`).
|
|
||||||
|
|
||||||
**`GoodwillRowIn`** `{ownership_share (share-строка 0…100), include_in_kfo (bool), comment (string | null, обязателен
|
**`GoodwillTotalsOut`** — по действующим строкам (без «Нет вложений»):
|
||||||
при include_in_kfo = true, ≤ 1000 символов)}`.
|
```
|
||||||
|
financial_investment_amount money все действующие строки, независимо от галочки
|
||||||
|
charter_capital_amount money все действующие строки (УК одной ДО у нескольких ГО входит несколько раз)
|
||||||
|
participation_amount money только отмеченные
|
||||||
|
goodwill_amount money только отмеченные, отрицательные и нулевые тоже
|
||||||
|
goodwill_in_kfo_amount money положительные G отмеченных строк с долей и комментарием; 0.00 при goodwill_enabled = false
|
||||||
|
```
|
||||||
|
|
||||||
**`GoodwillSettingsIn`** `{goodwill_enabled (bool)}`.
|
**`GoodwillBatchIn`** `{rows: GoodwillRowKeyIn[]}` (минимум одна строка).
|
||||||
|
|
||||||
## 5. Открытые вопросы (AURORA-1369, срок 02.11.2026)
|
**`GoodwillRowKeyIn`** `{head_legal_entity_id: uuid, subsidiary_legal_entity_id: uuid, ownership_share: string | null,
|
||||||
|
include_in_kfo: bool, comment: string | null (≤ 1000)}`.
|
||||||
|
|
||||||
- **OQ-10** — входит ли стр. 1350 (добавочный капитал) в базу участия. Допущение сейчас: **нет**, `participation_amount`
|
**`GoodwillSettingsIn`** `{goodwill_enabled: bool}`.
|
||||||
считается только от `charter_capital_amount`; `additional_capital_amount` хранится и показывается в таблице (колонка
|
|
||||||
есть и в DBML, и на фронте — макет её не показывает явно, но поле в `goodwill` есть с пометкой ADD), но не входит в
|
|
||||||
формулу. Если методологи подтвердят, что 1350 нужен — меняется только формула на бэкенде, контракт не меняется.
|
|
||||||
- **OQ-37** — код строки «Гудвилл» в результате КФО: служебный `GOODWILL` (как в DBML, принято этим контрактом) или
|
|
||||||
`1105` как в распознанной форме ББ (ФСБУ 4/2023). Контракта это не касается напрямую (он про таблицу `goodwill`, не
|
|
||||||
про `kfo_result_line`), но влияет на отдельную задачу построения КФО — не блокирует 1543/1544.
|
|
||||||
- Несколько `is_head_entity` в одном периметре — не встречалось на фикстурах, поведение не проверено отдельно.
|
|
||||||
|
|
||||||
**Фронт (AURORA-1544) ничего из этого не ждёт** — строит экран по схемам §4 на фейковых данных; поля не меняются от
|
## 5. Граница этапа и открытые вопросы
|
||||||
исхода открытых вопросов, меняются только числа внутри них.
|
|
||||||
|
|
||||||
## 6. Пример
|
- **КФО.** Применение гудвилла в КФО (1170 ГО − ФВ, 1310 ДО − P, строка `GOODWILL` + G), исключение обычного ББ-2 по
|
||||||
|
паре, пометка результата КФО устаревшим и фиксация при VERIFIED — задача AURORA-1546, этим API не делается.
|
||||||
|
- **OQ-10** — 1350 в базу участия не входит (DOC-259025 §6: «Для УК используется 1310»), колонка — справочно.
|
||||||
|
- **OQ-37** — служебный код `GOODWILL` для строки КФО (DOC-259025 §7).
|
||||||
|
|
||||||
|
## 6. Что изменилось против черновика 30.10
|
||||||
|
|
||||||
|
- ГО — по фактическим вложениям 58.01, а не по `is_head_entity`; строк «все ДО под каждой ГО» больше нет.
|
||||||
|
- Новые поля строки: `has_investments`, `warnings`; УК, 1350, P, G и ФВ — nullable.
|
||||||
|
- Новые поля ответа: `groups[]`, `totals.charter_capital_amount`.
|
||||||
|
- P и G — только у отмеченных строк; итоги P и G — по отмеченным.
|
||||||
|
- Доля — два знака, а не четыре.
|
||||||
|
- Построчный `PUT …/goodwill/{head}/{sub}` заменён пакетным `PUT …/goodwill` (одна транзакция, ответ — вся таблица).
|
||||||
|
- У экспорта — параметр `sign`.
|
||||||
|
|
||||||
|
## 7. Пример
|
||||||
|
|
||||||
`GET /api/v1/consolidations/versions/7b…/goodwill` (сокращено):
|
`GET /api/v1/consolidations/versions/7b…/goodwill` (сокращено):
|
||||||
|
|
||||||
@ -166,25 +190,72 @@ goodwill_amount}`, плюс `goodwill_in_kfo_amount` — сумма `goodwill_am
|
|||||||
"read_only_reason": null,
|
"read_only_reason": null,
|
||||||
"rows": [
|
"rows": [
|
||||||
{
|
{
|
||||||
"head_legal_entity": {"id": "a…", "name": "АО «Русский бисквит»"},
|
"head_legal_entity": {"id": "a…", "name": "Альфа"},
|
||||||
"subsidiary_legal_entity": {"id": "b…", "name": "ООО «Пекарня Счастливочная»"},
|
"subsidiary_legal_entity": {"id": "b…", "name": "Бета"},
|
||||||
"ownership_share": "100.0000",
|
"ownership_share": "80.00",
|
||||||
"financial_investment_amount": "5000000.00",
|
"financial_investment_amount": "180000.00",
|
||||||
"charter_capital_amount": "4500000.00",
|
"charter_capital_amount": "100000.00",
|
||||||
"additional_capital_amount": "0.00",
|
"additional_capital_amount": "0.00",
|
||||||
"participation_amount": "4500000.00",
|
"participation_amount": "80000.00",
|
||||||
"goodwill_amount": "500000.00",
|
"goodwill_amount": "100000.00",
|
||||||
"include_in_kfo": true,
|
"include_in_kfo": true,
|
||||||
"comment": "Доля подтверждена уставом от 01.01.2024",
|
"comment": "Доля подтверждена уставом",
|
||||||
|
"has_investments": true,
|
||||||
|
"warnings": [],
|
||||||
"updated_by": {"id": "u…", "name": "Иванов И. И."},
|
"updated_by": {"id": "u…", "name": "Иванов И. И."},
|
||||||
"updated_at": "2026-10-30T12:00:00+03:00"
|
"updated_at": "2026-11-06T12:00:00Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"head_legal_entity": {"id": "a…", "name": "Альфа"},
|
||||||
|
"subsidiary_legal_entity": {"id": "c…", "name": "Гамма"},
|
||||||
|
"ownership_share": "80.00",
|
||||||
|
"financial_investment_amount": "50000.00",
|
||||||
|
"charter_capital_amount": "100000.00",
|
||||||
|
"additional_capital_amount": null,
|
||||||
|
"participation_amount": "80000.00",
|
||||||
|
"goodwill_amount": "-30000.00",
|
||||||
|
"include_in_kfo": true,
|
||||||
|
"comment": "Доля подтверждена уставом",
|
||||||
|
"has_investments": true,
|
||||||
|
"warnings": [],
|
||||||
|
"updated_by": null,
|
||||||
|
"updated_at": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"head_legal_entity": {"id": "a…", "name": "Альфа"},
|
||||||
|
"totals": {
|
||||||
|
"financial_investment_amount": "230000.00",
|
||||||
|
"charter_capital_amount": "200000.00",
|
||||||
|
"participation_amount": "160000.00",
|
||||||
|
"goodwill_amount": "70000.00",
|
||||||
|
"goodwill_in_kfo_amount": "100000.00"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"totals": {
|
"totals": {
|
||||||
"financial_investment_amount": "5000000.00",
|
"financial_investment_amount": "230000.00",
|
||||||
"participation_amount": "4500000.00",
|
"charter_capital_amount": "200000.00",
|
||||||
"goodwill_amount": "500000.00",
|
"participation_amount": "160000.00",
|
||||||
"goodwill_in_kfo_amount": "500000.00"
|
"goodwill_amount": "70000.00",
|
||||||
|
"goodwill_in_kfo_amount": "100000.00"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`PUT /api/v1/consolidations/versions/7b…/goodwill`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"rows": [
|
||||||
|
{"head_legal_entity_id": "a…", "subsidiary_legal_entity_id": "b…", "ownership_share": "80", "include_in_kfo": true, "comment": "Доля подтверждена уставом"},
|
||||||
|
{"head_legal_entity_id": "a…", "subsidiary_legal_entity_id": "d…", "ownership_share": null, "include_in_kfo": false, "comment": null}
|
||||||
|
]}
|
||||||
|
```
|
||||||
|
|
||||||
|
Ошибка строки:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"detail": {"code": "COMMENT_REQUIRED", "message": "Укажите комментарий",
|
||||||
|
"head_legal_entity_id": "a…", "subsidiary_legal_entity_id": "b…"}}
|
||||||
|
```
|
||||||
|
|||||||
@ -1,278 +1,427 @@
|
|||||||
openapi: 3.1.0
|
openapi: 3.1.0
|
||||||
info:
|
info:
|
||||||
title: АРМ КА — таблица гудвилла
|
title: АРМ КА — таблица гудвилла (AURORA-1543/1544)
|
||||||
version: 0.1.0-draft
|
version: '1.0'
|
||||||
description: >
|
|
||||||
Черновик контракта AURORA-1543 (бэкенд) / AURORA-1544 (фронт). Текстовое описание, источники и открытые вопросы —
|
|
||||||
dev/api-contract-goodwill.md; оба файла держатся одинаковыми. Деньги — строки с двумя знаками в рублях, доля
|
|
||||||
владения — строка с четырьмя знаками. Чтение — CONSOLIDATION_VIEW, правки — CONSOLIDATION_EDIT.
|
|
||||||
servers:
|
|
||||||
- url: /api/v1
|
|
||||||
security:
|
|
||||||
- bearerAuth: []
|
|
||||||
|
|
||||||
paths:
|
paths:
|
||||||
/consolidations/versions/{version_id}/goodwill:
|
/api/v1/consolidations/versions/{version_id}/goodwill:
|
||||||
get:
|
get:
|
||||||
operationId: getGoodwillTable
|
tags:
|
||||||
summary: Таблица гудвилла версии
|
- consolidations
|
||||||
x-permission: CONSOLIDATION_VIEW
|
summary: Table
|
||||||
|
operationId: table_api_v1_consolidations_versions__version_id__goodwill_get
|
||||||
|
security:
|
||||||
|
- bearerAuth: []
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: '#/components/parameters/VersionId'
|
- name: version_id
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
title: Version Id
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: Строки пар (ГО, ДО) периметра, итоги
|
description: Successful Response
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema: { $ref: '#/components/schemas/GoodwillTableOut' }
|
schema:
|
||||||
'401': { $ref: '#/components/responses/Unauthorized' }
|
$ref: '#/components/schemas/GoodwillTableOut'
|
||||||
'403': { $ref: '#/components/responses/Forbidden' }
|
'422':
|
||||||
'404': { $ref: '#/components/responses/DomainError' }
|
description: Validation Error
|
||||||
|
content:
|
||||||
/consolidations/versions/{version_id}/goodwill-settings:
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/HTTPValidationError'
|
||||||
put:
|
put:
|
||||||
operationId: saveGoodwillSettings
|
tags:
|
||||||
summary: Переключатель расчёта гудвилла версии (consolidation_version.goodwill_enabled)
|
- consolidations
|
||||||
description: >
|
summary: Save
|
||||||
Аудит GOODWILL_ENABLED_CHANGE; результат КФО устаревает при любом изменении значения. Выключение не стирает
|
description: Пакет строк одной транзакцией; ошибка любой строки — 404/422 с её ключом, ничего не сохраняется.
|
||||||
сохранённые строки (ownership_share, comment, include_in_kfo).
|
operationId: save_api_v1_consolidations_versions__version_id__goodwill_put
|
||||||
x-permission: CONSOLIDATION_EDIT
|
security:
|
||||||
|
- bearerAuth: []
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: '#/components/parameters/VersionId'
|
- name: version_id
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
title: Version Id
|
||||||
requestBody:
|
requestBody:
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema: { $ref: '#/components/schemas/GoodwillSettingsIn' }
|
schema:
|
||||||
|
$ref: '#/components/schemas/GoodwillBatchIn'
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: Таблица с обновлённым флагом
|
description: Successful Response
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema: { $ref: '#/components/schemas/GoodwillTableOut' }
|
schema:
|
||||||
'401': { $ref: '#/components/responses/Unauthorized' }
|
$ref: '#/components/schemas/GoodwillTableOut'
|
||||||
'403': { $ref: '#/components/responses/Forbidden' }
|
'422':
|
||||||
'404': { $ref: '#/components/responses/DomainError' }
|
description: Validation Error
|
||||||
'409': { $ref: '#/components/responses/DomainError' }
|
content:
|
||||||
|
application/json:
|
||||||
/consolidations/versions/{version_id}/goodwill/{head_legal_entity_id}/{subsidiary_legal_entity_id}:
|
schema:
|
||||||
|
$ref: '#/components/schemas/HTTPValidationError'
|
||||||
|
/api/v1/consolidations/versions/{version_id}/goodwill-settings:
|
||||||
put:
|
put:
|
||||||
operationId: saveGoodwillRow
|
tags:
|
||||||
summary: Сохранить строку гудвилла (создать или заменить целиком)
|
- consolidations
|
||||||
description: >
|
summary: Settings
|
||||||
Аудит GOODWILL_ROW_EDIT; результат КФО устаревает. Вычисляемые поля (financial_investment_amount,
|
operationId: settings_api_v1_consolidations_versions__version_id__goodwill_settings_put
|
||||||
charter_capital_amount, additional_capital_amount, participation_amount, goodwill_amount) в тело запроса не
|
security:
|
||||||
входят — пересчитываются сервером. 404 — версия или пара (head/subsidiary) не из периметра; 409 — правок
|
- bearerAuth: []
|
||||||
версии; 422 — COMMENT_REQUIRED (include_in_kfo = true без комментария), INVALID_SHARE (вне 0…100 или больше
|
|
||||||
4 знаков после запятой).
|
|
||||||
x-permission: CONSOLIDATION_EDIT
|
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: '#/components/parameters/VersionId'
|
- name: version_id
|
||||||
- $ref: '#/components/parameters/HeadLegalEntityId'
|
in: path
|
||||||
- $ref: '#/components/parameters/SubsidiaryLegalEntityId'
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
title: Version Id
|
||||||
requestBody:
|
requestBody:
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema: { $ref: '#/components/schemas/GoodwillRowIn' }
|
schema:
|
||||||
|
$ref: '#/components/schemas/GoodwillSettingsIn'
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: Пересчитанная строка
|
description: Successful Response
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema: { $ref: '#/components/schemas/GoodwillRowOut' }
|
schema:
|
||||||
'401': { $ref: '#/components/responses/Unauthorized' }
|
$ref: '#/components/schemas/GoodwillTableOut'
|
||||||
'403': { $ref: '#/components/responses/Forbidden' }
|
'422':
|
||||||
'404': { $ref: '#/components/responses/DomainError' }
|
description: Validation Error
|
||||||
'409': { $ref: '#/components/responses/DomainError' }
|
content:
|
||||||
'422': { $ref: '#/components/responses/DomainOrValidationError' }
|
application/json:
|
||||||
|
schema:
|
||||||
/consolidations/versions/{version_id}/goodwill/export:
|
$ref: '#/components/schemas/HTTPValidationError'
|
||||||
|
/api/v1/consolidations/versions/{version_id}/goodwill/export:
|
||||||
get:
|
get:
|
||||||
operationId: exportGoodwillTable
|
tags:
|
||||||
summary: Выгрузка таблицы гудвилла в xlsx
|
- consolidations
|
||||||
description: Аудит EXPORT.
|
summary: Export
|
||||||
x-permission: CONSOLIDATION_VIEW
|
operationId: export_api_v1_consolidations_versions__version_id__goodwill_export_get
|
||||||
|
security:
|
||||||
|
- bearerAuth: []
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: '#/components/parameters/VersionId'
|
- name: version_id
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
title: Version Id
|
||||||
|
- name: sign
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
enum:
|
||||||
|
- all
|
||||||
|
- positive
|
||||||
|
- negative
|
||||||
|
- zero
|
||||||
|
type: string
|
||||||
|
default: all
|
||||||
|
title: Sign
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: Файл xlsx
|
description: Successful Response
|
||||||
content:
|
content:
|
||||||
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
|
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
|
||||||
schema: { type: string, format: binary }
|
schema:
|
||||||
'401': { $ref: '#/components/responses/Unauthorized' }
|
type: string
|
||||||
'403': { $ref: '#/components/responses/Forbidden' }
|
format: binary
|
||||||
'404': { $ref: '#/components/responses/DomainError' }
|
'422':
|
||||||
|
description: Validation Error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/HTTPValidationError'
|
||||||
components:
|
components:
|
||||||
securitySchemes:
|
|
||||||
bearerAuth: { type: http, scheme: bearer, bearerFormat: JWT }
|
|
||||||
|
|
||||||
parameters:
|
|
||||||
VersionId:
|
|
||||||
name: version_id
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
schema: { type: string, format: uuid }
|
|
||||||
HeadLegalEntityId:
|
|
||||||
name: head_legal_entity_id
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
description: Член периметра с is_head_entity = true
|
|
||||||
schema: { type: string, format: uuid }
|
|
||||||
SubsidiaryLegalEntityId:
|
|
||||||
name: subsidiary_legal_entity_id
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
description: Любой другой член периметра
|
|
||||||
schema: { type: string, format: uuid }
|
|
||||||
|
|
||||||
responses:
|
|
||||||
Unauthorized:
|
|
||||||
description: Нет или плохой токен
|
|
||||||
Forbidden:
|
|
||||||
description: Нет права
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties: { detail: { type: string } }
|
|
||||||
DomainError:
|
|
||||||
description: Доменная ошибка
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: { $ref: '#/components/schemas/DomainErrorOut' }
|
|
||||||
DomainOrValidationError:
|
|
||||||
description: Доменная ошибка или массив ошибок валидации pydantic
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
oneOf:
|
|
||||||
- $ref: '#/components/schemas/DomainErrorOut'
|
|
||||||
- type: object
|
|
||||||
properties:
|
|
||||||
detail:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
loc: { type: array, items: {} }
|
|
||||||
msg: { type: string }
|
|
||||||
type: { type: string }
|
|
||||||
|
|
||||||
schemas:
|
schemas:
|
||||||
Money:
|
GoodwillBatchIn:
|
||||||
type: string
|
|
||||||
pattern: '^-?\d+\.\d{2}$'
|
|
||||||
description: Сумма в рублях, два знака; может быть отрицательной (goodwill_amount)
|
|
||||||
examples: ['500000.00']
|
|
||||||
Share:
|
|
||||||
type: [string, 'null']
|
|
||||||
pattern: '^\d{1,3}\.\d{4}$'
|
|
||||||
description: Доля владения, % (numeric(7,4)); null — ещё не введена
|
|
||||||
ShareIn:
|
|
||||||
type: string
|
|
||||||
pattern: '^\d{1,3}(\.\d{1,4})?$'
|
|
||||||
description: 0…100, до 4 знаков после запятой; вне диапазона — 422 INVALID_SHARE
|
|
||||||
Ref:
|
|
||||||
type: object
|
|
||||||
required: [id, name]
|
|
||||||
properties:
|
properties:
|
||||||
id: { type: string, format: uuid }
|
|
||||||
name: { type: string }
|
|
||||||
|
|
||||||
DomainErrorOut:
|
|
||||||
type: object
|
|
||||||
required: [detail]
|
|
||||||
properties:
|
|
||||||
detail:
|
|
||||||
type: object
|
|
||||||
required: [code, message]
|
|
||||||
properties:
|
|
||||||
code:
|
|
||||||
type: string
|
|
||||||
enum:
|
|
||||||
- NOT_FOUND
|
|
||||||
- VERSION_NOT_EDITABLE
|
|
||||||
- LOCK_REQUIRED
|
|
||||||
- LOCKED_BY_OTHER
|
|
||||||
- COMMENT_REQUIRED
|
|
||||||
- INVALID_SHARE
|
|
||||||
message: { type: string, description: Текст по-русски }
|
|
||||||
additionalProperties: true
|
|
||||||
|
|
||||||
GoodwillTableOut:
|
|
||||||
type: object
|
|
||||||
required: [version_id, goodwill_enabled, editable, read_only_reason, rows, totals]
|
|
||||||
properties:
|
|
||||||
version_id: { type: string, format: uuid }
|
|
||||||
goodwill_enabled: { type: boolean }
|
|
||||||
editable: { type: boolean }
|
|
||||||
read_only_reason:
|
|
||||||
type: [string, 'null']
|
|
||||||
enum: [null, VERSION_NOT_EDITABLE, LOCK_REQUIRED, LOCKED_BY_OTHER]
|
|
||||||
rows:
|
rows:
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/GoodwillRowKeyIn'
|
||||||
type: array
|
type: array
|
||||||
items: { $ref: '#/components/schemas/GoodwillRowOut' }
|
minItems: 1
|
||||||
totals: { $ref: '#/components/schemas/GoodwillTotalsOut' }
|
title: Rows
|
||||||
|
additionalProperties: false
|
||||||
GoodwillRowOut:
|
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- head_legal_entity
|
- rows
|
||||||
- subsidiary_legal_entity
|
title: GoodwillBatchIn
|
||||||
- ownership_share
|
description: Пакет строк таблицы гудвилла; сохраняется целиком или не сохраняется.
|
||||||
- financial_investment_amount
|
GoodwillGroupOut:
|
||||||
- charter_capital_amount
|
|
||||||
- additional_capital_amount
|
|
||||||
- participation_amount
|
|
||||||
- goodwill_amount
|
|
||||||
- include_in_kfo
|
|
||||||
- comment
|
|
||||||
- updated_by
|
|
||||||
- updated_at
|
|
||||||
properties:
|
properties:
|
||||||
head_legal_entity: { $ref: '#/components/schemas/Ref' }
|
head_legal_entity:
|
||||||
subsidiary_legal_entity: { $ref: '#/components/schemas/Ref' }
|
$ref: '#/components/schemas/RefOut'
|
||||||
ownership_share: { $ref: '#/components/schemas/Share' }
|
totals:
|
||||||
financial_investment_amount: { $ref: '#/components/schemas/Money' }
|
$ref: '#/components/schemas/GoodwillTotalsOut'
|
||||||
charter_capital_amount: { $ref: '#/components/schemas/Money' }
|
|
||||||
additional_capital_amount: { $ref: '#/components/schemas/Money' }
|
|
||||||
participation_amount: { $ref: '#/components/schemas/Money' }
|
|
||||||
goodwill_amount: { $ref: '#/components/schemas/Money' }
|
|
||||||
include_in_kfo: { type: boolean }
|
|
||||||
comment: { type: [string, 'null'] }
|
|
||||||
updated_by:
|
|
||||||
oneOf:
|
|
||||||
- $ref: '#/components/schemas/Ref'
|
|
||||||
- type: 'null'
|
|
||||||
updated_at: { type: [string, 'null'], format: date-time }
|
|
||||||
|
|
||||||
GoodwillTotalsOut:
|
|
||||||
type: object
|
type: object
|
||||||
required: [financial_investment_amount, participation_amount, goodwill_amount, goodwill_in_kfo_amount]
|
required:
|
||||||
|
- head_legal_entity
|
||||||
|
- totals
|
||||||
|
title: GoodwillGroupOut
|
||||||
|
description: Итог «Всего» блока одной ГО.
|
||||||
|
GoodwillRowKeyIn:
|
||||||
properties:
|
properties:
|
||||||
financial_investment_amount: { $ref: '#/components/schemas/Money' }
|
ownership_share:
|
||||||
participation_amount: { $ref: '#/components/schemas/Money' }
|
anyOf:
|
||||||
goodwill_amount: { $ref: '#/components/schemas/Money' }
|
- type: string
|
||||||
goodwill_in_kfo_amount:
|
- type: 'null'
|
||||||
allOf: [{ $ref: '#/components/schemas/Money' }]
|
title: Ownership Share
|
||||||
description: Сумма goodwill_amount только по строкам include_in_kfo = true с положительным goodwill_amount
|
include_in_kfo:
|
||||||
|
type: boolean
|
||||||
GoodwillRowIn:
|
title: Include In Kfo
|
||||||
type: object
|
|
||||||
required: [ownership_share, include_in_kfo, comment]
|
|
||||||
properties:
|
|
||||||
ownership_share: { $ref: '#/components/schemas/ShareIn' }
|
|
||||||
include_in_kfo: { type: boolean }
|
|
||||||
comment:
|
comment:
|
||||||
type: [string, 'null']
|
anyOf:
|
||||||
maxLength: 1000
|
- type: string
|
||||||
description: Обязателен (непустой после обрезки), если include_in_kfo = true
|
maxLength: 1000
|
||||||
|
- type: 'null'
|
||||||
GoodwillSettingsIn:
|
title: Comment
|
||||||
|
head_legal_entity_id:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
title: Head Legal Entity Id
|
||||||
|
subsidiary_legal_entity_id:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
title: Subsidiary Legal Entity Id
|
||||||
|
additionalProperties: false
|
||||||
type: object
|
type: object
|
||||||
required: [goodwill_enabled]
|
required:
|
||||||
|
- ownership_share
|
||||||
|
- include_in_kfo
|
||||||
|
- head_legal_entity_id
|
||||||
|
- subsidiary_legal_entity_id
|
||||||
|
title: GoodwillRowKeyIn
|
||||||
|
description: 'Строка пакетного сохранения: пара ГО → ДО и ручной ввод.'
|
||||||
|
GoodwillRowOut:
|
||||||
properties:
|
properties:
|
||||||
goodwill_enabled: { type: boolean }
|
head_legal_entity:
|
||||||
|
$ref: '#/components/schemas/RefOut'
|
||||||
|
subsidiary_legal_entity:
|
||||||
|
$ref: '#/components/schemas/RefOut'
|
||||||
|
ownership_share:
|
||||||
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
- type: 'null'
|
||||||
|
title: Ownership Share
|
||||||
|
financial_investment_amount:
|
||||||
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
- type: 'null'
|
||||||
|
title: Financial Investment Amount
|
||||||
|
charter_capital_amount:
|
||||||
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
- type: 'null'
|
||||||
|
title: Charter Capital Amount
|
||||||
|
additional_capital_amount:
|
||||||
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
- type: 'null'
|
||||||
|
title: Additional Capital Amount
|
||||||
|
participation_amount:
|
||||||
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
- type: 'null'
|
||||||
|
title: Participation Amount
|
||||||
|
goodwill_amount:
|
||||||
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
- type: 'null'
|
||||||
|
title: Goodwill Amount
|
||||||
|
include_in_kfo:
|
||||||
|
type: boolean
|
||||||
|
title: Include In Kfo
|
||||||
|
comment:
|
||||||
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
- type: 'null'
|
||||||
|
title: Comment
|
||||||
|
has_investments:
|
||||||
|
type: boolean
|
||||||
|
title: Has Investments
|
||||||
|
warnings:
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/WarningOut'
|
||||||
|
type: array
|
||||||
|
title: Warnings
|
||||||
|
updated_by:
|
||||||
|
anyOf:
|
||||||
|
- $ref: '#/components/schemas/RefOut'
|
||||||
|
- type: 'null'
|
||||||
|
updated_at:
|
||||||
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
format: date-time
|
||||||
|
- type: 'null'
|
||||||
|
title: Updated At
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- head_legal_entity
|
||||||
|
- subsidiary_legal_entity
|
||||||
|
- ownership_share
|
||||||
|
- financial_investment_amount
|
||||||
|
- charter_capital_amount
|
||||||
|
- additional_capital_amount
|
||||||
|
- participation_amount
|
||||||
|
- goodwill_amount
|
||||||
|
- include_in_kfo
|
||||||
|
- comment
|
||||||
|
- has_investments
|
||||||
|
- warnings
|
||||||
|
- updated_by
|
||||||
|
- updated_at
|
||||||
|
title: GoodwillRowOut
|
||||||
|
GoodwillSettingsIn:
|
||||||
|
properties:
|
||||||
|
goodwill_enabled:
|
||||||
|
type: boolean
|
||||||
|
title: Goodwill Enabled
|
||||||
|
additionalProperties: false
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- goodwill_enabled
|
||||||
|
title: GoodwillSettingsIn
|
||||||
|
GoodwillTableOut:
|
||||||
|
properties:
|
||||||
|
version_id:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
title: Version Id
|
||||||
|
goodwill_enabled:
|
||||||
|
type: boolean
|
||||||
|
title: Goodwill Enabled
|
||||||
|
editable:
|
||||||
|
type: boolean
|
||||||
|
title: Editable
|
||||||
|
read_only_reason:
|
||||||
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
enum:
|
||||||
|
- VERSION_NOT_EDITABLE
|
||||||
|
- LOCK_REQUIRED
|
||||||
|
- LOCKED_BY_OTHER
|
||||||
|
- type: 'null'
|
||||||
|
title: Read Only Reason
|
||||||
|
rows:
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/GoodwillRowOut'
|
||||||
|
type: array
|
||||||
|
title: Rows
|
||||||
|
groups:
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/GoodwillGroupOut'
|
||||||
|
type: array
|
||||||
|
title: Groups
|
||||||
|
totals:
|
||||||
|
$ref: '#/components/schemas/GoodwillTotalsOut'
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- version_id
|
||||||
|
- goodwill_enabled
|
||||||
|
- editable
|
||||||
|
- read_only_reason
|
||||||
|
- rows
|
||||||
|
- groups
|
||||||
|
- totals
|
||||||
|
title: GoodwillTableOut
|
||||||
|
GoodwillTotalsOut:
|
||||||
|
properties:
|
||||||
|
financial_investment_amount:
|
||||||
|
type: string
|
||||||
|
title: Financial Investment Amount
|
||||||
|
charter_capital_amount:
|
||||||
|
type: string
|
||||||
|
title: Charter Capital Amount
|
||||||
|
participation_amount:
|
||||||
|
type: string
|
||||||
|
title: Participation Amount
|
||||||
|
goodwill_amount:
|
||||||
|
type: string
|
||||||
|
title: Goodwill Amount
|
||||||
|
goodwill_in_kfo_amount:
|
||||||
|
type: string
|
||||||
|
title: Goodwill In Kfo Amount
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- financial_investment_amount
|
||||||
|
- charter_capital_amount
|
||||||
|
- participation_amount
|
||||||
|
- goodwill_amount
|
||||||
|
- goodwill_in_kfo_amount
|
||||||
|
title: GoodwillTotalsOut
|
||||||
|
HTTPValidationError:
|
||||||
|
properties:
|
||||||
|
detail:
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/ValidationError'
|
||||||
|
type: array
|
||||||
|
title: Detail
|
||||||
|
type: object
|
||||||
|
title: HTTPValidationError
|
||||||
|
RefOut:
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
title: Id
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
title: Name
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
title: RefOut
|
||||||
|
description: 'Ссылка на объект справочника: идентификатор и название (ГК, филиал, ГСК/ГСЗ).'
|
||||||
|
ValidationError:
|
||||||
|
properties:
|
||||||
|
loc:
|
||||||
|
items:
|
||||||
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
- type: integer
|
||||||
|
type: array
|
||||||
|
title: Location
|
||||||
|
msg:
|
||||||
|
type: string
|
||||||
|
title: Message
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
title: Error Type
|
||||||
|
input:
|
||||||
|
title: Input
|
||||||
|
ctx:
|
||||||
|
type: object
|
||||||
|
title: Context
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- loc
|
||||||
|
- msg
|
||||||
|
- type
|
||||||
|
title: ValidationError
|
||||||
|
WarningOut:
|
||||||
|
properties:
|
||||||
|
code:
|
||||||
|
type: string
|
||||||
|
title: Code
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
title: Message
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- code
|
||||||
|
- message
|
||||||
|
title: WarningOut
|
||||||
|
|||||||
@ -0,0 +1,2 @@
|
|||||||
|
schema: spec-driven
|
||||||
|
created: 2026-11-06
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
## Context
|
||||||
|
|
||||||
|
Решение согласовано владельцем 27.10.2026 (комментарий в AURORA-1864): мягкие соотношения одной цели объединяются в
|
||||||
|
группу альтернатив, знак 2410 не определяется. Реализация — `arm_statements/checks.py` (`checks_from`) и загрузчик
|
||||||
|
словаря (`loader.py`); RSHB/pylib_ai_arm_statements#3.
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
|
||||||
|
- Группа считается в `checks_from` по паре (колонка, `group`) среди уже посчитанных исходов; `evaluate_relations` и
|
||||||
|
исходы для шага 8 не меняются — поэтому подсветка и Р-21 остаются прежними (каждая альтернатива подтверждает
|
||||||
|
значения сама, как раньше).
|
||||||
|
- «Сошлась» — расхождение в пределах допуска ±1 (`within_tolerance`), как для мягкого соотношения без группы.
|
||||||
|
- Проверки «`group` только у мягкого» и «у группы одна цель» — в загрузчике: жёсткая группа означала бы, что статус документа зависит от
|
||||||
|
выбора альтернативы, а этого решение не предусматривает.
|
||||||
|
|
||||||
|
## Decisions made without discussion
|
||||||
|
|
||||||
|
| Дата | Решение | Обоснование | Цена ошибки |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 2026-11-06 | Имя группы в словаре — `net_profit` для обоих наборов | Группа — по форме и варианту (`relations_for`), одно имя не смешивает полный и упрощённый наборы; имя описывает цель 2400 | Нулевая: имя только в словаре, наружу не выходит |
|
||||||
|
| 2026-11-06 | Если у всех несошедшихся альтернатив пуста цель или все члены (сравнить не с чем) — выдаётся первая по словарю | Расхождения нет, «ближайшую» выбрать не по чему; порядок словаря детерминирован | Низкая: текст нарушения другой альтернативы, сам факт нарушения тот же |
|
||||||
|
| 2026-11-06 | При равном расхождении выдаётся первая по словарю | Детерминированность | Нулевая |
|
||||||
|
| 2026-11-06 | Тест `test_simplified_income_soft` (2400 = 500 при 1000 − 600 ± 50) теперь ожидает нарушение новой альтернативы `… + 2410` — она ближе к цели (450 против 350) | Прямое следствие правила «ближайшая к цели» | Нулевая: данные теста неверны в обоих вариантах |
|
||||||
|
|
||||||
|
## Risks / Trade-offs
|
||||||
|
|
||||||
|
- Новая альтернатива упрощённого набора (`… + 2410`) при совпадении подтверждает неуверенные значения своих кодов
|
||||||
|
(Р-21), включая положительный 2410 — это и есть желаемое поведение для дохода по налогу.
|
||||||
|
- Документы, загруженные до выкладки 0.1.4, сохраняют прежние `checks` до пересчёта (правка аналитика) — ложное
|
||||||
|
предупреждение у них останется; переразбор не планируется.
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
## Why
|
||||||
|
|
||||||
|
Замечание тестировщика заказчика 23.10.2026 (AURORA-1864, ООО «Фавор плюс», ООО «Фактор»): у ОФР с положительной строкой
|
||||||
|
2410 «Налог на прибыль» (доход по налогу, ФСБУ 4/2023) появляется мягкое нарушение «2400 = 2300 − 2410 + 2420», хотя
|
||||||
|
форма верна (2400 = 2300 + 2410). 2410 — член `abs_terms`: правая часть считается и как записано, и с |2410|, но оба
|
||||||
|
варианта вычитают 2410. Второе соотношение «2400 = 2300 + 2410 + 2460» на таких данных сходится, а первое всё равно
|
||||||
|
выдаёт предупреждение. Аналитик видит «некорректную проверку».
|
||||||
|
|
||||||
|
## What Changes
|
||||||
|
|
||||||
|
- Словарь `statement_checks.yaml` (библиотека `pylib_ai_arm_statements` 0.1.4, RSHB/pylib_ai_arm_statements#3):
|
||||||
|
необязательный ключ `group` у мягких соотношений — группа альтернатив одной цели. В колонке сошлась хоть одна —
|
||||||
|
нарушений группы нет; не сошлась ни одна — одно нарушение, ближайшая к цели. `group` у жёсткого — ошибка загрузки.
|
||||||
|
- Соотношения 2400 ОФР — одна группа в полном наборе (`2400 = 2300 − 2410 + 2420`, `2400 = 2300 + 2410 + 2460`) и в
|
||||||
|
упрощённом (существующее + новое `2400 = 2110 − 2120 − 2330 + 2340 − 2350 + 2410`).
|
||||||
|
- Документы контекста: `05-domain-rules.md` §7 (правило группы, знак 2410 не определяется), `07-open-questions.md`
|
||||||
|
OQ-12 — закрыт в части знака 2410.
|
||||||
|
- Контракт `recognition-result` не меняется: формат `soft_relations_failed` прежний, меняется только состав нарушений.
|
||||||
|
|
||||||
|
Подъём версии библиотеки до 0.1.4 в arm-core, tabular-parser, scan-gateway — отдельными PR после merge AURORA-1677
|
||||||
|
(переезд на библиотеку; merge придержан владельцем до выкатки гудвилла).
|
||||||
|
|
||||||
|
## Non-goals
|
||||||
|
|
||||||
|
- Жёсткие проверки, подсветка, `needs_check`, подтверждение значений шагом 8 (Р-21) — без изменений.
|
||||||
|
- Формула старого бланка с 2430/2450 не добавляется.
|
||||||
|
- Словари по редакциям 66н / ФСБУ 4/2023 (OQ-146, OQ-150, AURORA-1554) — отдельная задача.
|
||||||
|
- Переразбор уже загруженных документов: новые проверки применяются к новым загрузкам и к пересчёту после правок.
|
||||||
|
|
||||||
|
## Impact
|
||||||
|
|
||||||
|
- Спека `statement-normalization` — требование «Шаг 7 — самопроверки §7».
|
||||||
|
- Репозитории: pylib_ai_arm_statements (код и словарь), arm-ka-docs (этот change); подъём пина в arm-core,
|
||||||
|
arm-tabular-parser, arm-scan-gateway — после AURORA-1677.
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
## MODIFIED Requirements
|
||||||
|
|
||||||
|
### Requirement: Шаг 7 — самопроверки §7
|
||||||
|
Шаг 7 SHALL считаться у обоих источников одним словарём `statement_checks.yaml` и выдавать `StatementChecks
|
||||||
|
{relations_failed[], soft_relations_failed[]}`; каждое нарушение — `{column_index, relation, codes, expected,
|
||||||
|
actual}`, где `codes` — коды цели и членов соотношения. Правила:
|
||||||
|
- значение кода в колонке — сумма по всем строкам `ok` с этим кодом; строки `detail`, `unreadable`, `missing` в
|
||||||
|
соотношения не входят; нарушение относится ко всем строкам его кодов;
|
||||||
|
- соотношение **посчитано**, если непуста цель или хотя бы один член (есть строка `ok` с кодом и `amount` не `null`);
|
||||||
|
пусто всё — соотношение пропускается; пустая цель при непустых членах и непустая цель при пустых членах — нарушение;
|
||||||
|
- жёсткое соотношение не сошлось, если расхождение больше допуска ±1 в единицах формы **и** больше 0,001 % наибольшего
|
||||||
|
по модулю числа соотношения — тогда оно в `relations_failed`; расхождение в пределах округления и мягкие
|
||||||
|
соотношения — в `soft_relations_failed`;
|
||||||
|
- члены `abs_terms` (2120, 2210, 2220, 2330, 2350, 2410) сравниваются и как записаны, и по модулю; такое соотношение
|
||||||
|
подтверждает величину, но не знак (шаг 8);
|
||||||
|
- набор соотношений — по `form_variant` (полный или упрощённый); `form_variant = null` — полный. В упрощённом наборе
|
||||||
|
соотношения ББ жёсткие, а `2400 = 2110 − 2120 − 2330 + 2340 − 2350 − 2410` и `2400 = 2110 − 2120 − 2330 + 2340 −
|
||||||
|
2350 + 2410` ОФР — мягкие, как `2400` полного набора;
|
||||||
|
- **группа альтернатив** (`group` в словаре, только у мягких соотношений одной формы и варианта): в колонке сошлась
|
||||||
|
хоть одна альтернатива — ни одна не попадает в `soft_relations_failed`; не сошлась ни одна — в
|
||||||
|
`soft_relations_failed` одно нарушение, ближайшая к цели альтернатива (меньшее расхождение; при пустой цели или пустых
|
||||||
|
членах — первая по словарю). `group` у жёсткого соотношения и разные цели в одной группе — ошибка загрузки словаря. Соотношения 2400 каждого
|
||||||
|
набора — одна группа: полный — `2400 = 2300 − 2410 + 2420` и `2400 = 2300 + 2410 + 2460`, упрощённый — два варианта
|
||||||
|
выше. Знак 2410 (расход или доход по налогу, ФСБУ 4/2023) не определяется — принимается любая альтернатива (OQ-12).
|
||||||
|
Группа не меняет жёстких проверок, подсветки, `needs_check` и подтверждения значений (шаг 8, Р-21);
|
||||||
|
- родитель пятизначной подстроки — ближайшая четырёхзначная строка выше с теми же первыми тремя цифрами, иначе код из
|
||||||
|
первых четырёх цифр; «сумма подстрок = родитель» (мягкое) — только если хотя бы одна подстрока в колонке непуста.
|
||||||
|
|
||||||
|
`checks` SHALL быть у каждого `BALANCE` / `INCOME` со строками и отсутствовать у документа без строк.
|
||||||
|
`duplicate_line_codes` MUST NOT выдаваться.
|
||||||
|
|
||||||
|
#### Scenario: «БАЛАНС» без кода
|
||||||
|
- **WHEN** строка «БАЛАНС» ушла в `detail` (код потерян), в колонке есть 1100 и 1200
|
||||||
|
- **THEN** соотношение `1600 = 1100 + 1200` посчитано и нарушено (пустая цель при непустых членах), в
|
||||||
|
`relations_failed`
|
||||||
|
|
||||||
|
#### Scenario: Лист только с активом
|
||||||
|
- **WHEN** в ББ заполнены 1100, 1200, 1600, а 1300–1700 отсутствуют
|
||||||
|
- **THEN** `1600 = 1700` нарушено (непустая цель при пустых членах), документ `needs_check`
|
||||||
|
|
||||||
|
#### Scenario: Повтор кода в соотношении
|
||||||
|
- **WHEN** две строки 2410 с суммами 100 и 649
|
||||||
|
- **THEN** в соотношениях код 2410 равен 749
|
||||||
|
|
||||||
|
#### Scenario: Упрощённый ОФР с доходом по налогу
|
||||||
|
- **WHEN** у упрощённого ОФР 2410 записан со знаком дохода, 2400 с ним сходится только по `2400 = 2110 − 2120 − 2330 +
|
||||||
|
2340 − 2350 + 2410`
|
||||||
|
- **THEN** нарушений по 2400 в `soft_relations_failed` нет
|
||||||
|
|
||||||
|
#### Scenario: Доход по налогу в полной форме (AURORA-1864)
|
||||||
|
- **WHEN** в колонке ОФР 2300 = 100, 2410 = 20 (без минуса и скобок), 2400 = 120
|
||||||
|
- **THEN** `2400 = 2300 − 2410 + 2420` не сошлось, но сошлось `2400 = 2300 + 2410 + 2460` из той же группы — нарушений
|
||||||
|
по 2400 в `soft_relations_failed` нет
|
||||||
|
|
||||||
|
#### Scenario: Расход по налогу в полной форме
|
||||||
|
- **WHEN** 2300 = 100, 2410 = −20 или (20) или 20, 2400 = 80
|
||||||
|
- **THEN** сходится `2400 = 2300 − 2410 + 2420` — нарушений по 2400 в `soft_relations_failed` нет
|
||||||
|
|
||||||
|
#### Scenario: Неверная чистая прибыль — одно нарушение
|
||||||
|
- **WHEN** 2300 = 100, 2410 = 20, 2400 = 150 — не сходится ни одна альтернатива группы
|
||||||
|
- **THEN** в `soft_relations_failed` одно нарушение по 2400 — `2400 = 2300 + 2410 + 2460` (`actual` 120 ближе к 150,
|
||||||
|
чем 80); документ из-за него не `needs_check`
|
||||||
|
|
||||||
|
#### Scenario: Группа считается по колонке
|
||||||
|
- **WHEN** в первой колонке 2400 сходится с одной из альтернатив, во второй — ни с одной
|
||||||
|
- **THEN** нарушение по 2400 одно и только у второй колонки
|
||||||
|
|
||||||
|
#### Scenario: Группа у жёсткого соотношения
|
||||||
|
- **WHEN** в `statement_checks.yaml` у соотношения со `strict: true` указан `group`
|
||||||
|
- **THEN** словарь не загружается (ошибка загрузки `statement_checks.yaml`)
|
||||||
|
|
||||||
|
#### Scenario: Округление итогов
|
||||||
|
- **WHEN** `1600 = 1700` расходится на 9,02 при итогах ~17 млрд
|
||||||
|
- **THEN** нарушение в `soft_relations_failed`, на статус и подсветку не влияет
|
||||||
@ -612,8 +612,15 @@ actual}`, где `codes` — коды цели и членов соотноше
|
|||||||
- члены `abs_terms` (2120, 2210, 2220, 2330, 2350, 2410) сравниваются и как записаны, и по модулю; такое соотношение
|
- члены `abs_terms` (2120, 2210, 2220, 2330, 2350, 2410) сравниваются и как записаны, и по модулю; такое соотношение
|
||||||
подтверждает величину, но не знак (шаг 8);
|
подтверждает величину, но не знак (шаг 8);
|
||||||
- набор соотношений — по `form_variant` (полный или упрощённый); `form_variant = null` — полный. В упрощённом наборе
|
- набор соотношений — по `form_variant` (полный или упрощённый); `form_variant = null` — полный. В упрощённом наборе
|
||||||
соотношения ББ жёсткие, а `2400 = 2110 − 2120 − 2330 + 2340 − 2350 − 2410` ОФР — мягкое, как `2400` полного набора
|
соотношения ББ жёсткие, а `2400 = 2110 − 2120 − 2330 + 2340 − 2350 − 2410` и `2400 = 2110 − 2120 − 2330 + 2340 −
|
||||||
(знак 2410, OQ-12);
|
2350 + 2410` ОФР — мягкие, как `2400` полного набора;
|
||||||
|
- **группа альтернатив** (`group` в словаре, только у мягких соотношений одной формы и варианта): в колонке сошлась
|
||||||
|
хоть одна альтернатива — ни одна не попадает в `soft_relations_failed`; не сошлась ни одна — в
|
||||||
|
`soft_relations_failed` одно нарушение, ближайшая к цели альтернатива (меньшее расхождение; при пустой цели или пустых
|
||||||
|
членах — первая по словарю). `group` у жёсткого соотношения и разные цели в одной группе — ошибка загрузки словаря. Соотношения 2400 каждого
|
||||||
|
набора — одна группа: полный — `2400 = 2300 − 2410 + 2420` и `2400 = 2300 + 2410 + 2460`, упрощённый — два варианта
|
||||||
|
выше. Знак 2410 (расход или доход по налогу, ФСБУ 4/2023) не определяется — принимается любая альтернатива (OQ-12).
|
||||||
|
Группа не меняет жёстких проверок, подсветки, `needs_check` и подтверждения значений (шаг 8, Р-21);
|
||||||
- родитель пятизначной подстроки — ближайшая четырёхзначная строка выше с теми же первыми тремя цифрами, иначе код из
|
- родитель пятизначной подстроки — ближайшая четырёхзначная строка выше с теми же первыми тремя цифрами, иначе код из
|
||||||
первых четырёх цифр; «сумма подстрок = родитель» (мягкое) — только если хотя бы одна подстрока в колонке непуста.
|
первых четырёх цифр; «сумма подстрок = родитель» (мягкое) — только если хотя бы одна подстрока в колонке непуста.
|
||||||
|
|
||||||
@ -634,9 +641,31 @@ actual}`, где `codes` — коды цели и членов соотноше
|
|||||||
- **THEN** в соотношениях код 2410 равен 749
|
- **THEN** в соотношениях код 2410 равен 749
|
||||||
|
|
||||||
#### Scenario: Упрощённый ОФР с доходом по налогу
|
#### Scenario: Упрощённый ОФР с доходом по налогу
|
||||||
- **WHEN** у упрощённого ОФР 2410 записан со знаком дохода, и `2400 = 2110 − 2120 − 2330 + 2340 − 2350 − 2410` по модулю
|
- **WHEN** у упрощённого ОФР 2410 записан со знаком дохода, 2400 с ним сходится только по `2400 = 2110 − 2120 − 2330 +
|
||||||
не сходится
|
2340 − 2350 + 2410`
|
||||||
- **THEN** нарушение в `soft_relations_failed`, документ из-за него не `needs_check`
|
- **THEN** нарушений по 2400 в `soft_relations_failed` нет
|
||||||
|
|
||||||
|
#### Scenario: Доход по налогу в полной форме (AURORA-1864)
|
||||||
|
- **WHEN** в колонке ОФР 2300 = 100, 2410 = 20 (без минуса и скобок), 2400 = 120
|
||||||
|
- **THEN** `2400 = 2300 − 2410 + 2420` не сошлось, но сошлось `2400 = 2300 + 2410 + 2460` из той же группы — нарушений
|
||||||
|
по 2400 в `soft_relations_failed` нет
|
||||||
|
|
||||||
|
#### Scenario: Расход по налогу в полной форме
|
||||||
|
- **WHEN** 2300 = 100, 2410 = −20 или (20) или 20, 2400 = 80
|
||||||
|
- **THEN** сходится `2400 = 2300 − 2410 + 2420` — нарушений по 2400 в `soft_relations_failed` нет
|
||||||
|
|
||||||
|
#### Scenario: Неверная чистая прибыль — одно нарушение
|
||||||
|
- **WHEN** 2300 = 100, 2410 = 20, 2400 = 150 — не сходится ни одна альтернатива группы
|
||||||
|
- **THEN** в `soft_relations_failed` одно нарушение по 2400 — `2400 = 2300 + 2410 + 2460` (`actual` 120 ближе к 150,
|
||||||
|
чем 80); документ из-за него не `needs_check`
|
||||||
|
|
||||||
|
#### Scenario: Группа считается по колонке
|
||||||
|
- **WHEN** в первой колонке 2400 сходится с одной из альтернатив, во второй — ни с одной
|
||||||
|
- **THEN** нарушение по 2400 одно и только у второй колонки
|
||||||
|
|
||||||
|
#### Scenario: Группа у жёсткого соотношения
|
||||||
|
- **WHEN** в `statement_checks.yaml` у соотношения со `strict: true` указан `group`
|
||||||
|
- **THEN** словарь не загружается (ошибка загрузки `statement_checks.yaml`)
|
||||||
|
|
||||||
#### Scenario: Округление итогов
|
#### Scenario: Округление итогов
|
||||||
- **WHEN** `1600 = 1700` расходится на 9,02 при итогах ~17 млрд
|
- **WHEN** `1600 = 1700` расходится на 9,02 при итогах ~17 млрд
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user