Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
price.php
1<?php
3
12class Price
13{
14 /* cache id template */
15 const CACHE_ID = 'catalog_price_round_';
16 /* cache time */
17 const CACHE_TIME = 360000;
18 /* maximal precision */
19 const VALUE_EPS = 1E-6;
20
21 /* static cache */
22 protected static $roundRules = array();
23
30 public static function handlerAfterUpdateCurrencyBaseRate(Main\Event $event)
31 {
32 $params = $event->getParameters();
33 if (empty($params))
34 return;
35
36 $oldBaseRate = (float)$params['OLD_BASE_RATE'];
37 if ($oldBaseRate < 1E-4)
38 return;
39 $currentBaseRate = (float)$params['CURRENT_BASE_RATE'];
40 if (abs($currentBaseRate - $oldBaseRate)/$oldBaseRate < 1E-4)
41 return;
42 $currency = $params['CURRENCY'];
43
44 $conn = Main\Application::getConnection();
45 $helper = $conn->getSqlHelper();
46
47 $query = 'update '.$helper->quote(Catalog\PriceTable::getTableName()).
48 ' set '.$helper->quote('PRICE_SCALE').' = '.$helper->quote('PRICE').' * '.$currentBaseRate.
49 ' where '.$helper->quote('CURRENCY').' = \''.$helper->forSql($currency).'\'';
50 $conn->queryExecute($query);
51
52 if (defined('BX_COMP_MANAGED_CACHE'))
53 {
54 $taggedCache = Main\Application::getInstance()->getTaggedCache();
55 $taggedCache->clearByTag('currency_id_'.$currency);
56 }
57 }
58
65 public static function loadRoundRules(array $priceTypes)
66 {
67 if (empty($priceTypes))
68 return;
69 Main\Type\Collection::normalizeArrayValuesByInt($priceTypes);
70 if (empty($priceTypes))
71 return;
72
73 $skipCache = (defined('CATALOG_SKIP_CACHE') && CATALOG_SKIP_CACHE);
74 $cacheTime = (int)self::CACHE_TIME;
76 $managedCache = Main\Application::getInstance()->getManagedCache();
77
78 $needLoad = array();
79 foreach ($priceTypes as $priceTypeId)
80 {
81 if (!isset(self::$roundRules[$priceTypeId]))
82 {
83 $rulesFound = false;
84 $cacheId = static::getRulesCacheId($priceTypeId);
85 if (!$skipCache)
86 {
87 $cacheExist = $managedCache->read($cacheTime, $cacheId, Catalog\RoundingTable::getTableName());
88 if ($cacheExist)
89 {
90 $rulesFound = true;
91 self::$roundRules[$priceTypeId] = $managedCache->get($cacheId);
92 }
93 }
94 if ($skipCache || !$rulesFound)
95 $needLoad[] = $priceTypeId;
96 unset($cacheId, $rulesFound);
97 }
98 }
99 unset($priceTypeId);
100
101 if (!empty($needLoad))
102 {
103 foreach ($needLoad as $priceTypeId)
104 self::$roundRules[$priceTypeId] = array();
105 unset($priceTypeId);
106 $iterator = Catalog\RoundingTable::getList(array(
107 'select' => array('PRICE', 'ROUND_TYPE', 'ROUND_PRECISION', 'CATALOG_GROUP_ID'),
108 'filter' => array('@CATALOG_GROUP_ID' => $needLoad),
109 'order' => array('CATALOG_GROUP_ID' => 'ASC', 'PRICE' => 'DESC')
110 ));
111 while ($row = $iterator->fetch())
112 {
113 $priceTypeId = (int)$row['CATALOG_GROUP_ID'];
114 self::$roundRules[$priceTypeId][] = $row;
115 unset($priceTypeId);
116 }
117 unset($row, $iterator);
118
119 if (!$skipCache)
120 {
121 foreach ($needLoad as $priceTypeId)
122 $managedCache->set(static::getRulesCacheId($priceTypeId), self::$roundRules[$priceTypeId]);
123 unset($priceType);
124 }
125 }
126 unset($needLoad);
127 unset($managedCache, $cacheTime, $skipCache);
128 }
129
136 public static function getRoundRules($priceType)
137 {
138 $priceType = (int)$priceType;
139 if ($priceType <= 0)
140 return array();
141 if (!isset(self::$roundRules[$priceType]))
142 static::loadRoundRules(array($priceType));
143
144 return self::$roundRules[$priceType];
145 }
146
153 public static function clearRoundRulesCache($priceType)
154 {
155 $priceType = (int)$priceType;
156 if ($priceType <= 0)
157 return;
158 if (isset(self::$roundRules[$priceType]))
159 unset(self::$roundRules[$priceType]);
160 Main\Application::getInstance()->getManagedCache()->clean(
161 static::getRulesCacheId($priceType),
163 );
164 }
165
174 public static function searchRoundRule(
175 $priceType,
176 $price,
177 $currency = ''
178 )
179 {
180 $rules = static::getRoundRules($priceType);
181 if (empty($rules))
182 return array();
183 foreach ($rules as $row)
184 {
185 if ($row['PRICE'] < $price)
186 return $row;
187 }
188 return array();
189 }
190
199 public static function roundPrice($priceType, $price, $currency)
200 {
201 $price = (float)$price;
202 if ($price <= 0)
203 return $price;
204 $priceType = (int)$priceType;
205 if ($priceType <= 0)
206 return $price;
207 $rule = static::searchRoundRule($priceType, $price, $currency);
208 if (empty($rule))
209 return $price;
210 return static::roundValue($price, $rule['ROUND_PRECISION'], $rule['ROUND_TYPE']);
211 }
212
221 public static function roundValue($value, $precision, $type)
222 {
223 $type = (int)$type;
224 if (!in_array($type, Catalog\RoundingTable::getRoundTypes(false)))
225 return $value;
226
227 $precision = (float)$precision;
228 if ($precision <= 0)
229 return 0;
230 if ($precision >= 1)
231 $precision = (int)$precision;
232
233 $value = (float)$value;
234 if (abs($value) <= self::VALUE_EPS)
235 return 0;
236
237 return ($precision < 1
238 ? static::roundFraction($value, $precision, $type)
239 : static::roundWhole($value, $precision, $type)
240 );
241 }
242
249 protected static function getRulesCacheId($priceType)
250 {
251 return self::CACHE_ID.$priceType;
252 }
253
262 protected static function roundWhole($value, $precision, $type)
263 {
264 $quotient = $value/$precision;
265 $quotientFloor = floor($quotient);
266 switch ($type)
267 {
268 case Catalog\RoundingTable::ROUND_UP:
269 if (($quotient - $quotientFloor) > self::VALUE_EPS)
270 $quotientFloor += 1;
271 break;
272 case Catalog\RoundingTable::ROUND_DOWN:
273 if ($quotientFloor < floor(($value + self::VALUE_EPS)/$precision))
274 $quotientFloor += 1;
275 break;
276 case Catalog\RoundingTable::ROUND_MATH:
277 default:
278 if (($quotient - $quotientFloor + self::VALUE_EPS) >= .5)
279 $quotientFloor += 1;
280 break;
281 }
282
283 return $quotientFloor*$precision;
284 }
285
294 protected static function roundFraction($value, $precision, $type)
295 {
296 $valueFloor = floor($value);
297 $fraction = $value - $valueFloor;
298 if ($fraction <= self::VALUE_EPS)
299 return $value;
300
301 return $valueFloor + static::roundWhole($fraction, $precision, $type);
302 }
303}
static searchRoundRule( $priceType, $price, $currency='')
Definition price.php:174
static roundFraction($value, $precision, $type)
Definition price.php:294
static getRulesCacheId($priceType)
Definition price.php:249
static roundWhole($value, $precision, $type)
Definition price.php:262
static getRoundRules($priceType)
Definition price.php:136
static clearRoundRulesCache($priceType)
Definition price.php:153
static roundPrice($priceType, $price, $currency)
Definition price.php:199
static handlerAfterUpdateCurrencyBaseRate(Main\Event $event)
Definition price.php:30
static roundValue($value, $precision, $type)
Definition price.php:221
static getRoundTypes(bool $full=false)
Definition rounding.php:443