Что делает эта часть модуля
Здесь живёт «ядро» уведомлений: как хранится само событие, как хранится персональное состояние каждого получателя и что происходит автоматически в момент создания уведомления — подбор подходящих сотрудников и рассылка сообщения по трём каналам (веб, мобильный push, Telegram). Проще говоря: одно событие в системе (новый заказ, задача, документ) превращается в одно Уведомление, а система сама решает, кому из сотрудников и по каким каналам его показать.Модель данных
Уведомление
Одна запись — одно событие компании. Уведомление принадлежит компании, знает, к какому объекту системы оно относится, и несёт текст сообщения плюс маршрутную информацию.Пара «Тип объекта» + «ID объекта» — это адрес связанной сущности. По ним строятся кликабельные ссылки в Telegram и переходы в приложениях. «Доп. данные» дополняют этот адрес нестандартными случаями (например, для задачи по лиду ссылка ведёт не на объект задачи, а на лид, чей идентификатор лежит именно в доп. данных).
Уведомление пользователя
Одно Уведомление может касаться нескольких сотрудников, но состояние «прочитано / в архиве» у каждого своё. Для этого на каждого получателя заводится отдельная персональная запись, привязанная к родительскому уведомлению.Комбинация «компания + получатель + уведомление» уникальна — у одного сотрудника не может быть двух персональных состояний по одному и тому же уведомлению. В самой записи хранится только признак архивации: отдельного булева-флага «прочитано» здесь нет. Судя по устройству модели, признаком прочтения служит само наличие персональной записи (и её время создания).
Веер доставки: что происходит при создании
Как только уведомление сохранено впервые, автоматически запускается веер доставки. При последующих изменениях того же уведомления веер не срабатывает — только при создании. Логика по шагам:- Определяется компания. Веер берёт текущую компанию из контекста запроса. Если компания не определена (например, вызов идёт вне контекста компании), доставка молча прекращается — ничего не рассылается.
- Собирается список штатных сотрудников этой компании. Берётся перечень пользователей, у которых признак сотрудника выдан именно в этой компании. Участник другой компании в список не попадает, даже если сотрудником он числится где-то ещё. Список кэшируется отдельно на каждую компанию и переиспользуется между уведомлениями, чтобы не пересчитывать его каждый раз.
- Фильтрация по матрице доступа. Из настроек доступа к уведомлениям отбираются строки, которые одновременно: относятся к этой компании, к теме данного уведомления, помечены как включённые и принадлежат сотрудникам из собранного списка. Если у уведомления задан явный список целевых получателей, фильтр дополнительно сужается только до них.
- Разделение по каналам. Для каждого из трёх каналов из отобранных строк доступа берутся только те сотрудники, у кого этот конкретный канал включён. Так один и тот же человек может получать уведомление в вебе, но не в Telegram — всё зависит от его персональной матрицы доступа.
- Отправка. По каждому каналу, который разрешён в самом уведомлении, вызывается свой помощник доставки — но только для «своего» списка сотрудников.
Условия по каждому каналу
Канал участвует в рассылке, только если он одновременно (а) входит в разрешённые каналы самого уведомления и (б) включён у конкретного сотрудника в его матрице доступа. Плюс к этому у веба и Telegram есть свои технические предусловия.
Как формируется сообщение в Telegram
Текст для Telegram собирается по-разному в зависимости от типа объекта, и в него подставляется ссылка на веб-кабинет компании. Адрес кабинета берётся из настроек компании (служебный префикс из адреса убирается); если адрес не задан, используется адрес по умолчанию.- Заказ — текст выделяется жирным, ниже добавляется ссылка на страницу заказа.
- Задача по лиду — текст предваряется подписью «Новая задача», ссылка ведёт на лид, идентификатор которого берётся из доп. данных. Если для такой задачи в доп. данных нет идентификатора лида, уведомление в Telegram не отправляется вовсе.
- Задача по обслуживанию — подпись «Новая задача ТОО» и ссылка на страницу обслуживания.
- Документ — текст жирным и ссылка на страницу документа.
Одноразовые уведомления («захват»)
Отдельный режим — уведомление с одноразовым захватом. Его смысл: событие показывается всем подходящим сотрудникам, но «забрать» (обработать) его должен только один. Когда кто-то его захватывает, фиксируется, кто именно и в какой момент это сделал. Для веба есть отдельный механизм отзыва: после захвата всем остальным веб-клиентам отправляется команда убрать это уведомление из списка, а у того, кто захватил, оно остаётся помеченным. Отзыв работает только при настроенном доступе к сервису Ably.Как это используется
Эта часть — фундамент всего модуля уведомлений. Прикладной код не рассылает сообщения вручную: он просто создаёт Уведомление с нужными текстом, темой, адресом объекта и (при необходимости) явным списком получателей — а веер доставки сам подбирает сотрудников по матрице доступа и раскладывает сообщение по каналам. Фоновые задачи создания, дозаписи и группировки уведомлений, а также детали каждого канала доставки и настройка матрицы доступа описаны в соседних разделах модуля.Особенности поведения
- Для задачи по лиду обязателен идентификатор лида в доп. данных: без него уведомление в Telegram не отправляется совсем (ссылку построить не из чего).
- Веб-канал участвует в рассылке только при настроенных доступах к сервису Ably, а Telegram — только при настроенном боте; иначе соответствующий канал тихо пропускается.
- Отзыв одноразового уведомления из веба работает только при настроенном доступе к Ably; без него остальные вкладки не узнают о захвате и уведомление у них останется в списке.
- Явный список целевых получателей только сужает аудиторию поверх матрицы доступа, но не обходит её: указанный сотрудник всё равно должен иметь включённый доступ по теме и каналу, иначе сообщения не получит.
- Признак сотрудника учитывается по конкретной компании, а не «в целом по системе»: клиент вашей компании, который в другой компании работает сотрудником, внутренних уведомлений вашей компании не получит.
- В персональной записи получателя нет отдельного флага «прочитано» — хранится только признак архивации; признаком прочтения, по-видимому, служит само наличие такой записи и её время создания.
- Разбивка по каналам идёт по индивидуальному признаку канала в строках матрицы доступа, поэтому один и тот же сотрудник может получать уведомление по одному каналу и не получать по другому.
Связанные страницы
Глоссарий: Модель и веер доставки
Полный перечень полей ядра уведомлений, типов и терминов веера доставки.
Уведомления (доставка и доступ)
Обзорная страница модуля: как устроены создание, доставка и доступ к уведомлениям.
Создание и группировка
Фоновые задачи создания уведомлений: одиночные, дозапись по объекту и группировка в окне времени с накоплением счётчика и сообщений.
Каналы доставки
Транспортные задачи и сервис: веб-доставка через Ably, мобильный push с деактивацией мёртвых токенов и Telegram-рассылка.
Чтение, архивация и список
Списки, счётчик непрочитанных, отметка прочтения и архивация, включая логику «забирает первый» для одноразовых уведомлений.
Push-токены устройств
Регистрация и отписка push-токенов мобильных устройств сотрудника с уникальностью по устройству и типом платформы.
Привязка Telegram
Привязка и отвязка аккаунта сотрудника к Telegram-боту по одноразовому коду верификации.
Доступ и настройки
Матрица доступа «источник × тема» на сотрудника, перечни источников и тем, а также массовое редактирование настроек.