1С-Битрикс. Сортировка по цене в системах с разной валютой.

Веб-программирование 19 сентября 2016 г., 6:01

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

И вот случилось чудо, спустя 4-5 лет долгих костылей и просьб на сайте разработчика, в API была добавлена возможность сортировать с учетом валюты.

Использование сортировки цен с валютой в 1C-Bitrix версии 16.0.3 и старше

Для того что бы использовать эту возможность, надо посмотреть в вашей системе, какой тип цены является базовы, для этого идем в Магазин → Настройки → Типы цен

В моем случае это ID = 1

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

		"ELEMENT_SORT_FIELD" => "CATALOG_PRICE_SCALE_1",
		"ELEMENT_SORT_ORDER" => "desc", 

Или возрастанию:

		"ELEMENT_SORT_FIELD" => "CATALOG_PRICE_SCALE_1",
		"ELEMENT_SORT_ORDER" => "asc", 

Так же, вы можете добавить 2 параметр сортировки с ключем ELEMENT_SORT_FIELD2 и ELEMENT_SORT_ORDER2.

Но что делать тем, у кого версия битрикса младше 16.0.3?

Для этого есть разные способы, я решил использовать дополнительное свойство, в которое я пишу цену в рублях (конвертирую) и уже сортирую по ней. Сейчас я его подробно опишу.

Для начала, нам нужно создать свойство: PRICE_SORT, в название я написал «Цена в рублях для сортировки», тип: число.

Дальше, нам необходимо заполнить его у всех товаров, я это сделал при помощи вот такого скрипта:

function update_catalog_price_sort(){
	
	$count = 0;	

	try{
		$arFilter = Array( "IBLOCK_ID" => 2 );
		$res = CIBlockElement::GetList(Array(), $arFilter, false, false, Array("ID", "PROPERTY_PRICE_SORT", 'CATALOG_GROUP_1') );
		while($row = $res->GetNext())
		{
			$price = $row['CATALOG_PRICE_1'];

			echo "Start update {$row['ID']}: {$price} {$row['CATALOG_CURRENCY_1']} to ";

			if ($row['CATALOG_CURRENCY_1'] != 'RUB'){
				$price = CCurrencyRates::ConvertCurrency($price, $row['CATALOG_CURRENCY_1'], 'RUB');
			}

			if ($price != $row['PROPERTY_PRICE_SORT_VALUE']){

				CIBlockElement::SetPropertyValuesEx($row['ID'], 2, array(
					'PRICE_SORT'  => $price
				));

				echo "{$price} {RUB} - DONE \n";

				$count++;

				sleep(0.2);

			} else {
				echo "{$price} {RUB} - NOT NEED UPDATE \n";
			}
		}

	} catch(Exception $ex) {
		smail('Запуск обновления цен-сортировок', 'Провал - обновления:' . $ex->getMessage() );
	}
	
	return $count;
}

Вначале мы запрашиваем все товары в системе, у меня около 120 тыс. Из запроса мы получаем:

  • ID - индификатор товара
  • CATALOG_PRICE_1 — цена товара. Учтите, что если у вас, базовый тип цены другой (смотри выше где можно проверить), то и цифра в конце ключа, будет другой. В любом случае, вы всегда можете сделать print_r($row) и узнать правильность ID базовой цены
  • CATALOG_CURRENCY_1 — в какой валюте сохранена цена. Так же как и с ценой, важно учитывать ID в конце ключа

Дальше все просто, если валюта отличается от RUB, делаем конвертацию:

$price = CCurrencyRates::ConvertCurrency($price, $row['CATALOG_CURRENCY_1'], 'RUB');

и потом полученную цену сравниваем с тем, что у нас сохранено в PRICE_SORT (ключ в массиве: PROPERTY_PRICE_SORT_VALUE), если цены различаются, обновляем.

Для отладки я использую вывод информации и отлов исключения, с уведомление на почту. Дальше нам остается функцию update_catalog_price_sort() поместить в агент, который будет обновлять цены. Я его добавил в агент обновляющий валюту. Он у меня запускается раз в сутки, когда на сервере минимальная нагрузка.

Учтите важный момент! Это ресурсоёмкая задача, по-этому агенты должны исполняться на cron.

Ну и самое важное, прописываем наше поле PRICE_SORT в вызове компонента:

	"ELEMENT_SORT_FIELD" => 'PROPERTY_PRICE_SORT',

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

Теги: php Bitrix 0


Станьте первым!

Пожалуйста, авторизуйтесь или зарегистрируйтесь для комментирования!

Яндекс.Метрика