Сотрудники — Карточка

Три режима одного экрана: просмотр, создание, редактирование.

(Переработано в BR 1.4.4)

Enum employees.role удалён. Из формы убран dropdown «Менеджер / Кассир» и отдельное поле «Торговая точка». Остался единый блок «Роли» — multi-select permissions-ролей, у каждой свой набор ТТ. Признак «владелец франшизы / партнёра» определяется не ролью, а владением ЮЛ (scope-правила).


Просмотр (/employees/:id)

API: GET /api/v1/employees/{id}

Что видит пользователь

Заголовок — ФИО сотрудника. Рядом — статус (Активен / Деактивирован) и бейдж «Курьер» если флаг установлен.

Если сотрудник является владельцем (определяется на бэке через legal_entities.owner_user_id) — показывается бейдж:

  • «Владелец франшизы» — если он owner_user_id главного ЮЛ (type=franchise)
  • «Владелец партнёра» — если он owner_user_id ЮЛ type=franchisee (рядом — название ЮЛ, ссылка на карточку)

(Бейджи «Менеджер / Кассир» убраны вместе с enum BR 1.4.4)

Кнопки в шапке (видимость по scope):

  • “Редактировать” → переход в /employees/{id}/edit
  • “Деактивировать” (status=active) / “Реактивировать” (status=inactive)

Блоки данных

Основные данные:

ПолеЗначение
Имяfirst_name
Фамилияlast_name
Emailemail
Телефонphone или ”—“
Статус”Активен” / “Деактивирован”
Курьер”Да” / “Нет”

Роли и торговые точки: (Обновлено в BR 1.4.4 — нет отдельного поля «Торговая точка»; ТТ показываются per-роль)

  • Список permissions-ролей сотрудника (массив roles[]). Каждая роль — карточка с названием и чипами привязанных ТТ
  • Скрытая роль владельца партнёра (если есть) отображается как «Собственные права» (без техназвания, см. Роли § Скрытые)
  • Для владельца главного ЮЛ — подпись «Доступ ко всей франшизе»
  • Для владельца партнёра — подпись «Доступ ко всем ТТ своих ЮЛ»

Создание (/employees/new)

API: POST /api/v1/employees Доступ: владелец франшизы, владелец партнёра (в своём scope)

Что видит пользователь

Заголовок: “Новый сотрудник”. Форма с полями.

Форма

Основные данные:

ПолеТип вводаОбязательноМаска/Валидация
ИмяText inputДаmax 255
ФамилияText inputДаmax 255
EmailText inputДаemail формат
ПарольPassword inputДаmin 6 символов
ТелефонText inputНет+7 (XXX) XXX-XX-XX
PIN-кодText inputНетровно 4 цифры
КурьерCheckboxНетФлаг “Может доставлять заказы”

Блок «Роли» (Переработано в BR 1.4.4 — единый блок без enum)

Repeater: для каждой строки — Select роли + Multi-select ТТ:

ПолеТип вводаОбязательноОписание
РольSelectНетИз активных обычных ролей (GET /api/v1/admin/roles?status=active). Скрытые роли владельцев партнёров не отображаются в списке
Торговые точкиMulti-selectНетИз ТТ, доступных текущему пользователю по его scope
  • Кнопка «+ Добавить роль» — добавляет строку
  • Кнопка «🗑 Удалить» в строке — убирает её
  • Можно сохранить сотрудника без ролей (пустой массив) и добавить позже на вкладке «Роли и магазины»

Доступные ТТ по scope текущего пользователя:

  • Владелец франшизы → любая ТТ франшизы
  • Владелец партнёра → только ТТ его ЮЛ
  • Обычный сотрудник → обычно не создаёт других (нет permission employees.edit)

Нет поля «Multi-tenancy роль» и нет отдельного поля «Торговая точка»

(Удалено в BR 1.4.4) — раньше требовалось выбрать одну ТТ для manager/cashier. Теперь набор ТТ задаётся через ТТ в каждой назначенной роли. Если сотрудник работает на одной ТТ — назначают одну роль с одной ТТ.

Валидация

  • На клиенте: email формат, PIN ровно 4 цифры, пароль min 6, обязательные поля
  • С сервера:
    • EMAIL_DUPLICATE — “Сотрудник с таким email уже существует”
    • PIN_DUPLICATE — “PIN-код уже занят на торговой точке [название ТТ]”
    • ROLE_STORE_OUT_OF_SCOPE — “Магазин недоступен в вашем scope” (под полем магазинов соответствующей строки)
    • ROLE_NOT_FOUND — “Выбранная роль не существует или скрыта” (под Select роли)

(Удалено в BR 1.4.4)

Ошибки ADMIN_ROLE_FORBIDDEN, ROLE_IMMUTABLE, ROLE_ESCALATION больше не существуют — enum-роли удалены, формы их не выбирают.

Кнопки

  • “Сохранить” — отправить форму
  • “Отмена” — возврат на список (с подтверждением если есть несохранённые данные)

После успеха

  • Redirect на /employees/{new_id} (карточка просмотра)
  • Toast: “Сотрудник создан”

Редактирование (/employees/:id/edit)

API: PATCH /api/v1/employees/{id} Доступ: владелец франшизы — все сотрудники; владелец партнёра — только своих

Что видит пользователь

Та же форма что при создании, но:

  • Поле Пароль — необязательное, placeholder “Оставьте пустым, если не хотите менять”
  • Предзаполнены текущие значения

(Изменено в BR 1.4.4)

Поля «Multi-tenancy роль» больше нет — нечего блокировать. Permissions-роли можно свободно менять (добавлять/удалять/менять магазины).

Что нельзя менять через эту форму

  • Признак владельца партнёра (управляется через legal_entities.owner_user_id — карточка ЮЛ)
  • Скрытую роль владельца партнёра (управляется через карточку ЮЛ → вкладка «Права»)

Владелец партнёра — ограничения scope

  • Может редактировать только сотрудников своих ТТ (своего scope)
  • При попытке открыть чужого — 403, редирект на список

Кнопки

  • “Сохранить” — отправить PATCH
  • “Отмена” — возврат на карточку просмотра

После успеха

  • Redirect на /employees/{id} (карточка просмотра)
  • Toast: “Изменения сохранены”

Состояния

СостояниеЧто показываем
Загрузка (просмотр/edit)Skeleton-блоки вместо полей
Сотрудник не найден (404)“Сотрудник не найден” + кнопка “Вернуться к списку”
Ошибка сохраненияОшибки под полями (validation) или toast (серверная ошибка)
Несохранённые измененияПри уходе со страницы: “У вас есть несохранённые изменения. Покинуть страницу?”

Переходы

ОткудаКудаТриггер
КарточкаСписокКнопка “Назад” / breadcrumb
КарточкаРедактированиеКнопка “Редактировать”
СозданиеКарточкаПосле успешного сохранения
СозданиеСписокКнопка “Отмена”
РедактированиеКарточкаПосле сохранения или “Отмена”

BR 1.4.1 — Карточка с вкладками

Расширение в рамках BR 1.4.1

Карточка сотрудника переходит с плоской формы на 5-табовый layout. Все существующие поля сохраняются на вкладке “Общая информация”.

Вкладки

#ВкладкаСодержаниеAPI
1Общая информацияТекущие поля (ФИО, email, телефон, PIN, курьер)GET /api/v1/employees/{id}
2Роли и магазиныPermissions-роли с per-role магазинами + индивидуальная формула зарплатыGET /api/v1/employees/{id}, GET /api/v1/salary-formulas/employee/{id}
3Юридические деталиИНН, паспорт, водительское удостоверение, СНИЛСGET /api/v1/employees/{id}/legal-details
4Рабочее времяКалендарь часов (план/факт)GET /api/v1/schedules?employee_id={id}
5История заказовЗаглушка до Order Service (BR 2.1)

Поведение

  • Вкладки рендерятся как горизонтальные табы под заголовком карточки
  • Default tab — “Общая информация”
  • Переключение вкладок не меняет URL (состояние в компоненте)
  • Кнопки “Редактировать”, “Деактивировать/Реактивировать” остаются в шапке (доступны на всех вкладках)

Вкладка “Роли и магазины”

(Переработано в BR 1.4.4 — секция «Multi-tenancy роль» удалена)

Блок «Permissions-роли» (что сотрудник может делать):

Список назначенных роль-объектов (каждая — карточка):

ЭлементОписание
Название ролиСсылка на /roles/:id. Скрытая роль владельца партнёра отображается как «Собственные права» без ссылки
МагазиныЧипы с названиями ТТ где эта роль действует. Если пусто — «Во всех доступных магазинах»
Действия«Изменить магазины» / «Удалить роль у сотрудника» (для скрытой роли «Удалить» недоступно — управляется через карточку ЮЛ)

Кнопка «Добавить роль» → модалка:

  • Select из активных обычных ролей франшизы (GET /api/v1/admin/roles?status=active); скрытые роли владельцев партнёров недоступны
  • Multi-select магазинов (из ТТ, доступных сотруднику-редактору по его scope)
  • «Сохранить» → PATCH сотрудника с новым массивом roles

Валидация:

  • Нельзя добавить роль, которая уже назначена (показывать её disabled в select)
  • Магазины — подмножество ТТ scope текущего пользователя
  • Сервер возвращает ROLE_STORE_OUT_OF_SCOPE → сообщение под полем магазинов

Блок «Индивидуальная формула зарплаты» (без изменений, из BR 1.4.1)

  • Если есть salary_formula для сотрудника — показать type + значения
  • Кнопка «Изменить формулу» (владельцы) — inline-редактирование или модалка
  • Формула индивидуальная → перекрывает любую ролевую

Вкладка “Юридические детали”

  • Поля: inn, passport_series, passport_number, passport_issued_by, passport_issued_date, driver_license, snils
  • Режим просмотра → кнопка “Редактировать” для inline-edit
  • API: GET /api/v1/employees/{id}/legal-details, PUT /api/v1/employees/{id}/legal-details

Вкладка “Рабочее время”

  • Мини-календарь с часами за текущий месяц
  • Для каждого дня: плановые часы (из расписания) и фактические (из shift records)
  • Итого внизу: сумма план / сумма факт
  • Ссылка “Открыть расписание” → /schedule?employee_id={id}

Вкладка “История заказов”

Заглушка

“История заказов будет доступна после подключения Order Service (BR 2.1)“


Ссылки