Admin Franchise — BR 1.4.3
Репо: erp-admin (C:\Users\A211\Desktop\erp-admin)
Зависимости
User Service + Auth Service должны быть готовы и задеплоены (для
/internal/users/*и/auth/me).
BFF (bff/src/)
Новые proxy-роуты
- Создать
routes/roles.ts— proxy к User Service/api/v1/roles:GET /api/v1/admin/roles→GET /api/v1/roles(c query paramsstatus,is_system,search,page,per_page)GET /api/v1/admin/roles/permission-catalog→GET /api/v1/roles/permission-catalogGET /api/v1/admin/roles/:id→GET /api/v1/roles/:idPOST /api/v1/admin/roles→POST /api/v1/rolesPATCH /api/v1/admin/roles/:id→PATCH /api/v1/roles/:idDELETE /api/v1/admin/roles/:id→DELETE /api/v1/roles/:idPOST /api/v1/admin/roles/:id/restore→POST /api/v1/roles/:id/restore
- Подключить роутер в
server.ts -
requireAuthmiddleware на всех роутах (уже существует)
Новый роут GET /api/v1/admin/auth/me
- Создать (или расширить существующий
routes/auth.ts) — proxy к Auth ServiceGET /auth/me - Пробросить Authorization header как есть
Изменения в существующих роутах
-
routes/employees.ts— никаких серверных изменений. Payloadroles[]в POST/PATCH пробрасывается прозрачно. Убедиться что БФФ не фильтрует это поле.
Web (web/src/)
Навигация и доступ
- В боковом меню добавить пункт «Роли» (иконка
shield-checkилиkey) под «Сотрудниками» - Видимость: только для
admin_franchise(проверка по multi-tenancy role из JWT) - Для
admin_franchisee— пункт скрыт (они используют существующие роли через карточку сотрудника)
PermissionContext
- Создать
contexts/PermissionContext.tsx:PermissionProvider— при старте приложения (после AuthContext) вызываетGET /api/v1/admin/auth/me, хранитpermissions: string[]- Hook
usePermission(key: string): boolean - Hook
useHasAllPermissions(keys: string[]): boolean
-
<RequirePermission keys={['menu.edit']}>{children}</RequirePermission>— компонент-gate; если нет права — рендеритfallback(null / 403 / disabled) - Также использовать для скрытия пунктов меню
API-клиент
-
api/roles.ts:listRoles(params): Promise<{ data: RoleListItem[], meta }>getRole(id): Promise<Role>createRole(payload): Promise<Role>updateRole(id, patch): Promise<Role>deleteRole(id): Promise<void>(черезDELETE)restoreRole(id): Promise<Role>getPermissionCatalog(): Promise<PermissionCatalog>
-
api/auth.ts— добавитьme(): Promise<MeResponse>
Страницы Роли
-
/roles—RoleListPage- Таблица (TanStack Table или существующий helper), пагинация, фильтры (Все/Системные/Пользовательские radio + поиск с debounce 300 мс)
- Query param
archive=1— отображать удалённые (status=deleted) - Переключатель «Удалённые роли» в шапке
- Кнопка «Добавить роль» →
/roles/new - Меню «…» на строке: Редактировать, Удалить
- Empty state с CTA «Добавить роль»
-
/roles/new—RoleCreatePage- 4 вкладки в компоненте
<RoleForm mode="create" />
- 4 вкладки в компоненте
-
/roles/:id—RoleViewPage(readonly)- Те же 4 вкладки, все поля disabled, кнопки Edit / Delete / Back
-
/roles/:id/edit—RoleEditPage<RoleForm mode="edit" role={data} />
Компоненты
-
components/roles/RoleForm.tsx— табы + state + submit (создание/редактирование) -
components/roles/BackofficePermissionsTab.tsx— таблица 16 разделов × {Read, Edit}. Логика Edit-implies-Read (checking Edit автоматически отмечает Read) -
components/roles/PosPermissionsTab.tsx— 14 чекбоксов -
components/roles/SalaryFormulaBlock.tsx— блок формулы (переиспользовать существующий компонент из EmployeeForm, выделить в общий если ещё нет) -
components/roles/DeleteRoleModal.tsx— простое подтверждение -
components/roles/RoleInUseModal.tsx— модалка со списком сотрудников + CTA «Открыть список сотрудников»
Страницы Сотрудники (обновления)
-
EmployeeListPage(/employees):- Добавить колонку «Permissions-роли» — чипы названий (до 3 + «+N»)
- Добавить фильтр «Permissions-роль» (dropdown из активных ролей, query param
role_id)
-
EmployeeViewPage/EmployeeEditPage— вкладка «Роли и магазины»:- Секция «Multi-tenancy роль» (existing, readonly бейдж)
- Новая секция «Permissions-роли» со списком назначенных ролей
- Каждая карточка роли: название (ссылка
/roles/:id), чипы магазинов, кнопки «Изменить магазины» / «Удалить» - Кнопка «Добавить роль» открывает
AssignRoleModal AssignRoleModal— Select активной роли + мульти-селект магазинов (из множества ТТ сотрудника)
-
EmployeeCreatePage:- Поле «Роль» переименовать в «Multi-tenancy роль (scope)» (оставить dropdown manager/cashier)
- Новая секция «Permissions-роли» (опциональная) с repeater’ом:
+ Добавить роль→ блок с Select роли + Multi-select магазинов
Роутинг и заголовки
- В
AppRouterдобавить/rolesи/roles/:id,/roles/:id/edit,/roles/new - Breadcrumbs для страниц ролей
Тестирование (manual + automated)
- Smoke-test: создание роли с разными комбинациями permissions
- Smoke-test: назначение 2+ ролей сотруднику с разными store-scope
- Edit implies Read — визуальный тест
- Удаление роли с активными сотрудниками →
ROLE_IN_USEмодалка - Системная роль «Администратор» — все вкладки disabled кроме Общее
- Фильтры на списке ролей и сотрудников
Выходные критерии
- BFF собирается и запускается (проксирование работает)
- Web:
/rolesзагружается, список ролей отображается - Создание роли → запись в БД → появление в списке
- Назначение роли сотруднику → отображение в его карточке
-
/auth/meзагружает permissions при старте app - UI-гейтинг через
<RequirePermission>работает для minimum 3 разделов (Каталог, ТТ, Сотрудники)