From d8af9579aaebb5bfb546f31bf9970a0de86cd69c Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Wed, 7 Oct 2026 18:00:58 +0400 Subject: [PATCH] =?UTF-8?q?docs:=20=D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0?= =?UTF-8?q?=D0=BA=D1=82=20=D1=84=D0=B0=D0=B9=D0=BB=D0=BE=D0=B2=20=D0=B8=20?= =?UTF-8?q?=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BE=D1=87=D0=BD=D0=B8=D0=BA?= =?UTF-8?q?=D0=BE=D0=B2,=20=D0=BF=D0=BE=D0=BB=D1=8F=20=D0=BA=D0=BE=D0=BD?= =?UTF-8?q?=D1=81=D0=BE=D0=BB=D0=B8=D0=B4=D0=B0=D1=86=D0=B8=D0=B9=20(arm-c?= =?UTF-8?q?ore#42),=20OQ-43,=20=D0=BC=D0=BE=D0=B4=D0=B0=D0=BB=D0=BA=D0=B0?= =?UTF-8?q?=20[42]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #50. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2 --- context/07-open-questions.md | 2 +- context/10-user-journey.md | 8 +- dev/api-contract-files-directories.md | 106 ++++++++++++++++++++++++++ dev/api-contract-slice-3b.md | 1 + dev/api-contract-slice-4.md | 54 +++++++++---- mockup/INDEX.md | 2 +- 6 files changed, 151 insertions(+), 22 deletions(-) create mode 100644 dev/api-contract-files-directories.md diff --git a/context/07-open-questions.md b/context/07-open-questions.md index 96c4335..da8b9b9 100644 --- a/context/07-open-questions.md +++ b/context/07-open-questions.md @@ -48,7 +48,7 @@ | 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-41 | Экран «ЮЛ вне ГК» (`61`, заголовок «Юридические лица») показывает все ЮЛ с заполненной колонкой ГК, а не только монозаёмщиков. Это сводный реестр ЮЛ или фильтр `company_group_id IS NULL`? | макет [61] | срез 1 | допущение: сводный реестр всех ЮЛ с фильтром «вне ГК», по умолчанию выключенным | | OQ-42 | «Проверка распознавания» для ОСВ (xlsx) в макете отсутствует (строки `doc-row--readonly`, `39`). Нужен ли отдельный экран проверки ОСВ (дерево строк, подсветка контрагентов) или проверка ОСВ только через сводную ОСВ (`30`)? | макет [39] | срез 2 (UI) | **закрыт решением владельца 05.10.2026:** экран проверки ОСВ **нужен** (дерево строк, суммы, нераспознанные контрагенты); в макете его нет — проектируется в подсрезе 2d «UI первичных документов» | -| OQ-43 | Кнопка «К отчетности» неактивна у консолидаций в статусах «Инициация» и «Верификация РФ», активна у «Консолидация РФ» и «Верифицирован» (`34`). Каково правило доступности отчёта по статусу / роли? | макет [34] | срез 4, 7 (policy) | допущение: отчёт доступен с `CONSOLIDATION_RF` и далее для всех ролей с `CONSOLIDATION_VIEW`; «Инициация» — только карточка | +| OQ-43 | Кнопка «К отчетности» неактивна у консолидаций в статусах «Инициация» и «Верификация РФ», активна у «Консолидация РФ» и «Верифицирован» (`34`). Каково правило доступности отчёта по статусу / роли? | макет [34] | срез 4, 7 (policy) | **решено владельцем 07.10.2026 (arm-core#42, П-3):** «К отчетности» доступна во всех статусах, начиная с `INITIATED`, для ролей с `CONSOLIDATION_VIEW`; правка свода (сопоставление контрагента) — только «в работе» со своей блокировкой. Было: допущение: отчёт доступен с `CONSOLIDATION_RF` и далее для всех ролей с `CONSOLIDATION_VIEW`; «Инициация» — только карточка | | OQ-44 | «Добавить версию» создаёт версию сразу без модалки (`43-01`), копируя периметр; нужно ли подтверждение и выбор сценария/подхода новой версии? | макет [43-01] | срез 7 | допущение: без модалки, периметр и сценарий копируются из предыдущей версии | | OQ-45 | Контракт `recognition-result.schema.json` допускает `data_type = NU` (строки налогового учёта в ОСВ «БУ, НУ»), а enum DBML `osv_data_type` — только BU, CURRENCY, QUANTITY, SUM. Добавлять NU в DBML (v5.14) или не хранить строки НУ? | контракт v1.0 vs DBML | срез 2 (маппинг `osv_entry`) | **закрыт решением владельца 05.10.2026:** строки налогового учёта `NU` **хранить в ядре**: `osv_data_type` расширяется значением `NU` в DBML v5.15 (подсрез 2c, маппинг); контракт уже допускает `NU` | | OQ-46 | Обязательны ли все ОСВ расширенного подхода (02, 03, 08, 44, 26, 91, 51, 52, 59, 80, 83, 86, 97, 001, 008, 009, 011) при `approach = EXTENDED`, или часть — «при наличии»? | ТЗ 5.1; `required_document_rule.is_mandatory` | срез 0 (seed), срез 3 (чек-лист) | допущение принято и применено в Срезе 0: все 27 строк EXTENDED в seed `arm-core/api/seed/core/required_document_rules.yaml` (маркер `ASSUMPTION(OQ-46)`) — `is_mandatory = true`; BASIC — 10 строк, все обязательные; смена правила — правка одного yaml; вопрос к методологам остаётся открытым до Среза 3 (чек-лист); источник: arm-core, предложения, раздел A | diff --git a/context/10-user-journey.md b/context/10-user-journey.md index baedf10..7102e0b 100644 --- a/context/10-user-journey.md +++ b/context/10-user-journey.md @@ -72,12 +72,12 @@ | Шаг | Экран | Действие | БД / статус | |---|---|---|---| -| 2.1 | Сайдбар → **Новая консолидация** [42] | ГК → ГСК (активна после ГК) → Год → Квартал → **Создать**. `scenario = CREATE`, `approach = BASIC`, `goodwill_enabled = false` по умолчанию (OQ-27). **API (Срез 4):** `POST /consolidations` (`{company_group_id, related_group_id, year, quarter}`; ≥ 2 члена ГСК), ГСК для выбора — справочники | `consolidation`, `consolidation_version(INITIATED)`, `consolidation_member` из текущего состава ГСК | -| 2.2 | Отчётность → Группы компаний [03] → **Консолидации →** [34] | [03]: таблица ГК (Группа компаний, CRM ID, Основной РФ, Организаций), поиск по ГК, CRM ID или РФ. [34]: таблица консолидаций ГК: Год, Квартал, Версия (дерево версий под периодом), Статус (бейдж), ГСК, Дата создания, Дата верификации, Организаций; кнопки в строке **Взять в работу**, **К отчетности** (неактивна у статусов «Инициация» и «Верификация РФ» — по снимку, OQ-43), меню «…»; чекбокс «Только в работе». Выбор строки открывает панель **Организации** (Ответственный / Утверждён в РФ / Верифицирован в ГО; таблица Наименование, Документы, ОФР, Бух. баланс, ОСВ — перечень счетов, ИНН, Тип). **API:** `GET /company-groups/{id}/consolidations?in_work_only=` (периоды и версии, блокировка), `GET /consolidations/versions/{id}` (карточка: члены с ячейками чек-листа, история) | `consolidation_version`, `consolidation_lock`, `consolidation_member`, `document` | +| 2.1 | Сайдбар → **Новая консолидация** [42] | ГК → ГСК (активна после ГК) → Год → Квартал; после выбора ГСК — блок **«ЮЛ консолидации»**: все неархивные ЮЛ ГК, отмечены члены выбранной ГСК, отметки меняются, «Выбрано ЮЛ: N. Минимум для консолидации: 2» → **Создать** (периметр — отмеченные ЮЛ; ГСК в версии не хранится, П-2). `scenario = CREATE`, `approach = BASIC`, `goodwill_enabled = false` по умолчанию (OQ-27). **API (Срез 4, arm-core #42):** `POST /consolidations` (`{company_group_id, related_group_id, year, quarter, legal_entity_ids?}`; без списка — члены ГСК, со списком — отмеченные ЮЛ ГК, ≥ 2), ГСК и ЮЛ для выбора — справочники (`dev/api-contract-files-directories.md`) | `consolidation`, `consolidation_version(INITIATED)`, `consolidation_member` из текущего состава ГСК | +| 2.2 | Отчётность → Группы компаний [03] → **Консолидации →** [34] | [03]: таблица ГК (Группа компаний, CRM ID, Основной РФ, Организаций), поиск по ГК, CRM ID или РФ. [34]: таблица консолидаций ГК: Год, Квартал, Версия (дерево версий под периодом), Статус (бейдж), ГСК, Дата создания, Дата верификации, Организаций; кнопки в строке **Взять в работу**, **К отчетности** (по снимку неактивна у «Инициация» и «Верификация РФ»; решение владельца 07.10.2026 — доступна во всех статусах, OQ-43), меню «…»; чекбокс «Только в работе». Выбор строки открывает панель **Организации** (Ответственный / Утверждён в РФ / Верифицирован в ГО; таблица Наименование, Документы, ОФР, Бух. баланс, ОСВ — перечень счетов, ИНН, Тип). **API:** `GET /company-groups/{id}/consolidations?in_work_only=` (периоды и версии, блокировка), `GET /consolidations/versions/{id}` (карточка: члены — тип ЮЛ `entity_type`, самоописывающие ячейки чек-листа ББ/ОФР, счета загруженных ОСВ `osv_accounts`; история; «Ответственный» — `lock.locked_by_name` при активной блокировке, иначе `initiator.name`; «Утверждён в РФ» / «Верифицирован в ГО» и колонка «ГСК» — Срез 7) | `consolidation_version`, `consolidation_lock`, `consolidation_member`, `document` | | 2.3 | [34] → **Взять в работу** [35] | «Консолидация … будет закреплена за вами для редактирования». **API:** `POST …/versions/{id}/lock` (перехват — `takeover_reason`), `DELETE …/lock`; ручной статус — `POST …/status` | `consolidation_lock`, `audit_event(CONSOLIDATION_LOCK)` | | 2.4 | [34] панель Организации → **Редактировать состав** [36] | фильтр по ГСК, «Показать все ЮЛ в ГК», чекбоксы, Сохранить. **API:** `PUT …/versions/{id}/members` (`{legal_entity_ids}`), нужны статус «в работе» и своя блокировка | `consolidation_member` | | 2.5 | строка организации → **Документы** → drawer «Первичные документы» [39] | список: документ (имя, формат, дата; подпись типа у прочих — «Прочий документ», «Бухгалтерская отчетность»), Период («2024 К1», «2025 · 9 мес.»), Проверка (✓ / ✗ / — Период, Контрагент), Статус (Загружен / Обработка / Требуется проверка / Ошибка); иконки: комментарий (поповер «Комментарий к документу …», [39-01]) и удалить; **Редактировать документы** — в снимке неактивна; **Загрузить документы** [40]: модалка с зоной «Перетащите файлы сюда» / **Выбрать документы**, Загрузить; **тип документа и период в модалке не выбираются** — определяются при распознавании. **API:** загрузка — `POST /legal-entities/{id}/files?consolidation_version_id=`; документы и подтверждение — `/files`, `/documents` (Срез 2c); подтверждённый документ привязывается к версиям «в работе» автоматически | `stored_file(UPLOADED)`, `s3_object`, `recognition_job(queued)`, `document.period_check/counterparty_check` → `DOCUMENTS_PROCESSING` | -| 2.6 | [34] → **Скачать чек-лист** [37] | матрица Организация × (Бух. баланс, ОФР, ОСВ 01 58 60 62 66 67 76 90, Прочие); легенда: Загружен / Обработка / Требуется проверка / Ошибка загрузки / Отсутствует; Скачать CSV. **API:** `GET …/versions/{id}/checklist` (`rules[]`, `rows[].cells[]`: `status`, `missing_quarters`, `document_ids`); CSV в Срезе 4 нет | `required_document_rule × consolidation_member − document(CONFIRMED)` | +| 2.6 | [34] → **Скачать чек-лист** [37] | матрица Организация × (Бух. баланс, ОФР, ОСВ 01 58 60 62 66 67 76 90, Прочие); легенда: Загружен / Обработка / Требуется проверка / Ошибка загрузки / Отсутствует; Скачать CSV. **API:** `GET …/versions/{id}/checklist` (`rules[]`, `rows[].cells[]`: `document_type`, `account`, `status`, `missing_quarters`, `document_ids`); «Скачать CSV» — `?format=csv` (Срез 3b) | `required_document_rule × consolidation_member − document(CONFIRMED)` | | 2.7 | drawer [39] → клик по **PDF**-документу → **Проверка распознавания** [41] | слева «Исходный документ» постранично с масштабом; справа «Результат распознавания»: шапка формы (организация, ИНН, ОКПО/ОКОПФ/ОКФС, адрес, аудит, ОКУД, отчётная дата, ОКЕИ, единица измерения) и таблица Пояснения / Наименование показателя / Код / колонки-даты (в таблице есть строки без кода «в том числе …» и строка «Гудвилл 1105» ФСБУ 4/2023 — OQ-36, OQ-37); выпадающий список **Документ** для перехода между документами ЮЛ; **Добавить комментарий**; **Редактировать** [41-02] → кнопки **Сохранить** / **Отменить** (значения таблицы редактируются на месте); **Подтвердить данные**. Блок логических ошибок — по ТЗ (в снимках не виден). Для ОСВ (xlsx) экран в макете не открывается — строки readonly, OQ-42 | `financial_statement_meta/column/line/value.is_modified`, `osv_entry.is_modified`, `document(CONFIRMED)`, `comment`, `audit_event(RECOGNIZED_DATA_EDIT, DOCUMENT_CONFIRM)` → `DATA_CORRECTION` | Монозаёмщики [60] [84]: тот же drawer документов без консолидации — первичка в ЕХ напрямую. @@ -90,7 +90,7 @@ | Шаг | Вкладка | Действие | БД | |---|---|---|---| -| 3.1 | **ОСВ** [30] | сводная ОСВ: Компания ГК, Счёт, Период, Контрагенты, ИНН, 6 сумм, Тип контрагента. Баннер «Требуется указать соответствия… Осталось: N» → **Показать ЮЛ без ИНН** [32-osv-no-inn] → **Указать** → модалка «Выбор организации для связи с …» [32-osv-map-counterparty]: ИНН, Организация, ГК, ГСК, ГСЗ, блок «Рекомендуемые», **Связать**. При уходе с вкладки с несопоставленными — «Остались неуказанные ИНН… Остаться / Перейти» [31-00]. **API:** `GET …/versions/{id}/osv` (фильтры, `limit` ≤ 2000), `…/osv/summary` (баннер «Осталось: N» — `unmapped_total`, пробелы — `gaps[]`), `…/counterparty-candidates?scope=&q=&entry_id=` (блок «Рекомендуемые» — `recommended`), `POST …/osv/entries/{entry_id}/counterparty` (**Связать**), `GET …/osv/export` (**Экспорт**, xlsx) | вычисляется; `osv_entry.counterparty_id`, `legal_entity_alias`, `audit_event(OSV_COUNTERPARTY_MAP)` | +| 3.1 | **ОСВ** [30] | сводная ОСВ: Компания ГК, Счёт, Период, Контрагенты, ИНН, 6 сумм, Тип контрагента. Баннер «Требуется указать соответствия… Осталось: N» → **Показать ЮЛ без ИНН** [32-osv-no-inn] → **Указать** → модалка «Выбор организации для связи с …» [32-osv-map-counterparty]: ИНН, Организация, ГК, ГСК, ГСЗ, блок «Рекомендуемые», **Связать**. При уходе с вкладки с несопоставленными — «Остались неуказанные ИНН… Остаться / Перейти» [31-00]. **API:** `GET …/versions/{id}/osv` (фильтры, `limit` ≤ 2000), `…/osv/summary` (баннер «Осталось: N» и «Показать ЮЛ без ИНН» — `unmapped_total` / `?unmapped=true`: все несопоставленные строки, в том числе с ИНН вне справочника, решение владельца 07.10.2026; пробелы — `gaps[]`), `…/counterparty-candidates?scope=&q=&entry_id=` (блок «Рекомендуемые» — `recommended`), `POST …/osv/entries/{entry_id}/counterparty` (**Связать**), `GET …/osv/export` (**Экспорт**, xlsx) | вычисляется; `osv_entry.counterparty_id`, `legal_entity_alias`, `audit_event(OSV_COUNTERPARTY_MAP)` | | 3.2 | **Шахматка** [31-01] | фильтры Год, Период, Компании, Дт-счета, Кт-счета; матрица компания × компания: сумма A / сумма B / (расхождение) красным; Итого; ниже результирующая таблица «Статья × компания» | вычисляется (§5–6 правил) | | 3.3 | **Таблица корректировки** [31-02] [31-02-02] | фильтр «Отклонение» (Все); пары «Актив баланса ЮЛ-1 / Пассив баланса ЮЛ-2»: Наименование, Строка баланса, Счёт, Сумма; **Контроль**: % отклонения, Сумма отклонения; **Корректировка**: Строка баланса / Дт, Строка баланса / Кт, Комментарий; строка пары раскрывается в детализацию по субсчетам; Итого. В макете % отклонения считается к сумме стороны ЮЛ-1, а не к меньшей (OQ-35). **Редактировать** [31-02-01] → баннер «Режим редактирования включён…», ячейки пары и корректировки становятся полями ввода, **Отменить изменения** / **Сохранить** | `correction` (+ дочерние строки `parent_correction_id`), `audit_event(CORRECTION_*)`; ≥ 5 % → `ADJUSTMENT` | | 3.4 | **Гудвилл** [31-03] | здесь же включается/выключается расчёт гудвилла для консолидации (`goodwill_enabled`; переключателя в снимках нет — решение OQ-27); фильтр «Гудвилл: Все значения»; по головной организации (с «Выделить все» и строкой «Всего»): Учёт в отчёте ☐, Наименование дочерней организации, Доля владения, Фондовые вложения головной организации, Доля участия головной организации в уставном капитале дочерней организации, Уставный капитал, Гудвилл (+/−), Комментарий; **Редактировать** [31-03-01] → «Доступны для редактирования столбцы „Доля владения“ и „Комментарий“» | `consolidation_version.goodwill_enabled`, `goodwill(ownership_share, include_in_kfo, comment)` | diff --git a/dev/api-contract-files-directories.md b/dev/api-contract-files-directories.md new file mode 100644 index 0000000..2f3e0f6 --- /dev/null +++ b/dev/api-contract-files-directories.md @@ -0,0 +1,106 @@ +# Контракт API: файлы и документы организации, справочники (для экранов до сводной ОСВ) + +Источник — реальный код arm-core (`api/src/schemas/files.py`, `schemas/documents.py`, `schemas/directories.py`, +`schemas/common.py`, `api/endpoints/files/{upload,read,documents}.py`, `api/endpoints/directories/*.py`; Swagger — `/docs`). +Маршруты существуют со Срезов 1 и 2c; здесь они впервые описаны для фронта (arm-core #42, П-5). Общие правила (префикс, токен, +формат ошибок, видимость 404) — `dev/api-contract-slice-4.md` §1; форма ББ/ОФР, комментарии, исходный файл — `dev/api-contract-slice-3b.md`; +консолидации — `dev/api-contract-slice-4.md`. Экраны — `context/10-user-journey.md`, номера `[…]` — снимки макета (`mockup/INDEX.md`). + +## 1. Общее + +- Права: файлы и документы — чтение `DOCUMENT_VIEW`, загрузка/удаление/подтверждение — `DOCUMENT_EDIT`; справочники — + `DIRECTORY_VIEW` (импорт ЕЦП — `DIRECTORY_ADMIN`, только у администратора: кнопку «Импорт» на [34] скрывайте по `GET /me`). +- Страницы — `{items, total, limit, offset}`: у файлов ЮЛ и справочников `limit` 1…200 (по умолчанию 50), у строк ОСВ документа + 1…2000 (по умолчанию 500); `offset ≥ 0`; вне предела — 422 (pydantic-массив). +- ЮЛ, файл или документ вне видимости пользователя неотличимы от несуществующих: 404 `NOT_FOUND`. +- Перечисления: `FileType` — `XLS`, `XLSX`, `XLSB`, `PDF`, `PNG`, `JPG`; `FileStatus` — `UPLOADED`, `PROCESSING`, `PROCESSED`, `ERROR`, + `SUPERSEDED`; `RecognitionStatus` (задание) — `queued`, `published`, `processing`, `done`, `needs_check`, `error`; `DocumentType` — + `BALANCE`, `INCOME`, `OSV`, `DISCLOSURE`, `OTHER`; `DocumentStatus` — `RECOGNIZED`, `NEEDS_CHECK`, `CONFIRMED`, `ERROR`; + `DocumentCheckResult` — `MATCH`, `MISMATCH`, `UNKNOWN`; `EntityType` — `ЮЛ`, `ИП`; `RelatedGroupKind` — `gsk`, `gsz`. + +## 2. Эндпоинты: файлы и документы + +| Метод и путь | Право | Запрос | Ответ | Ошибки | Экран | +|---|---|---|---|---|---| +| `GET /legal-entities/{legal_entity_id}/files` | VIEW | query `limit`, `offset`, `include_superseded` (bool, по умолчанию `false` — заменённые скрыты) | `Page[FileOut]`, новые первыми (по убыванию `uploaded_at`) | 404 | [39] drawer «Первичные документы» | +| `POST /legal-entities/{legal_entity_id}/files` | EDIT | multipart `files[]`; query `consolidation_version_id?` | 201 `UploadResult` (принят хотя бы один файл) / 422 `UploadResult` (ни один) | 404 (ЮЛ; версия — `VERSION_NOT_FOUND`), 409 `VERSION_NOT_EDITABLE`, 422 `ENTITY_NOT_IN_PERIMETER`, 503 `STORAGE_UNAVAILABLE` | [40] | +| `GET /files/{file_id}` | VIEW | — | `FileOut` | 404 | опрос строки файла | +| `DELETE /files/{file_id}` | EDIT | — | 204 | 404, 409 `FILE_HAS_CONFIRMED_DOCUMENTS`, 409 `FILE_SUPERSEDES_OTHERS` | [39] иконка «удалить» | +| `GET /files/{file_id}/content` | VIEW | query `disposition` (`attachment` по умолчанию / `inline`) | поток исходного файла | 404 (`FILE_CONTENT_NOT_FOUND` — объекта нет в хранилище), 503 | [41] «Исходный документ» (см. контракт 3b) | +| `GET /documents/{document_id}` | VIEW | — | `DocumentOut` | 404 | [41], карточка документа | +| `GET /documents/{document_id}/entries` | VIEW | query `limit` (≤ 2000, по умолчанию 500), `offset` | `Page[EntryOut]` по возрастанию `row_number`; дерево — по `parent_entry_id` | 404 | строки ОСВ документа (только чтение) | +| `POST /documents/{document_id}/confirm` | EDIT | — | `DocumentOut` | 404, 409 `ALREADY_CONFIRMED` / `FILE_SUPERSEDED` / `DOCUMENT_NOT_CONFIRMABLE`; для ББ/ОФР — `PERIOD_REQUIRED`, `CHECKS_NOT_PASSED` | «Подтвердить данные» | + +Фильтра «файлы в контексте версии консолидации» **нет** (решение владельца 07.10.2026, arm-core #42): drawer показывает все +документы ЮЛ, период — в колонке «Период». Подходит ли документ версии, видно по ячейкам чек-листа версии (`document_ids`). + +## 3. Схемы: файлы и документы + +**`UploadResult`** `{accepted[], rejected[]}`: `accepted[]` — `{file_id, job_id, name}`; `rejected[]` — `{name, code, message, +file_id?}`, где `code` — `UNSUPPORTED_FILE` (тип не из списка или сигнатура не совпала), `FILE_TOO_LARGE` (> 50 МиБ), +`DUPLICATE_FILE` (такой файл у ЮЛ уже есть — `file_id` указывает на него), `STORAGE_UNAVAILABLE`. **Два разных тела 422**: при +отказе всех файлов — `UploadResult` (смотрите `rejected[]`); при ЮЛ вне периметра версии — доменная ошибка +`{"detail": {"code": "ENTITY_NOT_IN_PERIMETER", "message": …}}`. Различайте по наличию `detail`. + +**`FileOut`** `{id, legal_entity_id, original_name?, file_type, status (FileStatus), version_no, size_bytes?, content_hash?, +uploaded_at?, uploaded_by?, superseded_by_file_id?, job (JobBrief | null), documents[] (DocumentBrief)}` — поля с `?` могут быть +`null`. **`JobBrief`** `{id, status (RecognitionStatus), error_code?, error_message?, mapping_error?, warnings[], +mapping_warnings[], finished_at?}` — причина ошибки сервиса распознавания (`error_*`) или маппинга (`mapping_error`). +**`DocumentBrief`** `{id, document_type, osv_account_code?, period_year?, period_quarter?, is_cumulative?, status (DocumentStatus), +period_check?, counterparty_check?, locator?, comments_count}` — порядок: тип, счёт, `locator`. + +**`DocumentOut`** = поля `DocumentBrief` + `{file_id, legal_entity_id, confirmed_by?, confirmed_at?, group_schema? ([{type, name?, +has_inn?}]), warnings[]}`. **`EntryOut`** `{id, row_number?, level?, parent_entry_id?, row_value?, group_type?, group_name?, +data_type?, account_code?, account_root?, account_id?, counterparty_name?, counterparty_inn?, counterparty_id?, match_kind?, +opening_debit?, opening_credit?, turnover_debit?, turnover_credit?, closing_debit?, closing_credit?}` — деньги строками. + +### Как собрать строку drawer [39] + +Строка — **файл** (`FileOut`); документы файла (`documents[]`) — подписи и проверки: + +- «Период»: `period_year` + `period_quarter` + `is_cumulative` — квартальный «2024 К1», нарастающий Q3 — «2024 · 9 мес.» + (Q1 — «3 мес.», Q2 — «6 мес.», Q4 — «12 мес.»); `period_quarter = null` — «период не определён» (`dev/api-contract-slice-4.md`, + нюанс 17). +- «Проверка»: «Контрагент» — `counterparty_check` (`MATCH` ✓, `MISMATCH` ✗, `UNKNOWN`/`null` —); «Период» — `period_check` сейчас + всегда `UNKNOWN` → показывайте «—» (OQ-120). +- «Статус» (подписи — `context/10-user-journey.md`, «Словарь UI»): файл `UPLOADED`/`PROCESSING` — «Обработка»; файл `ERROR` — + «Ошибка» (причина — `job.error_message` / `job.mapping_error`); иначе по документу: `NEEDS_CHECK` — «Требуется проверка», + `RECOGNIZED`/`CONFIRMED` — «Загружен» (подтверждённый можно пометить отдельно). +- Комментарий — у **документа** (`comments_count`, `GET/POST /documents/{id}/comments`, контракт 3b); у файла без документов + комментария нет. +- Опрос во время распознавания: перечитывайте `GET /legal-entities/{id}/files` (или `GET /files/{id}` для одного файла), пока + файл в `UPLOADED`/`PROCESSING`; разумный интервал — 3–5 с. +- Клик по строке ББ/ОФР-документа (PDF и Excel) — экран [41] (`GET /documents/{id}/statement`, контракт 3b); строки ОСВ — только + чтение (`GET /documents/{id}/entries`). + +## 4. Эндпоинты: справочники (экраны [03], [36], [42], [60]) + +Все — `GET`, право `DIRECTORY_VIEW`, префикс `/api/v1/directories`. + +| Путь | Query | Ответ | Экран | +|---|---|---|---| +| `/regional-offices` | — | `RegionalOfficeOut[]` `{id, name, is_active}` | имя «Основной РФ» на [03] (по `base_regional_office_id`) | +| `/company-groups` | `q` (подстрока name / crm_id / code), `is_archived`, `limit`, `offset` | `Page[CompanyGroupOut]` по имени | [03], выбор ГК в [42] | +| `/company-groups/{group_id}` | — | `CompanyGroupOut` | заголовок [34] («N организаций» — `legal_entities_count`) | +| `/company-groups/{company_group_id}/related-groups` | — | `RelatedGroupOut[]` (ГСК и ГСЗ; ГСК — `kind = gsk`) | выбор ГСК в [42], фильтр «ГСК» в [36] | +| `/related-groups/{group_id}` | — | `RelatedGroupDetail` (+ `members[]`) | отметки [42], колонка «ГСК» в [36] | +| `/legal-entities` | `company_group_id`, `outside_group` (bool), `inn` (точно), `q` (подстрока имени/ИНН), `closed` (bool), `limit`, `offset` | `Page[LegalEntityOut]` по имени | [36] «Показать все ЮЛ в ГК», список ЮЛ в [42], монозаёмщики [60] | +| `/legal-entities/{entity_id}` | — | `LegalEntityDetail` (+ `memberships[]`, `aliases[]`) | карточка ЮЛ | + +**`CompanyGroupOut`** `{id, code, crm_id?, name, base_regional_office_id?, is_archived, valid_from, legal_entities_count, created_at?, +updated_at?}`. **`RelatedGroupOut`** `{id, code, company_group_id, kind, name, created_date?, members_count}`; +**`RelatedGroupDetail`** — + `members[] {legal_entity_id, inn, name, valid_from}` (текущий состав). **`LegalEntityOut`** `{id, inn, +crm_id?, entity_type?, name, company_group_id?, regional_office_id?, close_date?, valid_from, created_at?, updated_at?, +documents_count}`; **`LegalEntityDetail`** — + `memberships[] {related_group_id, code, kind, name, valid_from}`, `aliases[] {id, +alias, normalized_alias, created_at?}`. + +Нюансы: + +- **Модалка [42]**: ЮЛ ГК — `legal-entities?company_group_id=<ГК>&closed=false` (неархивные = без `close_date`), отметки — члены + выбранной ГСК из `related-groups/{id}`; создание — `POST /consolidations` с `legal_entity_ids` (`dev/api-contract-slice-4.md`, + нюанс 19). +- **Колонка «ГСК» в [36]**: у `LegalEntityOut` членства нет — возьмите `related-groups/{id}` по каждой ГСК ГК (их немного) или + `LegalEntityDetail.memberships`. +- **Монозаёмщики [60]**: `legal-entities?outside_group=true`; «Документы» — `documents_count`, статусы ОФР/ББ/ОСВ — из + `GET /legal-entities/{id}/files` по ЮЛ (сводного поля нет; экран не отнесён к срезу, П-6). +- Поиск ГК по имени РФ не поддерживается (`q` — только name/crm_id/code); пользователю филиала он не нужен (видит один РФ). diff --git a/dev/api-contract-slice-3b.md b/dev/api-contract-slice-3b.md index b5999f0..b887f2c 100644 --- a/dev/api-contract-slice-3b.md +++ b/dev/api-contract-slice-3b.md @@ -5,6 +5,7 @@ D-1…D-14, «Decisions made without discussion» №1–№22). Правила предметной области — `context/05-domain-rules.md` §7, §9.3, §9.5 (п. 2, 4, 9, 10); экраны — `context/10-user-journey.md` (пути 1–2, шаг 3.1), номера в `[…]` — снимки макета (`mockup/INDEX.md`). Общие правила (префикс, токен, формат ошибок, права) — как в `dev/api-contract-slice-4.md` §1; здесь — то, что добавил Срез 3b. +Файлы, документы и справочники (схемы `FileOut`/`DocumentBrief`, загрузка, удаление) — `dev/api-contract-files-directories.md`. ## 1. Общее diff --git a/dev/api-contract-slice-4.md b/dev/api-contract-slice-4.md index 56055ba..0b610f9 100644 --- a/dev/api-contract-slice-4.md +++ b/dev/api-contract-slice-4.md @@ -17,7 +17,9 @@ - **Деньги — строки JSON с двумя знаками** (`"100.00"`, `"0.00"`), могут быть `null` (нарастающий документ отдаётся «как в файле»). Не парсить во `float`: суммы `numeric(18,2)`. - Идентификаторы — uuid-строки; даты — ISO; `quarter` — `Q1`…`Q4`. -- Страницы — `{items, total, limit, offset}`; `limit ≤ 2000` (по умолчанию 500), `offset ≥ 0`; больше 2000 — 422. +- Страницы — `{items, total, limit, offset}`, `offset ≥ 0`. Лимиты у списков разные: сводная ОСВ и строки ОСВ документа — `limit ≤ 2000` + (по умолчанию 500); файлы ЮЛ и справочники — `limit ≤ 200` (по умолчанию 50). Больше предела — 422. Файлы, документы и справочники — + `dev/api-contract-files-directories.md`. - Перечисления: `ConsolidationStatus` — `INITIATED`, `DOCUMENTS_PROCESSING`, `DATA_CORRECTION`, `CONSOLIDATION_RF`, `ADJUSTMENT`, `VERIFICATION_RF`, `CONSOLIDATION_GO`, `VERIFICATION_GO`, `VERIFIED`, `CANCELLED`, `REJECTED`, `ARCHIVED` (в Срезе 4 достижимы первые три и `CANCELLED`); `CounterpartyType` — `GSK`, `GK`, `EXTERNAL`; `CounterpartyMatchKind` — `INN`, `NAME`, `ALIAS`, @@ -32,14 +34,14 @@ | Метод и путь | Право | Запрос | Ответ | Ошибки | Экран | |---|---|---|---|---|---| -| `POST /consolidations` | EDIT | `ConsolidationCreate {company_group_id, related_group_id, year (2000–2100), quarter}` | 201 `VersionCard` (версия №1, `INITIATED`, `lock = null`) | 404 `NOT_FOUND` (ГК/ГСК не видна), 409 `CONSOLIDATION_EXISTS`, 422 `RELATED_GROUP_MISMATCH`, 422 `PERIMETER_TOO_SMALL` | [42] | +| `POST /consolidations` | EDIT | `ConsolidationCreate {company_group_id, related_group_id, year (2000–2100), quarter, legal_entity_ids? (≤ 500)}` | 201 `VersionCard` (версия №1, `INITIATED`, `lock = null`) | 404 `NOT_FOUND` (ГК/ГСК не видна), 409 `CONSOLIDATION_EXISTS`, 422 `RELATED_GROUP_MISMATCH`, 422 `ENTITY_NOT_IN_GROUP` (`legal_entity_ids`), 422 `PERIMETER_TOO_SMALL`, 422 (pydantic-массив) при более чем 500 `legal_entity_ids` | [42] | | `GET /company-groups/{group_id}/consolidations` | VIEW | query `in_work_only` (bool, по умолчанию `false`) | `ConsolidationPeriodOut[]` (период + `versions[]` — `VersionBrief`) | 404 `NOT_FOUND` | [34] | | `GET /consolidations/versions/{version_id}` | VIEW | — | `VersionCard` | 404 `NOT_FOUND` | [34] панель «Организации», [36], [37] | | `POST /consolidations/versions/{version_id}/lock` | EDIT | тело необязательно: `LockIn {takeover_reason?}` (≤ 1000) | 201 `LockOut` (новая блокировка или перехват) / 200 `LockOut` (уже ваша — идемпотентно) | 404 `NOT_FOUND`, 409 `VERSION_NOT_EDITABLE` (версия `CANCELLED`), 409 `LOCKED_BY_OTHER`, 422 (pydantic-массив) при `takeover_reason` длиннее 1000 символов | [35] | | `DELETE /consolidations/versions/{version_id}/lock` | EDIT | — | 204 (в т. ч. если активной блокировки нет) | 404 `NOT_FOUND`, 409 `NOT_LOCK_OWNER` | [34] | | `POST /consolidations/versions/{version_id}/status` | EDIT | `StatusIn {to_status, comment? (≤ 1000)}` | 200 `VersionCard` | 404, 409 `VERSION_NOT_EDITABLE` / `LOCK_REQUIRED` / `LOCKED_BY_OTHER` / `TRANSITION_NOT_ALLOWED`, 422 `COMMENT_REQUIRED`, 422 (pydantic-массив) при `comment` длиннее 1000 символов | [33-01], меню «…» [34] | | `PUT /consolidations/versions/{version_id}/members` | EDIT | `MembersIn {legal_entity_ids[] (≤ 500)}` | 200 `VersionCard` | 404, 409 `VERSION_NOT_EDITABLE` / `LOCK_REQUIRED` / `LOCKED_BY_OTHER`, 422 `ENTITY_NOT_IN_GROUP` (`legal_entity_ids`), 422 `PERIMETER_TOO_SMALL`, 422 (pydantic-массив) при более чем 500 `legal_entity_ids` | [36] | -| `GET /consolidations/versions/{version_id}/checklist` | VIEW | — | `ChecklistOut {rules[], rows[]}` | 404 | [37] | +| `GET /consolidations/versions/{version_id}/checklist` | VIEW | query `format` (`json` по умолчанию / `csv`) | `ChecklistOut {rules[], rows[]}`; с `format=csv` — файл CSV (Срез 3b) | 404 | [37] | | `GET /consolidations/versions/{version_id}/osv` | VIEW | query: `limit`, `offset`, `legal_entity_id`, `account_root`, `counterparty_type`, `unmapped` (bool), `match_kind` (повторяемый), `q` (≤ 500) | 200 `Page[ConsolidatedRowOut]` | 404, 422 (pydantic-массив) при `q` длиннее 500 символов | [30] | | `GET /consolidations/versions/{version_id}/osv/summary` | VIEW | — | `OsvSummaryOut {rows_total, unmapped_total, auto_matched_total, documents_total, gaps[]}` | 404 | [30], баннер «Осталось: N», [31-00] | | `GET /consolidations/versions/{version_id}/osv/export` | VIEW | те же фильтры, что у `…/osv`, без `limit`/`offset` | файл xlsx (`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`) | 404 | «Экспорт» [30] | @@ -56,18 +58,24 @@ `Ref {id, name}`. Поля без `?` присутствуют всегда. **`ConsolidationPeriodOut`** `{consolidation_id, year, quarter, reporting_date, versions[]}`. -**`VersionBrief`** `{id, version_no, status, scenario, approach, lock (LockOut | null), created_at, members_count}`. +**`VersionBrief`** `{id, version_no, status, scenario, approach, lock (LockOut | null), created_at (datetime | null), members_count}`. **`LockOut`** `{locked_by, locked_by_name, locked_at, taken_over_from (uuid | null), takeover_reason (string | null)}`. **`VersionCard`** = `VersionBrief` + `{consolidation_id, year, quarter, reporting_date, company_group (Ref), initiator (Ref), initiator_office (Ref), goodwill_enabled, is_in_work, previous_version_id, members[], history[]}`: -- `members[]` — `{id, name, inn, is_head_entity, checklist[]}`, где `checklist[]` — ячейки по правилам комплекта (тот же порядок, - что `ChecklistOut.rules`); +- `members[]` — `{id, name, inn, entity_type ("ЮЛ" | "ИП"), is_head_entity, checklist[], osv_accounts[]}` (arm-core #42): + - `checklist[]` — ячейки `ChecklistCellOut` по правилам комплекта (тот же порядок, что `ChecklistOut.rules`); ячейка + **самоописывающая** — ищите нужную по `document_type`/`account` («Бух. баланс» — `BALANCE`, «ОФР» — `INCOME`, «ОСВ 60» — + `OSV` + `"60"`), а не по индексу; + - `osv_accounts[]` — коды счетов ОСВ ЮЛ, **загруженных** к периоду версии: документы ОСВ за год версии с кварталом не позже + квартала версии, в любом статусе, кроме ошибки, из незаменённых файлов; натуральный порядок (`["01", "51", "58.03", "60"]`). + Это колонка «ОСВ» панели «Организации» [34] — «что загружено», а не «что готово»: готовность счетов комплекта — в ячейках + `checklist`. Пока файл распознаётся, его счетов в списке ещё нет (ячейки показывают `PROCESSING`); - `history[]` — `{from_status (null у первой записи), to_status, changed_by, changed_at, comment}`. **`ChecklistOut`** `{rules[], rows[]}`; `rules[]` — `{document_type (BALANCE/INCOME/OSV…), account (string | null — счёт ОСВ), is_mandatory}` в порядке: ББ, ОФР, ОСВ по коду счёта (натурально: `58 < 58.03 < 60`); `rows[]` — `{legal_entity_id, -legal_entity_name, legal_entity_inn, cells[]}`, порядок `cells` = порядок `rules`. **`ChecklistCellOut`** `{status (CellStatus), -missing_quarters[], document_ids[]}`: +legal_entity_name, legal_entity_inn, cells[]}`, порядок `cells` = порядок `rules`. **`ChecklistCellOut`** `{document_type, account +(string | null), status (CellStatus), missing_quarters[], document_ids[]}` — `document_type`/`account` — правило ячейки (arm-core #42): `CONFIRMED` — пара полностью покрыта привязанными подтверждёнными документами; `NEEDS_CHECK` / `RECOGNIZED` — есть неподтверждённый подходящий документ; `PROCESSING` — у ЮЛ есть файл в обработке (по **всем** недостающим столбцам ЮЛ, пока файл не смаплен — это известная неточность, OQ-122); `ERROR` — последний файл ЮЛ в `ERROR`; `MISSING` — нет ничего. @@ -75,15 +83,18 @@ missing_quarters[], document_ids[]}`: ОСВ по субсчёту (58.03) закрывает только своё правило, не «ОСВ 58». **`ConsolidatedRowOut`** — строка свода: -`{entry_ids[], legal_entity_id, legal_entity_name, legal_entity_inn, account_code, account_root, period ("<год> Q"), -is_cumulative, row_number, counterparty_name, counterparty_inn, counterparty_id, counterparty_entity_name, counterparty_type, -match_kind, match_stored, opening_debit, opening_credit, turnover_debit, turnover_credit, closing_debit, closing_credit, warnings[]}`. +`{entry_ids[], legal_entity_id, legal_entity_name, legal_entity_inn, account_code?, account_root?, period ("<год> Q"), +is_cumulative, row_number?, counterparty_name?, counterparty_inn?, counterparty_id?, counterparty_entity_name?, counterparty_type, +match_kind?, match_stored, opening_debit?, opening_credit?, turnover_debit?, turnover_credit?, closing_debit?, closing_credit?, +warnings[]}` — поля с `?` могут быть `null` (ключ присутствует всегда). `counterparty_name/inn` — как в файле ОСВ; `counterparty_id`/`counterparty_entity_name` — сопоставленное ЮЛ справочника или `null`; `match_stored = true` — сопоставление хранится в БД, `false` — вычислено на лету (в БД не пишется); `match_kind` — способ (`null`, если ЮЛ не найдено). Для склеенных строк `entry_ids` — записи по кварталам (порядок — от раннего к позднему). **`OsvSummaryOut`** `{rows_total, unmapped_total, auto_matched_total, documents_total, gaps[]}`: `rows_total` — число строк свода (без фильтров); `unmapped_total` — число строк свода с пустым `counterparty_id` **после** дорезолва на лету (то же, что `GET …/osv?unmapped=true` даёт в `total`; `unmapped=false` — только сопоставленные); `auto_matched_total` — число строк с `match_kind` `NAME` или `ALIAS` независимо от `match_stored` (`INN`, `MANUAL`, `PROPAGATED` не входят); `documents_total` — число ОСВ-документов, привязанных к версии; **`gaps[]`** — `{legal_entity_id, legal_entity_name, account_code, missing_quarters[]}` (пара ЮЛ × счёт, у которой нет ОСВ за какие-то кварталы; -строк такой пары в своде нет). **`CandidateOut`** `{id, inn, name, company_group (Ref | null), gsk (Ref | null), gsz (Ref | null), +строк такой пары в своде нет). Баннер «Требуется указать соответствия… Осталось: N», кнопка «Показать ЮЛ без ИНН» [32-osv-no-inn] +и предупреждение [31-00] опираются на `unmapped_total` / `…/osv?unmapped=true`: это **все** строки свода без сопоставленного ЮЛ, +в том числе с ИНН, которого нет в справочнике (решение владельца 07.10.2026, arm-core #42 П-1), а не только строки без ИНН. **`CandidateOut`** `{id, inn, name, company_group (Ref | null), gsk (Ref | null), gsz (Ref | null), counterparty_type, recommended}`. **`MapCounterpartyOut`** `{row (ConsolidatedRowOut | null), propagated, alias_created, alias_moved_from (uuid | null)}`. @@ -146,16 +157,27 @@ alias_moved_from (uuid | null)}`. 18. **Удаление алиаса** (`DELETE /directories/legal-entities/{id}/aliases/{alias_id}`) во время переноса этого же алиаса ручным сопоставлением (`move_alias: true`) теперь ждёт блокировку и отвечает 404 `NOT_FOUND`, если алиас уже переехал (arm-core #26, T11.3) — это не ошибка клиента, перечитайте список алиасов. +19. **Периметр при создании** (модалка [42], arm-core #42). После выбора ГК и ГСК модалка показывает все неархивные ЮЛ ГК + (`GET /directories/legal-entities?company_group_id=<ГК>&closed=false`), отмечены члены выбранной ГСК + (`GET /directories/related-groups/{id}` → `members[]`); отметки меняются, «Создать» активна при двух и более. Отправляйте + отмеченные в `legal_entity_ids`. Без поля (или `null`) ядро берёт текущий состав ГСК; пустой список `[]` — это явный пустой + периметр → 422 `PERIMETER_TOO_SMALL`. ЮЛ не из ГК (или несуществующее) → 422 `ENTITY_NOT_IN_GROUP` с перечнем. ГСК обязательна + и проверяется (`RELATED_GROUP_MISMATCH`), но в версии **не хранится** (П-2): периметр живёт в `consolidation_member`, в + справочник переезжает при верификации (Срез 7). Колонку «ГСК» таблицы [34] до верификации заполнить нечем — оставляйте пустой. +20. **«Ответственный»** на панели «Организации» [34]: `lock.locked_by_name`, если у версии есть активная блокировка, иначе + `initiator.name`. «Утверждён в РФ» и «Верифицирован в ГО» — маршрут согласования, Срез 7 (в API пока нет; показывайте «—»). +21. **«К отчетности»** [34] доступна во всех статусах, начиная с `INITIATED` (OQ-43 пересмотрен владельцем 07.10.2026, П-3): свод + читается в любом статусе; правки свода (сопоставление контрагента) — только «в работе» со своей блокировкой. ## 5. Сквозные сценарии экранов | Экран | Вызовы | |---|---| -| [42] Новая консолидация | справочники (ГК → её ГСК) → `POST /consolidations` | -| [34] Консолидации ГК | `GET /company-groups/{id}/consolidations` (+ `in_work_only`), клик по строке — `GET …/versions/{id}`; «Взять в работу» — `POST …/lock`; меню «…» → «Отмена КФО» — `POST …/status {CANCELLED, comment}` | +| [42] Новая консолидация | справочники: ГК → её ГСК (`…/company-groups/{id}/related-groups`, `kind = gsk`) → ЮЛ ГК и члены ГСК (нюанс 19) → `POST /consolidations` с `legal_entity_ids` | +| [34] Консолидации ГК | `GET /company-groups/{id}/consolidations` (+ `in_work_only`), клик по строке — `GET …/versions/{id}` (панель «Организации»: `members[]` — тип, ячейки ББ/ОФР, `osv_accounts`; «Ответственный» — нюанс 20); «Взять в работу» — `POST …/lock`; меню «…» → «Отмена КФО» — `POST …/status {CANCELLED, comment}` | | [36] Состав | `GET …/versions/{id}` (члены), все ЮЛ ГК — справочники, «Сохранить» — `PUT …/members` | -| [39]/[40] Документы организации | `GET /legal-entities/{id}/files`, `POST /legal-entities/{id}/files?consolidation_version_id=` | -| [37] Чек-лист | `GET …/checklist` (CSV в Срезе 4 нет) | +| [39]/[40] Документы организации | `GET /legal-entities/{id}/files` (все файлы ЮЛ, опрос во время распознавания — им же или `GET /files/{id}`; схема — `dev/api-contract-files-directories.md`), `POST /legal-entities/{id}/files?consolidation_version_id=` | +| [37] Чек-лист | `GET …/checklist`; «Скачать CSV» — `GET …/checklist?format=csv` (Срез 3b) | | [30] ОСВ | `GET …/osv` с фильтрами, `GET …/osv/summary`, «Экспорт» — `GET …/osv/export` | | [32-osv-no-inn], [32-osv-map-counterparty] | `GET …/osv?unmapped=true`, `GET …/counterparty-candidates`, «Связать» — `POST …/osv/entries/{entry_id}/counterparty` | | [31-00] Предупреждение при уходе с вкладки | `GET …/osv/summary` (`unmapped_total`) | diff --git a/mockup/INDEX.md b/mockup/INDEX.md index 36b619d..5013fea 100644 --- a/mockup/INDEX.md +++ b/mockup/INDEX.md @@ -42,7 +42,7 @@ GSK-002), консолидации 2024 К1 (v1 Верифицирован, v2 | `39-01` | Панель документов → «Редактировать документы» | кнопка в снимке неактивна (режим не включается); иконка комментария в строке → поповер «Комментарий к документу <файл>» («Комментарий отсутствует», Закрыть) | `comment(object_type='document')` | 2–3 | | `40` | Модалка «Загрузка документов» | заголовок с организацией; зона «Перетащите файлы сюда» + **Выбрать документы**; Отмена, Загрузить (неактивна, пока нет файлов). Тип документа и период в модалке **не выбираются** — определяются при распознавании | `stored_file`, `recognition_job` | 2 | | `41` | **Проверка распознавания** (клик по PDF-документу в `39`) | крошки Отчётность › ГК › ЮЛ › Проверка документа; заголовок + имя файла, формат, дата; выпадающий список **Документ** (переход между документами организации) + бейдж статуса; **Добавить комментарий**. Слева «Исходный документ»: постраничные изображения, масштаб 100 % ±, сброс. Справа «Результат распознавания»: шапка формы (организация, ИНН, ОКПО/ОКОПФ/ОКФС, адрес, аудит), «Бухгалтерский баланс на 30 сентября 2025 г.», ОКУД, отчётная дата, ОКЕИ, единица измерения; таблица Пояснения / Наименование показателя / Код / колонки-даты, разделы и итоги; в таблице есть строки **без кода** («в том числе: Основные средства, пригодные к использованию…») и строка «Гудвилл 1105» (ФСБУ 4/2023); **Редактировать**, **Подтвердить данные**. В снимке — реальный скан ББ «Пекарни Счастливочной» из фикстур при имени файла «ОФР_2024_К1.pdf» (данные макета условны) | `document`, `financial_statement_meta/column/line/value`, `comment`, `audit_event(RECOGNIZED_DATA_EDIT, DOCUMENT_CONFIRM)` | 3 | -| `42` | Модалка **«Новая консолидация»** | Группа компаний → ГСК («Сначала выберите ГК») → Год → Квартал; Создать. Сценарий/подход/гудвилл здесь не выбираются — решение в OQ-27: подход всегда базовый, гудвилл включается на вкладке «Гудвилл», сценарий «Подтверждение КФО клиента» — через меню «…» консолидации | `consolidation`, `consolidation_version` | 4 | +| `42` | Модалка **«Новая консолидация»** | Группа компаний → ГСК («Сначала выберите ГК») → Год → Квартал; после ГК и ГСК — блок «ЮЛ консолидации» (все неархивные ЮЛ ГК, отмечены члены ГСК, отметки меняются, минимум 2; снимок снят до выбора ГК — блока на нём нет, логика — в JS бандла); Создать. Сценарий/подход/гудвилл здесь не выбираются — решение в OQ-27: подход всегда базовый, гудвилл включается на вкладке «Гудвилл», сценарий «Подтверждение КФО клиента» — через меню «…» консолидации | `consolidation`, `consolidation_version` | 4 | | `30` | **Отчёт — вкладка ОСВ** (сводная ОСВ) | шапка: хлебные крошки Отчётность › ГК › 2024·К1, заголовок «ГК — 2024 К1», подзаголовок-пояснение статуса, бейдж **Статус отчёта**, **Изменить статус**; вкладки ОСВ · Шахматка · Таблица корректировки · Гудвилл · КФО · КФО Общий · Подтверждение КФО клиента; Единицы (тыс. руб.), Знаков после запятой, Настройка таблицы, Экспорт, На весь экран; предупреждение «Требуется указать соответствия… Осталось: N» + **Показать ЮЛ без ИНН**; таблица: Компания ГК, Счёт, Период, Контрагенты, ИНН, Сальдо начало Дт/Кт, Обороты Дт/Кт, Сальдо конец Дт/Кт, Тип контрагента | вычисляется из `osv_entry` × `consolidation_member`; `legal_entity_alias` | 4 | | `32-osv-no-inn` | ОСВ, фильтр «ЮЛ без ИНН» | строки без сопоставления, кнопка **Указать** | `osv_entry.counterparty_id IS NULL` | 4 | | `32-osv-map-counterparty` | Модалка «Выбор организации для связи с …» | колонки ИНН, Организация, ГК, ГСК, ГСЗ; блок «Рекомендуемые»; кнопка **Связать** в строке | `legal_entity_alias`, `osv_entry.counterparty_id`, `audit_event(OSV_COUNTERPARTY_MAP)` | 4 |