Справочник событий пользователя (user_events)

Документ описывает все типы событий, регистрируемых через UserEventService, их параметры и структуру JSON-данных. Предназначен для аналитиков для построения запросов к таблице user_events.

Источники событий: проекты stradarium.govern и stradarium.payment.


1. Схема таблицы

Таблица: user_events

Активные колонки

Колонка Тип Ограничения Описание
id VARCHAR(36) PK, NOT NULL Уникальный идентификатор записи (UUID)
username VARCHAR(255) NOT NULL Имя пользователя (email), всегда в нижнем регистре
event VARCHAR(255) NOT NULL Тип события — значение enum UserEventType, хранится как строка
timestamp_tz TIMESTAMPTZ NOT NULL Время регистрации события, устанавливается автоматически при вставке
details_json JSONB nullable Дополнительные параметры события в формате JSON. Может быть null для событий без параметров

Устаревшие колонки

Данные колонки присутствуют в таблице, но не используются текущим кодом. Могут содержать данные для старых записей.

Колонка Тип Описание
timestamp TIMESTAMP WITHOUT TIME ZONE Заменена колонкой timestamp_tz после миграции на поддержку часовых поясов
details VARCHAR Заменена колонкой details_json после миграции на JSONB

Индексы

Единственный индекс — первичный ключ по колонке id. Дополнительных индексов нет. Запросы с фильтрацией по username, event или timestamp_tz выполняют полное сканирование таблицы.

Устаревший формат details

Устаревший метод register(String, UserEventType, String) оборачивал строковый параметр в JSON вида:

{"message": "...", "_version": 1}

В текущем коде этот метод не используется, но в исторических записях могут встречаться строки с ключом _version. Наличие _version: 1 — маркер записи в устаревшем формате.


2. Каталог типов событий

2.1. Аутентификация

SUCCESSFUL_LOGIN

Успешный вход пользователя в личный кабинет.

Ключ Тип Описание
Параметры не передаются, details_json = null

Источник: governcontroller.hello.UsersController#login


UNSUCCESSFUL_LOGIN_ATTEMPT

Неудачная попытка входа (неверные учётные данные).

Ключ Тип Описание
Параметры не передаются, details_json = null

Источник: governcontroller.hello.UsersController#login


SUCCESSFUL_PASSWORD_RECOVERY

Успешное восстановление пароля.

Ключ Тип Описание
message String Описание действия

Источник: governcontroller.hello.UsersController#recover


UNSUCCESSFUL_PASSWORD_RECOVERY

Неудачная попытка восстановления пароля (пользователь не найден).

Ключ Тип Описание
Параметры не передаются, details_json = null

Источник: governcontroller.hello.UsersController#recover


2.2. Просмотр контента

LIST_COURSES

Пользователь запросил список курсов в личном кабинете.

Ключ Тип Описание
message String Описание действия
total Long Количество курсов в результате
productType String Тип продукта (значение enum ProductType)

Источник: governcontroller.hello.CoursesController#list


LIST_PRODUCTS

Пользователь запросил список доступных продуктов.

Ключ Тип Описание
Параметры не передаются, details_json = null

Источник: governcontroller.hello.ProductsController#list


COURSE_DETAILS

Пользователь просмотрел детали курса.

Ключ Тип Описание
message String Описание действия
courseId String Идентификатор курса

Источник: governcontroller.hello.CoursesController#details


MEETING_DETAILS

Пользователь просмотрел детали занятия (лекции).

Ключ Тип Описание
message String Описание действия
meetingId String Идентификатор занятия

Источник: governcontroller.hello.MeetingsController#details


MEETING_VIEW_UPDATE

Пользователь отметил занятие как просмотренное или снял отметку.

Ключ Тип Описание
message String Описание действия
meetingId String Идентификатор занятия
meetingName String Название занятия
viewed Boolean true — отмечено как просмотренное, false — отметка снята

Источник: governservice.MeetingViewService#markViewed, service.MeetingViewService#unmarkViewed


2.3. Профиль пользователя

USER_BIRTHDATE_UPDATE

Пользователь указал свою дату рождения.

Ключ Тип Описание
message String Описание действия
birthdate String Дата рождения (формат строки)

Источник: governservice.ProfileService#updateBirthdate


USER_INTERESTS_UPDATE

Пользователь обновил список своих интересов.

Ключ Тип Описание
message String Описание действия
interests String Список интересов через запятую

Источник: governservice.UserInterestsService#updateUserInterests


2.4. Администрирование

ENTITY_UPDATE

Администратор создал или обновил сущность (пользователь, регистрация на продукт).

Набор ключей зависит от типа сущности:

При обновлении пользователя (UserService#update):

Ключ Тип Описание
message String Описание действия
entityType String Всегда "user"
userId String Идентификатор пользователя
username String Имя пользователя
action String Всегда "update"

При отключении пользователя (UserService#disable):

Ключ Тип Описание
message String Описание действия
entityType String Всегда "user"
userId String Идентификатор пользователя
action String Всегда "disable"

При создании/обновлении регистрации на продукт:

Ключ Тип Описание
message String Описание действия
entityType String Всегда "registration"
registrationId UUID Идентификатор регистрации
username String Имя пользователя
productName String Название продукта
productId UUID Идентификатор продукта

Источники: governservice.UserService#update, service.UserService#disable, service.RegistrationService#saveOrUpdateProductRegistration


ENTITY_COPY

Администратор скопировал курс или продукт.

Набор ключей зависит от типа сущности:

При копировании курса:

Ключ Тип Описание
message String Описание действия
entityType String Всегда "course"
copyCourseId String Идентификатор новой копии
originalCourseId String Идентификатор оригинального курса
originalCourseName String Название оригинального курса

При копировании продукта:

Ключ Тип Описание
message String Описание действия
entityType String Всегда "product"
copyProductId UUID Идентификатор новой копии
originalProductId UUID Идентификатор оригинального продукта
originalProductName String Название оригинального продукта

Источники: governservice.CoursesService#copy, service.ProductsService#copy


GIFT_CERTIFICATE_DOWNLOAD

Скачивание подарочного сертификата.

Ключ Тип Описание
message String Описание действия
productRegistrationId String Идентификатор регистрации на продукт
productId UUID (как String) Идентификатор продукта
productType String Тип продукта (значение enum ProductType)
productName String Название продукта

Источник: governcontroller.admin.CertificateController#certificate


2.5. Уведомления и email

EMAIL

Отправка email-уведомления пользователю. Регистрируется из нескольких мест в обоих проектах.

Ключ Тип Описание
message String Описание действия
userEmail String Email получателя
eventType String Тип уведомления. В большинстве случаев — значение enum UserNotificationEventType (см. ниже). Исключение: в govern UserService#createUser передаётся строка "Доступ в личный кабинет" (константа NEW_USER_REGISTERED_SUBJECT)
productName String Название продукта (присутствует не во всех вызовах)
productId UUID Идентификатор продукта (присутствует не во всех вызовах)
activationCode String Код активации подарочного сертификата (только для подарочных регистраций в payment)
registrationId String Идентификатор регистрации (только для подарочных регистраций в payment)

Возможные значения eventType (enum UserNotificationEventType):

Значение Проект Описание
USER_REGISTRATION govern, payment Регистрация нового пользователя
COURSE_REGISTRATION govern, payment Регистрация на курс
COURSE_INFORMATION govern, payment Информационное письмо по курсу
GIFT_CERTIFICATE govern, payment Подарочный сертификат
PASSWORD_RECOVER govern Восстановление пароля
VETKA_REGISTRATION payment Регистрация на продукт типа «Ветка»

Дополнительные значения enum, не встречающиеся в событиях EMAIL: MEETING_RECORD_LOADED, SCHEDULED, MANUAL.

Источники: - governcontroller.admin.RegistrationsController#mail (2 вызова), service.UserService#createUser - paymentservice.UserService#createUser, service.notify.CourseProductNotifier#notify (3 вызова), service.notify.VetkaProductNotifier#notify (2 вызова)


USER_NOTIFICATION_CREATION

Администратор создал новое уведомление для пользователей.

Ключ Тип Описание
message String Описание действия
notificationId String Идентификатор уведомления
courseId String Идентификатор курса
eventType String Тип события уведомления (значение enum)
notificationType String Тип уведомления (значение enum)

Источник: governcontroller.admin.UserNotificationsController#save


USER_NOTIFICATION_BROADCAST

Массовая рассылка email-уведомлений пользователям курса (по расписанию).

Ключ Тип Описание
message String Описание действия
registrationsAmount Integer Количество регистраций, по которым выполнена рассылка
notificationId String Идентификатор уведомления

Источник: governschedule.UserNotifier#broadcast


STATISTICS_NOTIFICATION

Отправка статистических отчётов в Telegram (по расписанию).

Ключ Тип Описание
message String Описание действия
type String Тип отчёта: "timepad" или "courseRegistrationDaily"
transport String Канал отправки: "telegram"
format String Формат отчёта: "html" или "pdf"

Источники: governschedule.TimepadStatisticsNotifier#executeTelegramMessage, schedule.TimepadStatisticsNotifier#executePdf, schedule.CourseRegistrationStatisticsNotifier#execute


2.6. Платежи и подписки

SUBSCRIPTION

Подписка или отписка пользователя от email-рассылки через Unisender.

Ключ Тип Описание
message String Описание действия
action String Действие: "subscribe" или "exclude"
email String Email пользователя
listId String Идентификатор списка рассылки в Unisender

Источник: paymentservice.SubscriptionService#subscribe, service.SubscriptionService#exclude


DISCOUNT_PERIOD_EXTENDED

Автоматическое продление периода скидки для продукта (по расписанию).

Ключ Тип Описание
message String Описание действия
productId UUID Идентификатор продукта
productType String Тип продукта (значение enum ProductType)
productName String Название продукта
paymentDetailsId String (UUID формат) Идентификатор платёжных данных
discountStrategy String Стратегия скидки (значение enum)
newBestBefore String Новая дата окончания скидки

Источник: governservice.DiscountService#processDaily


3. Источники событий

По проектам

Тип события govern payment
SUCCESSFUL_LOGIN +
UNSUCCESSFUL_LOGIN_ATTEMPT +
SUCCESSFUL_PASSWORD_RECOVERY +
UNSUCCESSFUL_PASSWORD_RECOVERY +
LIST_COURSES +
LIST_PRODUCTS +
COURSE_DETAILS +
MEETING_DETAILS +
MEETING_VIEW_UPDATE +
USER_BIRTHDATE_UPDATE +
USER_INTERESTS_UPDATE +
ENTITY_UPDATE +
ENTITY_COPY +
GIFT_CERTIFICATE_DOWNLOAD +
EMAIL + +
USER_NOTIFICATION_CREATION +
USER_NOTIFICATION_BROADCAST +
STATISTICS_NOTIFICATION +
SUBSCRIPTION +
DISCOUNT_PERIOD_EXTENDED +

По классам

Класс Проект Типы событий Кол-во вызовов
controller.hello.UsersController govern SUCCESSFUL_LOGIN, UNSUCCESSFUL_LOGIN_ATTEMPT, SUCCESSFUL_PASSWORD_RECOVERY, UNSUCCESSFUL_PASSWORD_RECOVERY 4
controller.hello.CoursesController govern LIST_COURSES, COURSE_DETAILS 2
controller.hello.ProductsController govern LIST_PRODUCTS 1
controller.hello.MeetingsController govern MEETING_DETAILS 1
controller.admin.UserNotificationsController govern USER_NOTIFICATION_CREATION 1
controller.admin.CertificateController govern GIFT_CERTIFICATE_DOWNLOAD 1
controller.admin.RegistrationsController govern EMAIL 2
service.UserService govern ENTITY_UPDATE, EMAIL 3
service.ProfileService govern USER_BIRTHDATE_UPDATE 1
service.MeetingViewService govern MEETING_VIEW_UPDATE 2
service.DiscountService govern DISCOUNT_PERIOD_EXTENDED 1
service.CoursesService govern ENTITY_COPY 1
service.ProductsService govern ENTITY_COPY 1
service.UserInterestsService govern USER_INTERESTS_UPDATE 1
service.RegistrationService govern ENTITY_UPDATE 1
schedule.TimepadStatisticsNotifier govern STATISTICS_NOTIFICATION 2
schedule.CourseRegistrationStatisticsNotifier govern STATISTICS_NOTIFICATION 1
schedule.UserNotifier govern USER_NOTIFICATION_BROADCAST 1
service.UserService payment EMAIL 1
service.SubscriptionService payment SUBSCRIPTION 2
service.notify.CourseProductNotifier payment EMAIL 3
service.notify.VetkaProductNotifier payment EMAIL 2

Итого: 35 вызовов (27 в govern, 8 в payment) из 22 классов (18 в govern, 4 в payment).


4. Примеры SQL-запросов

Количество событий по типу за период

SELECT event, COUNT(*) AS cnt
FROM user_events
WHERE timestamp_tz BETWEEN '2025-01-01' AND '2025-02-01'
GROUP BY event
ORDER BY cnt DESC;

Все попытки входа конкретного пользователя

SELECT event, timestamp_tz, details_json
FROM user_events
WHERE username = 'user@example.com'
  AND event IN ('SUCCESSFUL_LOGIN', 'UNSUCCESSFUL_LOGIN_ATTEMPT')
ORDER BY timestamp_tz DESC;

Выборка по JSONB-полю — все письма определённого типа

SELECT username, timestamp_tz, details_json
FROM user_events
WHERE event = 'EMAIL'
  AND details_json->>'eventType' = 'COURSE_REGISTRATION'
ORDER BY timestamp_tz DESC;

Количество отправленных email по дням

SELECT DATE(timestamp_tz) AS day, COUNT(*) AS emails_sent
FROM user_events
WHERE event = 'EMAIL'
GROUP BY DATE(timestamp_tz)
ORDER BY day DESC;

Все подписки и отписки пользователя

SELECT timestamp_tz,
       details_json->>'action' AS action,
       details_json->>'listId' AS list_id
FROM user_events
WHERE event = 'SUBSCRIPTION'
  AND details_json->>'email' = 'user@example.com'
ORDER BY timestamp_tz DESC;

Копирование сущностей — какие курсы и продукты были скопированы

SELECT timestamp_tz,
       username,
       details_json->>'entityType' AS entity_type,
       COALESCE(details_json->>'originalCourseName', details_json->>'originalProductName') AS original_name
FROM user_events
WHERE event = 'ENTITY_COPY'
ORDER BY timestamp_tz DESC;

Поиск записей в устаревшем формате (с маркером _version)

SELECT id, username, event, timestamp_tz, details_json
FROM user_events
WHERE details_json ? '_version'
LIMIT 100;