Перейти к содержимому

Добавление в корзину - из списка, из кода, с нужными свойствами

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

Решение

Добавляем позицию в корзину текущего покупателя:

use Bitrix\Main\Loader;
use Bitrix\Sale\Basket;
use Bitrix\Sale\Fuser;
Loader::includeModule('sale');
$basket = Basket::loadItemsForFUser(Fuser::getId(), SITE_ID);
$item = $basket->createItem('catalog', $productId);
$item->setFields([
'QUANTITY' => 2,
'CURRENCY' => 'RUB',
'LID' => SITE_ID,
'PRODUCT_PROVIDER_CLASS' => \Bitrix\Catalog\Product\Basket::getDefaultProviderName(),
// поставщик отвечает за цену, остаток и резерв этой позиции
// поставщик отвечает за актуальную цену и проверку остатка
]);
$basket->save();

Поставщик данных - обязательное поле у позиции. Без него корзина не знает, откуда брать цену и остаток, и позиция навсегда остаётся с той ценой, которую ей передали в момент создания.

Передаём свойства позиции:

$item->getPropertyCollection()->setProperty([
['NAME' => 'Размер', 'CODE' => 'SIZE', 'VALUE' => '42'],
['NAME' => 'Цвет', 'CODE' => 'COLOR', 'VALUE' => 'синий'],
]);
$basket->save();

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

Меняем количество у существующей позиции:

$item = $basket->getExistsItem('catalog', $productId);
if ($item) {
$item->setField('QUANTITY', $item->getQuantity() + 1);
$basket->save(); // пересчёт цены и скидок идёт здесь
}

Повторное создание позиции вместо изменения количества - частая ошибка. Корзина в этом случае либо складывает количества сама, либо получает две одинаковых строки, в зависимости от совпадения свойств.

Добавляем в корзину с витрины:

// компонент каталога добавляет позицию сам, свойства берёт из параметров
'ADD_PROPERTIES_TO_BASKET' => 'Y',
'PRODUCT_PROPS_VARIABLE' => 'prop',
'PARTIAL_PRODUCT_PROPERTIES' => 'N',

Штатный путь с витрины не требует своего кода: компонент собирает позицию и её свойства сам. Свой код нужен там, где добавление идёт не из карточки - например, в наборах или в быстром заказе.

Цена позиции пересчитывается при сохранении корзины, а не в момент её создания. Поэтому скидки, зависящие от состава заказа, появляются только после сохранения, и проверять их до этого момента совершенно бессмысленно.

Проверку остатка при добавлении делает поставщик данных, а не корзина сама по себе. Он же решает, разрешать ли покупку при нулевом остатке: настройка живёт в торговом каталоге и действует одинаково и для витрины, и для своего кода.

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

Типичные проблемы

Цена позиции не меняется вслед за каталогом.

Не задан поставщик данных. Без него позиция хранит цену, переданную при создании, и не обновляет её.

Один товар лежит в корзине двумя строками.

У позиций разные свойства. Совпадение по товару без совпадения свойств новую строку не отменяет.

Количество удваивается при повторном добавлении.

Позиция создаётся заново вместо изменения количества. Существующую строку ищут перед созданием.

Скидка не применилась к новой позиции.

Проверка идёт до сохранения корзины. Пересчёт цен и скидок выполняется при сохранении.

После входа корзина опустела.

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

Частые вопросы

Как добавить товар в корзину другого пользователя?

Загрузив корзину по его идентификатору покупателя. Так делают перенос корзины и оформление заказа менеджером за клиента.

Можно ли положить в корзину товар не из каталога?

Да, позицией без привязки к элементу: цену и название задают полями. Такие позиции не участвуют в проверке остатков.

Как убрать всплывающее окно после добавления?

Это поведение шаблона компонента, а не логики корзины. Правят шаблон, оставляя сам вызов добавления как есть.

Что происходит с корзиной со временем?

Брошенные корзины хранятся, пока их не вычистит агент по сроку. Срок задаётся настройками модуля продаж.

Смежное

Первоисточник