Порядок проверок в контракте, ссылки на решения №1–19, разделители в OQ, уточнения по units и /users/brief, номера PR закрытых срезов 2a/2c/3a, убрана ссылка на исполнителя экранов. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
36 KiB
09. План работ вертикальными срезами
Принцип: каждый срез — рабочий end-to-end кусок (миграции + API + минимальный UI + тесты на реальных фикстурах), который можно показать аналитику. Порядок выбран так, чтобы самое рискованное (парсер ОСВ, матчинг ВГО) проверялось на реальных данных как можно раньше, а внешние зависимости (ИС Сканирование, РАИСА, NATS платформы) не блокировали.
Каждый срез = OpenSpec change в каждом затронутом репозитории (openspec/changes/<slug>/ с proposal.md, specs/,
tasks.md), сквозная часть — change в docs/; задачи — issues в Gitea; PR — по одному на репозиторий. Jira-эпики
пользователя маппятся на срезы (пользователь ведёт соответствие сам).
Срез 0 — Скелет (2–3 дня, три репозитория + docs)
- Три репозитория из нулевого коммита шаблона команды; соглашения шаблона — в
03-architecture.mdи вCLAUDE.mdкаждого репозитория. Первая задача агента — прочитать шаблон и дополнить документы. (Сделано: раздел «Соглашения шаблона команды» в03-architecture.md; вtabular-parser/scan-gatewayфронт и БД вырезаются задачами среза.) - OpenSpec change'и среза:
docs/openspec/changes/slice-0-skeleton(сквозной: контракт, compose, проверки качества, документы) и по одномуopenspec/changes/slice-0-skeletonвarm-core,tabular-parser,scan-gateway; issue #1 в каждом репозитории. docker-composeworkspace-уровня (docs/dev/docker-compose.yml): PostgreSQL 16, NATS 2.10 без JetStream (как на платформе; ack и повторная публикация — на уровне приложения), MinIO (S3, один бакетarm-ka), эмулятор ИС Сканирование (частьscan-gateway, отдаётfixtures/ocr/aep_N.json), три сервиса (профильservices, Python 3.11).Makefileс общими целямиup/test/test-integration/lint/check/check-full(+migrate/seedв ядре) в каждом репо. Порты, запуск профиляservicesи ручная сквозная проверка обменаrecognition_jobчерез NATS (сценарииtabular→NOT_IMPLEMENTED,image→ эмулятор ИС →INVALID_DOCUMENT, потеря ack →dlq) —docs/dev/README.md, разделы «Профильservices» и «Проверка окружения».- Контракт v1.0 — три схемы в
docs/contracts/:recognition-request,recognition-result-message(конверты NATS) иrecognition-result(файл результата) +examples/. Общий пакетarm-ka-contractsне публикуется: каждый сервис хранит копию схем вapi/contracts/и pydantic-модели вsrc/contract/, идентичность сdocs/contractsпроверяется вmake check(решение D-1 changeslice-0-skeletonв docs). - Alembic: миграция 0001 — все таблицы и enum'ы DBML v5.13 (черновик из ORM, сверка с DBML скриптом
api/scripts/check_dbml_vs_orm.py— расхождение = ошибка CI). - Seed (
arm-core/api/seed/, идемпотентно):regional_office(ГО; примеры РФ — только--dev),role(7),permission(16 осмысленных сочетаний объект × действие по §10),role_permissionпо §10,chart_of_account(План счетов 94н + типовые субсчета 1С, OQ-47),elimination_rulev1 из §4 (только ББ),required_document_ruleдля BASIC/EXTENDED (OQ-46). - Auth: валидация JWT + dev-эмитент;
app_userseed (по одному на роль); зависимостьrequire(permission). audit_eventhelper;s3_objectклиент; outbox-паблишер (ackprocessing, повторная публикация без ack,dlq) и подпискаrecognition.result(дедуп поresult_msg_id, пустой маппер документов).- Проверки качества вместо CI (в Gitea CI нет, пайплайн платформы вне репозиториев):
make check(ruff, mypy, pytest, контракт) иmake check-full(+ интеграционные тесты против compose, цикл миграций,check_dbml_vs_orm) —docs/dev/checks.md. - DoD:
GET /api/v1/meвозвращает пользователя и его эффективные права; все миграции применяются и откатываются;make check-fullзелёный в трёх репозиториях.
Срез 1 — Справочники (ГК / ЮЛ / ГСК / ГСЗ / филиалы) + пользователи и роли — завершён 05.10.2026
Объём — вариант Б по решению владельца 04.10.2026: без UI справочника, с минимальным экраном администратора; цель —
быстрее дойти до Среза 2 (tabular-parser). Изначальный состав среза (CRUD + импорт + админка + policy + фикстуры +
UI справочника по макету) разделён: всё, кроме UI справочника, сделано; UI вынесен в отдельный срез.
Сделано (по факту):
- API справочников (
arm-core,/api/v1/directories/*): ГК (code,crm_idnullable, закрепление за РФ, архив, история SCD4), ЮЛ/ИП (ИНН 10/12, алиасы, перевод в другую ГК сeffective_date, закрытие/вывод из ГК, история), ГСК/ГСЗ и состав (SCD2; ЮЛ — одна ГСК и одна ГСЗ одновременно), филиалы (чтение). Каждая мутация пишетaudit_event. - Импорт из выгрузки ЕЦП CRM (
POST /directories/import, правоDIRECTORY_ADMIN): правила —05-domain-rules.md§13,dry_runпо умолчанию,on_existing ∈ {skip, update}, отчёт с кодами,audit_event(DIRECTORY_IMPORT)и файл в S3; полная выгрузка (8400 строк) обрабатывается за ~1 с. - Policy видимости (§10.1): по
regional_office.is_head_office, без проверки кода роли; ЗО не фильтрует (OQ-86); объект вне видимости — 404. - Админ-API и минимальный экран
/admin(«Пользователи и роли»): пользователи, роли, матрица прав (USER_CHANGE,USER_ROLE_CHANGE,ROLE_PERMISSION_CHANGE), защитаLAST_ADMIN; вход — dev-форма (SSO РАИСА — позже). - DBML v5.14 (
related_group_member.kind, partial unique(legal_entity_id, kind),audit_action+LEGAL_ENTITY_CHANGE/USER_CHANGE) и миграция0002вarm-core;entities-v5.14.md. - Фикстура
fixtures/directories/ecp-export-russkiy-biskvit.xlsx(21 строка ГК «Русский Бисквит»;06-test-data.md§6.1). - Документы: §13 и §10.1 в
05-domain-rules.md(сверены с кодом, задача 3.1 changeslice-1-directories), OQ-31/32 закрыты, OQ-86…OQ-97 открыты. - PR: arm-core #6, docs #7, fixtures #3 (issue-ы: arm-core #5, docs #6, fixtures #2).
Перенесено в будущий срез «UI справочника» (номер не присвоен; планируется после Среза 2):
- Экраны справочника по макету: «ГК и организации» [50] (список ГК | карточка с вкладками ЮЛ / ГСК / ГСЗ / Архив),
создание ГК/ЮЛ/ГСК/ГСЗ [51], «ЮЛ вне ГК» [61], вкладка ГСК/ГСЗ [77], изменение ЮЛ [78]–[79], перевод ЮЛ [79-01],
вывод из состава ГК [80], модалка импорта [38]. API для них готов с Среза 1 (см.
10-user-journey.md). - Пока UI нет, справочники заполняются импортом ЕЦП и вызовами API (
/docs).
Срез 2 — Загрузка файлов + табличный парсер (ОСВ, ББ, ОФР из Excel) — самый рискованный, делать рано
Решение владельца 05.10.2026: срез делится на четыре подсреза со своими change'ами и PR; сначала только парсер ОСВ. Порядок: 2a → 2b → 2c → 2d. DoD среза в целом (без правил под конкретный файл, без координат в коде парсера) — в конце раздела.
Срез 2a — Парсер ОСВ (tabular-parser) — закрыт 05.10.2026 (tabular-parser #6, архив #8; docs #10, архив #15; fixtures #5)
Change'и: tabular-parser/openspec/changes/slice-2a-osv-parser (issue arm-tabular-parser#5, PR #6), сквозной
docs/openspec/changes/slice-2a-osv-parser (arm-ka-docs#9), фикстуры arm-ka-fixtures#4. Копия схемы v1.1 в arm-core —
отдельный bounded-PR без логики после merge docs и tabular-parser.
Сделано (по факту):
- Парсер ОСВ
tabular-parser/api/src/parser/: динамическое обнаружение структуры по содержимому (§1.0): листы ОСВ, заголовок таблицы и колонки сумм по тексту (обязательны «обороты» и «сальдо на конец»), шапка иgroup_schema(варианты 1 и 2), иерархия каскадомoutline → indent → account_pattern → sums(+trivialдля пустой ОСВ), классификация строк,Decimal, контрольные суммы §1.4, статусы и коды (05-domain-rules.md§1.6), лимитыPARSE_MAX_BYTES(50 МиБ) иPARSE_TIMEOUT_SECONDS(120 с). Чтение XLSX/XLS/XLSB по сигнатуре. - Словари
api/rules/{osv_headers,osv_groups,periods,data_types}.yaml(данные, не код) с проверкой при старте и тестом «каждая запись срабатывает хотя бы раз». - Контракт v1.1:
rows[].extra(нераспознанные колонки внутри таблицы); примерыresult-osv-minimal.json,result-osv-needs-check.json. - Результат на реальных данных: все 66 файлов
fixtures/osv/**—done, контрольные суммы сходятся, максимум 0,6 с на файл; 16 синтетических файлов (fixtures/osv/synthetic/); 82 golden-снимка (fixtures/golden/expected_osv_parse/); тест-линтер «нет координат вsrc/parser/»; CLIpython -m src.parser.cli <файл>. - Нетривиальное решение (R-21): сверка «сумма детей = родитель» по сальдо идёт по колонкам либо по нетто, если у родителя сальдо свёрнуто (1С показывает счёт нетто, субсчета — развёрнуто); без него 32 из 66 файлов не сходились.
- Допущения парсера, решаются в 2c:
is_cumulativeтолько по тексту периода (OQ-02),data_type = NUкак есть (OQ-45), «Итого» выдаётся строкойTOTAL(OQ-01). - Документы:
05-domain-rules.md§1 приведён к факту (§1.6 — результат парсера),06-test-data.md§7 (синтетика, golden, рукописный xlsb), OQ-98…OQ-105 открыты (финальное ревью добавило OQ-106…OQ-109), OQ-81 частично закрыт (вtabular-parserARM_KA_FIXTURESподдержан;scan-gateway— follow-up). - Не сделано / риски: xlsb проверен только рукописным синтетическим файлом (OQ-102); ИНН из текста строки не извлекался (OQ-100; реализовано позже в tabular-parser PR #15); счета с буквой в первом сегменте не распознаются (OQ-103).
Срез 2b — ББ/ОФР из Excel (tabular-parser) — закрыт 06.10.2026 (tabular-parser #16, docs #27, fixtures #10; follow-up arm-tabular-parser#20)
tabular-parser: ББ/ОФР из Excel по §12 в тот жеstatementDocument; поиск листов с формами по содержимому (в 2a такие листы пропускаются с предупреждениемskipped: statement (slice 2b)); словари синонимовrules/*.yaml; контрольные формулы §7 для форм.- Тесты: property-тесты инвариантов на всех файлах
fixtures/statements-xlsx/**(формулы §7) + синтетика (ББ+ОФР на одном листе, csv-подобный лист); снимки результата — рядом с golden ОСВ. - Реализовано (ветка
feat/14-slice-2b-statement-parser, tabular-parser PR #16; docs — PR #27, веткаfeat/26-slice-2b-statement-parser):BookParser+ конвейер формstatements/, словариstatement_*.yaml, контракт v1.2 (DISCLOSURE,checks, границы периода ОСВ; копии схемы в arm-core PR #27 и scan-gateway PR #5),§12/§7по решениям владельца. Тесты: манифестapi/tests/statements_manifest.yaml(18 реальных файлов), синтетикаst01–st07, goldenexpected_statement_parse/(18 + 7 снимков), интеграционный тест воркера на книге НПЗ. - Объём: парсер + контракт v1.2; маппинг форм в ядре (
statementDocument → document + financial_statement_*) — Срез 3. По фактуdoneтолько у форм Межениновской; остальныеneeds_checkпо данным файлов (рубли с копейками при «тыс. руб.», страницы без шапки, шаблоны) — OQ-138, OQ-140. - Не сделано / риски: единицы не нормализуются (OQ-138); форма без колонки кодов не разбирается (OQ-139); страницы
в разных файлах не склеиваются (OQ-140); строки без кода не хранятся (OQ-141); после контракта v1.2
docs/contracts/**заморожены (копии схемы в arm-core и scan-gateway должны совпадать с ними; в tabular-parser версия закреплена тестомapi/tests/unit/test_contract_v12.py, побайтное сравнение копий — вручную черезdiffпри раскатке); косметика T1.1/T2.x уходит в следующий MINOR.
Срез 2c — Загрузка файлов и маппинг результата в ядре (arm-core) — закрыт 06.10.2026 (arm-core #15, архив #16; docs #17, архив #18)
Change'и: arm-core/openspec/changes/slice-2c-osv-ingest (issue arm-core#14, ветка feat/14-slice-2c-osv-ingest), сквозной
docs/openspec/changes/slice-2c-osv-ingest (ветка feat/16-slice-2c-osv-ingest, DBML v5.15).
Сделано (по факту):
- Модель: DBML v5.15 —
osv_data_type + NU(налоговый учёт, OQ-45),app_user.emailв нижнем регистре (закрывает OQ-59); миграция0003_dbml_v5_15, циклupgrade → downgrade → upgradeи пустой autogenerate. - Загрузка:
POST /legal-entities/{id}/files(xls/xlsx/xlsb/pdf/png/jpg, проверка сигнатуры, лимит 50 МиБ, дедуп поsha256в пределах ЮЛ, частичный успехaccepted/rejected), S3uploads/{file_id}/{job_id}/…,stored_file+recognition_job(outbox) +FILE_UPLOAD. - Статусы файла ведёт код по текущему заданию (
UPLOADED → PROCESSING → PROCESSED | ERROR,SUPERSEDED): ack, результат,error,timeout,dlq; inbox результат не читает (OQ-67, OQ-69). - Цикл маппинга (третий фоновый цикл рядом с публикатором и вахтёром): проверка ключа результата (OQ-70), чтение S3
вне транзакции,
documentна лист ОСВ,osv_entryбезTOTALс деревом,account_root/account_id, резолвcounterparty_idпо ИНН/имени/алиасу,counterparty_check, статусRECOGNIZED/NEEDS_CHECK,is_cumulativeпо данным Q1 (OQ-02), до 3 попыток; ОСВ_60 за 2024 (1034 строки) — 0,3 с. - Автозамена версий (
SUPERSEDED,version_no,FILE_REPLACE; заменяется иCONFIRMED), API файлов/документов/строк,POST /documents/{id}/confirm,DELETE /files/{id}(запрет приCONFIRMEDи при заменивших другие,expires_atу объектов S3). - Проверки на реальных данных: golden — все 82 снимка парсера (85 документов, 13 510 строк, ≈ 4 с) разобраны, инварианты
спеки выполняются; сквозной прогон
make e2eс реальнымtabular-parserчерез compose (ОСВ_66 за 2024 →PROCESSED, 9 строк). Итогmake check-full(контроллер, HEAD f9b8a21): EXIT 0 — unit 900, integration 437, e2e skipped (профильservicesне поднят), docker-build и web-check OK; отдельный прогон e2e с реальнымtabular-parser: 1 passed (4,3 с);-m fixtures: 13 passed + 1 skipped. - Решения без обсуждения —
arm-core/openspec/changes/slice-2c-osv-ingest/design.md, разделы «Decisions made without discussion» (№1–52). Правила —05-domain-rules.md§1.3, §1.5, §3 п. 4, §9.2–9.5; архитектура —03-architecture.md(«Цикл маппинга результата и порядок блокировок»); QA —dev/qa-guide.md§6.6. - Закрыты OQ: 67, 69, 70, 59, 109. Открыты новые: OQ-110 (удаление файла после консолидаций), OQ-111 (ретеншн S3
при удалении), OQ-112 (остаточные объекты e2e), OQ-113 (полнота субсчетов seed), OQ-114 (
is_modifiedвEntryOut), OQ-115 (частичная замена файла), OQ-116 (нарастающая по Q1 →NEEDS_CHECK). - Остаётся (Срез 2d и далее): UI «Первичные документы»; маппинг ББ/ОФР (
statementDocument) — общий для Excel и OCR (Срез 3 его переиспользует); ручное сопоставление контрагента и пересчёт резолва при построении свода (Срезы 4–5); OQ-100 (ИНН из текста имени контрагента) по-прежнему не решён — резолв идёт по ИНН колонки, имени и алиасу. - Копия схемы контракта v1.1 в
arm-core(OsvRow.extra) — если не сделана bounded-PR раньше.
Срез 2d — UI «Первичные документы»
- Панель «Первичные документы», окно загрузки, таблица ОСВ с деревом строк и подсветкой нераспознанных контрагентов.
DoD среза 2 целиком: все реальные файлы и вся синтетика проходят без единого правила под конкретный файл или координату; в коде парсера нет литералов букв колонок/номеров строк/имён листов (проверяется тестом-линтером).
Срез 3 — ББ/ОФР: scan-gateway, маппинг форм, логические проверки, подтверждение документа
Срез 3 делится на два подсреза с отдельными change'ами.
Срез 3a — scan-gateway: горячие папки и нормализатор OCR (репозиторий scan-gateway)
Статус: закрыт 07.10.2026 (scan-gateway #8, архив #10; docs #47; fixtures #13; follow-up — issue arm-scan-gateway#9). Change slice-3a-ocr-normalizer (arm-scan-gateway#6;
docs#46, fixtures#12), спецификация — scan-gateway/openspec/changes/slice-3a-ocr-normalizer/ (design D-1…D-9, «Decisions made
without discussion» №1–№35). Реализация — по 05-domain-rules.md §11 и §11.1.
- Горячие папки в раскладке FileWorker (OQ-137):
Input/<job_id>.<ext>,.partвTmpи запись без замены,Output/<job_id>/*.jsonнабором (по стабилизации), очистка — под флагомSCAN_CLEANUP(по умолчанию выключена, OQ-144); таймаут 5 мин. - Эмулятор ИС Сканирование для dev: пара PDF + JSON по sha256 содержимого (
fixtures/ocr), набор по умолчаниюSCAN_EMULATOR_DEFAULT; сырой ответ → S3raw/. - Нормализатор
OcrNormalizer: перенос проверенного на стенде модуляofr_result_conversionстарого ядра (единственное разрешённое исключение дляreference-old-arm, решение владельца 06.10.2026) вstatementDocumentv1.2 — по документу на таблицу; справочникиapi/rules/с редакциями форм66n/fsbu4(fsbu4заполняет владелец, OQ-150);checksне передаются. - Эталоны нормализатора —
fixtures/ocr/expected_normalize/(отдельный PR fixtures),make golden-update. - Новые вопросы: OQ-144…OQ-152.
Срез 3b — маппинг форм, проверки, подтверждение и API до сводной ОСВ (arm-core)
Статус: бэкенд и API реализованы в arm-core, октябрь 2026; UI экрана «Проверка распознавания» в срез не входит. Объём по
решению владельца 07.10.2026: весь API пути пользователя до сводной ОСВ включительно. Issue arm-core#36, docs#48; спецификация —
arm-core/openspec/changes/slice-3b-statements-api/ (design D-1…D-14, «Decisions made without discussion» №1–№19); документы
workspace — bounded-PR в docs (без сквозного change: DBML и контракт не менялись).
Сделано (по факту):
- Маппинг форм в ядре:
statementDocumentBALANCE/INCOME(Excel и OCR) →document+financial_statement_meta/column/line/valueв той же транзакцииmap_file; период по дате отчёта либо по самой поздней дате колонок;DISCLOSURE/OTHER— документ без данных; файл только с формами — не ошибка (05-domain-rules.md§9.5 п. 2,03-architecture.md). - Проверки §7 в ядре (
domain/statement_checks.py, словарьapi/rules/statement_checks.yaml— копия словаря tabular-parser), межформенная проверка 1370/2400 — мягкая; акцепт жёстких нарушений с комментарием; статус документа формы (§9.3). - API формы:
GET/PATCH /documents/{id}/statement,POST …/statement/checks/accept; правка значений и ИНН/даты отчёта/единиц только до подтверждения; подтверждение ББ/ОФР с условиямиPERIOD_REQUIREDиCHECKS_NOT_PASSED;RECOGNIZED_DATA_EDITс before/after. - Мелкие дыры пути пользователя:
GET /files/{id}/content(исходный файл потоком), комментарии к документу иcomments_count,GET /users/brief,documents_countу ЮЛ, CSV чек-листа (…/checklist?format=csv). - Контракт API —
dev/api-contract-slice-3b.md; QA —dev/qa-guide.md§6.9. - Не вошло: UI; правка строк ОСВ, добавление/удаление строк формы и правка кода/названия строки; отмена подтверждения (исправление — новым файлом); формулы §7 и справочники по редакциям (OQ-146); аудит скачивания (OQ-153).
- Закрыты допущения: OQ-23, 36, 77, 140, 145 («Срез 3b: допущение реализовано»). Открыт новый: OQ-153. Открытые вопросы 3b: OQ-146 (словари по редакциям), OQ-149, OQ-152.
Исходный план среза (для справки):
- Маппинг:
financial_statement_meta/column/line/valueизstatementDocument(общий для Excel и OCR); числа, скобки, confidence; ИНН/имя сверка. - Логические проверки §7 (чистые функции
domain/checks.py), акцепт КА, «Подтвердить данные» →CONFIRMED,RECOGNIZED_DATA_EDITс before/after. - Чек-лист
required_document_rule × периметр − document CONFIRMED(API + модалка + CSV). - UI: экран «Проверка распознавания» (исходник слева — PDF.js, результат справа, блок «Логические ошибки»).
- Тесты: пары
aep_N.pdf/json; машиночитаемые PDF АО РБ 2024 как dev-путь без OCR (опционально pdfplumber).
Срез 4 — Консолидация: карточка, версии, периметр, периоды, сводная ОСВ
Статус: реализован в arm-core (бэкенд + API + экспорт xlsx), октябрь 2026; UI — отдельный исполнитель. Объём по решению
владельца 06.10.2026: бэкенд, API, экспорт xlsx. Issue arm-core#18, docs#19; спецификация —
arm-core/openspec/changes/slice-4-consolidation/ (design D-1…D-16, «Decisions made without discussion» №1–№85),
документный change — docs/openspec/changes/slice-4-consolidation/.
Сделано (по факту):
- DBML v5.16:
osv_entry.counterparty_match_kind+ enumcounterparty_match_kind(миграция0004_dbml_v5_16, backfill). - Версии консолидации (создание, список по ГК, карточка), периметр (
PUT …/members), блокировка «взять в работу» (перехват с причиной, без истечения), статусы: автоматические по событиям документов (INITIATED → DOCUMENTS_PROCESSING → DATA_CORRECTION) и ручные (CANCELLED, возврат вINITIATED); остальные — Срез 7. - Явная привязка подтверждённых документов к версии (
consolidation_document): подтверждение, подхват при создании версии и добавлении ЮЛ, отвязка при автозамене файла и удалении ЮЛ; Q1-эквивалентность ОСВ (R-14, OQ-124). - Чек-лист комплекта документов (перенесён из Среза 3:
required_document_rule × периметр, статусы ячеек) — API; CSV не делали. - Сводная ОСВ как чистая функция от версии: выбор источников и склейка кварталов (§2), пробелы, дорезолв контрагента, признак
GSK/GK/EXTERNAL, способ сопоставления; страница, сводка, фильтры. - Кандидаты и ручное сопоставление контрагента с алиасом, переносом алиаса и автоприменением (
PROPAGATED). - Экспорт xlsx (лист «Сводная ОСВ» и лист «Пробелы»).
- Сквозной тест на фикстурах РБ: ОСВ 60/62 РБ и 60/62/76 Счастливочной за Q1–Q3 2024 → версия Q3 → свод 1385 строк, 22
документа привязано; пары с одним лишь Q3 (РБ: 01, 58.03, 66, 67, 76; Счастливочная: 01, 02) — в
gapsс пропуском Q1–Q2; одно ручное сопоставление «Пекарня Счастливочная ООО» → ГСК. - Контракт API для фронта —
dev/api-contract-slice-4.md; QA —dev/qa-guide.md§7.
Закрыты OQ: 03, 19, 40 (допущение реализовано), 110 (для Среза 4). Открыты новые: OQ-118…OQ-129 (запрет загрузки после
DATA_CORRECTION, истечение блокировки, period_check, порог кэша свода, PROCESSING в чек-листе, общие строки osv_entry
у версий, Q1-эквивалентность, склейка Q1 версии Q1, область ручного сопоставления, рекомендация кандидата, неоднозначность
дорезолва, формулировка сценария «1 + propagated»).
Остаётся (UI и последующие срезы): экраны 34–37, 42, 30, 32-*, 31-00; CSV чек-листа (сделан в Срезе 3b);
«Добавить версию», CONFIRM, EXTENDED, гудвилл, маршрут согласования (Срезы 6–7); формы ББ/ОФР в чек-листе по
реальным документам — Срез 3b (реализован); шахматка и ВГО — Срез 5.
Исходный план среза (для справки): consolidation / consolidation_version / consolidation_member /
consolidation_document; приведение квартальных ОСВ (§2); сводная ОСВ (§3) как запрос; признак контрагента; ручное
сопоставление с алиасами и автоприменением; UI со списком, карточкой, составом, сводной ОСВ с фильтрами и экспортом;
тест: строки «Юг-Финанс / ПЕКАРНЯ СЧАСТЛИВОЧНАЯ» → ГСК после одного ручного сопоставления.
Срез 5 — ВГО: автоматическое сопоставление, шахматка, корректировки
elimination_ruleкак данные + версия вconsolidation_version; матчинг §5 (чистые функции на pydantic-моделях); шахматка §6;correctionс дочерними строками, контроль 5 %, статусы DRAFT/APPLIED/REVOKED;ADJUSTMENT.- UI: шахматка (ячейки с комментариями), таблица пар (авто/ручные/несопоставленные), таблица корректировок с импортом/экспортом xlsx.
- Тест: пара 60.01 АО РБ ↔ 62.01 Счастливочная на 30.09.2024 = 106 311 116,46 (точный матч по правилу № 6); заём
42 млн 66.03 ↔ 58.03; сверка «в т. ч. взаимные обязательства» с
Консолидация_Группа РБ.xlsxлист01.10.2024.
Срез 6 — КФО: результат, гудвилл, пороги, сравнение с клиентом
kfo_result(_line, _line_company): сумма → авто-элиминация → корректировки → гудвилл → итог; единицы (OQ-26); пороги §8;goodwill;client_kfo_lineдляCONFIRM.- UI: КФО (колонки как в эталонном Excel), сводка расхождений, гудвилл, подтверждение КФО клиента, экспорт xlsx.
- Тест: КФО группы РБ на 01.10.2024 vs эталонный лист (допуск на ручные правки аналитика — зафиксировать расхождения и показать аналитику).
Срез 7 — Маршрут согласования, ЕХ, журнал, выгрузки
- Полная машина статусов §9.1 с
consolidation_status_history, policy по ролям/филиалам; № и дата УОБ; новая версия. VERIFIED→ex_snapshot/_member/_item(payload по схемеdocs/contracts/ex-payload-v1.schema.json); read-only.- ЛК ЕХ: дерево ГК → ГСК → организации, просмотр payload, скачивание первички, выгрузка xlsx на лету.
- Журнал действий: экран с фильтрами по разделам/объектам/полям.
- Экспорт: настраиваемые колонки,
audit_event(EXPORT), S3exports/7 дней.
Срез 8 — Нефункциональные: ретеншн, архивирование, производительность, безопасность
- Lifecycle S3 и удаление по ТЗ 8.4 (5 лет), архив в data lake (ссылка), объёмы
osv_entry(индексы, partitioning по году при необходимости), нагрузочный тест парсера (1000-строчные ОСВ × 20 компаний), OWASP-проверка, аудит доступа.
Поперечные правила
- Любой срез, затрагивающий модель, начинается с diff к DBML (новая версия v5.14+ с записью в changelog) и миграции.
- Вычисляемые объекты — только
domain/+repositories/запросы; никаких таблиц «для ускорения» без DECISION. - Каждый алгоритм из
05-domain-rules.md— отдельный модуль с docstring-ссылкой на § и тестами на фикстурах. - Открытые вопросы — только через
07-open-questions.mdсASSUMPTION(OQ-nn)в коде.