Вариант решения задачи по перезвонам абонентов в с использованием метода работы с таблицей "Кеш внутри БД"

На примере рассмотрен вопрос организации сложного механизма (перезвон абонентам в индивидуальное время на конкретный телефон) перезвонов с использованием механизмов работы с таблицей.

1.    Теория
В Октеле существует 2 вида работы с таблицей абонентов:
    Загрузка в память и синхронизация,
    Кеш внутри БД.
В первом случае все алгоритмы работы с базой абонентов полностью определятеся несколькими опциями  по обходу списка абонентов, которые жёстко заложены в программу. В ряде случаев их бывает недостаточно. Тут нам на помощь может прийти второй метод работы с таблицей абонентов в рамках задачи.
Рассмотрим для начала структуру таблиц кеша внутри БД (здесь и далее база данных Октел):

Сам кеш для каждой задачи располагается в таблице вида A_TaskManager_Idx_XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX , где XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX — это ID нашей задачи. ID задачи узнаём из таблицы A_TaskManager_Tasks.
Поля:
•    [Id] [int] — индекс в таблице абонентов;
•        [AC] [int] — количество «просмотров» записи в таблице абонентов;
•        [State] [int] — состояние: 0 не звонили, 1 позвонили удачно,  2 звонили неудачно и достигли предела количества попыток, 3 больше не звонить по записи;
•        [NIdx] [int] — индекс номера, который следующим надо будет брать из общего списка номеров абонента в таблице абонентов.
Данные в кеше обнавляются по таймауту указанному в параметре задачи «Интервал синхронизации». При появлении в таблице абонентов новой записи при синхронизации в кеш добавляется строка с соответствующим ID и равными нулю остальными полями. При исчезновении записи из таблицы абонентов поле state записи с соответствующим ID становится равным 3. При выборке из таблицы абонентов записи для соответствущей записи в кеше поле АС увеличивается на 1.

2.    Задача
В качестве базовой задачи для примера осуществления перезвона в рамках исходящей кампании возьмём следующую задачу:
Имеется таблица абонентов, в таблице абонентов указано предпочтительное время звонка каждому абоненту (для каждого абонента время звонка строго индивидуально). Абоненту может потребоваться перезвон на другой номер в нужное время. Необходимо обзвонить всех абонентов, а так же организовать необходимое количество перезвонов для каждого абонента (число перезвонов для абонента - произвольно)

3.    Организация таблиц для перезвона
Процесс первоначального дозвона и перезвона организовывается в рамках одной и той же исходящей задачи. Для организации перезвона необходимо организовать следующие таблицы:
Справочник абонентов. По сути это и есть наш список абонентов, которым необходимо звонить. Должен иметь следующие обязательные поля:
•    идентификатор записи (тип поля не имеет значения);
•    идентификатор абонента (в общем случае абоненту может соответствовать несколько записей в справочнике абонентов, с помощью этого приёма для каждого абонента мы можем создать произвольное количество телефонных номеров для обзвона);
•    Наименование абонента;
•    поля с телефонами для дозвона — может быть несколько штук;
•    служебные поля для управления процессом обзвона абонентов.
Таблица перезвона. Представляет собой набор задач, по которым необходимо сделать телефонный вызов. Должен иметь следующие поля:
•    идентификатор записи (int – для стыковки с таблицей кеша);
•    ссылка на идентификатор справочника абонентов;
•    телефон для обзвона;
•    набор полей для активации записи для прозвона прозвоне.
На основе этих 2х таблиц генерируется таблица абонентов передаваемая в Октел (я это делаю с помощью view). При данной организации происходит унификация первоначальных звонков и перезвонов в рамках одной задачи на прозвон абонентов.

4.    Решение
Имеем таблицу абонентов:

CREATE TABLE [dbo].[is_alex_kls](
    [id] [uniqueidentifier] NOT NULL, --идентификатор абонента
    [fio] [varchar](50) NOT NULL, --фио
    [doljnost] [varchar](50) NOT NULL, -- должность
    [company] [varchar](50) NOT NULL, -- фирма
    [phone] [varchar](20) NOT NULL, --телефон
    [hours] [int] NOT NULL, -- предпочтительное время перезвона
 CONSTRAINT [PK_is_alex_kls] PRIMARY KEY CLUSTERED
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

Механизм формирования поля часов прозвона следующий: часы прозвона выступают в виде битовой маски из 3х байт (24 часа) с указанием в 1 тех битов, которым соответствуют часы прозвона. Т.е. если нам надо звонить с 9.00 до 10.00 и с 14.00 до 15.00 то значение будет следующее: 00000000 00100001 00000000 = 8448  . Разбиение временного суточного интервала в шагом в час связано с тем, что при массовом дозвоне сложно попасть в маленький временной интервал.

Формируем таблицу перезвона:

CREATE TABLE [dbo].[is_alex_recall](
    [id] [int] NOT NULL, --идентификатор записи для октела
    [kls] [uniqueidentifier] NOT NULL, --ссылка на поле в справочнике
    [phonerecall] [varchar](20) NOT NULL, --телефон для перезвона
    [daterecall] [datetime] NOT NULL, --дата перезвона
    [hourrecall] [int] NOT NULL,--часы прозвона для перезвона
    [status] [int] NOT NULL,--статус активности задачи на перезвон
 CONSTRAINT [PK_is_alex_recall] PRIMARY KEY CLUSTERED
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]


В качестве таблицы абонентов передаваемой непосредственно в октел будем использовать просмотр:

CREATE VIEW V_IS_RECALL
AS
SELECT [recall].[id] ---идентификатор в таблице абонентов октела
      ,[recall].[phonerecall]--телефон в таблице абонентов октела
    ,[kls].[doljnost] --информационное поле в таблице абонентов
        ,[kls].[fio] -- наименование в таблице абонентов
        ,[kls].[company]--информационное поле в таблице
  FROM [alexraznoe].[dbo].[is_alex_recall] recall
inner join [alexraznoe].[dbo].[is_alex_kls] kls on recall.kls=kls.id
where getdate() between daterecall and dateadd(dd,1,daterecall) -- проверяем попадаем ли в нужную дату для звонка
and (datepart(hh,getdate())&[recall].[hourrecall]>0) -- проверяем попадаем ли в часы

Как видно из запроса абонент будет периодически то пропадать в списке на прозвон то появляться (попадание в часы обзвона)
Для этого мы должны сделать служебный сценарий (запускать можно периодически, например раз в 10 минут), в котором выправляем поле state для таблицы кеша со значения 3 на 0.:

update [A_TaskManager_Idx_XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX]
set state=0
where id in(
SELECT [id]
  FROM [alexraznoe].[dbo].[IS_RECALL] recall
LEFT join
( SELECT [IdInList]
FROM [oktell_cc_temp].[dbo].[A_Cube_CC_EffortConnections]
where idtask='XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX' and
idchain is not null and idoperator<>'AB000000-0000-0000-0000-000000000000' ) tmp
on tmp.idinlist=recall.id
where tmp.idinlist is null
)
Т.е. Восстанавливаем state=0 всем задачам которые в активной таблице обзвона и по которым ни разу на дозвонились.

При необходимости перезвона абоненту происходит вставка задачи на перезвон в таблицу. [dbo].[is_alex_recall] с указанием: даты перезвона, предпочтительного времени перезвона, телефона, по которому осуществлять перезвон. Так же можно в таблице перезвонов указывать другие справочные данные, например ФИО нового контактного лица.
Крайне полезно для контроля выполнения перезвонов осуществлять привязку строки генерирующей перезвон со звонком, создавшим задачу на перезвон. Это можно сделать введением дополнительного uniqueidentifier-поля с ID цепочки комутаций сгенерировавшей задание на перезвон.
При необходимости исключить задание на перезвон, например в случае если был произведён один успешный перезвон и по остальным перезвонам абоненту звонить более не нужно — можно для данного абонента обнулить поле  hourrecall таблицы [dbo].[is_alex_recall] для всех последующих заданий на перезвон (т.е. С большим ID).

    Исходящая задача, Кеш внутри БД, перезвон

    Комментарии

    3

    Телсистемс Юкрейн


    26 марта 201014:13

    1. тут ещё надо будет проверять не пустая ли будет вьюха, тоесть например только начали обзвон и ещё нет данных о том кому в какое время и на какой телефон перезванивать и получится что таблица абонентов у нас полная, а таблица перезвона — пустая. Либо эту таблицу служебным сценарием наполнять либо саму вьюху пересоздавать без фильтров, до тех пор пока не появится необходимость.
    В итоге получается как бы симбиоз того что я предлагаю ( /tasks/public/869/ ) — отдельный режим обхода номеров служебным сценарием. Т.к. тут тоже решать кому звонить/не звонить вставляя записи в таблицу перезвона, будет тот же служебный сценарий
    2. Ещё вопрос возникает с КЕШем. Если из таблицы абонентов (в данном случае вьюхи) исчезает номер, то в КЕШе будет запись о том, что номеру присвоен статус 3 — тоесть исключён из набора как себя поведёт Октелл, когда у него в Вьюхе появится тот номер, который в КЕШе уже отмечен как "исключен из набора"? Поэтому надо будет ещё в КЕШе искать эту запись и править её помимо добалвение записи в таблицу перезвона
    3. Так же вопрос — это общий процент выполненения задачи, тоесть супервизор будет видеть в ресурсах, что задача выполнена на 90% и поставит туда только 1го оператора, а остальных перекинет на другие. А на самом деле там задача будет выполнене на 1-2%, а отображать 90% будет как результат обзвона по текущей вьюхе. В случае режима "обход по служебному сценарию" — хранимая процедура по расчёту ресурсов, будет опираться на реальную таблицу абонентов и оперативную статистику по задаче — поэтому будет давать объективные результаты

      4

      Инсофт Сервис


      26 марта 201014:36

      1) Вьюха будет пустая если не заполнены задания на перезвон. Указано, что при данной схеме — задания на первичный прозвон и задания на перезвон — суть одно и то же. Решать кому звонить, кому не звонить решает оператор во время диалога с абонентов, когда он указывает в диалоговой форме время перезвона.
      2) В статье указан механизм выправления кеша. Он прост как полено.
      3) Проблемы с % выполнения начнутся когда мы начнём "играться" со временем перезвона. Но нут не всё так однозначно: предположим, что "на сейчас" обзванивать негого — время не подошло, а обзвонить через неделю. Что делать?

        Новое сообщение

        Прикрепить файлы

        Написать