Обучаю битриксу программистов, интеграторов

Если 30 мин нет задачи по лиду или сделке, то уведомление ответственному отделу

Задача:
Отправить уведомление всем менеджерам ОП парка, если в лиде/сделке нет задачи больше 30 минут с момента снятия прошлой задачи. Если до этого задачи не было, то с момента создания лида/сделки
- По лидам это должно работать на стадиях: "Не обработан" и "В работе"
- По сделкам на стадиях от "бронь" до "предоплата" (для 4х воронок)

Парк - свойствА в лиде, сделке
В init.php

Функция, которая отправляет списку пользователей уведомление
function SendMessageByCrmTasks($arUsers, $entityType, $entityId){
    if(CModule::IncludeModule('im')){
        $message = '<a target="_self" href="https://bitrix.nikaverro.ru/crm/';
        if($entityType == CCrmOwnerType::Lead){
            $message .= 'lead/details/'.$entityId.'/" >Лид'; 
        }
        else{ //сделка
            $message .= 'deal/details/'.$entityId.'/">Сделка';
        }
        $message .=' №'.$entityId. '</a> без задачи более 30 минут';
        
        foreach($arUsers as $userId){
            $arFields = array(
               "NOTIFY_TITLE" => "Нет задачи", //заголовок                     
               "MESSAGE" => $message,
               "MESSAGE_TYPE" => IM_MESSAGE_SYSTEM, // IM_MESSAGE_PRIVATE, IM_MESSAGE_CHAT, IM_MESSAGE_OPEN, IM_MESSAGE_SYSTEM, IM_MESSAGE_OPEN_LINE
               "TO_USER_ID" => $userId,
               "FROM_USER_ID" => 0,
               //"AUTHOR_ID" => $userIdOther, //может отличаться от FROM_USER_ID                           
               "NOTIFY_TYPE" => IM_NOTIFY_SYSTEM,  // IM_NOTIFY_CONFIRM, IM_NOTIFY_SYSTEM, IM_NOTIFY_FROM
               "NOTIFY_MODULE" => "main", // module id sender (ex: xmpp, main, etc)
               "NOTIFY_EVENT" => "manage",                           
            );      
            CIMMessenger::Add($arFields);   
        }
    } 
}   
получает менеджеров для каждого парка
function GetParkManagers($arParks){
    CModule::IncludeModule('intranet');
    $arResult = [
        "BY_PARK" => [],
        "ALL" => []
    ];  
    
    foreach($arParks as $parkId => $parkDepartments){
        $rsUsers = CIntranetUtils::GetDepartmentEmployees($parkDepartments, true);
        while($arUser = $rsUsers->fetch()){
            $arResult["BY_PARK"][$parkId][$arUser["ID"]] = $arUser["ID"];                       
            $arResult["ALL"][$arUser["ID"]] = $arUser["ID"];
        }
    }
    return $arResult;
}



Функция, которая собирает такие лиды
function CheckTasksForEntity($entityType){

   CModule::IncludeModule('crm');   
   CModule::IncludeModule('tasks');
   
   

   //соответствие парков и департаментов
   if($entityType == CCrmOwnerType::Lead){
      $propPark = "UF_CRM_1540199230710"; 
      $prefix = "L_";
      $arParks = [
         282 => [1609, 1242],//парк 1
         284 => [1611, 181],//парк 2
         286 => [1612, 183],//парк 3
         288 => [1610, 1292],//парк 4         
      ];
      $arUsers = GetParkManagers($arParks);
      //выбираем ВСЕ лиды на 2х начальных стадиях
      $arFilter = array(
         "STATUS_ID" => ["NEW","IN_PROCESS"],
         "ASSIGNED_BY_ID"=> $arUsers["ALL"],
         "UF_CRM_1543416257" => "696", //входящий поток    
         $propPark => array_keys($arParks),
          "CHECK_PERMISSIONS"=>"N", //не проверять права доступа текущего пользователя
       );            
      $arSelect = array(
        "ID",            
        "DATE_CREATE",
        $propPark //парк
      );            
      $res = CCrmLead::GetList(Array(), $arFilter, $arSelect);
   }   
   else{//сделка   
      $propPark = "UF_CRM_5BCDF7FEE1029";
      $prefix = "D_";
      $arParks = [
         782 => [1609, 1242],//парк 1
         784 => [1611, 181],//парк 2
         786 => [1612, 183],//парк 3
         788 => [1610, 1292],//парк 4         
      ];
      $arUsers = GetParkManagers($arParks);
      $arFilter = array(
         "STAGE_ID" => [
            "C1:NEW","C1:PREPARATION","C1:PREPAYMENT_INVOICE","C1:EXECUTING",
             "C3:NEW","C3:PREPARATION","C3:PREPAYMENT_INVOICE","C3:EXECUTING",
             "C5:NEW","C5:PREPARATION","C5:PREPAYMENT_INVOICE","C5:EXECUTING",
             "C7:NEW","C7:PREPARATION","C7:PREPAYMENT_INVOICE","C7:EXECUTING"
         ],
         "ASSIGNED_BY_ID"=> $arUsers["ALL"],
         //"UF_CRM_1543416257" => "696", //входящий поток    
         $propPark => array_keys($arParks),
          "CHECK_PERMISSIONS"=>"N", //не проверять права доступа текущего пользователя
       );            
      $arSelect = array(
        "ID",            
        "DATE_CREATE",
        $propPark //парк
      );            
      $res = CCrmDeal::GetList(Array(), $arFilter, $arSelect);
   }
   
   $arIds = [];
   $arEntities = [];
   while($row = $res->Fetch()){      
      $arIds[] = $prefix.$row["ID"];
      $arEntities[$row["ID"]] = $row;
   }

   if(!empty($arIds)){
      $arFilter = array(                          
            "UF_CRM_TASK" => $arIds, 
      );
      $res = CTasks::GetList(
          Array("DEADLINE" => "ASC"), 
          $arFilter,
          array("ID","STATUS","CLOSED_DATE","STATUS_CHANGED_DATE","UF_CRM_TASK"),
          array("USER_ID"=>1)   //из-под админа получаем                 
      );
      $arTasks = [];
      while($arTask = $res->GetNext()){   
         foreach($arTask["UF_CRM_TASK"] as $entityId){
            $arTasks[$entityId][] = $arTask;   
         }
         
      }
      $t = time()-30*60; //30 мин назад
      

      foreach ($arEntities as $entityId => $arEntity) {
         $bFind = false;
         if(!empty($arTasks[$prefix.$entityId])){
            foreach($arTasks[$prefix.$entityId] as $arTask){
               if($arTask["STATUS"]==CTasks::STATE_COMPLETED){//завершена
                  if(strtotime($arTask["CLOSED_DATE"]) > $t){
                     $bFind = true;
                     break;
                  }
               }   
               elseif($arTask["STATUS"]==CTasks::STATE_SUPPOSEDLY_COMPLETED){//ждет приема
                  if(strtotime($arTask["STATUS_CHANGED_DATE"]) > $t){
                     $bFind = true;
                     break;
                  }
               }
               else{
                  $bFind = true;
                  break;
               }
            }            
         }
         elseif(strtotime($arEntity["DATE_CREATE"]) > $t){//проверяем дату создания         
            $bFind = true;            
         }   

         
            
         if(!$bFind && !empty($arUsers["BY_PARK"][$arEntity[$propPark]])){            
            SendMessageByCrmTasks($arUsers["BY_PARK"][$arEntity[$propPark]], $entityType, $entityId);
            //echo $entityId.", ";   
                    }
              
      }
   }   
}


агенты
function CheckLeadsWithoutTasksAgent(){
    $h = date("H");
    if($h>9 && $h<22){  
        CheckTasksForEntity(CCrmOwnerType::Lead);
    }   
    return "CheckLeadsWithoutTasksAgent();";
}

function CheckDealsWithoutTasksAgent(){
    $h = date("H");
    if($h>9 && $h<22){  
        CheckTasksForEntity(CCrmOwnerType::Deal);
    }   
    return "CheckDealsWithoutTasksAgent();";
}
Если блог был полезным, можете угостить меня "чашечкой кофе" :)

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