Расчет рабочего времени на основе данных системы контроля и управления доступом (СКУД) — классическая задача для автоматизации управленческого учета. Часто данные из турникетов поступают в 1С в виде «сырого» лога событий: сотрудник, время, тип события (Вход/Выход). Основная сложность заключается не в простом вычитании времени, а в обработке ошибочных ситуаций, когда сотрудники проходят «паровозиком», забывают карты или совершают несколько входов подряд. В этой статье мы разберем методики очистки данных и программные способы расчета интервалов.
Прежде чем приступать к написанию кода, проанализируем структуру данных. Обычно мы имеем дело с последовательностью записей. Рассмотрим типичную ситуацию: сотрудник может входить и выходить из здания несколько раз за день (на обед, по рабочим вопросам или на перекур). Наша задача — превратить этот плоский список в набор интервалов «Приход — Выход».
Разберем основные этапы предобработки, которые необходимо выполнить, чтобы расчет был корректным:
Проанализируем ситуацию с ошибочными записями. Чтобы расчет не «поплыл», мы должны применить логический фильтр. Рассмотрим шаги по очистке лога:
Во-первых, удалим идущие подряд одинаковые события для одного сотрудника. Если у нас есть цепочка «Вход 09:00, Вход 09:05, Выход 18:00», мы должны оставить только самый первый «Вход». Если же цепочка «Вход 09:00, Выход 17:55, Выход 18:00», мы оставляем только последний «Выход».
Во-вторых, разберем методику обработки «сиротских» записей. Если рабочий день начинается с выхода, это событие зачастую игнорируется при расчете текущего дня (или относится к предыдущему, если система поддерживает учет ночных смен). Аналогично, незакрытый вход в конце дня требует либо ручного вмешательства, либо автоматического «закрытия» по графику (например, в 18:00 или в 21:00).
Посмотрим, как можно реализовать этот алгоритм в коде 1С. Использование обычного перебора выборки в цикле может быть неэффективным при больших объемах данных (тысячи сотрудников). Проанализируем, как решить задачу с помощью механизмов платформы.
Наиболее эффективный современный способ (для платформы 8.3.15 и выше) — использование оконных функций в языке запросов. Рассмотрим логику применения функций LEAD или LAG. Эти функции позволяют в текущей строке запроса «заглянуть» в следующую или предыдущую строку. Таким образом, для каждой строки с типом «Приход» мы можем сразу получить время следующего за ним «Выхода».
Если же мы работаем на более старых версиях платформы, воспользуемся классическим методом соединения временных таблиц:
ВременнаяТаблицаСобытий с порядковым номером (используя автоинкремент или соединение по условию «меньше»).Т1.Сотрудник = Т2.Сотрудник И Т1.Номер = Т2.Номер - 1.Т1 событие — «Вход», а в Т2 — «Выход».Пример структуры запроса для вычисления интервалов:
ВЫБРАТЬ
Т1.Сотрудник,
Т1.Период КАК ВремяВхода,
МИНИМУМ(Т2.Период) КАК ВремяВыхода
ИЗ
РегистрСведений.СобытияСКУД КАК Т1
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СобытияСКУД КАК Т2
ПО Т1.Сотрудник = Т2.Сотрудник
И Т2.Период > Т1.Период
И Т2.ВидСобытия = ЗНАЧЕНИЕ(Перечисление.ВидыСобытийСКУД.Выход)
ГДЕ
Т1.ВидСобытия = ЗНАЧЕНИЕ(Перечисление.ВидыСобытийСКУД.Вход)
СГРУППИРОВАТЬ ПО
Т1.Сотрудник, Т1.Период
Важно помнить, что такое простое соединение может работать долго на больших базах. Поэтому предварительно стоит ограничить выборку конкретным днем и списком сотрудников.
Выясним, как именно суммировать полученные интервалы. Существует несколько подходов, выбор которых зависит от политики компании:
1. Метод «Чистое время»: Мы суммируем все интервалы нахождения внутри здания. Если сотрудник выходил курить 10 раз по 5 минут, эти 50 минут будут вычтены из рабочего времени. Это самый жесткий и точный метод.
2. Метод «Первый — последний»: Время рассчитывается как разница между самым первым входом и самым последним выходом за день. Промежуточные выходы игнорируются. Чтобы сотрудники не злоупотребляли этим, часто вводится фиксированный вычет на обед (например, 1 час), если общее нахождение превысило определенный порог.
3. Метод «С округлением и границами»: Проанализируем ситуацию, когда сотрудник приходит в 08:30 при начале рабочего дня в 09:00. В учетных системах часто настраивается «отсечение»: всё, что до 09:00 — личное время, если нет распоряжения о сверхурочных. Аналогично с уходом: уход в 18:05 считается как работа до 18:00.
Разберем подробнее технические нюансы работы самих систем СКУД. Рассмотрим понятие «Зоны доступа». В продвинутых системах офис разделен на зоны: «Улица», «Офис», «Столовая», «Склад». В этом случае выход из зоны «Офис» в зону «Столовая» может не считаться прерыванием рабочего времени, а выход в зону «Улица» — считаться.
Также стоит учитывать аппаратную функцию Anti-passback (антивозврат). Если она включена на стороне контроллера турникета, то сотрудник не сможет войти второй раз, не совершив выход. Это значительно упрощает жизнь программисту 1С, так как «сырые» данные приходят уже очищенными от большинства логических ошибок («вход после входа» становится невозможным).
Выясним юридический статус данных СКУД. Важно понимать, что данные с турникета — это лишь основание для заполнения ТабеляУчетаРабочегоВремени. Согласно трудовому законодательству, время нахождения в здании не всегда равно времени выполнения трудовых обязанностей. Поэтому в 1С рекомендуется делать промежуточный документ «Данные о присутствии», который HR-менеджер может скорректировать вручную (например, если сотрудник был в командировке или забыл карту), и только на его основе формировать окончательный табель.
Рассмотрим пример функции для расчета разницы в часах между двумя датами:
Функция РассчитатьВремяВЧасах(ВремяВхода, ВремяВыхода)
Если ЗначениеЗаполнено(ВремяВхода) И ЗначениеЗаполнено(ВремяВыхода) Тогда
РазницаВСекундах = ВремяВыхода - ВремяВхода;
Возврат РазницаВСекундах / 3600;
Иначе
Возврат 0;
КонецЕсли;
КонецФункции
Подводя итог, можно сказать, что идеальный расчет рабочего времени по СКУД в 1С — это сочетание автоматизированного сбора данных, сложного алгоритма очистки «мусора» и возможности ручной корректировки ответственными лицами.