Ограничения и лимиты акции¶
Ограничения отвечают на вопрос «не исчерпана ли норма акции»: сколько денег она может раздать, сколько раз сработать для всей базы и для одного клиента и сколько баллов дать за одно событие. Все четыре ограничения необязательны: акция без ограничений применяется ко всем подходящим событиям, а незаданное ограничение не означает нулевой лимит.
Ограничения задаются на вкладке «Ограничения» формы акции (см. «Создание и редактирование акции») и сохраняются тем же запросом, что и остальные поля акции.
Изменение 26.3.0: сумма чека — условие, а не ограничение
Диапазон суммы чека больше не входит в ограничения: это критерий «Сумма чека» на вкладке
«Условия», доступный в обеих зонах, — запись criteria с кодом check-amount вместо ключей
params.minCheckMinor/maxCheckMinor. См. «Условия акции».
Четыре ограничения¶
Вкладка сгруппирована по тому, на что смотрит счётчик. Каждое ограничение — фраза с чекбоксом, поля стоят внутри фразы на месте величины. Поля снятого ограничения остаются на месте недоступными и хранят введённое, но на сервер не уходят.
| Группа | Ограничение (фраза в форме) | Поле API | Единица | Что ограничивает |
|---|---|---|---|---|
| «На всю акцию» | «Акция может раздать не более [N] [₽ / баллов]» — бюджет акции | budgetMinor |
деньги, минорные единицы | Сколько денег акция может раздать за всё время линии версий |
| «На всю акцию» | «Всего акция сработает не более [N] раз» — общий лимит участий | totalLimit |
разы | Сколько раз акция срабатывает на всю базу за всё время линии версий |
| «На одного клиента» | «Один клиент может участвовать не чаще [N] раз [период]» — лимит участий на клиента | participationLimit |
разы + окно | Сколько раз акция срабатывает для одного клиента в окне |
| «На одно начисление» | «За одну покупку начисляем не более [N] баллов» — максимальное количество баллов | maxBonusMinor |
баллы, минорные единицы | Потолок начисления по одному событию |
Пояснения групп в форме: «Счёт общий для всех версий акции: создание новой версии не обнуляет израсходованное» (на всю акцию), «Сколько раз один клиент может получить бонус по этой акции. Возврат покупки использованное участие не возвращает: если клиент купил и вернул, попытка всё равно потрачена» (на одного клиента), «Сколько баллов максимум можно получить за одну покупку» (на одно начисление).
В форме деньги и баллы вводятся в целых рублях и баллах — на сервер они уходят умноженными на 100; счётчики участий уходят как есть.
Бюджет акции¶
- Задаётся в деньгах базовой валюты программы (в интерфейсе — ₽). Каждое начисление пересчитывается в деньги по курсу валюты баллов программы на момент начисления; курс сохраняется в операции, поэтому смена курса уже израсходованное не переоценивает.
- Бюджет можно ввести и в баллах: рядом с суммой — выбор «₽» или «баллов», под фразой — подсказка «по текущему курсу ≈ N баллов» (или «≈ N ₽»). Введённые баллы при сохранении пересчитываются в деньги по текущему курсу, и сохраняется денежная сумма — от последующей смены курса она не меняется. Если курса нет (или нет права на чтение справочника валют), вариант «баллов» недоступен; если курс пропал уже после выбора баллов, форма не сохраняется: «Нет текущего курса баллов — укажите бюджет в рублях».
- Для подсказки и пересчёта форма берёт курс первой включённой валюты баллов, выраженный в рублях. Если валют баллов несколько, он может не совпасть с курсом валюты баллов программы, по которому сервер считает расход, — тогда бюджет надёжнее задавать в рублях.
- Расход считается по журналу операций: начисления по акции минус их сторно. Сторно — в том числе при возврате покупки по чеку — возвращает деньги в бюджет.
- Акция применяется, только если остатка хватает на полное начисление. Частичного начисления «до остатка» нет: остаток, которого не хватает ни на одно начисление, остаётся неизрасходованным.
- Расход считается по всей линии версий: новая версия не обнуляет бюджет. У копии («Сохранить как») бюджет свой.
- Параллельные покупки не могут перерасходовать бюджет: проверка и начисление по одной акции выполняются последовательно.
- Бюджет не принимается, если курс валюты баллов равен нулю (
422 currency_zero_rate) или выражен не в базовой валюте (422 currency_rate_currency_invalid). Пока есть незавершённые акции с бюджетом вне архива, курс валюты баллов нельзя обнулить, а базовую валюту — сменить (409 base_currency_used_by_budget), см. «Справочник валют».
В форме, пока бюджет включён, в правой колонке — секция «Расход бюджета». На странице акции под
бюджетом показывается полоса «Израсходовано N из M ₽»; от 80 % она предупреждающая, при полном
расходе — «Бюджет исчерпан: …». В ответе API расход — поле budgetSpentMinor.
Изменение 26.3.0: budgetMinor — деньги
Тип поля не изменился, изменилась трактовка: раньше бюджет считался в баллах и был справочным
полем. Заведённые значения пересчитаны; при курсе баллов 1 : 1 численно они не изменились.
Курс берётся у валюты баллов программы — настройка «Валюта баллов» (points.currency) в
«Операционной конфигурации»: после её смены бюджеты считаются по
курсу новой валюты. Отдельная настройка loyalty.promotion.budget.point-currency больше не
читается — если она задана на контуре, её можно убрать.
Общий лимит участий¶
Сколько раз акция срабатывает на всю базу клиентов за всё время линии версий (целое больше нуля).
Исчерпанная акция перестаёт применяться ко всем, включая тех, кто ещё не участвовал. В ответе API —
totalUsed (участия по линии версий) и versionUsed (по этой версии).
Лимит участий на клиента¶
Число участий (целое больше нуля) и период, в котором они считаются. Подсказка у выбора периода объясняет разницу: календарный период обнуляется на границе у всех разом, а «за последние N дней» отсчитывается от покупки каждого клиента.
| Период в форме | Поля API | Как считается |
|---|---|---|
| «За всё время акции» | period: "TOTAL" |
Все участия клиента в линии версий акции |
| «По календарю» — «в день», «в неделю», «в месяц» | periodMode: "CALENDAR", period, periodAmount: 1 |
Окна идут подряд от начала периода акции, выровненные по границе единицы: день — с полуночи, неделя — с понедельника, месяц — с 1-го числа. Участие ровно на границе относится к новому окну. Счёт обнуляется у всех клиентов одновременно. Месяц — календарный, а не тридцать суток |
| «За последние N дней» | periodMode: "SLIDING", period: "DAY", periodAmount ≥ 2 |
Участия за последние N дней до момента покупки; участие ровно N дней назад уже не считается. Лимит возвращается по одному участию, а не сразу целиком |
period — DAY, WEEK, MONTH или TOTAL. У режима «за всё время» длительность и режим не
задаются. Пустые periodAmount/periodMode у ранее заведённых лимитов читаются как 1 и
CALENDAR («По календарю»). Календарные границы считаются в часовом поясе программы
(program.timezone), а не сервера.
Изменение 26.3.0: лимит участий принимает только окна, которые показывает форма
Запись лимита — в теле акции, через PUT /participation-limit и импортом — отклоняет единицу
«год» (422 invalid_period), календарный период из нескольких единиц и «за последние N» не в
днях или короче 2 дней (422 invalid_participation_window). Раньше такие окна сохранялись, а
форма показывала их неверно и при сохранении акции молча переписывала. Уже сохранённые окна
читаются и считаются как прежде.
- Участия считаются по всей линии версий акции — новая версия не открывает обход лимита.
- Сторно участие не возвращает: иначе цикл «купил — вернул — купил» обходил бы лимит (в отличие от бюджета — асимметрия намеренная).
- Участие фиксируется при каждом применении акции, даже если лимита у неё нет: лимит, добавленный в новой версии, учтёт и прежние участия.
- Новая версия и копия акции сохраняют лимит участий.
Для совместимости сохранён отдельный ресурс лимита:
| Метод и путь | Право | Назначение |
|---|---|---|
GET /v1/promotions/{promotionId}/participation-limit |
LOYALTY_PROMOTION_READ |
Лимит участий акции (404 participation_limit_not_found, если не задан) |
PUT /v1/promotions/{promotionId}/participation-limit |
LOYALTY_PROMOTION_WRITE |
Задать лимит |
DELETE /v1/promotions/{promotionId}/participation-limit |
LOYALTY_PROMOTION_WRITE |
Снять лимит |
Ресурс подчиняется тому же правилу правки, что и акция (409 promotion_not_editable), и так же
сбрасывает согласование запуска при фактическом изменении. Форма им не пользуется — лимит уходит в
теле акции.
Максимальное количество баллов¶
Потолок бонуса по одному событию: если расчёт по механике дал больше, начисляется значение потолка. Целое больше нуля. Задаётся только этим ограничением акции — отдельного параметра механики для потолка больше нет (см. «Механики начисления»).
Порядок проверок при покупке¶
Все проверки выполняются до арбитража: акция, выбывшая по ограничению, не занимает место в арбитраже и не блокирует совместимые акции (например, исчерпавшая бюджет эксклюзивная акция не мешает остальным).
flowchart LR
A[Период] --> B[Условия акции: товары, место, сумма чека]
B --> D[Клиент: статус, уровень, баланс, условия аудитории]
D --> E[Расчёт бонуса]
E --> F[Максимум баллов]
F --> G[Лимит участий на клиента]
G --> H[Общий лимит]
H --> I[Бюджет]
I --> J[Арбитраж]
Бюджет проверяется последним, потому что сравнивать с остатком можно только уже рассчитанный бонус.
Правка ограничений¶
Ограничения меняются вместе с акцией и по тем же правилам: на месте — у черновика, запланированной и не применявшейся паузы. У применявшейся акции ограничения меняются новой версией, при этом израсходованный бюджет и участия переходят к ней (счётчики привязаны к линии версий). Подробнее — «Создание и редактирование акции».
Отсутствующее ограничение снимается
Тело акции — полная замена: запрос без budgetMinor, maxBonusMinor, totalLimit или
participationLimit снимает соответствующее ограничение.
Ошибки¶
У ошибки под полем — короткий текст («Должно быть больше нуля», «Укажите длительность», «Слишком большое число»), полный раскрывается по значку ⓘ рядом.
| Код | HTTP | Когда возникает | Текст в форме |
|---|---|---|---|
invalid_budget |
422 | Бюджет не больше нуля | «Бюджет должен быть больше нуля» |
invalid_max_bonus |
422 | Максимум баллов не больше нуля | «Максимальное количество баллов должно быть больше нуля» |
invalid_max_count |
422 | Число участий не больше нуля | «Количество участий должно быть больше нуля» |
invalid_period |
422 | Неизвестная единица окна или единица «год» | «Выберите период лимита участий» |
invalid_participation_window |
422 | Не задан период, режим без длительности, длительность не больше нуля, неизвестный режим, длительность у окна «за всё время», календарный период из нескольких единиц, «за последние N» не в днях или короче 2 дней | «Укажите длительность периода: количество и единицу» |
invalid_total_limit |
422 | Общий лимит не больше нуля | «Общий лимит участий должен быть больше нуля» |
currency_zero_rate |
422 | Бюджет при нулевом курсе валюты баллов | — |
currency_rate_currency_invalid |
422 | Бюджет при курсе, выраженном не в базовой валюте | — |
promotion_not_editable |
409 | Правка применявшейся или работающей акции | «Акция уже запущена или применялась — изменить её нельзя. Создайте новую версию акции.» |
Форма проверяет и то, что до сервера не доходит: для «За последние N дней» — «Число дней — не меньше 2»; счётчики участий ограничены сверху значением 2 147 483 647 («Значение не может быть больше …»).