В 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
Seed chart_of_accounts.csv заменён выгрузкой 1С: буквенные субсчета (01.К, 62.ОТ, 76.АВ),
забалансовые 001–012 и буквенные корни (МЦ, ГТД…), «Я…». Валидатор seed принимает буквенные
коды, 000 и 012, сирот выгрузки («Я68.01» без «Я68») с пустым parent_code; kind — из «Вида» 1С.
18 из 19 кодов реальных ОСВ теперь получают account_id (60.АВ — только в синтетике, в 1С нет).
ASSUMPTION(OQ-113): выгрузка считается полной.
Closes#23
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
I-1 (T8.2): тесты, что неподтверждённый документ даёт NEEDS_CHECK/RECOGNIZED только если подходит версии (fits):
нарастающий Q2 и квартальный Q4 при версии Q3, другой год и ЮЛ вне периметра не влияют; положительный контроль.
M-2: 404 `NOT_FOUND` с сообщением `…_NOT_FOUND`, ключ привязки с признаком нарастающего (R-1, R-14), порядок и
режимы блокировок подтверждения (R-3) в spec. M-3: в design #39 и #43 — окно коммита перехода после загрузки.
M-5: docstring lock_versions_for_entity про ЮЛ без ГК в периметре.
Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
Точные числа свода и набор пробелов, кандидаты, MANUAL/alias_created, EXTERNAL до сопоставления; формулировка
сценария «Сопоставление из плана среза» и design #80 уточнены; docstring effective_cumulative.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
ББ/ОФР за Q1 — отчёт на конец квартала, не источник версий Q2–Q4. В
`consolidation_documents._cumulative` равнозначность Q1 (`effective_cumulative`)
применяется только к `document_type = OSV`; для ББ/ОФР — прежнее правило D-5 (NULL —
нарастающий, только квартал версии), ключ замены не меняется.
- тесты: ББ/ОФР за Q1 подходят только версии Q1; ключ замены ББ/ОФР всегда с
признаком нарастающего, ОСВ за Q1 — без различия флага; подтверждение ББ/ОФР за Q1
при версии Q3 — без привязки и перехода; ячейка ББ чек-листа Q3 не закрывается ББ Q1
- спека documents-api: ключ замены R-1 с признаком нарастающего (вместо устаревшей
«тройки»), равнозначность Q1 — только для ОСВ; consolidated-osv — «ОСВ за Q1»
- design #81: R-14 + R-14a
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
Сквозной тест на фикстурах РБ показал: парсер помечает ОСВ за Q1 нарастающей, а
привязка (`fits`) брала нарастающий только за квартал версии, `select_sources` не
считал его квартальным Q1 — для версии Q3 привязано 17 из 22, пары 60/62(/76) в
пробеле [Q1], свод пуст.
- consolidation_periods.effective_cumulative: для Q1 — квартальный при любом флаге;
одна функция для `fits`, ключа замены `_key`, `select_sources` (версии Q2+) и
адаптера чек-листа; для версии Q1 поведение прежнее (№50)
- тесты: таблица effective_cumulative, select_sources/build/чек-лист с нарастающим
Q1, fits любой версии года, подтверждение и подхват (нарастающий и квартальный Q1 —
один слот, побеждает поздний)
- test_consolidation_fixtures: xfail снят, сценарий зелёный (22 привязки, 1385 строк)
- спеки documents-api и consolidated-osv: фраза о равнозначности Q1; design #81;
план Task 13 Step 2–4 и tasks.md 5.1 отмечены
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
Хелпер map_golden_snapshot, сценарий маппинг golden -> подтверждение -> консолидация 2024 Q3 -> свод,
сопоставление Счастливочной, экспорт, независимая сверка склейки периодов. Тест помечен xfail(strict):
на реальных данных нарастающий Q1 (is_cumulative=true) не привязывается к версии Q3 и не считается
квартальным (fits / select_sources) — свод пуст; подробности в отчёте задачи.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
GET /consolidations/versions/{id}/osv/export: лист «Сводная ОСВ» (15 колонок D-14, суммы — числовые
ячейки #,##0.00 из Decimal) и лист «Пробелы» по своду целиком; фильтры как у GET …/osv без пагинации;
Content-Disposition с filename* (чистый ASCII); audit_event(EXPORT) с filters и rows.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
GET …/counterparty-candidates (scope group|all, QUERY_TOO_SHORT, recommended по
нормализованному имени строки) и POST …/osv/entries/{entry_id}/counterparty:
проверка строки свода версии, ЮЛ без policy, ALIAS_TAKEN с owners / перенос алиаса,
MANUAL строке и PROPAGATED строкам с тем же strip()-именем без противоречия ИНН,
один OSV_COUNTERPARTY_MAP и LEGAL_ENTITY_CHANGE на каждый алиас. Строки общие для
версий блокируются FOR NO KEY UPDATE ORDER BY id; advisory-блокировка алиаса общая
со справочником. Решения #62–#70 в design.md; 4.3 отмечена.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
GET /consolidations/versions/{id}/osv и /osv/summary (CONSOLIDATION_VIEW): ConsolidatedOsvService собирает свод
чистой функцией от версии (периметр, привязанные ОСВ, load_osv_rows, один CounterpartyIndex, один SELECT legal_entity)
и режет страницу в памяти; чтение любой версии, включая CANCELLED, без блокировок и аудита.
OsvFilters отделён от OsvPageParams (T2.7), суммы всегда с двумя знаками; account_sort_key устойчив к «6²»/«①» (T9.a).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
Домен `checklist` (Rule, CellStatus, Cell, order_rules, build) — чистые функции без ORM; ячейка (ЮЛ, правило):
CONFIRMED по привязанным документам (ОСВ: нарастающий за квартал версии либо квартальные Q1..Qn, пробел →
missing_quarters; ББ/ОФР: документ за квартал версии), NEEDS_CHECK/RECOGNIZED по неподтверждённому подходящему,
PROCESSING, ERROR, иначе MISSING; правило ОСВ закрывает только точный код счёта. Репозиторий: rules_for,
unconfirmed_documents. Сервис: checklist(), ячейки в карточке версии. Маршрут GET /consolidations/versions/{id}/checklist.
Схема использует CellStatus домена (T2.8). Решения №44-49 в design.md.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
T7.0: двухсессионный тест маппинг ∥ перевод версии в DOCUMENTS_PROCESSING (ловит мутант
statuses={DOCUMENTS_PROCESSING}). T7.1 (R-10, design №43): ошибка перехода после загрузки логируется,
принятые файлы и 201 сохраняются. T7.3: лог пропуска без uploaded_by только при наличии NEEDS_CHECK.
T7.4: TransactionFactory импортируется из session_audit. T7.2/T7.5: дополнена строка design №39.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
Загрузка с consolidation_version_id: проверки до приёма (404/409/422), после приёма
INITIATED -> DOCUMENTS_PROCESSING в отдельной транзакции без блокировки версии.
Маппинг: on_documents_mapped переводит версии DOCUMENTS_PROCESSING в DATA_CORRECTION
при подходящем документе NEEDS_CHECK (changed_by = uploaded_by), привязки не создаёт.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2