Почему в печатной форме документа Работа в выходные и праздничные дни в ЗУП 3.1 не отображаются дополнительные реквизиты для всех дат?

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом
← На главную

При разработке расширений для конфигурации Зарплата и управление персоналом, редакция 3.1 (ЗУП) программисты часто сталкиваются с нестандартным поведением документа РаботаВВыходныеИПраздничныеДни. Одной из наиболее распространенных задач является добавление в табличную часть Сотрудники дополнительных реквизитов, таких как «Причина работы» или «ФИО замещаемого», и вывод их в печатную форму служебной записки. Однако при попытке формирования запроса выясняется, что данные отображаются некорректно: информация выводится только для одной (как правило, последней) даты работы сотрудника.

В этой статье мы подробно разберем, почему так происходит, изучим внутреннюю архитектуру хранения данных в ЗУП и рассмотрим эффективные способы решения этой проблемы через оптимизацию запросов и механизмов записи данных.

Анализ архитектуры хранения данных в документе

Для начала проанализируем ситуацию: в интерфейсе программы документ Работа в выходные и праздничные дни выглядит обманчиво просто. В табличной части мы видим одну строку для каждого сотрудника, а даты работы представлены в виде колонок или отдельного списка. Однако на уровне базы данных 1С хранит информацию иначе.

Ключевая особенность: в табличной части Сотрудники этого документа для каждого сочетания «Сотрудник + Дата» создается отдельная физическая запись. Если сотрудник Иванов работает 1, 2 и 3 числа, в базе будет создано три строки. Когда вы добавляете через расширение новый реквизит в эту табличную часть, стандартный механизм платформы при заполнении на форме может записать значение только в одну из этих строк (например, в ту, которая соответствует первой выбранной дате), оставляя остальные строки пустыми.

Рассмотрим ситуацию, когда мы пытаемся получить данные простым запросом к табличной части. Мы увидим, что реквизиты НЛЭ_ПричиныОбоснования и НЛЭ_ФИОЗамещаемого заполнены только в одной строке из нескольких, относящихся к одному и тому же сотруднику. Именно это приводит к тому, что в печатной форме «пустоты» вытесняют нужные значения.

Решение проблемы через группировку в запросе

Если данные в базе уже «размазаны» по строкам (то есть причина заполнена только в одной строке для сотрудника), нам необходимо собрать их воедино при формировании выборки для печати. Для этого мы будем использовать агрегатные функции в языке запросов 1С.

Разберем по шагам, как модифицировать типовой запрос. Вместо прямого обращения к полям, применим функцию МАКСИМУМ к нашим дополнительным реквизитам. Это позволит «подтянуть» заполненное значение во все строки сотрудника в рамках текущего документа.

Пример формирования временной таблицы с данными документа:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    Сотрудники.Ссылка КАК Ссылка,
    Сотрудники.Сотрудник КАК Сотрудник,
    Сотрудники.Дата КАК Дата,
    // Используем МАКСИМУМ, чтобы получить заполненное значение из любой строки сотрудника
    МАКСИМУМ(Сотрудники.НЛЭ_ПричиныОбоснования) КАК Причина,
    МАКСИМУМ(Сотрудники.НЛЭ_ФИОЗамещаемого) КАК Замещаемый,
    Сотрудники.Ссылка.Дата КАК Период
ПОМЕСТИТЬ ВТДанныеДокументов
ИЗ
    Документ.РаботаВВыходныеИПраздничныеДни.Сотрудники КАК Сотрудники
ГДЕ
    Сотрудники.Ссылка В(&МассивОбъектов)
    И (Сотрудники.ОтработаноЧасов > 0 ИЛИ НЕ Сотрудники.НеРаботал)
СГРУППИРОВАТЬ ПО
    Сотрудники.Ссылка,
    Сотрудники.Сотрудник,
    Сотрудники.Дата,
    Сотрудники.Ссылка.Дата

Обратите внимание: использование СГРУППИРОВАТЬ ПО здесь критически важно. Мы группируем по сотруднику и дате, но за счет агрегатной функции получаем значение причины, даже если оно физически записано в другой строке того же сотрудника (если логика заполнения была реализована так, что значение дублируется или пишется хотя бы в одну строку).

Работа с кадровыми данными сотрудников

В ЗУП 3.1 получение должностей и ФИО напрямую из справочников считается плохим тоном, так как должность может меняться во времени. Проанализируем использование программного интерфейса (API) кадрового учета. Мы должны использовать метод КадровыйУчет.СоздатьВТКадровыеДанныеСотрудников.

При соединении основной таблицы данных с временной таблицей кадровых данных важно правильно указать условия связи. Одной связи по Сотруднику недостаточно — необходимо связываться и по полю Период, чтобы получить актуальные данные на дату документа или дату работы.


// Вторая часть запроса после формирования ВТКадровыеДанныеСотрудников
ВЫБРАТЬ РАЗРЕШЕННЫЕ
    ДанныеДокументов.Ссылка КАК Ссылка,
    ДанныеДокументов.Дата КАК Дата,
    ДанныеДокументов.Сотрудник КАК Сотрудник,
    ДанныеДокументов.Причина КАК Причина,
    ДанныеДокументов.Замещаемый КАК Замещаемый,
    КадровыеДанныеСотрудников.Должность.Наименование КАК Должность,
    КадровыеДанныеСотрудников.ФамилияИО КАК ФамилияИО
ИЗ
    ВТДанныеДокументов КАК ДанныеДокументов
        ЛЕВОЕ СОЕДИНЕНИЕ ВТКадровыеДанныеСотрудников КАК КадровыеДанныеСотрудников
        ПО ДанныеДокументов.Сотрудник = КадровыеДанныеСотрудников.Сотрудник
            И ДанныеДокументов.Период = КадровыеДанныеСотрудников.Период
УПОРЯДОЧИТЬ ПО
    Ссылка,
    Дата
ИТОГИ ПО
    Ссылка,
    Дата

Обеспечение целостности данных при записи (Метод «Дублирования»)

Чтобы не полагаться только на сложные запросы с группировками, рекомендуется внедрить логику «размножения» данных при записи документа. Рассмотрим, как это сделать в расширении. Нам необходимо перехватить событие ПередЗаписьюНаСервере в модуле формы документа или ПередЗаписью в модуле объекта.

Суть метода: мы обходим табличную часть и, если находим заполненную причину у сотрудника, проставляем её во все остальные строки этого же сотрудника в этом документе. Это сделает данные избыточными, но крайне удобными для чтения любым стандартным отчетом или печатной формой.

Важный нюанс: при работе в расширении вы можете столкнуться с ошибкой Поле объекта не обнаружено при попытке обращения к типовым реквизитам, таким как ОтработаноЧасов. Выясним причину: это происходит, если реквизит не был добавлен в расширение или если вы пытаетесь обратиться к нему через элементы формы, которые динамически меняются. Всегда проверяйте, что реквизиты табличной части добавлены в ваше расширение с сохранением их типов и имен.

Почему не стоит использовать ВЫРАЗИТЬ в условиях?

В исходных сообщениях темы упоминалось использование конструкции ВЫРАЗИТЬ(Сотрудники.Ссылка КАК Документ.РаботаВВыходныеИПраздничныеДни). Проанализируем этот момент. В языке запросов 1С обращение через точку от типизированной ссылки (например, Сотрудники.Ссылка.Дата) автоматически выполняет неявное соединение таблиц. Использование ВЫРАЗИТЬ избыточно и только загромождает код, если поле Ссылка уже имеет тип нужного документа. Кроме того, будьте осторожны с проверкой логических условий: поле ВремяВЧасах в ЗУП может быть как флагом (булево), так и числовым значением в зависимости от контекста, поэтому условия вида И НЕ Сотрудники.НеРаботал следует проверять на соответствие типам метаданных.

Подведем итог: для корректного вывода данных в печатную форму в ЗУП 3.1 необходимо учитывать «развертку» строк в базе данных. Оптимальным решением будет сочетание правильной группировки в запросе (с использованием МАКСИМУМ для строковых полей) и программного заполнения всех строк табличной части при записи документа.

← На главную