При разработке печатных форм в среде 1С:Предприятие 8.3, особенно в конфигурациях на базе БСП (например, Бухгалтерия предприятия 3.0), часто возникает задача вывести данные не только самого контрагента, но и его основного представителя. Начинающие разработчики часто сталкиваются с трудностями при попытке "достучаться" до этих данных из кода. В этой статье мы подробно разберем, как правильно реализовать отбор по контактному лицу, избежав распространенных ошибок.
Рассмотрим ситуацию, с которой столкнулся автор темы. Попытка использовать метод НайтиПоРеквизиту для поиска основного контактного лица является концептуально неверной по нескольким причинам:
КонтактныеЛица является подчиненным справочнику Контрагенты. Метод НайтиПоРеквизиту ищет первый попавшийся элемент во всей таблице базы данных. Если у вас 1000 контрагентов и у каждого есть "Основной" контакт, система вернет вам ссылку на контактное лицо случайного контрагента, а не того, который указан в документе."Список.Основной" ошибочно. Префикс Список относится к элементам интерфейса (динамическому списку на форме), в то время как программный код в модуле менеджера или объекта работает напрямую с метаданными и таблицами SQL. В базе данных реквизит называется просто Основной.Использование запроса — это наиболее эффективный и профессиональный способ получения данных в 1С. Проанализируем, как составить запрос, который выберет именно то контактное лицо, которое принадлежит нашему контрагенту и помечено как основное.
Для реализации этого метода нам необходимо передать в запрос ссылку на контрагента и условие по флагу Основной. Рассмотрим пример кода:
Функция ПолучитьОсновноеКонтактноеЛицо(СсылкаНаКонтрагента) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| КонтактныеЛица.Наименование КАК ФИО
|ИЗ
| Справочник.КонтактныеЛица КАК КонтактныеЛица
|ГДЕ
| КонтактныеЛица.Владелец = &Владелец
| И КонтактныеЛица.Основной = ИСТИНА
| И КонтактныеЛица.ПометкаУдаления = ЛОЖЬ";
Запрос.УстановитьПараметр("Владелец", СсылкаНаКонтрагента);
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
Возврат Выборка.ФИО;
Иначе
Возврат "__________________"; // Возвращаем пустую строку для макета
КонецЕсли;
КонецФункции
Разберем, что мы сделали: мы ограничили выборку владельцем (Владелец = &Владелец) и добавили проверку на пометку удаления, чтобы не выводить неактуальные данные. Использование ВЫБРАТЬ ПЕРВЫЕ 1 гарантирует нам получение только одной записи, даже если в базе произошла ошибка и основных лиц оказалось несколько.
Если по каким-то причинам вы не хотите использовать запрос (хотя это не рекомендуется для производительности), можно воспользоваться методом Выбрать() самого справочника. Проанализируем этот подход:
Отбор = Новый Структура;
Отбор.Вставить("Основной", Истина);
Выборка = Справочники.КонтактныеЛица.Выбрать(СсылкаНаКонтрагента, , Отбор);
Если Выборка.Следующий() Тогда
ОбластьПоставщик2.Параметры.тн_Контрагент = Выборка.Наименование;
Иначе
ОбластьПоставщик2.Параметры.тн_Контрагент = "__________________";
КонецЕсли;
Здесь важно помнить: первым параметром в метод Выбрать передается Владелец. Это ключевой момент, который решает проблему поиска "не того" сотрудника. Если передать Неопределено или пустую ссылку, поиск снова пойдет по всей базе.
В процессе обсуждения возникла путаница между "Основным контактным лицом" (представителем клиента) и "Текущим сотрудником" (тем, кто печатает документ). Выясним причину этой путаницы и как правильно работать с обоими понятиями.
Контактное лицо контрагента — это сторонний человек, сотрудник вашего партнера. Он хранится в справочнике КонтактныеЛица, владельцем которого является Контрагент.
Текущий сотрудник (пользователь) — это работник вашей организации, который авторизован в системе. Если задача стоит вывести именно того, кто нажал кнопку "Печать", то логика должна быть совершенно иной. В типовых конфигурациях для этого используются ПараметрыСеанса.
Посмотрим на пример получения ФИО текущего пользователя:
// Получаем текущего пользователя системы
ТекущийПользователь = ПараметрыСеанса.ТекущийПользователь;
// В БП 3.0 физическое лицо связано с пользователем через реквизит
ФизЛицоПользователя = ТекущийПользователь.ФизическоеЛицо;
Если ЗначениеЗаполнено(ФизЛицоПользователя) Тогда
ОбластьПоставщик2.Параметры.тн_Контрагент = Строка(ФизЛицоПользователя);
КонецЕсли;
Когда мы определились с методом получения данных, нам нужно передать их в параметры макета. Рассмотрим финальный алгоритм действий в модуле менеджера при формировании табличного документа:
Контрагента.Важный нюанс: Если вы работаете в конфигурации Бухгалтерия предприятия 3.0, рекомендуется использовать функции из состава БСП для форматирования ФИО (например, чтобы преобразовать "Иванов Иван Иванович" в "Иванов И.И."). Для этого можно обратиться к общему модулю ФизическиеЛица.
Таким образом, правильный подход к решению задачи заключается в строгом соблюдении иерархии данных: Контрагент (Владелец) -> Контактное лицо (Элемент) -> Свойство "Основной". Использование запроса с фильтром по владельцу — это надежный и масштабируемый способ, который обеспечит корректную работу печатной формы при любом объеме данных в базе.