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