BR 3.1 — Admin Franchise (BFF + Web)
erp-admin — monorepo: bff/ (Node.js + Fastify + TypeScript) + web/ (React SPA).
Контракты
- Клиенты — Список
- Клиенты — Карточка
- Группы — Список
- Группы — Карточка
- UI-гейтинг
- Заказы — блок «Клиент»
BFF задачи
1. Shared types
-
shared/types/customer.ts:Customer,CustomerResponse,CreateCustomerRequest,UpdateCustomerRequestCustomerAddress,CustomerGroup,CustomerGroupRulesJson
- Типы для правил JSON (discriminated union по
type)
2. HTTP client Customer Service
-
bff/src/services/customer-service-client.ts— обёртка надfetchдля:3013 - Прокидывание
Authorizationheader (Bearer JWT из запроса клиента) -
X-Service-Tokenдля internal-вызовов (из env)
3. Proxy routes (BFF)
-
/api/v1/admin/customers/*— проксирует в Customer Service/api/v1/customers/*- Для карточки клиента (
GET /admin/customers/{id}) — агрегация: Customer + вызов Order ServiceGET /api/v1/orders?customer_id=X&limit=20для вкладки «Заказы» - Список клиентов (
GET /admin/customers) — можно также подтянуть LTV / orders_count из Order ServiceGET /internal/orders/customer-summaryдля каждого (batch — по 20 на страницу ок, либо добавить batch endpoint в Order Service в будущем)
- Для карточки клиента (
-
/api/v1/admin/customer-groups/*— прокси 1:1 в Customer Service -
/api/v1/admin/customers/{id}/addresses/*— прокси
4. Admin BFF — обновить карточку заказа
-
GET /api/v1/admin/orders/{id}— если в ответеcustomer_id != null, подтянуть клиента черезGET /internal/customers/{id}Customer Service и подмерджить в response какcustomer: { id, first_name, last_name, phone, groups }
5. Тесты BFF
- Unit: маппинг customer response, агрегация с Order Service
- Integration: моки бэк-сервисов, проверка прокси
Web задачи
1. Routing + навигация
-
web/src/App.tsx— добавить роуты:/customers→CustomerListPage/customers/new→CustomerCreatePage/customers/:id→CustomerViewPage/customers/:id/edit→CustomerEditPage/customer-groups→CustomerGroupListPage/customer-groups/new→CustomerGroupCreatePage/customer-groups/:id→CustomerGroupViewPage/customer-groups/:id/edit→CustomerGroupEditPage- Все обёрнуты в
<PermissionRoute permission="...">как в других разделах
-
web/src/components/layout/Layout.tsx— добавить группу «Клиенты» в sidebar:Клиенты→/customersс permissioncustomers.readГруппы→/customer-groupsс permissioncustomer_groups.read
2. Страницы — Клиенты
-
pages/customers/ListPage.tsx— таблица + фильтры + поиск + пагинация. По паттернуemployees/ListPage -
pages/customers/ViewPage.tsx— карточка с табами (Profile/Addresses/Orders/Groups). Паттернemployees/ViewPage -
pages/customers/CreatePage.tsxиEditPage.tsx— формы. Можно через sharedCustomerFormкомпонент - Компонент
CustomerAddressesTab.tsx— таблица + форма добавления / редактирования - Компонент
CustomerOrdersTab.tsx— список заказов клиента (подтягивает из/admin/orders?customer_id=X) - Компонент
CustomerGroupsTab.tsx— chips групп + модалка добавления в static группы - Компонент
CustomerSidebar.tsx— LTV, средний чек, заказы, дней без визита - Utility
normalizePhoneE164(raw: string): string— нормализация на blur в форме - Модалка удаления клиента с подтверждением
3. Страницы — Группы клиентов
-
pages/customer-groups/ListPage.tsx -
pages/customer-groups/ViewPage.tsx— условный рендер табов для static vs dynamic -
pages/customer-groups/CreatePage.tsx— шаг 1 выбора типа (radio) → POST → redirect на edit -
pages/customer-groups/EditPage.tsx— rendering table members (static) или конструктор правил (dynamic) - Компонент
CustomerGroupStaticMembers.tsx— таблица + модалка «Добавить клиентов» - Компонент
CustomerGroupDynamicRulesEditor.tsx— конструктор правил:- Dropdown типов правил
- Форма параметров для каждого типа (switch по type)
- Кнопки «Сохранить» и «Пересчитать сейчас»
- Компонент
CustomerGroupDynamicMembersReadonly.tsx— read-only таблица
4. Обновить карточку заказа
-
pages/orders/OrderDetailPage.tsx— добавить блок «Клиент» (еслиorder.customer_id != null). Рендерить имя, телефон, chips групп, ссылка на карточку клиента
5. PermissionContext / гейтинг
- Добавить новые permissions в
PermissionContextесли таковой есть (должен автоматически подхватываться из JWT) - Применить
PermissionRouteиusePermissionв новых страницах
6. Тесты
- Unit: формы, валидация phone
- Integration (Cypress/Playwright если есть): смок-тест flow (список → карточка → edit → save)
Definition of Done
- В сайдбаре появляется группа «Клиенты» (если есть permission)
- Раздел «Клиенты» — полноценный CRUD с карточкой и вкладками
- Раздел «Группы клиентов» — static и dynamic группы работают (конструктор правил позволяет создать базовые правила)
- Карточка заказа показывает привязанного клиента
- Prohibited actions скрыты согласно ролевой матрице