rules: §9.1/§9.5 — загрузка в консолидацию и рабочий стол консоли (#90)

Ссылки на текущую модель в 05 и 08 переведены на v5.18 (R-12).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Andrey Epifancev 2026-10-09 23:30:12 +04:00
parent 0684481255
commit e4abd1717a
2 changed files with 25 additions and 10 deletions

View File

@ -1,4 +1,4 @@
# 05. Правила предметной области (выжимка из ТЗ, имена — v5.17) # 05. Правила предметной области (выжимка из ТЗ, имена — v5.18)
Каждый раздел: источник в ТЗ → правило → где в модели. Где ТЗ молчит или противоречит — пометка **[открыто]** и Каждый раздел: источник в ТЗ → правило → где в модели. Где ТЗ молчит или противоречит — пометка **[открыто]** и
ссылка на `07-open-questions.md`. ссылка на `07-open-questions.md`.
@ -567,7 +567,7 @@ NEEDS_CHECK`; пройдено/акцептовано + нажато «Подт
| Событие | Переход | Кто (`changed_by`) | | Событие | Переход | Кто (`changed_by`) |
|---|---|---| |---|---|---|
| загрузка файла с `consolidation_version_id`, принят ≥ 1 файл | INITIATED → DOCUMENTS_PROCESSING | загрузивший | | загрузка файла в консолидацию (`POST /consolidations/{id}/legal-entities/{le}/files`), принят ≥ 1 файл | INITIATED → DOCUMENTS_PROCESSING у **каждой** версии консолидации «в работе», где ЮЛ в периметре | загрузивший |
| маппинг создал документ `NEEDS_CHECK`, подходящий версии | DOCUMENTS_PROCESSING → DATA_CORRECTION | `stored_file.uploaded_by` (нет — переход пропускается, лог) | | маппинг создал документ `NEEDS_CHECK`, подходящий версии | DOCUMENTS_PROCESSING → DATA_CORRECTION | `stored_file.uploaded_by` (нет — переход пропускается, лог) |
| подтверждение документа, привязанного к версии | INITIATED / DOCUMENTS_PROCESSING → DATA_CORRECTION | подтвердивший | | подтверждение документа, привязанного к версии | INITIATED / DOCUMENTS_PROCESSING → DATA_CORRECTION | подтвердивший |
| `POST …/status {CANCELLED, comment}` (комментарий обязателен, 422 `COMMENT_REQUIRED`) | любой «в работе» → CANCELLED | пользователь с блокировкой | | `POST …/status {CANCELLED, comment}` (комментарий обязателен, 422 `COMMENT_REQUIRED`) | любой «в работе» → CANCELLED | пользователь с блокировкой |
@ -608,7 +608,8 @@ replay: dlq → queued (`attempt + 1`). `max_attempts`: OCR 1, парсер 3; `
### 9.5 Первичные документы: загрузка, маппинг, замена, удаление, подтверждение (Срез 2c) ### 9.5 Первичные документы: загрузка, маппинг, замена, удаление, подтверждение (Срез 2c)
1. **Загрузка** (`POST /legal-entities/{id}/files`, право `DOCUMENT_EDIT`, ЮЛ в видимости): тип файла по расширению и 1. **Загрузка** (`POST /legal-entities/{id}/files` — без контекста, `stored_file.consolidation_id = NULL`; в консолидацию —
п. 8; право `DOCUMENT_EDIT`, ЮЛ в видимости): тип файла по расширению и
сигнатуре (`xls` — BIFF8, `xlsx`/`xlsb` — zip, `pdf`, `png`, `jpg`); лимит `UPLOAD_MAX_BYTES` (50 МиБ); дедуп по сигнатуре (`xls` — BIFF8, `xlsx`/`xlsb` — zip, `pdf`, `png`, `jpg`); лимит `UPLOAD_MAX_BYTES` (50 МиБ); дедуп по
`sha256` в пределах ЮЛ среди файлов не `SUPERSEDED`. Принятый файл: объект S3 `uploads/{file_id}/{job_id}/{имя}`, `sha256` в пределах ЮЛ среди файлов не `SUPERSEDED`. Принятый файл: объект S3 `uploads/{file_id}/{job_id}/{имя}`,
`stored_file(UPLOADED, version_no = 1)`, `recognition_job(queued)`, `audit_event(FILE_UPLOAD)`. Тип документа и период `stored_file(UPLOADED, version_no = 1)`, `recognition_job(queued)`, `audit_event(FILE_UPLOAD)`. Тип документа и период
@ -641,7 +642,7 @@ replay: dlq → queued (`attempt + 1`). `max_attempts`: OCR 1, парсер 3; `
§9.3. §9.3.
3. **Автозамена.** После успешного маппинга другие файлы того же ЮЛ (не `SUPERSEDED`), содержащие документ с теми же 3. **Автозамена.** После успешного маппинга другие файлы того же ЮЛ (не `SUPERSEDED`), содержащие документ с теми же
`document_type`, `osv_account_code`, `period_year`, `period_quarter`, переводятся в `SUPERSEDED` `document_type`, `osv_account_code`, `period_year`, `period_quarter`, переводятся в `SUPERSEDED`
(`superseded_by_file_id` = новый файл); `version_no` нового = максимум заменённых + 1. Заменяется и файл с `CONFIRMED` (`superseded_by_file_id` = новый файл); `version_no` нового = максимум заменённых + 1. Новый файл без контекста (`consolidation_id IS NULL`) наследует `consolidation_id` первого (по `id`) заменённого файла, у которого он задан; файл, загруженный в консолидацию, сохраняет свою (v5.18). Заменяется и файл с `CONFIRMED`
документом (решение владельца 05.10.2026); документ без года или квартала в замене не участвует. Документы и строки документом (решение владельца 05.10.2026); документ без года или квартала в замене не участвует. Документы и строки
заменённых файлов сохраняются, но по умолчанию не показываются. Если новый файл содержит лишь часть документов заменённых файлов сохраняются, но по умолчанию не показываются. Если новый файл содержит лишь часть документов
заменяемого, заменяемый уходит в `SUPERSEDED` целиком (OQ-06: замена файлом целиком; частный случай — OQ-115). Для форм заменяемого, заменяемый уходит в `SUPERSEDED` целиком (OQ-06: замена файлом целиком; частный случай — OQ-115). Для форм
@ -680,10 +681,15 @@ replay: dlq → queued (`attempt + 1`). `max_attempts`: OCR 1, парсер 3; `
7. **Порядок блокировок** (против взаимоблокировок): задание → файл → документы (`FOR NO KEY UPDATE`) → advisory-lock ГК → 7. **Порядок блокировок** (против взаимоблокировок): задание → файл → документы (`FOR NO KEY UPDATE`) → advisory-lock ГК →
версии консолидации (`FOR UPDATE`, по возрастанию `id`); автозамена дополнительно берёт advisory-lock по ЮЛ. Подробности — версии консолидации (`FOR UPDATE`, по возрастанию `id`); автозамена дополнительно берёт advisory-lock по ЮЛ. Подробности —
`03-architecture.md`. `03-architecture.md`.
8. **Загрузка в контексте версии** (`?consolidation_version_id=`, Срез 4): до приёма — версия видима (404), «в работе» 8. **Загрузка в консолидацию** (`POST /consolidations/{consolidation_id}/legal-entities/{legal_entity_id}/files`,
(409 `VERSION_NOT_EDITABLE`), ЮЛ — член периметра (422 `ENTITY_NOT_IN_PERIMETER`); после приёма хотя бы одного файла `DOCUMENT_EDIT`; v5.18, решения владельца 09.10.2026, RSHB/arm-ka-docs#90): до приёма — консолидация видима (404
INITIATED → DOCUMENTS_PROCESSING (§9.1); сбой этого перехода не отменяет принятые файлы. Блокировка версии для загрузки не `NOT_FOUND`), ЮЛ видимо (404), есть версия консолидации «в работе» (409 `CONSOLIDATION_NOT_EDITABLE`), ЮЛ — член
нужна. периметра хотя бы одной такой версии (422 `ENTITY_NOT_IN_PERIMETER`). Принятый файл получает
`stored_file.consolidation_id`; `FILE_UPLOAD.after_value.consolidation_id`. После приёма хотя бы одного файла, отдельной
транзакцией, каждая версия консолидации «в работе» с этим ЮЛ в периметре и статусом INITIATED переходит в
DOCUMENTS_PROCESSING (§9.1; версии блокируются `FOR UPDATE` по возрастанию `id`, статус перечитывается); сбой перехода не
отменяет принятые файлы. Блокировка версии для загрузки не нужна. Query `consolidation_version_id` у
`POST /legal-entities/{id}/files` (Срез 4) удалён.
9. **Правка формы ББ/ОФР** (`PATCH /documents/{id}/statement`, `DOCUMENT_EDIT`, Срез 3b; решения владельца 07.10.2026). 9. **Правка формы ББ/ОФР** (`PATCH /documents/{id}/statement`, `DOCUMENT_EDIT`, Срез 3b; решения владельца 07.10.2026).
Правятся **суммы** ячеек (`values[] {line_id, column_id, amount}`) и три поля шапки: `inn` (10 или 12 цифр, иначе 422 Правятся **суммы** ячеек (`values[] {line_id, column_id, amount}`) и три поля шапки: `inn` (10 или 12 цифр, иначе 422
`INVALID_INN`, в том числе `null` — очистить ИНН нельзя; пересчитывается `counterparty_check`), `report_date` (пересчитываются `period_year`, `period_quarter`, `INVALID_INN`, в том числе `null` — очистить ИНН нельзя; пересчитывается `counterparty_check`), `report_date` (пересчитываются `period_year`, `period_quarter`,
@ -703,6 +709,15 @@ replay: dlq → queued (`attempt + 1`). `max_attempts`: OCR 1, парсер 3; `
`POST/GET /documents/{id}/comments` (таблица `comment`, `object_type = 'document'`); добавлять можно к документу в любом `POST/GET /documents/{id}/comments` (таблица `comment`, `object_type = 'document'`); добавлять можно к документу в любом
статусе; правки и удаления нет; при удалении файла (`DELETE /files/{id}`, п. 5) комментарии его документов удаляются вместе с ними статусе; правки и удаления нет; при удалении файла (`DELETE /files/{id}`, п. 5) комментарии его документов удаляются вместе с ними
(связь полиморфная, FK нет — удаляет сервис). (связь полиморфная, FK нет — удаляет сервис).
11. **Рабочий стол консоли** (`GET /consolidations/{consolidation_id}/legal-entities/{legal_entity_id}/files`,
`DOCUMENT_VIEW`; 404 на невидимые консолидацию или ЮЛ; `limit`, `offset`, `include_superseded`): файлы ЮЛ с
`consolidation_id` этой консолидации **плюс** файлы ЮЛ, у которых есть документ, привязанный (`consolidation_document`)
к любой версии этой консолидации (подхваченные ОСВ за `Q1` и файлы, загруженные без контекста); новые первыми
(`uploaded_at` desc, `id`); `SUPERSEDED` — только при `include_superseded=true`. Карточка файла та же, что в
`GET /legal-entities/{id}/files` (`FileOut` + `consolidation_id`). Рабочие версии одного периода видят один стол;
верифицированная версия заморожена привязками и `ex_snapshot` (Срез 7), отдельного «замороженного списка» в панели
нет. Панель [39] из карточки версии показывает стол консоли; переключатель «Все документы организации» —
`GET /legal-entities/{id}/files` с подписью консолидации у файла.
--- ---

View File

@ -48,8 +48,8 @@
| Файл | Что | | Файл | Что |
|---|---| |---|---|
| `data-model-v5.18.dbml` | источник истины; changelog v5.1…v5.18 в шапке; блоки «ИСТОЧНИК» над каждой таблицей (v5.13…v5.16 остаются рядом как история) | | `data-model-v5.18.dbml` | источник истины; changelog v5.1…v5.18 в шапке; блоки «ИСТОЧНИК» над каждой таблицей (v5.13…v5.17 остаются рядом как история) |
| `entities-v5.18.md` | описание сущностей по частям 01–09, таблицы «Что изменилось» по версиям, сценарий «как читать модель», открытые вопросы (v5.13…v5.16 остаются как история) | | `entities-v5.18.md` | описание сущностей по частям 01–09, таблицы «Что изменилось» по версиям, сценарий «как читать модель», открытые вопросы (v5.13…v5.17 остаются как история) |
| `diagrams/part01…09.{svg,png}` | диаграммы v5.18 по частям; перерисовываются `make diagrams` (`scripts/gen_model_diagrams.py`) | | `diagrams/part01…09.{svg,png}` | диаграммы v5.18 по частям; перерисовываются `make diagrams` (`scripts/gen_model_diagrams.py`) |
| `source/tz/data-model-part1_4.dbml` (лежит не в `model/`, а в экспорте ТЗ) | v4 часть 1 — историческое | | `source/tz/data-model-part1_4.dbml` (лежит не в `model/`, а в экспорте ТЗ) | v4 часть 1 — историческое |