При кастомизации подсистем расчета зарплаты и учета рабочего времени в решениях на платформе «1С:Предприятие 8» разработчики часто сталкиваются с неочевидным поведением виртуальных таблиц регистров расчета. Особенно ярко это проявляется в конфигурации «Зарплата и Управление Персоналом» редакции 2.5 (и аналогичных решениях), где механизмы расчета сильно завязаны на взаимное вытеснение и приоритеты источников данных о времени.
В этой статье мы подробно разберем ситуацию, когда внедрение нетипового документа «Табель учета рабочего времени» для первой половины месяца приводит к тому, что при расчете начислений (например, отпуска) во второй половине месяца система возвращает 0 оплачиваемых дней. Мы проанализируем внутреннее устройство подсистемы расчета времени, выясним причины такого поведения виртуальных таблиц и найдем пути решения проблемы.
Рассмотрим стандартный сценарий: за первую половину месяца (с 1 по 15 число) вводится документ учета времени. Во второй половине месяца сотрудник уходит в отпуск (например, с 17 числа). При расчете документа «Начисление отпуска» программа должна определить количество дней и часов, приходящихся на период отпуска, чтобы рассчитать сумму начисления.
Для определения времени в периоде действия записи регистр расчета обращается к виртуальной таблице ДанныеГрафика. В нормальной ситуации система должна вести себя следующим образом:
При использовании типового табеля этот алгоритм работает безотказно. Однако при проведении аналогичного нетипового табеля виртуальная таблица ДанныеГрафика (поле ОсновноеЗначениеПериодДействия) начинает игнорировать вторую половину месяца. Период с 16 по 31 число рассчитывается как пустой (значение 0), как будто у сотрудника не заполнен график работы.
Давайте разберемся, почему виртуальные таблицы платформы «1С» так избирательно реагируют на нетиповой документ, несмотря на то, что движения по регистру накопления РабочееВремяСотрудников у обоих документов абсолютно идентичны.
В ЗУП 2.5 реализован гибридный метод получения данных о рабочем времени. Платформа 1С определяет источник данных для виртуальной таблицы ДанныеГрафика динамически:
РабочееВремяСотрудников (или в регистре сведений ГрафикиРаботыПоВидамВремени) **нет вообще никаких записей**, то данные берутся напрямую из общего графика работы сотрудника.В чем кроется ловушка: когда вы проводите нетиповой табель с 1 по 15 число, вы регистрируете факт ввода времени в систему. Платформа «видит» наличие записей в регистре накопления и полностью переключает расчет на получение данных из табеля. Но поскольку табеля на вторую половину месяца еще нет, данные за период с 16 по 31 число в регистре отсутствуют. В результате виртуальная таблица возвращает пустые значения для второй половины месяца.
Почему же тогда при использовании типового табеля за первую половину месяца все работает корректно? Ответ кроется в дополнительных механизмах проведения типового документа и его регистрации в метаданных.
Для того чтобы механизмы вытеснения, связи периодов действия и фактического периода действия работали корректно, документ, влияющий на время, должен быть зарегистрирован в метаданных как регистратор для соответствующего регистра расчета.
Проанализируем этот момент подробнее. Даже если ваш нетиповой табель делает движения только по вспомогательным регистрам накопления или сведений (например, РабочееВремяСотрудников), платформа должна знать о его существовании в контексте регистра расчета ОсновныеНачисленияОрганизаций.
Если нетиповой документ отсутствует в списке регистраторов регистра расчета, то при формировании фактического периода действия (ФПД) платформа не может правильно сопоставить период действия и период регистрации этого документа с расчетными записями. Это приводит к рассинхронизации данных в виртуальных таблицах.
Важно проверить структуру движений, которые делает ваш нетиповой документ. Типовой табель при проведении за первую половину месяца четко ограничивает свои движения периодом с 1 по 15 число. При этом:
ПериодРегистрации должно быть установлено строго на первый день месяца (например, 01.07.2019).Если ваш нетиповой документ при формировании движений неявно записывает пустые строки (строки с нулевым временем) на оставшуюся часть месяца или некорректно заполняет реквизит ПериодРегистрации, система посчитает, что весь месяц уже полностью перекрыт табелем (но с нулевыми показателями). Это заблокирует получение данных из общего графика работы.
При расчете начислений в ЗУП 2.5 вызывается специализированный программный слой (общий модуль ПроцедурыУправленияРасчетами), в частности процедура ПроверитьИОбновитьДанныеОВремени.
Этот механизм анализирует состав документов, зарегистрированных в информационной базе за расчетный период. Если он находит «ручной» ввод времени (табель), он может динамически подменять или дополнять таблицы графиков. Но этот код жестко завязан на типы документов. Нетиповой документ просто не обрабатывается этими процедурами, из-за чего система «не понимает», как правильно совместить график и ваш кастомный документ.
Для того чтобы подружить нетиповой табель за половину месяца с механизмом расчета отпусков и отклонений, необходимо выполнить следующие действия.
Прежде всего, убедимся, что платформа видит наш документ как полноправного участника расчета времени:
ОсновныеНачисленияОрганизаций) и убедитесь, что ваш документ отмечен как Регистратор для этого регистра.ГрафикиРаботыПоВидамВремени.Проанализируем модуль проведения нетипового документа. Нам нужно убедиться, что он не пишет «лишних» данных во вторую половину месяца. Набор записей регистра накопления РабочееВремяСотрудников должен формироваться строго по 15 число включительно.
Пример корректного заполнения движений при проведении документа за первую половину месяца:
// Очищаем существующие движения по регистру
Движения.РабочееВремяСотрудников.Записывать = Истина;
Движения.РабочееВремяСотрудников.Очистить();
Для Каждого СтрокаВремени Из ТаблицаВремениСотрудников Цикл
// Проверяем, что дата записи не выходит за рамки первой половины месяца
Если СтрокаВремени.Дата >= НачалоМесяца(ПериодРегистрации) И СтрокаВремени.Дата <= КонецПериодаПервойПоловины Тогда
Движение = Движения.РабочееВремяСотрудников.Добавить();
Движение.Период = СтрокаВремени.Дата;
Движение.Сотрудник = СтрокаВремени.Сотрудник;
Движение.ВидИспользованияРабочегоВремени = СтрокаВремени.ВидВремени;
Движение.ЯвкаВЧасах = СтрокаВремени.Часы;
// Важно: ПериодРегистрации должен указывать на начало расчетного месяца!
Движение.ПериодРегистрации = НачалоМесяца(ПериодРегистрации);
КонецЕсли;
КонецЦикла;
Поскольку расчетные механизмы ЗУП 2.5 ориентируются на конкретные типы документов, нам необходимо найти места в общем модуле ПроцедурыУправленияРасчетами, где анализируется использование табелей.
Выполните глобальный поиск по конфигурации по ключевому слову ТабельУчетаРабочегоВремени. Вы найдете функции, определяющие, введен ли табель по сотруднику за указанный период регистрации.
Рассмотрим пример доработки одной из таких функций:
Функция СотрудникИмеетВведенныйТабель(Сотрудник, ПериодРегистрации) Экспорт
// Типовой запрос проверки наличия проведенного табеля
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| Ссылка
|ИЗ
| Документ.ТабельУчетаРабочегоВремени КАК Табель
|ГДЕ
| Табель.Проведен = ИСТИНА
| И Табель.ПериодРегистрации = &ПериодРегистрации
| И Табель.Сотрудники.Сотрудник = &Сотрудник";
// НАЧАЛО ДОРАБОТКИ: Добавляем проверку нашего нетипового табеля
Запрос.Текст = Запрос.Текст +
" ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ
| Ссылка
|ИЗ
| Документ.НетиповойТабельУчетаВремени КАК НетиповойТабель
|ГДЕ
| НетиповойТабель.Проведен = ИСТИНА
| И НетиповойТабель.ПериодРегистрации = &ПериодРегистрации
| И НетиповойТабель.Сотрудники.Сотрудник = &Сотрудник";
// КОНЕЦ ДОРАБОТКИ
Запрос.УстановитьПараметр("Сотрудник", Сотрудник);
Запрос.УстановитьПараметр("ПериодРегистрации", НачалоМесяца(ПериодРегистрации));
Возврат НЕ Запрос.Выполнить().Пустой();
КонецФункции
Добавление вашего документа во все подобные проверки позволит системе корректно идентифицировать ваш документ как полноценный аналог типового табеля, и механизмы расчета времени начнут обрабатывать его соответствующим образом.
Для исправления работы виртуальных таблиц при расчете второй половины месяца выполните следующие проверки:
ОсновныеНачисленияОрганизаций.РабочееВремяСотрудников.ТабельУчетаРабочегоВремени).Такой комплексный подход позволит полностью восстановить работоспособность виртуальных таблиц ДанныеГрафика и ФактическийПериодДействия, обеспечив точный и корректный расчет отпусков и других начислений для ваших сотрудников.