Кейс Битрикс24: добавление файлов из задачи, прикрепленной к сделке, в пользовательское поле самой сделки

Кейс Битрикс24: добавление файлов из задачи, прикрепленной к сделке, в пользовательское поле самой сделки

16 Апреля 2021
Битрикс24: добавление файлов из задачи, прикрепленной к сделке, в пользовательское поле типа «Файл» в самой сделке

Сегодня рассмотрим решение реальной задачи, релизованное нашими специалистами и которое может быть полезно разработчикам, занимающимся доработкой и расширением функционала коробочной версии Битрикс24 под конкретные задачи.

Задача следующая: При сохранении привязанной к сделке задачи дублировать в сделку файлы, прикрепленные к этой задаче, в пользовательское поле с множественными значениями типа «Файл». Данная возможность должна быть доступна только пользователям определенного подразделения, назначенным ответственными в этой задаче.

Для решения данной задачи будем использовать события модуля Tasks:

  • onTaskAdd – добавление задачи;
  • onTaskUpdate – обновление задачи.

На первый взгляд задача несложная, нужно найти где хранятся файлы в задаче и передать их в сделку с помощью комбинации:

  • CFile::MakeFileArray($ID_файла) - подготовить файлы;
  • Передать файлы в сделку через метод Update.

Но, к сожалению, данный метод здесь бесполезен, так как в задаче файлы хранятся по другому принципу с использованием WebDav (по приниципу почтового сервера) в виде хешей наименований без расширения. Данная система служит для экономии места на ресурсе, так как при таком методе при загрузке нового файла, создается хеш и сравнивается с уже имеющимися хешами в системе и, если такой хеш уже имеется, то загрузки дубликата не происходит, а к задаче привязывается хеш файла. Соответственно при удалении файла из задачи, отвязывается только хеш. В то время как данные в пользовательских полях типа «Файл» хранятся по старой схеме.

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

Для получения данных из WebDav нам приходит на помощь D7 и работа с диском \Bitrix\Disk\Driver и, немного покопавшись в официальной документации и по сети, мы пришли к следующему варианту:

$userFieldManager = \Bitrix\Disk\Driver::getInstance()->getUserFieldManager();
$userFieldManager->loadBatchAttachedObject($files);
foreach ($files as $attachedId) 
{   
    //...
    $attachedObject = $userFieldManager->getAttachedObjectById($attachedId);  
    //...
}

Здесь:

  • $files – массив идентификаторов в системе WebDav пришедший от задачи;
  • $attachedObject – возвращает объект с информацией и методами о привязанном файле в системе WebDav. В $attachedObject есть функция getFileId() которая возвращает идентификатор файла в классическом варианте удобоваримом классу CFile. Имея данный идентификатор можно использовать классический метод обработки CFile::MakeFileArray() плюс проверка на наличие уже такого файла в сделке.

Получаем код:


$userFieldManager = \Bitrix\Disk\Driver::getInstance()->getUserFieldManager();
$userFieldManager->loadBatchAttachedObject($files);
foreach ($files as $attachedId) 
{
    $key = false; 
    $attachedObject = $userFieldManager->getAttachedObjectById($attachedId); 
    if(sizeof($arFields['UF_CRM_1492767878']) > 0) 
    { 
        $key = array_search($attachedObject->getName(), array_column($arFileInfo, 'ORIGINAL_NAME')); 
    } 
    if ($key === false) { 
        $arFields['UF_CRM_1492767878'][] = CFile::MakeFileArray($attachedObject->getFileId()); 
    }
} 

Теперь полученное поле необходимо записать в сделку:

if(isset($arFields['UF_CRM_1492767878']) && sizeof($arFields['UF_CRM_1492767878']) > 0) {
    $crm = new CCrmDeal(false);
    $crm->Update($dealId, $arFields, true, true, ['DISABLE_USER_FIELD_CHECK' => true, 'REGISTER_SONET_EVENT' => true]);
}

Нам так же необходимо сохранить уже полученные файлы. Мы сделали это так:


$obDeal = CCrmDeal::GetList([], ['ID' => $dealId], ['*', 'UF_*']);         
$deal = $obDeal->GetNext();         
$dealFiles = $deal['UF_CRM_1492767878'];         
if(sizeof($dealFiles) > 0) 
{            
    foreach ($dealFiles as $f) 
    {               
        $arFields['UF_CRM_1492767878'][] = $f;               
        $arFileInfo[] = CFile::GetByID($f)->GetNext();            
     }         
}

Здесь:

$arFileInfo – содержит массив существующих уже в сделке файлов. Он нам потребуется для проверки по имени файла. Так же еще добавлена проверка по подразделению.

Итоговый вариант всего обработчика:


AddEventHandler("tasks", "OnTaskAdd", ["TaskEvent", "OnTaskAddHandler"]);
AddEventHandler("tasks", "OnTaskUpdate", ["TaskEvent", "OnTaskUpdateHandler"]);

class TaskEvent {   
    function OnTaskAddHandler($ID)
    {
        self::syncDealFiles($ID);   
    }   
    
    function OnTaskUpdateHandler($ID)
    {      
        self::syncDealFiles($ID);   
    }   
    
    private static function syncDealFiles($ID)
    {      
        CModule::IncludeModule('tasks');
        CModule::IncludeModule('crm');
        $obTask = CTasks::GetList([], ['ID' => $ID], ['*', 'UF_*']);
        $task = $obTask->GetNext();      
        list(, $dealId) = explode('_', array_shift($task['UF_CRM_TASK']));      
        $files = $task['UF_TASK_WEBDAV_FILES']; $arFileInfo = [];      
        $user = CUser::GetList(($by = 'id'), ($order = 'asc'), ['ID' => $task['RESPONSIBLE_ID'], 'UF_DEPARTMENT' => 28], ['SELECT' => ['*', 'UF_*']])->GetNext();      
        
        if (is_numeric($dealId) && sizeof($files) > 0 && isset($user['ID'])) 
        {         
            $obDeal = CCrmDeal::GetList([], ['ID' => $dealId], ['*', 'UF_*']);         
            $deal = $obDeal->GetNext();         
            $dealFiles = $deal['UF_CRM_1492767878'];         
            if(sizeof($dealFiles) > 0) 
            {            
                foreach ($dealFiles as $f) 
                {
                    $arFields['UF_CRM_1492767878'][] = $f;
                    $arFileInfo[] = CFile::GetByID($f)->GetNext();           
                }         
            }         
            $userFieldManager = \Bitrix\Disk\Driver::getInstance()->getUserFieldManager();         
            $userFieldManager->loadBatchAttachedObject($files);        
            foreach ($files as $attachedId) 
            {          
                $key = false;           
                $attachedObject = $userFieldManager->getAttachedObjectById($attachedId);         
                if(sizeof($arFields['UF_CRM_1492767878']) > 0) 
                {            
                    $key = array_search($attachedObject->getName(), array_column($arFileInfo, 'ORIGINAL_NAME'));           
                }           
                
                if ($key === false) 
                {           
                    $arFields['UF_CRM_1492767878'][] = CFile::MakeFileArray($attachedObject->getFileId());      
                }         
            }         
            
            if(isset($arFields['UF_CRM_1492767878']) && sizeof($arFields['UF_CRM_1492767878']) > 0) 
            {          
                $crm = new CCrmDeal(false);
                $crm->Update($dealId, $arFields, true, true, ['DISABLE_USER_FIELD_CHECK' => true, 'REGISTER_SONET_EVENT' => true]);         
            }
        }
    }
}
 
Так же может быть интересно