Повторить заказ на API 1С-Битрикс наполнив корзину из заказа

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

Задача: заполнить корзину пользователя теми же товарами и количествами которые были в ранее созданном заказе. При этом нужно очистить корзину от товаров которые в ней уже имеются

Повторить заказ на API 1С-Битрикс

Решение задачи заключается в следующем:

  • Получить текущую корзину пользователя и очистить ее
  • Получить товары из ранее созданного заказа и заполнить ими корзину

Получение корзины пользователя и ее очистка

Мы используем метод Sale\Basket::loadItemsForFUser для получения корзины пользователя и цикл для обхода всех ее элементов с последующим удалением.

use Bitrix\Main\Loader;
use Bitrix\Sale;
global $USER;

if ($USER->IsAuthorized()) {
    // Получаем корзину текущего пользователя
    $basket = Sale\Basket::loadItemsForFUser(
        Sale\Fuser::getId(),
        Bitrix\Main\Context::getCurrent()->getSite()
    );
    foreach ($basket as $basketItem) {
        // Отложенные не трогаем
        if ($basketItem->getField('DELAY') === 'N') {
            // Удаляем запись
            $basket->getItemById($basketItem->getId())->delete();
            // Сохраняем корзину
            $basket->save();
        }
    }
}
  • В начале скрипта мы подключаем необходимые классы и модули, такие как Sale\Basket и Bitrix\Main\Loader, чтобы иметь доступ к функционалу работы с корзиной и другими элементами сайта.
  • Проверяем, авторизован ли текущий пользователь на сайте. Это важно, потому что мы будем работать с корзиной пользователя, и нам нужно убедиться, что это сделает только авторизованный пользователь.
  • Получение корзины текущего пользователя: используем метод Sale\Basket::loadItemsForFUser для загрузки корзины текущего пользователя. Этот метод принимает идентификатор пользователя (Sale\Fuser::getId()) и сайт, на котором выполняется операция.
  • Обход элементов корзины: используем цикл foreach для обхода всех элементов корзины пользователя.
  • Внутри цикла мы проверяем каждый элемент корзины на предмет отложенности. Если товар не отложен ('DELAY' === 'N'), удаляем элемент из корзины с помощью метода delete().
  • После удаления товаров мы вызываем метод save() для сохранения изменений в корзине.

Копирование корзины заказа, добавление товара в корзину через API

Теперь нужно получить состав копируемого заказа. Точнее нам нужно получить корзину связанную с заказом и наполнить корзину пользователя ими:


$orderID = 4; // ID заказа
// Загружаем заказ
$order = Sale\Order::load($orderID);

if ($order) {
    // Получаем корзину заказа
    $orderBasket = $order->getBasket();

    foreach ($orderBasket as $orderItem) {
        $productID = $orderItem->getProductId();
        $quantity = $orderItem->getQuantity();
        // Добавляем товар в корзину
        $basketItem = $basket->createItem(
            'catalog',
            $productID
        );
        // Дозаполняем
        $basketItem->setFields(array(
            'QUANTITY' => $quantity,
            'CURRENCY' => $order->getCurrency(),
            'LID' => $order->getSiteId(),
            'PRODUCT_PROVIDER_CLASS' => '\CCatalogProductProvider',
        ));
    }
    $basket->save();
}
  • Загружаем заказ с помощью метода Sale\Order::load, передавая идентификатор заказа.
  • Проверяем, успешно ли загрузился заказ (if ($order)), чтобы убедиться, что заказ существует и был загружен.
  • Получаем корзину заказа с помощью метода $order->getBasket(), который возвращает объект корзины, содержащий все товары заказа.
  • Затем мы проходимся циклом foreach по товарам корзины заказа.
  • Для каждого товара мы получаем его идентификатор ($productID) и количество ($quantity).
  • Добавляем товар в текущую корзину ($basket) с помощью метода createItem.
  • После создания элемента корзины мы устанавливаем его поля, такие как количество ('QUANTITY'), валюта ('CURRENCY'), сайт ('LID') и класс поставщика продукта ('PRODUCT_PROVIDER_CLASS'). Эти поля берутся из соответствующих полей заказа.
  • Наконец, мы вызываем метод save() для сохранения изменений в корзине, тем самым добавляя все товары заказа в текущую корзину.

Код целиком, скрипт для повтора заказа по запросу

Например, в каком-то разделе вы выводите заказы и нужно дать пользователю повторить любой из них. Добавляем форму, которая отправит пользователя на файл с обработчиком, передав в POST ID заказа, и в конце скрипт перенаправит пользователя на офорление заказа:

require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php');
use Bitrix\Main\Loader;
use Bitrix\Sale;
global $USER;
if (!empty($_REQUEST['ORDER_ID_FOR_REPEAT'])) {

    if ($USER->IsAuthorized()) {

        $orderID = $_REQUEST['ORDER_ID_FOR_REPEAT'];

        // Очищаем корзину пользователя
        $basket = Sale\Basket::loadItemsForFUser(
            Sale\Fuser::getId(),
            Bitrix\Main\Context::getCurrent()->getSite()
        );
        foreach ($basket as $basketItem) {
            // Отложенные не трогаем
            if ($basketItem->getField('DELAY') === 'N') {
                // Удаляем запись
                $basket->getItemById($basketItem->getId())->delete();
                // Сохраняем корзину
                $basket->save();
            }
        }

        // Загружаем заказ
        $order = Sale\Order::load($orderID);

        if ($order) {
            // Получаем корзину заказа
            $orderBasket = $order->getBasket();

            foreach ($orderBasket as $orderItem) {

                $productID = $orderItem->getProductId();
                $quantity = $orderItem->getQuantity();
                // Добавляем товар в корзину
                $basketItem = $basket->createItem(
                    'catalog',
                    $productID
                );
                // Дозаполняем
                $basketItem->setFields(array(
                    'QUANTITY' => $quantity,
                    'CURRENCY' => $order->getCurrency(),
                    'LID' => $order->getSiteId(),
                    'PRODUCT_PROVIDER_CLASS'=>'\CCatalogProductProvider',
                ));
            }
            $basket->save();
        }
        // Отправляем на офорление уже с новой корзиной
        LocalRedirect('/personal/order/make/');
    }
} else {
   LocalRedirect('/');
}
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_after.php');
Скрипт-обработчик лучше всего завернуть в компонент с настройками и дополнительными проверками. Привел как есть, что бы не усложнять.

Михаил Базаров 04.02.2024
Пример для компонента "Детальная информация о заказе", что бы при повторе заказа товары не добавлялись к существующей корзине

В template.php вместо кнопки повтора ставим форму:
Код
<form action="" method="post">
  <button type="submit" name="ORDER_REPEAT" value="Y">
      Повторить заказ
  </button>
</form>

В component_epilog.php (если нет-то создаем):
Код
php
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) {
    die();
}

use Bitrix\Sale;
if ($_REQUEST['ORDER_REPEATT'] === 'Y') {
        // Очищаем корзину пользователя
        $basket = Sale\Basket::loadItemsForFUser(
            Sale\Fuser::getId(),
            Bitrix\Main\Context::getCurrent()->getSite()
        );
        foreach ($basket as $basketItem) {
            // Отложенные не трогаем
            if ($basketItem->getField('DELAY') === 'N') {
                // Удаляем запись
                $basket->getItemById($basketItem->getId())->delete();
                // Сохраняем корзину
                $basket->save();
            }
        }

        // Загружаем заказ
        $order = Sale\Order::load(
            $arResult['ID']
        );

        if ($order) {
            // Получаем корзину заказа
            $orderBasket = $order->getBasket();

            foreach ($orderBasket as $orderItem) {

                $productID = $orderItem->getProductId();
                $quantity = $orderItem->getQuantity();
                // Добавляем товар в корзину
                $basketItem = $basket->createItem(
                    'catalog',
                    $productID
                );
                // Дозаполняем
                $basketItem->setFields(array(
                    'QUANTITY' => $quantity,
                    'CURRENCY' => $order->getCurrency(),
                    'LID' => $order->getSiteId(),
                    'PRODUCT_PROVIDER_CLASS'=>'\CCatalogProductProvider',
                ));
            }
            $basket->save();
        }
        LocalRedirect('/personal/order/make/');
}

Убрана проверка на авторизацию, так как она уже есть в самом компоненте и не нужные подключения классов- так как тоже уже подключены компонентом