Andrey Epifancev 239d5bc270 OpenSpec: change slice-2c-osv-ingest (загрузка файлов, цикл маппинга, документы — спека)
proposal, design (D-1…D-13), спеки primary-files, osv-result-mapping, documents-api (новые), recognition-job-exchange,
data-model (MODIFIED), audit-trail (ADDED), tasks (13 задач).

Issue: RSHB/arm-core#14

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 21:08:56 +04:00

5.6 KiB
Raw Blame History

Spec Delta: data-model

RENAMED Requirements

  • FROM: ### Requirement: Схема БД равна DBML v5.14
  • TO: ### Requirement: Схема БД равна DBML v5.15

MODIFIED Requirements

Requirement: Схема БД равна DBML v5.15

ORM-метаданные SHALL содержать ровно 43 таблицы и 27 enum'ов из ../docs/model/data-model-v5.15.dbml в схеме dkb; имена таблиц, колонок, enum'ов и их значений SHALL совпадать с DBML буквально; nullability, PK, UNIQUE, FK, значения по умолчанию и индексы SHALL соответствовать DBML, включая частичные уникальные индексы (related_group_member (related_group_id, legal_entity_id) и (legal_entity_id, kind) WHERE is_current, consolidation_lock WHERE released_at IS NULL) и NULLS NOT DISTINCT на document (stored_file_id, document_type, osv_account_code). related_group_member.kind SHALL быть NOT NULL и равняться related_group.kind группы (проверяет ядро при вставке). audit_action SHALL содержать LEGAL_ENTITY_CHANGE и USER_CHANGE; osv_data_type SHALL содержать NU (после BU). app_user.email SHALL храниться в нижнем регистре (нормализация при записи seed'ом и администрированием). Поля, отсутствующие в DBML, MUST NOT существовать.

Scenario: Сверка ORM с DBML

  • WHEN выполняется python scripts/check_dbml_vs_orm.py ../../docs/model/data-model-v5.15.dbml
  • THEN вывод пуст и код возврата 0

Scenario: Лишняя колонка в ORM

  • WHEN в ORM добавлена колонка, которой нет в DBML (или удалена существующая)
  • THEN скрипт печатает таблица.колонка: отсутствует в DBML (или отсутствует в ORM) и возвращает код 1

Scenario: Расхождение типа или nullability

  • WHEN колонка osv_entry.opening_debit объявлена в ORM как Numeric(18, 4) или NOT NULL
  • THEN скрипт сообщает ожидалось numeric(18,2) NULL / фактически numeric(18,4) NOT NULL и возвращает код 1

Scenario: ЮЛ одновременно в ГСК и ГСЗ

  • WHEN для одного legal_entity_id вставлены две текущие строки related_group_member с kind = gsk и kind = gsz
  • THEN обе вставки проходят; третья текущая строка с kind = gsk нарушает уникальный индекс

Scenario: Строка налогового учёта

  • WHEN в osv_entry вставляется строка с data_type = 'NU'
  • THEN вставка проходит

Requirement: Миграции применяются с нуля и откатываются

Цепочка ревизий 0001_dbml_v5_13 → 0002_dbml_v5_14 → 0003_dbml_v5_15 SHALL создавать схему dkb (если нет), все enum'ы, таблицы, ограничения, индексы и последовательности кодов (company_group_code_seq, related_group_code_seq) на пустой базе PostgreSQL 16 (требуется ≥ 15); 0003 SHALL добавлять NU в osv_data_type и приводить app_user.email к нижнему регистру; downgrade до base SHALL удалять всё созданное (новые значения enum — через пересоздание типа), оставляя пустую схему; повторный upgrade после downgrade SHALL проходить без ошибок.

Scenario: Полный цикл

  • WHEN на пустой БД выполняются alembic upgrade head, alembic downgrade base, alembic upgrade head
  • THEN все три команды завершаются успешно, после последней в information_schema.tables схемы dkb 43 таблицы модели (+ служебная alembic_version) и в pg_type 27 enum-типов

Scenario: Откат на один шаг

  • WHEN после upgrade head выполняется alembic downgrade 0002_dbml_v5_14
  • THEN osv_data_type не содержит NU; регистр app_user.email не возвращается (данные)

Scenario: Автогенерация ничего не находит

  • WHEN после upgrade head выполняется alembic revision --autogenerate на той же БД
  • THEN сгенерированная ревизия не содержит операций (пустые upgrade/downgrade)

Requirement: Версия DBML зафиксирована в коде

Пакет моделей SHALL объявлять константу версии DBML (5.15); скрипт сверки SHALL сравнивать её с версией в шапке файла DBML и падать при расхождении — смена модели без осознанного обновления ORM невозможна.

Scenario: Новая версия DBML без обновления ORM

  • WHEN в docs/model/ появляется data-model-v5.16.dbml, а константа в ORM — 5.15
  • THEN сверка против нового файла падает с сообщением о версии до сравнения таблиц