При сопровождении систем на базе 1С:Зарплата и управление персоналом 8 (редакция 3.1) специалисты часто сталкиваются с неприятной ситуацией после обновления конфигурации до версии 3.1.23.165 и выше. Суть проблемы заключается в том, что при переносе данных из одной базы в другую (например, из ЗУП в ERP или наоборот) через механизм Конвертации данных 2.0, у новых сотрудников реквизит ГоловнойСотрудник заполняется значением «Объект не найден». Это влечет за собой целый «снежный ком» ошибок: сотрудники не отображаются в общем списке, некорректно заполняются регистры кадровой истории и данные для подбора.
В этой статье мы подробно разберем причины возникновения этой технической коллизии, проанализируем внутреннюю логику конфигурации и выработаем надежное решение для исправления правил обмена и восстановления уже поврежденных данных.
Для начала давайте проанализируем, как устроена логика справочника Сотрудники. Начиная с определенных релизов ветки 3.1.23, разработчики 1С ужесточили контроль целостности данных. В модуле объекта справочника Сотрудники, в процедуре ПередЗаписью, выполняется проверка: если создается новый сотрудник, который является основным (не внешним совместителем в определенных контекстах), его реквизит ГоловнойСотрудник должен содержать ссылку на него самого.
Рассмотрим, что происходит в момент программной загрузки через обмен данными:
ГоловнойСотрудник может остаться пустым или получить ссылку, которая еще не существует в базе.Записать() срабатывает обработчик ПередЗаписью. Система видит, что реквизит ГоловнойСотрудник не заполнен, и пытается программно его установить. Однако, если ссылка еще не была сгенерирована методом УстановитьСсылкуНового(), возникает конфликт, и в базу записывается некорректный идентификатор.Это приводит к тому, что в регистре сведений ДанныеДляПодбораСотрудников не устанавливается флаг ЭтоОсновнойСотрудник. Поскольку динамические списки в ЗУП 3.1 строятся именно по этому регистру (для оптимизации скорости), сотрудник физически в базе есть, но в списке его не видно.
Чтобы решить проблему системно, нам необходимо внести изменения в Правила Конвертации Объектов (ПКО) для справочника Сотрудники. Основная задача — гарантировать, что ссылка на новый объект будет создана до того, как система попытается записать объект в базу данных.
Рассмотрим по шагам, как настроить обработчик в Конвертации Данных 2.0:
Сотрудники.ПередЗагрузкой (или ПриЗагрузке, в зависимости от архитектуры ваших правил).Пример программного кода для вставки в ПКО:
Если Объект.ЭтоНовый() Тогда
// Генерируем новую уникальную ссылку для объекта, который еще не записан
НоваяСсылка = Справочники.Сотрудники.ПолучитьСсылку();
// Устанавливаем эту ссылку будущему объекту
Объект.УстановитьСсылкуНового(НоваяСсылка);
// Заполняем реквизит ГоловнойСотрудник ссылкой на самого себя
Объект.ГоловнойСотрудник = НоваяСсылка;
// Также рекомендуется передать признак записи нового в ДополнительныеСвойства
Объект.ДополнительныеСвойства.Вставить("ЗаписьНовогоСотрудника", Истина);
КонецЕсли;
Разберем, что делает этот код. Метод ПолучитьСсылку() создает GUID, который система зарезервирует за этим объектом. Метод УстановитьСсылкуНового() сообщает платформе, что при физической записи в таблицу Ref.Сотрудники нужно использовать именно этот идентификатор. Таким образом, на момент записи реквизит ГоловнойСотрудник уже содержит валидную ссылку, и проверка в модуле объекта проходит успешно.
Проанализируем ситуацию, описанную в сообщениях форума, когда код в ПередЗаписью не срабатывает из-за того, что ДополнительныеСвойства приходят пустыми. Это часто случается при обмене через Планы обмена (синхронизация данных), когда объект загружается не как самостоятельная единица, а как зависимый объект по ссылке из документа (например, из документа ПриемНаРаботу).
В этом случае важно убедиться, что в правилах обмена (ПКО) установлены правильные настройки поиска. Если объект найден по уникальному идентификатору, он не считается новым, и логика ЭтоНовый() не сработает. Если же вы хотите гарантированно обновлять поле ГоловнойСотрудник даже для существующих объектов, где оно «битое», используйте обработчик ПослеЗагрузки:
Если Не ЗначениеЗаполнено(Объект.ГоловнойСотрудник)
ИЛИ Объект.ГоловнойСотрудник.Наименование ЕСТЬ NULL Тогда
// Если ссылка битая или пустая, восстанавливаем ее
Объект.ГоловнойСотрудник = Объект.Ссылка;
// Принудительно инициируем запись для обновления регистров
Объект.Записать();
КонецЕсли;
Если ошибка уже произошла и в вашей базе ERP или ЗУП уже создано множество сотрудников с «Объект не найден», не обязательно удалять их и загружать заново. Мы можем исправить их программно с помощью обработки «Групповое изменение реквизитов» или написав небольшой скрипт в консоли кода.
Рассмотрим алгоритм восстановления:
ГоловнойСотрудник не заполнен или является «битой» ссылкой.Пример кода для восстановления данных:
Выборка = Справочники.Сотрудники.Выбрать();
Пока Выборка.Следующий() Цикл
Объект = Выборка.ПолучитьОбъект();
// Проверяем на битую ссылку через получение представления или попытку обращения
БитаяСсылка = Ложь;
Попытка
Имя = Объект.ГоловнойСотрудник.Наименование;
Если Имя = Неопределено Тогда
БитаяСсылка = Истина;
КонецЕсли;
Исключение
БитаяСсылка = Истина;
КонецПопытки;
Если БитаяСсылка Или Объект.ГоловнойСотрудник.Пустая() Тогда
// Для большинства случаев устанавливаем ссылку на самого себя
Объект.ГоловнойСотрудник = Объект.Ссылка;
// Важно: обмен данными должен быть выключен, чтобы сработали подписки на события
Объект.ОбменДанными.Загрузка = Ложь;
Попытка
Объект.Записать();
Сообщить("Сотрудник исправлен: " + Объект.Наименование);
Исключение
Сообщить("Ошибка при записи: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецЦикла;
Важный момент: При записи объекта после исправления реквизита ГоловнойСотрудник, система автоматически инициирует обновление записей в регистрах сведений Данные для подбора сотрудников и Кадровая история сотрудников. Это вернет сотрудника в списки выбора и сделает его доступным для кадровых документов.
Проанализируем ситуацию с внешними и внутренними совместителями. Для них логика ГоловнойСотрудник = Ссылка будет ошибочной. В ЗУП 3.1 ГоловнойСотрудник — это поле, которое объединяет все карточки сотрудников одного физического лица в рамках одного предприятия. У одного ФизическогоЛица может быть несколько Сотрудников, но у всех них будет один и тот же ГоловнойСотрудник (как правило, это самая первая созданная карточка по основному месту работы).
При настройке обмена важно обеспечить следующий порядок:
Если вы загружаете совместителя, а его «головная» карточка еще не создана в базе-приемнике, реквизит снова станет «битым». Поэтому в правилах поиска (ПКО) для ГоловнойСотрудник рекомендуется использовать поиск по Физическому лицу и признаку ВидЗанятости (Основное место работы).
Подведем итоги нашего анализа. Проблема «Объект не найден» в ЗУП 3.1.23+ вызвана не багом обмена как такового, а изменением порядка проверки данных внутри самой конфигурации. Для успешного переноса сотрудников теперь недостаточно просто передать набор полей — необходимо явно управлять ссылкой нового объекта в памяти.
Использование метода УстановитьСсылкуНового() в обработчиках Конвертации данных является наиболее корректным и «чистым» способом решения задачи, так как он не нарушает транзакционную логику 1С и позволяет штатным механизмам конфигурации-приемника правильно обработать данные при первой же записи.