При разработке внешних печатных форм (ВПФ) для документов Кадровый перевод и Кадровый перевод списком программисты часто сталкиваются с ситуацией, когда основные начисления (оклад, тарифная ставка) выводятся корректно, а дополнительные надбавки, такие как надбавка за вредность, ведут себя нестабильно: то появляются, то исчезают. Особенно остро эта проблема проявляется, если по одному сотруднику введено несколько кадровых документов за короткий период.
В этой статье мы подробно разберем, почему возникают такие ошибки, проанализируем представленный код и предложим надежные варианты решения задачи.
Давайте проанализируем фрагмент запроса, который используется для одиночного документа КадровыйПеревод. Проблема часто скрыта в секции ГДЕ вложенного запроса по табличной части начислений. Рассмотрим типичную ошибку:
| ГДЕ
| КадровыйПереводНачисления.Ссылка = &Ссылка
| И (КадровыйПереводНачисления.Начисление.Наименование ПОДОБНО ""%клад%""
| ИЛИ КадровыйПереводНачисления.Начисление.Наименование ПОДОБНО ""%плата по часовому тарифу%""
| ИЛИ КадровыйПереводНачисления.Начисление.Наименование ПОДОБНО ""%сложность%"")
В данном условии мы видим явное ограничение. Система выбирает только те строки из документа, где в названии начисления встречаются слова "оклад", "плата по часовому тарифу" или "сложность". Надбавка за вредность по определению не проходит этот фильтр. Следовательно, она никогда не попадет в выборку этого блока кода, даже если она физически присутствует в документе КадровыйПеревод.
Рекомендация: Для исправления этой ситуации необходимо либо расширить список условий ПОДОБНО, либо (что гораздо правильнее) полностью отказаться от фильтрации по наименованию внутри запроса. Лучше получить все начисления документа, а затем в цикле обхода выборки распределить их по нужным параметрам макета.
Вторая критическая ошибка заключается в получении данных через виртуальную таблицу СрезПоследних регистра сведений ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников. Рассмотрим этот фрагмент кода:
| ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
| ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник КАК Сотрудник,
| ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Значение КАК Значение
| ИЗ
| РегистрСведений.ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.СрезПоследних(&Дата, ) КАК ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних
| ГДЕ
| ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Показатель.Наименование ПОДОБНО ""%Вредность%"") КАК РК
Здесь кроются сразу две проблемы:
СсылкаНаОбъект.Дата (дата самого документа), то СрезПоследних вернет данные на начало этой секунды. Если кадровый перевод вступает в силу позже или в этот же день было несколько движений, результат может быть непредсказуемым. Данные "то появляются, то исчезают" именно из-за того, что время документа и время записи в регистре могут не совпадать нужным образом.ПОДОБНО по строковому представлению — это плохая практика. Если пользователь переименует начисление в "Доплата за условия труда", отчет перестанет работать.Рекомендация: Чтобы получить данные именно из документа, следует обращаться к его табличным частям. Если же нужно получить плановое значение, которое действует после этого перевода, нужно использовать дату начала перевода (поле ДатаНачала) с добавлением одной секунды или использовать специализированные механизмы БСП.
Выясним причину нестабильности: данные в ЗУП 3.1 могут храниться как в самом документе (вкладка "Начисления"), так и в регистрах плановых начислений. Если в Кадровом переводе стоит галочка Изменить начисления, данные нужно брать напрямую из документа. Проанализируем, как правильно изменить логику обхода:
// В запросе убираем фильтры по наименованию
Выборка = Запрос.Выполнить().Выбрать();
Оклад = 0;
Вредность = 0;
Пока Выборка.Следующий() Цикл
// Используем поиск в строке для распределения сумм
НаименованиеНачисления = ВРег(Выборка.НачислениеНаименование);
Если Найти(НаименованиеНачисления, "ОКЛАД") > 0 Тогда
Оклад = Выборка.Размер;
ИначеЕсли Найти(НаименованиеНачисления, "ВРЕДНОСТЬ") > 0 Тогда
Вредность = Выборка.Размер;
КонецЕсли;
// Заполнение параметров макета
ОбластьМакета.Параметры.Оклад = Оклад;
ОбластьМакета.Параметры.Вредность = Вредность;
КонецЦикла;
Для конфигурации 1С:Зарплата и управление персоналом 3.1 самым надежным способом является использование встроенных функций. Вместо написания сложных запросов к регистрам СрезПоследних, мы можем обратиться к типовому механизму. Рассмотрим пример использования функции из модуля УчетНачисленийЗарплаты.
Это позволит получить актуальные начисления сотрудника на любую дату, учитывая все цепочки кадровых переводов. Пример логики:
ДатаНачала перевода).ПлановыеНачисленияСотрудников.Важный нюанс: Надбавка за вредность часто зависит от показателя ПроцентНадбавкиЗаВредность. В коде ВПФ стоит искать не только само начисление, но и значение этого показателя в табличной части Показатели документа кадрового перевода.
Проанализировав ситуацию, можно составить чеклист для исправления внешней печатной формы:
Начисления нет жестких фильтров ГДЕ, которые отсекают "лишние" по мнению автора строки.КадровыйПереводСписком и КадровыйПеревод различается. Приведите их к единому стандарту — соберите ссылки в массив и используйте один универсальный запрос.Начисления и Показатели. Если нужны данные на дату, используйте программный интерфейс ЗУП, а не прямые запросы к регистрам сведений, так как типовые механизмы учитывают время, исправления и приоритеты документов."Вредность", старайтесь находить ссылку на показатель через Справочники.ПоказателиРасчетаЗарплаты.НайтиПоНаименованию(...) или по его идентификатору.Соблюдение этих правил гарантирует, что ваша печатная форма будет работать корректно даже при наличии нескольких кадровых изменений в один день.