В учетных системах часто требуется настроить динамическое формирование сегментов контрагентов. Типичный бизнес-кейс фитнес-клубов и сервисных компаний — автоматическое включение в программу лояльности только тех клиентов, которые проявляют регулярную активность, например, посещают клуб минимум один раз в месяц на протяжении последних шести месяцев.
Основная сложность здесь заключается в том, что простого условия по общему количеству визитов недостаточно: клиент мог прийти 10 раз за один месяц, а остальные пять месяцев отсутствовать. Разберем по шагам, как правильно спроектировать запрос и настроить схему компоновки данных (СКД) для решения этой задачи при регламентном фоновом расчете сегментов.
Проанализируем структуру хранения информации. Все визиты регистрируются в регистре накопления Посещения. Чтобы определить факт посещения в рамках каждого конкретного месяца, нам не требуется детальная таблица движений — достаточно обратиться к виртуальной таблице оборотов РегистрНакопления.Посещения.Обороты.
Для решения задачи выполним следующие преобразования:
Месяц. В этом случае система автоматически сгруппирует все движения одного клиента внутри каждого календарного месяца в одну сводную запись.Посмотрим на пример запроса. Чтобы система компоновки данных работала оптимально и не передавала лишние строки в память сервера, отсечение клиентов с недостаточным числом месяцев визитов лучше выполнять сразу на уровне СУБД с помощью конструкции ИМЕЮЩИЕ.
ВЫБРАТЬ
ПосещенияОбороты.Контрагент КАК Контрагент,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ПосещенияОбороты.Период) КАК КоличествоМесяцев
ИЗ
РегистрНакопления.Посещения.Обороты(&НачалоПериода, &КонецПериода, Месяц, ) КАК ПосещенияОбороты
ГДЕ
ПосещенияОбороты.КоличествоОборот > 0
СГРУППИРОВАТЬ ПО
ПосещенияОбороты.Контрагент
ИМЕЮЩИЕ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ПосещенияОбороты.Период) >= 6
Обратим внимание на важную деталь: поле ПосещенияОбороты.Период в виртуальной таблице с периодичностью Месяц возвращает дату начала соответствующего месяца. Функция агрегации КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...) подсчитывает, сколько уникальных месяцев клиент посещал занятия.
Выясним причину частой ошибки при настройке вычисляемых дат. Если попытаться записать в поле «Выражение» на вкладке «Параметры» СКД формулу вида ТекущаяДата() - 15552000, система выдаст синтаксическую ошибку. Язык выражений компоновки данных не поддерживает прямое вычитание секунд через математический оператор «минус», в отличие от встроенного языка 1С.
Кроме того, простое вычитание 180 дней смещает границу на произвольный день в середине месяца. Это приводит к тому, что в выборку могут попасть отрезки семи разных календарных месяцев, что исказит результат проверки.
Для корректного смещения дат в выражениях СКД используем встроенную функцию ДобавитьКДате(). На вкладке «Параметры» схемы компоновки данных настроим параметры для анализа шести предшествующих закрытых календарных месяцев:
НачалоПериода в колонке «Выражение» укажем:
НачалоПериода(ДобавитьКДате(ТекущаяДата(), "Месяц", -6), "Месяц")
КонецПериода в колонке «Выражение» зададим:
КонецПериода(ДобавитьКДате(ТекущаяДата(), "Месяц", -1), "Месяц")
При таком подходе отчет всегда будет проверять ровно 6 предшествующих закрытых календарных месяцев, не затрагивая текущий незавершенный месяц, в котором клиент мог просто еще не успеть отметиться.
Рассмотрим специфику механизма сегментов клиентов. Сегменты часто пересчитываются регламентным заданием в фоновом режиме. Фоновое задание не открывает пользовательских форм и не применяет интерактивные настройки отчета.
Если в тексте запроса заключить параметры виртуальной таблицы в фигурные скобки — {(&НачалоПериода)}, {(&КонецПериода)} — СКД сочтет их необязательными. Если модуль формирования сегмента не передаст эти параметры явно в структуру настроек, виртуальная таблица прочитает весь регистр за все время его существования. В результате отбор перестанет работать по датам и выдаст клиентов, набравших 6 визитов за несколько лет.
Именно поэтому параметры виртуальной таблицы в тексте запроса для сегментов следует указывать жестко без фигурных скобок: (&НачалоПериода, &КонецПериода, Месяц, ). В этом случае СКД обязательно подставит значения, рассчитанные в выражениях параметров схемы.
Для завершения настройки выполним следующие действия в схеме компоновки данных:
КоличествоМесяцев проверим свойства: у него не должно быть роли Период, так как это агрегированное числовое значение.Контрагент.Контрагент (поле КоличествоМесяцев можно оставить на время отладки, но для итогового правила сегмента требуется только ссылка на объект).В результате созданное правило динамического сегмента будет стабильно и без участия пользователя отбирать постоянных клиентов клуба при каждом регламентном пересчете.