From 58075e94458ddb6e736efe90fef015ec29412762 Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Sun, 4 Oct 2026 23:32:21 +0400 Subject: [PATCH] =?UTF-8?q?chore(openspec):=20=D1=80=D1=83=D0=BB=D0=B8?= =?UTF-8?q?=D0=BD=D0=B3=20R-17=20(=D1=80=D0=B5=D1=88=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20Task=2010)=20=D0=B2=20design.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2 --- openspec/changes/slice-1-directories/design.md | 1 + 1 file changed, 1 insertion(+) diff --git a/openspec/changes/slice-1-directories/design.md b/openspec/changes/slice-1-directories/design.md index c02a8ab..945afeb 100644 --- a/openspec/changes/slice-1-directories/design.md +++ b/openspec/changes/slice-1-directories/design.md @@ -158,3 +158,4 @@ WHERE is_current`; `ALTER TYPE audit_action ADD VALUE` ×2 (`LEGAL_ENTITY_CHANGE | 25 | 2026-10-04 | R-14 (SDD фаза 2, pre-flight): Task 10 выносит логику update ГК и ЮЛ в модульные функции `apply_group_update` / `apply_entity_update` (`services/company_groups.py`, `services/legal_entities.py`), `*Service.update` вызывает их; план называл их существующими, но в коде фазы 1 были только методы | импорт обязан писать историю/аудит так же, как ручная правка; дублирование — расхождение поведения | вернуть дублирование; регрессию фазы 1 ловят её тесты | | 26 | 2026-10-04 | R-15 (SDD фаза 2, Task 9, находка исполнителя): на фикстуре «Русский Бисквит» ожидается 20 ЮЛ/ИП (18 ЮЛ + 2 ИП), `DUPLICATE_IN_FILE` в этом файле не возникает (ФЛ с тем же ИНН идёт после ИП и отсекается типом); на полной выгрузке `groups_created = 344` (ГК `1-5AL0CDM` целиком из дублей), `LE_IN_OTHER_GROUP` на пустой БД недостижим и в ожиданиях не проверяется; текст спеки `directory-import`, tasks.md, design.md и план приведены к факту | данные важнее ориентировочных цифр спеки; ожидания фиксируются тестами по реальным файлам | поправить числа в тестах и спеке | | 27 | 2026-10-04 | R-16 (SDD фаза 2, Task 9, приняты решения исполнителя): `errors` считает итоговые коды-пропуски; `GK_EXISTS` и для неизменной ГК (идемпотентность); РФ разрешается один раз на ГК после проверок пустого iD ГК и конфликта имени (нет «осиротевших» филиалов, `RF_CREATED = 53`); ИНН считается «встречавшимся» после проверок типа и формата; офис нового ЮЛ = действующий РФ ГК; ГСК/ГСЗ создаётся по флагу даже если у ЮЛ уже есть членство того же вида в другой группе (буквально §13.2, возможна пустая группа — T9.5); флаги обрабатываются и при `skip` (добавляется отсутствующее членство); значение колонки ГСК «входит в ГСЗ» → `UNKNOWN_FLAG`; xlsx читается с `reset_dimensions()`; пины `openpyxl==3.1.5`, `et_xmlfile==2.0.0`, `types-openpyxl` (dev) | единообразие со спекой и идемпотентность повторного импорта | каждое — локальная правка `plan_import` и теста | +| 28 | 2026-10-04 | R-17 (SDD фаза 2, Task 10, приняты решения исполнителя): общие `apply_group_update`/`apply_entity_update(session, audit, obj, changes: dict, *, now, description=None)` принимают словарь изменений (PATCH и импорт делят одну реализацию), `snapshot_entity`/`touch_entity` — функции модуля; обновления ГК/ЮЛ импортом пишут собственные события `GROUP_CHANGE`/`ASSIGNMENT_CHANGE`/`LEGAL_ENTITY_CHANGE` с `description="импорт ЕЦП"` помимо одного `DIRECTORY_IMPORT` (создания — только сводным событием); тест `dry_run` — на отдельной БД с зафиксированным seed, т.к. `session.rollback()` под SAVEPOINT-фикстурой `app` сносит seed теста; `IMPORT_MAX_BYTES` также в `.env.test`; имя файла сводится к basename (путь отбрасывается, пустое/`.`/`..` → `import`) для формата, `description` и ключа S3; `s3_object.sha256` заполняется, `content_type` — по расширению; сначала строка `s3_object` + flush, затем `put_object` (ошибка S3 откатывает импорт); разбор файла в `asyncio.to_thread`; `created_date` ГСК/ГСЗ не заполняется; 413 проверяется в эндпоинте (до чтения) и в сервисе (`HTTPException` из сервиса, как в брифе); архивные ГК входят в снимок и при `update` не разархивируются; сообщение `LE_IN_OTHER_GROUP` называет ЮЛ из другой ГК независимо от филиала пользователя (импорт — только `DIRECTORY_ADMIN`, права — данные) | единообразие истории/аудита ручной правки и импорта; честная проверка rollback; безопасность ключа S3 | пересмотр — правка сервиса/теста; ограничить раскрытие имён при выдаче `DIRECTORY_ADMIN` филиальному пользователю — убрать имя из сообщения |