• Модуль: catalog
  • Путь к файлу: ~/bitrix/modules/catalog/lib/model/product.php
  • Класс: BitrixCatalogModelProduct
  • Вызов: Product::prepareForUpdate
static function prepareForUpdate(ORMDataUpdateResult $result, $id, array &$data): void
{
	$id = (int)$id;
	if ($id <= 0)
	{
		$result->addError(new ORMEntityError(
			Loc::getMessage('BX_CATALOG_MODEL_PRODUCT_ERR_WRONG_PRODUCT_ID')
		));
		return;
	}

	$iblockId = 0;
	if (isset($data['external_fields']['IBLOCK_ID']))
		$iblockId = (int)$data['external_fields']['IBLOCK_ID'];
	if ($iblockId <= 0)
		$iblockId = CIBlockElement::GetIBlockByID($id);
	if (empty($iblockId))
	{
		$result->addError(new ORMEntityError(
			Loc::getMessage('BX_CATALOG_MODEL_PRODUCT_ERR_ELEMENT_NOT_EXISTS')
		));
		return;
	}
	$iblockData = CCatalogSku::GetInfoByIBlock($iblockId);
	if (empty($iblockData))
	{
		$result->addError(new ORMEntityError(
			Loc::getMessage('BX_CATALOG_MODEL_PRODUCT_ERR_SIMPLE_IBLOCK')
		));
		return;
	}
	$data['external_fields']['IBLOCK_ID'] = $iblockId;

	$fields = $data['fields'];
	parent::prepareForUpdate($result, $id, $fields);
	if (!$result->isSuccess())
		return;

	if (self::$separateSkuMode === null)
	{
		self::$separateSkuMode = MainConfigOption::get('catalog', 'show_catalog_tab_with_offers') === 'Y';
	}

	static $quantityFields = null,
		$paymentPeriods = null,
		$tripleFields = null,
		$booleanFields = null,
		$nullFields = null,
		$sizeFields = null,
		$blackList = null;

	if ($quantityFields === null)
	{
		$quantityFields = ['QUANTITY', 'QUANTITY_RESERVED'];
		$paymentPeriods = CatalogProductTable::getPaymentPeriods(false);
		$tripleFields = ['QUANTITY_TRACE', 'CAN_BUY_ZERO', 'SUBSCRIBE'];
		$booleanFields = ['WITHOUT_ORDER', 'SELECT_BEST_PRICE', 'VAT_INCLUDED', 'BARCODE_MULTI', 'BUNDLE', 'AVAILABLE'];
		$nullFields = ['MEASURE', 'TRIAL_PRICE_ID', 'VAT_ID', 'RECUR_SCHEME_LENGTH'];
		$sizeFields = ['WIDTH', 'LENGTH', 'HEIGHT'];

		$blackList = [
			'ID' => true,
			'NEGATIVE_AMOUNT_TRACE' => true
		];
	}
	$fields = array_diff_key($fields, $blackList);

	$allowedTypes = self::getProductTypes($iblockData['CATALOG_TYPE']);

	if (array_key_exists('TYPE', $fields))
	{
		$fields['TYPE'] = (int)$fields['TYPE'];
		if (!isset($allowedTypes[$fields['TYPE']]))
		{
			$result->addError(new ORMEntityError(
				Loc::getMessage('BX_CATALOG_MODEL_PRODUCT_ERR_BAD_PRODUCT_TYPE')
			));
			return;
		}
	}

	foreach ($quantityFields as $fieldName)
	{
		if (array_key_exists($fieldName, $fields))
		{
			if ($fields[$fieldName] === null)
				unset($fields[$fieldName]);
			else
				$fields[$fieldName] = (float)$fields[$fieldName];
		}
	}
	foreach ($tripleFields as $fieldName)
	{
		if (array_key_exists($fieldName, $fields))
		{
			if (
				$fields[$fieldName] != CatalogProductTable::STATUS_NO
				&& $fields[$fieldName] != CatalogProductTable::STATUS_YES
				&& $fields[$fieldName] != CatalogProductTable::STATUS_DEFAULT
			)
				unset($fields[$fieldName]);
		}
	}
	if (isset($fields['SUBSCRIBE']))
		$data['actions'][self::ACTION_SEND_NOTIFICATIONS] = true;
	foreach ($booleanFields as $fieldName)
	{
		if (array_key_exists($fieldName, $fields))
		{
			if (
				$fields[$fieldName] != CatalogProductTable::STATUS_NO
				&& $fields[$fieldName] != CatalogProductTable::STATUS_YES
			)
				unset($fields[$fieldName]);
		}
	}
	foreach ($nullFields as $fieldName)
	{
		if (isset($fields[$fieldName]))
		{
			$fields[$fieldName] = (int)$fields[$fieldName];
			if ($fields[$fieldName] <= 0)
			{
				$fields[$fieldName] = null;
			}
		}
	}
	foreach ($sizeFields as $fieldName)
	{
		if (isset($fields[$fieldName]))
		{
			$fields[$fieldName] = (float)$fields[$fieldName];
			if ($fields[$fieldName] <= 0)
			{
				$fields[$fieldName] = null;
			}
		}
	}
	unset($fieldName);

	if (array_key_exists('PRICE_TYPE', $fields))
	{
		if (
			$fields['PRICE_TYPE'] != CatalogProductTable::PAYMENT_TYPE_REGULAR
			&& $fields['PRICE_TYPE'] != CatalogProductTable::PAYMENT_TYPE_TRIAL
			&& $fields['PRICE_TYPE'] != CatalogProductTable::PAYMENT_TYPE_SINGLE
		)
			unset($fields['PRICE_TYPE']);
	}
	if (array_key_exists('RECUR_SCHEME_TYPE', $fields))
	{
		if (!in_array($fields['RECUR_SCHEME_TYPE'], $paymentPeriods, true))
			unset($fields['RECUR_SCHEME_TYPE']);
	}

	if (array_key_exists('WEIGHT', $fields))
	{
		if ($fields['WEIGHT'] === null)
		{
			unset($fields['WEIGHT']);
		}
		else
		{
			$fields['WEIGHT'] = (float)$fields['WEIGHT'];
			$data['actions'][self::ACTION_RECALCULATE_SETS] = true;
		}
	}
	if (isset($fields['TMP_ID']))
	{
		$fields['TMP_ID'] = mb_substr($fields['TMP_ID'], 0, 40);
	}

	if (array_key_exists('QUANTITY_RESERVED', $fields) && (float)$fields['QUANTITY_RESERVED'] < 0)
	{
		$result->addError(new ORMEntityError(
			Loc::getMessage('BX_CATALOG_MODEL_PRODUCT_ERR_QUANTITY_RESERVE_LESS_ZERO'),
			'BX_CATALOG_MODEL_PRODUCT_ERR_QUANTITY_RESERVE_LESS_ZERO'
		));
	}

	/* purchasing price */
	$existPurchasingPrice = array_key_exists('PURCHASING_PRICE', $fields);
	$existPurchasingCurrency = array_key_exists('PURCHASING_CURRENCY', $fields);
	if ($existPurchasingPrice)
	{
		$fields['PURCHASING_PRICE'] = static::checkPriceValue($fields['PURCHASING_PRICE']);
		if ($fields['PURCHASING_PRICE'] === null)
		{
			$fields['PURCHASING_CURRENCY'] = null;
			$existPurchasingCurrency = false;
		}
	}
	if ($existPurchasingCurrency)
	{
		$fields['PURCHASING_CURRENCY'] = static::checkPriceCurrency($fields['PURCHASING_CURRENCY']);
		if ($fields['PURCHASING_CURRENCY'] === null)
		{
			$result->addError(new ORMEntityError(
				Loc::getMessage('BX_CATALOG_MODEL_PRODUCT_ERR_WRONG_PURCHASING_CURRENCY')
			));
		}
	}
	/* purchasing price end */

	if ($result->isSuccess())
	{
		if (isset($fields['CAN_BUY_ZERO']))
			$fields['NEGATIVE_AMOUNT_TRACE'] = $fields['CAN_BUY_ZERO'];
		$fields['TIMESTAMP_X'] = new MainTypeDateTime();

		if (isset($fields['AVAILABLE']))
		{
			$copyFields =
				isset($fields['TYPE'])
					? $fields
					: array_merge(static::getCacheItem($id, true), $fields)
			;
			$copyFields['TYPE'] = (int)$copyFields['TYPE'];
			$isService = $copyFields['TYPE'] === CatalogProductTable::TYPE_SERVICE;
			if ($isService)
			{
				//TODO: remove this hack after reservation resource
				$fields['QUANTITY'] = $fields['AVAILABLE'] !== CatalogProductTable::STATUS_YES ? 0 : 1;
			}
			if (!$isService)
			{
				$data['actions'][self::ACTION_CHANGE_PARENT_AVAILABLE] = true;
			}
			$data['actions'][self::ACTION_RECALCULATE_SETS] = true;
			$data['actions'][self::ACTION_SEND_NOTIFICATIONS] = true;
		}
		else
		{
			$needCalculateAvailable = (isset($fields['TYPE'])
				|| isset($fields['QUANTITY'])
				|| isset($fields['QUANTITY_TRACE'])
				|| isset($fields['CAN_BUY_ZERO'])
			);
			if ($needCalculateAvailable)
			{
				$needCache = (!isset($fields['TYPE'])
					|| !isset($fields['QUANTITY'])
					|| !isset($fields['QUANTITY_TRACE'])
					|| !isset($fields['CAN_BUY_ZERO'])
				);
				$copyFields = (
					$needCache
					? array_merge(static::getCacheItem($id, true), $fields)
					: $fields
				);
				$copyFields['TYPE'] = (int)$copyFields['TYPE'];
				self::calculateAvailable($copyFields, $data['actions']);
				if ($copyFields['AVAILABLE'] !== null)
					$fields['AVAILABLE'] = $copyFields['AVAILABLE'];
				unset($copyFields, $needCache);
			}
			unset($needCalculateAvailable);
		}
		$data['fields'] = $fields;
	}

	unset($fields);
}