artem
14.12.2017
13052

Направление входящего вызова на последнего абонента, не дозвонившегося на номер

В этой статье будет описан сценарий обработки входящих вызовов, при котором вызов в первую очередь направляется на абонента, который последним набирал номер звонящего и не дозвонился. Может быть весьма полезным использование такого сценария в компаниях, сотрудники которых часто звонят на мобильные номера клиентов — чтобы клиент, перезвонив на городской номер, сразу дозвонился до сотрудника, который пытался с ним связаться.
(приведённые в статье инструкции рассчитаны на FreePBX 13 и любой совместимый с ним Asterisk)

Направление входящего вызова на последнего абонента, не дозвонившегося на номер звонящего - VoxLink

ODBC-функция для определения последнего абонента, который не дозвонился до номера звонящего

Определять последнего абонента, который звонил на номер звонящего, будем по данным из таблицы CDR с помощью ODBC-функции. ODBC-подключение к MySQL и запись CDR в таблицу MySQL по умолчанию настроены в FreePBX 13, для этого дополнительных действий не требуется.
ODBC-функции описываются в файле /etc/asterisk/func_odbc.conf (если этот файл не существует, просто создайте его), добавьте в файл следующую функцию:

[LAST_OUTBOUND_CALL_TO_NUMBER]
dsn=asteriskcdrdb
readsql=SELECT `src`,`disposition`,`billsec` FROM `cdr` WHERE `dst` LIKE ‘%${SQL_ESC(${ARG1})}’ AND `calldate`>=’${SQL_ESC(${ARG2})}’ ORDER BY `calldate` DESC LIMIT 1

DSN asteriskcdrdb в FreePBX 13 должен быть по умолчанию описан в файле /etc/asterisk/res_odbc_additional.conf, убедитесь, что это так. Для применения изменений в файле /etc/asterisk/func_odbc.conf, выполните в CLI Asterisk команду:

module reload func_odbc.so

или

module load func_odbc.so
(если модуль func_odbc.so ранее не был загружен)

Если всё сделано правильно, команда «core show function ODBC_LAST_OUTBOUND_CALL_TO_NUMBER» в CLI Asterisk должна выдать SQL-запрос, указанный в файле func_odbc.conf.

Приведение номера звонящего к общему виду

Во всех сценариях маршрутизации входящих вызовов, которые учитывают номер звонящего, обязательно приведение этого номера к общему виду. Даже если для маршрутизации входящих вызовов не используется ничего особенного, номер звонящего всё равно лучше привести к общему виду — так можно быть уверенным в том, что абоненты смогут совершить вызов из истории входящих звонков телефонного аппарата.

Для приведения номера звонящего к общему виду будет использоваться следующий контекст:

[sub-fix-cid]
exten => s,1,GotoIf($[${REGEX(«^[0-9]{7}$» ${CALLERID(num)})} = 0]?cont1)
same  => n,Set(CALLERID(num)=7495${CALLERID(num)})
same  => n,Set(CALLERID(ANI-num)=${CALLERID(num)})
same  => n,Goto(end)
same  => n(cont1),GotoIf(${REGEX(«^[78]?[2-9][0-9]{9}$» ${CALLERID(num)})}?fix_cid)same  => n,GotoIf(${REGEX(«^\+?7[2-9][0-9]{9}$» ${CALLERID(num)})}?fix_cid)
same  => n,Goto(end)
same  => n(fix_cid),Set(CALLERID(num)=7${CALLERID(num):-10})
same  => n,Set(CALLERID(ANI-num)=${CALLERID(num)})
same  => n(end),Return

Как видите, контекст приводит к общему виду только номера России, номера, непохожие на российские, будут оставлены без изменений. Также к коротким городским номерам подставляется 7495, поменяйте код города, если это требуестя (впрочем очень немногие провайдеры передают номер звонящего в таком виде).
Ещё обратите внимание на то, что номер звонящего приводится к виду 7XXXXXXXXXX (если требуется, поменяйте формат на более подходящий для своих задач).

Добавление своего диалплана для обработки входящих вызовов в FreePBX

Для приёма входящих вызовов от провайдера у FreePBX есть контекст from-trunk, но у пользователя есть полный контроль над тем, в какой контекст попадёт входящий вызов — просто укажите другой контекст в параметре транка context, и входящие вызовы пойдут туда. Следовательно, самый простой способ добавить в FreePBX свой диалплан для обработки входящих вызовов — принимать вызовы из транка провайдера в самописный контекст, затем переводить их в контекст from-trunk. Пример:

[from-trunk-pre]
exten => _X.,1,Set(DID_NUM=${EXTEN})
same  => n,Goto(process,1)
exten => _+X.,1,Set(DID_NUM=${EXTEN})
same  => n,Goto(process,1)

exten => process,1,Gosub(sub-fix-cid,s,1)
same  => n,Goto(from-trunk,${DID_NUM},1)

Edit trunk

Таким образом, мы уже пристроили контекст sub-fix-cid, диалплан, реализующий основной функционал, также будет вызываться из from-trunk-pre.

Диалплан для направления входящего вызова на последнего абонента, недозвонившегося на номер звонящего

Ниже приведён код контекста, реализующего описываемый сценарий.

[sub-dial-last-caller]
exten => s,1,GotoIf($[${LEN(${CALLERID(num)})} < 10]?end)
same  => n,Set(LC_MYSQL_DATE_FROM=${STRFTIME(${EPOCH},,%Y-%m-%d)} 00:00:00)
same  => n,Set(ARRAY(LC_LAST_CALL_SRC,LC_LAST_CALL_RESULT,LC_LAST_CALL_BILLSEC)=${ODBC_LAST_OUTBOUND_CALL_TO_NUMBER(${CALLERID(num):-10},${LC_MYSQL_DATE_FROM})})
same  => n,GotoIf($[«${LC_LAST_CALL_SRC}» = «»]?end)
same  => n,Set(LC_TARGET_DEVICE=${DB(DEVICE/${LC_LAST_CALL_SRC}/device)})
same  => n,GotoIf($[«${LC_TARGET_DEVICE}» = «»]?end)
same  => n,GotoIf($[«${EXTENSION_STATE(${LC_LAST_CALL_SRC}@ext-local)}» != «NOT_INUSE»]?end)
same  => n,GotoIf($[«${LC_LAST_CALL_RESULT}» = «ANSWERED» & ${LC_LAST_CALL_BILLSEC} > 4]?end)
same  => n,Macro(user-callerid)
same  => n,Gosub(sub-record-check,s,1(in,${LC_LAST_CALL_SRC},yes))
same  => n,Set(DIALSTATUS=)
same  => n,Dial(${LC_TARGET_DEVICE},15,t)
same  => n,ExecIf($[«${DIALSTATUS}» = «ANSWER»]?Hangup)
same  => n(end),Return

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

Контекст sub-dial-last-caller можно вызывать с помощью Gosub из контекста from-trunk-pre после sub-fix-cid.

[from-trunk-pre]
exten => _X.,1,Set(PRE_DID_NUM=${EXTEN})
same  => n,Goto(process,1)
exten => _+X.,1,Set(PRE_DID_NUM=${EXTEN})
same  => n,Goto(process,1)

exten => process,1,Gosub(sub-fix-cid,s,1)
same  => n,Gosub(sub-dial-last-caller,s,1)
same  => n,Goto(from-trunk,${PRE_DID_NUM},1)

Учтите, что здесь приведён самый простой способ внедрения описываемого сценария в диалплан FreePBX, если требуется сперва проиграть звонящему какое-либо сообщение и/или переводить на последнего звонящего только в рабочее время, можно переходить на sub-dial-last-caller,s,1 из FreePBX с помощью модуля «Custom Destinations».

На этом всё, удачных экспериментов.

Телефонная книга CallMetrix
Корпоративный телефонный справочник для удобной связи между сотрудниками организации
Скачать описание CallMetrix
Подписаться
Уведомить о
guest
2 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Иван
Иван
22.11.2019 10:57

Добрый день, вот не могу понять от куда АТС берет LC_TARGET_DEVICE ?
Соответственно звонок не возвращается. т.к. LC_TARGET_DEVICE пустой
У меня FreePBX 14.

TerAnYu
TerAnYu
13.12.2020 17:25

Немного изменил:

[LAST_OUTBOUND_CALL_TO_NUMBER] dsn=asterisk_cdr readsql=SELECT src,disposition,billsec,channel FROM cdr WHERE dst LIKE ‘%${SQL_ESC(${ARG1})}’ AND calldate>=’${SQL_ESC(${ARG2})}’ ORDER BY calldate DESC LIMIT 1

И в диалплане так:
   same => n,Set(ARRAY(LC_LAST_CALL_SRC,LC_LAST_CALL_RESULT,LC_LAST_CALL_BILLSEC,LC_LAST_CALL_CHANNEL)=${ODBC_LAST_OUTBOUND_CALL_TO_NUMBER(${CALLERID(num)},${LC_MYSQL_DATE_FROM})})
   same => n,Set(LC_TARGET_DEVICE=${CUT(LC_LAST_CALL_CHANNEL,\-,1)})

Остались вопросы?

Я - Першин Артём, менеджер компании Voxlink. Хотите уточнить детали или готовы оставить заявку? Укажите номер телефона, я перезвоню в течение 3-х секунд.

VoIP оборудование


ближайшие курсы

10 доводов в пользу Asterisk

Распространяется бесплатно.

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

Безопасен в использовании.

Любое программное обеспечение может стать объектом интереса злоумышленников, в том числе телефонная станция. Однако, сам Asterisk, а также операционная система, на которой он работает, дают множество инструментов защиты от любых атак. При грамотной настройке безопасности у злоумышленников нет никаких шансов попасть на станцию.

Надежен в эксплуатации.

Время работы серверов некоторых наших клиентов исчисляется годами. Это значит, что Asterisk работает несколько лет, ему не требуются никакие перезагрузки или принудительные отключения. А еще это говорит о том, что в районе отличная ситуация с электроэнергией, но это уже не заслуга Asterisk.

Гибкий в настройке.

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

Имеет огромный функционал.

Во многом именно Asterisk показал какой должна быть современная телефонная станция. За многие годы развития функциональность Asterisk расширилась, а все основные возможности по-прежнему доступны бесплатно сразу после установки.

Интегрируется с любыми системами.

То, что Asterisk не умеет сам, он позволяет реализовать за счет интеграции. Это могут быть интеграции с коммерческими телефонными станциями, CRM, ERP системами, биллингом, сервисами колл-трекинга, колл-бэка и модулями статистики и аналитики.

Позволяет телефонизировать офис за считанные часы.

В нашей практике были проекты, реализованные за один рабочий день. Это значит, что утром к нам обращался клиент, а уже через несколько часов он пользовался новой IP-АТС. Безусловно, такая скорость редкость, ведь АТС – инструмент зарабатывания денег для многих компаний и спешка во внедрении не уместна. Но в случае острой необходимости Asterisk готов к быстрому старту.

Отличная масштабируемость.

Очень утомительно постоянно возвращаться к одному и тому же вопросу. Такое часто бывает в случае некачественного исполнения работ или выбора заведомо неподходящего бизнес-решения. С Asterisk точно не будет такой проблемы! Телефонная станция, построенная на Asterisk может быть масштабируема до немыслимых размеров. Главное – правильно подобрать оборудование.

Повышает управляемость бизнеса.

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

Снижает расходы на связь.

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