Уведомление о пропущенном и время первого исходящего звонка

Задача:
1. В поле лида положить время первого звонка менеджера
2. Присылать уведомление о пропущенном звонке всем сотрудникам того же департамента (для определенных департаментов), в котором находится ответственный за лид или контакт.
AddEventHandler("voximplant", "onCallEnd", "MyOnCallEnd");
function MyOnCallEnd($data)
{
    if (!empty($data['CALL_ID']) && !empty($data['CALL_TYPE']) && ($data['CALL_TYPE'] == 1) && CModule::IncludeModule('voximplant')) {//если исходящий
        $arCalls = Bitrix\Voximplant\StatisticTable::getList([
            'select' => ['ID', 'CRM_ENTITY_ID', 'CRM_ENTITY_TYPE'],
            'filter' => [
                'CALL_ID' => $data['CALL_ID']
            ],
            'order' => ['ID' => 'DESC'],
            'limit' => 1
        ])->fetchAll();
        foreach ($arCalls as $arCall) {
            if (in_array($arCall['CRM_ENTITY_TYPE'], ['LEAD', 'CONTACT']) && CModule::IncludeModule('crm')) {
                $arFilter = [
                    'UF_CRM_1668703501' => false,
                    '>DATE_CREATE' => '18.11.2022', //с какого числа начали записывать
                    'CHECK_PERMISSIONS' => 'N' //не проверять права доступа текущего пользователя
                ];

                if ($arCall['CRM_ENTITY_TYPE'] == 'LEAD') {
                    $arFilter['ID'] = $arCall['CRM_ENTITY_ID'];
                } elseif ($arCall['CRM_ENTITY_TYPE'] == 'CONTACT') {
                    $arFilter['CONTACT_ID'] = $arCall['CRM_ENTITY_ID'];
                }

                $arSelect = ['ID'];
                $res = CCrmLead::GetList(array(), $arFilter, $arSelect);
                $lead = new  \CCrmLead(false);
                while ($arLead = $res->Fetch()) {

                    $arUpdateData = array(
                        'UF_CRM_1668703501' => $data['CALL_START_DATE']->format('d.m.Y H:i:s')
                    );
                    $arOptions = array();
                    $upRes = $lead->Update($arLead['ID'], $arUpdateData, true, true, $arOptions);
                }
            }
        }
    }
    if (($data['CALL_TYPE'] == 2) && ($data['CALL_FAILED_CODE'] == 304) && CModule::IncludeModule('intranet') && CModule::IncludeModule('im') && CModule::IncludeModule('voximplant')) {
        $arCalls = Bitrix\Voximplant\StatisticTable::getList([
            'select' => ['ID', 'CRM_ENTITY_ID', 'CRM_ENTITY_TYPE'],
            'filter' => [
                'CALL_ID' => $data['CALL_ID']
            ],
            'order' => ['ID' => 'DESC'],
            'limit' => 1
        ])->fetchAll();
        foreach ($arCalls as $arCall) {
            $notifyMessage = '';
            if (in_array($arCall['CRM_ENTITY_TYPE'], ['LEAD', 'CONTACT']) && CModule::IncludeModule('crm')) {
                $arFilter = [
                    'CHECK_PERMISSIONS' => 'N', //не проверять права доступа текущего пользователя
                    'ID' => $arCall['CRM_ENTITY_ID']
                ];
                $arSelect = ['ID', 'ASSIGNED_BY_ID'];
                if ($arCall['CRM_ENTITY_TYPE'] == 'LEAD') {
                    $res = CCrmLead::GetListEx(array(), $arFilter, $arSelect);
                    $arEntity = $res->Fetch();
                    $notifyMessage = 'У  [URL=https://bitrix.nikaverro.ru/crm/lead/details/' . $arEntity['ID'] . '/] Лида №' . $arEntity['ID'] . '[/URL] пропущен звонок';
                } elseif ($arCall['CRM_ENTITY_TYPE'] == 'CONTACT') {
                    $res = CCrmContact::GetListEx(array(), $arFilter, $arSelect);
                    $arEntity = $res->Fetch();
                    $notifyMessage = 'У  [URL=https://bitrix.nikaverro.ru/crm/contact/details/' . $arEntity['ID'] . '/] Контакта №' . $arEntity['ID'] . '[/URL] пропущен звонок';
                }
            }
        }
        if (!empty($arEntity['ASSIGNED_BY_ID'])) {
            $arDepartments = CIntranetUtils::GetUserDepartments($arEntity['ASSIGNED_BY_ID']);
            if (!empty($arDepartments)) {
                $needDepartments = [1609, 1610, 1611, 1612, 1242, 1292, 181, 183];
                $arDepartmentsFilter = [];
                foreach ($arDepartments as $departmentId) {
                    if (in_array($departmentId, $needDepartments)) {
                        $arDepartmentsFilter[] = $departmentId;
                    }
                }

                if (!empty($arDepartmentsFilter)) {
                    $rsUsers = CIntranetUtils::GetDepartmentEmployees($arDepartmentsFilter);
                    while ($arUser = $rsUsers->fetch()) {
                        if ($arUser['ID'] != $data['PORTAL_USER_ID']) {
                            $arFields = array(
                                'NOTIFY_TITLE' => 'Пропущенный звонок от ' . $data['PHONE_NUMBER'], //заголовок
                                'MESSAGE' => $notifyMessage,
                                'MESSAGE_TYPE' => IM_MESSAGE_SYSTEM, // IM_MESSAGE_PRIVATE, IM_MESSAGE_CHAT, IM_MESSAGE_OPEN, IM_MESSAGE_SYSTEM, IM_MESSAGE_OPEN_LINE
                                'TO_USER_ID' => $arUser['ID'],
                                'FROM_USER_ID' => $arUser['ID'],
                                //'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);
                        }
                    }
                }
            }
        }
    }
}
оптимизированная ИИ версия (не тестировалась)
AddEventHandler("voximplant", "onCallEnd", "MyOnCallEnd");

function MyOnCallEnd($data){
    // Проверяем обязательные поля
    if(empty($data["CALL_ID"]) || empty($data["CALL_TYPE"])){
        return;
    }

    // Проверяем наличие необходимого модуля
    if(!CModule::IncludeModule('voximplant')){
        return;
    }

    // Получаем данные о звонке один раз для обоих случаев
    $arCalls = Bitrix\Voximplant\StatisticTable::getList([
        "select" => ["ID", "CRM_ENTITY_ID", "CRM_ENTITY_TYPE"],
        "filter" => ["CALL_ID" => $data["CALL_ID"]],
        "order" => ['ID' => 'DESC'],
        "limit" => 1
    ])->fetchAll();

    if(empty($arCalls)){
        return;
    }

    $arCall = $arCalls[0];

    // Обработка исходящих звонков (CALL_TYPE == 1)
    if($data["CALL_TYPE"] == 1 && !empty($arCall["CRM_ENTITY_TYPE"])){
        handleOutgoingCall($data, $arCall);
    }
    // Обработка пропущенных звонков (CALL_TYPE == 2 и код ошибки 304)
    elseif($data["CALL_TYPE"] == 2 && $data["CALL_FAILED_CODE"] == 304){
        handleMissedCall($data, $arCall);
    }
}

function handleOutgoingCall($data, $arCall){
    // Обновляем только для LEAD и CONTACT
    if(!in_array($arCall["CRM_ENTITY_TYPE"], ["LEAD", "CONTACT"])){
        return;
    }

    if(!CModule::IncludeModule('crm')){
        return;
    }

    // Формируем фильтр для поиска
    $arFilter = [
        "UF_CRM_1668703501" => false,
        ">DATE_CREATE" => "18.11.2022",
        "CHECK_PERMISSIONS" => "N"
    ];

    if($arCall["CRM_ENTITY_TYPE"] == "LEAD"){
        $arFilter["ID"] = $arCall["CRM_ENTITY_ID"];
        $entity = new CCrmLead(false);
        $res = CCrmLead::GetList([], $arFilter, ["ID"]);
    } else { // CONTACT
        $arFilter["CONTACT_ID"] = $arCall["CRM_ENTITY_ID"];
        $entity = new CCrmLead(false);
        $res = CCrmLead::GetList([], $arFilter, ["ID"]);
    }

    // Обновляем найденные сущности
    $updateData = [
        "UF_CRM_1668703501" => $data["CALL_START_DATE"]->format("d.m.Y H:i:s")
    ];

    while($arEntity = $res->Fetch()){
        $entity->Update($arEntity["ID"], $updateData, true, true, []);
    }
}

function handleMissedCall($data, $arCall){
    // Проверяем необходимые модули
    if(!CModule::IncludeModule('intranet') || !CModule::IncludeModule('im') || !CModule::IncludeModule('crm')){
        return;
    }

    // Обрабатываем только для LEAD и CONTACT
    if(!in_array($arCall["CRM_ENTITY_TYPE"], ["LEAD", "CONTACT"])){
        return;
    }

    // Получаем данные ответственного
    $arEntity = getResponsibleUser($arCall);
    
    if(empty($arEntity["ASSIGNED_BY_ID"])){
        return;
    }

    // Формируем сообщение
    $notifyMessage = generateNotifyMessage($arCall, $arEntity);

    // Отправляем уведомления сотрудникам отдела
    sendNotificationsToDepartment($data, $arEntity, $notifyMessage);
}

function getResponsibleUser($arCall){
    $arFilter = [
        "CHECK_PERMISSIONS" => "N",
        "ID" => $arCall["CRM_ENTITY_ID"]
    ];
    
    $arSelect = ["ID", "ASSIGNED_BY_ID"];

    if($arCall["CRM_ENTITY_TYPE"] == "LEAD"){
        $res = CCrmLead::GetListEx([], $arFilter, $arSelect);
    } else { // CONTACT
        $res = CCrmContact::GetListEx([], $arFilter, $arSelect);
    }

    return $res->Fetch();
}

function generateNotifyMessage($arCall, $arEntity){
    $baseUrl = "https://bitrix.nebojump.ru";
    $entityType = $arCall["CRM_ENTITY_TYPE"];
    $entityId = $arEntity["ID"];

    if($entityType == "LEAD"){
        $url = "{$baseUrl}/crm/lead/details/{$entityId}/";
        $typeText = "Лида";
    } else {
        $url = "{$baseUrl}/crm/contact/details/{$entityId}/";
        $typeText = "Контакта";
    }

    return "У [URL={$url}] {$typeText} №{$entityId}[/URL] пропущен звонок";
}

function sendNotificationsToDepartment($data, $arEntity, $message){
    // Получаем отделы сотрудника
    $arDepartments = CIntranetUtils::GetUserDepartments($arEntity["ASSIGNED_BY_ID"]);
    
    if(empty($arDepartments)){
        return;
    }

    // Фильтруем нужные отделы
    $needDepartments = [1609, 1610, 1611, 1612, 1242, 1292, 181, 183];
    $arDepartmentsFilter = array_intersect($arDepartments, $needDepartments);

    if(empty($arDepartmentsFilter)){
        return;
    }

    // Получаем всех сотрудников отделов
    $rsUsers = CIntranetUtils::GetDepartmentEmployees($arDepartmentsFilter);
    
    $arFields = [
        "NOTIFY_TITLE" => "Пропущенный звонок от " . $data["PHONE_NUMBER"],
        "MESSAGE" => $message,
        "MESSAGE_TYPE" => IM_MESSAGE_SYSTEM,
        "FROM_USER_ID" => 0,
        "NOTIFY_TYPE" => IM_NOTIFY_SYSTEM,
        "NOTIFY_MODULE" => "main",
        "NOTIFY_EVENT" => "manage",
    ];

    // Отправляем уведомления всем, кроме инициатора
    while($arUser = $rsUsers->fetch()){
        if($arUser["ID"] != $data["PORTAL_USER_ID"]){
            $arFields["TO_USER_ID"] = $arUser["ID"];
            CIMMessenger::Add($arFields);
        }
    }
}