feat: «Основной РФ» объектом в ответах ЮЛ и ГК (#47) #51

Merged
aep merged 1 commits from feat/47-regional-office-object into main 2026-10-07 18:01:47 +03:00
Owner

Closes #47

Что сделано

В ответах ЮЛ и ГК филиал приходит объектом RegionalOfficeBrief {id, name, is_head_office} рядом с прежним *_id (аддитивно, фронт не ломается). Входные схемы не менялись.

Схема Новое поле
LegalEntityOut, LegalEntityDetail (список, карточка, create, PATCH, move, withdraw) regional_office
LegalEntityHistoryOut regional_office (филиал снимка)
CompanyGroupOut (список, карточка, create, PATCH, archive/unarchive) base_regional_office
CompanyGroupHistoryOut base_regional_office (филиал снимка)

Пример (GET /directories/legal-entities/{id}):

{ "id": "…", "name": "ООО Ромашка", "regional_office_id": "9f1c…",
  "regional_office": { "id": "9f1c…", "name": "Ростовский региональный филиал", "is_head_office": false }, "…": "…" }

Без филиала: "regional_office_id": null, "regional_office": null. Для ГК — base_regional_office_id / base_regional_office.
Неактивный филиал (is_active=false) отдаётся объектом как обычно.

Rulings I made

  • R-1: загрузка без N+1 — не ORM-relationship, а один батч-запрос regional_offices_by_ids на набор id (списки, карточки, history). Единый путь для живых таблиц и history (в *_history FK на филиал нет), модели не менялись, DBML не затронут.
  • R-2: новые поля в схемах необязательные (= None), чтобы прочие места, строящие эти схемы из ORM, не ломались.
  • R-3: GET /legal-entities и /company-groups — число запросов не зависит от числа строк (+1 SELECT regional_office на страницу); в history — ровно один SELECT по филиалам.
  • R-4: отдельного снапшота OpenAPI в репозитории нет (только test_openapi_routes.py по составу маршрутов) — схема обновляется автоматически из pydantic; README дополнен абзацем про объект филиала.
  • R-5: два существующих теста, сверявших точный набор ключей history, обновлены под новое поле.
  • Строка контракта для фронта в arm-ka-docs (п. 5 issue) не делалась — отдельный репозиторий; вынесено человеку.

Проверка

make check-full зелёный: lint (ruff, mypy), unit 1199 passed, dbml-check, integration 802 passed, e2e skipped (нет профиля services), web-check/docker-build — успешно.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EAKRDNzXtRrwmWz9z6PZu3

Closes #47 ## Что сделано В ответах ЮЛ и ГК филиал приходит объектом `RegionalOfficeBrief {id, name, is_head_office}` рядом с прежним `*_id` (аддитивно, фронт не ломается). Входные схемы не менялись. | Схема | Новое поле | |---|---| | `LegalEntityOut`, `LegalEntityDetail` (список, карточка, create, PATCH, move, withdraw) | `regional_office` | | `LegalEntityHistoryOut` | `regional_office` (филиал снимка) | | `CompanyGroupOut` (список, карточка, create, PATCH, archive/unarchive) | `base_regional_office` | | `CompanyGroupHistoryOut` | `base_regional_office` (филиал снимка) | Пример (`GET /directories/legal-entities/{id}`): ```json { "id": "…", "name": "ООО Ромашка", "regional_office_id": "9f1c…", "regional_office": { "id": "9f1c…", "name": "Ростовский региональный филиал", "is_head_office": false }, "…": "…" } ``` Без филиала: `"regional_office_id": null, "regional_office": null`. Для ГК — `base_regional_office_id` / `base_regional_office`. Неактивный филиал (`is_active=false`) отдаётся объектом как обычно. ## Rulings I made - R-1: загрузка без N+1 — не ORM-relationship, а один батч-запрос `regional_offices_by_ids` на набор id (списки, карточки, history). Единый путь для живых таблиц и history (в `*_history` FK на филиал нет), модели не менялись, DBML не затронут. - R-2: новые поля в схемах необязательные (`= None`), чтобы прочие места, строящие эти схемы из ORM, не ломались. - R-3: `GET /legal-entities` и `/company-groups` — число запросов не зависит от числа строк (+1 SELECT regional_office на страницу); в history — ровно один SELECT по филиалам. - R-4: отдельного снапшота OpenAPI в репозитории нет (только `test_openapi_routes.py` по составу маршрутов) — схема обновляется автоматически из pydantic; README дополнен абзацем про объект филиала. - R-5: два существующих теста, сверявших точный набор ключей history, обновлены под новое поле. - Строка контракта для фронта в arm-ka-docs (п. 5 issue) не делалась — отдельный репозиторий; вынесено человеку. ## Проверка `make check-full` зелёный: lint (ruff, mypy), unit 1199 passed, dbml-check, integration 802 passed, e2e skipped (нет профиля services), web-check/docker-build — успешно. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01EAKRDNzXtRrwmWz9z6PZu3
aep added 1 commit 2026-10-07 17:47:06 +03:00
В 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
aep merged commit f4a780648d into main 2026-10-07 18:01:47 +03:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RSHB/arm-core#51
No description provided.