29 KiB
29 KiB
code, title
| code | title |
|---|---|
| DOC-019834 | 2. Модель данных (сущности) |
2. Модель данных (сущности)
1
Состав ГК\_ГСК\_ГСЗ\_из выписок\на 1 кв. 2026\ (2).xlsx 17 апр. 2026 г., 10:39
data-model-part1 \_4.dbml 21 сент. 2026 г., 15:02
Файлы, справочники, пользователи
Все сущности
// ДКБ · Модель данных · Часть 1: файлы и справочники
// Формат: DBML (dbdiagram.io). Вставить на https://dbdiagram.io/d
//
// Ключи: у ВСЕХ сущностей суррогатный PK (uuid). Натуральные ключи
// (ИНН, код счёта, CRM ID, код ГСК/ГСЗ) - UNIQUE-колонки, не PK. FK ссылаются на id.
// (Для высокообъёмных таблиц - osv_entry и т.п. - uuid можно заменить на bigint identity.)
// ЮЛ и ГК - SCD Type 4: живая таблица (текущее) + *_history (прошлые снимки).
// Членство в ГСК/ГСЗ - SCD Type 2 (одна таблица, флаг is_current).
// Пользователи: филиал = regional_office (ГО + РФ), отдельная ssp не заводится.
// Разбор файла берём через stored_file.current_recognition_job_id (авторитетный прогон).
// Распознавание: XLSX -> табличный сервис, PDF/PNG/JPG -> сервис изображений (pipeline).
// Результаты обоих сервисов приходят одним потоком NATS (JSON), коррелируются по recognition_job.id.
// ============ ENUMS ============
Enum entity_type {
"ЮЛ"
"ИП"
}
Enum related_group_kind {
gsk
gsz
}
Enum account_kind {
A [note: 'актив']
P [note: 'пассив']
AP [note: 'активно-пассивный']
}
Enum document_type {
"Бухгалтерская отчётность"
"ОСВ"
"ОФР"
"Прочий документ"
}
Enum file_type {
XLSX // машиночитаемые -> табличный сервис
PDF // изображения -> сервис изображений
PNG
JPG
}
Enum recognition_pipeline {
tabular // XLSX-сервис (машиночитаемые данные)
image // PDF/PNG/JPG-сервис (распознавание изображений)
}
Enum period_quarter {
Q1
Q2
Q3
Q4
}
Enum file_status {
"Загружен"
"Обработка"
"Требуется проверка"
"Ошибка"
}
Enum recognition_status {
queued
processing
done
error
}
Enum counterparty_type {
"ГК"
"ГСК"
"Внешний"
}
Enum statement_type {
balance
income
}
Enum fsl_row_kind {
section
row
sub
total
balance
}
// ============ СПРАВОЧНИКИ ============
Table regional_office {
id uuid [pk]
name varchar [not null, unique]
is_active boolean [not null, default: true]
Note: 'Филиал: ГО и региональные филиалы (РФ)'
}
// --- ГК: SCD4 (живая таблица + история) ---
Table company_group {
id uuid [pk]
crm_id varchar [not null, unique, note: 'натуральный ключ из CRM']
name varchar [not null]
base_regional_office_id uuid [ref: > regional_office.id]
valid_from timestamptz [not null, note: 'действует с']
updated_by varchar
created_at timestamptz
Note: 'ГК - ТЕКУЩЕЕ состояние (SCD4). Одна строка на группу. История - company_group_history'
}
Table company_group_history {
id uuid [pk]
company_group_id uuid [not null, ref: > company_group.id]
crm_id varchar [not null]
name varchar [not null]
base_regional_office_id uuid
valid_from timestamptz [not null]
valid_to timestamptz [note: 'когда снимок перестал действовать']
changed_by varchar
Indexes {
(company_group_id, valid_from) [unique]
}
Note: 'Прошлые снимки ГК (пишутся при каждом изменении company_group)'
}
// --- ЮЛ: SCD4 (живая таблица + история) ---
Table legal_entity {
id uuid [pk]
inn varchar [not null, unique, note: 'натуральный ключ']
entity_type entity_type [note: 'ЮЛ/ИП']
name varchar [not null]
company_group_id uuid [not null, ref: > company_group.id, note: 'текущая ГК (меняется событием «Переход в ГК»)']
regional_office_id uuid [ref: > regional_office.id]
close_date date [note: 'NULL = активна; дата = архивирована/закрыта']
valid_from timestamptz [not null, note: 'действует с']
updated_by varchar
created_at timestamptz
Note: 'Организация (ЮЛ/ИП) - ТЕКУЩЕЕ состояние (SCD4). История - legal_entity_history'
}
Table legal_entity_history {
id uuid [pk]
legal_entity_id uuid [not null, ref: > legal_entity.id]
inn varchar [not null]
entity_type entity_type
name varchar [not null]
company_group_id uuid [not null]
regional_office_id uuid
close_date date
valid_from timestamptz [not null]
valid_to timestamptz [note: 'когда снимок перестал действовать']
changed_by varchar
Indexes {
(legal_entity_id, valid_from) [unique]
}
Note: 'Прошлые снимки организации (пишутся при каждом изменении legal_entity)'
}
Table related_group {
id uuid [pk]
code varchar [not null, unique, note: 'человеко-код, напр. GSK-001']
company_group_id uuid [not null, ref: > company_group.id]
kind related_group_kind
name varchar [not null]
created_date date
Indexes {
(id, kind) [unique, note: 'нужно для composite FK из related_group_member']
}
Note: 'Группа связанных компаний/заёмщиков (ГСК/ГСЗ) - current-state'
}
// --- Членство: SCD2 (одна таблица + is_current) ---
Table related_group_member {
id uuid [pk]
related_group_id uuid [not null, ref: > related_group.id]
legal_entity_id uuid [not null, ref: > legal_entity.id]
kind related_group_kind [not null, note: 'копия из related_group; composite FK (related_group_id, kind) > related_group(id, kind)']
valid_from timestamptz [not null]
valid_to timestamptz [note: 'NULL = текущая']
is_current boolean [not null]
created_by varchar
Indexes {
(related_group_id, legal_entity_id) [note: 'partial UNIQUE WHERE is_current - одна текущая версия на пару']
legal_entity_id [note: 'ВРЕМЕННО: partial UNIQUE WHERE is_current AND kind = gsk - одна ГСК на организацию']
}
Note: 'Состав ГСК/ГСЗ (M:N) - SCD2. Исключение = закрытие версии (is_current=false), не DELETE'
}
Table chart_of_account {
id uuid [pk]
code varchar [not null, unique, note: 'натуральный код счёта, напр. 60.01']
parent_id uuid [ref: > chart_of_account.id, note: 'иерархия счетов']
name varchar [not null]
kind account_kind
Note: 'План счетов'
}
// ============ ПОЛЬЗОВАТЕЛИ И РОЛИ ============
Table role {
id uuid [pk]
code varchar [not null, unique, note: 'машинный код: KA_RF, KA_GO, KA_GO_DM, CURATOR_GO, ADMIN']
name varchar [not null, note: 'отображаемое название роли']
Note: 'Справочник ролей. Матрица прав (создание ГК, правка состава ГСК, утверждение КФО)'
}
Table app_user {
id uuid [pk]
email varchar [not null, unique]
username varchar [not null, unique]
hashed_password varchar
full_name varchar
role_id uuid [not null, ref: > role.id]
regional_office_id uuid [not null, ref: > regional_office.id, note: 'филиал пользователя: ГО или РФ']
created_at timestamptz
updated_at timestamptz
is_active boolean [not null, default: true]
Note: 'Пользователь системы. Видимость данных = роль + филиал'
}
// ============ ФАЙЛЫ / РАСПОЗНАВАНИЕ ============
Table stored_file {
id uuid [pk]
legal_entity_id uuid [not null, ref: > legal_entity.id]
document_type document_type
file_type file_type
original_name varchar
s3_key varchar [unique, note: 'ключ объекта; бакет из конфига (uploads)']
content_hash varchar [note: 'sha256, дедуп']
size_bytes bigint
period_year smallint [note: 'отчётный период сдачи документа']
period_quarter period_quarter
status file_status
current_recognition_job_id uuid [ref: > recognition_job.id, note: 'авторитетный прогон: чьи строки показываем']
uploaded_by varchar
uploaded_at timestamptz
Note: 'Загруженный файл (в S3 - только ссылка). Строки разбора берём через current_recognition_job_id'
}
Table recognition_job {
id uuid [pk]
file_id uuid [not null, ref: > stored_file.id]
pipeline recognition_pipeline [not null, note: 'tabular=XLSX-сервис, image=PDF/PNG/JPG-сервис']
service_version varchar [note: 'версия сервиса/модели, для диагностики']
status recognition_status
attempt smallint
queue_msg_id varchar [note: 'id сообщения NATS для дедупа при redelivery']
requested_at timestamptz [note: 'опубликовано в очередь']
started_at timestamptz [note: 'сервис взял в работу']
finished_at timestamptz
error_message text
raw_result_s3_key varchar [note: 'ключ JSON-результата; бакет из конфига (results)']
Note: 'Задание на распознавание. Роутинг по pipeline; результат приходит по NATS, коррелируется по id'
}
Table osv_entry {
id uuid [pk]
recognition_job_id uuid [not null, ref: > recognition_job.id, note: 'файл достаётся через задание']
account_code varchar [note: 'сырой код счёта из разбора']
account_id uuid [ref: > chart_of_account.id, note: 'резолвнутая ссылка на план счетов (nullable)']
account_root varchar
counterparty_name varchar
counterparty_inn varchar [note: 'просто данные; внешний контрагент, без FK']
counterparty_type counterparty_type
opening_debit numeric
opening_credit numeric
turnover_debit numeric
turnover_credit numeric
closing_debit numeric
closing_credit numeric
Note: 'Строка ОСВ (разобрано из XLSX)'
}
Table financial_statement_line {
id uuid [pk]
recognition_job_id uuid [not null, ref: > recognition_job.id, note: 'файл достаётся через задание']
statement_type statement_type [note: 'balance | income (ОФР)']
line_code varchar [note: 'код строки формы, напр. 1230']
line_name varchar
row_kind fsl_row_kind
ordinal int
Note: 'Строка баланса/ОФР (распознано из изображения: PDF/PNG/JPG)'
}
Table financial_statement_value {
id uuid [pk]
line_id uuid [not null, ref: > financial_statement_line.id]
period_label varchar [note: 'колонка-компаратор внутри формы (2-3 сравнительные даты), не период файла']
amount numeric
is_recognized boolean [note: 'false = не распознано']
Note: 'Значение строки по колонке-периоду (сравнительные колонки баланса/ОФР)'
}
Табличная форма
| Сущность | Наименование атрибута | Тип данных | Обязательность | Ограничения | Комментарии |
|---|---|---|---|---|---|
| regional\_office | id | uuid | + | PK | Идентификатор филиала |
| name | varchar | + | UNIQUE | Наименование филиала | |
| is\_active | boolean | + | DEFAULT true | Признак активности филиала | |
| company\_group | id | uuid | + | PK | Идентификатор группы компаний |
| crm\_id | varchar | + | UNIQUE | Ключ из CRM | |
| name | varchar | + | Наименование ГК | ||
| base\_regional\_office\_id | uuid | - | FK regional\_office(id) | Региональный филиал группы | |
| valid\_from | timestamptz | + | Дата начала действия текущего состояния (SCD4) | ||
| updated\_by | varchar | - | Кто последним изменил запись | ||
| created\_at | timestamptz | - | Дата создания записи | ||
| company\_group\_history | id | uuid | + | PK | Идентификатор снимка |
| company\_group\_id | uuid | + | FK company\_group(id) | Группа компаний, к которой относится снимок | |
| crm\_id | varchar | + | Ключ из CRM | ||
| name | varchar | + | Наименование ГК | ||
| base\_regional\_office\_id | uuid | - | Региональный филиал группы | ||
| valid\_from | timestamptz | + | Начало действия снимка | ||
| valid\_to | timestamptz | - | Окончание действия снимка | ||
| changed\_by | varchar | - | Кто изменил запись | ||
| - | - | UNIQUE (company\_group\_id, valid\_from) | Уникальность снимка группы на дату | ||
| legal\_entity | id | uuid | + | PK | Идентификатор организации |
| inn | varchar | + | UNIQUE | ИНН | |
| entity\_type | entity\_type | - | ENUM | Тип субъекта. Возможные значения: * ЮЛ (юридическое лицо) * ИП (индивидуальный предприниматель) | |
| name | varchar | + | Наименование организации | ||
| company\_group\_id | uuid | + | FK company\_group(id) | Текущая группа компаний | |
| regional\_office\_id | uuid | - | FK regional\_office(id) | Филиал, за которым закреплена организация | |
| close\_date | date | - | NULL - организация активна; дата - архивирована или закрыта | ||
| valid\_from | timestamptz | + | Дата начала действия текущего состояния (SCD4) | ||
| updated\_by | varchar | - | Кто последним изменил запись | ||
| created\_at | timestamptz | - | Дата создания записи | ||
| legal\_entity\_history | id | uuid | + | PK | Идентификатор снимка |
| legal\_entity\_id | uuid | + | FK legal\_entity(id) | Организация, к которой относится снимок | |
| inn | varchar | + | ИНН на момент снимка | ||
| entity\_type | entity\_type | - | ENUM | Тип субъекта на момент снимка (ЮЛ / ИП) | |
| name | varchar | + | Наименование организации на момент снимка | ||
| company\_group\_id | uuid | + | Группа компаний на момент снимка | ||
| regional\_office\_id | uuid | - | Филиал на момент снимка | ||
| close\_date | date | - | Дата архивирования на момент снимка | ||
| valid\_from | timestamptz | - | Начало действия снимка | ||
| valid\_to | timestamptz | - | Окончание действия снимка | ||
| changed\_by | varchar | - | Кто изменил запись | ||
| - | - | UNIQUE (legal\_entity\_id, valid\_from) | Уникальность снимка организации на дату | ||
| related\_group | id | uuid | + | PK | Идентификатор группы связанных компаний / заёмщиков |
| code | varchar | + | UNIQUE | Код группы (например, GSK-001) | |
| company\_group\_id | uuid | + | FK company\_group(id) | Группа компаний, в рамках которой создана ГСК/ГСЗ | |
| kind | related\_group\_kind | - | ENUM | Вид группы. Возможные значения: * gsk (группа связанных компаний) * gsz (группа связанных заёмщиков) | |
| name | varchar | + | Наименование группы | ||
| created\_date | date | - | Дата создания группы | ||
| - | - | UNIQUE (id, kind) | Ограничение для составного внешнего ключа из related\_group\_member | ||
| related\_group\_member | id | uuid | + | PK | Идентификатор записи о членстве |
| related\_group\_id | uuid | + | FK related\_group(id) | Группа, в состав которой входит организация | |
| legal\_entity\_id | uuid | + | FK legal\_entity(id) | Организация - участник группы | |
| kind | related\_group\_kind | + | составной FK (related\_group\_id, kind) related\_group(id, kind) | Копия вида группы из related\_group | |
| valid\_from | timestamptz | + | Дата включения в состав группы | ||
| valid\_to | timestamptz | - | Дата исключения. NULL - действующая версия | ||
| is\_current | boolean | + | Признак действующей версии (SCD2) | ||
| created\_by | varchar | - | Кто включил организацию в состав | ||
| - | - | partial UNIQUE (related\_group\_id, legal\_entity\_id) WHERE is\_current | Одна текущая версия на пару группа - организация | ||
| - | - | partial UNIQUE (legal\_entity\_id) WHERE is\_current AND kind = gsk | Организация одновременно входит только в одну ГСК | ||
| chart\_of\_account | id | uuid | + | PK | Идентификатор счёта |
| code | varchar | + | UNIQUE | Натуральный код счёта или субсчёта (например, 60.01) | |
| parent\_id | uuid | - | FK chart\_of\_account(id) | Родительский счёт | |
| name | varchar | + | Наименование счёта | ||
| kind | account\_kind | - | ENUM | Тип счёта. Возможные значения: * A (активный) * P (пассивный) * AP (активно-пассивный) | |
| role | id | uuid | + | PK | Идентификатор роли |
| code | varchar | + | UNIQUE | Код роли. Возможные значения: * ADMIN (администратор) * KA\_RF (кредитный аналитик РФ) * KA\_GO (кредитный аналитик ГО) * KA\_HEAD (руководитель КА) * CLIENT\_MANAGER (клиентский менеджер) * CURATOR\_GO (куратор ГО) * EXPERT (Эксперт) | |
| name | varchar | + | Отображаемое название роли. Отделено от кода, чтобы права проверялись по коду, а не по русской строке | ||
| app\_user | id | uuid | + | PK | Идентификатор пользователя |
| varchar | + | UNIQUE | Электронная почта пользователя | ||
| username | varchar | + | UNIQUE | Логин пользователя | |
| hashed\_password | varchar | - | Хеш пароля | ||
| full\_name | varchar | - | ФИО пользователя | ||
| role\_id | uuid | + | FK role(id) | Роль пользователя | |
| regional\_office\_id | uuid | + | FK regional\_office(id) | Филиал пользователя | |
| created\_at | timestamptz | - | Дата создания учётной записи | ||
| updated\_at | timestamptz | - | Дата изменения учётной записи | ||
| is\_active | boolean | + | DEFAULT true | Признак активности учётной записи | |
| stored\_file | id | uuid | + | PK | Идентификатор загруженного файла |
| legal\_entity\_id | uuid | + | FK legal\_entity(id) | Организация - владелец документа | |
| document\_type | document\_type | - | ENUM | Тип документа. Возможные значения: * Бухгалтерская отчётность * ОСВ * ОФР * Прочий документ | |
| file\_type | file\_type | - | ENUM | Формат файла. Определяет маршрут распознавания: * XLSX - табличный сервис * PDF, PNG, JPG - сервис изображений | |
| original\_name | varchar | - | Исходное имя файла при загрузке | ||
| s3\_key | varchar | - | UNIQUE | Ключ объекта в хранилище S3 | |
| content\_hash | varchar | - | SHA-256 содержимого для дедупликации | ||
| size\_bytes | bigint | - | Размер файла в байтах | ||
| period\_year | smallint | - | Год отчётного периода | ||
| period\_quarter | period\_quarter | - | ENUM | Квартал отчётного периода - Q1, Q2, Q3, Q4 | |
| status | file\_status | - | ENUM | Статус обработки файла. Возможные значения: * Загружен * Обработка * Требуется проверка * Ошибка | |
| current\_recognition\_job\_id | uuid | - | FK recognition\_job(id) | Авторитетный прогон распознавания. Определяет, чьи строки отображаются | |
| uploaded\_by | varchar | - | Кто загрузил файл | ||
| uploaded\_at | timestamptz | - | Дата и время загрузки | ||
| recognition\_job | id | uuid | + | PK | Идентификатор задания на распознавание |
| file\_id | uuid | + | FK stored\_file(id) | Файл, который распознаётся | |
| pipeline | recognition\_pipeline | + | ENUM | Маршрут обработки. Возможные значения: * tabular (сервис разбора XLSX) * image (сервис распознавания PDF/PNG/JPG) | |
| service\_version | varchar | - | Версия сервиса или модели распознавания | ||
| status | recognition\_status | - | ENUM | Статус задания. Возможные значения: * queued (в очереди) * processing (в обработке) * done (завершено) * error (ошибка) | |
| attempt | smallint | - | Номер попытки | ||
| queue\_msg\_id | varchar | - | Идентификатор сообщения NATS для дедупликации при повторной доставке | ||
| requested\_at | timestamptz | - | Дата и время публикации задания в очередь | ||
| started\_at | timestamptz | - | Когда сервис взял задание в работу | ||
| finished\_at | timestamptz | - | Когда задание завершено | ||
| error\_message | text | - | Текст ошибки распознавания | ||
| raw\_result\_s3\_key | varchar | - | Ключ JSON-результата в хранилище (бакет results) | ||
| osv\_entry | id | uuid | + | PK | Идентификатор строки ОСВ |
| recognition\_job\_id | uuid | + | FK recognition\_job(id) | Задание распознавания | |
| account\_code | varchar | - | Код счёта в исходном виде из документа | ||
| account\_id | uuid | - | FK chart\_of\_account(id) | Ссылка на план счетов | |
| account\_root | varchar | - | Корневой счёт | ||
| counterparty\_name | varchar | - | Наименование контрагента | ||
| counterparty\_inn | varchar | - | ИНН контрагента | ||
| counterparty\_type | counterparty\_type | - | ENUM | Признак контрагента. Возможные значения: * ГК (в группе компаний) * ГСК (в периметре) * Внешний | |
| opening\_debit | numeric | - | Сальдо на начало периода, дебет | ||
| opening\_credit | numeric | - | Сальдо на начало периода, кредит | ||
| turnover\_debit | numeric | - | Оборот за период, дебет | ||
| turnover\_credit | numeric | - | Оборот за период, кредит | ||
| closing\_debit | numeric | - | Сальдо на конец периода, дебет | ||
| closing\_credit | numeric | - | Сальдо на конец периода, кредит | ||
| financial\_statement\_line | id | uuid | + | PK | Идентификатор строки формы отчётности |
| recognition\_job\_id | uuid | + | FK recognition\_job(id) | Задание распознавания, из которого получена строка | |
| statement\_type | statement\_type | - | ENUM | Тип формы. Возможные значения: * balance (бухгалтерский баланс) * income (ОФР) | |
| line\_code | varchar | - | Код строки формы (например, 1230) | ||
| line\_name | varchar | - | Наименование показателя | ||
| row\_kind | fsl\_row\_kind | - | ENUM | Вид строки. Возможные значения: * section (раздел) * row (показатель) * sub (подстрока) * total (итог раздела) * balance (валюта баланса) | |
| ordinal | int | - | Порядок строки в форме | ||
| financial\_statement\_value | id | uuid | + | PK | Идентификатор значения |
| line\_id | uuid | + | FK financial\_statement\_line(id) | Строка формы, к которой относится значение | |
| period\_label | varchar | - | Колонка-компаратор внутри формы (сравнительные даты) | ||
| amount | numeric | - | Значение показателя | ||
| is\_recognized | boolean | - | false - значение не распознано |
