Как-то раз, в самый обычный день, для самого обычного программиста прилетела на голову задача: "Нужно учитывать фактическое пребывание персонала на территории".
И вот не долго думая, не гадая, выбор пал на СКУД (Система Контроля и Управления Доступа). Проанализировав внимательно возможности системы которая имелась, а это была СКУД Orion, стало очевидно, что функционала, который она дает, недостаточно для учета посещений.
Так появилась идея для доработки функционала.
Первым делом необходимо было проанализировать базу данных системы и оценить хранимые в ней данные.
Таким образом, в результате анализа выяснилось что, например, таблица pLogData хранила в себе нужные события прохода по пропускам, а таблица pList это таблица сотрудников.
После тщательного анализа продумывались запросы к базе данных которые будут исходить из 1С и просить вернуть необходимые данные.
Так получился запрос для сбора необходимых данных:
|Select
| [TimeVal]
| ,PCompany.[Name] as Company
| ,PDivision.Name as Division
| ,[DoorIndex] as DoorIndex
| ,AP.Name as DoorName
| ,PPost.Name as Post
| ,pList.Post as IDPost
| ,pList.Name + ' ' + pList.FirstName + ' ' + pList.MidName as FIO
| ,pList.Name + ' ' + SUBSTRING(pList.FirstName, 1, 1) + '. ' + SUBSTRING(pList.MidName, 1, 1) + '.' as ShortFIO
| ,pList.ID as IDWoker
| ,pList.Company as IDCompany
| ,pList.Section as IDDivision
| ,[Remark]
| ,[pLogData].[Mode]
| ,[DeviceTime]
| ,pLogData.[Event] as Event
|From [dbo].[pLogData]
| inner join [dbo].[pList]
| ON pList.ID = pLogData.HozOrgan "
+ ?(ЗначениеЗаполнено(Сотрудник) ИЛИ ЗначениеЗаполнено(Подразделение) ИЛИ ЗначениеЗаполнено(Организация) ИЛИ ЗначениеЗаполнено(Турникет),
?(ЗначениеЗаполнено(Сотрудник), "and HozOrgan in (" + СтрЗаменить(Строка(Сотрудник) + ")", " ", ""), "") +
?(ЗначениеЗаполнено(Подразделение), "and Section in (" + СтрЗаменить(Строка(Подразделение) + ")", " ", ""), "") +
?(ЗначениеЗаполнено(Организация), "and Company in (" + СтрЗаменить(Строка(Организация) + ")", " ", ""), "" ) +
?(ЗначениеЗаполнено(ТурникетП), "and DoorIndex in (" + СтрЗаменить(Строка(ТурникетП) + ")", " ", ""), "" ) +
?(ЗначениеЗаполнено(событиеП), "and pLogData.[Event] in (" + СтрЗаменить(Строка(событиеП) + ")", " ", ""), "" ),
"") +
"
| And TimeVal BETWEEN CAST(Convert(varchar, '"+НачалоПериода +"', 103) AS DateTime) AND CAST(Convert(varchar, '"+КонецПериода +"', 103) AS DateTime)
| left join [dbo].[PCompany]
| on pList.Company = PCompany.ID
| left join [dbo].[PDivision]
| on pList.Section = PDivision.ID
| left join [dbo].[PPost]
| on pList.Post = PPost.ID
| Inner join [dbo].[AcessPoint] as AP
| on pLogData.DoorIndex = AP.GIndex "
+ ?(ЗначениеЗаполнено(НомерНужнойЗоны), "and AP.IndexZone2 = " + СтрЗаменить(Строка(НомерНужнойЗоны), " ", ""), "") +
"
| Order by PCompany.[Name], PDivision.Name, pList.Name + ' ' + pList.FirstName + ' ' + pList.MidName, pList.ID, TimeVal
А теперь получается что мы получили запрос, которому необходимо передавать параметры, чтобы он отработал правильно.
Значит, при формировании отчета мы должны их откуда-то брать, а перед этим еще и выбрать нужные нам параметры.
Решение пало на загрузку параметров из базы данных СКУД.
Тем самым мы получили еще один пакетный запрос:
|Set NOCOUNT ON
|
|SELECT [pList].[ID] as IDWorker
| ,[pList].[Name] + ' ' + [FirstName] + ' ' + [MidName] as FIO
| ,[Company] as IDCompany
| ,[Section] as IDSection
| ,[Post] as IDPost
| ,[PCompany].[Name] as NameCompany
| ,[PDivision].[Name] as NameDivision
| ,[PPost].[Name] as NamePost
|FROM [Orion].[dbo].[pList]
|left join [Orion].[dbo].[PCompany]
|on pList.Company = PCompany.ID
|left join [Orion].[dbo].[PDivision]
|on pList.Section = PDivision.ID
|left join [Orion].[dbo].[PPost]
|on pList.Post = PPost.ID
|
|SELECT
| [ID]
| ,[Name]
| FROM [Orion].[dbo].[AccessZone]
|
|SELECT [GIndex]
| ,[Name]
|FROM [Orion].[dbo].[AcessPoint]
|
|SELECT [Event] as ID
| ,[Contents] as Name
|FROM [Orion].[dbo].[Events]
|
Этим самым запросом мы получаем данные, необходимые для подстановки в первый запрос.
Теперь мы получили необходимые данные и готовы использовать их.
Так как внешний отчет формируется на СКД (Система Компоновки Данных), необходимо полученные параметры передать в параметры СКД и показать пользователю для выбора.
Для этого распределяем полученные данные в таблицы подобным образом:
Пока Результат <> Неопределено Цикл
Если НомерРекордсета = 1 Тогда
Пока Не Результат.EOF Цикл
Таблица = ТаблицаСотрудников;
ТаблицаЗапись = Таблица.Добавить();
ТаблицаЗапись.ИДСотрудника = Число(Результат.Fields("IDWorker").Value);
ТаблицаЗапись.ФИОСотрудника = СокрЛП(Строка(Результат.Fields("FIO").Value));
ТаблицаЗапись.ИДОрганизации = Число(Результат.Fields("IDCompany").Value);
ТаблицаЗапись.ИмяОрганизации = СокрЛП(Строка(Результат.Fields("NameCompany").Value));
ТаблицаЗапись.ИДПодразделения = Число(Результат.Fields("IDSection").Value);
ТаблицаЗапись.ИмяПодразделения = СокрЛП(Строка(Результат.Fields("NameDivision").Value));
Результат.MoveNext();
КонецЦикла;
ИначеЕсли НомерРекордсета = 2 Тогда
Пока Не Результат.EOF Цикл
Таблица = ТаблицаЗоны;
ТаблицаЗапись = Таблица.Добавить();
ТаблицаЗапись.Идентификатор = Число(Результат.Fields("ID").Value);
ТаблицаЗапись.Значение = СокрЛП(Строка(Результат.Fields("Name").Value));
Результат.MoveNext();
КонецЦикла;
ИначеЕсли НомерРекордсета = 3 Тогда
Пока Не Результат.EOF Цикл
Таблица = ТаблицаТурникетов;
ТаблицаЗапись = Таблица.Добавить();
ТаблицаЗапись.Идентификатор = Число(Результат.Fields("GIndex").Value);
ТаблицаЗапись.Значение = СокрЛП(Строка(Результат.Fields("Name").Value));
Результат.MoveNext();
КонецЦикла;
ИначеЕсли НомерРекордсета = 4 Тогда
Пока Не Результат.EOF Цикл
Таблица = ТаблицаСобытий;
ТаблицаЗапись = Таблица.Добавить();
ТаблицаЗапись.Идентификатор = Число(Результат.Fields("ID").Value);
ТаблицаЗапись.Значение = СокрЛП(Строка(Результат.Fields("Name").Value));
Результат.MoveNext();
КонецЦикла;
КонецЕсли;
Результат = Результат.NextRecordSet();
НомерРекордсета = НомерРекордсета + 1;
КонецЦикла;
Теперь загружаем полученные таблицы в параметры СКД и получаем данные из СКУД с учетом параметров и также распределяем данные событий.
Если Выборка <> Неопределено И НЕ Выборка.BOF Тогда
ТаблицаСКУД.Очистить();
Выборка.MoveFirst();
Пока Не Выборка.EOF Цикл
СтрокаТаблицаСКУД = ТаблицаСКУД.Добавить();
СтрокаТаблицаСКУД.Время = Дата(Выборка.Fields("TimeVal").Value);
СтрокаТаблицаСКУД.Организация = СокрЛП(Выборка.Fields("Company").Value);
СтрокаТаблицаСКУД.Подразделение = СокрЛП(Выборка.Fields("Division").Value);
СтрокаТаблицаСКУД.Должность = СокрЛП(Выборка.Fields("Post").Value);
Если ПолноеИмя Тогда
СтрокаТаблицаСКУД.ФИО = СокрЛП(Выборка.Fields("FIO").Value);
Иначе
СтрокаТаблицаСКУД.ФИО = СокрЛП(Выборка.Fields("ShortFIO").Value);
КонецЕсли;
СтрокаТаблицаСКУД.ИДСотрудника = Число(Выборка.Fields("IDWoker").Value);
СтрокаТаблицаСКУД.КраткоФИО = СокрЛП(Выборка.Fields("ShortFIO").Value);
СтрокаТаблицаСКУД.Комментарий = СокрЛП(Выборка.Fields("Remark").Value);
СтрокаТаблицаСКУД.ВходВыход = Число(Выборка.Fields("Mode").Value);
Выборка.MoveNext();
КонецЦикла;
КонецЕсли;
Для удобства пользователя ячейки отчета с выходными, итогами по дням и итогами по месяцу, слишком большим отклонением и отсутствием прохода были раскрашены в разные цвета. Чтобы пользователи всегда понимали какой цвет что обозначает, была создана Легенда цветов с обозначением каждого цвета.
Каждое цветовое обозначение отчета представлено на второй картинке в описании.
Задача была формировать отчет независимо от того в какой конфигурации будет он формироваться, он должен работать. Как результат, отчет не привязан к объектам конфигурации, полностью собирает данные из СКУД и обрабатывает не используя данные конфигурации.
В заключении, таким образом был создан отчет, который показывает фактическое пребывание персонала на территории; показывает время прихода и ухода сотрудников; собирает данные в удобном представлении для пользователя и так как отчет на СКД использует все возможности отчетов СКД. Не используя при этом данные и объекты конфигурации 1С, что позволяет запускать его в любой конфигурации, которая имеет возможность чтобы взаимодействовать с базой данных пропускной системы.
Проверено на следующих конфигурациях и релизах:
- Бухгалтерия предприятия КОРП, редакция 3.0, релизы 3.0.186.21
- Бухгалтерия предприятия, редакция 3.0, релизы 3.0.186.21
Вступайте в нашу телеграмм-группу Инфостарт