first commit
This commit is contained in:
207
class/class.CNB.php
Normal file
207
class/class.CNB.php
Normal file
@@ -0,0 +1,207 @@
|
||||
<?php
|
||||
|
||||
use KupShop\I18nBundle\Entity\Currency;
|
||||
use KupShop\KupShopBundle\Context\CurrencyContext;
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
|
||||
class CNB
|
||||
{
|
||||
private static $url = 'https://www.cnb.cz/cs/financni_trhy/devizovy_trh/kurzy_devizoveho_trhu/denni_kurz.txt';
|
||||
|
||||
// Allowed difference in percent between old and new currency
|
||||
private static $allow_difference = 10;
|
||||
|
||||
/**
|
||||
* @param false $admin
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function updateCurrencies($admin = false)
|
||||
{
|
||||
$new_currencies = self::getSharedCurrencies();
|
||||
|
||||
$currencyContext = ServiceContainer::getService(CurrencyContext::class);
|
||||
$em = ServiceContainer::getService('doctrine.orm.entity_manager');
|
||||
|
||||
$currencies = $currencyContext->getAll();
|
||||
|
||||
$defaultCurrency = $currencyContext->getDefaultId();
|
||||
if ($defaultCurrency == 'CZK') {
|
||||
$conversionRate = DecimalConstants::one();
|
||||
} else {
|
||||
$conversionRate = DecimalConstants::one()->div($new_currencies[$defaultCurrency]);
|
||||
}
|
||||
|
||||
$new_currencies['CZK'] = DecimalConstants::one();
|
||||
|
||||
/** @var Currency $currency */
|
||||
foreach ($currencies as $currency) {
|
||||
if ($currency->getSync() == 'Y') {
|
||||
$currency_name = $currency->getId();
|
||||
if (!empty($new_currencies[$currency_name])) {
|
||||
$value = self::prepPrice($new_currencies[$currency_name]);
|
||||
if (!$currency->getCorrections()->isZero()) {
|
||||
$value = $value->add(self::prepPrice($currency->getCorrections()));
|
||||
}
|
||||
|
||||
$value = $value->mul($conversionRate);
|
||||
|
||||
if ($currency->getRate()->isPositive()) {
|
||||
$old_currency = $currency->getRate()->asFloat();
|
||||
$new_currency = $value->asFloat();
|
||||
|
||||
$difference = ($old_currency - $new_currency) / ($old_currency / 100);
|
||||
|
||||
if (!$admin && abs($difference) > self::$allow_difference) {
|
||||
throw new Exception('Aktualizace kurzu měn selhala. Měna "'.$currency_name.'", rozdíl '.round($difference, 2)." % !!, stará = '{$old_currency}', nová = '{$new_currency}'");
|
||||
}
|
||||
}
|
||||
|
||||
$currency->setRate($value);
|
||||
|
||||
$currency->setSyncDateUpdated();
|
||||
}
|
||||
}
|
||||
}
|
||||
$em->flush();
|
||||
|
||||
$dispatcher = ServiceContainer::getService('event_dispatcher');
|
||||
$dispatcher->dispatch(new KupShop\KupShopBundle\Event\CNBSyncEvent(), KupShop\KupShopBundle\Event\CNBSyncEvent::NAME);
|
||||
}
|
||||
|
||||
public static function prepPrice($price, $div = null)
|
||||
{
|
||||
$price = toDecimal(floatval(str_replace(',', '.', trim($price))));
|
||||
|
||||
if ($div) {
|
||||
$div = toDecimal(floatval(str_replace(',', '.', trim($div))));
|
||||
if ($div->isPositive()) {
|
||||
$price = $price->div($div);
|
||||
}
|
||||
}
|
||||
|
||||
return $price;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getCurrency($currency): Decimal
|
||||
{
|
||||
if ($currency === 'CZK') {
|
||||
return Decimal::create(1, 20);
|
||||
}
|
||||
$currencies = static::getCurrencies();
|
||||
|
||||
if (!isset($currencies[$currency])) {
|
||||
throw new Exception("CNB: Undefined currency: {$currency}");
|
||||
}
|
||||
|
||||
return $currencies[$currency];
|
||||
}
|
||||
|
||||
/**
|
||||
* Download actual CNB currencies and update on shared DB.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function updateSharedCurrencies(): void
|
||||
{
|
||||
$currencies = self::downloadCurrencies();
|
||||
|
||||
foreach ($currencies as $id => $rate) {
|
||||
sqlQuery(
|
||||
'INSERT INTO kupshop_shared.cnb_currencies (id,rate)
|
||||
VALUES (:id, :rate)
|
||||
ON DUPLICATE KEY UPDATE id=:id, rate=:rate',
|
||||
[
|
||||
'id' => $id,
|
||||
'rate' => $rate,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Decimal[]
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getCurrencies(): array
|
||||
{
|
||||
static $currencies = null;
|
||||
|
||||
if (!$currencies) {
|
||||
$currencies = static::getSharedCurrencies();
|
||||
}
|
||||
|
||||
return $currencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Decimal[]
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
private static function downloadCurrencies(): array
|
||||
{
|
||||
$currencies_file = self::downloadFile();
|
||||
|
||||
$currencies = [];
|
||||
foreach ($currencies_file as $v) {
|
||||
$h = explode('|', $v);
|
||||
if (!empty($h[3])) {
|
||||
$currencies[$h[3]] = self::prepPrice($h[4], $h[2]);
|
||||
}
|
||||
}
|
||||
|
||||
return $currencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get CNB currencies from shared db.
|
||||
*/
|
||||
private static function getSharedCurrencies(): array
|
||||
{
|
||||
$result = sqlQueryBuilder()->select('id, rate')
|
||||
->from('kupshop_shared.cnb_currencies')
|
||||
->execute();
|
||||
|
||||
$currencies = [];
|
||||
|
||||
foreach ($result as $row) {
|
||||
$currencies[$row['id']] = Decimal::create($row['rate'], 20);
|
||||
}
|
||||
|
||||
return $currencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
private static function downloadFile(): array
|
||||
{
|
||||
$file = file(self::$url);
|
||||
|
||||
if ($file === false) {
|
||||
throw new Exception('Soubor CNB nedostupny.');
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
public static function setUrl(string $url)
|
||||
{
|
||||
self::$url = $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function convertPrice(Decimal $price, $from, $to)
|
||||
{
|
||||
$exchange_rate = self::getCurrency($from)->div(self::getCurrency($to));
|
||||
|
||||
return $price->mul($exchange_rate);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user