`memberships` перенесено из `LegalEntityDetail` в `LegalEntityOut`: поле приходит в списке
`GET /directories/legal-entities`, в ответах `move`/`withdraw` (после них — `[]`) и, как раньше,
в карточке. Членства набора ЮЛ читаются одним запросом
(`current_memberships_by_entities`), без N+1. Нужно карточке ГК для фильтра ЮЛ по ГСК/ГСЗ.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Пункт 3.2 (make check-full) не отмечен: Python-часть зелёная, web-check падает на npm install (404 rollup в реестре).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- invalid_subject параметризован по трём ключам, equality покрывает три пары
- кейс утечки JWT/seed при невалидном subject
- /healthcheck с нестандартными subject'ами и проверкой отсутствия JWT
- subscribe с настроенным subject'ом, лог старта с subject'ами
- tasks.md: отмечены 1.1, 1.2, 2.x, 3.1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
I-2: delta MODIFIED consolidations-api «Статусы Среза 4» (загрузка в консолидацию).
T1.1: шапки моделей — DBML v5.18.
T3.1: lock_versions_of_consolidation — двухшаговая блокировка (FOR UPDATE без членства, затем выборка членов);
тесты гонки и выборки.
M-1: тест миграции 0006 — порядок кварталов внутри года.
M-2: тест 404 для ЮЛ чужого филиала на столе своей консолидации.
T4.1: docstring supersede_previous — перенос строк.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Формы «Добавить/Изменить юридическое лицо» (макет 51-02, 79) отправляют всё
одним запросом. POST/PATCH /directories/legal-entities принимают `aliases`,
`gsk_id`, `gsz_id` и применяют их в той же транзакции, что и поля ЮЛ.
- POST: алиасы и членства создаются вместе с ЮЛ; ошибка откатывает всё.
- PATCH: `aliases` — итоговый набор (сверка по normalized_alias; удаление —
с правом DIRECTORY_DELETE, иначе 403), `gsk_id`/`gsz_id` — итоговые группы
(`null` — выйти, другая — сменить); не переданное поле не меняется.
- Новая ошибка 422 WRONG_GROUP_KIND; дубль в списке — 409 ALIAS_EXISTS.
- Ответ POST и PATCH — LegalEntityDetail (надмножество LegalEntityOut).
- Логика ручек алиасов и состава ГСК/ГСЗ вынесена в функции модулей
(add_alias/remove_alias, add_membership/close_membership) — форма и ручки
ведут себя одинаково; PermissionDeniedError — единый 403 «недостаточно прав».
- Спека directories-api и README обновлены.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Спеки documents-api и statement-checks обновлены дельтой change'а; change перенесён в
openspec/changes/archive/2026-10-09-statement-template-lines/. Реализация — PR #81.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
M-9: design.md и proposal.md приведены к коду (достройка - _lines_out в
schemas/statements.py, справочник без valid_from/valid_until, ленивая
загрузка с ручными проверками); добавлены R-12 и R-13. T5.1/M-8: сигнатура
PATCH values и обратные кавычки в таблице ошибок README.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Спека: достройка формы по справочнику строк редакции в GET …/statement,
создание строки и ячейки при первой правке по line_code, пустые шаблонные
строки вне проверок §7 и статуса.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019qoydUVv8g1qHxc123u2RR
Решения владельца 08.10.2026:
- отмена П-1: «Осталось N» (`unmapped_total`) и `?unmapped=true` — строки без ЮЛ после резолва и без ИНН из файла;
строка с ИНН, которого нет в справочнике, сопоставления не требует (`domain.needs_mapping`);
- `ConsolidatedRowOut.counterparty_entity_inn` — ИНН сопоставленного ЮЛ справочника (П-8): фронту — «таблетка»
с ИНН и пересопоставление у строк, сопоставленных без ИНН в файле.
Фикстуры РБ 2024 Q3: unmapped_total 1379 → 1260. Спека consolidated-osv и README обновлены.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
В LegalEntityOut (а значит и LegalEntityDetail) добавлено company_group_name: текущее имя ГК company_group_id,
архивной тоже; у монозаёмщика null. Есть во всех ответах /directories/legal-entities: список, карточка, POST,
PATCH, move, withdraw; в снимках истории нет. Имена набора ЮЛ подгружаются одним батч-запросом
(repositories.directories.company_group_names_by_ids), число запросов списка от числа строк не зависит.
Спека directories-api и README дополнены.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
Proposal, design (D-1…D-6, решения без обсуждения №1–7) и дельты osv-result-mapping,
primary-files, audit-trail: чистый документ при маппинге сразу CONFIRMED (система,
confirmed_by NULL; переход версии — от загрузившего), удаление автоподтверждённых
файлов до DATA_CORRECTION включительно. Решение владельца 08.10.2026, ТЗ 03_9 п. 4.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Замена остаётся на уровне файла (§9.5 п. 3, OQ-115), но если у заменённого файла есть
документы, ключа которых (document_type, osv_account_code, год, квартал) нет среди
документов нового файла, в metrics.mapping_warnings задания нового файла добавляется
предупреждение (OQ-154): имя и версия заменённого файла, выпавшие документы (тип, счёт,
период, статус, в т. ч. CONFIRMED) и версии консолидации, с которых сняты привязки
выпавших документов. Поведение замены, FILE_REPLACE и статусы документов не меняются.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
CounterpartyIndex.resolve: порядок шагов ИНН -> точное имя -> алиас -> нормализованное
имя (OQ-128, §3 п. 4). Алиас уникален (ALIAS_TAKEN), поэтому владелец алиаса берётся
с match_kind = ALIAS, даже если есть ЮЛ-тёзки по нормализованному имени; NULL остаётся
при нескольких совпадениях только по имени. Правило общее для маппинга (Срез 2c) и
дорезолва свода на чтение (§3 п. 7).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
- модели 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
seed/dev/company_groups.yaml: ГК «Русский Бисквит» ровно как в fixtures/directories/ecp-export-russkiy-biskvit.xlsx
(20 ЮЛ/ИП, crm_id, филиал «Санкт-Петербургский РФ», ГСК из РБ и Счастливочной), ГК Унагранде/НПЗ/Межениновская по
ИНН из форм ББ/ОФР; алиасы под имена контрагентов и шапок ОСВ («Юг-Финанс / ПЕКАРНЯ СЧАСТЛИВОЧНАЯ», ...), чтобы
документы из fixtures ложились на «своих» ЮЛ и резолвились. Загрузчик проверяет ИНН, виды, ссылки членов и
уникальность «ЮЛ в одной ГСК/ГСЗ» до записи; apply — upsert по name/inn/(ГК, name), коды из последовательностей
API, без удалений. `--no-dev-groups` / `run_seed(dev_groups=False)` — dev-данные без ГК; фикстуры тестов API
используют его, чтобы начинать с пустых справочников.
make check: 1132 passed; интеграция seed/import: 23 passed. Два теста падают и на main из-за обновлённых golden
(test_mapping_golden 88 → 113, test_consolidation_fixtures UNMAPPED_TOTAL) — отдельная issue.
Closes#31
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b