16 private static $separateSkuMode =
null;
18 private static $productPrices = [];
20 private static $basePriceType =
null;
22 private static $priceTypes =
null;
24 private static $extraList =
null;
26 private static $productList = [];
29 private static $queryElementDate;
38 return '\Bitrix\Catalog\PriceTable';
63 if (self::$separateSkuMode ===
null)
68 if (empty(self::$extraList) || self::$basePriceType == 0)
74 'select' => [
'ID',
'PRODUCT_ID',
'CATALOG_GROUP_ID',
'PRICE',
'CURRENCY',
'QUANTITY_FROM',
'QUANTITY_TO'],
75 'filter' => [
'=ID' => $id]
82 $price[
'CATALOG_GROUP_ID'] = (int)$price[
'CATALOG_GROUP_ID'];
83 if ($price[
'CATALOG_GROUP_ID'] != self::$basePriceType)
86 $productId = (int)$price[
'PRODUCT_ID'];
92 !self::$separateSkuMode
103 $filter->where(
'PRODUCT_ID',
'=', $productId);
104 $filter->where(
'CATALOG_GROUP_ID',
'!=', self::$basePriceType);
105 $filter->whereIn(
'EXTRA_ID', array_keys(self::$extraList));
106 if ($price[
'QUANTITY_FROM'] ===
null)
107 $filter->whereNull(
'QUANTITY_FROM');
109 $filter->where(
'QUANTITY_FROM',
'=', (
int)$price[
'QUANTITY_FROM']);
111 if ($price[
'QUANTITY_TO'] ===
null)
112 $filter->whereNull(
'QUANTITY_TO');
114 $filter->where(
'QUANTITY_TO',
'=', (
int)$price[
'QUANTITY_TO']);
117 $updatePriceTypes = [];
119 'select' => [
'ID',
'EXTRA_ID',
'CATALOG_GROUP_ID',
'QUANTITY_FROM',
'QUANTITY_TO'],
125 'PRICE' => $price[
'PRICE']*self::$extraList[$row[
'EXTRA_ID']],
126 'CURRENCY' => $price[
'CURRENCY'],
127 'TIMESTAMP_X' => $datetime
129 $fields[
'PRICE_SCALE'] = $fields[
'PRICE']*
$currency[
'CURRENT_BASE_RATE'];
132 if ($result->isSuccess())
133 $updatePriceTypes[$row[
'CATALOG_TYPE_ID']] = $row[
'CATALOG_TYPE_ID'];
135 unset($result, $fields,
$currency, $index);
154 $fields =
$data[
'fields'];
155 parent::prepareForAdd($result, $id, $fields);
156 if (!$result->isSuccess())
159 if (self::$separateSkuMode ===
null)
161 self::loadSettings();
171 'CATALOG_GROUP_ID' => 0,
175 'QUANTITY_FROM' =>
null,
176 'QUANTITY_TO' =>
null,
185 $fields = array_merge(
$defaultValues, array_diff_key($fields, $blackList));
187 $fields[
'PRODUCT_ID'] = (int)$fields[
'PRODUCT_ID'];
188 if ($fields[
'PRODUCT_ID'] <= 0)
191 Loc::getMessage(
'BX_CATALOG_MODEL_PRICE_ERR_WRONG_PRODUCT_ID')
195 $fields[
'CATALOG_GROUP_ID'] = (int)$fields[
'CATALOG_GROUP_ID'];
196 if (!isset(self::$priceTypes[$fields[
'CATALOG_GROUP_ID']]))
199 Loc::getMessage(
'BX_CATALOG_MODEL_PRICE_ERR_WRONG_CATALOG_GROUP_ID')
205 if ($fields[
'CATALOG_GROUP_ID'] == self::$basePriceType)
207 $fields[
'EXTRA_ID'] =
null;
208 if (isset(
$data[
'actions'][
'OLD_RECOUNT']))
210 if (
$data[
'actions'][
'OLD_RECOUNT'] ===
true)
211 $data[
'actions'][
'PARENT_PRICE'] =
true;
216 if ($fields[
'TMP_ID'] !==
null)
217 $fields[
'TMP_ID'] = mb_substr($fields[
'TMP_ID'], 0, 40);
219 static::checkQuantityRange($result, $fields);
221 if ($fields[
'EXTRA_ID'] !==
null)
223 $fields[
'EXTRA_ID'] = (int)$fields[
'EXTRA_ID'];
224 if (!isset(self::$extraList[$fields[
'EXTRA_ID']]))
226 unset($fields[
'EXTRA_ID']);
231 (!isset($fields[
'PRICE']) && !isset($fields[
'CURRENCY']))
232 || (isset(
$data[
'actions'][
'OLD_RECOUNT']) &&
$data[
'actions'][
'OLD_RECOUNT'] ===
true)
234 self::calculatePriceFromBase(
null, $fields);
238 if ($fields[
'PRICE'] ===
null)
241 Loc::getMessage(
'BX_CATALOG_MODEL_PRICE_ERR_WRONG_PRICE')
246 $fields[
'PRICE'] = self::checkPriceValue($fields[
'PRICE']);
247 if ($fields[
'PRICE'] ===
null || $fields[
'PRICE'] < 0)
250 Loc::getMessage(
'BX_CATALOG_MODEL_PRICE_ERR_WRONG_PRICE')
254 $fields[
'CURRENCY'] = (string)$fields[
'CURRENCY'];
255 if (!
Currency\CurrencyManager::isCurrencyExist($fields[
'CURRENCY']))
258 Loc::getMessage(
'BX_CATALOG_MODEL_PRICE_ERR_WRONG_CURRENCY')
262 if ($result->isSuccess())
265 if (isset($fields[
'PRICE_SCALE']))
266 $fields[
'PRICE_SCALE'] = self::checkPriceValue($fields[
'PRICE_SCALE']);
268 if (!isset($fields[
'PRICE_SCALE']))
272 $fields[
'PRICE_SCALE'] = $fields[
'PRICE']*
$currency[
'CURRENT_BASE_RATE'];
276 if (isset(
$data[
'actions'][
'PARENT_PRICE']))
277 unset(
$data[
'actions'][
'PARENT_PRICE']);
278 if (!self::$separateSkuMode)
282 $data[
'actions'][
'PARENT_PRICE'] =
true;
285 if (isset(
$data[
'actions'][
'RECOUNT_PRICES']))
287 if ($fields[
'CATALOG_GROUP_ID'] != self::$basePriceType)
288 unset(
$data[
'actions'][
'RECOUNT_PRICES']);
290 $data[
'actions'][
'RECOUNT_PRICES'] =
true;
293 $data[
'fields'] = $fields;
313 Loc::getMessage(
'BX_CATALOG_MODEL_PRICE_ERR_WRONG_PRICE_ID')
318 if (self::$separateSkuMode ===
null)
320 self::loadSettings();
323 $fields =
$data[
'fields'];
324 parent::prepareForUpdate($result, $id, $fields);
325 if (!$result->isSuccess())
332 $fields = array_diff_key($fields, $blackList);
334 if (array_key_exists(
'PRODUCT_ID', $fields))
336 $fields[
'PRODUCT_ID'] = (int)$fields[
'PRODUCT_ID'];
337 if ($fields[
'PRODUCT_ID'] <= 0)
339 Loc::getMessage(
'BX_CATALOG_MODEL_PRICE_ERR_WRONG_PRODUCT_ID')
343 if (array_key_exists(
'CATALOG_GROUP_ID', $fields))
345 $fields[
'CATALOG_GROUP_ID'] = (int)$fields[
'CATALOG_GROUP_ID'];
346 if (!isset(self::$priceTypes[$fields[
'CATALOG_GROUP_ID']]))
349 Loc::getMessage(
'BX_CATALOG_MODEL_PRICE_ERR_WRONG_CATALOG_GROUP_ID')
354 if ($fields[
'CATALOG_GROUP_ID'] == self::$basePriceType)
356 $fields[
'EXTRA_ID'] =
null;
357 if (isset(
$data[
'actions'][
'OLD_RECOUNT']))
359 if (
$data[
'actions'][
'OLD_RECOUNT'] ===
true)
360 $data[
'actions'][
'PARENT_PRICE'] =
true;
366 if (isset($fields[
'TMP_ID']))
367 $fields[
'TMP_ID'] = mb_substr($fields[
'TMP_ID'], 0, 40);
369 $existQuantityFrom = array_key_exists(
'QUANTITY_FROM', $fields);
370 $existQuantityTo = array_key_exists(
'QUANTITY_TO', $fields);
371 if ($existQuantityFrom != $existQuantityTo)
373 if ($existQuantityFrom)
375 Loc::getMessage(
'BX_CATALOG_MODEL_PRICE_ERR_QUANTITY_RANGE_LEFT_BORDER_ONLY')
379 Loc::getMessage(
'BX_CATALOG_MODEL_PRICE_ERR_QUANTITY_RANGE_RIGHT_BORDER_ONLY')
384 if ($existQuantityFrom)
385 static::checkQuantityRange($result, $fields);
387 unset($existQuantityTo, $existQuantityFrom);
389 if (isset($fields[
'EXTRA_ID']))
391 $fields[
'EXTRA_ID'] = (int)$fields[
'EXTRA_ID'];
392 if (!isset(self::$extraList[$fields[
'EXTRA_ID']]))
395 Loc::getMessage(
'BX_CATALOG_MODEL_PRICE_ERR_WRONG_EXTRA_ID')
401 (!isset($fields[
'PRICE']) && !isset($fields[
'CURRENCY']))
402 || (isset(
$data[
'actions'][
'OLD_RECOUNT']) &&
$data[
'actions'][
'OLD_RECOUNT'] ===
true)
404 self::calculatePriceFromBase($id, $fields);
408 if (array_key_exists(
'PRICE', $fields))
410 $fields[
'PRICE'] = self::checkPriceValue($fields[
'PRICE']);
411 if ($fields[
'PRICE'] ===
null || $fields[
'PRICE'] < 0)
414 Loc::getMessage(
'BX_CATALOG_MODEL_PRICE_ERR_WRONG_PRICE')
419 if (array_key_exists(
'CURRENCY', $fields))
421 $fields[
'CURRENCY'] = (string)$fields[
'CURRENCY'];
422 if (!
Currency\CurrencyManager::isCurrencyExist($fields[
'CURRENCY']))
425 Loc::getMessage(
'BX_CATALOG_MODEL_PRICE_ERR_WRONG_CURRENCY')
430 if ($result->isSuccess())
432 if (isset(
$data[
'actions'][
'PARENT_PRICE']))
433 unset(
$data[
'actions'][
'PARENT_PRICE']);
435 $priceScale = !isset($fields[
'PRICE_SCALE']) && (isset($fields[
'PRICE']) || isset($fields[
'CURRENCY']));
436 $needCalculatePrice = (
437 !self::$separateSkuMode
439 isset($fields[
'PRODUCT_ID'])
440 || isset($fields[
'CATALOG_GROUP_ID'])
441 || isset($fields[
'PRICE'])
442 || isset($fields[
'CURRENCY'])
445 $recountPrices = isset(
$data[
'actions'][
'RECOUNT_PRICES']);
448 if ($priceScale || $needCalculatePrice || $recountPrices)
449 $copyFields = array_merge(static::getCacheItem($id,
true), $fields);
451 if (isset($fields[
'PRICE_SCALE']))
453 $fields[
'PRICE_SCALE'] = self::checkPriceValue($fields[
'PRICE_SCALE']);
454 if ($fields[
'PRICE_SCALE'] ===
null || $fields[
'PRICE_SCALE'] < 0)
455 unset($fields[
'PRICE_SCALE']);
457 if (!isset($fields[
'PRICE_SCALE']))
459 if (isset($fields[
'PRICE']) || isset($fields[
'CURRENCY']))
463 $fields[
'PRICE_SCALE'] = $copyFields[
'PRICE']*
$currency[
'CURRENT_BASE_RATE'];
467 if ($needCalculatePrice)
471 $data[
'actions'][
'PARENT_PRICE'] =
true;
474 if (isset(
$data[
'actions'][
'RECOUNT_PRICES']))
476 if ($copyFields[
'CATALOG_GROUP_ID'] != self::$basePriceType)
477 unset(
$data[
'actions'][
'RECOUNT_PRICES']);
479 $data[
'actions'][
'RECOUNT_PRICES'] =
true;
486 $data[
'fields'] = $fields;
500 if ((
int)
$data[
'fields'][
'CATALOG_GROUP_ID'] === self::$basePriceType)
502 if (isset(self::$productPrices[
$data[
'fields'][
'PRODUCT_ID']]))
504 unset(self::$productPrices[
$data[
'fields'][
'PRODUCT_ID']]);
507 if (isset(
$data[
'actions'][
'RECOUNT_PRICES']))
509 self::recountPricesFromBase($id);
511 if (isset(
$data[
'actions'][
'PARENT_PRICE']))
514 $data[
'fields'][
'PRODUCT_ID'],
517 [0 =>
$data[
'fields'][
'CATALOG_GROUP_ID']]
520 self::updateProductModificationTime(
$data[
'fields'][
'PRODUCT_ID']);
532 $price = self::getCacheItem($id);
533 if ((
int)$price[
'CATALOG_GROUP_ID'] === self::$basePriceType)
535 if (isset(self::$productPrices[$price[
'PRODUCT_ID']]))
537 unset(self::$productPrices[$price[
'PRODUCT_ID']]);
540 if (isset(
$data[
'actions'][
'RECOUNT_PRICES']))
542 self::recountPricesFromBase($id);
544 if (isset(
$data[
'actions'][
'PARENT_PRICE']))
546 $priceTypes = [0 => $price[
'CATALOG_GROUP_ID']];
548 isset($price[self::PREFIX_OLD.
'CATALOG_GROUP_ID'])
549 && $price[self::PREFIX_OLD.
'CATALOG_GROUP_ID'] != $price[
'CATALOG_GROUP_ID']
551 $priceTypes[] = $price[self::PREFIX_OLD.
'CATALOG_GROUP_ID'];
555 isset($price[self::PREFIX_OLD.
'PRODUCT_ID'])
556 && $price[self::PREFIX_OLD.
'PRODUCT_ID'] != $price[
'PRODUCT_ID']
561 self::updateProductModificationTime($price[
'PRODUCT_ID']);
563 isset($price[self::PREFIX_OLD.
'PRODUCT_ID'])
564 && $price[self::PREFIX_OLD.
'PRODUCT_ID'] != $price[
'PRODUCT_ID']
567 self::updateProductModificationTime($price[self::PREFIX_OLD.
'PRODUCT_ID']);
580 $price = self::getCacheItem($id);
585 $price[self::PREFIX_OLD.
'PRODUCT_ID'],
588 [0 => $price[self::PREFIX_OLD.
'CATALOG_GROUP_ID']]
591 if (!empty($product))
593 self::updateProductModificationTime($price[self::PREFIX_OLD.
'PRODUCT_ID']);
595 unset($product, $price);
608 if (
$fields[
'QUANTITY_FROM'] !==
null)
611 if (
$fields[
'QUANTITY_FROM'] <= 0)
613 Loc::getMessage(
'BX_CATALOG_MODEL_PRICE_ERR_WRONG_QUANTITY_FROM')
616 if (
$fields[
'QUANTITY_TO'] !=
null)
619 if (
$fields[
'QUANTITY_TO'] <= 0)
621 Loc::getMessage(
'BX_CATALOG_MODEL_PRICE_ERR_WRONG_QUANTITY_TO')
624 if (
$fields[
'QUANTITY_FROM'] !==
null &&
$fields[
'QUANTITY_TO'] !=
null)
628 $result->addError(
new ORM\EntityError(
629 Loc::getMessage(
'BX_CATALOG_MODEL_PRICE_ERR_WRONG_QUANTITY_RANGE_ZERO')
634 $result->addError(
new ORM\EntityError(
636 'BX_CATALOG_MODEL_PRICE_ERR_WRONG_QUANTITY_RANGE_INVERT',
637 [
'#LEFT#' =>
$fields[
'QUANTITY_FROM'],
'#RIGHT#' =>
$fields[
'QUANTITY_TO']]
651 private static function checkPriceValue($price)
657 if (is_string($price))
659 if ($price !==
'' && is_numeric($price))
661 $price = (float)$price;
662 if (is_finite($price))
668 || (is_float($price) && is_finite($price))
678 private static function loadSettings()
680 self::$separateSkuMode = Main\Config\Option::get(
'catalog',
'show_catalog_tab_with_offers') ===
'Y';
682 self::$extraList = [];
685 self::$extraList[$row[
'ID']] = (100 + (float)$row[
'PERCENTAGE']) / 100;
690 self::$priceTypes = Catalog\GroupTable::getTypeList();;
693 private static function calculatePriceFromBase($id,
array &$fields)
696 $copyFields = $fields;
698 !isset($fields[
'PRODUCT_ID'])
699 || !isset($fields[
'CATALOG_GROUP_ID'])
700 || !array_key_exists(
'QUANTITY_FROM', $fields)
701 || !array_key_exists(
'QUANTITY_TO', $fields)
708 'select' => [
'ID',
'PRODUCT_ID',
'CATALOG_GROUP_ID',
'QUANTITY_FROM',
'QUANTITY_TO'],
709 'filter' => [
'=ID' => $id]
715 $copyFields = array_merge(
$data, $copyFields);
731 if (!isset(self::$productPrices[$productId]))
732 self::loadProductBasePrices($productId);
734 $index = self::getPriceIndex($copyFields);
735 if (!isset(self::$productPrices[$productId][$index]))
738 $fields[
'PRICE'] = self::$productPrices[
$productId][$index][
'PRICE']*self::$extraList[$copyFields[
'EXTRA_ID']];
739 $fields[
'CURRENCY'] = self::$productPrices[
$productId][$index][
'CURRENCY'];
742 private static function getPriceIndex(
array $row): string
744 return ($row[
'QUANTITY_FROM'] ===
null ?
'ZERO' : $row[
'QUANTITY_FROM']).
745 '-'.($row[
'QUANTITY_TO'] ===
null ?
'INF' : $row[
'QUANTITY_TO']);
748 private static function loadProductBasePrices($productId)
750 self::$productPrices = [
753 $iterator = Catalog\PriceTable::getList([
754 'select' => [
'ID',
'PRICE',
'CURRENCY',
'QUANTITY_FROM',
'QUANTITY_TO'],
755 'filter' => [
'=PRODUCT_ID' => $productId,
'=CATALOG_GROUP_ID' => self::$basePriceType]
758 self::$productPrices[
$productId][self::getPriceIndex($row)] = $row;
764 parent::clearSettings();
766 self::$separateSkuMode =
null;
767 self::$basePriceType =
null;
768 self::$priceTypes =
null;
769 self::$extraList =
null;
772 private static function updateProductModificationTime(
int $productId): void
774 if (!isset(self::$productList[$productId]))
776 self::$productList[$productId] =
true;
778 if (self::$queryElementDate ===
null)
780 $helper = $conn->getSqlHelper();
782 .
' set '.$helper->quote(
'TIMESTAMP_X') .
' = '.$helper->getCurrentDateTimeFunction()
783 .
' where '.$helper->quote(
'ID') .
'=';
785 $conn->queryExecute(self::$queryElementDate . $productId);
static getConnection($name="")
static getList(array $parameters=array())
static update($primary, array $data)
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)