- consolidation_version.elimination_rules_version NOT NULL: миграция 0010
проставляет существующим версиям номер правил, действовавших на дату
создания (по Москве), иначе последних открытых; без правил — отказ;
создание версии без действующих правил — 409 ELIMINATION_RULES_MISSING;
ветки «правила не зафиксированы» убраны (rules, preset, is_version_fixed
всегда true);
- GET …/elimination-totals: все тройки «правило ББ × упорядоченная пара
периметра» с ΣA, ΣB, расхождением, суммой элиминации, статусом
AUTO/DISCREPANCY/ONE_SIDED/MANUAL и osv_entry_ids; сводная ОСВ строится
один раз; сбор строк сторон вынесен в _collect_rule_sides — общий
с упаковкой тройки.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Модели и upgrade ревизии 0007_dbml_v5_19: пять enum'ов, колонки строк/значений/колонок/шапок форм,
document.file_ordinal (уникален в файле, уникальность типа только для не-форм), recognition_job.statements_version,
related_group.crm_id, таблица document_issue; заполнение по умолчанию (row_index, needs_review, header_source и др.).
delete_file_statements удаляет document_issue; make_document берёт следующий file_ordinal; маппер пока нумерует
документы по порядку создания. downgrade — заглушка (задача A2).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
DB_SCHEMA (по умолчанию dkb, валидация идентификатора) читают models/base.py (SCHEMA), db/db.py (search_path),
alembic/env.py и миграции 0001-0005 (SCHEMA и строковые FK f"{SCHEMA}.x.id" вместо литералов). В контуре -
OPENBAO__APP__DB_SCHEMA. Офлайн-SQL `alembic upgrade head --sql` при значении по умолчанию совпадает побайтно.
Тесты: валидация настройки, миграции и сессия приложения в схеме dkb_alt; .env.example/.env.test/README/CLAUDE.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EAKRDNzXtRrwmWz9z6PZu3
- модели LegalEntity.kpp / LegalEntityHistory.kpp (последней колонкой), миграция 0005_dbml_v5_17 (upgrade/downgrade);
- domain/kpp.py: 9 символов (4 цифры, 2 цифры/латинские A-Z, 3 цифры), у ИП запрещён, иначе 422 INVALID_KPP;
- схемы Create/Update/Out/Detail/HistoryOut, PATCH пишет снимок history и аудит before/after с kpp, поиск q по КПП;
- импорт справочника: необязательная колонка КПП (синоним kpp), код INVALID_KPP, update обновляет непустой КПП;
- dev-seed: необязательный ключ kpp (значений в данных нет, не выдумываем);
- сверка с DBML, Makefile, README, CLAUDE.md, openspec/config.yaml — на v5.17.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EAKRDNzXtRrwmWz9z6PZu3
- ORM: ix_osv_entry_parent_entry_id, ix_osv_entry_recognition_job_id (models/osv.py),
ix_stored_file_current_recognition_job_id (models/files.py) — по DBML v5.15 п. 4.
- Миграция 0003_dbml_v5_15: create_index в upgrade, drop_index в downgrade.
- tests/test_migrations.py: индексы есть после upgrade head (btree, не unique), исчезают
после downgrade на 0002 и возвращаются при повторном upgrade.
- openspec change: design.md решение №53 (I-1 закрыт в v5.15), Migration Plan; дельта
data-model — 0003 создаёт индексы, откат на шаг их удаляет.
- README «Ограничения Среза 2c»: убран пункт об отсутствии индексов.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
- OsvDataType.NU после BU, DBML_VERSION = 5.15, Makefile/dbml_parity/docstring'и на data-model-v5.15.dbml;
- миграция 0003_dbml_v5_15: ADD VALUE 'NU' AFTER 'BU' + lower(app_user.email); downgrade пересоздаёт osv_data_type
(регистр email не возвращается);
- email хранится в нижнем регистре: users_admin.create_user и seed (_apply_users); с UNIQUE по строчному email гонка
создания в другом регистре теперь ловится индексом (тест test_api_constraint_races обновлён);
- тесты: enum NU, откат на шаг, lower email на миграции, seed/админка, вставка NU, фиктивная v5.16.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
- RelatedGroupMember.kind (related_group_kind, NOT NULL) между legal_entity_id и valid_from, как в DBML;
частичный уникальный индекс uq_related_group_member_entity_kind_current (legal_entity_id, kind) WHERE is_current —
ЮЛ одновременно в одной ГСК и одной ГСЗ.
- AuditAction: LEGAL_ENTITY_CHANGE (после GROUP_CHANGE), USER_CHANGE (после USER_ROLE_CHANGE).
- Последовательности company_group_code_seq / related_group_code_seq в metadata (design D-5).
- Миграция 0002_dbml_v5_14: related_group_member пересоздаётся с переносом строк (kind из группы), чтобы порядок
колонок совпал с DBML и create_all; ALTER TYPE ADD VALUE ×2; downgrade пересоздаёт audit_action v5.13.
- DBML_VERSION = 5.14, пути к data-model-v5.14.dbml (Makefile, dbml_parity), тесты: откат на шаг, перенос строк,
уникальность gsk+gsz, офлайн-SQL до head.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
PostgreSQL проверяет право CREATE на базу раньше IF NOT EXISTS: роль миграций, которой платформа выдала готовую
схему dkb без этого права, падала на CREATE SCHEMA IF NOT EXISTS. env.py (онлайн) проверяет pg_namespace и создаёт
схему только при отсутствии; офлайн-SQL и upgrade() ревизии 0001 — DO-блок с той же проверкой. Тест: схема заранее
во владении отдельной роли, CREATE на базу отозван у PUBLIC — upgrade/check/downgrade/upgrade проходят.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Схема dkb создаётся и фиксируется до context.configure (онлайн) и печатается первой в офлайн-SQL.
URL: -x dburl > sqlalchemy.url, заданный вызывающим кодом (не заглушка driver://) > настройки.
Async-движок из URL напрямую (без configparser-интерполяции %).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>