Как программно заполнить контактное лицо при выборе клиента в документе Заказ клиента в 1С:КА 2

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

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

Разбор типичной ошибки: Ссылка vs Строка

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

Если Объект.Партнер = "ООО Тест" Тогда Объект.КонтактноеЛицо = "ХХХ"; КонецЕсли;

Почему это не работает? В системе 1С реквизиты Партнер и КонтактноеЛицо имеют тип «Ссылка» (СправочникСсылка.Партнеры и СправочникСсылка.КонтактныеЛицаПартнеров соответственно). Ссылка — это уникальный идентификатор записи в базе данных (UUID), а не текст, который мы видим на экране. Строка «ООО Тест» — это лишь значение реквизита Наименование внутри объекта, на который указывает ссылка.

Для того чтобы обращение к реквизитам было корректным, нам необходимо либо сравнивать наименование объекта со строкой, либо (что более правильно) найти ссылку на нужный объект в справочнике и сравнивать уже две ссылки.

Решение 1: Использование метода НайтиПоНаименованию

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

Во-первых, нам нужно найти саму компанию (Партнера). Во-вторых, нужно найти контактное лицо, которое принадлежит именно этой компании. Рассмотрим пример кода:


// Определяем названия, которые мы ищем
НаименованиеКлиента = "ООО Тест";
НазваниеКонтакта = "Иванов Иван Иванович";

// Находим ссылку на партнера
СсылкаНаКлиента = Справочники.Партнеры.НайтиПоНаименованию(НаименованиеКлиента);

// Проверяем, что партнер найден и совпадает с выбранным в документе
Если Объект.Партнер = СсылкаНаКлиента И Не СсылкаНаКлиента.Пустая() Тогда
    
    // Ищем контактное лицо, ОХЗАТЕЛЬНО указывая владельца
    // Третий параметр метода НайтиПоНаименованию — это владелец (Партнер)
    СсылкаНаКонтакт = Справочники.КонтактныеЛицаПартнеров.НайтиПоНаименованию(НазваниеКонтакта, Ложь, СсылкаНаКлиента);
    
    Если Не СсылкаНаКонтакт.Пустая() Тогда
        Объект.КонтактноеЛицо = СсылкаНаКонтакт;
    КонецЕсли;
    
КонецЕсли;

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

Решение 2: Обращение через точку (Наименование)

Если нам нужно просто проверить условие, не выполняя поиск в справочнике, мы можем обратиться к реквизиту Наименование через точку от ссылки. Посмотрим на этот вариант:


Если Объект.Партнер.Наименование = "ООО Тест" Тогда
    // Здесь должна быть логика поиска ссылки на контактное лицо, 
    // так как присвоить строку "ХХХ" в реквизит Ссылка нельзя.
КонецЕсли;

Важное предупреждение: Обращение через точку Объект.Партнер.Наименование заставляет систему выполнять неявный запрос к базе данных для получения этого поля. Если вы делаете это в цикле или при обработке большого количества данных, это может замедлить работу программы. Кроме того, если реквизит Партнер не заполнен (пустая ссылка), обращение к его наименованию в некоторых случаях может вернуть пустую строку, но лучше всегда проверять на Пустая().

Особенности архитектуры 1С:Комплексная автоматизация 2

Проанализируем специфику конфигурации КА 2. В этой системе разделены понятия Партнер и Контрагент:

  1. Партнер — это управленческое понятие (бренд, холдинг). Именно партнеры указываются в поле «Клиент» во многих документах.
  2. Контрагент — это юридическое лицо (ИНН, КПП, расчетные счета).

Контактные лица в КА 2 привязываются именно к Партнеру. Поэтому при программной подстановке убедитесь, что вы ищете контакт в справочнике КонтактныеЛицаПартнеров, а в качестве владельца передаете именно ссылку из поля Партнер (или Клиент, в зависимости от имени реквизита в форме).

Продвинутый подход: Избегаем «хардкода»

Использование жестко прописанных строк типа "ООО Тест" в коде считается плохой практикой (Hardcode). Если пользователь изменит название компании (например, добавит лишний пробел или изменит кавычки), ваш код перестанет работать. Рассмотрим более надежные способы реализации:

Место размещения кода: Обработчик события

Чтобы контактное лицо подставлялось сразу после того, как пользователь выбрал клиента, код необходимо разместить в модуле формы документа ЗаказКлиента. Для этого используется событие ПартнерПриИзменении.

Поскольку поиск в справочниках — это серверная операция, мы должны правильно распределить вызовы между клиентом и сервером:


&НаКлиенте
Процедура ПартнерПриИзменении(Элемент)
    // Вызываем серверную процедуру для поиска и подстановки
    ПодставитьКонтактноеЛицоНаСервере();
КонецПроцедуры

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

Использование параметра Истина во втором аргументе метода НайтиПоНаименованию гарантирует поиск по полному соответствию строки, что исключает ошибки, когда «ООО Тест» путается с «ООО Тест Плюс».

Итоги и рекомендации

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

  1. Никогда не присваивайте строку реквизиту, имеющему тип «СправочникСсылка». Сначала найдите ссылку.
  2. Всегда указывайте Владельца при поиске контактных лиц.
  3. Выполняйте поиск на Сервере, так как менеджеры справочников недоступны на клиенте.
  4. Используйте Истина для поиска по полному совпадению наименования.
  5. Проверяйте результат поиска методом Пустая(), чтобы не затереть существующие данные пустым значением.

Применяя эти правила, вы создадите надежный и отказоустойчивый код для автоматизации работы пользователей в 1С:Комплексная автоматизация 2.

← На главную