В конфигурации 1С:Зарплата и управление персоналом 3.1 разработчики часто сталкиваются с задачей получения не просто итоговой суммы расчетной базы начисления (например, премии), а её детальной расшифровки. Программа должна «понимать», из каких именно сумм (Оклад, Надбавки, Доплаты) сложилась эта база. Ситуация осложняется тем, что ЗУП 3.1 в документах и регистрах часто хранит только финальный результат, а детальный состав базы вычисляется «на лету» в момент расчета документа.
Рассмотрим несколько эффективных способов решения этой задачи: от использования типового Менеджера расчета до прямых запросов к виртуальным таблицам регистров расчета.
Этот метод считается наиболее надежным и «чистым» с точки зрения методологии 1С, так как он использует те же алгоритмы, которые применяет сама система при нажатии кнопки «Рассчитать» в документе. Суть метода заключается в том, чтобы программно инициализировать объект МенеджерРасчета, загрузить в него данные сотрудника и выполнить расчет. Чтобы не изменять данные в базе, все операции проводятся внутри транзакции, которая в конце отменяется.
Разберем по шагам реализацию этого подхода:
РасчетЗарплатыРасширенный.СоздатьМенеджерРасчета.РассчитатьЗарплату.МенеджерРасчета.Зарплата.Начисления.Проанализируем пример кода для реализации этого метода:
УстановитьПривилегированныйРежим(Истина);
НачатьТранзакцию();
// Инициализируем менеджер расчета по организации и периоду
МенеджерРасчета = РасчетЗарплатыРасширенный.СоздатьМенеджерРасчета(Объект.ПериодРегистрации, Объект.Организация);
МенеджерРасчета.НастройкиРасчета.РассчитыватьНачисления = Истина;
МенеджерРасчета.ИсключаемыйРегистратор = Объект.Ссылка;
СотрудникиДляНачислений = МенеджерРасчета.ТаблицаСотрудников;
СотрудникиДляРассчета = Новый Массив;
// Заполняем список сотрудников (например, из выборки или документа)
Пока ВыборкаСотрудник.Следующий() Цикл
СотрудникиДляРассчета.Добавить(ВыборкаСотрудник.Сотрудник);
НоваяСтрока = СотрудникиДляНачислений.Добавить();
НоваяСтрока.Сотрудник = ВыборкаСотрудник.Сотрудник;
НоваяСтрока.ДатаНачала = Объект.ПериодРегистрации;
НоваяСтрока.ДатаОкончания = КонецМесяца(Объект.ПериодРегистрации);
КонецЦикла;
МенеджерРасчета.НастройкиРасчета.Сотрудники = СотрудникиДляРассчета;
ОтборМенеджераРасчета = МенеджерРасчета.СоздатьОтборы();
// При необходимости устанавливаем отбор по подразделению
ОтборМенеджераРасчета.Подразделение = Объект.Подразделение;
// Заполняем данные и рассчитываем
МенеджерРасчета.ЗаполнитьНачислениеЗарплаты(СотрудникиДляНачислений, ОтборМенеджераРасчета);
МенеджерРасчета.РассчитатьЗарплату();
// Здесь мы получаем доступ к рассчитанным данным, включая показатели базы
ТаблицаРезультатов = МенеджерРасчета.Зарплата.Начисления;
ОтменитьТранзакцию();
УстановитьПривилегированныйРежим(Ложь);
Важный нюанс: при таком подходе вы получите значение показателя РасчетнаяБаза. Чтобы увидеть, из чего она состоит в разрезе начислений, необходимо анализировать промежуточные таблицы менеджера, такие как ДанныеДляРасчета, где хранятся связи между начислениями и их базовыми записями.
Если данные уже записаны в регистр расчета Начисления, мы можем воспользоваться механизмом платформы для получения базы. Для этого используется виртуальная таблица РегистрРасчета.Начисления.БазаОсновныеНачисления.
Посмотрим на пример запроса, который позволяет определить, какие начисления входят в базу конкретного вида расчета (например, нашей премии):
ВЫБРАТЬ
НачисленияБазовыеВидыРасчета.ВидРасчета КАК БазовыйВидРасчета
ПОМЕСТИТЬ ВТ_БазовыеВиды
ИЗ
ПланВидовРасчета.Начисления.БазовыеВидыРасчета КАК НачисленияБазовыеВидыРасчета
ГДЕ
НачисленияБазовыеВидыРасчета.Ссылка = &ВидРасчетаПремия;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
НачисленияБаза.ВидРасчета КАК ВидРасчета,
НачисленияБаза.НомерСтроки КАК НомерСтроки,
НачисленияБаза.РезультатБаза КАК СуммаВходящаяВБазу,
НачисленияБаза.Сотрудник КАК Сотрудник
ИЗ
РегистрРасчета.Начисления.БазаОсновныеНачисления(
&ИзмеренияОсновногоРегистра,
&ИзмеренияБазовогоРегистра,
&Разрезы,
ВидРасчета = &ВидРасчетаПремия И Регистратор = &Регистратор
) КАК НачисленияБаза
При использовании этого метода важно правильно настроить параметры виртуальной таблицы:
Сотрудник, Организация).Преимущество: Это работает быстро и не требует эмуляции расчета. Недостаток: Если после расчета премии базовые начисления (например, оклад) были изменены или пересчитаны без пересчета самой премии, виртуальная таблица может вернуть актуальные (измененные) данные, которые не будут соответствовать сумме, фактически зафиксированной в премии.
Часто задача получения базы премии связана с расчетом среднего заработка (как упоминал автор темы в сообщении 53). В ЗУП 3.1 существует регистр сведений ДанныеОНачисленияхДляРасчетаСреднегоЗаработкаОбщий. Хотя он хранит уже «пропорциональные» суммы, в нем можно отследить связь начислений с конкретным периодом и регистратором.
Если же стоит задача изменить логику вхождения премии в средний заработок в зависимости от наличия командировок, рассмотрите возможность использования показателей. Как предложено в сообщении 56, можно создать технический показатель Командировка, который будет принимать значение 1 или 0, и использовать его прямо в формуле премии:
Оклад + ?(Командировка = 0, Надбавка, Надбавка * ДоляОтработки)
Выбирая метод, проанализируйте следующие факторы:
Важный совет: В ЗУП 3.1 активно используется кэширование и временные таблицы в памяти при расчете. Если вы пишете расширение для изменения логики расчета, старайтесь внедряться в процедуры модуля РасчетЗарплатыРасширенный, где таблицы с базой уже подготовлены системой и доступны для анализа без дополнительных запросов к базе данных.