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