Были интернет-магазин и b2b платформа у одной компании на системе 1с-Битрикс. Компания росла и появились свои склады и добавились еще склады партнеров которые нужно было отображать. Возникла необходимость отображения остатков по нескольким складам.

И что нам говорит Битрикс: Пожалуйста переходите на редакцию «Бизнес» и будет всё замечательно и сразу. На редакцию перешли и оказалось, что многоценновость и многоскладовость в 1С-Битрикс живут отдельной жизнью. Первая нужна для отображения разных цен для разных групп пользователей, а второе для отображения остатков на разных складах.

Нам нужно было выводить остатки со своей ценой по каждому складу, так как цена у партнеров и у нас может отличаться на одну и ту же позицию. Штатного такого функционала оказалось, что нет.

Тут и пришла в голову идея переделать стандартные шаблоны и на стороне сайта сделать связку склад-цена.

Первое что пришлось сделать это переделать шаблоны catalog.section и catalog.element. В них был вставлен компонент catalog.store.amount:

1. Для карточки товара был выведен список складов с ценами

Фрагмент кода
if ($arResult['CATALOG_QUANTITY']!=0){ //не отображать если не на одном складе нет остатков
      $APPLICATION->IncludeComponent("bitrix:catalog.store.amount","finnit_buy",
          array("ELEMENT_ID"  => $arResult["ID"] //фильтрация по ID элемента


2. Для списка товаров через компонент сделана выборка всего одной цены (или самая низкая цена или минимальный срок доставки).

Фрагмент кода
$APPLICATION->IncludeComponent( "bitrix:catalog.store.amount", "finnit_1sk",
	 array( "ELEMENT_ID"   => $arElement["ID"]//фильтрация по ID элемента


Так для каждого вида был создан свой шаблон, по мимо этого было создано еще несколько шаблонов. К примеру шаблон для быстрой покупки в котором выводится оптимальный склад с ценой для совершения покупки.

Работы по компоненту catalog.store.amount шли в 3 этапа.

1. Ручное сопоставление в коде склад — цена (удобно при малом количестве складов). В данном случае в коде пишется указание типа цены для определенного склада.

Фрагмент кода
if ($arProperty['ID'] == 29){// Идентификатор склада
                        $db_res = CPrice::GetList( array(),  array("PRODUCT_ID" => $arParams['ELEMENT_ID'],"CATALOG_GROUP_ID" => '28')); // 28 - это идентификатор необходимого типа цены
                        if ($ar_res = $db_res->Fetch()){
                            if($min_price > (ceil(($ar_res["PRICE"] + ($ar_res["PRICE"]/100))/10)* 10))
                                $min_price = ceil(($ar_res["PRICE"] + ($ar_res["PRICE"]/100))/10)* 10; // получаем минимальную цену по всем складам по данному товару и округляем
                            $amount = $arProperty["AMOUNT"]; // получаем количество по складу
                            $title = $arProperty["ID"]; // изначально передалось Наименование в переменную, но при смене наименования в 1С при обмене склад переименовывался и на сайте - по этому привязку сделали по ID, а название переменной не трогали.
                        }


2. После того как стали подключаться еще склады первый вариант оказался непригодным и было принято решение вести связки склад- цена в отдельном инфоблоке.

скриншот


Фрагмент кода
<?// запрос инфоблока со списком сопоставления
                                $arSelectEquals = Array("ID", "IBLOCK_ID");
                                $arFilterEquals = Array("IBLOCK_ID"=>18); //ID инфоблока сопоставления
                                $equals = CIBlockElement::GetList(Array(), $arFilterEquals, false, Array(), $arSelectEquals);
                                while($equal = $equals->GetNextElement()){
                                    $arPropsEquals = $equal->GetProperties();
                                    if ($arProperty["ID"] == $arPropsEquals["SKLAD_ID"]["VALUE"]){// если склад сопоставлен
                                        $db_res = CPrice::GetList(
                                            array(),  array("PRODUCT_ID" => $arParams['ELEMENT_ID'],"CATALOG_GROUP_ID" => $arPropsEquals["PRICE_ID"]["VALUE"]));
                                        if ($ar_res = $db_res->Fetch()){
                                            if (!isset($ar_res["PRICE"])){
                                                echo GetMessage('FINN_PRICE_MANAGER');//вывод сообщения если нет цены
                                            }else{ // если цена есть по сопоставленным данным
                                                    $pricen = ceil( $ar_res["PRICE"] );// получение данных для дальнейшего заказа
                                                    $price_id = $ar_res["CATALOG_GROUP_ID"];// получение данных для дальнейшего заказа
                                                    $price_name = $ar_res["CATALOG_GROUP_NAME"];// получение данных для дальнейшего заказа
                                                }
                                                //echo number_format( $pricen, 0, ',', ' ' );
                                                $torgId  = $ar_res["ID"]; // получение данных для дальнейшего заказа
                                                $torgGId = $ar_res["CATALOG_GROUP_ID"];// получение данных для дальнейшего заказа
                                            }
                                        } else{}}
                                }
                                ?>


Таким образом уже можно вести достаточно большой объем складов.

3. Использование пользовательских полей непосредственно в складах для сопоставления с типами цен.

Этот вариант изначально не рассматривался. И только после того как открылся магазин по мимо Челябинска еще и в Санкт-Петербурге понадобилось указывать срок поставки товара в зависимости от склада, для этих целей как раз и использовали пользовательские поля в складах.

Скриншот


Считаю данный вариант самый оптимальный. И на данный момент уже несколько шаблонов переведены на этот же вариант сопоставления складов и цен.

P.S. Если Вы знаете более подходящий вариант — пишите в комментариях, буду благодарен.

P.P.S. Если есть замечания или вопросы пишите — отвечу.

Комментарии (3)


  1. qnok
    13.08.2018 20:03
    +1

    Раз уж Вы просили замечания и комментарии, то у меня есть несколько.

    1. Фрагменты кода оформлены ужасно. Операции по условиям обрываются. Отступы нечитаемые. Особенно третий.
    2. Много ошибок в тексте: «если не на одном складе нет остатков», «Штатного такого функционала оказалось, что нет.», «после того как открылся магазин по мимо Челябинска», пунктуация.
    3. Скриншот с суперсекретными замазанными названиями складов/городов, и это при условии, что Вы все равно засветили адрес сайта. А в следующем скриншоте Вы их всё-таки не замазали.
    4. Слишком узкое повествование. Перечисление кодов компонентов без их названий только добавляет путаницы. Тот, кто с Битриксом не работает, вообще читать после этого перестанет.

    Я знаком с Битриксом, но и для меня статья в текущем виде имеет спорную ценность.
    Спасибо, что поделились своим опытом, возможно, Вам удастся реабилитировать Вашу статью. Я оценок статье не ставил, но все-таки думаю, что её бы лучше приняли на более узком Битрикс-ресурсе.


    1. andreyjktl Автор
      14.08.2018 07:56

      Спасибо за комментарий, обязательно учту. Попытаюсь или дополнить и исправить данную статью или в дальнейшем буду делать аккуратнее.
      1. Фрагмент кода был скопирован из Php Storm — не подправил отступы, для удобства пользователей Хабр.
      2. Получилось так, что русский в школе практически не учил. Так как выходец из одной из бывших республик СССР. Сейчас подтягиваю знания, в том числе и через критику. Спасибо.
      3. Замазаны были названия складов в которых указывалось название или аббревиатуры организаций, а города не являются секретом.
      4. Попытаюсь изложить более развернуто.


  1. serginhold
    16.08.2018 00:21

    Прям пособие, как не надо делать сторонний функционал