Оглавление

Задача

Задача, обновить остатки товаров по складам средствами API, например по запросу со стороны внешнего сервиса (REST API). Допустим что нам передаётся ID товара, ID склада и остаток на этом складе.

Решение

Для начала нам нужно получить ID записи в таблице БД об остатках конкретного товара на складе (создать её если нет).


<?

//Получим ID записи в таблице складских остатков 
$arStoreProduct = \Bitrix\Catalog\StoreProductTable::getList([
	'filter' => ['=PRODUCT_ID'=>$prodcutId, '=STORE_ID'=>$storeId],
	'select' => ['*'],
])->fetchAll();

//На всякий случай проверим, а есть ли записиси вообще
if(empty($arStoreProduct)){
	//Создаём запись об остатках, если её нет
	$productResUpdate = \Bitrix\Catalog\StoreProductTable::add([
		'STORE_ID' => $storeId,
		'PRODUCT_ID' => $prodcutId,
		'AMOUNT' => $quantity
	]);
	
} else {
	//Обновляем запись
	$storeProductData = current($arStoreProduct);
	//Доступное количество
	$offerProductData = [
		'AMOUNT' => $quantity
	];

	$productResUpdate = \Bitrix\Catalog\StoreProductTable::update($storeProductData['ID'], $offerProductData);
}

Готово. При добавлении записи есть нюанс. \Bitrix\Catalog\StoreProductTable::add() не проверяет, есть ли указанный в STORE_ID склад или нет, а просто добавляет запись в таблице. Если не проверить предварительно наличие склада по переданному $storeId вы рискуете получить некорректные данные по остаткам, а именно остатки на несуществующих складах и их не будет видно в админке.

Поэтому прежде чем выполнять код выше, следует получить список существующих, активных складов и проверить есть ли такой склад как $storeId. 


<? 

//Получим список существующих складов
$arStoresById = [];
$arStores = \Bitrix\Catalog\StoreTable::getList([
	'select' => ['*','UF_*'],
	'filter' => ['ACTIVE'=>'Y']
])->fetchAll();

foreach ($arStores as $store){
	if($store['ID']){
		$arStoresByXmlId[$store['ID']] = [
			'XML_ID' => $store['XML_ID'],
			'TITLE' => $store['TITLE']
		];
	}
}

 и далее 


<?

if($arStoresByXmlId[$storeId]) {
	//выполняем обновление остатков
}

После того, как вы обновили остатки товара на складе, вам следует обновить свойство "Доступный остаток" у самого товара. Это разные сущности и они никак не связаны по умолчанию. Так что теперь нам придётся получить все записи по остаткам этого товара на складах, просуммировать свободный остаток и обновить данные товара.


<?

$arStoreProduct = \Bitrix\Catalog\StoreProductTable::getList([
	'filter' => ['=PRODUCT_ID'=>$prodcutId],
	'select' => ['*'],
])->fetchAll();
		
		
$amount = 0;
foreach ($arStoreProduct as $store){
	$amount += ($store['AMOUNT'] - $store['QUANTITY_RESERVED']);
}

$offerProductData = [
	'ID' => $productId,
	'AVAILABLE' => ($amount > 0) ? 'Y' : 'N',
	'QUANTITY' => $amount
];

$productResUpdate = \Bitrix\Catalog\Model\Product::update($productId, $offerProductData);
if($productResUpdate->isSuccess()){
	//возвращаем некий успешный ответ
} else {
	//или информацию об ошибке $productResUpdate->getErrorMessages()
}	

Готово. Теперь вы знаете как обновлять остатки товаров на складах в 1С Битрикс.

И полный листинг кода:


<?

//Входящие параметры
$prodcutId = 123; //ID товара
$storeId = 1; //ID склада
$quantity = 10; //Количество товара на складе

//Получим список существующих складов
$arStoresById = [];
$arStores = \Bitrix\Catalog\StoreTable::getList([
	'select' => ['*','UF_*'],
	'filter' => ['ACTIVE'=>'Y']
])->fetchAll();

foreach ($arStores as $store){
	if($store['ID']){
		$arStoresByXmlId[$store['ID']] = [
			'XML_ID' => $store['XML_ID'],
			'TITLE' => $store['TITLE']
		];
	}
}

//Получим ID записи в таблице складских остатков 
//Тут может быть цикл, т.к. данные могут прийти не по единичному товару/складу
$arStoreProduct = \Bitrix\Catalog\StoreProductTable::getList([
	'filter' => ['=PRODUCT_ID'=>$prodcutId, '=STORE_ID'=>$storeId],
	'select' => ['*'],
])->fetchAll();

//На всякий случай проверим, а есть ли записи вообще
if(empty($arStoreProduct)){
	//Создаём запись об остатках, если её нет
	$productResUpdate = \Bitrix\Catalog\StoreProductTable::add([
		'STORE_ID' => $storeId,
		'PRODUCT_ID' => $prodcutId,
		'AMOUNT' => $quantity
	]);
	
} else {
	//Обновляем запись
	$storeProductData = current($arStoreProduct);
	//Доступное количество
	$offerProductData = [
		'AMOUNT' => $quantity
	];

	$productResUpdate = \Bitrix\Catalog\StoreProductTable::update($storeProductData['ID'], $offerProductData);
}


//Т.к. информация может обновиться на нескольких складах, достаём данные по всем сразу
//После обновления остатков на складе, обновляем достпный остаток у товара
$arStoreProduct = \Bitrix\Catalog\StoreProductTable::getList([
	'filter' => ['=PRODUCT_ID'=>$prodcutId],
	'select' => ['*'],
])->fetchAll();
		
$amount = 0;
foreach ($arStoreProduct as $store){
	$amount += ($store['AMOUNT'] - $store['QUANTITY_RESERVED']);
}

$offerProductData = [
	'ID' => $productId,
	'AVAILABLE' => ($amount > 0) ? 'Y' : 'N',
	'QUANTITY' => $amount
];

$productResUpdate = \Bitrix\Catalog\Model\Product::update($productId, $offerProductData);
if($productResUpdate->isSuccess()){
	//возвращаем некий успешный ответ
} else {
	//или информацию об ошибке $productResUpdate->getErrorMessages()
}	

Желаю удачи!

Полезная статья?
(Голосов: 2, Рейтинг: 3.44)
Вам также могут понравиться
Упрощенная имитация HTTP-ответов в тестах Laravel

Упрощенная имитация HTTP-ответов в тестах Laravel

В статье рассмотрен пример работы с мок-данными для тестирования работы приложения с HTTP-ответами.

Английский для программистов

Английский для программистов

Почему IT-специалисту необходимо освоить английский язык? Разбираем в статье.

Как подключить CSS и JS файлы к шаблону 1С Битрикс

Как подключить CSS и JS файлы к шаблону 1С Битрикс

Как правильно подключать стили и скрипты к шаблону 1С Битрикс.


Комментарии
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке