Налаштування масового оновлення цін у 1С-Бітрікс
Поставщик надіслав прайс з новими закупівельними цінами — 3000 позицій. Роздрібна надбавка 40%. Потрібно оновити роздрібні ціни до ранку. Вручну — нереально. Імпорт через 1С — не завжди є інтеграція. Пряме оновлення через API Бітрікса — рішення за кілька годин налаштування.
Таблиця цін та типи цін
Ціни зберігаються в b_catalog_price. Ключові поля: PRODUCT_ID, CATALOG_GROUP_ID (тип ціни), PRICE, CURRENCY, QUANTITY_FROM, QUANTITY_TO (для цінових діапазонів).
Типи цін — b_catalog_group: BASE — базова, решта — додаткові (роздрібна, оптова, закупівельна). CATALOG_GROUP_ID = 1 зазвичай — базова ціна, але це залежить від конкретного встановлення.
Отримати ID типу ціни за назвою:
$priceType = \Bitrix\Catalog\GroupTable::getList([
'filter' => ['NAME' => 'Роздрібна'],
'select' => ['ID'],
])->fetch();
$priceTypeId = $priceType['ID'];
Масове оновлення через D7
Оновлення ціни одного товару:
// Перевірити, існує ли ціна
$existing = \Bitrix\Catalog\PriceTable::getList([
'filter' => ['PRODUCT_ID' => $productId, 'CATALOG_GROUP_ID' => $priceTypeId],
'select' => ['ID'],
])->fetch();
if ($existing) {
\Bitrix\Catalog\PriceTable::update($existing['ID'], [
'PRICE' => $newPrice,
'CURRENCY' => 'BYN',
]);
} else {
\Bitrix\Catalog\PriceTable::add([
'PRODUCT_ID' => $productId,
'CATALOG_GROUP_ID' => $priceTypeId,
'PRICE' => $newPrice,
'CURRENCY' => 'BYN',
]);
}
Для масового оновлення — цикл з пакетованням. При 3000 позиціях рекомендується пакет по 100 з паузою 50 мс, щоб не створювати піків навантаження на MySQL.
Розрахунок ціни за надбавкою
При завантаженні закупівельних цін роздрібна розраховується автоматично:
function calcRetailPrice(float $purchasePrice, float $markup): float {
return round($purchasePrice * (1 + $markup / 100), 2);
}
foreach ($newPrices as $item) {
$retail = calcRetailPrice($item['purchase_price'], 40.0);
updatePrice($item['product_id'], RETAIL_PRICE_TYPE_ID, $retail);
updatePrice($item['product_id'], PURCHASE_PRICE_TYPE_ID, $item['purchase_price']);
}
Завантаження з Excel/CSV
Прайс від поставщика найчастіше приходить в Excel або CSV. Для парсингу Excel використовується PhpSpreadsheet:
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load('/path/to/price.xlsx');
$sheet = $spreadsheet->getActiveSheet();
foreach ($sheet->getRowIterator(2) as $row) { // з другого рядка (пропускаємо заголовок)
$cells = $row->getCellIterator();
$cells->setIterateOnlyExistingCells(false);
$rowData = [];
foreach ($cells as $cell) {
$rowData[] = $cell->getValue();
}
$articul = $rowData[0]; // A: артикул
$newPurchase = (float)$rowData[3]; // D: закупівельна ціна
// Знайти товар за артикулом
$productId = findProductByArticul($articul);
if ($productId) {
updatePrice($productId, PURCHASE_PRICE_TYPE_ID, $newPurchase);
updatePrice($productId, RETAIL_PRICE_TYPE_ID, calcRetailPrice($newPurchase, 40.0));
}
}
Інвалідація кешу після оновлення
Після масового оновлення цін сторінки каталогу показують старі ціни з кешу. Скидання кешу для всього каталогу:
// Видалити кеш компонентів каталогу
\Bitrix\Main\Application::getInstance()->getTaggedCache()->clearByTag('catalog');
// Або скидання за інфоблоком
\Bitrix\Main\Application::getInstance()->getTaggedCache()->clearByTag('iblock_id_' . $iblockId);
Альтернатива — не скидати кеш масово, а чекати природного застарівання (TTL). Але якщо ціни змінилися на акційні з конкретним терміном, чекати не можна — скидання обов'язкове.
Журнал змін цін
Для аудиту рекомендується перед оновленням зберігати старі ціни в користувацьку таблицю catalog_price_history з полями (product_id, price_type_id, old_price, new_price, changed_by, changed_at). Це дозволяє відкотити помилкове оновлення та аналізувати динаміку цін.







