Разработка сервиса купонов и скидок

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Разработка сервиса купонов и скидок
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1214
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    852
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    823
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    815

Разработка сервиса купонов и скидок

Купоны и скидки — это не просто поле «введите промокод» на странице чекаута. Это система правил, которая управляет ценообразованием: кому, когда, на что и в каком размере предоставлять скидку. Плохо спроектированная система превращается в дыры для злоупотреблений и хаос в аналитике. Хорошо спроектированная — в инструмент точечного маркетинга.

Типология скидок

Прежде чем писать код, нужно зафиксировать модель:

Купоны (промокоды) — пользователь вводит код вручную или ссылка применяет его автоматически. Код уникален или многоразов, привязан к правилу скидки.

Автоматические скидки — применяются без кода при выполнении условий: «все товары категории X со скидкой 15% в пятницу», «скидка 500 руб. от заказа на 3000».

Накопительные программы — скидка зависит от истории покупок клиента (кешбэк, баллы, уровни лояльности).

Скидки по группам — оптовые цены для B2B-клиентов, скидки для сотрудников, партнёрские условия.

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

discount_rules (
  id, name, type,              -- coupon | automatic | loyalty
  discount_type,               -- percentage | fixed_amount | free_shipping | bxgy
  discount_value NUMERIC,
  min_order_amount NUMERIC,
  min_qty INT,
  max_uses INT,                -- NULL = безлимит
  max_uses_per_user INT,
  starts_at TIMESTAMPTZ,
  ends_at TIMESTAMPTZ,
  is_active BOOLEAN,
  stackable BOOLEAN            -- можно ли совмещать с другими скидками
)

discount_conditions (
  id, rule_id,
  condition_type,              -- product | category | tag | user_group | first_order
  condition_operator,          -- in | not_in | gte | lte
  condition_value JSONB
)

coupons (
  id, rule_id, code VARCHAR(32),
  usage_count INT DEFAULT 0,
  is_single_use BOOLEAN
)

coupon_uses (
  id, coupon_id, order_id, user_id, used_at,
  discount_amount NUMERIC      -- сколько было списано в момент применения
)

Разделение discount_rules и coupons позволяет одному правилу иметь много кодов (bulk generation для email-кампаний) или один код с разными ограничениями.

Генерация купонов пачками

Для email-рассылок нужны уникальные коды — по одному на каждого получателя. Генерация:

function generateCouponBatch(int $ruleId, int $count): array {
    $codes = [];
    while (count($codes) < $count) {
        $code = strtoupper(Str::random(8)); // A-Z0-9, 8 символов
        if (!Coupon::where('code', $code)->exists()) {
            $codes[] = ['rule_id' => $ruleId, 'code' => $code, 'is_single_use' => true];
        }
    }
    Coupon::insert($codes);
    return array_column($codes, 'code');
}

Для крупных рассылок (100 000+ кодов) генерируем заранее с проверкой уникальности через индекс, а не через SELECT EXISTS в цикле.

Валидация и применение купона

При вводе кода в чекауте нужно проверить:

  1. Код существует и активен
  2. Дата начала/окончания акции
  3. Лимит использований не превышен (max_uses)
  4. Пользователь не исчерпал лимит (max_uses_per_user)
  5. Сумма корзины >= min_order_amount
  6. Товары в корзине соответствуют условиям (discount_conditions)

Проверка должна происходить атомарно при применении — race condition возможен, если два запроса одновременно применяют последний доступный купон. Решение:

UPDATE coupons
SET usage_count = usage_count + 1
WHERE code = :code
  AND usage_count < max_uses  -- для single-use: usage_count < 1
RETURNING id;
-- если 0 строк — купон уже использован

Обновление через UPDATE ... RETURNING внутри транзакции исключает гонку условий.

Расчёт скидки для корзины

Скидка рассчитывается на сервере, никогда не доверяем клиентскому расчёту. Алгоритм:

1. Получить применённые правила скидок (автоматические + купон)
2. Для каждого правила определить eligible позиции (с учётом условий)
3. Применить скидки в порядке приоритета
4. Если stackable=false — применяем только наибольшую скидку
5. Вернуть breakdown: какая скидка применена к каждой позиции

Breakdown важен для отображения пользователю («-500 руб. по купону SAVE500») и для аналитики.

BxGy (Buy X Get Y) — «купи 3, получи 4-й в подарок». Реализуется отдельным типом правила: при qty >= X добавляем в корзину товар Y с нулевой ценой или уменьшаем цену на N-ой единицы.

Автоматические скидки и приоритеты

Несколько автоматических правил могут срабатывать одновременно. Нужна политика:

  • Первое совпавшее — применяется самое первое правило по приоритету
  • Лучшая скидка — применяется то правило, которое даёт наибольшую выгоду
  • Все совместимые — применяются все правила с stackable=true

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

Аналитика и отчётность

Без аналитики маркетинг летает вслепую. Базовый набор метрик:

Метрика SQL
Использований купона SELECT COUNT(*) FROM coupon_uses WHERE coupon_id = ?
Средний размер скидки SELECT AVG(discount_amount) FROM coupon_uses WHERE ...
Revenue с учётом скидки SUM(order.total) vs SUM(order.total + discount_amount)
Конверсия с купоном vs без Сравнение CR для сессий с applied_coupon и без

Для маркетолога — дашборд с фильтрацией по периоду, типу скидки, каналу (откуда пришёл пользователь с купоном).

Предотвращение злоупотреблений

  • Один купон на заказ — стандартное ограничение, но если разрешён стек, нужна явная конфигурация
  • Верификация email перед применением скидки «для новых клиентов» — иначе создадут 100 аккаунтов
  • Rate limiting на endpoint применения купона — защита от брутфорса кодов
  • Алерты при резком росте использований одного купона — возможна утечка

Личный кабинет маркетолога

Интерфейс для управления акциями должен позволять:

  • Создавать правила скидок с визуальным конструктором условий
  • Генерировать и выгружать CSV пачки купонов
  • Просматривать статистику по каждой акции в реальном времени
  • Деактивировать акцию одним кликом (важно при ошибках в настройках)

Сроки

  • Базовая система купонов (промокод, процент/сумма, дата окончания): 1–2 недели
  • Полноценная система (условия по категориям/товарам, автоматические скидки, BxGy, аналитика, кабинет маркетолога): 3–5 недель
  • Программа лояльности с баллами и уровнями добавляет 3–4 недели