benefits-cafeteria

Кафетерий льгот

Система управления материальными и нематериальными поощрениями сотрудников: витрина льгот, корпоративная валюта, окна выбора, согласования, административная панель.

Реализована по техническому заданию как полноценное приложение: серверная часть с базой данных, клиентская часть, контейнерная поставка.


Стек и почему он такой

Слой Решение
Серверная часть 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

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.

Локально, без Docker

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 не запускался. Конфигурация написана по стандартной схеме, но перед передачей в контур её стоит прогнать.

Данные

Все данные вымышлены. Сотрудники, суммы, организации и обращения созданы для демонстрации и не относятся к реальным лицам или компаниям.