Как программно проверить вхождение контрагента в группу и заполнить статью затрат в 1С 8.3

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

В процессе автоматизации учетных систем на базе 1С:Предприятие 8.3 часто возникает задача автоматической подстановки данных в зависимости от того, к какому сегменту или папке справочника относится выбранный объект. Типичный пример — документ Платежное поручение, где при выборе контрагента из определенной группы (например, «Реконструкция») должна автоматически подставляться соответствующая Статья затрат.

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

Метод 1. Проверка через непосредственного родителя

Самый простой, но ограниченный способ — проверка реквизита Родитель. Этот метод подходит только в том случае, если вы точно уверены, что справочник имеет одноуровневую структуру и все нужные контрагенты лежат непосредственно внутри искомой папки.

Рассмотрим пример кода:


ПапкаКонтрагент = Справочники.Контрагенты.НайтиПоНаименованию("РЕКОНСТРУКЦИЯ");
Если Контрагент.Родитель = ПапкаКонтрагент Тогда
    СтатьяЗатрат = Справочники.СтатьиЗатрат.НайтиПоНаименованию("РЕКОНСТРУКЦИЯ");
Иначе
    СтатьяЗатрат = Справочники.СтатьиЗатрат.НайтиПоНаименованию("ПРОЧИЙ РАСХОД");
КонецЕсли;

Важное ограничение: Если внутри папки «РЕКОНСТРУКЦИЯ» создана еще одна подпапка, и контрагент находится в ней, условие Контрагент.Родитель = ПапкаКонтрагент вернет Ложь. Это связано с тем, что реквизит Родитель хранит ссылку только на ближайший вышестоящий уровень.

Метод 2. Использование метода ПринадлежитЭлементу (Рекомендуемый)

Для работы с иерархическими справочниками в платформе 1С предусмотрен встроенный метод ПринадлежитЭлементу(). Он проверяет вхождение элемента в группу на любом уровне вложенности. Это наиболее надежный способ для проверки принадлежности к папке.

Проанализируем реализацию этого метода:


// Сначала найдем ссылку на нужную группу
ГруппаРеконструкция = Справочники.Контрагенты.НайтиПоНаименованию("РЕКОНСТРУКЦИЯ");

// Проверяем вхождение контрагента в эту группу
Если ЗначениеЗаполнено(Контрагент) И Контрагент.ПринадлежитЭлементу(ГруппаРеконструкция) Тогда
    Объект.СтатьяЗатрат = Справочники.СтатьиЗатрат.НайтиПоНаименованию("РЕКОНСТРУКЦИЯ");
Иначе
    Объект.СтатьяЗатрат = Справочники.СтатьиЗатрат.НайтиПоНаименованию("ПРОЧИЙ РАСХОД");
КонецЕсли;

Преимущества этого подхода:

  1. Корректно работает с многоуровневой иерархией.
  2. Код легко читается и понимается.
  3. Метод встроен в платформу и оптимизирован для простых проверок одиночных ссылок.

Метод 3. Проверка через запрос (универсальный подход)

Если нам требуется проверить не одного контрагента, а целый список, или если логика проверки является частью сложного алгоритма заполнения, лучше использовать механизм запросов с оператором В ИЕРАРХИИ. Это позволяет избежать лишних обращений к базе данных в цикле.

Разберем, как это реализовать программно:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Контрагенты.Ссылка КАК Ссылка
    |ИЗ
    |	Справочник.Контрагенты КАК Контрагенты
    |ГДЕ
    |	Контрагенты.Ссылка = &Контрагент
    |	И Контрагенты.Ссылка В ИЕРАРХИИ(&Группа)";

Запрос.УстановитьПараметр("Контрагент", Объект.Контрагент);
Запрос.УстановитьПараметр("Группа", Справочники.Контрагенты.НайтиПоНаименованию("РЕКОНСТРУКЦИЯ"));

РезультатЗапроса = Запрос.Выполнить();

Если НЕ РезультатЗапроса.Пустой() Тогда
    // Контрагент входит в группу
    Объект.СтатьяЗатрат = Справочники.СтатьиЗатрат.НайтиПоНаименованию("РЕКОНСТРУКЦИЯ");
КонецЕсли;

Интеграция в форму документа: Событие ПриИзменении

Чтобы автоматизация сработала в момент выбора пользователя, нам необходимо встроить код в обработчик события ПриИзменении для поля Контрагент или ВидОперации. Рассмотрим ситуацию, когда подстановка должна происходить в документе Платежное поручение при условии, что выбран вид операции «Прочий расход».

Пример реализации в модуле формы:


&НаКлиенте
Процедура КонтрагентПриИзменении(Элемент)
    ЗаполнитьСтатьюПоКонтрагентуСервер();
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьСтатьюПоКонтрагентуСервер()
    
    // Проверяем, что вид операции соответствует нашей логике
    Если Объект.ВидОперации = ПредопределенноеЗначение("Перечисление.ВидыОперацийПлатежноеПоручение.ПрочийРасход") Тогда
        
        ПапкаРеконструкция = Справочники.Контрагенты.НайтиПоНаименованию("РЕКОНСТРУКЦИЯ");
        
        Если ЗначениеЗаполнено(Объект.Контрагент) И Объект.Контрагент.ПринадлежитЭлементу(ПапкаРеконструкция) Тогда
            Объект.СтатьяЗатрат = Справочники.СтатьиЗатрат.НайтиПоНаименованию("РЕКОНСТРУКЦИЯ");
        Иначе
            Объект.СтатьяЗатрат = Справочники.СтатьиЗатрат.НайтиПоНаименованию("ПРОЧИЙ РАСХОД");
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Почему поиск по наименованию — это плохо, и как сделать лучше?

Использование функции НайтиПоНаименованию("РЕКОНСТРУКЦИЯ") считается «жестким кодированием» (hardcode) и имеет существенные недостатки:

Как рекомендуют эксперты:

1. Предопределенные элементы: Если группа «РЕКОНСТРУКЦИЯ» является системной, сделайте её предопределенной в конфигураторе. Тогда в коде вы сможете обращаться к ней так: Справочники.Контрагенты.Реконструкция.

2. Использование дополнительных реквизитов (БСП): Вместо привязки к папке, добавьте контрагенту дополнительный признак (флажок) «Относится к реконструкции». Это позволит перемещать контрагента между любыми папками без потери логики заполнения.

3. Использование констант или настроек: Создайте константу или запись в регистре сведений «Настройки программы», куда пользователь сам один раз выберет нужную папку. В коде вы будете считывать значение из этой настройки.

Оптимизация производительности

Помните, что метод ПринадлежитЭлементу() и НайтиПоНаименованию() — это серверные операции. При работе в управляемом приложении (1С 8.3) старайтесь минимизировать количество вызовов сервера. Если вам нужно часто проверять принадлежность, имеет смысл кэшировать ссылку на группу «РЕКОНСТРУКЦИЯ» при открытии формы, чтобы не искать её каждый раз заново в базе данных при изменении реквизитов.

Также важно всегда проверять ссылку на пустое значение перед вызовом методов объекта. Вызов Объект.Контрагент.ПринадлежитЭлементу(...) приведет к ошибке выполнения, если Контрагент не выбран (имеет значение ПустаяСсылка).

← На главную