76 Commits

Author SHA1 Message Date
Andrey Epifancev
b4522addc0 feat: DBML v5.23 — версия правил обязательна; список пар ВГО версии (ревью #175, AURORA-1536)
- 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>
2026-10-23 18:42:10 +04:00
Andrey Epifancev
888ad4b401 Merge origin/main в AURORA-1536 (ревью #175)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 18:34:35 +04:00
Andrey Epifancev
e13cd88fea Merge origin/main в feat/renew-processing-timeout (ревью #161, раунд 2)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 17:59:00 +04:00
622a60e4e0 AURORA-1442: Правки по раунду 1 2026-10-23 13:39:30 +03:00
PotapovaA
232fecec39 автоматическое проставление версии правил при создании консолидация, если таких создается версия консолидации создается с NULL 2026-10-23 12:10:35 +03:00
PotapovaA
fabc9b48b2 docs(matrix): указать разделы ТЗ в новых функциях 2026-10-21 19:10:45 +03:00
PotapovaA
3eb5362e58 fix(matrix): выбирать последнюю открытую версию правил 2026-10-21 18:51:06 +03:00
PotapovaA
e9dc67b2e9 refactor(matrix): вынести применение корректировок из ветки пресетов 2026-10-21 18:40:05 +03:00
Andrey Epifancev
367a11ed38 chore(api): format, mypy и тест версии правил; убрать мёртвое as_of (ревью #141)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 14:04:38 +04:00
Andrey Epifancev
a8e510e402 Merge origin/main в add-preset-shahmatka (ревью #141) 2026-10-21 14:03:12 +04:00
PotapovaA
abe1d890d0 правки по ревью 2026-10-21 11:59:23 +03:00
Andrey Epifancev
01e1f81516 fix(statements): вставка document_issue пакетами по BATCH (#142, AURORA-1711)
add_issues вставлял все записи документа одним INSERT: 16 параметров на
запись, лимит asyncpg 32 767 — потолок около 2 047 замечаний. Лист ОСВ
«11.xlsx» (сч. 11, 2 128 строк «Кол. доп.» на парсере контура 40287e1)
давал 2 131 предупреждение, маппинг падал с InterfaceError, файл ERROR.
Теперь пакеты по BATCH (1000), как у строк и значений форм.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:59:25 +04:00
PotapovaA
487a8521da Merge branch 'main' into add-preset-shahmatka 2026-10-20 14:58:34 +03:00
PotapovaA
53c2d5c73d пресеты для шахматки 2026-10-20 14:45:27 +03:00
Andrey Epifancev
21e0720fb0 feat(mapping): маппер результата 2.0 для форм — хранение как пришло, document_issue, условие RECOGNIZED
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 21:42:04 +04:00
Andrey Epifancev
065153e470 feat(statements): пересчёт после правки точкой входа arm_statements, §7 только из document_issue
recompute_form (services/statement_recompute.py) собирает вход из БД, зовёт engine.recompute и пишет needs_review
строк и значений, form_variant, parent_row_index расшифровок, записи relation/soft и core по P3-8, статус через
form_status_v2. GET/confirm/accept читают нарушения §7 из document_issue. Правка header.report_date пересчитывает
relative:* колонки. Временный код A12/A13 удалён.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 20:26:40 +04:00
Andrey Epifancev
1ab7f2238d chore(statements): комментарии, README, типы, тесты по итогам финального ревью (M-1, M-2, M-3, M-5, M-7, M-9, T2.1, T4.5, T10.1, T11.1)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
2026-10-18 19:04:40 +04:00
Andrey Epifancev
8296c77fe5 fix(api): OpenAPI-коды ошибок PATCH формы, confirm и crm_id; organization_name:null — 422 (I-2, M-11)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
2026-10-18 19:04:40 +04:00
Andrey Epifancev
3753e32219 feat(statements): PATCH lines — назначение кода, расшифровка, подтверждение кода, LINE_CODE_TAKEN
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
2026-10-18 19:04:40 +04:00
Andrey Epifancev
f1fcb861a6 feat(statements): PATCH — подтверждение ячейки, дата колонки, наименование организации, подтверждение даты
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
2026-10-18 19:04:40 +04:00
Andrey Epifancev
361e7094e3 feat(documents): порядок 409 подтверждения формы — LINES_UNRESOLVED, DUPLICATE_FORM
form_confirmable заменён на form_blocker: PERIOD_REQUIRED -> LINES_UNRESOLVED -> DUPLICATE_FORM -> CHECKS_NOT_PASSED.
Ручное и автоподтверждение используют одну функцию.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
2026-10-18 19:04:40 +04:00
Andrey Epifancev
f3a86479aa feat(mapping): маппер 1.x пишет поля v5.19, file_ordinal, хранит вторую форму, MAPPING_WARNING в document_issue
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
2026-10-18 19:04:40 +04:00
Andrey Epifancev
65a833fd98 feat(api): StatementOut и DocumentOut по v5.19 — статусы строк, needs_review, issues, порядок строк
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
2026-10-18 19:04:40 +04:00
Andrey Epifancev
a15111ab60 feat(statements): агрегат формы по коду — проверки, межформенная, parent_code, достройка, правка по коду
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
2026-10-18 19:04:40 +04:00
Andrey Epifancev
782580beb4 feat(scripts): purge_statements — очистка форм ББ/ОФР перед выкладкой v5.19 (Р-24, Р-27)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
2026-10-18 19:04:40 +04:00
Andrey Epifancev
b7f45c6a47 feat(directories): crm_id ГСК/ГСЗ сохраняется, 409 CRM_ID_EXISTS (arm-core#112)
crm_id пишется в колонку related_group.crm_id (v5.19), попадает в ответы и в
payload аудита; занятый значением другой ГСК/ГСЗ даёт 409 CRM_ID_EXISTS
(pre-check и uq_related_group_crm_id на гонку). Смена crm_id пишется как
GROUP_CHANGE с before/after всех изменённых полей (Р-41, P3-18).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
2026-10-18 19:04:40 +04:00
Andrey Epifancev
2db0a66a86 feat(models): DBML v5.19 — колонки форм, document_issue, file_ordinal, crm_id ГСК (миграция 0007)
Модели и 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
2026-10-18 19:04:40 +04:00
PotapovaA
4390ce8f27 Merge branch 'main' into add-report-shahmatka 2026-10-15 13:18:22 +03:00
PotapovaA
db19b3a176 корректировка расчета шахматки, добавление эндпоинтов для получения статей, добавления эндпоинта для выгрузки xlsx 2026-10-15 13:17:54 +03:00
Andrey Epifancev
4973e47290 feat(directories): текущие членства ГСК/ГСЗ в списке ЮЛ (#109)
`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>
2026-10-13 18:06:02 +04:00
Andrey Epifancev
1ae6b8d2da feat(consolidation): временный режим «период ОСВ из версии консолидации» (#103)
Настройка CONSOLIDATION_PERIOD_FROM_VERSION (по умолчанию false; в контуре —
OPENBAO__APP__CONSOLIDATION_PERIOD_FROM_VERSION): ОСВ, загруженная в консолидацию
(stored_file.consolidation_id), считается нарастающей за год и квартал консолидации,
какой бы период ни стоял в шапке. Нужен для тестов на произвольных ОСВ: без него ОСВ
за 1 кв. 2025 в консолидации 2026 Q1 молча не привязывается и свод пуст.

- domain/version_period.py: представление документа с периодом версии (первичка не меняется)
- consolidation_documents.for_consolidation: единая точка подмены; её используют привязка
  (fits, ключ R-1, bind_confirmed, хуки подтверждения и маппинга), свод, чек-лист,
  колонка «ОСВ» периметра (osv_accounts)
- ББ/ОФР и файлы с рабочего стола режим не затрагивает; склейки кварталов в режиме нет
- тесты: unit на чистые функции, интеграционные — сценарий 2025 Q1 → 2026 Q1 с режимом
  и без, файл вне консолидации, чек-лист и карточка, подхват «один слот на счёт»

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:17:01 +04:00
PotapovaA
d44a4ff007 Merge branch 'main' into add-report-shahmatka 2026-10-12 14:26:43 +03:00
Andrey Epifancev
4abfa03539 fix-волна ревью: delta статусов, блокировка версий консолидации, тесты (#96)
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>
2026-10-10 02:23:09 +04:00
Andrey Epifancev
1e888d4670 api: загрузка файлов в консолидацию, переход версий «в работе»; query версии у загрузки ЮЛ удалён (#96)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-10 01:31:35 +04:00
Andrey Epifancev
956a730a3c api: рабочий стол консолидации для ЮЛ и consolidation_id в карточке файла (#96)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-10 01:10:21 +04:00
PotapovaA
bb6795c052 добавление ручки для получения правил шахматки 2026-10-09 16:16:24 +03:00
Andrey Epifancev
2d21a416d6 feat(statements): созданные пустые строки вне проверок §7 (#80)
statement_amounts не отдаёт проверкам строки с line_code_original_value IS NULL,
у которых все суммы пустые; заполненная хотя бы в одной колонке строка
проверяется по всем колонкам.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-09 12:06:34 +04:00
Andrey Epifancev
37e7f40890 feat(statements): PATCH создаёт строку и ячейку по line_code (#80)
CellPatch адресует ячейку ровно одним из line_id / line_code. Строка справочника
редакции, которой нет в форме, создаётся при первой непустой правке
(line_code_original_value = NULL — признак «не из источника»); отсутствующая
ячейка существующей строки тоже создаётся. Адресация (колонка, строка, код)
проверяется целиком до первой вставки, две ячейки новой строки делят одну
строку, повтор line_code после создания даёт 422 UNKNOWN_CELL. Аудит — одно
RECOGNIZED_DATA_EDIT на запрос, у созданной ячейки before = null.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-09 12:03:59 +04:00
Andrey Epifancev
64be2f2b5c feat: имя ГК (company_group_name) в ответах ЮЛ (#67)
В 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
2026-10-08 17:01:25 +04:00
Andrey Epifancev
7dcffbd10d Резолв контрагента: алиас приоритетнее ЮЛ-тёзки по нормализованному имени (#57)
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
2026-10-08 00:21:15 +04:00
Andrey Epifancev
a76fc3ed99 Merge main в feat/45-kpp (после #51 и docs#54)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EAKRDNzXtRrwmWz9z6PZu3
2026-10-07 19:10:20 +04:00
Andrey Epifancev
4cc926c033 КПП юридического лица: legal_entity.kpp, миграция 0005, API, импорт (DBML v5.17, #45)
- модели 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
2026-10-07 18:51:50 +04:00
Andrey Epifancev
9cceb84827 feat: «Основной РФ» объектом в ответах ЮЛ и ГК (#47)
В LegalEntityOut/Detail/HistoryOut добавлено regional_office, в CompanyGroupOut/HistoryOut — base_regional_office
(RegionalOfficeBrief {id, name, is_head_office} или null); *_id оставлены. Филиалы подгружаются одним батч-запросом
на набор id (списки, карточки, history без FK); неактивный филиал отдаётся. Тесты: совпадение с *_id, null,
число запросов списка не растёт, history — один запрос на филиалы.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EAKRDNzXtRrwmWz9z6PZu3
2026-10-07 18:46:59 +04:00
Andrey Epifancev
d782637bc1 feat(consolidations): тип ЮЛ и счета ОСВ к периоду версии у участника периметра (#42)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 17:51:45 +04:00
Andrey Epifancev
ffc01836b7 fix(statements): единое определение has_lines, inn=null — 422, заголовки отдачи первички, тест подтверждения при нарушении 1370/2400 (M-2, M-5, M-7, M-8)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 14:31:14 +04:00
Andrey Epifancev
e851445866 fix(statements): цель проверки присутствует в колонке только при наличии суммы; docstring порядка строк (M-1, M-3)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 14:28:49 +04:00
Andrey Epifancev
dd7f7cc42d fix(files): удаление файла убирает формы ББ/ОФР и комментарии документов (C-1, T8.2)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 14:26:34 +04:00
Andrey Epifancev
6078532982 feat(directories): documents_count в списке и карточке ЮЛ (D-13)
Добавлено поле documents_count в LegalEntityOut, содержащее число документов
файлов ЮЛ со статусом не SUPERSEDED. Функция documents_count_by_entity в
репозитории получает счётчики одним подзапросом для эффективности. Используется
в списке и карточке через сервис. Тест проверяет, что заменённые файлы не
учитываются в подсчёте.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 13:16:47 +04:00
Andrey Epifancev
58f039a91d feat(users): GET /users/brief — имена пользователей для всех аутентифицированных (D-12)
Добавлен эндпоинт GET /api/v1/users/brief для получения краткого справочника
пользователей (id, ФИО, статус активности) по списку id. Доступен любому
аутентифицированному пользователю без отдельного права. Максимум 200 id,
иначе 422 TOO_MANY_IDS; некорректный UUID — 422 INVALID_IDS.

- Создан api/src/api/endpoints/users.py с маршрутом /brief
- Добавлен метод users_brief в repositories/users.py
- Добавлена схема UserBriefOut в schemas/admin.py
- Подключён маршрут users в build_api_router ДО admin.router
- Обновлены тесты OpenAPI: добавлены маршрут и префикс /users/brief
- Написаны интеграционные тесты в test_api_users_brief.py

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 13:08:29 +04:00
Andrey Epifancev
c9bd620a18 feat(documents): комментарии к документу и comments_count в карточке (D-11)
POST/GET /documents/{id}/comments, счётчик комментариев в карточке файла
и документа одним запросом на пачку документов.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 12:46:43 +04:00