При работе в программе 1С:Зарплата и управление персоналом (редакция 3.1) пользователи периодически сталкиваются с неприятной ситуацией: при попытке вручную добавить сотрудника в табличную часть какого-либо документа (например, формы СЗВ-СТАЖ, ЕФС-1 или ведомости на выплату зарплаты) нужного человека просто нет в списке выбора. При этом, если воспользоваться кнопкой «Заполнить», программа успешно находит этого сотрудника, определяет его статус и без проблем добавляет в документ. Особо часто эта проблема затрагивает исполнителей, работающих по договорам гражданско-правового характера (ГПХ).
В этой статье мы подробно разберем, почему возникает этот сбой, проанализируем внутренние механизмы платформы 1С и рассмотрим два действенных метода решения проблемы: штатный сервисный (без программирования) и программный (для разработчиков).
Для оптимизации работы и ускорения отклика интерфейса в конфигурации 1С:ЗУП 3.1 списки сотрудников строятся не по «сырому» справочнику Сотрудники, а с использованием вспомогательных регистров сведений, играющих роль индексированных таблиц быстрого доступа. Ключевым среди них является регистр сведений ТекущиеКадровыеДанныеСотрудников.
Если мы проанализируем внутренний запрос платформы, который формирует динамический список выбора сотрудников (именно этот запрос отрабатывает в момент нажатия на поле выбора), то увидим следующую картину:
ВЫБРАТЬ
СправочникФизическиеЛица.Ссылка КАК Ссылка,
СправочникФизическиеЛица.ПометкаУдаления КАК ПометкаУдаления,
СправочникФизическиеЛица.Предопределенный КАК Предопределенный,
СправочникФизическиеЛица.Родитель КАК Родитель,
СправочникФизическиеЛица.ЭтоГруппа КАК ЭтоГруппа,
СправочникФизическиеЛица.Код КАК Код,
СправочникФизическиеЛица.Наименование КАК Наименование,
СправочникФизическиеЛица.ДатаРождения КАК ДатаРождения,
СправочникФизическиеЛица.ИНН КАК ИНН,
СправочникФизическиеЛица.СтраховойНомерПФР КАК СтраховойНомерПФР,
ТекущиеКадровыеДанныеСотрудников.Сотрудник.Код КАК ТабельныйНомер,
ТекущиеКадровыеДанныеСотрудников.ТекущаяОрганизация КАК Филиал,
ТекущиеКадровыеДанныеСотрудников.Сотрудник.ВАрхиве КАК ВАрхиве,
ТекущиеКадровыеДанныеСотрудников.ТекущееПодразделение КАК Подразделение,
ТекущиеКадровыеДанныеСотрудников.ДатаПриема КАК ДатаПриема,
ТекущиеКадровыеДанныеСотрудников.ДатаУвольнения КАК ДатаУвольнения,
ТекущиеКадровыеДанныеСотрудников.ГоловнаяОрганизация КАК Организация,
ТекущиеКадровыеДанныеСотрудников.ТекущийВидЗанятости КАК ВидЗанятости
ИЗ
РегистрСведений.ТекущиеКадровыеДанныеСотрудников КАК ТекущиеКадровыеДанныеСотрудников
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ФизическиеЛица КАК СправочникФизическиеЛица
ПО ТекущиеКадровыеДанныеСотрудников.ФизическоеЛицо = СправочникФизическиеЛица.Ссылка
И (ТекущиеКадровыеДанныеСотрудников.ОсновноеРабочееМестоВОрганизации)
Обратим особое внимание на конструкцию ВНУТРЕННЕЕ СОЕДИНЕНИЕ (INNER JOIN). Из правил работы баз данных следует, что при внутреннем соединении в итоговую выборку попадут только те физические лица, для которых существует соответствующая (и актуальная) запись в таблице регистра ТекущиеКадровыеДанныеСотрудников.
Если по какой-то причине запись для конкретного сотрудника ГПХ в этом регистре отсутствует или повреждена, внутреннее соединение полностью исключает его из результатов запроса. В итоге в интерфейсе программы мы видим пустой список или не находим в нем нужных людей.
Почему записи в регистре могут отсутствовать?
Перенос данных могут не зафиксировать все необходимые движения по регистрам кадровой истории.Перейдем к методам решения данной проблемы.
Разработчики фирмы 1С предусмотрели встроенные механизмы самодиагностики и восстановления вспомогательных регистров. Прежде чем приступать к написанию кода, рекомендуется выполнить процедуру принудительного перезаполнения таблиц подбора.
Выполним следующие шаги:
Данные для подбора сотрудников (техническое имя: ДанныеДляПодбораСотрудников). Также можно быстро перейти к нему, нажав комбинацию клавиш Shift+F11 и вставив навигационную ссылку: e1cib/list/РегистрСведений.ДанныеДляПодбораСотрудников.Текущие кадровые данные сотрудников (техническое имя: ТекущиеКадровыеДанныеСотрудников).Дополнительные локальные проверки:
Договор (работы, услуги) по «пропавшему» сотруднику и сделать его перепроведение. При записи и проведении документа конфигурация автоматически пытается актуализировать данные физического лица в связанных регистрах подбора.Если база данных имеет внушительный объем, процедура полного интерактивного перезаполнения регистра может выполняться слишком долго или приводить к блокировкам таблиц. В таком случае оптимальным решением станет точечная запись недостающих данных программным путем.
Напишем внешнюю обработку или воспользуемся групповой обработкой данных для выполнения следующего алгоритма. Мы найдем всех сотрудников, по которым есть кадровые данные или договоры, но отсутствуют записи в регистре ТекущиеКадровыеДанныеСотрудников, и принудительно добавим их.
Рассмотрим код процедуры заполнения:
// Создаем запрос для поиска расхождений между справочником сотрудников и регистром кадровых данных
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Сотрудники.Ссылка КАК Сотрудник,
| Сотрудники.ФизическоеЛицо КАК ФизическоеЛицо,
| ТекущиеКадровыеДанныеСотрудников.ФизическоеЛицо КАК РегФизическоеЛицо,
| Сотрудники.ГоловнаяОрганизация КАК ГоловнаяОрганизация
|ИЗ
| Справочник.Сотрудники КАК Сотрудники
| ПОЛНОЕ СОЕДИНЕНИЕ РегистрСведений.ТекущиеКадровыеДанныеСотрудников КАК ТекущиеКадровыеДанныеСотрудников
| ПО (ТекущиеКадровыеДанныеСотрудников.ФизическоеЛицо = Сотрудники.ФизическоеЛицо)
|ГДЕ
| ТекущиеКадровыеДанныеСотрудников.ФизическоеЛицо ЕСТЬ NULL
| И НЕ Сотрудники.ПометкаУдаления";
// Инициализируем менеджер записи для регистра сведений
НаборЗаписей = РегистрыСведений.ТекущиеКадровыеДанныеСотрудников.СоздатьНаборЗаписей();
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Выведем лог для контроля процесса в окно сообщений
Сообщить("Восстановление записи для: " + Выборка.ФизическоеЛицо + " (Сотрудник: " + Выборка.Сотрудник + ")");
// Создаем новую строку в наборе записей
НоваяЗапись = НаборЗаписей.Добавить();
// Заполняем реквизиты и измерения на основе выборки запроса
ЗаполнитьЗначенияСвойств(НоваяЗапись, Выборка);
// Дополнительно укажем признак основного рабочего места, чтобы сработало внутреннее соединение
НоваяЗапись.ОсновноеРабочееМестоВОрганизации = Истина;
КонецЦикла;
// Записываем набор данных в базу.
// Параметр "Ложь" указывает системе, что мы производим запись в режиме добавления,
// без предварительного замещения всего содержимого регистра.
Если НаборЗаписей.Количество() > 0 Тогда
НаборЗаписей.Записать(Ложь);
Сообщить("Регистр успешно актуализирован. Проверьте списки выбора сотрудников.");
Иначе
Сообщить("Расхождений не обнаружено. Все записи регистра в актуальном состоянии.");
КонецЕсли;
Важное техническое примечание к коду: Метод НаборЗаписей.Записать(Ложь) используется для дозаписи новых строк в независимый регистр сведений без очистки существующих записей. Перед запуском данного кода на рабочей базе настоятельно рекомендуется сделать резервную копию (архив выгрузки .dt) во избежание дублирования ключевых записей или нарушения ссылочной целостности.
После выполнения данного скрипта или проведения процедуры переиндексации все "пропавшие" сотрудники ГПХ мгновенно станут доступными для ручного выбора в СЗВ-СТАЖ, ЕФС-1 и любых других отчетных формах 1С:ЗУП 3.1.