Admin Franchise (BFF + Web) — BR 1.4.2

Спеки: Сотрудники — Карточка, Юридические лица — Карточка

Admin BFF (Node.js + Fastify)

  • Shared types: обновить EmployeeRole union → "admin_franchise" | "admin_franchisee" | "manager" | "cashier"
  • Обновить auth middleware (парсинг JWT role) — новые значения
  • Обновить role-based route guards (requireRole('admin_franchise'))
  • Проверить проксирование POST /legal-entities — новый body (блок owner) и response (блок owner)
  • Проверить проксирование POST /employees — передавать новый error ADMIN_ROLE_FORBIDDEN во фронт

Web (React SPA)

Общие места

  • AuthContext / JWT parsing — принять новые значения role
  • Маппинг role → русский лейбл (“Владелец франшизы”, “Владелец партнёра”, “Менеджер”, “Кассир”)
  • Sidebar / меню — обновить role-based visibility (замена строк franchise/franchisee)
  • RoleBadge компонент — обновить варианты

Форма сотрудника (/employees/new, /employees/:id/edit)

  • Dropdown “Роль” — только Менеджер и Кассир (admin_* убрать)
  • При получении ошибки ADMIN_ROLE_FORBIDDEN — показать под полем “Роль”
  • В режиме просмотра карточки — корректно показывать русские лейблы для всех 4 ролей (включая admin_*, если существующий сотрудник)

Список сотрудников

  • Фильтр “Роль” — оставить все 4 значения (для просмотра существующих admin_*)
  • Колонка “Роль” — показывать русские лейблы
  • Бейджи роли — обновить
  • Добавить блок “Владелец партнёра” (5 полей: first_name, last_name, email, phone?, password?)
  • Блок виден только при type=franchisee
  • Валидация: first_name, last_name, email — обязательные; email — формат
  • Поле “Пароль” — placeholder “Оставьте пустым, чтобы сгенерировать автоматически”
  • Обработка серверных ошибок: OWNER_FIELDS_REQUIRED, OWNER_EMAIL_DUPLICATE
  • Убрать старое поле “Владелец (select)” из формы создания

Модалка “Партнёр создан”

  • После успешного POST /legal-entities (type=franchisee) — показать модалку поверх карточки
  • Email владельца (крупно) + кнопка “Скопировать”
  • Временный пароль (крупно, моноширинный) + кнопка “Скопировать” — только если owner.temporary_password в ответе не null
  • Callout-предупреждение о необходимости сохранить данные
  • Кнопка “Закрыть” → redirect на /legal-entities/{id}

Карточка ЮЛ — просмотр

  • Поле “Владелец” — показать ФИО + email сотрудника по owner_user_id (кликабельно — переход на карточку сотрудника)
  • Для legacy-записей без owner_user_id — “Не назначен”

Тесты (e2e / integration)

  • Форма сотрудника не показывает admin_* в dropdown
  • Создание ЮЛ Франчайзи — обязателен блок Владельца
  • После создания ЮЛ — показывается модалка с credentials
  • temporary_password не показывается, если пользователь задал свой пароль
  • Русские лейблы корректны для всех 4 ролей