# Приоритеты разработки (эпики)

> **MVP = Спринты 1-4 (8 недель).** Все клубы на варианте A (RLS).

## Sprint 1: Фундамент + Multi-tenancy

1. Monorepo (Turborepo + pnpm)
2. Prisma-схема (20+ таблиц)
3. Auth (JWT, 6 ролей, API-ключи)
4. TenantStrategy + RLS-политики
5. Модульная система (club_modules + ModuleGuard)
6. ProvisioningService (RLS-реализация)
7. Docker Compose (PostgreSQL + Redis + coturn)
8. CI pipeline

## Sprint 2: Клиенты + Главная

6. CRUD клиентов
7. Mobile: auth, главная, клиенты
8. Web: рецепция
9. API-клиент (OpenAPI -> TS)

## Sprint 3: Расписание + Воронка

10. Расписание (CRUD + отмена/перенос/повтор)
11. Воронка (этапы, переходы, распределение)
12. Mobile: расписание, воронка
13. Push-уведомления (9 типов)

## Sprint 4: Статистика + Продажи = MVP

14. Статистика, конверсия, рейтинг
15. Продажи, реализация, долги
16. Mobile: статистика, рейтинг, продажи

## Sprint 5: Координатор + SIP + Спящие

17. Координатор: распределение, статистика
18. SIP-клиент: звонок, PiP, журнал
19. Спящие клиенты
20. График работы (1С)

## Sprint 6: Веб-отчёты + Панель клуба + Email

21. Web: 3 отчёта
    22-23. Панель админа клуба (10 разделов)
22. Email-модуль: NestJS (шаблоны, BullMQ-очереди, провайдер Strategy, трекинг)
23. Email UI: раздел «Рассылки» в панели админа клуба
24. 5 автоматических email-триггеров

## Sprint 7: Суперадмин + Webhooks + Beta

27. Панель суперадмина
28. Webhooks (14 типов)
29. Интеграция 1С (полная)
30. Beta

## Sprint 8: Полировка + Темы + Ребрендинг + Release

31. E2E тесты
32. Оптимизация
33. Аудит безопасности
34. Темы оформления — кросс-сервисная интеграция (см. `.claude/docs/themes.md`)
35. Ребрендинг: FitCRM -> MyFitCRM (см. `.claude/docs/rebranding.md`)
36. App Store + Google Play
37. Пилот

## Sprint 9: CRM-модуль (Entity Factory)

> Подробная документация: `.claude/docs/crm.md`

38. Entity Factory ядро: EntityManager<T>, EntityRegistry, система событий (onBefore/onAfterAdd/Update/Delete), EntityContext (skipEvents, skipPermissions, skipValidation)
39. CRM-сущности: CrmDeal (сделка + контакт + реквизиты), CrmTraining (привязка к сделке), CrmPipeline, CrmStage (OPEN/WON/LOST, авто-дела, staleDays)
40. Кастомные поля: CrmUserField (STRING/INTEGER/FLOAT/LIST/BOOLEAN/DATE/DATETIME/TIME), showToTrainer, fieldName (англ.), CrmUserFieldValue — настройка per-club
41. Таймлайн сделки: карточки FORM_SUBMISSION, CALL (с прослушкой recordUrl), COMMENT, MESSAGE_TG/WA/VK/EMAIL, STAGE_CHANGE, ACTIVITY, TRAINING
42. Дела (CrmActivity): запланированные звонки/встречи на дату, мультиканальные сообщения (TG/WhatsApp/VK/Email), результат выполнения в таймлайн
43. Интеграция с лендингом: POST /v1/crm/deals/from-form, антифрод 5 уровней (honeypot, rate limit, fingerprint, scoring, captcha)
44. Универсальный webhook: POST /v1/crm/deals/webhook/:token, Smart Field Detection (автопарсинг по имени/значению), маппинг полей и значений списков, сквозная аналитика (UTM, Яндекс, Google, Roistat, Calltouch)
45. Напоминания: BullMQ crm-scheduler, staleDays, дедлайны дел, истечение лицензий, необработанные лиды
46. Аналитика CRM: конверсия воронки, прогноз выручки, эффективность менеджеров, средний цикл сделки
47. UI: Kanban-доска (drag&drop), карточка сделки с таймлайном, настройки полей/стадий/вебхуков — web-platform-admin + web-club-admin

## Sprint 10: Баги club-admin + UX-авторизация + Role Switcher + CRM-допиливание

> **ПРИОРИТЕТ №1:** 7 багов club.myfitcrm.ru (web-club-admin). Затем — «Hide, Don't Block» + имперсонация суперадмина.

### Баги club-admin (ПРИОРИТЕТ)

| # | URL / Проблема | Корневая причина | Решение |
|---|---------------|-----------------|---------|
| 1 | `/staff` — не открывается | Backend RBAC: API возвращает 403 для роли club_admin | Проверить guards на `/v1/users` (или staff endpoint), добавить `club_admin` в `@Roles()` |
| 2 | `/rooms` — не открывается | Backend RBAC: API возвращает 403 | Проверить guards на `/v1/rooms`, добавить `club_admin` в `@Roles()` |
| 3 | Sidebar — нет имени пользователя, роли и кнопки выхода | В `sidebar.tsx` club-admin нет секции user info (в web-admin есть, строки 99-119) | Портировать блок user info + logout из `apps/web-admin/src/components/layout/sidebar.tsx` |
| 4 | `/catalog` — не открывается | Backend RBAC: API возвращает 403 | Проверить guards на `/v1/catalog` (или services/subscriptions), добавить `club_admin` |
| 5 | `/notifications` — не открывается | Backend RBAC: API возвращает 403 | Проверить guards, добавить `club_admin` в `@Roles()` |
| 6 | `/email` — «Access denied. Required roles: club_admin» | Роль пользователя не совпадает с требуемой (возможно, залогинен не как club_admin, или guard проверяет неправильно) | Проверить AuthGuard + RolesGuard на email endpoints, убедиться что club_admin role маппится корректно |
| 7 | `/settings` — «Validation failed (uuid is expected)» | clubId не передаётся или передаётся как undefined/null в API-запросе | Проверить как clubId извлекается из JWT/context в settings endpoint, убедиться что TenantResolver корректно резолвит clubId |

**UX-авторизация (Hide, Don't Block)** 48. `<RoleGate>` компонент (web) + `useHasRole` хук (mobile): скрытие UI-элементов вместо показа «нет доступа» 49. Фильтрация sidebar/navigation по `allowedRoles`: пункты меню не рендерятся, если роль не в списке 50. API: `filterByRole()` в EntityPermissions для всех сущностей — WHERE на уровне запроса, 404 вместо 403 для чужих записей 51. Redirect при прямом переходе по URL без доступа → главная страница роли (не страница «403»)

**Имперсонация суперадмина (Role Switcher)** 52. `POST /v1/auth/impersonate { targetRole, clubId? }` — временный JWT с `impersonatedBy`, read-only по умолчанию 53. UI: выпадающий список ролей в header platform-admin, баннер «Вы просматриваете как [Роль]» с кнопкой возврата 54. Аудит: все действия в режиме имперсонации логируются с `impersonatedBy: realUserId`

**CRM-допиливание** 55. RLS-политики для CRM-таблиц: crm_pipelines, crm_stages, crm_deals, crm_activities, crm_timeline, crm_trainings, crm_stage_history, crm_lost_reasons, crm_user_fields, crm_user_field_values, crm_webhook_endpoints — аналогично существующим (clubId IS NULL OR clubId = current_setting) 56. FK-связи в CrmWebhookEndpoint: добавить @relation для pipelineId → CrmPipeline, stageId → CrmStage, defaultAssigneeId → User (onDelete: SetNull) 57. CrmStageHistory.toStage: изменить onDelete: Cascade → SetNull (сохранение аудита при удалении стадий) 58. Строгая типизация фронтенда CRM: заменить Record<string, any> → типизированные интерфейсы (KanbanData, TimelineConfig, ActivityTypeMap), убрать `as any` кастинг 59. Accessibility CRM-компонентов: aria-labels на icon-only кнопки (kanban, timeline pin, activity complete), aria-hidden на декоративные SVG 60. AbortController в CRM-компонентах: добавить cleanup в useEffect для всех API-запросов (предотвращение race conditions) 61. Shared CRM-пакет: выделить дублированные CRM-компоненты из web-platform-admin и web-club-admin в @fitcrm/crm-ui 62. CRM-аналитика: дашборд конверсии воронки, средний цикл сделки, эффективность менеджеров, прогноз выручки 63. Интеграция CRM с SIP: привязка входящих/исходящих звонков к сделкам, запись звонков в таймлайн с плеером 64. Мессенджер-каналы: интеграция Telegram Bot / WhatsApp Business API для отправки сообщений из карточки сделки
