arm-ka-docs/source/tz/АРМ КА.Техническое задание - 01_2. Модель данных (сущности).md

29 KiB
Raw Blame History

code, title
code title
DOC-019834 2. Модель данных (сущности)

2. Модель данных (сущности)

1

attachment Состав ГК\_ГСК\_ГСЗ\_из выписок\на 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 Идентификатор пользователя
email 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 - значение не распознано