• Как пересчитать заказ с учетом всех скидок с использованием события OnSaleOrderSaved?

    @tgarl Автор вопроса
    и вызываю пересчет
    $basket->refreshData(array('PRICE', 'COUPONS'));
    $discount->calculate();


    если на отдельной странице вызвать
    spoiler

    $order_resave = \Bitrix\Sale\Order::load($now_order_id);
                $discount = $order_resave->getDiscount();
                \Bitrix\Sale\DiscountCouponsManager::clearApply(true);
                \Bitrix\Sale\DiscountCouponsManager::useSavedCouponsForApply(true);
                $discount->setOrderRefresh(true);
                $discount->setApplyResult(array());
    
                if (!($basket = $order_resave->getBasket())) {
                   throw new \Bitrix\Main\ObjectNotFoundException('Entity "Basket" not found');
                }
    
                $basket->refreshData(array('PRICE', 'COUPONS'));
                $discount->calculate();
    
                $order_resave->setField("PRICE", $order_resave->getPrice());
                $order_resave->save();


    то пересчет срабатывает, в событии нет
  • В один из разделов каталога выгружаются не все фотографии позиций. Как исправить?

    @tgarl
    Возможно какое-то ограничение в настройках сервера на одномоментное количество записей в файл. Столкнулся с похожей проблемой(и пришел к такому выводу), причем не предсказуемо где это проявится, а где нет. Например, на главной странице file_put_contents без вопросов всегда выполняется, а в контактах вставляешь тот же код фиг вам. Через пару недель наоборот. Из-за такой ситуации картинки в каталоге пропадают - файлы просто не сохраняются на сервере с выгрузкой, а в файле иморта указаны, поэтому старые затираются, а новых нет. Найдете причину отпишитесь, может и нам поможет.
  • Узнать купоны введенные пользователем в Bitrix?

    @tgarl
    Возможно вы что-то не так делаете. Мой пример выдает результат если купон был применен в корзине, но еще заказ не оформлен. Если нужно у сущестующего заказа, то
    сначала нужно заказ подгрузить
    $order = Bitrix\Sale\Order::load($order_id);
    далее
    
    $discounts  =  $order ->getDiscount();
     $res  =  $discounts ->getApplyResult();
    
    foreach($res['COUPON_LIST'] as $cupo_n=>$ar_r){

    кроме того может быть скидка без купона, тогда ключа COUPON_LIST не будет
    распечатайте массив $res и посмотрите что в нем получается
  • Как сделать акцию в битриксе 3 товара по цене 2?

    @tgarl Автор вопроса
    Ну думаю не последний раз у нас такая акция, перед следующим запуском протестирую ваше решение, возможно из описания я не все возможности увидел и понял. В моем решении периодически проскакивают ошибки - мой вариант сильно не оптимизирован(если кто-то им будет пользоваться учтите этот момент) и грузит сайт, что выдает иногда непредсказуемый результат например на 50 товаров 30 по цене 0. А вынос скидочного товара в отдельную позицию плохо сказывается на обмене с 1С(объединяет либо игнорирует товар ) и пересчет заказа у нас на сайте его удваивал.
  • Как сделать акцию в битриксе 3 товара по цене 2?

    @tgarl Автор вопроса
    Модуль полезный, но не подходит для моей задачи.

    Он не определяет самый дешевый товар, 3 товар это количественный или позиционный?
    если я закину 1 позицию на 3 ед по 10р и 1 позицию на 1 ед по 9р:
    итог скидка должна быть на товар за 9 рублей и не важно в какой последовательности я закину товары.

    если 1 позиця на 3 ед по 10 -> должна быть скидка на 10р
    если 1 позиция на 4 ед по 10р и 1 позиция по 2 ед на 11 -> мы должны получить скидку на 20р

    т.е. каждая самая дешевая 3 единица должна быть бесплатно
  • Как сделать акцию в битриксе 3 товара по цене 2?

    @tgarl Автор вопроса
    А вы можете поделиться примером как вы реализовали? Может я тогда пойму что не так в моем коде. По описанной вами задаче принцип похож.
  • Как сделать акцию в битриксе 3 товара по цене 2?

    @tgarl Автор вопроса
    Я у Романа в комментариях привел код, который я использовал.
    Скидка 3=2 в моем случае подразумевает следующее:
    закинули 3 позиции одного товара по 10р, получили не 30, а 20 рублей
    закинули еще 1 товар за 5 рублей, получили 30 рублей
    т.е. каждый 3 самый дешевый товар в корзиние должен быть бесплатным
    закинули 6 товаров, бесплатными должны стать 2 товара и.д.

    В приведенном мной коде у Романа получается корзина в виде:
    1вариант:
    товар | количество | цена | сумма
    а | 2 | 10 | 20
    a | 1 | 10 | 0

    2 вариант:
    товар | количество | цена | сумма
    а | 3 | 10 | 30
    b | 1 | 5 | 0

    но когда я перехожу к оформлению заказа происходит зацикливание и корзина меняется в большую сторону
  • Как сделать акцию в битриксе 3 товара по цене 2?

    @tgarl Автор вопроса
    Да именно через события корзины я и пошел.
    А рекурсия все-равно срабатывает((
    protected static $Action3for2Disallow = false;
    public static function Action3for2($event)
        {
    		
    		
    		if (self::$Action3for2Disallow) 
               return; 
    		/* взводим флаг запуска */
    		self::$Action3for2Disallow = true;  
    		global $USER;
    		
    		if(!is_object($USER)){
    			 $USER = new CUser();
    		}
    		$userId=$USER->GetID();
    		if ($userId=="81035" ){
    			$_SESSION["Action3for2"]=2;
    			Loader::IncludeModule('iblock');
    			Loader::IncludeModule('catalog');
    			Loader::IncludeModule('sale');
    			$basket = $event->getParameter("ENTITY");
    			
    			$res=[];
    			$tovar=[];
    			foreach ($basket as $basketItem) {
    				$basketPropertyCollection = $basketItem->getPropertyCollection(); 
    				
    				$res[]=[$basketItem->getProductId(),$basketItem->getPrice(), $basketItem->getQuantity(), $basketItem->getFinalPrice(), $basketPropertyCollection->getPropertyValues()['BAR_CODE']['VALUE']];
    				$tovar[]=$basketPropertyCollection->getPropertyValues()['BAR_CODE']['VALUE'];
    				$basketItem->delete();				
    			}
    			file_put_contents($_SERVER["DOCUMENT_ROOT"]."/even.txt", "\n** ".date("d.m.Y H:i:s")." ****". __FILE__ ." ". __LINE__ ."**********\n".print_r($res, true), FILE_APPEND | LOCK_EX);
    			
    			//удаляем если что-то есть в корзине
    			$fuser=\Bitrix\Sale\Fuser::getIdByUserId($userId);
    						
    			$coli=[];
    			foreach($res as $vl){
    				for ($x=1; $x<=$vl[2]; $x++){
    					$coli[]=[$vl[4],$vl[1]];
    				}
    			}
    			$cont=count($coli);
    			
    				usort($coli, function($a, $b){
    					return $a['1'] <=> $b['1'];
    				});
    				$skidka = floor($cont / 3);
    				for ($x=0; $x<$skidka; $x++){
    					$coli[$x][1]=0;
    				}
    				$coli = array_reverse($coli);
    				file_put_contents($_SERVER["DOCUMENT_ROOT"]."/even.txt", "\n** ".date("d.m.Y H:i:s")." ****". __FILE__ ." ". __LINE__ ."**********\n".print_r($coli, true), FILE_APPEND | LOCK_EX);
    				
    								
    				$arFilter = Array( "IBLOCK_ID"=>27, "PROPERTY_CML2_BAR_CODE"=>$tovar );
    				$res = \CIBlockElement::GetList(Array("SORT"=>"ASC",), $arFilter, false,false,array('ID',"PROPERTY_CML2_BAR_CODE",'CATALOG_QUANTITY','PROPERTY_CML2_LINK','IBLOCK_EXTERNAL_ID','XML_ID'));
    				$productsId=[];
    				$productsIdXml=[];
    				
    				while($ar_fields = $res->GetNext())
    				{
    					$productsId[$ar_fields["PROPERTY_CML2_BAR_CODE_VALUE"]]=$ar_fields['ID'];
    					$productsIdXml[$ar_fields["PROPERTY_CML2_BAR_CODE_VALUE"]]=['IBLOCK_EXTERNAL_ID'=>$ar_fields['IBLOCK_EXTERNAL_ID'],'XML_ID'=>$ar_fields['XML_ID']];
    				}
    				$itogTovar=[];
    				foreach($coli as $val){
    					$itogTovar[$val[1]][$val[0]]++;
    				}
    				file_put_contents($_SERVER["DOCUMENT_ROOT"]."/even.txt", "\n** ".date("d.m.Y H:i:s")." ****". __FILE__ ." ". __LINE__ ."**********\n".print_r($itogTovar, true), FILE_APPEND | LOCK_EX);
    				
    				
    					
    				
    				foreach($itogTovar as $price0=>$value){
    					foreach($value as $barcode=>$qunt){
    						$arParams = \bh\catalog\tools::getBasketPropsByOfferId($productsId[$barcode]);
    						unset($arParams['more_photos']);
    						unset($arParams['more_images']);
    						$arParams['CATALOG_XML_ID']=array(
    							'NAME' => 'Catalog XML_ID',
    							'CODE' => 'CATALOG.XML_ID',
    							'VALUE' => $productsIdXml[$barcode]['IBLOCK_EXTERNAL_ID']
    						);
    						$arParams['PRODUCT_XML_ID']=array(
    							"NAME" => "Product XML_ID",
    							"CODE" => "PRODUCT.XML_ID",
    							"VALUE" => $productsIdXml[$barcode]['XML_ID']
    						);
    						if($price0<1){
    							$arParams['ACTION']=array(
    								"NAME" => "ACTION",
    								"CODE" => "ACTION",
    								"VALUE" => 'Товар по акции 2=3'
    							);
    						}
    						
    						
    						$item = $basket->createItem('catalog', $productsId[$barcode]); //создаём новый товар в корзине
    						$itemField=[];
    						$itemField['CURRENCY']=\Bitrix\Currency\CurrencyManager::getBaseCurrency();
    						$itemField['LID']=\Bitrix\Main\Context::getCurrent()->getSite();
    						$itemField['PRODUCT_PROVIDER_CLASS']='CCatalogProductProvider';
    						$itemField['CATALOG_XML_ID']=$productsIdXml[$barcode]['IBLOCK_EXTERNAL_ID'];
    						$itemField['PRODUCT_XML_ID']=$productsIdXml[$barcode]['XML_ID'];
    						$itemField['QUANTITY']=$qunt;
    						if($price0<1){
    							$itemField['CUSTOM_PRICE']='Y';
    							$itemField['PRICE']=0;
    						}
    						
    						$item->setFields($itemField);
    						$item->getPropertyCollection()->setProperty($arParams);
    						
    					}					
    				}
    				
    			if(\CSaleBasket::DeleteAll($fuser,false)) {$basket->save();}
    			self::$Action3for2Disallow = true;  
    			
    		}
    	}


    Т.е. смысл такой что я после сохранения корзины собираю ее содержимое сортирую по ценнику и количеству. затем стирю то что есть сейчас и заливаю по тем ценам которые нужны. В самой корзине все отрабатывается как должно, но как только я перехожу на страницу оформления заказа товары начинают дублироваться. в итоге закинул на 300р, а на последенем шаге оформления заказа в заказ и соответсвенно на оплату уже тысяч 5 идет