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