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