В процессе сопровождения конфигурации 1С:Зарплата и управление персоналом 3.1 часто возникает необходимость автоматизировать рутинные операции, такие как наведение порядка в справочнике Сотрудники. Одной из типичных задач является массовая установка флага В архиве для тех сотрудников (подработчиков), у которых срок подработки уже истек. Это позволяет разгрузить списки выбора и отчеты от неактуальных записей.
В данной статье мы подробно разберем, как написать эффективную обработку для решения этой задачи, проанализируем типичные ошибки начинающих разработчиков и рассмотрим способы оптимизации кода для работы с большими базами данных.
Рассмотрим ситуацию: нам необходимо выбрать всех сотрудников из документов НазначениеПодработки, у которых ДатаОкончания меньше определенного порога и не является пустой. При этом важно корректно спозиционироваться на объекте справочника, чтобы внести изменения.
Проанализируем базовый алгоритм, который поможет нам извлечь нужные данные. Нам потребуется использовать объект Запрос для эффективной выборки ссылок на сотрудников. Важно понимать, что в 1С:ЗУП один и тот же человек (физическое лицо) может иметь несколько записей в справочнике Сотрудники. Установка флага архивации должна происходить точечно — именно для той карточки, которая относится к завершенной подработке.
Первое, на что стоит обратить внимание, — это эффективность выборки. Использование конструкции ВЫБРАТЬ РАЗЛИЧНЫЕ в запросе позволяет избежать многократной обработки одного и того же сотрудника, если на него было оформлено несколько документов НазначениеПодработки. Также крайне важно добавить условие, исключающее тех сотрудников, которые уже находятся в архиве. Это значительно сократит количество операций записи в базу данных.
Давайте составим правильный текст запроса, учитывая рекомендации экспертов:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| НазначениеПодработки.СовмещающийСотрудник КАК Сотрудник
|ИЗ
| Документ.НазначениеПодработки КАК НазначениеПодработки
|ГДЕ
| НазначениеПодработки.ДатаОкончания < &ДатаКонца
| И НазначениеПодработки.ДатаОкончания <> ДАТАВРЕМЯ(1, 1, 1)
| И НЕ НазначениеПодработки.СовмещающийСотрудник.ВАрхиве";
Запрос.УстановитьПараметр("ДатаКонца", Объект.ДатаВерхнегоПредела);
РезультатЗапроса = Запрос.Выполнить();
В этом запросе мы используем обращение через точку к реквизиту ВАрхиве прямо в условии ГДЕ. Это стандартный механизм платформы 1С, который позволяет фильтровать данные по реквизитам связанных объектов без использования соединений вручную.
После того как мы получили список сотрудников, нуждающихся в архивации, необходимо выполнить обход результата запроса. Для изменения данных в 1С всегда используется метод ПолучитьОбъект(). Однако стоит помнить, что эта операция ресурсоемкая.
Разберем по шагам процесс изменения реквизита:
Истина для реквизита ВАрхиве.Записать().Посмотрим на пример реализации цикла обработки:
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Получаем объект для изменения
ОбъектСотрудник = Выборка.Сотрудник.ПолучитьОбъект();
Если ОбъектСотрудник <> Неопределено Тогда
// Устанавливаем флаг архивации
ОбъектСотрудник.ВАрхиве = Истина;
// Отключаем лишние проверки для ускорения (если это допустимо)
ОбъектСотрудник.ОбменДанными.Загрузка = Истина;
Попытка
ОбъектСотрудник.Записать();
Исключение
ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Не удалось записать сотрудника: " + Выборка.Сотрудник);
КонецПопытки;
КонецЕсли;
КонецЦикла;
Рассмотрим подробнее несколько критически важных моментов, которые часто упускают при разработке подобных обработок:
1. Уникальность идентификации. В 1С поиск по коду (табельному номеру) или наименованию является ненадежным, так как они могут дублироваться (например, у основного сотрудника и его подработки). Всегда работайте со ссылками (тип СправочникСсылка.Сотрудники). Ссылка уникальна в пределах всей базы данных и гарантирует, что вы измените именно ту карточку, которая указана в документе.
2. Использование режима "Загрузка". Свойство ОбменДанными.Загрузка = Истина позволяет обойти большинство прикладных проверок в модуле объекта и подписки на события. Это существенно ускоряет работу обработки, но использовать этот метод нужно осторожно, чтобы не нарушить логическую целостность данных.
3. Работа с транзакциями. Если список сотрудников велик (тысячи записей), выполнение каждой записи в отдельной транзакции (что происходит по умолчанию) может занять много времени. В таких случаях мы рекомендуем оборачивать весь цикл или его части в явную транзакцию с помощью методов НачатьТранзакцию() и ЗафиксироватьТранзакцию(). Это ускоряет процесс в несколько раз за счет оптимизации записи на уровне СУБД.
4. Обработка пустых дат. Проверка на пустую дату в запросе (<> ДАТАВРЕМЯ(1, 1, 1)) обязательна. Если подработка бессрочная, дата окончания может быть не заполнена, и такая запись не должна попадать в архив преждевременно.
Проанализируем ситуацию, когда писать код необязательно. В типовых конфигурациях существует мощный инструмент Групповое изменение реквизитов (в разделе Администрирование — Обслуживание).
Многие ошибочно полагают, что эта обработка не подходит для сложных условий. Однако, используя механизм отборов "через точку", можно построить весьма сложные фильтры. Например, выбрав объект Сотрудники, вы можете добавить условие на связанные документы, если в конфигурации настроены соответствующие критерии отбора или связи. Тем не менее, для специфической логики ЗУП (где нужно анализировать именно дату окончания в конкретном виде документа Назначение подработки), программный метод, описанный выше, остается наиболее гибким и точным.
Выясним причину, по которой автор темы на форуме столкнулся с проблемой: он редактировал одну версию обработки, а запускал другую. Это напоминание всем нам — всегда проверяйте путь к файлу при запуске внешних обработок в режиме 1С:Предприятие!
Используя предложенные методы и оптимизированный запрос, вы сможете быстро и безопасно привести справочник сотрудников в актуальное состояние, скрыв ненужные записи подработок в архив.