Your IP : 216.73.216.86


Current Path : /var/www/homesaver/www/bitrix/modules/webdebug.antirutin/include/actions/
Upload File :
Current File : /var/www/homesaver/www/bitrix/modules/webdebug.antirutin/include/actions/PriceChange.php

<?
class CWDA_PriceChange extends CWDA_Plugin {
	CONST GROUP = 'CATALOG';
	CONST CODE = 'PRICE_CHANGE';
	CONST NAME = 'Пересчет цен - наценки и скидки';
	//
	static function GetDescription() {
		$Descr = 'Плагин для изменения цен. Доступны как увеличения цен, так и снижения. Имеется возможность увеличивать/уменьшать цены как процентным указанием (напр., <b>5%</b> [равно как и +5%] и <b>-5%</b>), так и числовым (напр., <b>200</b> [равно как и +200], и <b>-200</b>). Также доступна возможность округления несколькими способами.';
		if (!CWDA::IsUtf()) {
			$Descr = CWDA::ConvertCharset($Descr);
		}
		return $Descr;
	}
	static function GetMessage($Code, $ConvertCharset=false) {
		$MESS = array(
			'ROUND_3' => 'тысяч',
			'ROUND_2' => 'сотен',
			'ROUND_1' => 'десятков',
			'ROUND_0' => 'целых',
			'ROUND_M1' => 'десятых',
			'CASE_LOWER' => 'нижний («для примера»)',
			'CASE_UPPER' => 'верхний («ДЛЯ ПРИМЕРА»)',
			'CASE_UCWORDS' => 'первые буквы («Для Примера»)',
			'ALERT_NO_PRICE_SOURCE' => 'Укажите поле с ценой',
			'PRICE_RUB_FULL' => 'руб',
			'PRICE_RUB_SHORT' => 'р',
			//
			'FIELD_SOURCE' => 'Цена:',
			//
			'SELECT_PRICE_SOURCE' => 'Укажите здесь свойство инфоблока или цену торгового каталога (в случае установленного модуля «Каталог»), которое следует взять для сохранение в другое свойство/цену. Показаны значения только типов «Число» и «Строка».',
			'ADDITIONAL_SETTINGS' => 'Дополнительные опции',
			'PARAM_USE_PURCHASE' => 'Пересчет относительно закупочной цены',
			'PARAM_CHANGE_VALUE' => 'Значение наценки/скидки',
			'PARAM_ROUND' => 'Округлить до:',
			'PARAM_FORMAT' => 'Формат:',
			'PARAM_OFFERS' => 'Применить для торговых предложений',
			'PARAM_LIMIT_BELOW' => 'Ограничить минимальную цену<br/>относительно закупочной цены',
			//
			'HINT_PARAM_USE_PURCHASE' => 'Если данная опция включена, цена будет подсчитана на основе закупочной цены.',
			'HINT_PARAM_CHANGE_VALUE' => 'Значение можно указывать как в процентах, так и числом, например: <ul style=\'font-family:monospace\'><li>+5%</li><li>200</li><li>+200</li><li>-3%</li><li>-200</li></ul>',
			'HINT_PARAM_ROUND' => 'Опция позволяет округлять загружаемые цены до тысяч (12345.67 => 12000), сотен (12345.67 => 12300), десятков (12345.67 => 12350) и целых (12345.67 => 12346)',
			'HINT_PARAM_FORMAT' => 'Опция позволяет изменить формат сохранения валюты. Применяется только для сохранения цены в свойство инфоблока; при сохранении цены в торговый каталог сохраняется только число, цена форматируется на основании настроек валют в модуле «Валюты».',
			'HINT_PARAM_OFFERS' => 'Опция позволяет применить пересчет цен в том числе для торговых предложений, относящихся к обрабатываемым товарам',
			'HINT_PARAM_LIMIT_BELOW' => 'Опция позволяет снижать цены (применять скидки), ограничивая при этом ее нижнее значение - чтобы итоговая цена товаров не была ниже закупочной (плюс некоторый процент).',
			//
			'CATALOG_PURCHASING_PRICE' => 'Закупочная цена',
		);
		$MESS = trim($MESS[$Code]);
		if ($ConvertCharset && !CWDA::IsUtf()) {
			$MESS = CWDA::ConvertCharset($MESS);
		}
		return $MESS;
	}
	//
	static function AddHeadData() {
		?>
		<script>
		BX.addCustomEvent('onWdaAfterActionChange', function(){
			if(WdaCurrentAction=='<?=self::CODE?>'){
				WDA_<?=self::CODE?>_Fill();
			}
		});
		BX.addCustomEvent('onWdaBeforeSubmit', function(){
			if(WdaCurrentAction=='<?=self::CODE?>'){
				if ($.trim($('#wda_field_source').val())=='') {
					alert('<?=self::GetMessage('ALERT_NO_PRICE_SOURCE',true);?>');
					WdaCanSubmit = false;
				}
			}
		});
		//
		function WDA_<?=self::CODE?>_Fill(){
			var Select = $('#wda_filter_param');
			// Source
			var SelectSource = $('#wda_field_source').html(Select.html()); // Price
			SelectSource.find('optgroup').not('optgroup[data-group=PRICES]').not('optgroup[data-group=PROPERTIES]').remove();
			SelectSource.find('optgroup[data-group=PROPERTIES] option').not('[data-type^=N]').not('[data-type=S]').remove();
			SelectSource.find('optgroup[data-group=PRICES]').append('<option value="CATALOG_PURCHASING_PRICE" data-type="P"><?=self::GetMessage('CATALOG_PURCHASING_PRICE',true);?></option>');
			SelectSource.change();
			// Target
			var SelectTarget = $('#wda_field_target').html(Select.html()); // Property
			SelectTarget.find('optgroup').not('optgroup[data-group=PRICES]').not('optgroup[data-group=PROPERTIES]').remove();
			SelectTarget.find('optgroup[data-group=PROPERTIES] option').not('[data-type^=N]').not('[data-type=S]').remove();
			SelectTarget.find('[value=ID],[value=ACTIVE_DATE],[value=SECTION_GLOBAL_ACTIVE]').remove();
			SelectTarget.find('optgroup[data-group=PRICES]').append('<option value="CATALOG_PURCHASING_PRICE" data-type="P"><?=self::GetMessage('CATALOG_PURCHASING_PRICE',true);?></option>');
			SelectTarget.change();
		}
		</script>
		<?
	}
	static function GetPriceFormats() {
		// 1. [# руб] - обозначение валюты
		// 2. [ ] - разделитель тысяч
		// 3. [.] - разделитель дроби
		// 4. [2] - количество десятичных символов
		// 5. [Y] - скрывать незначащие десятичные нули
		$arResult = array(
			'[# '.self::GetMessage('PRICE_RUB_FULL').'.][ ][.][2][Y]',
			'[# '.self::GetMessage('PRICE_RUB_FULL').'][ ][.][2][Y]',
			'[# '.self::GetMessage('PRICE_RUB_SHORT').'.][ ][.][2][Y]',
			'[# '.self::GetMessage('PRICE_RUB_SHORT').'][ ][.][2][Y]',
			'[$#][ ][.][2][Y]',
			'[&euro;#][ ][.][2][Y]',
		);
		return $arResult;
	}
	static function FormatPrice($Price, $Format) {
		$Format = str_replace("][", "]\n[", $Format);
		$arFormat = explode("\n",$Format);
		if (is_array($arFormat)) {
			foreach($arFormat as $Key => $Value) {
				$arFormat[$Key] = substr($Value,1,-1);
			}
			$Price = FloatVal($Price);
			if ($arFormat[4]=='Y' && $Price==IntVal($Price)) {
				$arFormat[3] = 0;
			}
			$Price = number_format($Price,$arFormat[3],$arFormat[2],$arFormat[1]);
			$Format = str_replace('#',$Price,$arFormat[0]);
			return $Format;
		}
		return '';
	}
	static function ShowSettings($IBlockID=false) {
		?>
		<div id="wda_settings_<?=self::CODE?>">
			<div class="wda_settings_header"><?=self::GetMessage('FIELD_SOURCE');?></div>
			<div>
				<div><select name="params[field_source]" id="wda_field_source" class="wda_select_field"></select><?=CWDA::ShowHint(self::GetMessage('SELECT_SOURCE_PRICE'));?></div>
			</div>
			<br/>
			<div class="wda_settings_header"><?=self::GetMessage('PROP_GROUP_ADDITIONAL_SETTINGS');?></div>
			<div class="wda_additional_params" id="wda_additional_params_<?=self::CODE?>">
				<table>
					<tbody>
						<tr>
							<td class="label" colspan="2">
								<label for="wda_input_change_value"><?=self::GetMessage('PARAM_CHANGE_VALUE');?></label>
								<?=CWDA::ShowHint(self::GetMessage('HINT_PARAM_CHANGE_VALUE'));?>
							</td>
							<td class="value">
								<input type="text" name="params[change_value]" value="+10%" size="10" maxlength="10" id="wda_input_change_value" />
							</td>
						</tr>
						<tr>
							<td class="check">
								<input type="checkbox" name="params[use_purchase]" value="Y" id="wda_checkbox_use_purchase" />
							</td>
							<td class="label">
								<label for="wda_checkbox_use_purchase"><?=self::GetMessage('PARAM_USE_PURCHASE');?></label>
								<?=CWDA::ShowHint(self::GetMessage('HINT_PARAM_USE_PURCHASE'));?>
							</td>
							<td class="value"></td>
						</tr>
						<tr>
							<td class="check">
								<input type="checkbox" name="params[round]" value="Y" id="wda_checkbox_round" />
							</td>
							<td class="label">
								<label for="wda_checkbox_round"><?=self::GetMessage('PARAM_ROUND');?></label>
								<?=CWDA::ShowHint(self::GetMessage('HINT_PARAM_ROUND'));?>
							</td>
							<td class="value">
								<select name="params[round_value]">
									<?foreach(array(3,2,1,0,-1) as $fRound):?>
										<option value="<?=$fRound;?>"<?if($fRound==0):?> selected="selected"<?endif?>><?=self::GetMessage('ROUND_'.str_replace('-','M',$fRound));?></option>
									<?endforeach?>
								</select>
							</td>
						</tr>
						<tr>
							<td class="check">
								<input type="checkbox" name="params[format]" value="Y" id="wda_checkbox_format" />
							</td>
							<td class="label">
								<label for="wda_checkbox_format"><?=self::GetMessage('PARAM_FORMAT');?></label>
								<?=CWDA::ShowHint(self::GetMessage('HINT_PARAM_FORMAT'));?>
							</td>
							<td class="value">
								<?$arFormats = self::GetPriceFormats();?>
								<select name="params[format_value]">
									<?foreach($arFormats as $strFormat):?>
										<option value="<?=$strFormat;?>"><?=self::FormatPrice(45678.90, $strFormat);?></option>
									<?endforeach?>
								</select>
							</td>
						</tr>
						<tr>
							<td class="check">
								<input type="checkbox" name="params[offers]" value="Y" id="wda_checkbox_offers" />
							</td>
							<td class="label" colspan="2">
								<label for="wda_checkbox_offers"><?=self::GetMessage('PARAM_OFFERS');?></label>
								<?=CWDA::ShowHint(self::GetMessage('HINT_PARAM_OFFERS'));?>
							</td>
						</tr>
						<tr>
							<td class="check">
								<input type="checkbox" name="params[limit_below]" value="Y" id="wda_checkbox_limit_below" />
							</td>
							<td class="label">
								<label for="wda_checkbox_limit_below"><?=self::GetMessage('PARAM_LIMIT_BELOW');?></label>
								<?=CWDA::ShowHint(self::GetMessage('HINT_PARAM_LIMIT_BELOW'));?>
							</td>
							<td>
								<input type="text" name="params[limit_below_value]" value="+10%" size="10" maxlength="5" id="wda_limit_below_value" />
							</td>
						</tr>
					</tbody>
				</table>
			</div>
		</div>
		<?
	}
	static function ParsePrice($Price) {
		if (preg_match_all('#([\d\,.]{1})#is',$Price,$M)) {
			$Price = str_replace(',','.',implode($M[1]));
		}
		$Price = FloatVal($Price);
		return $Price;
	}
	static function ChangePrice($Price, $Delta) {
		if ($Price<0) {
			$Price = 0;
		}
		if (preg_match_all('#([\d\,\.\+\-%]{1})#is',$Delta,$M)) {
			$Delta = str_replace(',','.',implode($M[1]));
		}
		if (preg_match('#^\+([\d\,\.]+)%$#',$Delta,$M) || preg_match('#^([\d\,\.]+)%$#',$Delta,$M)) {
			$Price = $Price + Round($Price*$M[1]/100,2);
		} elseif (preg_match('#^\-([\d\,\.]+)%$#',$Delta,$M)) {
			$Price = $Price - Round($Price*$M[1]/100,2);
		} elseif (preg_match('#^\+([\d\,\.]+)$#',$Delta,$M) || preg_match('#^([\d\,\.]+)$#',$Delta,$M)) {
			$Price = $Price + $M[1];
		} elseif (preg_match('#^\-([\d\,\.]+)$#',$Delta,$M)) {
			$Price = $Price - $M[1];
		}
		if ($Price<0) {
			$Price = 0;
		}
		return $Price;
	}
	static function Process($ElementID, $arElement, $Params) {
		$bResult = false;
		$UsePurchasePrice = $Params['use_purchase']=='Y';
		// Source
		$SourcePriceID = false;
		if(preg_match('#^CATALOG_PRICE_(\d+)$#i',$Params['field_source'],$M)) {
			$SourcePriceID = IntVal($M[1]);
		}
		$SourcePropertyID = false;
		if(preg_match('#^PROPERTY_(\d+)$#i',$Params['field_source'],$M)) {
			$SourcePropertyID = IntVal($M[1]);
		}
		$SourcePurchasing = false;
		if($Params['field_source']=='CATALOG_PURCHASING_PRICE') {
			$SourcePurchasing = true;
		}
		$SourceCurrency = false;
		if ($SourcePriceID>0 || $SourcePropertyID>0 || $SourcePurchasing) {
			// 1. prepare source
			$PriceRaw = 0;
			if ($SourcePurchasing || $UsePurchasePrice) {
				if (CModule::IncludeModule('catalog')) {
					$arProduct = CCatalogProduct::GetByID($ElementID);
					if (is_array($arProduct)) {
						$PriceRaw = $arProduct['PURCHASING_PRICE'];
						$SourceCurrency = $arProduct['PURCHASING_CURRENCY'];
					}
				}
			} elseif ($SourcePriceID>0) {
				$PriceRaw = FloatVal($arElement['CATALOG_PRICE_'.$SourcePriceID]);
				$SourceCurrency = $arElement['CATALOG_CURRENCY_'.$SourcePriceID];
			} elseif ($SourcePropertyID>0) {
				$arProp = CWDA::GetPropertyFromArrayById($arElement['PROPERTIES'], $SourcePropertyID);
				$PriceRaw = $arProp['VALUE'];
				if (is_array($PriceRaw) && !empty($PriceRaw)) {
					foreach($PriceRaw as $PriceRawItem) {
						$PriceRaw = $PriceRawItem;
						break;
					}
				}
				$PriceRaw = self::ParsePrice($PriceRaw);
			}
			// 2. process price
			$PriceBefore = $PriceRaw;
			$PriceAfter = self::ChangePrice($PriceBefore, $Params['change_value']);
			$Price = $PriceAfter;
			// 2.1 handle min price (compare with purchasing price)
			$MinPrice = false;
			if (!$SourcePurchasing && $Params['limit_below']=='Y' && strlen($Params['limit_below_value']) && CModule::IncludeModule('catalog')){
				$arProduct = CCatalogProduct::GetByID($ElementID);
				if (is_array($arProduct)) {
					$PurchasingPriceValue = $arProduct['PURCHASING_PRICE'];
					$PurchasingPriceCurrency = $arProduct['PURCHASING_CURRENCY'];
					if($SourceCurrency!==false && $SourceCurrency!=$PurchasingPriceCurrency && CModule::IncludeModule('currency')){
						$PurchasingPriceValue = $PurchasingPriceValue*CCurrencyRates::GetConvertFactor($PurchasingPriceCurrency,$SourceCurrency);
						$PurchasingPriceCurrency = $SourceCurrency;
					}
					$MinPrice = self::ChangePrice($PurchasingPriceValue, $Params['limit_below_value']);
				}
			}
			if($MinPrice!==false && $Price<$MinPrice) {
				$Price = $MinPrice;
			}
			// 2.2 round price
			if ($Params['round']=='Y') {
				$Price = CWDA::RoundEx($Price, IntVal($Params['round_value']));
			}
			// 3. save value
			if ($SourcePropertyID>0) {
				if ($Params['format']=='Y') {
					$Price = self::FormatPrice($Price, $Params['format_value']);
				}
				CIBlockElement::SetPropertyValuesEx($ElementID, $arElement['IBLOCK_ID'], array($SourcePropertyID=>$Price));
				CWDA::Log('Set price for element #'.$ElementID.' from '.$PriceBefore.' to '.$PriceAfter.' (property #'.$SourcePropertyID.', change:'.$Params['change_value'].')', self::CODE);
				$bResult = true;
			} elseif ($SourcePriceID>0) {
				$Currency = 'RUB';
				if (strlen($SourceCurrency)) {
					$Currency = $SourceCurrency;
				}
				if (CWDA::SetProductPrice($ElementID, $SourcePriceID, $Price, $Currency)) {
					CWDA::Log('Set price for element #'.$ElementID.' from '.$PriceBefore.' to '.$PriceAfter.' (price #'.$SourcePriceID.', change:'.$Params['change_value'].')', self::CODE);
					$bResult = true;
				}
			} elseif ($SourcePurchasing) {
				if (CModule::IncludeModule('catalog')) {
					$Currency = 'RUB';
					if (strlen($SourceCurrency)) {
						$Currency = $SourceCurrency;
					}
					$arFields = array(
						'ID' => $ElementID,
						'PURCHASING_PRICE' => $Price,
						'PURCHASING_CURRENCY' => $Currency,
					);
					if (CCatalogProduct::Add($arFields)) {
						CWDA::Log('Set price ['.$Price.'] for element #'.$ElementID.' to price #'.$TargetPriceID, self::CODE);
						$bResult = true;
					} else {
						CWDA::Log('Error update '.$Target.' for element #'.$ElementID.', fields: '.print_r($arFields,1));
					}
				}
			}
		}
		// 4. process offers
		if ($Params['offers']=='Y' && CModule::IncludeModule('catalog')) {
			$OfferParams = $Params;
			$OfferParams['offers'] = 'N';
			$arCatalog = CCatalog::GetByID($arElement['IBLOCK_ID']);
			if ($arCatalog['OFFERS_IBLOCK_ID']>0 && $arCatalog['OFFERS_PROPERTY_ID']) {
				$resOffers = CIBlockElement::GetList(array('ID'=>'ASC'),array('IBLOCK_ID'=>$arCatalog['OFFERS_IBLOCK_ID'],'PROPERTY_'.$arCatalog['OFFERS_PROPERTY_ID']=>$ElementID),false,false,array('ID'));
				while ($arOffer = $resOffers->GetNext(false,false)) {
					$arOfferFields = CWDA::GetElementByID($arOffer['ID']);
					self::Process($arOffer['ID'], $arOfferFields, $OfferParams);
				}
			}
		}
		return $bResult;
	}
}
?>