Обучаю битриксу программистов, интеграторов. Подробнee ⇒

Манипуляции с товарами в сделке, купоны



У заказчика было несколько обработчиков на добавление и редактирование сделки
Для оптимизации объединила в 1.

Реализация купона  (купон - это свойство в сделке типа список (3 вида купона), который действует на некоторые виды товаров
20% от стоимости товара, но максимум 3000р

Считает сумму среднюю по чеку на 1 гостя, считает сколько на товары типа напитки, бар. декор и тд приходится

OnBeforeCrmDealAdd, OnBeforeCrmDealUpdate -  в них товары не меняются при изменении массива $arFields["PRODUCT_ROWS"]
OnBeforeCrmDealProductRowsSave - тут тоже не модифицируется товары (есть тикет в битриксе на доработку)
OnAfterCrmDealProductRowsSave - поэтому приходится после сохранения их еще раз сохранять. можно было бы сюда всю логику положить с модификацией товара, но так как мне еще надо свойства в сделке менять, то пришлось бы 2 раза делать выборки и прочее.

function CalcMultipleForDeal(&$arFields){
   //AddMessage2Log("CalcMultipleForDeal");
   if(isset($arFields["PRODUCT_ROWS"])){
      // global $USER;
      // if($USER->GetID()==54043){
      //    AddMessage2Log($arFields["PRODUCT_ROWS"]);
      // }      
      $entertSum = 0;// Развлечения 530
      $menuSum = 0;// Банкет 531
      $dopSum = 0;// Допы 533
      $barSum = 0;// Бар 532

      $sumAll = 0;

      $sumAverage = 0;

      $arSectionIds = [];
      
      $arProductIds = [];
      foreach($arFields["PRODUCT_ROWS"] as $arProduct){
         $arProductIds[] = $arProduct["PRODUCT_ID"];
      }

      if(!empty($arProductIds) && CModule::IncludeModule("iblock")){         

         //свойство в сделке купоны: UF_CRM_1708101511: 13928 13929 13930 
         $bCoupon = false;
         if(isset($arFields["UF_CRM_1708101511"])){
            //AddMessage2Log($arFields["UF_CRM_1708101511"]);
            if(in_array($arFields["UF_CRM_1708101511"],[13928, 13929, 13930])){
               $bCoupon = true;
            }
         }
         elseif(!empty($arFields["ID"]) && CModule::IncludeModule("crm")){ //если изменение сделки
            //получаем значение свойства купон
            $arFilter = array(
               "ID"=>$arFields["ID"], //выбираем определенную сделку по ID
               "CHECK_PERMISSIONS"=>"N" //не проверять права доступа текущего пользователя
            );            
            $arSelect = array(
               "ID",
               "UF_CRM_1708101511", //
               "UF_CRM_1530623573843",
                   "UF_CRM_1530623600935"
            );            
            $res = CCrmDeal::GetList(Array(), $arFilter, $arSelect);
            if($deal = $res->Fetch()){
               //AddMessage2Log($deal);
                  if(in_array($deal["UF_CRM_1708101511"],[13928, 13929, 13930])){
                  $bCoupon = true;
               }
            }            
         }

         if($bCoupon){   
            //AddMessage2Log("купон найден");            
            //скидка 20% от стоимости, максимум 3000р    
            $maxDiscount = 3000;
            
            //свойство, из которого брать PROPERTY_626
            // -Анимация  304  -Аренда 314  -Батут 298  -Декор 308  -Доп. услуги (подарок) 312  -Доп. услуги (шоу) 306  -Зал\Стол 316  -Носки 300   -Официант 328  -Пробка 326  -Тренер 302      
            $arTypesForCoupon = [304,314,298,308,312,306,316,300,328,326,302];


            
            
         }
         

         $arFilter = Array(
              "IBLOCK_ID"=>28,               
              "ID" => $arProductIds               
         );
         $arSelect = Array("ID","IBLOCK_ID","PROPERTY_4098","PROPERTY_626","IBLOCK_SECTION_ID");
         
         $res = CIBlockElement::GetList(Array("sort"=>"asc"), $arFilter, false, Array("nPageSize"=>150,"iNumPage"=>1), $arSelect);
         
         $arEntertIds = [];
         $arMenuIds = [];
         $arDopIds = [];
         $arBarIds = [];
         $arAverageIds = [];
         $arBatutIds = [];

         $arCouponItems = [];
         while($arItem = $res->Fetch()){
            
            if($bCoupon && !empty($arItem["PROPERTY_626_ENUM_ID"]) && in_array($arItem["PROPERTY_626_ENUM_ID"],$arTypesForCoupon)){
               $arCouponItems[$arItem["ID"]] = $arItem["ID"]; // товары, которые попадают по купоны
            }
            if($arItem["PROPERTY_4098_ENUM_ID"]==530){
                 $arEntertIds[$arItem["ID"]] = $arItem["ID"];// Развлечения
              }   
              elseif($arItem["PROPERTY_4098_ENUM_ID"]==531){// Банкет
                 $arMenuIds[$arItem["ID"]] = $arItem["ID"];                 
              }   
              elseif($arItem["PROPERTY_4098_ENUM_ID"]==532){// Бар
                 $arBarIds[$arItem["ID"]] = $arItem["ID"];              
              }
              elseif($arItem["PROPERTY_4098_ENUM_ID"]==533){// Допы
                 $arDopIds[$arItem["ID"]] = $arItem["ID"];              
              }
              elseif($arItem["PROPERTY_4098_ENUM_ID"]==298){// Допы
                 $arDopIds[$arItem["ID"]] = $arItem["ID"];              
              }
              if(in_array($arItem["PROPERTY_626_ENUM_ID"], [318,320,322])){ 
                    $arAverageIds[$arItem["ID"]] = $arItem["ID"];
                }
                elseif($arItem["PROPERTY_626_ENUM_ID"] == 298){//Батут
                   $arBatutIds[$arItem["ID"]] = $arItem["ID"]; 
                }
                
              $arSectionIds[$arItem["IBLOCK_SECTION_ID"]] = $arItem["IBLOCK_SECTION_ID"];

         }      
         if($bCoupon && !empty($arCouponItems)){
            //сначала проверяем сумму товаров и смотрим 20% или 3000р
            $sumCoupon = 0;
            $sumBatut = 0;
            foreach($arFields["PRODUCT_ROWS"] as $arProduct){
               if(in_array($arProduct["PRODUCT_ID"],$arCouponItems)){
                  $sumCoupon = $sumCoupon + $arProduct["QUANTITY"]*$arProduct["PRICE_BRUTTO"];
               }
               if(in_array($arProduct["PRODUCT_ID"],$arBatutIds)){
                  $sumBatut = $sumBatut + $arProduct["QUANTITY"]*$arProduct["PRICE_BRUTTO"];
               }
            }
            if($sumCoupon>0){
               //AddMessage2Log(["sumGoods",$sumCoupon]);
               if(($sumCoupon*0.2)<$maxDiscount){ //уменьшаем на 20%
                  //$discount = 20;
                  $sumCoupon = $sumCoupon*0.2;
               }
               else{
                  $sumCoupon = 3000;
                  //$discount = $maxDiscount*100/$sumCoupon;
               }   
               //AddMessage2Log(["sumCoupon",$sumCoupon]);
               //AddMessage2Log(["sumBatut",$sumBatut]);
               if($sumCoupon>($sumBatut-0)){
                  $sumCoupon = $sumBatut - 0;
               }
               //AddMessage2Log(["sumCoupon2",$sumCoupon]);


               $discount = $sumCoupon*100/$sumBatut;
               //AddMessage2Log(["discount",$discount]);

               //AddMessage2Log($discount);
                           
            }
            $arProducts = [];   
            //$arProducts2 = [];   
            global $newProducts;
            $newProducts = [];               
            foreach($arFields["PRODUCT_ROWS"] as $key => $arProduct){   
               if(in_array($arProduct["PRODUCT_ID"],$arBatutIds)){                  
                  $arProduct["DISCOUNT_TYPE_ID"] = 1;
                  //$arProduct["DISCOUNT_RATE"] = $discount;
                  //AddMessage2Log([$arProduct["PRICE_BRUTTO"]*$discount/100,round($arProduct["PRICE_BRUTTO"]*$discount/100,1,PHP_ROUND_HALF_DOWN),round($arProduct["PRICE_BRUTTO"]*$discount/100,2,PHP_ROUND_HALF_DOWN)]);
                  
                  $arProduct["DISCOUNT_SUM"] = round($arProduct["PRICE_BRUTTO"]*$discount/100);
                  $arProduct["PRICE"] = $arProduct["PRICE_BRUTTO"] - $arProduct["DISCOUNT_SUM"];
                  $arProduct["PRICE_EXCLUSIVE"] = $arProduct["PRICE"];
                  
                  
                  $arProduct["DISCOUNT_ROW"] = $arProduct["DISCOUNT_SUM"]*$arProduct["QUANTITY"];

                  $newProducts[$key] = [
                      "ID"=> $arProduct["ID"],
                      "PRODUCT_ID" => $arProduct["PRODUCT_ID"],
                      "QUANTITY" => $arProduct["QUANTITY"],
                      "PRICE" => $arProduct["PRICE"],
                      "DISCOUNT_TYPE_ID" => 1,
                      "DISCOUNT_SUM" => $arProduct["DISCOUNT_SUM"]
                   ];   
                  
               }
               else{                  
                  $newProducts[$key] = $arProduct; 
               }      
               $arProducts[$key] = $arProduct;   
               
                  
            }
            $arFields["PRODUCT_ROWS"] = $newProducts;
            //$newProducts = $arProducts2;
            

         }
         if(!empty($arAverageIds)){
                foreach ($arFields["PRODUCT_ROWS"] as $arProduct) {
                    if(isset($arAverageIds[$arProduct["PRODUCT_ID"]])){
                        $sumAverage = $sumAverage + $arProduct["PRICE"]*$arProduct["QUANTITY"];
                    }
                }
                if($sumAverage){
                    $questCount = 1;
                    if((!$bCoupon ||!isset($arFields['UF_CRM_1530623573843']) || !isset($arFields['UF_CRM_1530623600935'])) && CModule::IncludeModule("crm")){ //поля с количеством гостей
                        
                        $arFilter = array(
                           "ID"=>$arFields["ID"], //выбираем определенную сделку по ID
                           "CHECK_PERMISSIONS"=>"N" //не проверять права доступа текущего пользователя
                        );            
                        $arSelect = array(
                           "ID",
                           "UF_CRM_1530623573843",
                           "UF_CRM_1530623600935"
                        );            
                        $res = CCrmDeal::GetList(Array(), $arFilter, $arSelect);
                        
                        if($deal = $res->Fetch()){
                           $questCount = $deal["UF_CRM_1530623573843"] + $deal["UF_CRM_1530623600935"];
                        }
                    }
                    else{
                       if($bCoupon){
                          $questCount = $deal["UF_CRM_1530623573843"] + $deal["UF_CRM_1530623600935"];
                       }
                        $questCount = $arFields["UF_CRM_1530623573843"] + $arFields["UF_CRM_1530623600935"];
                    }
                    if($questCount < 1){
                        $questCount = 1;
                    }
                    $sumAverage = ceil($sumAverage/$questCount);
                }
            }   
         
         foreach($arFields["PRODUCT_ROWS"] as $arProduct){
            if(isset($arEntertIds[$arProduct["PRODUCT_ID"]])){
               $entertSum = $entertSum + $arProduct["QUANTITY"]*$arProduct["PRICE"];
            }
            if(isset($arMenuIds[$arProduct["PRODUCT_ID"]])){
               $menuSum = $menuSum + $arProduct["QUANTITY"]*$arProduct["PRICE"];
            }
            if(isset($arDopIdsp[$arProduct["PRODUCT_ID"]])){
               $dopSum = $dopSum + $arProduct["QUANTITY"]*$arProduct["PRICE"];
            }   
            if(isset($arBarIds[$arProduct["PRODUCT_ID"]])){
               $barSum = $barSum + $arProduct["QUANTITY"]*$arProduct["PRICE"];
            }   
            $sumAll = $sumAll + $arProduct["PRICE"]*$arProduct["QUANTITY"];            
         }

      }

      $arFields["UF_CRM_ENTERTAINMENT_AMOUNT"] = $entertSum;
      $arFields["UF_CRM_SUM_BANQUET"] = $menuSum;
      $arFields["UF_CRM_SUM_ADDITIONAL"] = $dopSum;
      $arFields["UF_CRM_SUM_BAR"] = $barSum;
      $arFields["UF_CRM_1619693698"] = implode(", ", $arSectionIds);
      $arFields["UF_CRM_AVERAGE_CHECK"] = $sumAverage;   
      if($bCoupon){
         $arFields["OPPORTUNITY"] = $sumAll;   
      }
      //AddMessage2Log([$entertSum,$menuSum,$dopSum,$barSum,$sumAverage,$arFields["UF_CRM_1619693698"]]);

   }
}



AddEventHandler('crm', 'OnBeforeCrmDealAdd', 'MyOnBeforeCrmDealAdd', 10000);
function MyOnBeforeCrmDealAdd(&$arFields){
   CalcMultipleForDeal($arFields);
   
}

AddEventHandler('crm', 'OnBeforeCrmDealUpdate', 'MyOnBeforeCrmDealUpdate', 10000);
function MyOnBeforeCrmDealUpdate(&$arFields){      
   CalcMultipleForDeal($arFields); //   
}


вариант 1. Без правки ядра, но в списке товаров цены БЕЗ скидки, она есть. но не видна (надо закрыть сделку и открыть)
OnAfterCrmDealProductRowsSave
AddEventHandler('crm', 'OnAfterCrmDealProductRowsSave', 'MyOnAfterCrmDealProductRowsSave');
function MyOnAfterCrmDealProductRowsSave($id,$fields){
   global $newProducts;
   if(!empty($newProducts)){
      CCrmProductRow::SaveRows('D', $id, $newProducts);      
   }
      
}
вариант 2.
с правкой ядра (эта ошибка есть у Битрикса в доработке), но все красиво отображается
OnBeforeCrmDealProductRowsSave
AddEventHandler('crm', 'OnBeforeCrmDealProductRowsSave', 'MyOnBeforeCrmDealProductRowsSave');
function MyOnBeforeCrmDealProductRowsSave($id,&$fields){
   global $newProducts;   
   if(!empty($newProducts)){
      $fields = $newProducts;
   }
      
}
в ядре правим место
/bitrix/modules/crm/classes/general/crm_deal.php
добавляем & перед $arRows в методе SaveProductRows

   


и чтобы красиво итоговые суммы были
/local/assets/entities-expansion/js/deal.js
BX.addCustomEvent( 'onAjaxSuccess' ,   function  (params, event) {
    if(event){
        let url = event.url;
        if(
            (url.indexOf('/bitrix/components/bitrix/crm.entity.product.list/list.ajax.php') >= 0) &&
            (url.indexOf('grid_action=showpage') >= 0)
        ){
            
            setTimeout(function(){               
                if($('div[data-name=QUANTITY] input.main-grid-editor-money-price').length >0){                   
                    let id = $('div[data-name=QUANTITY] input.main-grid-editor-money-price').first().attr('id');
                    let qnt = $('div[data-name=QUANTITY] input.main-grid-editor-money-price').first().val();                   
                    $('div[data-name=QUANTITY] input.main-grid-editor-money-price').first().val(1);
                    BX.fireEvent(BX(id),'change');
                    $('div[data-name=QUANTITY] input.main-grid-editor-money-price').first().val(qnt);
                    BX.fireEvent(BX(id),'change');                    
                }    
            },500);
            
        }    
    }
});
Если блог был полезным, можете угостить меня "чашечкой кофе" :)

Сбер по номеру телефона +7 (953) 585-13-09 Вероника.
Спасибо!