Описание готового решения №1

 

 

Потребности в интеграции возникли, со слов клиента по следующим причинам:

Проблема была следующая - звонит клиент. Сотрудник поднимает трубку, находит сделку, а в этой сделке стоит другой ответственный. Ответившему на звонок сотруднику приходится вручную менять ответственного. Так как звонков в день очень много, то рекрутеры часто забывали это делать, да и само по себе редактирование этого поля было рутиной, а при пропущенном звонке задача вообще ставилась на другого сотрудника.

 

Бизнес-процесс построен в 2 этапа: квалификация и сопровождение. Вся основная работа ведется в сделках — это самый трудоемкий этап квалификация который можно автоматизировать и убрать лишнюю рутинную работу.

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

 

 

1. Смена ответственного по сделке в amoCRM (Ссылка)

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

const SipuniAmoCrm = require('@sipuni/amocrm');

async function updateLeadIfOpen(api, lead_id, responsible_user_id) {
   const lead = await api.leads.get(lead_id);
   if (lead
&& lead.status_id !== 142 && lead.status_id !== 143 // у закрытых сделок статус всегда будет или 142 (успешная) или 143 (неуспешная)
&& lead.responsible_user_id !== responsible_user_id
   ) {
await api.leads.update({ id: lead_id, responsible_user_id: responsible_user_id });
return lead_id;
   }
return 0;
}

module.exports = async (args) => {

        // Список разрешенных схем
const allowedTreeNames = [
          'Входящая 1',
          'Входящая 2',
          'Входящая 3'
        ];

        if (!allowedTreeNames.includes(args.call_args.tree_name)) {
           return { reason: `Схема ${args.call_args.tree_name} не в списке разрешенных` };
        }

    // Если найден/создан контакт при поступлении звонка,
    // его ID находится в args.context.contact_id

    if (!args.context.contact_id) {
         return { new_responsible_id: -1, reason: 'Нет контакта в контексте звонка' };
    }

    const amoApi = new SipuniAmoCrm({
           domain: args.settings.domain, accessToken: args.crm_auth
    });

    // Получаем ID ответившего на звонок
    const responsible_user_id = parseInt(args.context.answered_user_id, 10);

    // Получаем список сделок
    const { contact_id } = args.context;
    const result = await amoApi.request('GET', `/contacts/${contact_id}` , { with: 'leads' });
    const { leads } = result._embedded;

    // Обновляем открытые сделки
    const promises = leads.map(lead => updateLeadifOpen(amoApi, lead.id, responsible_user_id));
    const updatedLeads = await Promise.all(promises);

    return {
       updatedLeads, // массив с результатами, включает id обновленных сделок и нули для не обновлённых
       new_responsible_id: responsible_user_id,
    };
};

 

 

2. Назначение задач о пропущенных звонках на ответственного в сделке amoCRM (Ссылка)

Стандартная интеграция позволяет создавать задачи в карточке контакта, ответственному за данный контакт сотруднику.

У клиента, ответственный за контакт сотрудник - не всегда ответственный за сделку.

При использование данного кода, мы ставим задачу в сделку на ответственного по этой сделке.

const SipuniAmoCrm = require('@sipuni/amocrm');

const LEAD_CLOSED_STATUSES = [142 /*успешная*/, 143 /*неуспешная*/];
const TASK_TEXT = 'Пропущен звонок';
const TASK_DUE = 4*60*60; // 4 часа в секундах

// Создание задачи если сделка открыта
async function createTaskifLeadOpen(amoApi, lead_id) {
       const lead = await amoApi.leads.get(lead_id);
       if (lead && !LEAD_CLOSED_STATUSES.includes(lead.status_id)) {
                 // Поиск незакрытой задачи
                 const existingTask = await amoApi.tasks.list({
                         'filter[responsible_user_id]': lead.responsible_user_id,
                         'filter[is_completed]': 0,
                         'filter[entity_type]': 'leads',
                         'filter[entity_id]': lead_id,
                  });
                  // Если нет открытых задач, создаем новую
                  if (!existingTask) {
                      const timestamp = Math.ceil((new Date()).getTime()/1000);
                      await amoApi.tasks.create({
                             responsible_user_id: lead.responsible_user_id,
                             entity_id: lead_id,
                             entity_type: 'leads',
                             complete_till: timestamp + TASK_DUE,
                             text: TASK_TEXT,
                      });
                  }
                  return lead_id;
      }
      return 0;
}

// Получение списка сделок для контакта
async function getLeads(amoApi, contact_id) {
       const result = await amoApi.request('GET', `/contacts/${contact_id}` , { with: 'leads' });
       return result._embedded.leads;
}

module.exports = async (args) => {


         // Если найден/создан контакт при поступлении звонка,
         // его ID находится в args.context.contact_id
         if (!args.context.contact_id) {
             return { reason: 'Нет контакта в контексте звонка' };
         }

         const amoApi = new SipuniAmoCrm({
                domain: args.settings.domain, accessToken: args.crm_auth
         });

        
         // Получаем список сделок
         const leads = await getLeads(amoApi, args.context.contact_id);

         // Создаем задачи для открытых сделок
         const promises = leads.map(lead => createTaskifLeadOpen(amoApi, lead.id));
         const openLeads = await Promise.all(promises);

         if (updatedLead) {
             return {
                    updatedLeads: openLeads, // массив с результатами, включает id сделок для которых создали задачи и нули для остальных сделок
             };
         } else {
              return {updatedLeads: openLeads}; // массив с результатами, включает id сделок для которых создали задачи и нули для остальных сделок
};

 

 

3. Добавление метки в пользовательское поле при создании сделки в amoCRM от существующего контакта (Ссылка)

Для фильтрации созданных сделок от существующих контактов при пропущенном звонке, в пользовательское поле добавляем метку во вновь созданную сделку.

module.exports = async (args) => {

         // Если найден/создан контакт при поступлении звонка,
         // его ID находится в args.context.contact_id

         if (!args.context.contact_id) {
             return { reason: 'Нет контакта в контексте звонка' };
         }





         const amoApi = new SipuniAmoCrm({
                domain: args.settings.domain, accessToken: args.crm_auth
         });





 // Если создана новая сделка для существующего контакта
         let updatedLead = null;
         if (args.context.already_created_deal) {
             updatedLead = await amoApi.leads.update({
                     'id': parseInt(args.context.deal_id), // id обновляемой сделки

                    // любые поля для обновления
                     'custom_fields_values': [
                           {
                                   'field_id': 817366,
                                   'values': [{
                                         'value': 'Существует'
                                    }]
                            }
                    ]
            });
         }

         return (updatedLead);

};

 

 

 

Была ли эта статья полезной?
Пользователи, считающие этот материал полезным: 0 из 0