Как реализовать автоматический выбор сотрудника при выборе подразделения в 1С

Программист 1С v8.3 (Управляемые формы) Управленческий учет IT и автоматизация бизнеса
← На главную

В процессе разработки конфигураций на платформе 1С:Предприятие 8.3 часто возникает задача автоматического заполнения реквизитов. Одним из наиболее востребованных сценариев является подстановка ответственного лица (например, руководителя) сразу после того, как пользователь выбрал подразделение в документе или справочнике. Это минимизирует количество ошибок и ускоряет работу оператора.

В этой статье мы подробно разберем, как правильно реализовать этот механизм, проанализируем типичные ошибки новичков и создадим надежный программный код для работы в управляемом приложении.

Постановка задачи и структура данных

Предположим, у нас есть независимый Регистр сведений (назовем его ип_ДРГОтветственныеЛица), в котором хранится информация о том, какой сотрудник какую должность занимает в конкретном подразделении. Структура регистра обычно следующая:

Наша цель: при выборе подразделения в форме документа автоматически найти в этом регистре запись с типом "Руководитель" и подставить найденного сотрудника в соответствующее поле документа.

Разбор типичных ошибок реализации

Прежде чем перейти к правильному решению, проанализируем ошибки, которые часто допускают начинающие программисты (как в сообщениях форума):

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

Шаг 1. Создание обработчика на клиенте

Для начала создадим клиентскую процедуру, которая будет срабатывать при изменении поля Подразделение. Мы воспользуемся событием ПриИзменении.

Рассмотрим код вызова:


&НаКлиенте
Процедура ПодразделениеПриИзменении(Элемент)
    
    // Передаем в серверную функцию ссылку на подразделение и дату документа
    // чтобы получить актуального руководителя на конкретный момент времени
    НайденныйСотрудник = ПолучитьРуководителяПодразделения(Объект.Подразделение, Объект.Дата);
    
    // Если результат найден, заполняем реквизит документа
    Если ЗначениеЗаполнено(НайденныйСотрудник) Тогда
        Объект.ОтветственноеЛицо = НайденныйСотрудник;
    КонецЕсли;
    
КонецПроцедуры

Шаг 2. Реализация серверной функции поиска

Теперь напишем функцию, которая будет выполнять запрос к базе данных. Обратите внимание на использование директивы &НаСервереБезКонтекста — это наиболее производительный способ, так как на сервер не передаются лишние данные формы.

Проанализируем структуру запроса и правильную установку параметров:


&НаСервереБезКонтекста
Функция ПолучитьРуководителяПодразделения(Знач ВыбранноеПодразделение, Знач ДатаДокумента)
    
    // Если подразделение не выбрано, возвращать некого
    Если Не ЗначениеЗаполнено(ВыбранноеПодразделение) Тогда
        Возврат Справочники.Сотрудники.ПустаяСсылка();
    КонецЕсли;
    
    Запрос = Новый Запрос;
    // Используем параметры виртуальной таблицы СрезПоследних для оптимизации
    Запрос.Текст = 
    "ВЫБРАТЬ
    |	ОтветственныеЛицаСрезПоследних.Сотрудник КАК Сотрудник
    |ИЗ
    |	РегистрСведений.ип_ДРГОтветственныеЛица.СрезПоследних(
    |			&Период,
    |			Подразделение = &Подразделение
    |				И ОтветственноеЛицо = &ТипОтветственного) КАК ОтветственныеЛицаСрезПоследних";
    
    // Устанавливаем параметры запроса
    Запрос.УстановитьПараметр("Период", ?(ЗначениеЗаполнено(ДатаДокумента), ДатаДокумента, ТекущаяДата()));
    Запрос.УстановитьПараметр("Подразделение", ВыбранноеПодразделение);
    Запрос.УстановитьПараметр("ТипОтветственного", Перечисления.ОтветственныеЛица.Руководитель);
    
    РезультатЗапроса = Запрос.Выполнить();
    
    // Проверяем, есть ли данные в результате
    Если Не РезультатЗапроса.Пустой() Тогда
        Выборка = РезультатЗапроса.Выбрать();
        Выборка.Следующий(); // Переходим к первой (и единственной) записи
        Возврат Выборка.Сотрудник;
    Иначе
        // Если руководитель не найден для данного подразделения
        Возврат Справочники.Сотрудники.ПустаяСсылка();
    КонецЕсли;
    
КонецФункции

Шаг 3. Оптимизация и дополнительные возможности

Рассмотрим ситуацию, когда в структуре предприятия есть вложенные подразделения. Бывает так, что руководитель назначен для "Департамента", но не назначен для конкретного "Отдела" внутри него. В этом случае может потребоваться поиск руководителя "вверх" по иерархии.

Для реализации такой логики можно использовать цикл Пока, который будет проверять родительские подразделения, если для текущего запись в регистре отсутствует. Выясним, как это может выглядеть в коде:


// Фрагмент логики поиска по иерархии
ТекущееПодразделение = ВыбранноеПодразделение;
Пока ЗначениеЗаполнено(ТекущееПодразделение) Цикл
    НайденныйСотрудник = ВыполнитьПоискВРегистре(ТекущееПодразделение); // вызов функции с запросом
    Если ЗначениеЗаполнено(НайденныйСотрудник) Тогда
        Возврат НайденныйСотрудник;
    КонецЕсли;
    
    // Поднимаемся на уровень выше
    ТекущееПодразделение = ТекущееПодразделение.Родитель;
КонецЦикла;

Важные моменты при разработке

Проанализируем еще несколько нюансов, которые помогут сделать ваше решение более профессиональным:

Таким образом, мы разобрали полный цикл реализации задачи: от перехвата события на клиенте до оптимизированного запроса к базе данных. Использование параметров виртуальной таблицы СрезПоследних и правильная работа с выборкой гарантируют высокую скорость работы системы даже при больших объемах данных в регистре ответственных лиц.

← На главную