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

Удалить контакты без лидов и сделок в битрикс24

У заказчика облачный битрикс24 тариф "Профессиональный"
Аналитику можно смотреть, когда не более 100тыс. контактов, что было превышено.
Сначала вручную удалены были старые лиды.

Задача:
удалить контакты с типом НЕ "дилер", у которых нет лидов с источником "бесплатная версия" или сделки

Завела в битрикс24 в контактах 3 свойства типа да/нет
  • есть лиды
  • есть сделки
  • есть лиды или сделки
Реализовала агента CleanContacts

function CleanContacts() - на самом деле метод спец класса, для работы с битрикс24

self::CONTACT_PROPS["ххх"] - это просто код поля в битрикс типа "UF_CRM_yyy"  
self::CONTACT_TYPES["dealer"]  - тип клиента - тоже срока например "UC_FZVJ48"
static::SendRequest - описана там же

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

За одну итерацию обходит максимум 50*50 = 2500 контактов. Занимает примерно 500 секунд.
Если у вас время исполнения крипта меньшее 500. можно поставить $max не 50,  меньше (хоть 1). Тогда будет обходить по 50 контактов за 1 запуск агента.


Агент запустила раз в 900 секунд. За 9 часов должен обойти 100тыс контактов.
В следующий раз. чтобы чистить, надо будет новые поля завести, чтобы в данных их не было
  • есть лиды
  • есть сделки
  • есть лиды или сделки
function CleanContacts(){
       $i = 0;
       $max = 50;//1-50

       while($i>=0){ //для простого выхода 

           //получаем список контактов max запросов по 50 штук
           $arContactsDeletedAllIds = [];
           $arContactsNotDeletedIds = [];
           $arContactsNotDeleted = [];

           $batch = [];
           for ($j=0; $j < $max; $j++) {
                $batch[] = 'crm.contact.list?'.http_build_query([
                     "order" => ["ID" => "ASC"],
                     "select" => ["ID"],
                     "filter" => [
                         "!TYPE_ID"=>self::CONTACT_TYPES["dealer"],//не дилеров
                         self::CONTACT_PROPS["hasDealsOrLeads"] => false, //исключаем тех, кого уже проверили и поставили, что у них ЕСТЬ лиды или сделки
                     ],
                     "start" => $i*50
                ]);
                $i++;
           }
           $arData = [
               "halt" => 0,
               "cmd" => $batch
           ];
           $result = static::SendRequest("batch.json", $arData);

          
           $total = $result["result"]["result_total"][0]??0;
          
           if($total == 0){
               $i = -1;
               break;
           }

           sleep(1);
          
           //для каждого получаем 1 лид и 1 сделку, где он клиент, 1 сделку, где он в свойстве конечник (при заказе через дилера)
           for ($j=0; $j < $max; $j++) {
               if(is_array($result["result"]["result"][$j])){
                   for ($l=0; $l < 4; $l++) { // для 50 контактов мне надо сделать по 3 проверки
                       $arContactsIds = [];
                       $arContactsDeletedIds = [];
                       $batch2 = [];
                       for ($k = 16*$l; $k < (16+16*$l); $k++) { //у меня 3 проверки, поэтому floor(50/3) = 16. 
                           $contactId = $result["result"]["result"][$j][$k]["ID"] ?? false;
                           if (!empty($contactId)) {
                               $arContactsIds[] = $contactId;
                               $batch2["lead" . $contactId] = 'crm.lead.list?' . http_build_query([
                                       "select" => ["ID"],
                                       "filter" => ["CONTACT_ID" => $contactId],
                                       "limit" => 1
                                   ]);
                               $batch2["deal" . $contactId] = 'crm.deal.list?' . http_build_query([
                                       "select" => ["ID"],
                                       "filter" => ["CONTACT_ID" => $contactId],
                                       "limit" => 1
                                   ]);
                               $batch2["dealDealer" . $contactId] = 'crm.deal.list?' . http_build_query([
                                       "select" => ["ID"],
                                       "filter" => [self::DEAL_PROPS["client"] => $contactId],
                                       "limit" => 1
                               ]);
                           }
                       }
                       if(!empty($batch2)) {
                           $arData = [
                               "halt" => 0,
                               "cmd" => $batch2
                           ];                           
                           $result2 = static::SendRequest("batch.json", $arData);
                           sleep(1);
                           foreach ($arContactsIds as $contactId) {
                               if (
                                   empty($result2["result"]["result"]["lead" . $contactId]) &&
                                   empty($result2["result"]["result"]["deal" . $contactId]) &&
                                   empty($result2["result"]["result"]["dealDealer" . $contactId])
                               ) {
                                   $arContactsDeletedIds[] = $contactId;
                                   $arContactsDeletedAllIds[] = $contactId;
                               } else {
                                   $arContactsNotDeleted[] = [
                                       'id' => $contactId,
                                       'hasDeals' => (!empty($result2["result"]["result"]["deal" . $contactId])||!empty($result2["result"]["result"]["dealDealer" . $contactId])),
                                       'hasLeads' => (!empty($result2["result"]["result"]["lead" . $contactId]))
                                   ];
                                   $arContactsNotDeletedIds[] = $contactId;
                               }
                           }                         

                       }
                   }
               }
           }
           if(!empty($arContactsDeletedAllIds)){
               $file = fopen($_SERVER["DOCUMENT_ROOT"] . "/b24deletelog.txt", 'a+');
               fputs($file, implode(", ",$arContactsDeletedAllIds) . "\r\n");

           }
//           echo "удаленные<br>";
//           echo implode(", ",$arContactsDeletedAllIds);
//           echo "<br>";
//           echo "НЕудаленные<br>";
//           echo  implode(", ",$arContactsNotDeletedIds);
//           echo "<br>";

           if(!empty($arContactsDeletedAllIds)) {
               $arContactsDeletedAllIds = array_chunk($arContactsDeletedAllIds, 50);
               foreach ($arContactsDeletedAllIds as $arContactsDeletedIds) {
                   $batch2 = [];
                   //удаляем контакт в битрикс24, айдишник автоматом чистится
                   foreach ($arContactsDeletedIds as $contactId) {
                       $batch2[] = 'crm.contact.delete?' . http_build_query([
                               'id' => $contactId
                           ]);

                   }
                   if (!empty($batch2)) {
                       $arData = [
                           "halt" => 0,
                           "cmd" => $batch2
                       ];
                       $result2 = static::SendRequest("batch.json", $arData);
                       sleep(1);                      
                   }
               }
           }
           if(!empty($arContactsNotDeleted)){
               $arContactsNotDeleted = array_chunk($arContactsNotDeleted, 50);
               
               foreach ($arContactsNotDeleted as $arContactsNotDeletedTemp) {
                   $batch2 = [];
                   //$batchTemp = [];
                   foreach ($arContactsNotDeletedTemp as $arContactFields) {
                       $batch2[] = 'crm.contact.update?' . http_build_query([
                               'id' => $arContactFields["id"],
                               'fields' => [
                                   self::CONTACT_PROPS['hasLeads'] => $arContactFields['hasLeads'],
                                   self::CONTACT_PROPS['hasDeals'] => $arContactFields['hasDeals'],
                                   self::CONTACT_PROPS['hasDealsOrLeads'] => true
                               ],
                               'params' => [
                                   'REGISTER_SONET_EVENT' => 'N'
                               ]
                       ]);
                       
                   }
                   $arData = [
                       "halt" => 0,
                       "cmd" => $batch2
                   ];

                   $result2 = static::SendRequest("batch.json", $arData);
                   sleep(1);
                   
               }
           }
           
           break;          
       }
       return ($i>=0)?"nikaverro\dev\bitrix24\Bitrix24::CleanContacts();":"";
   }
Если блог был полезным, можете угостить меня "чашечкой кофе" :)

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