Как рассчитать время отсутствия сотрудников по данным пропускной системы (СКУД) в 1С?

Программист 1С v8.3 (Управляемые формы) Управленческий учет IT и автоматизация бизнеса
← На главную

Рассмотрим классическую задачу контроля рабочего времени. У нас есть база данных системы контроля и управления доступом (СКУД), в которой фиксируются события прохода сотрудников через турникеты или двери. Руководство ставит задачу: выявить всех сотрудников, которые в течение рабочего дня отлучались с рабочего места (выходили из рабочей зоны) более чем на 20 минут.

Проанализируем исходные данные. Как правило, таблица логов СКУД содержит следующие базовые поля:

  1. TimeVal — точные дата и время события;
  2. HozOrgan — уникальный идентификатор (ID) сотрудника;
  3. Mode — тип события (например, 1 — вход, 2 — выход).

Разберем два подхода к решению этой задачи: с помощью языка запросов 1С и с использованием алгоритма конечного автомата в коде. А также посмотрим на современные способы интеграции.

Попытка 1: Решение задачи с помощью SQL-запроса в 1С

Первая мысль разработчика — написать запрос, который выберет все входы, все выходы, соединит их по идентификатору сотрудника и найдет разницу во времени. Посмотрим на пример запроса, где мы пытаемся получить временные таблицы входов и выходов, а затем вычислить интервал с помощью функции РАЗНОСТЬДАТ.


ВЫБРАТЬ
    dbo_pLogData.HozOrgan КАК HozOrgan,
    dbo_pLogData.TimeVal КАК времяВхода
ПОМЕСТИТЬ ВременнаяТаблицаВходы
ИЗ
    ВнешнийИсточникДанных.ПроходнаяSQL.Таблица.dbo_pLogData КАК dbo_pLogData
ГДЕ
    dbo_pLogData.Mode = 1
СГРУППИРОВАТЬ ПО
    dbo_pLogData.HozOrgan,
    dbo_pLogData.TimeVal
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    dbo_pLogData.HozOrgan КАК HozOrgan,
    dbo_pLogData.TimeVal КАК времявыхода
ПОМЕСТИТЬ ВременнаяТаблицаВыходы
ИЗ
    ВнешнийИсточникДанных.ПроходнаяSQL.Таблица.dbo_pLogData КАК dbo_pLogData
ГДЕ
    dbo_pLogData.Mode = 2
СГРУППИРОВАТЬ ПО
    dbo_pLogData.HozOrgan,
    dbo_pLogData.TimeVal
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Входы.HozOrgan КАК HozOrgan,
    ВЫБОР
        КОГДА РАЗНОСТЬДАТ(Выходы.времявыхода, Входы.времяВхода, МИНУТА) > 20
        ТОГДА РАЗНОСТЬДАТ(Выходы.времявыхода, Входы.времяВхода, МИНУТА)
    КОНЕЦ КАК ВремяОтсутствия,
    Входы.времяВхода КАК времяВхода,
    Выходы.времявыхода КАК времявыхода
ИЗ
    ВременнаяТаблицаВходы КАК Входы
        ПОЛНОЕ СОЕДИНЕНИЕ ВременнаяТаблицаВыходы КАК Выходы
        ПО Входы.HozOrgan = Выходы.HozOrgan
            И (НАЧАЛОПЕРИОДА(Выходы.времявыхода, ДЕНЬ) = НАЧАЛОПЕРИОДА(Входы.времяВхода, ДЕНЬ))
            И (Выходы.времявыхода < Входы.времяВхода)

Почему такой подход часто не работает? Сырые логи СКУД практически никогда не бывают идеальными. Сотрудник может выйти, не приложив карту (кто-то открыл дверь перед ним), приложить карту два раза подряд (турникет не сработал с первого раза). В результате в базе появляются два события «Вход» подряд без события «Выход». В таком случае полное или левое соединение в запросе выдаст некорректные декартовы произведения строк (задвоения), и результаты расчета времени поедут. Решить проблему краевых случаев исключительно запросом — невероятно сложная задача.

Попытка 2: Использование алгоритма «Машина состояний» (Конечный автомат)

Выясним, как правильно обрабатывать поток событий. Лучший подход — отказаться от сложных соединений в запросе и пройтись по отсортированной выборке событий программно, используя логику конечного автомата. Разберем алгоритм по шагам.

  1. Сортировка. Получаем из базы плоский список событий за день, отсортированный по TimeVal по возрастанию.
  2. Хранилище состояний. Создаем в коде структуру или Соответствие, где ключом будет ID сотрудника, а значением — структура его текущего состояния (например: ТекущийСтатус (Вошел/Вышел), ВремяПоследнегоСобытия, СсылкаНаСтрокуТаблицыОтсутствия).
  3. Цикл обработки. Начинаем перебирать события:
    • Берем строку события. Проверяем состояние сотрудника в нашем соответствии. Если его там нет — создаем.
    • Сценарий А: Статус был «Вышел», текущее событие «Вход». Добавляем строку в итоговую таблицу посещений, записываем время входа, обновляем статус сотрудника на «Вошел». Если нас интересует время отсутствия, мы берем время предыдущего выхода (из состояния) и сравниваем с текущим входом. Если разница больше 20 минут — фиксируем нарушение.
    • Сценарий Б: Статус был «Вошел», событие «Выход». Вычисляем время нахождения на рабочем месте, переводим статус сотрудника в «Вышел», запоминаем время выхода для будущего сравнения.
    • Сценарий В (Ошибки СКУД): Статус был «Вошел», и прилетает снова «Вход». Мы анализируем время предыдущего входа. Если оно было пару секунд назад — это ложное срабатывание (дрогнула рука у считывателя), игнорируем. Если прошел час — значит, сотрудник выходил по чужой карте. Помечаем этот отрезок как проблемный для дальнейшего анализа.

Такой программный проход в один цикл работает крайне быстро и позволяет гибко реагировать на любые аномалии в данных (например, если первое событие за день — это «Выход»).

Современные подходы и готовые решения интеграции

Проанализируем ситуацию на сегодняшний день. Писать парсинг сырых логов СКУД с нуля требуется все реже. Современная практика диктует использование специализированных решений:

1. Специализированные модули интеграции. Вместо прямых SQL-запросов к таблицам СКУД сейчас используют готовые модули от производителей (например, Sigur, RusGuard или интеграции с системами Болид). Эти модули самостоятельно очищают логи от двойных прикладываний, формируют готовые смены и передают в 1С уже рассчитанные интервалы присутствия.

2. Настройка допусков без кода. Современные подсистемы Учета рабочего времени (WFM) позволяют кадровикам настраивать правила «на лету». Можно в режиме предприятия указать, что отлучки до 10 минут суммируются, но не считаются прогулом, а все, что больше 20 минут — жестко вычитается из табеля.

3. Связь с кадровыми документами (Т-13). Программная фиксация отсутствия в 25 минут — это только половина дела. Правильная интеграция сопоставляет эти пропуски с документами из 1С:ЗУП. Если на время отсутствия оформлена «Местная командировка» или согласованный отгул, система не посчитает это прогулом.

4. Аппаратная защита от "мусора" в логах. Чтобы не писать сложный код обработки ложных входов/выходов, безопасники включают на контроллерах функцию Anti-passback (запрет повторного прохода). Турникет просто не пустит человека внутрь по карте, если по базе он уже находится внутри. Это автоматически делает логи СКУД линейными и чистыми, что сводит написание отчетов в 1С к простейшим запросам.

Применяя данные рекомендации и комбинируя программные проверки с аппаратными настройками СКУД, вы сможете построить точную систему учета рабочего времени.

← На главную