# MyFitCRM — CRM-система для фитнес-клубов

CRM для фитнес-клубов на 6 ролей: Тренер, Координатор, Фитнес-менеджер, Админ рецепции, Админ клуба, Суперадминистратор. Мобильное приложение (React Native) + 3 веб-панели (Next.js 15) + API (NestJS 11). Эталон — FoxFit.

## Инструкции для AI-агентов

### Обязательно прочитай перед началом работы:

1. Этот файл (`CLAUDE.md`) — краткие инструкции, стек, конвенции, команды
2. `.claude/docs/` — детальная документация по подсистемам (читай по необходимости)
3. `docs/tz/tz-fitness-crm-full-v2.docx` — основное ТЗ (все экраны, поля, бизнес-логика)
4. `docs/tz/tz-fitness-crm-dopolnenie.docx` — дополнение (SIP, multi-tenancy, webhooks, лицензирование)
5. `docs/plan/plan-ai-first-crm-v2.docx` — план разработки по спринтам

### Правило: не выдумывай — читай ТЗ

Если нужны детали по экрану, полю или бизнес-правилу — ищи ответ в документах выше.

## Детальная документация (.claude/docs/)

| Файл                   | Содержание                                                               |
| ---------------------- | ------------------------------------------------------------------------ |
| `architecture.md`      | Стек, структура монорепо, интеграции                                     |
| `multi-tenancy.md`     | RLS, Strategy Pattern, варианты изоляции                                 |
| `modules-licensing.md` | Модульная система, metering, лицензии                                    |
| `roles-rbac.md`        | 6 ролей, матрица прав доступа                                            |
| `api-endpoints.md`     | REST API эндпоинты, webhooks (15 типов)                                  |
| `themes.md`            | 10 тем, архитектура, чеклист интеграции                                  |
| `email.md`             | Email-рассылки, Prisma-модели, провайдеры                                |
| `sip.md`               | SIP-клиент, кодеки, экран звонка                                         |
| `business-logic.md`    | Воронка, конверсия, push-уведомления                                     |
| `design-system.md`     | Цвета, типография, UI-компоненты                                         |
| `multi-agent.md`       | Мультиагентный workflow, worktrees                                       |
| `sprints.md`           | Спринты 1-8, приоритеты                                                  |
| `rebranding.md`        | Чеклист FitCRM -> MyFitCRM                                               |
| `watchdog.md`          | Мониторинг инфраструктуры, auto-fix, алерты                              |
| `innervoice.md`        | Telegram-бридж, MCP-сервер, чатбот, очереди                              |
| `safety.md`            | Изоляция чатбота, worktree, pre-commit хуки, merge-протокол, откат       |
| `crm.md`               | CRM-модуль: Entity Factory, сделки, таймлайн, кастомные поля, webhooks   |
| `ai-dev-workflow.md`   | AI-first workflow: test-first, слой за слоем, quality gate, антипаттерны |

## Стек (кратко)

- **Backend**: NestJS 11, Prisma 6, PostgreSQL 17, Redis 8, BullMQ
- **Mobile**: React Native 0.76+, Zustand, React Query, React Navigation 7
- **Web (x3)**: Next.js 15 (App Router), shadcn/ui, Tailwind CSS 4
- **Watchdog**: TypeScript, чистый Node.js — мониторинг 7 сервисов, auto-fix через PM2
- **InnerVoice**: TypeScript, Express + Telegraf + MCP SDK — Telegram-бридж для Claude
- **Infra**: Docker, K8s (prod), GitHub Actions, Prometheus + Grafana
- **Multi-tenancy**: RLS (MVP), Strategy Pattern для миграции на DB-per-tenant / K8s

## Команды разработки

```bash
pnpm install                                # Установка
pnpm dev                                    # Все сервисы
pnpm --filter api dev                       # Backend API
pnpm --filter mobile start                  # React Native
pnpm --filter web-admin dev                 # Рецепция
pnpm --filter web-club-admin dev            # Панель админа клуба
pnpm --filter web-platform-admin dev        # Суперадмин

pnpm test                                   # Все тесты
pnpm --filter api test                      # Backend
pnpm --filter api test:e2e                  # E2E API
pnpm lint && pnpm format                    # Линтинг

pnpm --filter api prisma:migrate            # Миграции БД
pnpm --filter api prisma:generate           # Генерация Prisma Client
pnpm --filter api prisma:seed               # Сидинг
pnpm --filter api prisma:studio             # Prisma Studio

docker compose up -d                        # PostgreSQL + Redis + coturn
pnpm build                                  # Сборка
pnpm typecheck                              # Проверка типов (безопасная)
```

### КРИТИЧНО: Никогда не запускать `build` на живом сервере

Все 3 веб-панели работают через PM2 в dev-режиме (`next dev`). Команда `next build` **удаляет `.next/`** перед сборкой. Если сборка упадёт (TS-ошибка), dev-сервер потеряет `.next/routes-manifest.json` и весь сайт отдаст 500 Internal Server Error.

**Правила:**

- Для проверки типов использовать `pnpm --filter <app> typecheck` (= `tsc --noEmit`) — безопасно, не трогает `.next/`
- `pnpm build` допустим ТОЛЬКО при остановленных сервисах или в CI/CD
- Если build всё же нужен: сначала `pnpm --filter <app> typecheck`, и только при успехе — `build`

## Конвенции кода

### Общие

- TypeScript strict mode везде
- camelCase (переменные), PascalCase (типы, компоненты), kebab-case (утилиты)
- Максимум 300 строк на файл
- UI на русском, комментарии единообразно

### UX-авторизация (обязательно!)

- **Hide, Don't Block**: если у роли нет доступа — элемент НЕ рендерится. Ни в меню, ни в списках, ни в карточках
- Sidebar, кнопки, колонки таблиц, действия — фильтруются по роли на фронте (`<RoleGate>`, `useHasRole`)
- API возвращает только доступные записи (`filterByRole` в WHERE), 404 вместо 403 для чужих сущностей
- Прямой переход по URL без доступа → допустимо показать «Контент недоступен» (пользователь мог получить ссылку извне)
- Суперадмин: Role Switcher в header — просмотр системы от лица любой роли без перелогинивания

### Backend (NestJS)

- Один модуль = одна сущность
- DTO: class-validator + class-transformer
- Swagger: @ApiTags, @ApiOperation
- RBAC: `@Roles('trainer', 'coordinator', 'manager', 'receptionist', 'club_admin', 'super_admin')`
- Multi-tenancy: club_id в контексте, RLS, TenantResolver
- Модульность: `@RequireModule('sip')`, club_modules
- Webhooks: EventEmitter2 + BullMQ
- API-ключи: scoped access, audit log

### Mobile (React Native)

- Функциональные компоненты + хуки
- Экран = папка: `index.tsx` + `hooks.ts` + `components/`
- StyleSheet.create, типизированная навигация, React Query
- SIP: синглтон через Zustand store

### Тесты

- Backend: Jest + Supertest
- Mobile: Jest + React Native Testing Library
- Web: Vitest + Testing Library
- Покрытие: >= 70% бизнес-логики
- E2E: Detox (mobile), Playwright (web)

## Workflow обработки задач через Telegram

**Принцип:** каждое сообщение из Telegram — новая сессия без истории. Контекст передаётся через цитирование сообщений.

**Детальный AI-workflow:** см. `.claude/docs/ai-dev-workflow.md` — test-first, декомпозиция по слоям, quality gate, антипаттерны.

### Получение новой задачи

1. **Задача точная** (конкретный файл, конкретное действие) -> выполняй сразу
2. **Задача неточная / требует уточнения** -> составь план с Definition of Done и отправь через `telegram_notify`:

```
📋 Задача #N: [краткое название]

План (слой за слоем):
1. 🗃 [Схема/данные]
2. 🔌 [API/бизнес-логика]
3. 🧪 [Тесты]
4. 📱/🖥 [UI]
5. ✅ typecheck всех затронутых apps

Definition of Done:
- [конкретные критерии приёмки]
- typecheck проходит
- Существующие тесты не ломаются

Утверждаем план?
```

### Получение ответа на план (цитата)

Когда в сообщении есть **цитата** с текстом, содержащим `📋 Задача #` — это ответ на ранее отправленный план:

1. **Парси цитату**: извлеки номер задачи, название и план
2. **Читай ответ пользователя** (текст после цитаты):
   - `Да` / `Ок` / `Утверждаю` -> выполняй план как есть
   - Подробный ответ с корректировками -> обнови план и выполняй
   - `Нет` / `Отмена` -> сообщи что задача отменена
3. **По завершении** -> отправь результат через `telegram_notify`

### Распознавание цитаты

Telegram-бридж оборачивает цитируемый текст в маркеры `❓` ... `❓📋`:

```
❓ [текст цитируемого сообщения] ❓📋

[ответ пользователя]
```

1. Текст между `❓` и `❓📋` — это цитата
2. Если внутри `📋 Задача #` — это ответ на план
3. Текст ПОСЛЕ `❓📋` — ответ пользователя
4. **НЕ создавай новую задачу** — продолжай работу по задаче из цитаты

### Генерация документов

Если задача из Telegram требует формирования документа:

1. **Создай HTML-страницу** в `apps/web-platform-admin` по маршруту `/documents/{id}`
   - Красиво оформлена (Tailwind CSS, shadcn/ui), защищена AuthGuard
2. **Кнопки экспорта**: DOCX (для текста) и/или XLSX (для таблиц)
3. **В ответе** верни прямую ссылку: `https://platform.myfitcrm.ru/documents/{id}`
