При разработке интеграций, написании обработок по переносу данных или автоматическом заполнении справочников в конфигурациях «1С:Управление торговлей 11», «1С:ERP Управление предприятием» или «1С:Комплексная автоматизация» программисты часто сталкиваются со следующей проблемой. При попытке программно связать новое контактное лицо с контрагентом или партнером через стандартное свойство Владелец система выдает ошибку: «Справочник не имеет владельца».
В этой статье мы подробно разберем, почему возникает эта ошибка, проанализируем архитектурные особенности современных конфигураций 1С и научимся правильно создавать контактные лица программным путем, включая заполнение их контактных данных (телефонов, email) и ФИО.
В старых конфигурациях 1С (например, в «Управление торговлей 10.3») справочник КонтактныеЛица был подчинен справочнику Контрагенты классическим платформенным способом. Разработчик мог написать НовоеКЛ.Владелец = СсылкаНаКонтрагента, и этого было достаточно.
В современных конфигурациях на управляемых формах (УТ 11, ERP, КА) архитектура работы с клиентами кардинально изменилась. Было введено жесткое разделение на две сущности:
Поскольку менеджеры общаются с конкретными людьми (контактными лицами) в рамках операционной деятельности, в системе 1С контактные лица привязываются именно к Партнерам, а не к контрагентам. Более того, связь может быть гибкой (одно контактное лицо может работать с разными партнерами или контрагентами).
Из-за этой гибкости разработчики фирмы «1С» отказались от стандартного платформенного механизма подчинения справочников (свойства метаданных «Владелец»). Если вы откроете конфигуратор, то увидите, что у справочника КонтактныеЛица свойство «Владельцы» пустое и недоступно для редактирования. Связь реализуется через обычный реквизит с именем ОбъектВладелец, который имеет составной тип данных (чаще всего это СправочникСсылка.Партнеры, но может также включать физических лиц или контрагентов в зависимости от настроек конфигурации).
Посмотрим на пример кода, который вызывает ошибку, описанную автором темы:
// Ошибочный код, вызывающий сбой "Справочник не имеет владельца"
КЛ = Справочники.КонтактныеЛица.CreateItem(); // СоздатьЭлемент()
КЛ.Наименование = "Иван Иванович";
КЛ.Владелец = СсылкаНаКонтрагента; // ОШИБКА!
КЛ.Записать();
Чтобы исправить эту ошибку, нам необходимо вместо свойства Владелец использовать реквизит ОбъектВладелец и передавать туда ссылку на Партнера (или контрагента, если ваша конфигурация и бизнес-логика это предусматривают). Перепишем код правильно:
// Корректное заполнение владельца
НовоеКЛ = Справочники.КонтактныеЛица.СоздатьЭлемент();
НовоеКЛ.ОбъектВладелец = СсылкаНаПартнера; // Записываем в специальный реквизит
// Дальнейшее заполнение реквизитов...
НовоеКЛ.Записать();
Проанализируем ситуацию глубже. Простого указания владельца и наименования часто недостаточно для полноценного создания карточки контактного лица. Ниже мы разберем по шагам, как правильно заполнить все ключевые данные.
В современных конфигурациях 1С реквизит Наименование справочника КонтактныеЛица формируется автоматически при записи элемента на основе трех отдельных реквизитов: Фамилия, Имя и Отчество. Если вы просто запишете ФИО в наименование, при открытии карточки в режиме предприятия система может отобразить пустые поля имени или некорректно их распознать.
Рассмотрим правильный пример заполнения персональных данных:
НовоеКЛ = Справочники.КонтактныеЛица.СоздатьЭлемент();
НовоеКЛ.ОбъектВладелец = СсылкаНаПартнера;
// Заполняем составляющие ФИО отдельно
НовоеКЛ.Фамилия = "Иванов";
НовоеКЛ.Имя = "Иван";
НовоеКЛ.Отчество = "Иванович";
// Дополнительно можно указать должность по визитке
НовоеКЛ.ДолжностьПоВизитке = "Ведущий менеджер по закупкам";
НовоеКЛ.Записать();
После вызова метода Записать() система автоматически соберет строку "Иванов Иван Иванович" и запишет ее в стандартное наименование элемента.
Контактная информация (номера телефонов, адреса электронной почты) в современных конфигурациях хранится в табличной части КонтактнаяИнформация самого справочника. Эта подсистема построена на базе БСП (Библиотеки стандартных подсистем).
Попытка напрямую заполнить эту табличную часть вручную — частая ошибка начинающих программистов. Из-за этого могут не заполниться служебные поля (такие как хэш-адреса, городские коды и т.д.), и информация не будет отображаться на форме или в отчетах. Для правильной работы необходимо использовать стандартный программный интерфейс БСП — общий модуль УправлениеКонтактнойИнформацией.
Проанализируем пример добавления телефона и адреса электронной почты для созданного контактного лица:
// Сначала записываем элемент, чтобы получить валидную ссылку
НовоеКЛ.Записать();
СсылкаНаКЛ = НовоеКЛ.Ссылка;
// Добавляем телефон контактного лица
ВидТелефона = Справочники.ВидыКонтактнойИнформации.ТелефонКонтактногоЛица;
УправлениеКонтактнойИнформацией.ЗаписатьКонтактнуюИнформацию(
СсылкаНаКЛ,
"89991112233",
ВидТелефона,
Перечисления.ТипыКонтактнойИнформации.Телефон
);
// Добавляем адрес электронной почты
ВидEmail = Справочники.ВидыКонтактнойИнформации.EmailКонтактногоЛица;
УправлениеКонтактнойИнформацией.ЗаписатьКонтактнуюИнформацию(
СсылкаНаКЛ,
"ivanov@client.ru",
ВидEmail,
Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты
);
Очень часто при создании контактного лица требуется сразу сделать его «главным» (основным) для конкретного партнера, чтобы оно автоматически подставлялось в документы продажи или отчеты. Связь «Основное контактное лицо» хранится в самой карточке партнера.
Выясним, как программно обновить эту связь:
// Получаем объект партнера для изменения
ОбъектПартнера = СсылкаНаПартнера.ПолучитьОбъект();
// Устанавливаем ссылку на наше новое контактное лицо
ОбъектПартнера.ОсновноеКонтактноеЛицо = СсылкаНаКЛ;
// Записываем партнера
ОбъектПартнера.Записать();
Поскольку у справочника КонтактныеЛица отсутствует стандартный реквизит Владелец, написание привычных запросов с условием ВЫБРАТЬ ... ГДЕ Владелец = &Владелец приведет к синтаксической ошибке на этапе выполнения кода.
Посмотрим на правильный вариант построения запроса к базе данных для получения всех контактных лиц конкретного партнера:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КонтактныеЛица.Ссылка КАК КонтактноеЛицо,
| КонтактныеЛица.Наименование КАК ФИО,
| КонтактныеЛица.ДолжностьПоВизитке КАК Должность
|ИЗ
| Справочник.КонтактныеЛица КАК КонтактныеЛица
|ГДЕ
| КонтактныеЛица.ОбъектВладелец = &Партнер УСТАНОВИТЬ ГРАНИЦУ"; // Используем реквизит ОбъектВладелец
Запрос.УстановитьПараметр("Партнер", СсылкаНаПартнера);
РезультатЗапроса = Запрос.Выполнить();
Также разработчики могут использовать готовые функции БСП, которые позволяют быстро извлечь данные по умолчанию без ручного написания текстов запросов. Например:
ПартнерыИКонтрагенты.ПолучитьКонтактноеЛицоПартнераПоУмолчанию(Партнер) — возвращает ссылку на основное контактное лицо указанного партнера.ПартнерыИКонтрагенты.ПолучитьКонтактноеЛицоПартнераКонтрагентаПоУмолчанию(Контрагент) — находит партнера, связанного с контрагентом, и возвращает его основное контактное лицо.Мы выяснили причину возникновения популярной ошибки и разобрали правильный алгоритм работы со справочником контактных лиц в современных конфигурациях 1С. Подведем итог ключевых правил:
Владелец для справочника КонтактныеЛица в УТ 11 / ERP — его там нет. Используйте реквизит ОбъектВладелец.Партнеры, а не Контрагенты (за исключением редких специфических настроек учета).УправлениеКонтактнойИнформацией, чтобы избежать повреждения структуры данных КИ.