Почему при программной загрузке Табеля в 1С:ЗУП 3.1 пропадают невыходы (НН) и как это исправить?

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

При автоматизации учета рабочего времени в программе 1С:Зарплата и управление персоналом 3.1 разработчики часто сталкиваются со странным поведением системы при интеграции с внешними источниками. Типичный сценарий: в течение месяца кадровики создают документы Отсутствие (болезнь, прогул, неявка), регистрируя невыходы (код «НН»). В конце месяца из сторонней системы (например, СКУД или внешней базы) загружаются данные и программно создаются документы Табель. Однако сразу после загрузки в отчете «Т-13» вместо ожидаемых «НН» в дни отсутствий выводятся выходные дни («В»).

Самое удивительное происходит дальше: если этот табель вручную распровести, а затем снова провести, то «НН» возвращается на свое место в отчете Т-13! Выясним причину этого феномена и найдем системные способы его решения без использования «костылей» в виде интерактивного перепроведения.

Архитектура учета времени в 1С:ЗУП 3.1: почему так происходит?

Для начала проанализируем, как конфигурация 1С:ЗУП 3.1 собирает данные для унифицированной формы Т-13. В отличие от старых версий (например, ЗУП 2.5), где документ Табель обладал абсолютным приоритетом и перезаписывал любые другие кадровые данные, в редакции 3.1 логика кардинально изменилась.

Отчет Т-13 строится на основании данных из нескольких регистров накопления:

  1. «Данные табельного учета рабочего времени сотрудников» — сюда записывает движения документ Табель.
  2. «Отработанное время по сотрудникам» — сюда пишут свои движения документы-отклонения (такие как Больничный лист, Отпуск, Отсутствие (болезнь, прогул, неявка) и т.д.).

При формировании Т-13 программа сопоставляет эти данные. Согласно методологии конфигурации, документы-отклонения имеют приоритет вытеснения над плановым временем и явками, указанными в табеле. Если за один и тот же день зарегистрированы и невыход, и явка (или выходной), приоритет отдается невыходу.

Однако при программном создании документа Табель этот механизм дает сбой. Рассмотрим по шагам, почему при первой записи документа код «НН» заменяется на «В»:

  1. Программа создает новый объект документа в оперативной памяти и заполняет его табличную часть данными из файла (где на месте отсутствия сотрудника указан код «В» или стоят пустые часы).
  2. Разработчик вызывает метод Записать(РежимЗаписиДокумента.Проведение).
  3. Внутри транзакции проведения срабатывает обработчик ОбработкаПроведения модуля документа. На этом этапе система выполняет сложные поисковые запросы к СУБД для сопоставления данных новой табличной части документа Табель с существующими в базе документами отклонений.
  4. Критический момент: поскольку документ абсолютно новый и еще ни разу не был физически записан в базу данных, СУБД в контексте транзакции проведения не может корректно проиндексировать и сопоставить строки табличной части табеля по его ссылке с другими регистрами. Ссылка на документ уже существует, но сами данные табличной части в таблицах базы данных еще физически отсутствуют (они находятся только в оперативной памяти объекта).
  5. В результате алгоритм сопоставления отрабатывает некорректно: система не находит пересечений и записывает в регистр «чистые» движения из файла (где стоял выходной «В»). Отчет Т-13 выводит «В».

Когда мы делаем отмену проведения и повторное проведение, документ уже записан в базе данных. Его строки физически сохранены на диске. При повторном проведении запросы ЗУП отрабатывают штатно, находят пересечение с документом Отсутствие и заменяют «В» на «НН» в движениях регистров.

---

Как решить проблему правильно: три практических способа

Рассмотрим несколько вариантов решения этой проблемы в коде вашей обработки загрузки.

Способ 1. Разделение записи и проведения (самый быстрый и надежный)

Чтобы избежать сбоев в работе запросов внутри обработчика проведения, нам необходимо гарантировать, что данные табличной части физически попадут в базу данных до того, как начнется транзакция проведения и расчет движений. Для этого достаточно разделить запись объекта и его проведение.

Посмотрим на пример правильной последовательности вызовов в коде:


// Заполняем реквизиты и табличные части документа "Табель"...
ДокТабель.Дата = КонецМесяца(ПериодРегистрации);
ДокТабель.Организация = ВыбраннаяОрганизация;
// ... (заполнение ТЧ ДанныеОРабочемВремени)

// Шаг 1. Записываем документ в базу данных без проведения
ДокТабель.Записать(РежимЗаписиДокумента.Запись); 

// Шаг 2. Проводим уже физически существующий в базе документ
ДокТабель.Записать(РежимЗаписиДокумента.Проведение);

При такой схеме во время выполнения транзакции проведения СУБД успешно прочитает строки табличной части документа из базы данных, сопоставит их с зарегистрированными ранее отклонениями и запишет в регистры верные данные с кодом «НН».

Способ 2. Использование типового механизма заполнения времени

Просто переносить «Я» и «В» из внешнего файла в пустой документ — не всегда лучшее решение, так как кадровики не увидят реальную картину отклонений в интерфейсе самого документа Табель (там останутся «В» вместо «НН», хотя в отчете Т-13 все будет красиво).

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

  1. Создаем документ Табель.
  2. Заполняем список сотрудников.
  3. Вызываем встроенный экспортный метод для заполнения рабочих дней по графикам и отклонениям, зарегистрированным в ЗУП. В зависимости от версии конфигурации это могут быть методы общего модуля УчетРабочегоВремени или модуля менеджера документа. Например:

// Заполняем документ стандартным механизмом ЗУП
Документы.Табель.ЗаполнитьДокумент(ДокТабель);

После этого в табличной части документа уже будут стоять корректные «НН», «ОТ» (отпуска) и «Б» (больничные). Теперь мы можем обойти табличную часть циклом, сравнить ее с данными из нашего внешнего файла загрузки, обновить только часы явки («Я») там, где это необходимо, и провести документ стандартным образом.

Способ 3. Обязательное заполнение служебных табличных частей

При программном создании документов в ЗУП 3.1 разработчики часто забывают, что под капотом сложных документов скрывается множество служебных табличных частей. У документа Табель, помимо основной ТЧ ДанныеОРабочемВремени, присутствуют табличные части Сотрудники и ФизическиеЛица.

Если при программном формировании документа вы заполняете только ДанныеОРабочемВремени, оставляя служебные ТЧ пустыми, то при проведении алгоритмы расчета времени ЗУП отработают непредсказуемо, так как они ориентируются на состав сотрудников в ТЧ Сотрудники.

Обязательно проверяйте полноту заполнения всех связанных табличных частей. Для упрощения этой задачи рекомендуется использовать процедуру инициализации документа:


// Заполнение служебных таблиц на основании основных данных
ДокТабель.ЗаполнитьФизическихЛиц();

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

← На главную