Полный цикл в digital

Работа с элементами инфоблока, товароми, торговыми предложениями

Товар добавляется самый обычный простой товар, без каких-либо дополнительных возможностей. Это тот тип товара, который наиболее употребим, и используется в данный момент повсеместно.

Торговые предложения Данный товар (как товар хранящий список предложений) не имеет остатков, не имеет цены и других атрибутов, которые есть у обычного товара. Этот товар не является товаром. По сути, он содержит список «торговых предложений», которые и являются товарами (предложениями).

Набор это список привязанных к основному товару товаров, которые магазин хочет порекомендовать к покупке. В набор могут быть добавлены именно товары: торговые предложения и/или простые товары. Товар с торговыми предложениями добавить в него нельзя.

Комплект это список товаров, составляющих необходимую комплектацию основного товара. Сам комплект не имеет физического остатка, его остаток зависит от товаров, которые входят в этот комплект. В комплект могут быть добавлены именно товары: торговые предложения и/или простые товары. Товар с торговыми предложениями добавить в него нельзя.

Работа с элементами инфоблоков

Добавление элемента инфоблока на сайт:

// инициализируем соответствующий модуль
CModule::IncludeModule("iblock");
// массив со свойствами элемента инфоблока, где ключами массива служат id нужного свойства (но можно использовать параметр CODE). Так же нужно помнить, что для списков и полей с привязкой к элементам или справочникам в качестве значения мы указываем id элемента списка, справочника или объекта
$PROP = array(
    '342'=>'',
    '315'=>''
);
// создаем объект класса для работы
$el = new CIBlockElement;
// заполняем массив с данными
$arLoadProductArray = Array(
    // указываем ID пользователя
    "MODIFIED_BY"           => 1, 
    // для привязки ко многим разделам			       
    "IBLOCK_SECTION"        => $IBLOCK_SECTION_ID,
    // для одиночного раздела          
    //"IBLOCK_SECTION_ID"   => $IBLOCK_SECTION_ID,     
    "IBLOCK_ID"             => 20,
    "IBLOCK_TYPE"           => 'aspro_next_catalog',
    "PROPERTY_VALUES"       => $PROP,
    "NAME"                  => $NAME,
    "ACTIVE"                => "Y",
    "CODE"                  => $CODE,
    //"PREVIEW_TEXT"        => "текст для списка элементов",
    //"DETAIL_TEXT"         => "текст для детального просмотра",
    //"DETAIL_PICTURE"      => CFile::MakeFileArray($_SERVER["DOCUMENT_ROOT"]."/image.gif")
);
$res = $el->Add($arLoadProductArray);
if($res>0) {
    // успешно добавили, в $res хранится id добавленной записи
} else {
    // добавить не удалось, выводим сообщение с ошибкой
    echo $el->LAST_ERROR;
}

Превращаем элемент инфоблока в товар:

/* Делаем добавленный товар простым */
$productFileds = array(
    // ID добавленного элемента инфоблока
    "ID" => $res, 
    // выставляем тип ндс (задается в админке)
    "VAT_ID" => 1, 
    // НДС входит в стоимость
    "VAT_INCLUDED" => "Y", 
    // тип товара
    "TYPE " => \Bitrix\Catalog\ProductTable::TYPE_PRODUCT 
);
// возможные значения типа товара:
//const TYPE_PRODUCT = 1;
//const TYPE_SET = 2;
//const TYPE_SKU = 3;
//const TYPE_OFFER = 4;
//const TYPE_FREE_OFFER = 5;
//const TYPE_EMPTY_SKU = 6;
if(CCatalogProduct::Add($productFileds)) {
    // элемент инфоблока превращен в товар
} else {
    // произошла ошибка
}

Получение списка свойств элемента инфоблока с помощью D7:

$res = \Bitrix\Iblock\ElementTable::getList(array(
    "select" => array("ID", "*"),
    "filter" => array("IBLOCK_ID" => $IBLOCK_ID, "ID" => $ELEMENT_ID),
    "order"  => array("ID" => "ASC")
));
while ($arItem = $res->fetch()) {
    $propRes = \Bitrix\Iblock\ElementPropertyTable::getList(array(
        "select" => array("ID", "*"),
        "filter" => array("IBLOCK_ELEMENT_ID" => $arItem["ID"],),
        "order"  => array("ID" => "ASC")
    ));
	
    while($prop = $propRes->Fetch())
        $arItem["PROPERTIES"][$prop["IBLOCK_PROPERTY_ID"]] = $prop;
}

Битрикс получить ID элемента по его символьному коду:

CIBlockFindTools::GetElementID($ELEMENT_ID, $ELEMENT_CODE, $SECTION_ID, $SECTION_CODE, $arFilter)
// $section_id - ID секции в которой лежит элемент
// $section_code - символьный код секции в которой лежит элемент
// $arFilter - массив дополнительных свойств для фильтрации
// пример использования
$objFindTools = new CIBlockFindTools();
$elementID = $objFindTools->GetElementID(false, "super_element", false, "super_section", array("IBLOCK_ID" => 1));
// метод возвращает ID элемента, если найдет его, и 0, если элемент не будет найден.

Работа с торговым каталогом

Получаем список типов цен с помощью d7:

$rsPrices = \Bitrix\Catalog\GroupTable::getList();
while($arPrice = $rsPrices->fetch()){
    $PRICE_IDS[] = $arPrice['ID'];
}

Получаем цену и кол-во товара с помощью D7:

$dbPrice = \Bitrix\Catalog\Model\Price::getList([
	"filter" => array(
		"PRODUCT_ID" => $id,
		"CATALOG_GROUP_ID" => 1
	)]);
if ($arPrice = $dbPrice->fetch()) {
	$price = $arPrice['PRICE'];
}

Добавляем или обновляем цену товара:

$arFieldsPrice = array(
    // ID добавленного товара
    "PRODUCT_ID" => $ID,
    // ID типа цены							
    "CATALOG_GROUP_ID" => 1,
    // значение цены					
    "PRICE" => $item['price'],
    // валюта			
    "CURRENCY" => !$currency ? "RUB" : $currency,
);
// смотрим установлена ли цена адля данного товара
$dbPrice = \Bitrix\Catalog\Model\Price::getList([
    "filter" => array(
        "PRODUCT_ID" => $item['ID'],
        "CATALOG_GROUP_ID" => 1
    )
]);
if ($arPrice = $dbPrice->fetch()) {
    // если цена установлена, то обновляем
    $result = \Bitrix\Catalog\Model\Price::update($arPrice["ID"], $arFieldsPrice);
    if ($result->isSuccess()) {
        echo "Обновили цену у товара у элемента каталога " . $item['ID'] . " Цена " . $item['price'] . PHP_EOL;
    } else {
        echo "Ошибка обновления цены у товара у элемента каталога " . $item['ID'] . " Ошибка " . $result->getErrorMessages() . PHP_EOL;
    }
} else {
    // если цены нет, то добавляем
    $result = \Bitrix\Catalog\Model\Price::add($arFieldsPrice);
    if ($result->isSuccess()) {
        echo "Добавили цену у товара у элемента каталога " . $item['ID'] . " Цена " . $item['price'] . PHP_EOL;
    } else {
        echo "Ошибка добавления цены у товара у элемента каталога " . $item['ID'] . " Ошибка " . $result->getErrorMessages() . PHP_EOL;
    }
}

Добавляем к товару количество на складах:

$arFields = Array(
    // ID товара
	"PRODUCT_ID" => $id, 		
    // ID склада
	"STORE_ID"   => $storeId, 	
    // количество
	"AMOUNT"     => $amount,	
);
CCatalogStoreProduct::Add($arFields);

Обновляем кол-во товара на складах:

$rs = CCatalogStoreProduct::GetList(false, array(
    // ID товара
	'PRODUCT_ID'=> $id, 
    // ID склада		
	'STORE_ID' => $storeId		
));
while($ar_fields = $rs->GetNext())
{
	// обновим значение остатка на складе из значения остатка количественного учёта
	$arFields = Array(
        // ID товара
		"PRODUCT_ID" => $id, 
        // ID склада		
		"STORE_ID"   => $storeId, 	
        // количество
		"AMOUNT"     => $amount,	
	);
	CCatalogStoreProduct::Update($ar_fields['ID'], $arFields);
}

Обновление остатков товаров с помощью D7:

$existProduct = \Bitrix\Catalog\Model\Product::getCacheItem($arFields['ID'],true);
if(!empty($existProduct)){
    \Bitrix\Catalog\Model\Product::update(intval($arFields['ID']),$arFields);
} else {
    \Bitrix\Catalog\Model\Product::add($arFields);
}

Добавляем или обновляем общее кол-во товара, параметр "Доступное кол-во":

CCatalogProduct::Update(
    // ID добавленного или обновляемого товара
$ID, 
array(  
            // кол-во товара
    "QUANTITY" => $amount, 
)
)

Добавляем товар в резерв:

$provider = new \Bitrix\Catalog\Product\CatalogProvider;
$resReserve = $provider->reserve(array(
    $productId => ["PRODUCT_ID" => $PRODUCT_ID,  "QUANTITY" => 10]
));

Снятие резерва:

$provider = new \Bitrix\Catalog\Product\CatalogProvider;
$resReserve = $provider->reserve(array(
    $productId => ["PRODUCT_ID" => $PRODUCT_ID,  "QUANTITY" => -10 ]
));

Работа со свойствами товаров

Получаем значение отдельного свойства товара в Битрикс с помощью D7:

class Product
{
    private $id;
    public function __construct($id)
    {
        if (empty($id)) {
            throw new \Bitrix\Main\ArgumentNullException('id');
        }
        $this->id = $id;
    }
    public function getFields()
    {
        return \Bitrix\Iblock\ElementTable::getById($this->id)->fetch();
    }
    public function getProperty($code)
    {
        $fields = $this->getFields();
        if ($fields) {
            $iblock = \Bitrix\Iblock\Iblock::wakeUp($fields['IBLOCK_ID']);
            $element = $iblock->getEntityDataClass()::getByPrimary($this->id, ['select' => [$code]])->fetchObject();
            $property = $element->__call('get', [$code]);
        }
        return $property ? $property->getValue() : null;
    }
}

Обновить свойство у элемента по коду свойства и ID элемента:

\CIBlockElement::SetPropertyValuesEx(PRODUCT_ID, false, array('PROPERTY_CODE' => $NEW_PROPERTY_VALUE));

Очистить значение множественного свойства:

\CIBlockElement::SetPropertyValuesEx(PRODUCT_ID, false, ['PROPERTY_CODE' => [0 => ["VALUE" => "" , "DESCRIPTION" => ""]]]);

Получаем значение отдельного свойства товара или ТП, старый способ:

$arFilter = Array("IBLOCK_ID"=>$kitOffer['IBLOCK_ID'], "ID"=>$kitOffer['ID']);
$arSelect = Array("SORT");
$res = CIBlockElement::GetList(Array(), $arFilter,false,false,$arSelect);
if ($ob = $res->GetNextElement()){;
    $arFields = $ob->GetFields();
}

Получаем товары в Битрикс с помощью D7:

// фильтр стандартный, вы знаете как им пользоваться
$elementIterator = \Bitrix\Iblock\ElementTable::getList([
    'select' => [
        'ID',
    ],
    'filter' => [
        '=IBLOCK_ID' => 20,
        '!=ID' => array(1,2,3),// массив ID товаров которые нужно пропустить
    ]
]);
$elems = $elementIterator->fetchAll();
foreach ($elems as $element) {
    // создаем объект класса для работы
    $obElement = new CIBlockElement();
    
    // обновляем элемент и делаем неактивным
    $obElement->Update($element['ID'], Array("ACTIVE" => 'N'));
}

Получаем все свойства элемента инфоблока:

CIBlockElement::GetByID($arResult['ID'])->GetNextElement()->GetProperties()

Вывод всех свойств товара:

CCatalogProduct::GetByIDEx($arElement['ID'])

Получаем значения свойства товара типа список:

$property_enums = CIBlockPropertyEnum::GetList(Array("DEF"=>"DESC", "SORT"=>"ASC"), Array("IBLOCK_ID"=>15, "CODE"=>"BREND_INTERNAL"));
while($enum_fields = $property_enums->GetNext()){
    echo $enum_fields["ID"]." - ".$enum_fields["VALUE"]."<br>";
}

Добавить новое значение в свойство типа список:

$ibpenum = new CIBlockPropertyEnum;
if($PropID = $ibpenum->Add(Array('PROPERTY_ID'=>$PROPERTY_ID, 'VALUE'=>'New Enum 1')))
    echo 'New ID:'.$PropID;

Добавить новое значение в свойство типа список с помощью D7:

\Bitrix\Main\Loader::includeModule('iblock');
$property = \CIBlockProperty::GetList(
    [],
    [
        'IBLOCK_ID' => $iblockId,  
        'CODE' => $code'
    ]
)->Fetch();
$ibpenum = new \CIBlockPropertyEnum();
$valueId = $ibpenum->Add([
    'PROPERTY_ID' => $property['ID'],
    'VALUE' => $newValueText,
    'XML_ID' => $newValueXmlId,
]);
if ((int) $valueId < 0) {
    throw new \Exception('Unable to add a value');
}

Удалить значение из свойства типа список:

CIBlockPropertyEnum::Delete(ID);

Удалить значение из свойства типа список с помощью D7:

if (! \Bitrix\Main\Loader::includeModule('iblock')) {
    throw new \Bitrix\Main\LoaderException('Unable to load IBLOCK module');
}
$property = \CIBlockProperty::GetList([], ['IBLOCK_ID' => $iblockId, 'CODE' => $propertyCode])->Fetch();
if (! $property) {
    throw new \Exception('No such property');
}
$query = \CIBlockPropertyEnum::GetList(
    [], 
    ["IBLOCK_ID" => $iblockId, "XML_ID" => 6, "PROPERTY_ID" => $property['ID']]
);
$value = $query->GetNext();
if (! $value) {
    throw new \Exception('No such value');
}
$delete = \CIBlockPropertyEnum::delete($value['ID']);
if (! $delete) {
    throw new \Exception('Error while deleting the property value');
}

Работа с наборами и комплектами

Получаем состав наборов и комплектов для родительского товара:

$arProducts = CCatalogProductSet::GetList(
	array(), array( "TYPE" => array(1,2), "OWNER_ID" => $productID), false, false, array()
);
while($item = $arSets->Fetch() ){
	if($item["OWNER_ID"]!=$item["ITEM_ID"]  ){
		$arComplects[] = $item["ITEM_ID"];
	}
}

Получаем товары соседствующие с искомым в наборе или комплекте:

\Bitrix\Main\Loader::includeModule('catalog');
$rItems = CCatalogProductSet::GetList(
    array(),
    array(
        array(
            'LOGIC' => 'OR',
            'TYPE' => CCatalogProductSet::TYPE_GROUP,
            'TYPE' => CCatalogProductSet::TYPE_SET
        ),
        'ITEM_ID' => $arResult['ID']),
    false,
    false,
    array('SET_ID', 'OWNER_ID', 'ITEM_ID', 'TYPE')
);
while ($item = $rItems->Fetch()) {
    $arComplect[] = $item;
}

Получаем нужные свойства по массиву id торговых предложений:

function getInform($arrOffersIDs){
	$arrProductsIDs = array();
	foreach($arrOffersIDs as $intElementID){
		$mxResult = CCatalogSku::GetProductInfo(
			$intElementID, 4
		);
		if (is_array($mxResult))
		{
			$arrProductsIDs[] = $mxResult["ID"];
		}
	}
	return  CCatalogSKU::getOffersList(
		$arrProductsIDs,
		$iblockID = 4,
		$skuFilter = array('ID'=>$arrOffersIDs),
		$fields = array('ID','NAME','DETAIL_PICTURE'),
		$propertyFilter = array() );
}
				
print_r(getInform(array(45,87,98)));

Получаем нужные свойства всех торговых предложений:

function getInform($arrOffersIDs){
	$arrProductsIDs = array();
	foreach($arrOffersIDs as $intElementID){
		$mxResult = CCatalogSku::GetProductInfo(
			$intElementID, 
			4 //ID каталога с товаром
		);
		if (is_array($mxResult))
		{
			$arrProductsIDs[] = $mxResult["ID"];
		}
	}
	return  CCatalogSKU::getOffersList(
		$arrProductsIDs,
		$iblockID = 4, //ID каталога с товаром
		$skuFilter = array(),
		$fields = array('NAME','ID','DETAIL_PICTURE','PREVIEW_PICTURE', "DETAIL_PAGE_URL", "CML2_MANUFACTURER", "DETAIL_TEXT"),//Получаемые свойства
		$propertyFilter = array() );
}
print_r(getInform(array(45,87,98)));

Работа со скидками

Получаем скидки и правила работы с корзиной, которые были применены к товару. В файле result_modifier.php компонента sale.basket.basket получаем перечень примененных к товару скидок:

/** @var \Bitrix\Sale\BasketBase $basket */
$basket = (\Bitrix\Sale\Basket\Storage::getInstance(
    \Bitrix\Sale\Fuser::getId(),
    \Bitrix\Main\Context::getCurrent()->getSite()))
    ->getOrderableBasket();
$order = $basket->getOrder();
$discountApplyResults = $order->getDiscount()->getApplyResult(false);

Автогенерации правила работы с корзиной, добавление купона и его применение.

Код генерации:

require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
use Bitrix\Sale\Internals;
CModule::IncludeModule("catalog");
CModule::IncludeModule("iblock");
CModule::IncludeModule("sale");
global $APPLICATION;
$unixStart = strtotime(date("d.m.Y H:i:s"));
// 12 часов
$unixEnd = $unixStart+43200; 
$xcount = 0;
// размер случайной скидки от 1 до 10 процентов
$discountValue = rand(1,10); 
$Actions["CLASS_ID"] = "CondGroup";
$Actions["DATA"]["All"] = "AND";
$Actions["CLASS_ID"] = "CondGroup";
$Actions["CHILDREN"][0]["CLASS_ID"] = "ActSaleBsktGrp";
$Actions["CHILDREN"][0]["DATA"]["Type"] = "Discount";
$Actions["CHILDREN"][0]["DATA"]["Value"] = $discountValue;
$Actions["CHILDREN"][0]["DATA"]["Unit"] = "Perc";
$Actions["CHILDREN"][0]["DATA"]["All"] = "OR";
$DbParentEl = CIBlockElement::GetList(array(),array("SECTION_ID"=>array(10,11)),false,false,array("ID")); 
while($ParentId = $DbParentEl->Fetch()){
    //Массив товаров к которым будет применяться скидка
    $Actions["CHILDREN"][0]["CHILDREN"][$xcount]["CLASS_ID"] = "CondIBElement"; 
    $Actions["CHILDREN"][0]["CHILDREN"][$xcount]["DATA"]["logic"] = "Equal";
    $Actions["CHILDREN"][0]["CHILDREN"][$xcount]["DATA"]["value"] = $ParentId["ID"];
    $xcount++;	
}
$Conditions["CLASS_ID"] = "CondGroup";
$Conditions["DATA"]["All"] = "AND";
$Conditions["DATA"]["True"] = "True";
$Conditions["CHILDREN"] = "";
// массив для создания правила
$arFields = array(
    "LID"=>"s1",
    "NAME"=>$discountValue."% Скидки ".date("d.m.y"),
    "CURRENCY"=>"RUB",
    "ACTIVE"=>"Y",
    "USER_GROUPS"=>array(1),
    "ACTIVE_FROM"=>ConvertTimeStamp($unixStart, "FULL"),
    "ACTIVE_TO"=>ConvertTimeStamp($unixEnd, "FULL"),
    "CONDITIONS"=>$Conditions,
    'ACTIONS' => $Actions
    );
// создаем правило корзины
$ID = CSaleDiscount::Add($arFields); 
$res = $ID>0;
if ($res) { 	
        // генирация купона
    $codeCoupon = CatalogGenerateCoupon(); 
        $fields["DISCOUNT_ID"] = $ID;
    $fields["COUPON"] = $codeCoupon;
    $fields["ACTIVE"] = "Y";
    $fields["TYPE"] = 2;
    $fields["MAX_USE"] = 0;
        // создаем купон для этого правила
    $dd = Internals\DiscountCouponTable::add($fields); 
    if (!$dd->isSuccess())
    {
        $err = $dd->getErrorMessages();
    }else{
        echo 'Купон на скидку: '.$codeCoupon;
    }
}else{
    $ex = $APPLICATION->GetException();  
    echo 'Ошибка: '.$ex->GetString();
}

Код вызова:

require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
use Bitrix\Main\Loader;
use Bitrix\Sale\DiscountCouponsManager;
CModule::IncludeModule("sale");
$check = DiscountCouponsManager::isExist($_POST['coupon']);
if($check["ID"]>0){
    DiscountCouponsManager::add($_POST['coupon']); 	
    echo "ok";
}else{
    echo 'Такого купона не существует';
}
Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!
Эйч Маркетинг