Skip to main content
Полный перечень полей — в глоссарии промо-баннеров. Промо-баннеры — это часть модуля настроек, которая устроена иначе, чем всё остальное: у баннера вообще нет привязки к компании. Остальные записи настроек ссылаются на компанию (иногда ссылка пуста — тогда запись считается общей платформенной заготовкой), а у баннера такого поля просто нет. Баннер создаётся один раз в административной панели и показывается сотрудникам всех компаний, кроме тех, кому он явно запрещён. Внутри самой записи баннера ведётся журнал: кому и когда его уже показывали.

Модель данных

Промо-баннер — одна запись с содержимым, правилами доступности и журналом показов. Обязательны только заголовок и описание — всё остальное имеет значение по умолчанию или может быть пустым. Порядок сортировки у баннеров не задан.
Журнал показов и чёрный список живут внутри записи баннера, а не в данных компании. Это значит, что действия сотрудников разных компаний (отметки о прочтении) пишутся в одну и ту же строку одной общей таблицы.

Что уходит в интерфейс

Наружу отдаётся только содержательная часть баннера: идентификатор, заголовок, описание, промокод, иконка, ссылка, изображение и анимация. Периодичность показа, журнал показов, чёрный список компаний и флаг активности остаются внутренними — интерфейс их не видит и не может самостоятельно решить, пора ли показывать баннер. Вся логика «показывать или нет» находится на стороне сервера.

Логика выбора баннера

Запрос за баннером доступен только авторизованному пользователю; кроме того, общий контур доступа пропускает к этому разделу лишь сотрудника выбранной компании (либо сотрудника платформы). Сервер берёт две координаты — текущую компанию и текущего пользователя — и подбирает один баннер.

Шаги подбора

  1. Отбираются все включённые баннеры.
  2. Из них исключаются те, в чей чёрный список входит текущая компания.
  3. Оставшиеся перебираются по очереди. Для каждого сервер смотрит в журнал показов: сначала находит раздел текущей компании, внутри него — отметку по текущему пользователю.
  4. Отметки нет — баннер этому человеку в этой компании ещё не показывали, он и возвращается, перебор прекращается.
  5. Отметка есть — сравнивается, сколько времени прошло с последнего показа. Если прошло не меньше, чем указано в периодичности (в часах), баннер возвращается. Если меньше — сервер переходит к следующему баннеру, а не прекращает поиск.
  6. Отметку не удалось разобрать — если сохранённое время записано строкой в неожиданном формате или без часового пояса, баннер считается непоказанным и возвращается.
  7. Если ни один баннер не подошёл, ответ пустой — со статусом «нет содержимого», без тела.
Сравнение идёт по правилу «прошло не меньше заданной периодичности». При периодичности 24 часа баннер повторно доступен ровно через сутки после последнего отмеченного показа. Периодичность 0 (или отрицательная) означает, что баннер подходит всегда, при каждом запросе — нижней границы у этого значения нет.

Что означает «первый подходящий»

Перебор идёт в том порядке, в котором записи отдаёт база: явная сортировка не задана ни в описании данных, ни в запросе. Пока активен один баннер, это не имеет значения. Как только активных баннеров несколько и человек подходит под условия сразу нескольких, предсказать, какой из них покажется, нельзя. Практический способ управлять очерёдностью — держать включённым один баннер за раз.
Подбор не кэшируется и выполняется на каждый запрос: сервер каждый раз выбирает из базы включённые баннеры вместе с их журналами и разбирает журналы в памяти приложения, а не средствами базы. Это допустимо, пока баннеров единицы; при десятках записей с большими журналами запрос станет заметно дороже.

Отметка о прочтении

Сама выдача баннера ничего не записывает. Журнал пополняется только отдельным вызовом, который интерфейс делает по номеру баннера — обычно в момент, когда баннер реально показан пользователю или закрыт им. Что происходит при этом вызове:
  1. Баннер ищется по номеру. Если такого нет — ответ «не найдено».
  2. В журнале берётся (или создаётся) раздел текущей компании.
  3. В нём по ключу текущего пользователя записывается текущее время.
  4. Запись баннера сохраняется целиком.
Ответ пустой, со статусом успеха. Тело запроса при этом не читается и не проверяется — значение имеет только номер баннера в адресе, а компания и пользователь берутся из контекста запроса, поэтому подделать чужую отметку таким вызовом нельзя.
Пока отметка не поставлена, тот же самый баннер будет возвращаться при каждом обращении. Если интерфейс показывает баннер, но не вызывает отметку, пользователь увидит его снова при следующей загрузке страницы.
Отметка не проверяет ни активность баннера, ни чёрный список — она принимает любой существующий номер. Отметить «прочитанным» можно и выключенный баннер, и тот, который данной компании вообще не показывается.

Разделение по компаниям и пользователям

Ключ в журнале двойной: сначала компания, затем пользователь. Отсюда несколько следствий, которые обычно вызывают вопросы:
  • Один и тот же сотрудник, работающий в двух компаниях, увидит баннер дважды — по разу в каждой компании, и отметки будут независимыми.
  • Чёрный список исключает компанию целиком. Скрыть баннер от конкретного человека, не скрывая от его коллег, нельзя.
  • Записи в журнале не удаляются: ни ручной очистки, ни фоновой уборки не предусмотрено. Со временем журнал накапливает по одной отметке на каждую пару «компания — пользователь», которой баннер когда-либо показывали.
  • Чтобы показать баннер заново всем, недостаточно поменять его содержимое: нужно либо очистить журнал вручную, либо завести новый баннер.

Управление в административной панели

Баннеры создаются и отключаются на отдельной странице платформенной админки.
  • Список показывает заголовок и признак активности.
  • Поиск работает по заголовку, описанию, промокоду и ссылке.
  • Фильтр — по признаку активности.
Отдельных удобных инструментов для чёрного списка и журнала показов нет: и то и другое редактируется как обычные поля формы — список номеров компаний и структура отметок соответственно. Править журнал руками рискованно: если время показа окажется строкой в неразборчивом формате или без часового пояса, отметка перестанет учитываться и баннер начнёт показываться снова; а если вместо строки со временем окажется число или будет нарушена структура раздела компании, запрос за баннером завершится ошибкой сервера.
Самый безопасный способ снять баннер с показа — снять флаг активности, а не удалять запись: журнал показов сохранится, и при повторном включении баннер не «выстрелит» заново всем, кто его уже видел.

Как это используется

Типовой сценарий работы интерфейса:
  1. При входе в рабочее пространство фронтенд запрашивает баннер.
  2. Если ответ пустой — ничего не показывается.
  3. Если баннер пришёл — он отрисовывается по полученным полям: заголовок, описание, картинка или анимация, иконка, промокод и ссылка перехода.
  4. Сразу после показа (или при закрытии) интерфейс вызывает отметку о прочтении с номером этого баннера — иначе баннер вернётся снова.
Поскольку сервер отдаёт только содержимое и не сообщает ни периодичность, ни историю показов, интерфейс не должен пытаться самостоятельно решать, когда баннер уместен: единственный источник этого решения — запрос за баннером.

Подводные камни

  • Показ сам по себе ничего не записывает. Если интерфейс не вызовет отдельную отметку о прочтении, один и тот же баннер будет возвращаться при каждом запросе — пользователь увидит его снова и снова.
  • Порядок перебора баннеров не задан. Сортировка не указана ни в описании данных, ни в запросе, поэтому при нескольких подходящих баннерах выбор зависит от того, в каком порядке их вернёт база.
  • Отметки могут затирать друг друга. Отметка о прочтении читает журнал, дописывает в него запись и сохраняет баннер целиком, поэтому одновременные отметки от разных пользователей — в том числе из разных компаний — могут потерять часть данных.
  • Отметка о прочтении принимает любой существующий номер баннера: ни активность, ни чёрный список компании при этом не проверяются, а тело запроса не читается и не валидируется.
  • Если сохранённое время последнего показа записано строкой в неразборчивом формате или без часового пояса, баннер считается непоказанным и выдаётся снова — такая ошибка в журнале приводит к бесконечному показу, а не к его прекращению.
  • Если журнал испорчен грубее — вместо строки со временем записано число либо раздел компании перестал быть структурой «ключ-значение», — запрос за баннером завершится ошибкой сервера, а не мягким пропуском записи.
  • Периодичность показа не ограничена снизу: значение 0 или отрицательное означает, что баннер подходит при каждом запросе.
  • Чёрный список исключает компанию целиком; скрыть баннер от отдельного пользователя внутри компании невозможно.
  • Изображение и анимация складываются в одну и ту же папку файлового хранилища, причём анимация загружается как произвольный файл без проверки того, что это картинка.
  • Когда показывать нечего, ответ приходит со статусом «нет содержимого» и пустым телом, а не пустым объектом — интерфейс должен корректно обрабатывать этот статус.
  • Журнал показов растёт бесконечно: отметки по каждой паре «компания — пользователь» никогда не удаляются и хранятся внутри самой записи баннера; ни фоновой уборки, ни отдельного инструмента очистки нет.
  • Один и тот же человек, работающий в двух компаниях, получает баннер отдельно в каждой из них, потому что ключ журнала составной — сначала компания, затем пользователь.
  • Наружу не отдаются периодичность, журнал показов, чёрный список и флаг активности, поэтому интерфейс не может самостоятельно решить, пора ли показывать баннер.
  • Подбор баннера не кэшируется и на каждый запрос вычитывает включённые баннеры с их журналами, разбирая их в памяти приложения, а не в базе.
  • В административной панели нет отдельных инструментов для чёрного списка и журнала показов: список содержит только заголовок и признак активности, фильтр — только по активности, а обе структуры правятся как обычные поля формы.
  • Страница баннеров, в отличие от соседней страницы настроек таблиц, не ограничена дополнительно правами суперпользователя — редактировать баннеры может любой сотрудник платформы с обычными правами админки на эту запись.
  • У промо-баннера, в отличие от остальных настроек, нет поля компании вовсе; у прочих записей раздела ссылка на компанию есть и может быть пустой — это означает общую платформенную заготовку.

Связанные страницы

Глоссарий: Промо-баннеры

Полный перечень полей баннера, журнала показов и правил подбора.

Настройки компании

Обзорная страница модуля: из чего состоят настройки компании и как они связаны между собой.

Реестр настроек компании

Полный перечень параметров компании: что можно включить или выключить, какие значения стоят по умолчанию и как настройки читаются и сохраняются.

Хранение и кэш настроек

Как значение настройки попадает в базу, как оно кэшируется по компаниям и почему изменение настройки сбрасывает кэш целиком.

Дополнительные поля

Собственные поля компании для клиентов, инвентаря, аренд и других справочников: типы, обязательность, отображение в таблице и фильтрах.

Переименование сущностей

Как компания меняет названия разделов и статусов под свою нишу, включая формы слова по падежам и числам.

Настройки таблиц

Сохранённый состав, порядок и ширина колонок для таблиц интерфейса — отдельно по каждой таблице компании.

Сквозная автонумерация

Общий счётчик компании, из которого берутся номера клиентов, артикулы создаваемых единиц инвентаря и номера документов.

Настройки в админ-панели

Служебный экран платформы для просмотра и правки настроек конкретной компании со сбросом значений к умолчанию.