Setting up automatic price recalculation by exchange rate in 1C-Bitrix
Base prices in the catalog are stored in one currency while exchange rate changes daily. If prices are fixed in EUR but customer pays in BYN — without automatic recalculation manager will manually update thousands of positions every morning. The currency module in Bitrix solves on-the-fly conversion, but real price recalculation requires additional setup.
On-the-fly conversion vs. recalculation of stored prices
These are two fundamentally different strategies.
On-the-fly conversion — price is stored in source currency (EUR), displayed to user converted by current rate from b_catalog_currency_rate. Method CCurrencyRates::ConvertCurrency(100, 'EUR', 'BYN') does this in one line. Advantage: nothing to recalculate. Disadvantage: price "floats", customer sees different amounts at different times of day.
Recalculation of stored prices — agent takes rate and updates values in b_catalog_price for target price type. Customer sees stable price until next recalculation. Suitable for B2B where counterparties expect fixed price list for the day.
Setting up automatic rate updates
Before recalculating prices, ensure rates update automatically. The currency module supports Central Bank of RF and ECB providers. For National Bank of RB (nbrb.by) and other banks you need custom provider — class implementing \Bitrix\Currency\RateProvider.
Rate update agent: \Bitrix\Currency\CurrencyManager::updateCurrencyRates(). Runs via cron (cron_events.php). Without cron agent executes only on hits — on low-traffic B2B portal rate may not update until afternoon.
Implementation through agent
Create agent that recalculates target price type after rate update:
-
Get current rate:
CCurrencyRates::GetConvertFactor('EUR', 'BYN'). -
Select products with source-currency prices: query
\Bitrix\Catalog\PriceTable::getList()filtered byCATALOG_GROUP_ID(price type) andCURRENCY. - Calculate new price: multiply base price by rate, round by currency rules.
-
Write to target price type:
\Bitrix\Catalog\PriceTable::update()for existing records.
Rounding — set in currency settings. For BYN usually to cents (2 decimal places). For wholesale prices may require rounding to whole rubles: round($price, 0).
Agent must work in batches — by 500 products per iteration to avoid max_execution_time. Use \Bitrix\Main\Application::getConnection()->startTransaction() for update atomicity.
Control and notifications
Add anomaly check: if rate changed more than 5% per day — don't update prices automatically, send admin notification via \Bitrix\Main\Mail\Event::send(). This protects from provider data errors.
Log recalculation to \Bitrix\Main\Diag\FileLogger — date, old rate, new rate, number of updated items. When investigating order discrepancies this log will be the only source of truth.







