Система управления материальными и нематериальными поощрениями сотрудников: витрина льгот, корпоративная валюта, окна выбора, согласования, административная панель.
Реализована по техническому заданию как полноценное приложение: серверная часть с базой данных, клиентская часть, контейнерная поставка.
| Слой | Решение |
|---|---|
| Серверная часть | Python 3.12, FastAPI, SQLAlchemy 2.0 |
| База данных | PostgreSQL 16 (локально — SQLite без изменений кода) |
| Авторизация | JWT, bcrypt |
| Клиентская часть | Vanilla JavaScript, CSS с переменными |
| Графики | Chart.js 4.4 |
| Поставка | Docker, docker-compose, nginx |
Почему FastAPI. ТЗ требует «комплект документации». FastAPI генерирует OpenAPI-схему из кода, поэтому документация API не пишется отдельно и не расходится с реализацией: /api/docs всегда соответствует тому, что работает. Для системы с шестнадцатью группами функциональных требований это экономит заметную часть работы и снимает риск устаревшей документации.
Почему PostgreSQL и SQLAlchemy. Развёртывание в закрытом контуре заказчика означает, что СУБД будет его, а не облачная. PostgreSQL — стандарт для российского госсектора и корпоративного сегмента. SQLAlchemy позволяет держать одну кодовую базу: локальная разработка идёт на SQLite, продуктовый контур на PostgreSQL, строка подключения меняется переменной окружения.
Почему права проверяются на сервере. Ролевая модель из раздела 3 ТЗ реализована зависимостями FastAPI: каждый эндпоинт Пульта закрыт проверкой конкретного экрана, витрина фильтрует разделы по роли. Клиент не решает ничего — он только отображает то, что разрешил сервер. Поэтому попытка обратиться к закрытому разделу через API вернёт 403 независимо от того, что показано в интерфейсе.
Почему клиентская часть без фреймворка. Бизнес-логика целиком на сервере: расчёт баланса, приоритет списания, лимиты, валидация заказа, маршрут согласования. Клиенту остаётся получить данные и отрисовать их. При такой задаче React или Vue добавили бы сборку и зависимости, не добавив ничего по существу. Один файл без сборки проще разворачивать в закрытом контуре и проще передавать заказчику.
Почему Chart.js. Единственная внешняя библиотека на клиенте. Подключается одним скриптом и не требует отдельного CSS — это важно, потому что политика безопасности в корпоративных контурах часто режет внешние стили.
docker compose up --build
Поднимутся три контейнера: PostgreSQL, бэкенд и nginx с клиентской частью. База наполняется демонстрационными данными автоматически при первом запуске.
Бэкенд умеет сам отдавать клиентскую часть — тогда достаточно одного процесса вместо трёх:
cd backend
pip install -r requirements.txt
python -m app.seed
uvicorn app.main:app --port 8000
Приложение откроется на http://localhost:8000, документация API — на /api/docs.
Этот же режим используется для развёртывания демонстрационного стенда: конфигурация в render.yaml.
cd backend
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python -m app.seed # наполнение демо-данными
uvicorn app.main:app --reload
Клиентская часть — статический файл frontend/index.html.
Выводятся прямо на экране входа. Каждая роль видит свой набор разделов.
| Пользователь | Логин | Пароль | Что проверяет |
|---|---|---|---|
| Дроздюк А. В. | a.drozdiuk@corp.example | demo1234 | Полный доступ к витрине |
| Назарова Е. А. | e.nazarova@corp.example | demo1234 | Декрет: раздел «Моё здоровье» скрыт |
| Орлов В. Н. | v.orlov@corp.example | demo1234 | ВИП: только общие предложения |
| Соколова И. П. | i.sokolova@corp.example | hr1234 | HR: Пульт без настроек, аудита и аномалий |
| Белов С. А. | s.belov@corp.example | admin1234 | Администратор: полный Пульт |
| Гаврилов П. И. | p.gavrilov@corp.example | demo1234 | Exclusion: доступ к Системе закрыт |
Вход доступен тремя способами: по логину и паролю, через имитацию корпоративного SSO и по коду приглашения (KL-2026-7788).
Попытка войти с почтой, которой нет в базе, возвращает сообщение о рассинхронизации данных с 1С:ЗУП — поведение из ФТ-ОНБ.6.
Ролевая модель (раздел 3). Шесть ролей, карта «роль → права», разграничение на уровне разделов витрины, позиций каталога и экранов Пульта. Изменения ролей фиксируются в журнале аудита.
Балльная система (4.4). Сгораемые и несгораемые баллы отдельными лотами, срок сгорания задаётся при начислении, приоритет списания — сначала сгораемые с ближайшим сроком. Ручные начисления и списания с обязательным комментарием, заморозка баллов.
Бюджеты и лимиты (4.5). Модель по грейдам, массовый пересчёт с предварительным просмотром и списком исключений, лимиты позиций по периодам с проверкой фактических заказов.
Каталог и витрина (4.2). Иерархия «раздел → категория → позиция», поиск и фильтры, одиннадцать типов позиций с разной механикой оформления, архивация с сохранением в прежних заказах, блокировка удаления позиции с активными заказами.
ДМС (4.3). Расширения пакета, подключение членов семьи с валидацией возраста и расчётом стоимости по возрастной группе, отказ от базового полиса с сохранением баллов.
Окна выбора (4.6). Кампании с датами и сегментами, контроль корректности дат, два режима правил изменения льгот: ограничивающий и информирующий.
Заказы и согласования (4.7). Полный цикл со статусами, маршрут согласования, отмена с возвратом баллов, отдельное правило для промокодов (отмене не подлежат).
Промокоды (4.8). Партии с остатками и сроками, автоматическая выдача кода при покупке, предупреждение при снижении остатка ниже порога.
Переводы и благотворительность (4.12). Переводы между сотрудниками с комиссией, донаты с софинансированием компании.
Поддержка, новости, опросы (4.10, 4.11, 4.13). Обращения со статусами, публикации с комментариями и модерацией, опросы с подсчётом голосов.
Пульт (4.14). Дашборд с метриками и графиками, управление каталогом, бюджетами, начислениями, окнами выбора, заказами, сотрудниками и ролями, промокодами, обращениями.
Аналитика и выгрузка (4.16). Использование бюджета по подразделениям, популярные льготы, структура баллов, динамика заказов. Выгрузка в бухгалтерию со всеми пятнадцатью полями из ФТ-АНЛ.6, валидация и экспорт в CSV.
Аудит и контроль (4.17). Журнал всех финансово значимых операций, журнал аномалий с правилами выявления и отметкой легитимности.
Настройки платформы (4.15). Комиссия перевода, минимальная сумма, множитель софинансирования, стоимость балла, срок сгорания, потолок ручного начисления, срок ответа поддержки, режим окна выбора, включение и отключение разделов — всё меняется через интерфейс без доработки кода.
Интеграции с 1С:ЗУП, SSO и SMTP показаны как статусы каналов с проверкой доступности. В границы ТЗ инфраструктура заказчика не входит, а имитировать обмен с несуществующими системами означало бы выдавать заглушку за интеграцию.
Push-уведомления — в соответствии с ФТ-КОМ.7 не реализуются в первой версии.
Миграции Alembic подготовлены как зависимость, но схема создаётся напрямую: для демонстрационного стенда это проще, в продуктовом контуре потребуется первая миграция.
backend/
app/
models/ модели предметной области
schemas/ схемы запросов и ответов
api/
deps.py зависимости: текущий пользователь, проверка прав
auth.py вход, SSO, приглашение
shop.py витрина сотрудника
pult.py административная панель
core/
security.py пароли и токены
points.py балльная механика
seed.py демонстрационные данные
main.py
Dockerfile
frontend/
index.html клиентская часть
nginx.conf раздача статики и проксирование /api
Dockerfile
docker-compose.yml
render.yaml конфигурация демонстрационного стенда
cd backend && pytest
123 теста, покрытие 90%. Подробности, подход и список найденных дефектов — в TESTING.md.
Отдельные документы: CODE_REVIEW.md — ревью кода с исправлениями, REQUIREMENTS.md — построчная сверка со 114 требованиями ТЗ.
Связка бэкенда с клиентской частью проверена локально и покрыта автотестами: авторизация тремя способами, разграничение прав по ролям, оформление заказа со всеми валидациями, согласование, возврат баллов, выгрузка, журнал аудита.
Сборка Docker-образов не проверялась: на машине разработки Docker не запускался. Конфигурация написана по стандартной схеме, но перед передачей в контур её стоит прогнать.
Все данные вымышлены. Сотрудники, суммы, организации и обращения созданы для демонстрации и не относятся к реальным лицам или компаниям.