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