Prisma's `@default(uuid())` runs in the client layer and is bypassed by
`$queryRawUnsafe` / `$executeRawUnsafe`. The DB column has no server-side
default and pgcrypto/uuid-ossp aren't enabled, so every aggregate /
increment call failed with 23502 NOT NULL on `id`.
Pass a `randomUUID()` from `node:crypto` as the first parameter in all
four raw INSERTs (aggregateUsage, recordApiRequest, recordWebhookSent,
recordPushSent).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Help system (new):
- HelpProvider in dashboard layout drives a right-side Sheet with topic
content; HelpIcon ("?") buttons open it inline without leaving context.
- 8 topics written for managers in plain language: overview, create,
dashboard, scenarios (with per-step-type sections), subscribers,
broadcasts, webhooks, analytics.
- Full-page mirrors at /help/bots and /help/bots/[topic] so links can be
shared with colleagues.
- ~45 HelpIcon callouts placed at every functional block in the bot UI,
including each step header and sub-section in the scenario step editor.
- Real PNG screenshots embedded from public/help/bots/.
UI improvements bundled in:
- Webhooks: edit dialog reuses the create form, power toggle, edit/test/
delete actions on each row.
- Subscribers: minor layout tweaks alongside the help icons.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- backlog.md: technical items intentionally postponed (log retention, async
callback endpoint, external API for broadcasts).
- tz-bitrix-bot-bridge.md: spec for the Bitrix24 PHP module that talks to
MyFitCRM bots via HTTPS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- New tg_bot_webhook_deliveries table tracks every outbound webhook attempt
(status code, response body/headers, error, attempts) for audit and retries.
- Reusable Telegram-safe HTML sanitizer extracts only Telegram-allowed tags.
- MAX and Telegram adapters: unify message payload, broader event handling.
- Scenario engine and subscriber service: refinements for referral counting
and onboarding flow consistency.
- CSV export: type-safe stringification of subscriber cells.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- New (network-admin) layout in web-club-admin for users with access to
multiple clubs: admin/clubs (list+CRUD), admin/staff (network-wide),
admin/license, admin/audit
- NetworkAdminShell + NetworkAdminSidebar + NetworkTopBar with club
switcher
- DashboardShell detects network access and renders top bar accordingly
- Clubs components: create-club-dialog, edit-club-dialog, actions-menu
- /structure route (club org-chart) in standard dashboard layout
- Doc pages: auth-refactor-plan, org-structure-plan, visual-editor-redesign
- scripts/add-club-subdomain.sh (auto-provision nginx vhost on trial)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- DB migration 00010_org_structure: Department tree, DepartmentType
(DEPARTMENT/TEAM), DeptMember with roles (EMPLOYEE/HEAD/DEPUTY),
DepartmentLog audit trail, DeptLogAction enum
- DTOs: add-member, move-member, update-member, move-department
- DepartmentsService: CRUD, tree navigation, member management, move
operations with audit logging
- UI /staff org-chart: drag-and-drop tree visualization with bottom bar,
context menu (create/rename/move/delete), detail panel, user select
dialog, node/connector components
- Create department wizard with type selection and parent picker
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- BotScenario.oneWay flag: prevent revisiting message/input nodes (acts
at executeFromNode level with _visited_nodes array; reset on /start)
- Engine enriches variables with subscriber profile (_first_name,
_last_name, _username, _phone, _source, _chat_id, _subscriber_id,
_bot_id, _club_id) for use in webhook bodies and templates
- stripEmoji() removes 4-byte UTF-8 from names before CRM sync
(Bitrix rejected leads with emoji-only names)
- Bot webhook processor supports application/x-www-form-urlencoded
(Bitrix custom module expects form data, not JSON)
- Step editor: oneWay toggle in scenario header
Fixes: infinite send_to_crm duplication, Bitrix lead creation failures
for users with emoji in Telegram first_name, and referral loop when
user clicks /start from an input node.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add CLUBS_ADMIN role with ClubGroup ownership (1 owner → N clubs)
- UserClubAccess for multi-club staff access with per-club roles
- Provisioning: provisionClubInGroup with license slot validation
- ClubSwitcher component, subdomain-based club routing
- Network staff management across club groups
- RolesGuard: CLUBS_ADMIN inherits CLUB_ADMIN permissions
- Auth: switch-club endpoint, club group ownership validation
- Platform-admin: clubs/licenses/audit filtered by group for CLUBS_ADMIN
- Migrations 00007-00008, documents, platform leads UI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Images:
- Multi-image support: sendPhoto / sendMediaGroup
- Local file upload via multipart for bot-media
- Media upload API endpoint
- Image support in input nodes
Step Editor:
- WYSIWYG contentEditable with formatting toolbar
- Paste from Miro/Docs preserves formatting
- Ctrl+Z undo, local state prevents cursor jumping
- Button drag-and-drop reordering
- Node rename with automatic reference updates
- Progressive delay intervals UI
Referral system:
- Bonus by registered friends (phone), not clicks
- onFriendRegistered notifies referrer
- Existing users get "promo for new users" message
- Invalid/self ref link protection, FK safety
- count_referrals action type
- 7 referral messages configurable in scenario settings
Blocked users:
- Catch blocked errors in engine + delay processor
- Dashboard and analytics stat cards
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Для super_admin clubId=null — не добавляем фильтр WHERE clubId,
чтобы видеть данные всех клубов. Club roles фильтруют по своему clubId.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
clubId=null — платформенные данные, недоступны club_admin.
Вернул строгий фильтр по clubId. Pipelines привязаны к клубу в БД.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
findAll теперь возвращает pipelines с clubId текущего клуба И с
clubId=null (общие, созданные суперадмином). Ранее club_admin не
видел pipelines → фронтенд не загружал сделки.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Удалены отдельные эндпоинты /by-number/:number для deals и users.
Теперь GET /:id определяет формат параметра (число → getByNumber,
UUID → getById) и вызывает соответствующий метод. Фронтенд вызывает
/crm/deals/{number} и /users/{number} напрямую.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- onDealClick передаёт number (string) или UUID как фоллбэк
- deal/[id] загружает по by-number или по UUID в зависимости от формата
- Проставлен number=100 для сделки без номера в БД
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- API: GET /users/by-number/:number + findByNumber в UsersService
- Список: клик по сотруднику → /staff/{number}
- Детальная: загрузка через /users/by-number/{number}
- PATCH/avatar/password операции используют user.id (UUID) внутри
- Синхронизировано в web-platform-admin
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Старый маршрут /crm/[id] теперь редиректит UUID-ссылки (из кеша
браузера или внешних источников) на новый формат /crm/deal/{number}.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- API: GET /crm/deals/by-number/:number для поиска сделки по номеру
- Маршруты: /crm/deal/kanban, /crm/deal/list, /crm/deal/{number}
- /crm редиректит на /crm/deal/kanban
- Карандашик в блоке переводит ВСЕ editable поля в edit mode
- Кнопки «Общий/Мой вид» и «Добавить раздел» — под блоками
- Убран double-click для редактирования полей
- onDealClick передаёт deal.number, API операции через deal.id (UUID)
- Изменения синхронизированы в web-platform-admin
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
API с booking-модулем потребляет ~160MB (через dist/main.js),
ранее nest start тянул ~800MB и PM2 убивал по лимиту 512M.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- GET /users/staff endpoint с поиском по имени
- Fix /staff → /users/staff во всех CRM-компонентах
- Searchable combobox для выбора ответственного (create/edit deal)
- Default assignee = текущий пользователь при создании сделки
- Bitrix-style переключатель стадий (цветные прямоугольники)
- Inline-редактирование карточки сделки (вместо диалога)
- Форма создания дел (активностей) в activity-list
- Loading states для Win/Lose/Delete/Complete (защита от двойных кликов)
- Fix body parser: NestJS API вместо дублирующих express middleware
- Копирование staff-компонентов в platform-admin (аватар, сотрудники)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
— Очистка тестового мусора: дубликаты полей, пайплайнов, причин проигрыша
— Порядковые номера сделок (#N) per-club с @@unique([clubId, number])
— DELETE endpoints для стадий (с переносом сделок) и пайплайнов
— onDelete: Cascade→Restrict для стадий, SetNull для истории
— PipelineManager: полный CRUD воронок и стадий с палитрой цветов
— FieldManager: CRUD кастомных полей с типами и опциями
— EditDealDialog: редактирование сделки (контакт, сумма, компания, ответственный)
— Кастомные поля в форме создания и карточке сделки
— Soft-delete сделок, выбор ответственного, расширенные фильтры
— Поиск по номеру сделки (#42 / 42)
— Исправлены pre-existing тесты: module.guard, themes, auth, reports
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Корневая проблема: validateAndMerge() никогда не вызывалась из
task-manager — документы создавались в worktree, но не мёрджились
в main. Пользователь видел старый контент.
Исправлено:
- task-manager.ts: вызов validateAndMerge() после завершения задачи
- worktree-manager.ts: две стратегии мёрджа:
- Документы (apps/*/document/**): fast path без lint/typecheck/test,
rebase + merge, рестарт только web-platform-admin
- Код: полный путь lint → typecheck → test → rebase → merge
- Rebase вместо ff-only решает расхождение веток при параллельной работе
- Восстановлен документ франшиз (90+ записей из chatbot worktree)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Формализация процесса разработки на основе анализа статьи Zilliz
о провале Claude Code на крупном проекте. Новый документ описывает:
- Формат задачи с Definition of Done до начала работы
- Test-first подход (тесты → код → проверка)
- Послойная декомпозиция (Prisma → API → UI), max 20 файлов/коммит
- Автоматический quality gate (typecheck всех apps + тесты)
- Таблица антипаттернов и метрики качества
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Backend: GET/PATCH /users/:id, POST /users/:id/password, POST /users/:id/avatar
- Prisma: email, roomId, comment поля в User, relation к Room
- Static files: avatars через useStaticAssets, multer upload (5MB, JPEG/PNG/WebP)
- Club-admin: /staff/[id] — аватар, ФИО, email, телефон, роль, департамент, зал, комментарий, смена пароля
- Все панели: sidebar с user info + logout, /profile с role switcher для admin/super_admin
- Ecosystem: dist/main.js вместо nest start для стабильного запуска
- .npmrc: public-hoist-pattern для @types/* (fix pnpm + @types/react)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Документ: сравнительный анализ 11 фитнес-студий Екатеринбурга
(fitness-studios-comparison) — специализация, цены, ИНН, масштаб
- Fix: 3 strict-TS ошибки в CRM (possibly undefined) блокировавшие сборку
- Safety: скрипт typecheck (tsc --noEmit) во всех web-приложениях —
безопасная проверка типов без удаления .next/
- CLAUDE.md: правило «никогда не запускать build на живом сервере»
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Global setup: единый логин всех пользователей перед тестами (без rate limit)
- Playwright проекты: testMatch привязка файлов к проектам (убрал 5x дублирование)
- LP порт: 3004 → 3050 (реальный порт из ecosystem.config)
- Theme тесты: мок API через page.route() (предотвращение 401→logout)
- Web UI тесты: защита response?.status() ?? 200 от undefined
- getCachedTokens(): чтение токенов из файла вместо loginAs в каждом beforeAll
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ссылка от коллеги по прямому URL — допустимо показать страницу «Контент недоступен».
Но ссылка нигде в интерфейсе пользователя не должна появляться: ни в меню, ни в списках, ни в карточках.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- UX-авторизация: недоступные элементы не рендерятся (не «403 / нет прав»)
- Role Switcher: суперадмин переключает роль в header без перелогинивания
- Обновлены: CLAUDE.md, roles-rbac.md, business-logic.md, sprints.md
- Sprint 10: добавлены задачи 48-54 (RoleGate, filterByRole, impersonate API)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Корневая причина: @unique на themeId в Prisma → P2002 ошибка при
повторной установке ранее использованной темы → .catch() скрывал ошибку →
API fetch на перезагрузке возвращал старую тему и перезаписывал localStorage.
Исправления:
- Убран @unique с themeId в PlatformTheme (разрешает аудит-трейл)
- Добавлен @@index([createdAt]) для быстрого findFirst orderBy desc
- handleApply теперь показывает ошибки пользователю вместо .catch(() => {})
- Лендинг: @theme inline → @theme, добавлен ThemeSync компонент
(подтягивает primary color из API и применяет к LP)
- Lint-фиксы в competitor-analysis-skk
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Заменили @theme inline на @theme в globals.css всех 3 приложений —
Tailwind v4 теперь генерирует var() ссылки вместо хардкода значений,
что позволяет runtime-переключение тем через CSS custom properties
- Исправлен дублирующийся React-ключ #42A5F5 в палитре Azure Professional
- Исправлена key-стратегия: key={color.hex} → key={color.name}
- Убраны неиспользуемые импорты в theme-provider (web-admin, web-club-admin)
- Добавлены E2E тесты: применение темы к сайдбару, отсутствие duplicate keys
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Обновлены цветовые схемы 9 тем (WCAG AA, контраст sidebar ≥8:1)
- Заменены 60+ hardcoded цветов на theme-aware классы (text-text, bg-card, text-error и т.д.)
- Создан SVG-логотип MyFitCRM (компонент Logo с вариантами full/icon)
- Ребрендинг FitCRM → MyFitCRM во всех 5 сервисах (17 файлов)
- Добавлена поддержка тем в web-admin и web-club-admin (ThemeProvider, globals.css)
- Обновлена страница «Разработка»: спринты, прогресс, theme-aware компоненты
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>