Picture this: an online store with 10,000 products; a supplier price list arrives daily at 6 a.m. Manual updates take 3 hours, and by 10 a.m. prices are already outdated if the supplier changes them at 8 a.m. Automation solves this: a scheduled cron update reduces latency to minutes and eliminates input errors. We automate price synchronization from external sources into 1C-Bitrix—from parsing price lists to anomaly control. Our experience shows that proper setup pays off within a few weeks. We have 5+ years of experience in 1C-Bitrix integrations with external systems and have delivered over 50 price automation projects. Get a free project assessment.
How to Set Up Scheduled Price Updates in 1C-Bitrix
Data Sources for Prices
Suppliers provide prices in various formats. Let's compare them:
| Format | Delivery Method | Complexity | Reliability |
|---|---|---|---|
| CSV/Excel | FTP, link, email | Low | Medium |
| XML (YML, CommerceML) | HTTP, FTP | Medium | High |
| REST API | HTTP requests | High | High |
| 1C export | CommerceML | Medium | High |
Each format requires its own handler, but the price update logic in Bitrix is the same. Parsing via API is 10 times more reliable than manual entry—it eliminates the human factor.
Price Structure in Bitrix
Prices are stored in the b_catalog_price table. Key fields: PRODUCT_ID, CATALOG_GROUP_ID, PRICE, CURRENCY. To update a price via API:
\Bitrix\Catalog\PriceTable::update($priceId, [ 'PRICE' => $newPrice, 'CURRENCY' => 'RUB', ]); Bitrix Documentation: PriceTable API
Update Algorithm
Step 1. Load the price list. The script fetches the file via FTP (ftp_get()), downloads by URL (file_get_contents()), or requests the supplier's API.
Step 2. Parse. CSV is parsed with fgetcsv(), Excel with PhpSpreadsheet, XML with SimpleXMLElement. The result is an array of "product identifier → price" pairs. We use batch processing to handle large volumes efficiently, and transactions ensure atomicity.
Step 3. Map. The supplier's SKU is matched to a Bitrix catalog element. Search by property PROPERTY_SUPPLIER_ARTICLE or XML_ID:
$element = CIBlockElement::GetList( [], ['IBLOCK_ID' => $catalogIblockId, 'PROPERTY_ARTICLE' => $supplierArticle], false, ['nTopCount' => 1], ['ID'] )->Fetch(); Step 4. Update. Write the new price to b_catalog_price. When updating thousands of items, use direct SQL queries or D7 batch updates—element-by-element updates via CPrice::SetBasePrice() are too slow.
Markups and Formulas
The supplier gives the purchase price. The retail price is calculated using formulas:
- Fixed markup: retail = purchase × 1.3 (30%).
- Progressive: markup depends on price range (cheap items 50%, expensive 15%).
- Rounding:
ceil($price / 10) * 10 - 1→ price 1,287 → 1,289.
Markup formulas are stored in configuration, not hardcoded. This allows managers to change rules via the admin interface.
| Purchase Range | Markup | Example |
|---|---|---|
| Up to 500 ₽ | 50% | 300 → 450 ₽ |
| 500–5,000 ₽ | 30% | 2,000 → 2,600 ₽ |
| Over 5,000 ₽ | 15% | 10,000 → 11,500 ₽ |
Cron Setup
Price updates are triggered by cron:
# Load supplier A price list—daily at 6:00 0 6 * * * /usr/bin/php /home/bitrix/scripts/update_prices.php --source=supplier_a >> /var/log/price_update.log 2>&1 # Load supplier B price list—daily at 6:30 30 6 * * * /usr/bin/php /home/bitrix/scripts/update_prices.php --source=supplier_b >> /var/log/price_update.log 2>&1 Stagger updates in time—parallel imports stress the database and can cause deadlocks.
Why Anomaly Control Matters?
Blindly updating prices is risky. A mistake in the supplier's price list (e.g., 100 instead of 10,000) leads to losses. Protection mechanisms:
- Change threshold—if a price changes by more than 30%, do not update automatically; flag for manual review.
- Logging—a
price_update_logtable with fields: product, old price, new price, source, date. Allows rolling back erroneous updates. - Notification—email or Telegram alert to the manager for anomalies.
- Idempotency checks prevent duplicate updates if the script runs twice.
$changePercent = abs($newPrice - $oldPrice) / $oldPrice * 100; if ($changePercent > 30) { logAnomaly($productId, $oldPrice, $newPrice, $source); continue; // Skip update } Cache Clearing After Update
After a mass price update, clear the catalog cache; otherwise users see old prices:
\Bitrix\Iblock\ElementTable::getEntity()->cleanCache(); BXClearCache(true, '/catalog/'); For sites with composite cache, additionally call \Bitrix\Main\Composite\Engine::deleteAllCache() or selectively clear pages of changed products.
Our Approach and What's Included
We use a proven methodology:
- Analysis—examine supplier data sources, price list structure, format.
- Design—develop handler architecture, mapping rules, and markup formulas.
- Implementation—write load, parse, and update code; configure cron.
- Testing—verify on a test catalog with 100 representative products, simulate anomalies.
- Deployment—go live, set up monitoring and notifications.
Work package includes:
- Analysis of data sources and formats.
- Development of parsers for each source.
- Configuration of SKU mapping and markup formulas.
- Implementation of control mechanisms (thresholds, logging, notifications).
- Cron task and monitoring setup.
- Documentation and instructions for the manager.
- One-month warranty of correct operation.
A real-world case: for a client with 12,000 SKUs and three suppliers, we reduced update time from 2.5 hours to 12 minutes and caught a 150% price anomaly that would have caused a 40,000 ₽ loss. The project paid for itself in three weeks.
Contact us—we'll help set up a turnkey price update solution. Get a consultation for your project. Order a free assessment—we'll analyze your sources and propose the optimal solution.

