15 KiB
Контракт API результата КФО (AURORA-1546 / AURORA-1547)
Контракт вкладки «КФО» отчёта версии консолидации — до реализации (docs #206, OpenSpec change
kfo-calculation-contract). Машиночитаемая копия — dev/api-contract-kfo.openapi.yaml с тремя полными примерами
ответа (их можно брать как фейк для экрана). Когда расчёт появится в arm-core, копия выгружается из app.openapi() и
сверяется тестом, как у гудвилла; если файлы разойдутся с кодом — прав код, оба файла правятся вслед за ним.
Источники, в порядке приоритета:
05-domain-rules.md§8 «КФО» — алгоритм (п. 1–12) и сквозной пример. Здесь формулы не повторяются — только ссылки «п. N».- DBML v5.26:
kfo_result,kfo_result_line,kfo_result_line_company,consolidation_version. - DOC-274647 «Экран: КФО» (черновик) и макет
[31-04],[31-04-01]— состав колонок, состояния экрана.
1. Общее
Как в dev/api-contract-corrections.md §1 и dev/api-contract-goodwill.md §1:
- префикс
/api/v1,Authorization: Bearer <JWT>; - чтение — право
KFO_VIEW(неCONSOLIDATION_VIEW, как у корректировок и гудвилла: право в seed есть и означает ровно это), правки —CONSOLIDATION_EDIT(KFO_EDITв seed нет); - версия вне видимости — 404
NOT_FOUND, как несуществующая; - доменные ошибки —
{"detail": {"code", "message", ...}}, 422 валидации тела — массив pydantic; - деньги — строки с двумя знаками в тыс. руб. (
"588500.00"), полеunits = "thousand_rub". Это отличие от корректировок и гудвилла, где рубли: результат КФО по определению в тысячах (округление — часть расчёта, §8 «КФО» п. 6), рубли из него не восстановить. Переключатели «Единицы» (тыс. / млн) и «Знаков после запятой» — только показ; - проценты — строки с двумя знаками (
"70.42"),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. Понятия
- Строки — бланк ББ и ОФР редакции на отчётную дату версии (66н до 31.12.2024, ФСБУ 4 позже) плюс служебная
GOODWILLв разделе I сразу после 1170 (§8 «КФО» п. 1, 8). Приходят все строки бланка в его порядке (ordinal), включая нулевые;is_total— итоговая строка. - По компании (
companies[]строки, порядок — какKfoResultOut.companies): «По данным клиента» (client_amount), «В том числе взаимные обязательства / обороты» (vgo_amount), «Очищенные показатели» (cleaned_amount = client_amount − vgo_amount), «Доля в показателе по группе, %» (share_percent). Строки расходов (2120, 2210, 2220, 2330, 2350) — со знаком минус, и ихvgo_amountтоже (п. 2, 6). УGOODWILLразреза нет. - По строке:
sum_amount(Σ клиента),vgo_amount(Σ взаимных =eliminated_auto + eliminated_manual),goodwill_adjust(уGOODWILL, 1100, 1600),bank_amount— «КФО, подготовленная банком» (sum_amount − vgo_amount + goodwill_adjust),deviation_amount— «Расхождения» (у итоговnull),comment. - Сводка расхождений (
summary.balance,summary.income) — две плашки экрана: сумма расхождений, база (base_kind: ЧА / ВБ / прибыль от продаж / выручка), предел и процент от базы,exceeded— красная плашка (п. 10). При превышении у строки базыis_threshold_base = true— подсветка. - Обоснование (
threshold_justification) — принятие риска при превышении;justification_required— превышение есть хотя бы по одному отчёту. Обязательность перед отправкой на верификацию проверяет переход статуса (AURORA-2002), не этот API. - Реквизиты формы (
requisites, п. 11): ГК, ГСК, отчётная дата, номер и статус версии, сценарий, подход (пакет документов), причины отклонений от Методики (methodology_deviations— редактируется здесь), решение УОБ (только чтение), корректировки — число агрегатов с применённой корректировкой и Σ их исключений. - Предупреждения (
warnings[], п. 12) — не блокируют:FORM_MISSING,FORM_AMBIGUOUS,FORM_UNITS_UNKNOWN,LINE_OUTSIDE_BLANK,UNALLOCATED_ROWS(count— строк),INCOME_RULES_MISSING,GOODWILL_NOT_APPLIED,GOODWILL_ROW_REASSIGNED. Текстыmessage— с сервера, фронт показывает как есть.
3. Эндпоинты
| Метод и путь | Право | Запрос | Ответ | Ошибки |
|---|---|---|---|---|
GET /consolidations/versions/{version_id}/kfo |
KFO_VIEW |
— | 200 KfoResultOut |
404 NOT_FOUND |
PUT /consolidations/versions/{version_id}/kfo/annotations |
CONSOLIDATION_EDIT |
KfoAnnotationsIn |
200 KfoResultOut |
404 NOT_FOUND, 409 правок версии, 422 UNKNOWN_LINE, 422 валидации тела |
Выгрузки («Таблица», «Форма 2.03.01.01с») — AURORA-1565, отдельным контрактом.
3.1 GET …/kfo — результат
Весь результат одним ответом, без страниц. Пока версия не заморожена, ответ — по текущим данным версии: если
что-то изменилось после computed_at (документы, сопоставление, разнесение, корректировки, гудвилл), сервер
пересчитывает и сохраняет результат до ответа (как он это обнаруживает — AURORA-1417). Кнопки «Рассчитать» нет. У
замороженной версии (is_frozen = true, ставится при «Верифицирован») — сохранённый результат без пересчёта,
editable = false.
Версия без компаний или без форм — не ошибка: строки бланка с нулями и warnings (FORM_MISSING по каждой компании
и отчёту).
3.2 PUT …/kfo/annotations — ручные поля
Тело:
{
"comments": [{"statement_type": "balance", "line_code": "1520", "comment": "Акт сверки на 01.10 не получен"}],
"threshold_justification": "Расхождение по 1520 — сверка в работе; риск принят",
"methodology_deviations": null
}
- Поле, которого нет в теле, не меняется;
null— очищает. Пустой объект{}— допустим, ничего не пишет. comments[]— только изменённые строки;comment≤ 2000 символов,nullили пустой после обрезки — очистить. Строки нет в бланке версии (илиGOODWILLвincome) — 422UNKNOWN_LINEсdetail.statement_type,detail.line_code; ничего не сохраняется.threshold_justification,methodology_deviations— ≤ 4000 символов; длиннее — 422 массивом pydantic.- Обоснование можно сохранить и без превышения — сервер его не стирает;
justification_requiredот этого не меняется. - Всё одной транзакцией; комментарии и обоснование переживают пересчёт (по
statement_type,line_code). - Аудит — одно событие
KFO_EDITна запрос (object_type = kfo_result, разделKFO),before/after— только изменённые поля. Запрос без изменений аудит не пишет.
Ответ — KfoResultOut целиком (с пересчётом, если он нужен).
4. Схемы
Полностью — в OpenAPI. Кратко:
KfoResultOut
version_id uuid; computed_at date-time; is_frozen bool; editable bool; read_only_reason enum|null
units "thousand_rub"
companies[] {legal_entity_id, name, inn} — порядок колонок (по имени)
requisites KfoRequisitesOut
summary {balance: KfoThresholdOut, income: KfoThresholdOut}
justification_required bool; threshold_justification string|null
goodwill {enabled bool, total money}
balance, income {lines: KfoLineOut[]}
warnings[] KfoWarningOut {code, message, legal_entity_id?, statement_type?, count?}
KfoLineOut
line_code, line_name, ordinal, is_total, is_threshold_base
companies[] {legal_entity_id, client_amount, vgo_amount, cleaned_amount, share_percent|null} (у GOODWILL — [])
sum_amount, vgo_amount, eliminated_auto, eliminated_manual, goodwill_adjust, bank_amount money
deviation_amount money|null (у итогов null)
comment string|null
KfoThresholdOut
deviation_total money; base_kind NET_ASSETS|BALANCE_TOTAL|SALES_PROFIT|REVENUE; base_amount money
limit_percent "10.00"|"1.00"; limit_amount money; deviation_percent pct|null; exceeded bool
KfoRequisitesOut
company_group_name, related_group_name|null, reporting_date, version_no, version_status, scenario, approach
methodology_deviations|null, uob_decision_no|null, uob_decision_date|null
corrections_balance, corrections_income {count int, amount money}
KfoAnnotationsIn {comments?: [{statement_type, line_code, comment|null}], threshold_justification?, methodology_deviations?}
5. Состояния экрана (DOC-274647) → поля ответа
| Состояние | Как видно из ответа |
|---|---|
| Нет форм у части компаний | warnings[].code = FORM_MISSING с legal_entity_id, statement_type; у компании нули |
| ОФР не исключается автоматически | INCOME_RULES_MISSING (до AURORA-1999); взаимные обороты — только корректировками |
| Есть нераспределённые строки | UNALLOCATED_ROWS, count |
| Превышение порога | summary.*.exceeded = true, is_threshold_base у строки базы, justification_required = true |
| Гудвилл учтён | goodwill.enabled = true, goodwill.total, строка GOODWILL с bank_amount |
| Только чтение | editable = false, read_only_reason; при «Верифицирован» ещё is_frozen = true |
6. Примеры
Три полных ответа — в OpenAPI (examples у GET …/kfo), на числах сквозного примера §8 «КФО» (три компании, бланк
сокращён до строк примера; настоящий ответ содержит все строки бланка):
goodwill_exceeded— гудвилл включён, превышение порога ББ (42 900 > 37 100),justification_required = true;goodwill_disabled— та же версия без учёта гудвилла: строкаGOODWILL= 0, 1600 = 580 500;frozen— «Верифицирован»:is_frozen,editable = false, обоснование, комментарий 1520, реквизиты УОБ.
Фрагмент goodwill_exceeded — строка 1230:
{
"line_code": "1230", "line_name": "Дебиторская задолженность", "ordinal": 40,
"is_total": false, "is_threshold_base": false,
"companies": [
{"legal_entity_id": "1111…", "client_amount": "520000.00", "vgo_amount": "120000.00", "cleaned_amount": "400000.00", "share_percent": "70.42"},
{"legal_entity_id": "2222…", "client_amount": "130000.00", "vgo_amount": "10000.00", "cleaned_amount": "120000.00", "share_percent": "21.13"},
{"legal_entity_id": "3333…", "client_amount": "48000.00", "vgo_amount": "0.00", "cleaned_amount": "48000.00", "share_percent": "8.45"}
],
"sum_amount": "698000.00", "vgo_amount": "130000.00", "eliminated_auto": "100000.00", "eliminated_manual": "30000.00",
"goodwill_adjust": "0.00", "bank_amount": "568000.00", "deviation_amount": "2900.00", "comment": null
}
7. Открытые вопросы
Варианты, принятые на старте, могут измениться по ответу заказчика — контракт меняется вместе с §8: OQ-180 (строки вне бланка), OQ-181 (колонки), OQ-182 (значение без формы), OQ-183 (итоговая строка), OQ-184 (округление), OQ-185 (место гудвилла), OQ-186 (объём расхождений), OQ-187 (ЧА), OQ-188 (нулевая база), OQ-189 (действие при превышении), OQ-190/191 (подход по Методике, согласование клиентом — полей нет), OQ-192 (пересчёт).