Дополнительные опции/услуги, добавляемые в корзину, в карточке товаров

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

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

Дополнительные опции/услуги, добавляемые в корзину, в карточке товаров 0

Связка элементов каталога с другим каталогом

В реалиях 1С-Битрикс нельзя добавить несуществующий товар в корзину: для реализации потребуется создать отдельный инфоблок с услугами/опциями, который будет так же (как и основной каталог) являться торговым каталогом.

На самом деле: можно добавить не существующий товар в корзину и учесть при оформлении заказа, подробнее в этой заметке: Добавление в корзину и заказ не существующего товара.

В настройках основного каталога нужно создать свойство типа "Привязка к элементам" и в качестве назначения указать этот дополнительный торговый каталог. В моем случае, к товарам каталога предлагается дополнительная услуга "Поверка оборудования" с кодом TSENA_POVERKI

Дополнительные опции/услуги, добавляемые в корзину, в карточке товаров 1

В инфоблоке с дополнительными услугами нужно создать свойство типа "Строка", в моем случае названо "Для оборудования" (код ATT_FORE). Оно нужно для того, что бы эти услуги не объединялись в корзине и не перемешивались.

Дополнительные опции/услуги, добавляемые в корзину, в карточке товаров 2

Создаем нужные, дополнительные услуги но это свойство оставляем пустым. И связываем товары основного каталога с дополнительными услугами.

Добавление товара в корзину на API Битрикс

Данная заметка написана как базис/ориентир по данному функционалу. Можно расширить опции к товару, сделать их множественными и вывести в виде чекбоксов. При реализации использовать AJAX, c собственным компонентом.

Открываем шаблон детальной карточки catalog.element и в том месте, где планируете выводить дополнительные услуги добавляем:

<? if (!empty($arResult['PROPERTIES']['TSENA_POVERKI']['VALUE'])) {
$page = $APPLICATION->GetCurPage();
if (!empty($arResult['PROPERTIES']['TSENA_POVERKI']['VALUE'])) {
    $res = CIBlockElement::GetByID($arResult['PROPERTIES']['TSENA_POVERKI']['VALUE']);
    if ($ar_res = $res->Fetch()) {
        $poverkaName = $ar_res['NAME'];
    }
}
?>

Доступна услуга поверки оборудования:
<?= $poverkaName ?> руб.

<form action="/local/ajax/add_poverka.php" method="post">
    <input type="hidden" value="<?= $arResult['PROPERTIES']['TSENA_POVERKI']['VALUE'] ?>"
   		name="ADD_POVERKA_PRICE">
    <input type="hidden" value="<?= $arResult['NAME'] ?>" name="ADD_POVERKA_FOR">
    <input type="hidden" value="<?= $page ?>" name="ADD_POVERKA_COMEBACK">
    <button type="submit" class="btn btn-info">В корзину с поверкой + <?= $poverkaName ?> руб.
    </button>
</form>

<?
if ($_REQUEST['ADD_ITEM_TO_CART'] == 'Y') { ?>
<script>
    $(document).ready(function () {
        $('#<?= $itemIds['ADD_BASKET_LINK'] ?>').click();
    });
</script>
<? }
} ?>

Проверили есть ли для этого товара дополнительная услуга. Если есть, собираем данные о товаре и дополнительной услуге в форму. В скрытых полях формы:

  • ID элемента дополнительной услуги из свойства инфоблока, со связанным товаром.
  • Название текущего элемента-товара
  • Адрес страницы текущего товара, полученные методом $APPLICATION->GetCurPage();

Под формой добавляем js код который имитирует нажатие на кнопку добавления в корзину (основного товара) если в параматрах URL есть запрос вида ?ADD_ITEM_TO_CART=Y

Форму, при нажатии на кнопку, отправляем на файл add_poverka.php в директории /local/ajax.. В этом файле размещаем код:

require_once($_SERVER['DOCUMENT_ROOT'] . "/bitrix/modules/main/include/prolog_before.php");

use \Bitrix\Main\Loader;

if (!$_POST['ADD_POVERKA_PRICE']) {
    LocalRedirect('/');
}

Loader::includeModule('iblock');
Loader::includeModule('sale');
Loader::includeModule('catalog');

$resPrice = CIBlockElement::GetList(
    array(),
    array('=ID' => $_POST['ADD_POVERKA_PRICE']),
    false, false,
    array(
        'ID',
        'NAME'
    )
);
while ($obPrice = $resPrice->Fetch()) {
    $arFields = array(
        "PRODUCT_ID" => $obPrice['ID'],
        "PRODUCT_PRICE_ID" => 1,
        "PRICE" => (int)$obPrice['NAME'],
        "CURRENCY" => "RUB",
        "WEIGHT" => '',
        "QUANTITY" => 1,
        "LID" => LANG,
        "DELAY" => "N",
        "CAN_BUY" => "Y",
        "NAME" => "Поверка оборудования",
        "CALLBACK_FUNC" => "",
        "MODULE" => "",
        "NOTES" => "",
        "ORDER_CALLBACK_FUNC" => "",
        "DETAIL_PAGE_URL" => ""
    );
    $arProps = array();

    $arProps[] = array(
        "NAME" => "Для",
        "CODE" => "ATT_FORE",
        "VALUE" => $_POST['ADD_POVERKA_FOR']
    );

    $arFields["PROPS"] = $arProps;
    CSaleBasket::Add($arFields);
}
LocalRedirect($_POST['ADD_POVERKA_COMEBACK'].'?ADD_ITEM_TO_CART=Y');
exit();

Здесь мы обрабатываем $_POST запрос с данными переданными формой:

  • Методом CIBlockElement::GetList получаем данные о дополнительной услуге.
  • Собираем поля для формирования добавляемого товара в корзину.
  • В полях изменяем название услуги, если это нужно.
  • В свойство ATT_FORE записываем название элемента, для которого добавляется услуга.
  • Методом CSaleBasket::Add добавляем услугу в корзину
  • C помощью LocalRedirect($_POST['ADD_POVERKA_COMEBACK'].'?ADD_ITEM_TO_CART=Y'); отправляем на страницу товара, добавив параметр URL ?ADD_ITEM_TO_CART=Y

Таким образом: когда пользователь нажимает на кнопку заказа, с дополнительной услугой, мы отправляем его на обработчик добавляющий услугу в корзину, с изменением названия товара-услуги. Сразу после этого возвращаем на страницу товара, добавляя в параметр URL запрос. Если этот запрос есть в параметрах, иммитируем нажатие на кнопку добавления в корзину самого товара.

В итоге, в корзине будут и сами товары и дополнительные опции/услуги с указанием к какому товару они относятся. Все будет чередоваться правильно: каждая опция над товаром к которому относится и дополнительным указанием в свойстве "Для оборудования".

Дополнительные опции/услуги, добавляемые в корзину, в карточке товаров 3

Повторюсь: эта заметка только базис. На реальном проекте и под конкретные задачи, лучше всего вынести всю эту логику в собственный компонент и реализовать AJAX. Что бы для пользователя все проходило максимально гладко.

Михаил Базаров 15.11.2022
При создании собственого компонента, всю логику обработки и AJAX можно завернуть в него.
Просто, вызвав компонент в карточке товара.
Владимир 21.12.2022
Заметил что если добавлять в корзину через  CSaleBasket::Add($arFields);
То при оформлении заказа не считается НДС, как победить?)
Михаил Базаров 21.12.2022
Судя по документации, но не проверял. Нужно добавить параметр
"PRODUCT_PROVIDER_CLASS" => "CCatalogProductProvider",
Гость 22.12.2022
Цитата
написал:
Судя по документации, но не проверял. Нужно добавить параметр
"PRODUCT_PROVIDER_CLASS" => "CCatalogProductProvider",
Но тогда перестает работать CASTOM PRICE и берется обычная цена товара)
замкнутый круг получается , использую этот метод именно для того что бы добавлять товар в корзину с кастомной ценой
Как быть?)
Михаил Базаров 22.12.2022
Это надо поковырять сам метод. Найти его в ядре и разложить на атомы  :)
Я пока с такой задачей не столкнусь, ни чего разумного не подскажу.
Гость 21.02.2023
Подскажите статью где вы описали добавление товара не из каталога? В сноске написано позже.  
Михаил Базаров 06.05.2023
Цитата
Гость написал:
Подскажите статью где вы описали добавление товара не из каталога? В сноске написано позже.  

Вот тут: https://bazarow.ru/blog-note/15736/