Домен, стек, слои, команды, тесты, базовая ветка test. .claude/code-paths: api/src/, api/alembic/, web/src/. Refs #198 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
43 lines
5.4 KiB
Markdown
43 lines
5.4 KiB
Markdown
# Архитектура
|
||
|
||
Монорепозиторий: `api/` (FastAPI) отдаёт REST, WebSocket и собранный фронт; `web/` — SPA на React. Основная бизнес-логика — PL/pgSQL-функции схемы `v3` в Postgres. Python-слой проверяет роли, валидирует запрос, вызывает функцию и маппит её ошибки.
|
||
|
||
Поток редактирования ячейки: `RealtimeTable` → WebSocket `/api/v1/ws/form/{id}/sheet/{sheet}` (`cell_edit_start` — блокировка, `cell_updated`) → `SheetService` → `v3.upd_form_cell(s)`. Функция проверяет роль и окно этапа и пишет аудит `v3.log_event`, после чего изменение рассылается остальным подключённым.
|
||
|
||
## Модули
|
||
|
||
| Модуль | Ответственность | Зависит от |
|
||
|---|---|---|
|
||
| `api/src/api/v1/` | Роутеры: auth, users, admin, audit, forms, projects, form_phases (`/stages`), phase_template, export, websocket, org_unit, vsp (`/dict/info`), expense_item, summary (`/svod`) | services, deps |
|
||
| `api/src/api/v1/deps.py` | Текущий пользователь из JWT, гарды ролей | repository.user_repository, core.security |
|
||
| `api/src/api/v1/websocket.py` | ConnectionManager, блокировки ячеек в памяти, события форм и FORM_4/проектов, синхронизация сателлитов AHR | services |
|
||
| `api/src/services/` | Сервисы по сущностям, контроль доступа (`access_control_service.py`) | repository |
|
||
| `api/src/services/export_service/` | Фоновые выгрузки в Excel: ProcessPool, таблица `export_job`, файлы в `tmp/exports`, маппинг колонок `export_mappings.py` | repository, openpyxl/XlsxWriter |
|
||
| `api/src/repository/` | SQLAlchemy-запросы и вызовы SQL-функций `v3.*`, `SET LOCAL app.user_id` | db |
|
||
| `api/src/db/` | engine, `Base`, сессия, ORM-модели (36) | core.config |
|
||
| `api/src/domain/` | pydantic-схемы API, enums | — |
|
||
| `api/src/core/` | Настройки, JWT/argon2, исключения и маппинг ошибок Postgres в HTTP | — |
|
||
| `api/alembic/` | Миграции (около 49 ревизий); `versions/sql/*.sql` — DDL, функции, сиды, около 43 тыс. строк | Postgres |
|
||
| `web/src/app/` | Роуты, AuthProvider (токены в localStorage) | pages |
|
||
| `web/src/pages/` | Задачи (формы), карточка формы или проекта, проекты и их своды, свод 1 и 2, админка, справочники | components, api |
|
||
| `web/src/components/RealtimeTable/` | Редактируемая таблица листа: WebSocket, блокировки, конфиги колонок `constants/FORM_*` | api |
|
||
| `web/src/api/` | axios-клиент `/api/v1`, модули по сущностям, WebSocket выгрузок | — |
|
||
|
||
## Границы
|
||
- Роутеры не ходят в БД напрямую, только через сервисы и репозитории. Сейчас нарушают `admin.py`, `main.py` (engine) и `websocket.py` (бизнес-логика в слое API).
|
||
- Проверка прав на ячейки и окна этапов — в SQL. Python её не дублирует, только маппит ошибки.
|
||
- Изменения схемы и функций — только новой миграцией alembic; старые миграции не правятся.
|
||
- Фронт обращается только к `/api/v1` через `web/src/api/`.
|
||
|
||
## Открытые вопросы
|
||
- Prod-авторизация через Keycloak (`raisa_fastapi_protected_api`) закомментирована в `main.py`, `deps.py`, `auth.py`; сейчас всегда работает локальный JWT. Как будет устроен prod?
|
||
- `websocket.py:333`, `:357`: условие `form_key != form_key` всегда ложно, поэтому блокировки сравниваются по `line_id` между всеми формами; `release_locks_for_row` ничего не возвращает.
|
||
- Раскладка колонок дублируется: `web/.../constants/FORM_1|2|4/*.js` (около 4 тыс. строк каждый) и `api/.../export_mappings.py`. Источник правды не определён.
|
||
- Названия форм в БД и UI расходятся (FORM_2, FORM_4).
|
||
- Мёртвый код фронта: `pages/TablePage.jsx`, `FormsPage.jsx`, `TablesTest.jsx`, `TableTempPage/`, `api/tables.js`, `api/client_form.js`, `api/ws.js`, `constants/FORM_1/*_NO_LOCAL.js`.
|
||
- В `package.json` не объявлены `@mui/x-date-pickers`, `@mui/icons-material`; tailwind/daisyui не используются.
|
||
- `Settings.CORS_ORIGINS` не применяется (в `main.py` `allow_origins=["*"]`), `APP_ENV` не читается, `JWT_SECRET` по умолчанию небезопасный.
|
||
- `/` монтируется дважды в `api/src/main.py:289` и `:291`.
|
||
- Интеграционные тесты зависят от данных в общей БД и не изолированы; `downgrade()` в миграциях пустые.
|
||
- Python-линтеров и проверок CI в репозитории нет.
|