Реалии белорусского бизнеса таковы, что все іншаземныя товары у нас принято считать в иностранной валюте, переводя в «деревянные» лишь при продаже. Соответственно в интернет-магазинах и интернет-витринах в подавляющем большинстве используются цены в долларах/евро/российских рублях, которые необходимо (по законодательству) выводить на front-end именно в национальной валюте.

Решений этой дилеммы я встречала множество: от умножения на курс при запросе пользователем страницы и кэширования, до ручного ввода менеджером ежедневно новых цен. И так, в ходе работы со многими сайтами пришло комбинированное решение — писать цены в валюте, а дальше раз/два в день их автоматически обновлять, получая данные курсов от Нацбанка. Сразу оговорюсь, что пример будет для белорусских сайтов и хостингов, однако адаптировать, думаю, не сложно.

Первое, что мы делаем — это создаем у шаблона товара три новых поля price, price_eur и price_usd. А также (на случай акций) два поля price_sale_eur и price_sale Т.е для нашего сайта в валюте евро, которая еще и в долларовом ценовом наполнении должна быть. Представим, что нашему клиенту нужно выводить все три валюты. Не самый простой экземпляр в общем :)

Почему не сразу евро в поле price и не перерасчет при запросе страницы? Ну
а — постоянная дополнительная нагрузка на сервер,
б — возможны косяки в работе других дополнений (например mfilter2),
в — не красивое решение :)

Теперь пишем пару цен в евро для дальнейшей проверки в карточках нескольких (или всех) товаров.

Следующим этапом нам нужно получить актуальный курс валют, умножить его на наши деньги по умолчанию и все это записать в базу. Итак, создаем новый сниппет, например price_in_cron, и пишем в нем следующие строки:

<?php
// адрес нашего банка
$content = file_get_contents("http://www.nbrb.by/Services/XmlExRates.aspx?ondate=".date("m/d/Y"));
$kurs = new SimpleXMLElement($content);
// порядковый номер валют, если откроете в браузере ссылку выше, увидите их
$eur = (string)$kurs->Currency[5]->Rate;
$usd = (string)$kurs->Currency[4]->Rate;
// теперь нам нужно вытянуть наши товары. Они лежит в каталоге с id=5 и их шаблон четвертый. 
$ids = $modx->runSnippet('pdoResources', array(
'parents'=> '5',
'depth' => 10,
'templates'=> '4',
'returnIds' => 1,
'limit'=>0
));
$arr = explode(',', $ids);
// Теперь мы должны пробежаться по списку и получить нужные нам поля. Причем в этом примере у нас есть поле с акционной ценой,
// которую менеджер заполняет также в евро.
foreach($arr as $id){
  $res = $modx->getObject('modResource', $id);
  //поле с ценой в евро от менеджера
  $price_euro = $res->getTVValue('price_eur');
  // поле для вывода национальной цены
  $price_rub = $res->getTVValue('price');
  // поле для перевода евро в доллары (коль надо, значит делаем и это)
  $price_usd = $res->getTVValue('price_usd');
  // поле с ценой по акции, заполняемой ручками менеджера
  $price_sale = $res->getTVValue('price_sale_eur');
  // акционная цены, которую мы должны умножить (благо только в нац. деньгах, но Вы можете умножать и на доллары, добавив еще поле)
  $price_sale_rub = $res->getTVValue('price_sale');
  // Немного пересчетов с обрезанием личший знаков и форматированием
  $price_rub1 = $price_euro * $eur;
  $price_usd1 =  $price_rub1 / $usd;
  $price_rub1 = round($price_rub1,2);
  $price_rub1 = sprintf("%.2f", $price_rub1);
  $price_usd1 = round($price_usd1,2);
  $price_usd1 = sprintf("%.2f", $price_usd1);
  $price_sale_rub1 = $price_sale * $eur;
  $price_sale_rub1 = round($price_sale_rub1,2);
  $price_sale_rub1 = sprintf("%.2f", $price_sale_rub1);

// проверка на то, чтобы затрагивать только те поля, которые отличаются. По желанию можно добавить еще проверок на нулевые значение и пр.
  if ($price_rub != $price_rub1) {
// пишем в наши пустые (старые) поля новые данные цен
    $res->setTVValue('price', $price_rub1);
    $res->setTVValue('price_usd', $price_usd1);
  }
// проверяем на пустоту поле с акцией и пишем в него национальную цену
  if ($price_sale != '') {
       $res->setTVValue('price_sale', $price_sale_rub1);
  }
}
// Поля для проверки :) Вызываем сниппет в каком-нибудь ресурсе, чтобы проверить работоспособность перед следующим этапом.
//После успешной проверки - сжечь :)
$textpage = 'Курс обновлен на '.date("m/d/Y").' Евро - '.$eur.', Доллар -'.$usd;
echo $textpage;


Ну вот. Пол дела сделано. Осталось все это мероприятие автоматизировать, чтобы не участвовать в периодическом обновлении цен лично. Для этого качаем приложение Cron Manager в стандартном репозитории MODX REVO (спасибо огромное Павлу, который привил мне к нему любовь). И (после установки, конечно), указываем в нем адрес нашего сниппета и время в минутах, через которое он должен выполняться. Ну и да — галочку на активности не забываем ставить.


Теперь идем на сервер. Рассмотрим пример на besthost.by (остальные по аналогии)
1. Левая панель — планировщик > создать
Команда
/usr/bin/php -f /var/www/логин/data/www/домен/assets/components/cronmanager/cron.php

Описание — чтобы не забыть пишите что хотите
Включено — галочка
Экспертный режим
Минуты — 0
Часы — 0,3,6,9,12,15,18,21 (У нас выше в Cron Manager стоит время на каждые три часа. Но лучше обновлять курсы в 9.30 утра, 12.30 дня и 16,00 вечера. Это я как немного знающий финансовые институты человек говорю :) )
Дни месяцев, Месяцы, Дни недели — везде символ *
Можете указать адрес e-mail вверху, чтобы получать ошибки, если они будут из-за неправильного пути, отсутствия файла и пр.


На этом все. Если ошибок нет — письма на почту не придет, а Ваши цены будут сами себя контролировать :)