Как запретить покупку более одного товара в 1С-Битрикс

Просмотров: 8793

Иногда бизнес-логика проекта требует ограничить пользователя покупкой ровно одного товара. Сохранив удобство для пользователя и менеджера по отбработке заказов

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

При этом важно сохранить возможность «передумать»:

  • пользователь может добавить товар в корзину;
  • затем выбрать другой товар, не оформляя заказ;
  • в корзине в итоге должен остаться только последний добавленный товар.

Удалять товар вручную из корзины и добавлять новый — неудобно. Поэтому логика была реализована автоматически.

Логика решения: удаление и добавление товаров в корзине

Пользователь добавляет товары в каталогe без ограничений. Когда переходит на страницу корзины, мы проверяем её содержимое.

Если в корзине больше одного товара: все товары удаляются, обратно добавляется только последний добавленный товар.

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

В шаблоне корзины (sale.basket.basket) добавляем файл result_modifier.php (если его нет — создаём).

if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die();

/** 
 * Модификатор корзины - оставляет в корзине только последний добавленный товар
 *
 * Логика работы:
 * 1. Если в корзине больше одного товара - удаляет все и оставляет только последний
 * 2. После очистки делает перезагрузку страницы для обновления интерфейса
 * 3. После перезагрузки скрипт не выполняется повторно благодаря GET-параметру
 */

// Проверяем, не пришли ли мы после редиректа
// Если параметр basket_updated=Y присутствует - значит корзина уже была обработана
$isAfterRedirect = isset($_GET['basket_updated']) && $_GET['basket_updated'] === 'Y';

// Выполняем операции только при первой загрузке страницы (не после редиректа)
if (!$isAfterRedirect) {

    // Получаем все товары из текущей корзины пользователя
    $arBasketItems = array();
    $dbBasketItems = CSaleBasket::GetList(
        array("ID" => "ASC"), // Сортировка по ID (первыми будут старые товары)
        array(
            "FUSER_ID" => CSaleBasket::GetBasketUserID(), // ID текущего пользователя корзины
            "LID" => SITE_ID, // ID текущего сайта
            "ORDER_ID" => "NULL" // Только товары не привязанные к заказу
        ),
        false,
        false,
        array("PRODUCT_ID", 'ID') // Выбираем только ID продукта и ID записи корзины
    );

    // Подсчитываем количество товаров и запоминаем ID последнего товара
    $basketCount = 0;
    while ($arItems = $dbBasketItems->Fetch()) {
        // Каждая итерация перезаписывает - в итоге останется последний
        $lastAddedItem = $arItems['PRODUCT_ID'];
        $basketCount++; // Счетчик товаров в корзине
    }

    // Выполняем операции только если в корзине больше одного товара
    // Если товар один - ничего не делаем
    if ($basketCount > 1) {

        // Удаляем ВСЕ товары из корзины текущего пользователя
        CSaleBasket::DeleteAll(CSaleBasket::GetBasketUserID());

        // Формируем данные для добавления последнего товара обратно в корзину
        $fields = [
            'PRODUCT_ID' => $lastAddedItem, // ID последнего добавленного товара
            'QUANTITY' => 1, // Количество = 1 шт
        ];

        // Добавляем последний товар обратно в корзину
        $r = Bitrix\Catalog\Product\Basket::addProduct($fields);

        // Формируем URL с GET-параметром для предотвращения повторной обработки
        // Этот параметр говорит скрипту, что корзина уже была обработана
        $redirectUrl = $APPLICATION->GetCurPage() . '?basket_updated=Y';

        // Делаем перезагрузку страницы для обновления интерфейса корзины
        // После перезагрузки скрипт увидит параметр basket_updated=Y и не будет выполняться
        LocalRedirect($redirectUrl);
    }
}

Пояснения к реализации

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

После изменений выполняем редирект, так как: товары удаляются программно. Стандартный интерфейс корзины не успевает корректно перерисоваться.

GET-параметр basket_updated=Y предотвращает повторное выполнение кода после обновления страницы.

Таким образом, пользователь может свободно выбирать товары, но в корзине всегда будет находиться только один — последний выбранный.

Решение не требует кастомизации каталога или JS-ограничений и полностью реализуется на стороне шаблона корзины.

Стоимость разработки на 1С-Битрикс:

Индивидуальная разработка магазина

от 500 000 руб. от 5-ти недель

Разработка магазина на 1С-Битрикс с нуля. Дизайн, сборка и оптимизация производительности под конкретный проект и требования. Реализация любого функционала без ограничений готовых решений.

Запуск сайта на готовом решении

от 150 000 руб. от 7-ми дней

Вариант для тех, кто не хочет тратить много средств на индивидуальный проект, и не имеет серьезных требований к сайту. Магазин, быстро запускается на базе одного из 200-та готовых решений.

Мобильное приложение

от 400 000 руб. от 5-ти недель

Разработка кроссплатформенного мобильного приложения, которое не уступает нативным решениям как в производительности, так и пользовательском опыте. Публикуется в AppStore, GooglePlay и RuStore

Сайт компании

от 300 000 руб. от 2-х недель

Корпоративный сайт с информационными разделами, каталогом товаров или услуг. Включает формы обратной связи карточек каталога, любое количество статичных и динамичных разделов.

Инфоресурс

от 300 000 руб. от 4-х недель

Информационный ресурс любой сложности. Сайт для СМИ, городской портал или многопользовательская доска объявлений. Внутренние форумы, блоги- по необходимости.

3D‑моделирование, визуализация

от 25 000 руб. от 3-х дней

По вашим фото, чертежам или описанию создадим 3D‑модели и отрендерим набор изображений для каталога товаров: общий вид, крупные планы и технические ракурсы или 360°‑обзор товара.