Оглавление
Задача
Задача, обновить остатки товаров по складам средствами 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()
}
Желаю удачи!