Учет опозданий сотрудников

Материал из Oktell
Перейти к: навигация, поиск

Наверх

Задача: вести статистику по опозданиям сотрудников.

Каждый руководитель хочет быть уверен в соблюдении правил внутреннего распорядка своими сотрудниками. Одним из критериев ответственности сотрудника является время появления на работе. Oktell позволяет автоматизировать эту проверку.


Способы проверки

Существует несколько способов проверки появления сотрудника на работе. Рассмотрим их на примере. Пусть компания начинает работу в 9-00.


Способ 1. Проверка дозвоном.

Каждый день в 9-05 производится обзвон всех сотрудников. Если сотрудник снимает трубку, то считается, что он на рабочем месте.

Достоинства:

  • Проверяет наличие сотрудника на рабочем месте

Недостатки:

  • Вместо проверяемого сотрудника, трубку может снять его коллега.
  • Возможность установить софтфон на телефоне, используя технологию SIP Forking, позволяет сотруднику взять трубку где угодно при наличии интернета. Однако, чаще всего сотрудники не знают паролей от своих устройств.


Способ 2. Проверка по клиентскому приложению.

В 9-05 служебный сценарий обращается в таблицу [oktell].[dbo].[A_CallCenter_UserStateHistory]. В этой таблице хранится время запуска клиентского приложения (столбец TimeEnter) и время, когда клиентское приложение было закрыто (столбец TimeLeave). Для того, чтобы использовать эту идею необходимо включенное клиентское приложение.

Достоинства:

  • Не отвлекает сотрудника от работы

Недостатки:

  • Клиентское приложение должно быть обязательно включено
  • При наличии домена для веб-клиента или веб-оператора, сотрудник может отметиться, зайдя на веб-сервис со своего смартфона.


Способ 3. Смешанный вариант.

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

Достоинства:

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

Недостатки:

  • Такие же, как у варианта 1 - трубку могут поднять другие сотрудники. Однако, этот вариант можно обработать отдельно и записать в отчет с особой пометкой.

В этой статье рассматривается смешанный вариант учета опозданий.


Создание таблицы

Предварительно создается таблица latecomers, в которой будет храниться вся информация по сотрудникам. Таблица имеет следующие поля:

  • Id - номер записи в списке. Тип Int, создается автоматически.
  • date - дата и время проверки. Тип Datetime.
  • user - имя пользователя. Тип NVarchar (auto).
  • status - результат проверки. Тип NVarchar (auto).
  • time - время, с которого у пользователя включено клиентское приложение. Тип Datetime.
  • iduser - идентификатор пользователя. Нужен для нахождения внутреннего номера. Тип NVarchar (auto).


Реализация сценария

Сценарий выглядит следующим образом:


Учет опозданий-001.png


Структурно сценарий состоит из


Компонент "Проверка по таблице" - SQL-запрос определяет запущено ли клиентское приложение у сотрудника и записывает результаты в таблицу.

with ausers as
(
select getdate() ddt,us.Name,'На месте' status,uh.TimeEnter, us.ID
from  [oktell].[dbo].[A_CallCenter_UserStateHistory] uh 
inner join A_Users us 
on uh.operatorid=us.ID
where GETDATE()>TimeEnter 
and (GETDATE()<TimeLeave or TimeLeave is null)
and uh.State =0 
)

insert into latecomers (date,[user],status,time,iduser)
select * from ausers 
union all
select getdate(),Name,'0',null, ID
from A_Users 
where id not in (select id from ausers)


Компонент "id_before" - присваивает переменной id_before (строковая) значение "-1000". Нужен для перебора сотрудников в таблице latecomers, у которых еще нет статуса (не определены с прошлого шага).


Компонент "Определяем следующего" - SQL-запрос определяет следующего пользователя в таблице latecomers, которому нужно позвонить.

select top 1 @id=id, @iduser=iduser, @user=[user]
from latecomers 
where id > @id_before
and status='0' 
and cast(floor(cast(getdate() as float)) as datetime) = cast(floor(cast(date as float)) as datetime)

set @rowcount=@@rowcount

где

  • @id - переменная id_after (строковая). Переменная содержит номер найденного пользователя в таблице latecomers.
  • @id_before - переменная id_before.
  • @iduser - переменная iduser (строковая). Переменная содержит id пользователя.
  • @rowcount - переменная rowcount (строковая). Переменная содержит количество найденных строк.
  • @user - переменная user (строковая). Переменная содержит имя пользователя.


Компонент "Проверка на завершение" - определяет завершен ли перебор по пользователям. Сравнение переменной rowcount с "0".


Компонент "id_before=id_after" - переприсваивает переменную id_before, чтобы найти следующего пользователя. Также обнуляет переменную prefix.

  • переменной idbefore присваивает переменную id_after
  • переменной prefix присваивает пустую строку


Компонент "Внутренний номер по id" - SQL-запрос находит по таблице внутренний номер пользователя по его идентификатору iduser.

ВНИМАНИЕ: У пользователя должен быть "нативный" номер, то есть такой стандартный внутренний номер, в котором только один объект - данный пользователь. Иначе запрос не найдет внутренний номер этого пользователя.

SELECT TOP 1 @prefix=np.Prefix FROM A_NumberPlan np 
INNER JOIN A_NumberPlanAction npa ON np.ID=npa.NumID AND npa.ExtraId IN 
(SELECT RuleID FROM A_RuleRecords 
WHERE reactid=@userid AND InnerAddressType=0 
AND RuleID IN 
(SELECT RuleID FROM A_RuleRecords 
GROUP BY RuleID HAVING COUNT(*)=1)) 
ORDER BY np.Prefix 

где

  • @prefix - переменная prefix, содержит внутренний номер пользователя
  • @userid - переменная iduser


Компонент "Дозвон" - происходит дозвон до пользователя. Если пользователь поднимет трубку или занят (в разговоре) - считается, что он на месте.

  • Номер/команда - prefix
  • Среда - Внутренний номерной план
  • Обслуживание - IVR
  • Сценарий IVR - предварительно созданный IVR сценарий "Учет опозданий IVR". Сценарий достаточно простой - после того, как сотрудник берет трубку, связь обрывается. Здесь можно поставить звуковое оповещение сотрудника о том, что это проверка.


Учет опозданий-002.png


  • Caller ID - "Proverka" (устанавливается по желанию, сотрудники будут видеть это название на табло телефона)
  • Caller Name - "Proverka" (аналогично полю Caller ID)
  • Очередь ожидания - Нет
  • Время ожидания - 40 секунд. Максимальное время за которое сотрудник должен поднять трубку, чтобы система отметила его как на месте.


Компоненты "На месте" , "Занято" или "Нет на месте" - SQL-запросы для обновления статуса в таблице latecomers. Переход к этим компонентам происходит по веткам от предыдущего компонента "Дозвон". Соответственно:

update latecomers 
set status = 'На месте (Взял трубку)'
where iduser=@iduser
update latecomers 
set status = 'На месте (Занято)'
where iduser=@iduser
update latecomers 
set status = 'Нет на месте'
where iduser=@iduser

где

  • @iduser - переменная iduser (во всех запросах).


Создание служебной задачи

Данный сценарий необходимо назначить на служебную задачу. Переходим «Администрирование» - «Общие настройки» - вкладка «Служебные задачи» - «Добавить»

  • Выбираем для запуска данный сценарий.
  • Указываем расписание - с понедельника по пятницу, с 9:05 до 9:10.
  • Тип запуска - периодический, раз в сутки.
  • Нажимаем «Сохранить» и активируем служебную задачу.

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


Учет опозданий-004.png


Результат работы

В таблице latecomers формируется следующая информация:


Учет опозданий-003.png


Файл сценария: Учет опозданий.zip


Запрос для создания таблицы:

USE [oktell]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[latecomers](
	[Id] [int] IDENTITY(1,1) NOT NULL, 
	[date] [datetime] NULL,
	[user] [nvarchar](2000) NULL,
	[status] [nvarchar](2000) NULL,
	[time] [datetime] NULL,
	[iduser] [nvarchar](2000) NULL,
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]
GO