Примеры пользовательских процедур — различия между версиями

Материал из Oktell
Перейти к: навигация, поиск
(Новая страница: «Наверх <pre> if (@idtask = 'B8A22910-BFA4-480D-BFB1-151D0C06F93B') begin select @Id = operatorid from TableMain where Id = @…»)
 
 
(не показано 10 промежуточных версии этого же участника)
Строка 1: Строка 1:
 
[[Практики|Наверх]]
 
[[Практики|Наверх]]
  
 +
__TOC__
 +
 +
Каждый раз когда задача выбирает абонента в исходящей задаче или поступает абонент по входящей, ей необходимо закрепить за ним оператора, который будет его обслуживать. Для этого используется опция "Вариант обхода операторов" в настройках задачи. Администраторы задачи могут выбрать один из 6 алгоритмов распределения или написать свой с помощью пользовательской процедуры.
 +
 +
Пользовательская процедура применяется в Call-центре для динамического распределения операторов внутри задачи. Процедура часто используется в тех случаях, когда каждому клиенту необходимо предоставлять различный набор операторов для обслуживания. В частности, формируемый список может зависеть от квалификации оператора и степени важности клиента. Нередко пользовательская процедура применяется для закрепления абонента за оператором, например в задачах с автоматическим перезвоном.
 +
 +
'''Техническая документация:''' [[Задачи:Ресурсы#procedura|Пользовательская процедура]]
 +
 +
Чтобы установить пользовательскую процедуру в задаче необходимо выполнить следующие шаги:
 +
 +
'''1.''' В настройках задачи на вкладке "'''Ресурсы'''" выберите "'''Вариант обхода операторов'''" - Пользовательская процедура.
 +
 +
 +
[[Файл:Пример пользовательских процедур.png|center|600px]]
 +
 +
 +
'''2.''' Измените текст хранимой процедуры A_TaskManager_OperatorsAll_Get_Custom. Запрос должен возвращать столбец с GUID-идентификаторами операторов в порядке уменьшения приоритета. Тип возвращаемых значений обязательно должен быть uniqueidentifier. В случае необходимости используйте функцию cast:
 +
 +
  cast([user_id] as uniqueidentifier)
 +
 +
В процессе выделения оператора, задача пробегается по полученному от хранимой процедуры списку сверху вниз и берет первого доступного оператора, который работает по данной задаче (является ресурсом для данной задачи). В запросе вы можете использовать следующие входные переменные
 +
*@idtask - идентификатор задачи
 +
*@idlist - идентификатор таблицы абонентов
 +
*@idabonent - номер абонента в списке, т.е. таблице абонентов по которой работает задача
 +
*@idline - идентификатор внешней линии
 +
*@dtnow - текущее время сервера
 +
 +
Чтобы пользовательская процедура срабатывала только для определенной задачи следует воспользоваться конструкцией ''if'':
 +
 +
if (@idtask = 'B77E5601-A103-4A41-B1FD-6E82EEB6B46A')
 +
 +
ID задачи можно узнать в таблице '''A_TaskManager_Tasks'''
 +
 +
 +
Для изменения текста пользовательской процедуры используйте SQL Server Management Studio (SSMS). Найдите хранимую процедуру в списке и нажмите "Изменить". Запрос следует вставлять в специально предназначенное для этого место после комментария (см. рисунок). После изменения выполните запрос.
 +
 +
 +
[[Файл:Перезвон-013.png|center|600px]]
 +
 +
 +
Далее в статье представлены некоторые примеры пользовательских процедур, которые вы можете использовать для решения собственных задач.
 +
 +
 +
== Выбор оператора в зависимости от его приоритета ==
 +
 +
Если в компании операторы имеют некоторое значение квалификации, можно настроить задачу таким образом, чтобы все поступающие абоненты приоритетно распределялись на менее опытных, а если они заняты - то на более опытных специалистов. Для этого создана таблица [oktell].[dbo].[Poryadok_operatory] с полями id (идентификатор оператора), name (имя оператора), mark (оценка квалификации). Хранимая процедура создана таким образом, что в случайном порядке берет менее опытных операторов с оценкой меньше 50, а затем добавляет к списку более опытных. 
  
 
<pre>
 
<pre>
if (@idtask = 'B8A22910-BFA4-480D-BFB1-151D0C06F93B')
+
if (@idtask = '703DDF3A-47E5-4C87-AF0C-5E90130819A8')
begin
+
begin
 +
select *
 +
from (
 +
select top 1000 [id]
 +
from [oktell].[dbo].[Poryadok_operatory]
 +
where mark < 50
 +
order by NEWID()
 +
) a
 +
 +
union all
 +
 +
select *
 +
from (
 +
select top 1000 [id]
 +
from [oktell].[dbo].[Poryadok_operatory]
 +
where mark >= 50
 +
order by NEWID()
 +
) b
 +
end
 +
</pre>
  
  select @Id = operatorid
+
==С закреплением оператора за абонентом==
  from TableMain
+
  where Id = @idabonent
+
 
+
  if (@Id is null)
+
  begin
+
    select u.Id
+
    from A_Users u
+
      inner join A_UserParams up on u.Id = up.Iduser
+
    where IsOperator = 1
+
    order by NEWID()
+
  
  end
+
Данная пользовательская процедура позволяет прикрепить абонента за оператором. В таблице абонентов, по которой работает данная задача, должно быть поле operatorid. Для каждого абонента в этом поле указывается GUID-идентификатор прикрепленного оператора. Запрос работает таким образом, что если у абонента указан закрепленный за ним оператор, то возвращает только его GUID. Если закрепленного оператора нет возвращается список всех операторов в случайном порядке.
  else
+
 
  begin
+
Если вы используете данную процедуру для входящей задачи, то рекомендуется установить очередь ожидания.
    select @Id Id
+
 
  end
+
<pre>
 +
if (@idtask = 'B8A22910-BFA4-480D-BFB1-151D0C06F93B')
 +
begin
 +
select @Id = operatorid
 +
from TableMain
 +
where Id = @idabonent
 +
 
 +
if (@Id is null)
 +
begin
 +
select u.Id
 +
from A_Users u
 +
inner join A_UserParams up on u.Id = up.Iduser
 +
where IsOperator = 1
 +
order by NEWID()
 +
end
 +
else
 +
begin
 +
select @Id Id
 +
end
 +
end
 
</pre>
 
</pre>
  
  
 +
==С закреплением оператора за абонентом и проверкой статуса оператора ==
 +
 +
Данная пользовательская процедура аналогична предыдущей с закреплением оператора, однако она также учитывает еще и текущий статус оператора. В таблице абонентов, по которой работает задача, должно быть поле idoperator. Для каждого абонента в этом поле указывается GUID-идентификатор прикрепленного оператора. Процедура учитывает статус оператора таким образом, что если его нет на месте или он не авторизован в клиентском приложении, то абонент распределяется на остальных операторов в случайном порядке. Если же оператор на месте, занят, в перерыве или недоступен, но у него включено клиентское приложение, считается, что он в системе, поэтому процедура выбирает только его.
 +
 +
Такой алгоритм изначально был реализован для исходящей задачи с перезвоном. Алгоритм позволяет обойти ситуацию, когда перезвон назначен, но ответственный оператор вдруг заболел. Тогда, задача распределяет перезвон на других операторов.
  
 
<pre>
 
<pre>
if (@idtask = 'B77E5601-A103-4A41-B1FD-6E82EEB6B46A')
+
if (@idtask = 'B77E5601-A103-4A41-B1FD-6E82EEB6B46A')
begin
+
begin
+
declare @state int
declare @state int  
+
  
select @ID = idoperator
+
select @ID = idoperator
from clients
+
from clients
where id = @idabonent
+
where id = @idabonent
  
SELECT top 1 @state = h.state  
+
select top 1 @state = h.state
FROM A_Users u
+
from A_Users u
LEFT JOIN (SELECT h.*
+
left join (
    FROM
+
select h.*
      (
+
from (
  SELECT UserId, max(TimeChange) TimeChange
+
select UserId
  FROM A_UserStateHistory  
+
,max(TimeChange) TimeChange
        GROUP BY UserId
+
from A_UserStateHistory
  ) t
+
group by UserId
    JOIN A_UserStateHistory h ON t.UserId = h.UserId AND h.TimeChange = t.TimeChange
+
) t
    ) h ON h.UserId = u.Id
+
join A_UserStateHistory h on t.UserId = h.UserId
WHERE u.id   = @ID
+
and h.TimeChange = t.TimeChange
 +
) h on h.UserId = u.Id
 +
where u.id = @ID
  
    if (@state= 0 or @state is null)
+
if (
    begin
+
@state = 0
  select u.Id
+
or @state is null
    from A_Users u
+
)
      inner join A_UserParams up on u.Id = up.Iduser
+
begin
    where IsOperator = 1
+
select u.Id
    order by NEWID()
+
from A_Users u
  end
+
inner join A_UserParams up on u.Id = up.Iduser
  else
+
where IsOperator = 1
  begin
+
order by NEWID()
    select @ID Id
+
end
  end
+
else
end
+
begin
 +
select @ID Id
 +
end
 +
end
 
</pre>
 
</pre>

Текущая версия на 12:43, 21 марта 2015

Наверх

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

Пользовательская процедура применяется в Call-центре для динамического распределения операторов внутри задачи. Процедура часто используется в тех случаях, когда каждому клиенту необходимо предоставлять различный набор операторов для обслуживания. В частности, формируемый список может зависеть от квалификации оператора и степени важности клиента. Нередко пользовательская процедура применяется для закрепления абонента за оператором, например в задачах с автоматическим перезвоном.

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

Чтобы установить пользовательскую процедуру в задаче необходимо выполнить следующие шаги:

1. В настройках задачи на вкладке "Ресурсы" выберите "Вариант обхода операторов" - Пользовательская процедура.


Пример пользовательских процедур.png


2. Измените текст хранимой процедуры A_TaskManager_OperatorsAll_Get_Custom. Запрос должен возвращать столбец с GUID-идентификаторами операторов в порядке уменьшения приоритета. Тип возвращаемых значений обязательно должен быть uniqueidentifier. В случае необходимости используйте функцию cast:

 cast([user_id] as uniqueidentifier)

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

  • @idtask - идентификатор задачи
  • @idlist - идентификатор таблицы абонентов
  • @idabonent - номер абонента в списке, т.е. таблице абонентов по которой работает задача
  • @idline - идентификатор внешней линии
  • @dtnow - текущее время сервера

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

if (@idtask = 'B77E5601-A103-4A41-B1FD-6E82EEB6B46A')

ID задачи можно узнать в таблице A_TaskManager_Tasks


Для изменения текста пользовательской процедуры используйте SQL Server Management Studio (SSMS). Найдите хранимую процедуру в списке и нажмите "Изменить". Запрос следует вставлять в специально предназначенное для этого место после комментария (см. рисунок). После изменения выполните запрос.


Перезвон-013.png


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


Выбор оператора в зависимости от его приоритета

Если в компании операторы имеют некоторое значение квалификации, можно настроить задачу таким образом, чтобы все поступающие абоненты приоритетно распределялись на менее опытных, а если они заняты - то на более опытных специалистов. Для этого создана таблица [oktell].[dbo].[Poryadok_operatory] с полями id (идентификатор оператора), name (имя оператора), mark (оценка квалификации). Хранимая процедура создана таким образом, что в случайном порядке берет менее опытных операторов с оценкой меньше 50, а затем добавляет к списку более опытных.

if (@idtask = '703DDF3A-47E5-4C87-AF0C-5E90130819A8')
begin
	select *
	from (
		select top 1000 [id]
		from [oktell].[dbo].[Poryadok_operatory]
		where mark < 50
		order by NEWID()
		) a
	
	union all
	
	select *
	from (
		select top 1000 [id]
		from [oktell].[dbo].[Poryadok_operatory]
		where mark >= 50
		order by NEWID()
		) b
end

С закреплением оператора за абонентом

Данная пользовательская процедура позволяет прикрепить абонента за оператором. В таблице абонентов, по которой работает данная задача, должно быть поле operatorid. Для каждого абонента в этом поле указывается GUID-идентификатор прикрепленного оператора. Запрос работает таким образом, что если у абонента указан закрепленный за ним оператор, то возвращает только его GUID. Если закрепленного оператора нет возвращается список всех операторов в случайном порядке.

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

if (@idtask = 'B8A22910-BFA4-480D-BFB1-151D0C06F93B')
begin
	select @Id = operatorid
	from TableMain
	where Id = @idabonent

	if (@Id is null)
	begin
		select u.Id
		from A_Users u
		inner join A_UserParams up on u.Id = up.Iduser
		where IsOperator = 1
		order by NEWID()
	end
	else
	begin
		select @Id Id
	end
end


С закреплением оператора за абонентом и проверкой статуса оператора

Данная пользовательская процедура аналогична предыдущей с закреплением оператора, однако она также учитывает еще и текущий статус оператора. В таблице абонентов, по которой работает задача, должно быть поле idoperator. Для каждого абонента в этом поле указывается GUID-идентификатор прикрепленного оператора. Процедура учитывает статус оператора таким образом, что если его нет на месте или он не авторизован в клиентском приложении, то абонент распределяется на остальных операторов в случайном порядке. Если же оператор на месте, занят, в перерыве или недоступен, но у него включено клиентское приложение, считается, что он в системе, поэтому процедура выбирает только его.

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

if (@idtask = 'B77E5601-A103-4A41-B1FD-6E82EEB6B46A')
begin
	declare @state int

	select @ID = idoperator
	from clients
	where id = @idabonent

	select top 1 @state = h.state
	from A_Users u
	left join (
		select h.*
		from (
			select UserId
				,max(TimeChange) TimeChange
			from A_UserStateHistory
			group by UserId
			) t
		join A_UserStateHistory h on t.UserId = h.UserId
			and h.TimeChange = t.TimeChange
		) h on h.UserId = u.Id
	where u.id = @ID

	if (
			@state = 0
			or @state is null
			)
	begin
		select u.Id
		from A_Users u
		inner join A_UserParams up on u.Id = up.Iduser
		where IsOperator = 1
		order by NEWID()
	end
	else
	begin
		select @ID Id
	end
end