Automatic filling of balances and prices from 1C-Bitrix supplier price lists

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1175
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

Auto-Filling Stock Levels and Prices from Supplier Price Lists in 1C-Bitrix

A supplier price list — an Excel or CSV file sent on a schedule via email or uploaded to FTP — differs from an API in that it is not updated in real time. For most B2B stores, however, updates once or twice a day are perfectly adequate. The task: extract prices and stock levels from a non-standard file and update b_catalog_price and b_catalog_store_product.

Retrieving the Price List

Email attachment — the most common scenario. Connect to the mailbox via IMAP, search for messages from the supplier, download the attachment:

$imap = imap_open('{mail.example.com:993/imap/ssl}INBOX', $user, $pass);
$emails = imap_search($imap, 'FROM "[email protected]" UNSEEN');
foreach ($emails as $num) {
    $structure = imap_fetchstructure($imap, $num);
    // extract attachment
}

FTP/SFTP — periodically download the file and compare its modification date against the previous run. If unchanged, skip it.

HTTP URL — the supplier publishes the price list at a URL, sometimes with Basic Auth.

Reading Excel/CSV

Use PhpSpreadsheet (the successor to PHPExcel) for Excel files:

$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($filePath);
$sheet = $spreadsheet->getActiveSheet();
$rows = $sheet->toArray();

The challenge: every supplier uses a different format. The SKU, price, and stock columns are in different positions, and the header rows vary in depth.

Solution: a configurable column mapping stored in the database:

supplier_id: 42
sku_column: B       # SKU in column B
price_column: D     # price in column D
qty_column: F       # stock in column F
header_rows: 3      # first 3 rows are headers

Updating Prices

Prices in 1C-Bitrix are stored in b_catalog_price. Each price type is a separate record:

$priceType = CCatalogPriceType::GetList([], ['NAME' => 'Purchase'])->Fetch();
CCatalogProduct::SetPrice($elementId, $priceType['ID'], $price, 'RUB');

If the supplier has multiple price types (retail, wholesale, special) — create the corresponding types in 1C-Bitrix and update each separately.

Markup on import: often the purchase price is imported and the retail price is calculated automatically. The markup coefficient is stored in the supplier settings and applied at write time:

$retailPrice = $supplierPrice * $supplier->getMarkupCoefficient();

Updating Stock Levels

b_catalog_store_product is the per-warehouse stock table. If warehouses are not in use, update QUANTITY directly via CCatalogProduct::Update().

With warehouses enabled:

CCatalogStoreProduct::Update($storeProductId, ['AMOUNT' => $qty]);
// or add a new record if it doesn't exist
CCatalogStoreProduct::Add([
    'PRODUCT_ID' => $elementId,
    'STORE_ID' => $storeId,
    'AMOUNT' => $qty,
]);

Product Identification by SKU

The price list contains supplier SKUs; 1C-Bitrix stores its own codes. A lookup table is required. Storage options:

  • A SUPPLIER_SKU property on the info block — simple
  • A SupplierMapping Highload block with (supplier_id, supplier_sku, element_id) tuples — scalable

For 50,000+ SKUs, build a reverse index in memory when the worker starts: load all pairs into a PHP array once and use it for mapping without repeated DB queries.

Project Timeline

Phase Duration
File retrieval setup (email/FTP/HTTP) 4–8 hours
Excel/CSV reading with configurable mapping 1–2 days
Price and stock updates in 1C-Bitrix 1 day
Product identification logic, SKU lookup table 4–8 hours
Error handling, logging, scheduling 4–6 hours

Total: 4–6 working days per supplier. With multiple suppliers, the configurable mapping pays for itself from the third connection onward.