В этой заметке постараюсь описать процесс реализации индивидуальных цен, для пользователей. При этом, индивидуальные цены будут синхронизироваться с 1С:Предприятие - в обе стороны.
Индивидуальная цена распостраняется не на все товары каталога, а на какие-то определенные. И мы не будем создавать собственные компоненты и по чем зря раздувать init.php
Все данные будем хранить в Highload-блоке, что обеспечит нам и достаточную скорость работы (так как цен и контрагентов может быть много) и гибкость при дальнейшей работе.
Создаем Highload-блок, называем, например Индивидуальные цены контрагентов c тремя полями:
Заполняем тремя-четырмя элементами и экспортируем в файл. Этот файл отдаем программисту 1С, как образец и просим заполнить реальными данными.
Как получаем файл, выполняем импорт. В дальнейшем, 1С будет обмениваться этими данными автоматически. На стороне сайта ничего делать не надо, на стороне 1С используем дополнительный модуль обмена: который умеет выгружать справочники в HL блоки.
В итоге получаем заполненный инфоблок с индивидуальными ценами.
Теперь нужно вывести эти цены, авторизованному пользователю в разделе каталога и в детальной карточке товара.
В шаблоне catalog.item создаем файл result_modifier.php и добавляем в него следующий код (пояснения ниже):
if($USER->IsAuthorized()) { $rsUser = CUser::GetByID($USER->GetID()); $arUser = $rsUser->Fetch(); $curUserXmlId = $arUser['XML_ID']; $curItemXmlId = $arResult['ITEM']['XML_ID']; \Bitrix\Main\Loader::includeModule('highloadblock'); use Bitrix\Highloadblock as HL; use Bitrix\Main\Entity; $hlblockId = HL\HighloadBlockTable::getById(4)->fetch(); $entity = HL\HighloadBlockTable::compileEntity($hlblockId); $entity_data_class = $entity->getDataClass(); $rsDataPrice = $entity_data_class::getList(array( "select" => array("UF_PRICE_CONTRAGENT"), "filter" => array( "UF_GOOD_BY_CONTRAGENT" => $curItemXmlId, "UF_XML_ID_CONTRAGENT" => $curUserXmlId ) )); while ($arItemPrice = $rsDataPrice->Fetch()) { $arResult['ITEM']['INDIVIDUAL_PRICE'] = $arItemPrice['UF_PRICE_CONTRAGENT']; } }
В шаблоне catalog.item/ВАШ_ШАБЛОН/card/template.php просто делаем условие, обвернув в него цену. Если $arResult['ITEM']['INDIVIDUAL_PRICE'] пустая- то выводим обычную цену, иначе показываем индивидуальную.
foreach ($item['ITEM_PRICES'] as $PRICE) { if (empty($arResult['ITEM']['INDIVIDUAL_PRICE'])) { echo $PRICE['PRINT_RATIO_BASE_PRICE']; } else { echo $arResult['ITEM']['INDIVIDUAL_PRICE'] . ' руб.'; } }
По сути, тоже самое проделываем с детальной карточкой товара в result_modifier.php и template.php шаблона catalog.element:
//// ------- result_modifier.php if($USER->IsAuthorized()) { $rsUser = CUser::GetByID($USER->GetID()); $arUser = $rsUser->Fetch(); $curUserXmlId = $arUser['XML_ID']; $curItemXmlID = $arResult['XML_ID']; \Bitrix\Main\Loader::includeModule('highloadblock'); use Bitrix\Highloadblock as HL; use Bitrix\Main\Entity; $hlblockId = HL\HighloadBlockTable::getById(4)->fetch(); $entity = HL\HighloadBlockTable::compileEntity($hlblockId); $entity_data_class = $entity->getDataClass(); $rsDataPrice = $entity_data_class::getList(array( "select" => array("UF_PRICE_CONTRAGENT"), "filter" => array( "UF_GOOD_BY_CONTRAGENT" => $curItemXmlID, "UF_XML_ID_CONTRAGENT" => $curUserXmlId ) )); while ($arItemPrice = $rsDataPrice->Fetch()) { $arResult['INDIVIDUAL_PRICE'] = $arItemPrice['UF_PRICE_CONTRAGENT']; } } //// ------- template.php foreach ($$arResult['ITEM_PRICES'] as $PRICE) { if (empty($arResult['INDIVIDUAL_PRICE'])) { echo $PRICE['PRINT_RATIO_BASE_PRICE']; } else { echo $arResult['INDIVIDUAL_PRICE'] . ' руб.'; } }
В целом, в корзине проделываем тоже самое, единственное что весь код добавляем в файл /sale.basket.basket/ВАШ_ШАБЛОН/mutator.php - здесь нужно модифицировать несколько полей массива, в которых содержатся цены и суммы каждого товара.
До foreach ($this->basketItems as $row):
\Bitrix\Main\Loader::includeModule('highloadblock'); global $USER; $rsUser = CUser::GetByID($USER->GetID()); $arUser = $rsUser->Fetch(); $curUserXmlId = $arUser['XML_ID']; // XML ID текущего пользователя use Bitrix\Highloadblock as HL; use Bitrix\Main\Entity; $hlblockId = HL\HighloadBlockTable::getById(4)->fetch(); // Получаем запись из HL блока №4 $entity = HL\HighloadBlockTable::compileEntity($hlblockId); $entity_data_class = $entity->getDataClass();
В самом переборе массива, в самом верху, так же проверяем наличие индивидуальной цены для этого товара, этому пользователю и подменяем значения ключей массива:
$rsDataPrice = $entity_data_class::getList(array( "select" => array("UF_PRICE_CONTRAGENT"), "filter" => array( "UF_GOOD_BY_CONTRAGENT" => $row['PRODUCT_XML_ID'], "UF_XML_ID_CONTRAGENT" => $curUserXmlId ) )); while ($arItemPrice = $rsDataPrice->Fetch()) { $curItemPrice = $arItemPrice['UF_PRICE_CONTRAGENT']; // Индивидуальная цена для этого товара этому контрагенту } if (!empty($curItemPrice)) { $row['PRICE_FORMATED'] = $curItemPrice . ' руб.'; $row['PRICE'] = $curItemPrice; $row['FULL_PRICE'] = $curItemPrice; $row['FULL_PRICE_FORMATED'] = $curItemPrice . $row['CURRENCY']; $row['SUM_PRICE'] = $curItemPrice * $row['QUANTITY']; $row['SUM_PRICE_FORMATED'] = $curItemPrice * $row['QUANTITY'] . ' руб.'; $row['SUM'] = $curItemPrice * $row['QUANTITY'] . ' руб.'; $row['SUM_FULL_PRICE_FORMATED'] = $curItemPrice * $row['QUANTITY'] . ' руб.'; $row['SUM_FULL_PRICE'] = $curItemPrice * $row['QUANTITY']; $row['SUM_FULL_PRICE'] = $curItemPrice * $row['QUANTITY']; $row['SUM_VALUE'] = $curItemPrice * $row['QUANTITY']; }
И в самом низу, перед завершением foreach ($this->basketItems as $row)
$allSumCustom += $row['PRICE'] * $row['QUANTITY']; // И меняем сумму корзины в totalData $totalData = array( 'DISABLE_CHECKOUT' => (int)$result['ORDERABLE_BASKET_ITEMS_COUNT'] === 0, 'PRICE' => $allSumCustom, 'PRICE_FORMATED' => $allSumCustom . ' руб', 'PRICE_WITHOUT_DISCOUNT_FORMATED' => $result['PRICE_WITHOUT_DISCOUNT'], 'CURRENCY' => $result['CURRENCY'] );
При желании, также подменяем сумму в шаблоне sale.basket.basket.line - таким же образом, как в шаблонах каталога, перемножив и сплюсовав цены и колличества товаров.
А теперь самый главный финт - нужно сохранить индивидуальные цены в заказ. Будем делать это методом CSaleBasket::Update - который обновляет записи корзины, связанной с заказом.
То есть: само оформление произойдет с обычными ценами, но на последнем шаге, когда заказ уже сформирован, просто получаем его ID и меняем цены на индивидуальные.
В файл /sale.order.ajax/ВАШ_ШАБЛОН/confirm.php добавляем код.
До проверки if (!empty($arResult["ORDER"]))::
$rsUser = CUser::GetByID($USER->GetID()); $arUser = $rsUser->Fetch(); $userId = $arUser['ID']; $curUserXmlId = $arUser['XML_ID']; \Bitrix\Main\Loader::includeModule('highloadblock'); use Bitrix\Highloadblock as HL; use Bitrix\Main\Entity; $hlblockId = HL\HighloadBlockTable::getById(4)->fetch(); // Получаем запись из HL блока №4 $entity = HL\HighloadBlockTable::compileEntity($hlblockId); $entity_data_class = $entity->getDataClass();
Внутри if (!empty($arResult["ORDER"])):
$dbBasketItems = CSaleBasket::GetList( false, array( "ORDER_ID" => $arResult["ORDER"]['ID'] ), false, false, array('PRODUCT_XML_ID', 'ID') ); while ($arItems = $dbBasketItems->Fetch()) { $rsDataPrice = $entity_data_class::getList(array( "select" => array("UF_PRICE_CONTRAGENT"), "filter" => array( "UF_GOOD_BY_CONTRAGENT" => $arItems['PRODUCT_XML_ID'], "UF_XML_ID_CONTRAGENT" => $curUserXmlId ) )); while ($arItemPrice = $rsDataPrice->Fetch()) { $curItemPrice = $arItemPrice['UF_PRICE_CONTRAGENT']; } if (!empty($curItemPrice)) { $arFields = array( "PRICE" => $curItemPrice, ); CSaleBasket::Update($arItems['ID'], $arFields); } unset($curItemPrice); }
Все. Заказ будет формироваться с учетом индивидуальной цены, в 1С этот заказ придет с уже измененными данными - в общем, задача решена.
PS: В одной из следующих заметок расскажу о способе подмены цен в корзине, с помощью провайдера цен. При нем, не нужно будет ничего делать с шаблоном корзины и оформления заказа.
Но, если индивидуальных цен много - Провайдер цен может вызвать значительные нагрузки. Потому, оставил это на будущие заметки.
Способ описанный выше, хоть и более обширный, но с другой стороны: сделал и забыл. Не так часто меняется логика корзины и оформления.
![]()
Михаил Базаров
|
Не учел, в заметке, один момент:
Пересчет заказа происходит после его окончательного оформления. А в процессе оформления, цены и сумма будут без учета индивидуальных. Не учел это, так как на конкретном проекте максимально упростил оформление заказа, у меня там не показываются товары и сумма (пример на скрине) Если эти данные нужны, то также модифицируете их через result_modifier.php редактируя массив $arResult['BASKET_ITEMS'] самого компонента оформления. PS: Его же используете в confirm.php, плодить вызовы не надо |
На нем, уже много видеоуроков по 1С-Битрикс. Как одиночные видео так и серии видеоуроков Перейти на канал
Совсем скоро выйдет видеокурс по разработке доски объявлений с мобильным приложением. Подписывайтесь и будьте в курсе: