DBML v5.16 (Срез 4): enum counterparty_match_kind и osv_entry.counterparty_match_kind; уточнение семантики consolidation_document (точки привязки/отвязки) и consolidation_lock (без истечения, OQ-119). entities-v5.16.md, 04-data-model-guide (DECISION-5: способ сопоставления хранится, пробелы и свод — нет), repo-templates -> v5.16, tasks.md change'а: пункт 1 выполнен. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
95 lines
11 KiB
Markdown
95 lines
11 KiB
Markdown
# 04. Как читать модель данных v5.16
|
||
|
||
Файлы: `docs/model/data-model-v5.16.dbml` (источник истины), `docs/model/entities-v5.16.md` (смысл таблиц; предыдущие
|
||
версии `data-model-v5.13…v5.15.dbml` и `entities-v5.13…v5.15.md` остаются как история),
|
||
`docs/model/diagrams/part01…09.svg` (диаграммы v5.12 — на одну версию старше: нет `permission`/`role_permission`,
|
||
нет `document`, есть `osv_group_schema`, нет `related_group_member.kind`; читать с поправкой на changelog v5.13…v5.16 в шапке DBML).
|
||
|
||
## Девять частей модели
|
||
|
||
| Часть | Таблицы | Что это |
|
||
|---|---|---|
|
||
| 01 Группы и организации | `regional_office`, `company_group(+_history)`, `legal_entity(+_history)`, `legal_entity_alias`, `related_group`, `related_group_member` | справочник клиентов; SCD4 для ГК/ЮЛ, SCD2 для членства |
|
||
| 02 Пользователи и права | `app_user`, `role`, `permission`, `role_permission`, `user_role` | матрица прав как данные |
|
||
| 03 Бухгалтерские справочники | `chart_of_account`, `elimination_rule`, `elimination_rule_account`, `required_document_rule` | план счетов (seed из 1С), правила элиминации Прил. 3/4 (версионируются), чек-лист по подходу |
|
||
| 04 Файлы и распознавание | `s3_object`, `stored_file`, `document`, `recognition_job` | физический файл → задание → логические документы |
|
||
| 05 Разобранные ОСВ | `osv_entry` | строка ОСВ с шестью суммами, сырым контрагентом и резолвом |
|
||
| 06 Формы ББ/ОФР | `financial_statement_meta`, `_column`, `_line`, `_value` | шапка, колонки-даты, строки с кодами, значения с confidence |
|
||
| 07 Консолидация | `consolidation`, `consolidation_version`, `_status_history`, `_lock`, `_member`, `_document` | логическая консолидация (ГК × период) и её версии с периметром |
|
||
| 08 Корректировки и КФО | `correction`, `goodwill`, `kfo_result`, `kfo_result_line`, `kfo_result_line_company`, `client_kfo_line` | ручные решения и результат |
|
||
| 09 Комментарии, аудит, ЕХ | `comment`, `audit_event`, `ex_snapshot`, `ex_snapshot_member`, `ex_snapshot_item` | полиморфные комментарии, append-only журнал, замороженные срезы |
|
||
|
||
## Соглашения
|
||
|
||
- PK везде `uuid`; натуральные ключи — `UNIQUE` (ИНН, код счёта, crm_id, код ГСК). Для `osv_entry` и `audit_event`
|
||
допустима замена на `bigint identity` при объёмах.
|
||
- Денежные поля `numeric(18,2)`, проценты `numeric(7,4)`/`numeric(9,4)`, confidence `numeric(5,2)` (0–100).
|
||
- Временные метки `timestamptz`; отчётные даты `date`.
|
||
- Партиальные уникальные индексы (помечены в notes): `related_group_member (legal_entity_id, kind) WHERE is_current`
|
||
(v5.14: ЮЛ — не более одной текущей группы каждого вида, т.е. одна ГСК и одна ГСЗ одновременно; `kind` — денормализация
|
||
`related_group.kind`),
|
||
`consolidation_lock.consolidation_version_id WHERE released_at IS NULL`,
|
||
`document (stored_file_id, document_type, osv_account_code) NULLS NOT DISTINCT`.
|
||
- Enum'ы PostgreSQL — ровно как в DBML (`consolidation_status`, `document_status`, `audit_action` …). Добавление значения —
|
||
миграция + версия DBML.
|
||
- История: `*_history` — снимки предыдущего состояния (SCD4); `related_group_member` — версии строк (SCD2);
|
||
остальное — `audit_event(before_value, after_value)`.
|
||
- Поля `*_by` → `app_user.id`; `NULL` — системное действие.
|
||
|
||
## Что намеренно НЕ хранится (DECISION-5) и как это вычислять
|
||
|
||
Способ сопоставления контрагента хранится (`osv_entry.counterparty_match_kind`, v5.16); пробелы квартальной склейки и сам свод — нет.
|
||
|
||
| Объект | Вычисление |
|
||
|---|---|
|
||
| Сводная ОСВ | `osv_entry` актуальных `document` (OSV, CONFIRMED, период версии) всех `consolidation_member` версии; только строки `group_type = COUNTERPARTY` и `data_type IN (BU, SUM)`; строки не агрегируются |
|
||
| Признак контрагента | `counterparty_id ∈ member(version)` → ГСК; иначе `legal_entity.company_group_id = consolidation.company_group_id` → ГК; иначе Внешний |
|
||
| Пары ВГО | по `elimination_rule(_account)` версии правил `consolidation_version.elimination_rules_version` — §5 правил |
|
||
| Шахматка | агрегат пар по компаниям и выбранным наборам счетов — §6 |
|
||
| Логические проверки форм | формулы §7 по `financial_statement_value` |
|
||
| Чек-лист документов | `required_document_rule(approach) × consolidation_member − document(CONFIRMED)` |
|
||
| «Исправлено полей» | `COUNT(*) WHERE is_modified` |
|
||
| «Требует проверки» ячейка | `confidence < порог OR NOT is_recognized` |
|
||
|
||
Всё это — чистые функции от `consolidation_version_id`; результат кэшируется только в памяти запроса.
|
||
При `VERIFIED` единственный раз сериализуется в `ex_snapshot_item.payload`.
|
||
|
||
## v4 → v5.13: таблица переименований (обязательна при чтении ТЗ)
|
||
|
||
v5.14 имена таблиц и полей не менял (добавлены `related_group_member.kind` и два значения `audit_action`), v5.15 — тоже
|
||
(добавлено значение `osv_data_type.NU`), v5.16 — тоже (колонка `osv_entry.counterparty_match_kind`), поэтому таблица справедлива и для v5.14, v5.15 и v5.16.
|
||
|
||
| В страницах ТЗ (модель v4 и старше) | В v5.13 / v5.14 / v5.15 / v5.16 |
|
||
|---|---|
|
||
| `stored_file.period_year / period_quarter / document_type / osv_account` | `document.period_year / period_quarter / document_type / osv_account_code / is_cumulative` |
|
||
| `stored_file.status` «Загружен / Обработка / Требуется проверка / Ошибка» | техника: `stored_file.status` UPLOADED/PROCESSING/PROCESSED/ERROR/SUPERSEDED; проверка: `document.status` RECOGNIZED/NEEDS_CHECK/CONFIRMED/ERROR |
|
||
| `stored_file.current_recognition_job_id` как источник строк | `osv_entry.document_id` / `financial_statement_meta.document_id`; `current_recognition_job_id` остаётся как «авторитетный прогон» файла |
|
||
| `osv_entry.legal_entity_id` | `osv_entry.owner_legal_entity_id` |
|
||
| `osv_entry.stored_file_id` | `osv_entry.document_id` (файл — через `document.stored_file_id`) |
|
||
| `osv_entry.group_schema_id → osv_group_schema / osv_grouping_schema` | `osv_entry.group_type` (enum) + `recognition_job.group_schema jsonb` |
|
||
| `osv_entry.counterparty_type` (ГК/ГСК/Внешний) | не хранится, вычисляется |
|
||
| `fin_report_header`, `Fin_report_rows`, `report_id`, `row_code`, `value_current/prior/prior2`, `needs_review` | `financial_statement_meta` / `_column` (`period_date`, `is_current`) / `_line.line_code` / `_value.amount, confidence, is_recognized` |
|
||
| `financial_statement_line.amount` | `financial_statement_value.amount` (строка × колонка) |
|
||
| `Consolidation_package`, `Consolidation_template`, `Company_data`, `Intercompany_reconciliation`, `vgo_pair_match`, `chess_cell`, `consolidated_osv_line` | `consolidation`/`consolidation_version`/`consolidation_member`; КФО — `kfo_result(_line)`; остальное вычисляется |
|
||
| `Company`, `Organizations`, `Organization_aliases`, `ref_crm_region`, `consolidation_group`, `group_membership` | `legal_entity`, `legal_entity_alias`, `regional_office`, `company_group`, `related_group(_member)` |
|
||
| `users` (email, role) | `app_user` + `user_role` + `role_permission` |
|
||
| `raw_result_s3_key`, `queue_msg_id` | `recognition_job.result_s3_object_id` (единственная ссылка на результат), `request_msg_id / result_msg_id` |
|
||
| `chart_of_account.account_code` | `chart_of_account.code` |
|
||
| `role.code` KA_HEAD / KA_GO_DM | `KA_RF, KA_GO, RKA, CLIENT_MANAGER, CURATOR_GO, EXPERT, ADMIN` (seed) |
|
||
| статус документа `MANUAL_CHECK` | `document.status = NEEDS_CHECK` |
|
||
| статус консолидации `CREATED` (черновик) | `INITIATED` |
|
||
|
||
## Открытые места модели (не придумывать, спросить)
|
||
|
||
- **Закрыто в v5.14:** OQ-32 (членство в ГСК и ГСЗ одновременно) — решение владельца 04.10.2026: ЮЛ в одной ГК и одновременно
|
||
в одной ГСК и одной ГСЗ (ANL-030 отменён); OQ-31 (КПП) — не вводится.
|
||
|
||
- **№2 `osv_entry.parent_entry_id`**: хранить ли все строки ОСВ (п. 11 «Парсинг ОСВ» — да) или только контрагентские;
|
||
нужно ли дерево. Рекомендация для среза 2: хранить **все** строки с `level` и `parent_entry_id` — это дёшево и
|
||
позволяет сверять «Σ контрагентов = итог счёта»; вопрос закрывать с аналитиками.
|
||
- `document.RECOGNIZED` — нужен ли статус «проверка не требуется», или всё идёт через `NEEDS_CHECK → CONFIRMED`.
|
||
- Замена по-документно (одна ОСВ из файла с пятью листами) — сейчас только файлом целиком.
|
||
- `goodwill.participation_amount` — входит ли стр. 1350 в базу (вопрос методологам).
|
||
- `user_role` M:N vs 1:1 — если ТЗ строго «одна роль», заменить на `app_user.role_id`.
|
||
- `consolidation_status` REJECTED/ARCHIVED — из макета, не из ТЗ (ANL-035).
|