Сентябрь 22, 2018
Теги: Магазин, Как это сделать?
Добавление в корзину с заданным типом цены (а не с минимальной ценой как по умолчанию).
Чтобы добавить в корзину товар с заранее заданным типом цены, а не с минимальной ценой из возможных типов, к которым пользователь имеет доступ, необходимо при добавлении в корзину указать класс провайдера "PRODUCT_PROVIDER_CLASS", который будет использоваться системой для расчета цены. В данном примере наследуется стандартный класс провайдера "\Bitrix\Catalog\Product\CatalogProvider", в котором переопределяются функции "getProductData" и "getCatalogData", в которых перед запуском тех же функций в родительском классе добавляется обработчик события "OnGetOptimalPrice", который влияет на выбор типа цены при расчете. XML_ID типа цены заранее сохраняется в свойствах элемента корзины, а в функциях "getProductData" и "getCatalogData" массив цены товара сохраняется в статическую переменную класса, откуда впоследствии забирается в обработчике "OnGetOptimalPrice". Возвращая этот массив, обработчик "OnGetOptimalPrice" указывает функции "CCatalogProduct::GetOptimalPrice" использовать именно этот тип цены.
<?php
namespace Partner;
\Bitrix\Main\Loader::includeModule("catalog");
class Basket
{
const defaultCatalogGroupXmlId = "base_price";
public static function add($productId,$quantity=1,$catalogGroupXmlId)
{
// функция добавления в корзину, сохраняем тип цены в свойствах элемента корзины
// параметр $catalogGroupXmlId содержит XML_ID нужного типа цены
if($catalogGroupXmlId)
{
$rsGroup = \Bitrix\Catalog\GroupTable::getList(array('filter'=>array('XML_ID'=>$catalogGroupXmlId)));
if(!$rsGroup->fetch())
$catalogGroupXmlId = self::defaultCatalogGroupXmlId;
}
else
$catalogGroupXmlId = self::defaultCatalogGroupXmlId;
$arRewriteFields = array(
'PRODUCT_PROVIDER_CLASS' => '\Partner\CatalogProvider',
);
$arProps = array( // required for $arRewriteFields, can be an empty array
array(
"NAME" => "Тип цены",
"CODE" => "CATALOG_GROUP_XML_ID",
"VALUE" => $catalogGroupXmlId,
"SORT" => "100",
),
);
$basketId = \Add2BasketByProductID(
$productId,
$quantity,
$arRewriteFields,
$arProps
);
$basket = \Bitrix\Sale\Basket::loadItemsForFUser(\Bitrix\Sale\Fuser::getId(), \Bitrix\Main\Context::getCurrent()->getSite());
$refreshStrategy = \Bitrix\Sale\Basket\RefreshFactory::create(\Bitrix\Sale\Basket\RefreshFactory::TYPE_FULL);
$result = $basket->refresh($refreshStrategy);
$basket->save();
return $basketId;
}
}
class CatalogProvider extends \Bitrix\Catalog\Product\CatalogProvider
{
private static $PartnerPrice = false;
/**
* @param array $products
*
* @return Sale\Result
*/
public function getProductData(array $products)
{
return self::customGetData($products,__FUNCTION__);
}
/**
* @param array $products
*
* @return Sale\Result
*/
public function getCatalogData(array $products)
{
return self::customGetData($products,__FUNCTION__);
}
private function customGetData(array $products,$methodName)
{
self::$PartnerPrice = false;
foreach($products as $product)
{
$basketPropRes = \Bitrix\Sale\Internals\BasketPropertyTable::getList(array(
'filter' => array('BASKET_ID' => $product['BASKET_ID'],'CODE'=>'CATALOG_GROUP_XML_ID'),
));
if (
!($property = $basketPropRes->fetch())
|| !($catalogGroupXmlId=$property['VALUE'])
)
continue;
$rsPrice = \Bitrix\Catalog\PriceTable::getList(array(
'filter' => array('PRODUCT_ID'=>$product['PRODUCT_ID'],'CATALOG_GROUP.XML_ID'=>$catalogGroupXmlId),
'limit' => 1,
));
if($arPrice=$rsPrice->fetch())
{
if(!is_array(self::$PartnerPrice))
self::$PartnerPrice=array();
self::$PartnerPrice[intval($product['PRODUCT_ID'])] = $arPrice;
}
}
$eventManager = \Bitrix\Main\EventManager::getInstance();
// Добавляем обработчик OnGetOptimalPrice
$eventManager->addEventHandler('catalog', 'OnGetOptimalPrice', '\\'.static::class.'::onGetOptimalPriceHandler');
$arResult = parent::$methodName($products);
self::$PartnerPrice = false;
// Убираем обработчик OnGetOptimalPrice
$eventManager->removeEventHandler('catalog', 'OnGetOptimalPrice', '\\'.static::class.'::onGetOptimalPriceHandler');
return $arResult;
}
public function onGetOptimalPriceHandler(
$intProductID,
$quantity = 1,
$arUserGroups = array(),
$renewal = "N",
$arPrices = array(),
$siteID = false,
$arDiscountCoupons = false
) {
/*
В результате работы обработчика могут быть возвращены следующие значения:
true - обработчик ничего не сделал, будет выполнена работа метода CCatalogProduct::GetOptimalPrice;
false - возникла ошибка, работа метода прерывается;
массив, описывающий наименьшую цену для товара.
*/
if(
!is_array(self::$PartnerPrice)
|| !is_array($arPrice=self::$PartnerPrice[$intProductID])
)
return true;
return array('PRICE'=>$arPrice); // также можно вернуть описания скидок
}
}