# Улучшение системы оповещений **Дата:** 2026-05-18 ## Проблемы 1. **Дублирование кода входа в Telegram** — настройка `authCodeDuplicate` не работает, т.к. `resolveAuthCodeTargets` импортирован, но не вызывается в диспетчере уведомлений. 2. **Двойное уведомление о новом заказе** — `order:created` и `order:created:admin` оба проходят через `resolveAdminNotificationTargets('order:created')`, что даёт 2 одинаковых оповещения админу. 3. **Пропущен `PAID` в русских лейблах статусов** — в `telegram-templates.js` и `email-templates.js` нет ключа `PAID`. 4. **Текст оповещений слишком краткий** — нет подсказок о следующих действиях для пользователя и админа. ## Решения ### 1. Дублирование кода входа (гибридный подход) - Письмо с кодом входа уходит **мгновенно** через прямой вызов `sendLoginCodeEmail` в `issueEmailCode` (без изменений). - В `dispatchNotification` для `AUTH_CODE_REQUESTED` используется отдельный резолвер `resolveAuthCodeTargets` вместо общих `resolveUserNotificationTargets` / `resolveAdminNotificationTargets`. - `resolveAuthCodeTargets` уже правильно реализован: отправляет email пользователю, а Telegram — только если `payload.isAdmin === true` и включена настройка `authCodeDuplicate`. **Изменяемые файлы:** - `server/src/index.js` — добавить условие в `dispatchNotification` для `AUTH_CODE_REQUESTED` ### 2. Двойное уведомление о новом заказе - Удалить `ORDER_CREATED` из `adminEventFieldMap` в `preferences.js`. - Админ получает уведомление о новом заказе только через событие `'order:created:admin'`. **Изменяемые файлы:** - `server/src/lib/notifications/preferences.js` — удалить `[ORDER_CREATED]: "newOrder"` из `adminEventFieldMap` ### 3. Добавление PAID в лейблы статусов - `PAID: 'Оплачен'` в `telegram-templates.js` и `email-templates.js`. **Изменяемые файлы:** - `server/src/lib/notifications/templates/telegram-templates.js` - `server/src/lib/notifications/templates/email-templates.js` ### 4. Расширение текста оповещений #### 4a. Пользователь: Заказ создан В событие `ORDER_CREATED` передаётся `deliveryType`: - `deliveryType === 'pickup'` → *"Ваш заказ №XXX успешно создан. Товаров: X | Сумма: XXX ₽. Ожидает оплаты."* - `deliveryType === 'delivery'` → *"Ваш заказ №XXX успешно создан. Товаров: X | Сумма: XXX ₽. Оплата будет доступна после уточнения стоимости доставки."* **Изменяемые файлы:** - `server/src/routes/user-orders.js` — добавить `deliveryType` в payload события `ORDER_CREATED` - `server/src/lib/notifications/templates/telegram-templates.js` — обновить `renderOrderCreatedTg` - `server/src/lib/notifications/templates/email-templates.js` — обновить `renderOrderCreatedEmail` #### 4b. Новое событие: deliveryFeeAdjusted При корректировке стоимости доставки (`PATCH /api/admin/orders/:id/delivery-fee`) отправлять пользователю уведомление: - Текст: *"Стоимость доставки скорректирована. Ожидает оплаты."* Событие: `'order:deliveryFeeAdjusted'` — добавляется в `NOTIFICATION_EVENTS`. **Изменяемые файлы:** - `shared/constants/notification-events.js` — добавить `DELIVERY_FEE_ADJUSTED` - `shared/constants/notification-events.d.ts` — добавить `'order:deliveryFeeAdjusted'` - `server/src/lib/notifications/preferences.js` — добавить `DELIVERY_FEE_ADJUSTED` в `userEventFieldMap` - `server/src/routes/api/admin-orders.js` — emit `DELIVERY_FEE_ADJUSTED` после обновления - `server/src/routes/user/notifications.js` — добавить поле в API - `client/src/pages/me/ui/sections/NotificationsPage.tsx` — добавить переключатель - `server/src/lib/notifications/templates/telegram-templates.js` — новый рендерер - `server/src/lib/notifications/templates/email-templates.js` — новый рендерер - `server/src/lib/notifications/channels/telegram-channel.js` — зарегистрировать шаблон - `server/src/lib/notifications/channels/email-channel.js` — зарегистрировать шаблон - `server/src/index.js` — подписаться на событие Также нужно добавить миграцию Prisma для поля `deliveryFeeAdjusted` в `NotificationPreference`. #### 4c. Админ: Новый заказ В событие `'order:created:admin'` передаётся `deliveryType`: - `deliveryType === 'delivery'` → добавить *"Скорректируйте стоимость доставки"* - `deliveryType === 'pickup'` → как сейчас **Изменяемые файлы:** - `server/src/routes/user-orders.js` — добавить `deliveryType` в payload `'order:created:admin'` - `server/src/lib/notifications/templates/telegram-templates.js` — обновить `renderAdminOrderCreatedTg` - `server/src/lib/notifications/templates/email-templates.js` — обновить `renderAdminOrderCreatedEmail` ## Схема данных ### NotificationPreference (добавить поле) ```prisma model NotificationPreference { id String @id @default(cuid()) userId String @unique globalEnabled Boolean @default(true) orderCreated Boolean @default(true) orderStatusChanged Boolean @default(true) orderMessageReceived Boolean @default(true) paymentStatusChanged Boolean @default(true) deliveryFeeAdjusted Boolean @default(true) // НОВОЕ createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } ``` ## Обработка ошибок - Если при delivery-fee эмите не указан `userId` — событие не отправляется. - Если рендерер не найден для события — `telegram-channel.js` и `email-channel.js` логируют warning (существующее поведение). ## Тестирование - `server/src/lib/notifications/__tests__/preferences.test.js` — добавить тест для `resolveAuthCodeTargets` в контексте `dispatchNotification` - Проверить, что после удаления `ORDER_CREATED` из `adminEventFieldMap` админ не получает дубликат