Skip to content

Instantly share code, notes, and snippets.

@Isa3v
Last active May 24, 2023 14:32
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Isa3v/fd43ecae6173bf2ab6330966102a2188 to your computer and use it in GitHub Desktop.
Save Isa3v/fd43ecae6173bf2ab6330966102a2188 to your computer and use it in GitHub Desktop.
Тип цен в зависимости от суммы корзины (Bitrix)

Тип цен в зависимости от суммы корзины (Bitrix)

В init.php PHP 7.0+ Bitrix (Бизнес) 16+

Задача

Изменение типов цен в зависимости от суммы коризны.

  • При сумме заказа до 15 000 рублей по розничной стоимости - тип цены розница
  • При сумме заказа от 15.000 руб по розничной стоимости - тип цены мелкий опт
  • При сумме заказа от 50.000 руб по мелкий опт стоимости - тип цены средний опт
  • При сумме заказа от 100.000 руб по средний опт стоимости - тип цены крупный опт

Если у одного из товаров отсутвует одна из цен то берется предыдущая для суммирования
Например если у товара "Гвоздь" есть все типы цен, а у товара "Молоток" есть только розница, то будет считать: Крупный опт = Гвоздь (крупный опт) * кол-во + Молоток (розница) * кол-во

Вдохновлен старой статьей 2013 год

<?php
$eventManager = \Bitrix\Main\EventManager::getInstance();
$eventManager->addEventHandler("catalog", "OnGetOptimalPrice", ["amountForPrice", "onGetPriceEvent"]);
global $basketPrice;
$basketPrice = [];
class amountForPrice
{
/**
* [BASE ID: 1] при сумме заказа до 15 000 рублей
* [SALE_SMAL ID: 2] Мелкий опт от 15.000 руб.
* [SALE_MIDDLE ID: 4] Средний опт от 50.000 руб.
* [SALE_LARGE ID: 5] Крупный опт от 100.000 руб.
*/
// Проставляем ID типов цен
protected static $baseGroup = 1;
protected static $smallGroup = 2;
protected static $middleGroup = 4;
protected static $largeGroup = 5;
public function onGetPriceEvent($productID, $quantity = 1, $arUserGroups = [], $renewal = "N", $arPrices = array(), $siteID = false, $arDiscountCoupons = false)
{
// Через global, чтоб не вызывалось по несколько раз
// OnGetOptimalPrice вызывается для каждого товара
global $basketPrice;
if (empty($basketPrice)) {
$basketPrice = self::getBasketUser();
}
// Получаем доступные цены для товара
$resOptPrices = \Bitrix\Catalog\PriceTable::getList([
'filter' => ['=PRODUCT_ID' => $productID],
'select' => ['CATALOG_GROUP_ID', 'PRICE', 'CURRENCY'],
]);
while($optPrice = $resOptPrices->fetch()){
$arOptPrices[$optPrice['CATALOG_GROUP_ID']] = $optPrice;
}
if(empty($arOptPrices)){
return false;
}
$arPrice = self::getPrice($basketPrice, $arOptPrices);
$result = [
'PRICE' => [
"ID" => $productID,
'CATALOG_GROUP_ID' => $arPrice['group'],
'PRICE' => $arPrice['price'],
'CURRENCY' => $arPrice['currency'],
'ELEMENT_IBLOCK_ID' => $productID,
'VAT_INCLUDED' => "Y",
],
'DISCOUNT' => ['VALUE' => $discount, 'CURRENCY' => $arPrice['currency']],
];
return $result;
}
/**
* Функция смотрит цену корзины и выбирает подходящую цену
* Функции цен уже сам перебразывают цену в зависимости от доступности
*/
public function getPrice($sum = [], $arPrices = [])
{
if ($sum[self::$middleGroup] >= 100000) {
$result = self::priceLarge($arPrices);
} elseif ($sum[self::$smallGroup] >= 50000) {
$result = self::priceMiddle($arPrices);
} elseif ($sum[self::$baseGroup] >= 15000) {
$result = self::priceSmall($arPrices);
} else {
$result = self::priceBase($arPrices);
}
return $result;
}
public function priceLarge(array $arPrices)
{
if (empty($arPrices[self::$largeGroup])) {
$result = self::priceMiddle($arPrices);
} else {
$result = [
'group' => self::$largeGroup,
'price' => $arPrices[self::$largeGroup]['PRICE'],
'currency' => $arPrices[self::$largeGroup]['CURRENCY']
];
}
return $result;
}
public function priceMiddle(array $arPrices)
{
if (empty($arPrices[self::$middleGroup])) {
$result = self::priceSmall($arPrices);
} else {
$result = [
'group' => self::$middleGroup,
'price' => $arPrices[self::$middleGroup]['PRICE'],
'currency' => $arPrices[self::$middleGroup]['CURRENCY']
];
}
return $result;
}
public function priceSmall(array $arPrices)
{
if (empty($arPrices[self::$smallGroup])) {
$result = self::priceBase($arPrices);
} else {
$result = [
'group' => self::$smallGroup,
'price' => $arPrices[self::$smallGroup]['PRICE'],
'currency' => $arPrices[self::$smallGroup]['CURRENCY']
];
}
return $result;
}
public function priceBase(array $arPrices)
{
$result = [
'group' => 1,
'price' => $arPrices[self::$baseGroup]['PRICE'],
'currency' => $arPrices[self::$baseGroup]['CURRENCY']
];
return $result;
}
/**
* Получение суммы корзины текущего пользователя
* Получаем суммы всех типов цен
*/
public function getBasketUser()
{
$resultPrice = [];
$resultPrice[self::$baseGroup] = 0;
$resultPrice[self::$smallGroup] = 0;
$resultPrice[self::$middleGroup] = 0;
//$resultPrice[self::$largeGroup] = 0; // large мы не считаем т.к он уже не учавствует в выборке
$obBasket = \Bitrix\Sale\Basket::getList([
'filter' => [
'FUSER_ID' => \Bitrix\Sale\Fuser::getId(),
'LID' => SITE_ID,
'ORDER_ID' => NULL // Т.к корзина связана с заказами, то нам нужна корзина у которой нет заказа
],
'select' => ['QUANTITY', 'PRODUCT_ID', 'CAN_BUY', 'DELAY']
]);
while($arItem = $obBasket->Fetch()){
// Нам нужны только доступные товары остальные не считаем
if ($arItem['DELAY'] == 'N' && $arItem['CAN_BUY'] == 'Y') {
$resPrices = \Bitrix\Catalog\PriceTable::getList([
'filter' => ['=PRODUCT_ID' => $arItem['PRODUCT_ID']],
'select' => ['CATALOG_GROUP_ID', 'PRICE'],
]);
while ($price = $resPrices->fetch()) {
$arItem['PRICES'][$price['CATALOG_GROUP_ID']] = $price['PRICE'];
}
// Если вдруг нет у товара цены, то берем следующую т.к нам нужна именно сумма
$resultPrice[self::$middleGroup] += (($arItem['PRICES'][self::$middleGroup] ?? $arItem['PRICES'][self::$smallGroup] ?? $arItem['PRICES'][self::$baseGroup]) * $arItem['QUANTITY']);
$resultPrice[self::$smallGroup] += (($arItem['PRICES'][self::$smallGroup] ?? $arItem['PRICES'][self::$baseGroup]) * $arItem['QUANTITY']);
$resultPrice[self::$baseGroup] += ($arItem['PRICES'][self::$baseGroup] * $arItem['QUANTITY']);
}
}
return $resultPrice;
}
}
<?php
$eventManager = \Bitrix\Main\EventManager::getInstance();
$eventManager->addEventHandler("catalog", "OnGetOptimalPrice", ["amountForPrice", "onGetPriceEvent"]);
global $basketPrice;
$basketPrice = [];
class amountForPrice
{
/**
* [BASE ID: 7] при сумме заказа до 15 000 рублей
*/
// Проставляем ID типов цен
const BASE_GROUP = 7;
const GROUP_15 = 5;
const GROUP_20 = 2;
const GROUP_40 = 6;
const GROUP_80 = 3;
const GROUP_110 = 4;
public function onGetPriceEvent($productID, $quantity = 1, $arUserGroups = [], $renewal = "N", $arPrices = array(), $siteID = false, $arDiscountCoupons = false)
{
// Через global, чтоб не вызывалось по несколько раз
// OnGetOptimalPrice вызывается для каждого товара
global $basketPrice;
if (empty($basketPrice)) {
$basketPrice = self::getBasketUser();
}
// Получаем доступные цены для товара
$resOptPrices = \Bitrix\Catalog\PriceTable::getList([
'filter' => ['=PRODUCT_ID' => $productID],
'select' => ['CATALOG_GROUP_ID', 'PRICE', 'CURRENCY', 'QUANTITY_TO', 'QUANTITY_FROM'],
]);
while($optPrice = $resOptPrices->fetch()){
// Если вкл. расширенные цены
if(!empty($optPrice['QUANTITY_FROM']) && $optPrice['QUANTITY_FROM'] > $quantity){
continue;
}
if(!empty($optPrice['QUANTITY_TO']) && $optPrice['QUANTITY_TO'] < $quantity){
continue;
}
$arOptPrices[$optPrice['CATALOG_GROUP_ID']] = $optPrice;
}
if(empty($arOptPrices)){
return false;
}
$arPrice = self::getPrice($basketPrice, $arOptPrices);
$result = [
'PRICE' => [
"ID" => $productID,
'CATALOG_GROUP_ID' => $arPrice['group'],
'PRICE' => $arPrice['price'],
'CURRENCY' => $arPrice['currency'],
'ELEMENT_IBLOCK_ID' => $productID,
'VAT_INCLUDED' => "Y",
],
'DISCOUNT' => ['VALUE' => $discount, 'CURRENCY' => $arPrice['currency']],
];
return $result;
}
/**
* Функция смотрит цену корзины и выбирает подходящую цену
* Функции цен уже сам перебразывают цену в зависимости от доступности
*/
public function getPrice($sum = [], $arPrices = [])
{
if ($sum[self::GROUP_110] >= 110000) {
$result = self::price110($arPrices);
}elseif ($sum[self::GROUP_80] >= 80000) {
$result = self::price80($arPrices);
} elseif ($sum[self::GROUP_40] >= 40000) {
$result = self::price40($arPrices);
} elseif ($sum[self::GROUP_20] >= 20000) {
$result = self::price20($arPrices);
} elseif ($sum[self::GROUP_15] >= 15000) {
$result = self::price15($arPrices);
} else {
$result = self::priceBase($arPrices);
}
return $result;
}
public function price110(array $arPrices)
{
if (empty($arPrices[self::GROUP_110])) {
$result = self::price40($arPrices);
} else {
$result = [
'group' => self::GROUP_110,
'price' => $arPrices[self::GROUP_110]['PRICE'],
'currency' => $arPrices[self::GROUP_110]['CURRENCY']
];
}
return $result;
}
public function price80(array $arPrices)
{
if (empty($arPrices[self::GROUP_80])) {
$result = self::price40($arPrices);
} else {
$result = [
'group' => self::GROUP_80,
'price' => $arPrices[self::GROUP_80]['PRICE'],
'currency' => $arPrices[self::GROUP_80]['CURRENCY']
];
}
return $result;
}
public function price40(array $arPrices)
{
if (empty($arPrices[self::GROUP_40])) {
$result = self::price20($arPrices);
} else {
$result = [
'group' => self::GROUP_40,
'price' => $arPrices[self::GROUP_40]['PRICE'],
'currency' => $arPrices[self::GROUP_40]['CURRENCY']
];
}
return $result;
}
public function price20(array $arPrices)
{
if (empty($arPrices[self::GROUP_20])) {
$result = self::price15($arPrices);
} else {
$result = [
'group' => self::GROUP_20,
'price' => $arPrices[self::GROUP_20]['PRICE'],
'currency' => $arPrices[self::GROUP_20]['CURRENCY']
];
}
return $result;
}
public function price15(array $arPrices)
{
if (empty($arPrices[self::GROUP_15])) {
$result = self::priceBase($arPrices);
} else {
$result = [
'group' => self::GROUP_15,
'price' => $arPrices[self::GROUP_15]['PRICE'],
'currency' => $arPrices[self::GROUP_15]['CURRENCY']
];
}
return $result;
}
public function priceBase(array $arPrices)
{
$result = [
'group' => 1,
'price' => $arPrices[self::BASE_GROUP]['PRICE'],
'currency' => $arPrices[self::BASE_GROUP]['CURRENCY']
];
return $result;
}
/**
* Получение суммы корзины текущего пользователя
* Получаем суммы всех типов цен
*/
public function getBasketUser()
{
$resultPrice = [];
$resultPrice[self::BASE_GROUP] = 0;
$resultPrice[self::GROUP_15] = 0;
$resultPrice[self::GROUP_20] = 0;
$resultPrice[self::GROUP_40] = 0;
$resultPrice[self::GROUP_80] = 0;
$resultPrice[self::GROUP_110] = 0;
$obBasket = \Bitrix\Sale\Basket::getList([
'filter' => [
'FUSER_ID' => \Bitrix\Sale\Fuser::getId(),
'LID' => 's1',
'ORDER_ID' => NULL // Т.к корзина связана с заказами, то нам нужна корзина у которой нет заказа
],
'select' => ['QUANTITY', 'PRODUCT_ID', 'CAN_BUY', 'DELAY']
]);
while($arItem = $obBasket->Fetch()){
// Нам нужны только доступные товары остальные не считаем
if ($arItem['DELAY'] == 'N' && $arItem['CAN_BUY'] == 'Y') {
$resPrices = \Bitrix\Catalog\PriceTable::getList([
'filter' => ['=PRODUCT_ID' => $arItem['PRODUCT_ID']],
'select' => ['CATALOG_GROUP_ID', 'PRICE'],
]);
while ($price = $resPrices->fetch()) {
$arItem['PRICES'][$price['CATALOG_GROUP_ID']] = $price['PRICE'];
}
// Если вдруг нет у товара цены, то берем следующую т.к нам нужна именно сумма
$resultPrice[self::GROUP_110] += (($arItem['PRICES'][self::GROUP_110] ?? $arItem['PRICES'][self::GROUP_80] ?? $arItem['PRICES'][self::GROUP_40] ?? $arItem['PRICES'][self::GROUP_20] ?? $arItem['PRICES'][self::GROUP_15] ?? $arItem['PRICES'][self::BASE_GROUP]) * $arItem['QUANTITY']);
$resultPrice[self::GROUP_80] += (($arItem['PRICES'][self::GROUP_80] ?? $arItem['PRICES'][self::GROUP_40] ?? $arItem['PRICES'][self::GROUP_20] ?? $arItem['PRICES'][self::GROUP_15] ?? $arItem['PRICES'][self::BASE_GROUP]) * $arItem['QUANTITY']);
$resultPrice[self::GROUP_40] += (($arItem['PRICES'][self::GROUP_40] ?? $arItem['PRICES'][self::GROUP_20] ?? $arItem['PRICES'][self::GROUP_15] ?? $arItem['PRICES'][self::BASE_GROUP]) * $arItem['QUANTITY']);
$resultPrice[self::GROUP_20] += (($arItem['PRICES'][self::GROUP_20] ?? $arItem['PRICES'][self::GROUP_15] ?? $arItem['PRICES'][self::BASE_GROUP]) * $arItem['QUANTITY']);
$resultPrice[self::GROUP_15] += (($arItem['PRICES'][self::GROUP_15] ?? $arItem['PRICES'][self::BASE_GROUP]) * $arItem['QUANTITY']);
$resultPrice[self::BASE_GROUP] += ($arItem['PRICES'][self::BASE_GROUP] * $arItem['QUANTITY']);
}
}
return $resultPrice;
}
/**
* Получение цен и текущей цены
*/
public function getListPrices()
{
$oPrices = self::getBasketUser();
foreach($oPrices as $key => $price){
$arPrice[$key]['price'] = $price;
$arPrice[$key]['~price'] = html_entity_decode(\CCurrencyLang::CurrencyFormat($price, \Bitrix\Currency\CurrencyManager::getBaseCurrency()));
$arPrice[$key]['group'] = $key;
$arPrice[$key]['active'] = false;
}
// Ищем актуальную цену
if ($arPrice[self::GROUP_110]['price'] >= 110000) {
$arPrice[self::GROUP_110]['active'] = true;
}elseif ($arPrice[self::GROUP_80]['price'] >= 80000) {
$arPrice[self::GROUP_80]['active'] = true;
}elseif ($arPrice[self::GROUP_40]['price'] >= 40000) {
$arPrice[self::GROUP_40]['active'] = true;
}elseif ($arPrice[self::GROUP_20]['price'] >= 20000) {
$arPrice[self::GROUP_20]['active'] = true;
}elseif ($arPrice[self::GROUP_15]['price'] >= 15000) {
$arPrice[self::GROUP_15]['active'] = true;
}else{
$arPrice[self::BASE_GROUP]['active'] = true;
}
// Узнаем название группы
$rsGroup = \Bitrix\Catalog\GroupTable::getList(['select' => ['ID', 'NAME', 'XML_ID', 'SORT']]);
while($arGroup = $rsGroup->fetch()){
$id = $arGroup['ID'];
if(isset($arPrice[$id])){
$arPrice[$id]['name'] = $arGroup['NAME'];
$arPrice[$id]['XML_ID'] = $arGroup['XML_ID'];
$arPrice[$id]['SORT'] = $arGroup['SORT'];
}
}
// Сортируем
usort($arPrice, function($a, $b){
if ($a['SORT'] == $b['SORT']) {
return 0;
}
return ($a['SORT'] < $b['SORT']) ? -1 : 1;
});
return $arPrice;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment