Как получить менеджера заказа в реализации при наличии нескольких заказов?

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

В практике разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда стандартный код получения данных перестает работать при изменении бизнес-логики использования документа. Одной из таких типовых задач является вывод менеджера заказа в печатную форму или спецификацию документа РеализацияТоваровИУслуг. Если реализация оформлена на основании одного заказа, данные легко получить через реквизит шапки, но если заказов несколько — система ведет себя иначе. Рассмотрим подробнее, почему так происходит и как правильно написать код для обработки обоих случаев.

Выясним причину проблемы: архитектура типовых решений

В современных конфигурациях, таких как УТ 11, ERP 2 или Комплексная автоматизация, реализован гибкий механизм связи отгрузки с распоряжениями. Проанализируем ситуацию: в документе реализации существует реквизит ЗаказКлиента. Однако он заполняется только в том случае, если весь документ оформлен по одному-единственному заказу. Как только менеджер добавляет в табличную часть товары из разных заказов, реквизит в шапке становится пустым (или содержит неопределенное значение), а ссылки на конкретные заказы переезжают в табличную часть Товары.

Именно поэтому обращение через точку вида ТекущийОбъект.ЗаказКлиента.Менеджер возвращает пустое значение. Программа просто не знает, какого именно менеджера выбрать из списка заказов, содержащихся в строках документа.

Способ 1. Использование запроса для получения списка менеджеров

Наиболее правильным и производительным методом в среде 1С является использование запроса. Это позволяет избежать обращения к объектам в цикле и дает возможность сразу сгруппировать данные. Разберем по шагам, как получить уникальных менеджеров из всех заказов, фигурирующих в реализации.

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |	РеализацияТовары.Заказ.Менеджер КАК Менеджер
    |ИЗ
    |	Документ.РеализацияТоваровИУслуг.Товары КАК РеализацияТовары
    |ГДЕ
    |	РеализацияТовары.Ссылка = &Ссылка
    |	И РеализацияТовары.Заказ <> ЗНАЧЕНИЕ(Документ.ЗаказКлиента.ПустаяСсылка)";

Запрос.УстановитьПараметр("Ссылка", ТекущийОбъект.Ссылка);
РезультатЗапроса = Запрос.Выполнить();

В данном примере мы используем ключевое слово РАЗЛИЧНЫЕ, чтобы исключить дублирование имен менеджеров, если несколько строк документа относятся к заказам одного и того же сотрудника. Далее мы можем либо объединить их в строку через запятую, либо выбрать первого найденного.

Способ 2. Работа с коллекцией табличной части через ВыгрузитьКолонку

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

  1. Выгружаем все ссылки на заказы из колонки Заказ таблицы Товары.
  2. Очищаем массив от пустых ссылок.
  3. Удаляем дублирующиеся значения.
  4. Если массив не пуст, обращаемся к первому элементу.

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


МассивЗаказов = ТекущийОбъект.Товары.ВыгрузитьКолонку("Заказ");

// Удаляем пустые значения, которые могут быть, если часть товара без заказа
Счетчик = МассивЗаказов.Количество() - 1;
Пока Счетчик >= 0 Цикл
    Если Не ЗначениеЗаполнено(МассивЗаказов[Счетчик]) Тогда
        МассивЗаказов.Удалить(Счетчик);
    КонецЕсли;
    Счетчик = Счетчик - 1;
КонецЦикла;

// Если заказы найдены, берем менеджера из первого заказа
Если МассивЗаказов.Количество() > 0 Тогда
    ПервыйЗаказ = МассивЗаказов[0];
    ОбластьМакета.Параметры.МенеджерЗаказа = ПервыйЗаказ.Менеджер;
Иначе
    // Если заказов в ТЧ нет, пробуем взять из шапки или ответственного
    ОбластьМакета.Параметры.МенеджерЗаказа = ТекущийОбъект.Ответственный;
КонецЕсли;

Способ 3. Универсальная проверка типа данных

Иногда при разработке функций печати данные могут приходить в разном формате: как одиночная ссылка или как массив ссылок. Чтобы код был отказоустойчивым, рекомендуется добавить проверку типа значения (ТипЗнч). Рассмотрим, как это применить в процедуре печати:


Если ТипЗнч(ТекущийОбъект.ЗаказКлиента) = Тип("ДокументСсылка.ЗаказКлиента") 
    И ЗначениеЗаполнено(ТекущийОбъект.ЗаказКлиента) Тогда
    
    // Случай 1: Заказ указан в шапке
    МенеджерДляПечати = ТекущийОбъект.ЗаказКлиента.Менеджер;
    
ИначеЕсли ТекущийОбъект.Товары.Количество() > 0 Тогда
    
    // Случай 2: Ищем в табличной части
    Для Каждого СтрокаТовара Из ТекущийОбъект.Товары Цикл
        Если ЗначениеЗаполнено(СтрокаТовара.Заказ) Тогда
            МенеджерДляПечати = СтрокаТовара.Заказ.Менеджер;
            Прервать; // Берем менеджера из первой же заполненной строки
        КонецЕсли;
    КонецЦикла;
    
КонецЕсли;

Если Не ЗначениеЗаполнено(МенеджерДляПечати) Тогда
    МенеджерДляПечати = ТекущийОбъект.Ответственный;
КонецЕсли;

Рекомендации по выводу данных в спецификацию

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

Использование отладки для поиска данных

Если вы не уверены, где именно в вашей конфигурации хранятся связи, воспользуйтесь точкой останова в процедуре печати. Проанализируйте структуру ТекущийОбъект. Обратите внимание на коллекции Товары и, в редких случаях, ЭтапыГрафикаОплаты. В некоторых отраслевых решениях заказы могут храниться не в основной таблице товаров, а в скрытых служебных табличных частях или регистрах сведений (например, СвязиДокументов).

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

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

← На главную