# DFiP_Budget_planing ## Что это Система бюджетного планирования ДФиП РСХБ (платформа raisa). Исполнители ССП и региональных филиалов (РФ) совместно, в реальном времени заполняют бюджетные формы (сметы) по листам, статьям расходов и кварталам. Что и когда может править каждая роль, задают этапы (окна редактирования колонок). ДФиП и ДУРРС корректируют (секвестр), администратор ведёт пользователей, оргструктуру, шаблоны этапов и журнал аудита. Поверх форм строятся своды 1 и 2, реестр проектов РФ (открытие, закрытие и переезд ВСП и т.п.) с отчётами по годам, справочник ВСП и фоновая выгрузка в Excel. Формы (`v3.form_type`): FORM_1 «Смета ГО» (AHR/CAP/OPER/SMETA, AHR и CAP делятся по direction Support/Development), FORM_2 «ПД» (плюс сателлиты AHR_LIMIT/RENT/UTILITY/SECURITY, OTCH9F), FORM_3 «Отчёт РФ развитие» (хранится в project → rf_project_year → rf_project_report), FORM_4 «Смета РФ поддержка» (плюс STRUCTURE — программы и проекты). Названия на фронте (`web/src/constants/constants.jsx`) расходятся с БД, источник истины — БД. Роли (`api/src/db/models/role.py`): 1 ADMIN; 2 EXECUTOR_DFIP (несколько ССП/РФ); 3 EXECUTOR_RF (одна оргединица); 4 EXECUTOR_DURRS. ## Стек и ограничения - Backend `api/`: Python, FastAPI 0.111, SQLAlchemy 2 async + asyncpg, Alembic, pydantic-settings, JWT (python-jose, HS256) + argon2. - **БД — только PostgreSQL**, всё в схеме `v3`. Бизнес-логика в основном в PL/pgSQL-функциях `v3.add_*`/`upd_*`/`del_*`/`v_*`, их зовут через `text("SELECT ... FROM v3.fn(...)")` из `api/src/repository/`. Функции живут в `api/alembic/versions/sql/*.sql` и переопределяются `CREATE OR REPLACE` в последующих миграциях: актуальна последняя версия. SQLite в `DATABASE_URL` по умолчанию — ловушка, на нём приложение не работает. - Frontend `web/`: React 18 на Rsbuild, **JavaScript (JSX)**, хотя есть tsconfig. UI — MUI и material-react-table. Основная таблица — собственный `components/RealtimeTable/`. Состояние в React Context, роутинг react-router-dom 6, axios. Biome для линта. Tailwind/daisyui остались от шаблона и не используются. - Платформа raisa: обязателен `api/run_server.py`; хост и порт из `SERVER__HOST`/`SERVER__PORT`. CI — внешний шаблон `cicd/ci/fastapi-app.yml` (`.gitlab-ci.yml`), ресурсы в `raisa_config.yml`. Собранный фронт отдаёт сам API из `api/web` (StaticFiles). - Зависимости ставятся из корпоративного Nexus (`setup/pip.conf`, `setup/.npmrc`). `raisa-fastapi-protected-api` есть только там. - cwd процессов API, тестов и alembic — `api/`: пути `alembic.ini`, `.env`, `web`, `back_static`, `tmp/exports` относительные. - Состояние WebSocket-блокировок ячеек и менеджер выгрузок живут в памяти процесса: один процесс, без нескольких воркеров. - Настройки (`api/src/core/config.py`): `OPENBAO__SETTINGS__*` или короткое имя (`DATABASE_URL`, `DEBUG`, `DATABASE_SCHEMA`). `DEBUG` по умолчанию true. При false на старте выполняются `alembic upgrade head` и цикл чистки аудита. ## Архитектура Подробная карта — в ARCHITECTURE.md. - `api/src/api/v1/` — роутеры (`/api/v1/...`) и `deps.py` (текущий пользователь, гарды `require_admin`/`require_executor*`). `websocket.py` — realtime-редактирование и блокировки ячеек. - `api/src/services/` — сервисы `*Service(db)`; `export_service/` — Excel-выгрузки в ProcessPool. - `api/src/repository/` — `*Repository(db)`: SQLAlchemy и вызовы SQL-функций. Текущий пользователь передаётся в SQL через `SET LOCAL app.user_id` (для аудита `v3.log_event`). - `api/src/db/models/` — ORM (36 моделей), `api/src/domain/schemas.py` — pydantic-схемы, `api/src/core/` — конфиг, безопасность, ошибки. - Права на ячейки проверяет SQL (`role_not_allowed:`, `window_closed:`). `core/exception_handlers.py` по тексту ошибки Postgres превращает их в 403/409/400/404/422. - `web/src/app/Routes.jsx` — страницы, `web/src/api/*.js` — клиент API, `web/src/components/RealtimeTable/` — редактируемая таблица, конфиги колонок по формам в `constants/FORM_*`. ## Команды - Установка: `cd setup && ./setup.sh` (venv в `api/.venv`, `npm i` в `web/`). Для тестов дополнительно `pip install -r api/requirements-dev.txt`. - API: `cd api && python run_server.py` (нужен Postgres в `DATABASE_URL`). Миграции: `cd api && alembic upgrade head`. - Web: `cd web && npm run start` (dev), `npm run build` (результат в `web/dist`). Линт: `cd web && npx biome check src`. - Тесты backend: `cd api && pytest` — весь набор. Зелёным считается только весь набор. `pytest tests/unit` — без БД. `pytest tests/integration` — нужен живой Postgres; `--init_db` накатывает миграции и сид `tests/sqls/fixture.sql`. - Тесты frontend: `cd web && node --test src/components/RealtimeTable/utils/*.test.js`. ## Тесты - `api/tests/unit/` — моки сессии и репозиториев (`AsyncMock`, `monkeypatch`), БД не нужна. - `api/tests/integration/` — `TestClient(app)` с полным lifespan, сессия с rollback. Фикстуры `admin_tokens`/`isp_tokens` (`api/tests/conftest.py`, `tests/integration/conftest.py`). Тестовое окружение — Postgres из `DATABASE_URL`, пароли `OPENBAO__TEST_ADMIN_PASSWORD`/`OPENBAO__TEST_EXECUTOR_PASSWORD`. Часть тестов делает `skip` при отсутствии данных. - Новая логика в SQL-функциях покрывается интеграционными тестами через API. Логику без БД выносить в сервисы и покрывать unit-тестами. ## Ветки и PR - **Базовая ветка — `test`**, не `main`: в неё идут все PR, `main` — устаревший шаблон. Везде, где процесс обвязки говорит «main» (база worktree, PR, `openspec archive`, `git pull --ff-only` в основном checkout), читать `test`. - Хук guard-main защищает только main/master, `test` он не охраняет. Прямые коммиты в `test` запрещены так же, как в main; исключение — только коммит `openspec archive`. - PR создаётся с `--base test`. ## OpenSpec и superpowers - Вход в любую задачу — superpowers:brainstorming. Skills openspec-propose и openspec-explore сами по себе не запускать. - Когда brainstorming классифицировал задачу как architectural, структуру change создать через `openspec new change ` (или `/opsx:propose `), а содержимое proposal.md, specs/ и design.md написать по итогам brainstorming. tasks.md из OpenSpec не заполнять — задачи живут в плане superpowers. - `/opsx:apply` не использовать: исполнение идёт через writing-plans и SDD/executing-plans. - `openspec archive ` — после merge PR, как часть чеклиста закрытия. - Хук require-plan защищает каталоги из `.claude/code-paths`: `api/src/`, `api/alembic/` (SQL-логика), `web/src/`.