Как вывести состав товаров в форме списка заказов в 1С:Управление торговлей 11.4?

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

В процессе работы менеджеры по продажам ежедневно обрабатывают десятки и сотни заказов клиентов. Для ускорения работы у них часто возникает вполне резонное желание: видеть состав выбранного заказа непосредственно в форме списка, не открывая сам документ. Это классическая схема отображения данных Master-Detail (главный-подчиненный), которая значительно экономит время и снижает нагрузку на пользователя.

В типовой конфигурации «1С:Управление торговлей», редакция 11.4 (УТ 11), стандартная форма списка заказов клиентов не предоставляет такой возможности «из коробки». В то же время в других современных решениях от 1С (например, в «1С:УНФ» или «1С:Розница 3.0») эта опция уже является штатной и активируется простым флажком в настройках списка. В этой статье мы подробно разберем, как самостоятельно реализовать подобный функционал в УТ 11.4 с помощью механизма расширений конфигурации, не снимая систему с поддержки.

Мы рассмотрим два основных технических подхода к решению этой задачи, проанализируем их сильные и слабые стороны, а также разберем вопросы оптимизации производительности интерфейса.


Вариант 1. Быстрое решение через добавление динамического списка на форму

Рассмотрим самый простой и быстрый способ реализации, который упоминается разработчиками на форумах. Этот метод основан на добавлении подчиненной таблицы непосредственно в форму списка через использование динамического списка с отбором по текущей строке основного списка документов.

Разберем по шагам, как это сделать:

  1. Создаем расширение конфигурации. Чтобы сохранить типовую конфигурацию на поддержке, все доработки будем выполнять в расширении. Создадим новое расширение, добавим в него форму списка документа ЗаказКлиента.
  2. Добавляем новый реквизит формы. В редакторе формы расширения добавим новый реквизит с типом ДинамическийСписок. Назовем его, например, СоставЗаказа.
  3. Настраиваем свойства динамического списка. В свойствах созданного списка установим флаг ПроизвольныйЗапрос и напишем простой запрос к табличной части товаров заказа:
    
    Выбрать
        ЗаказТовары.Номенклатура КАК Номенклатура,
        ЗаказТовары.Количество КАК Количество,
        ЗаказТовары.Цена КАК Цена,
        ЗаказТовары.Сумма КАК Сумма
    Из
        Документ.ЗаказКлиента.Товары КАК ЗаказТовары
    Где
        ЗаказТовары.Ссылка = &Ссылка
    
  4. Размещаем таблицу на форме. Перетащим реквизит СоставЗаказа на форму в качестве таблицы. Лучше всего расположить ее в нижней части формы или на боковой панели справа, предварительно создав группу панелей для удобного разделения экрана.
  5. Устанавливаем связь по текущей строке. Чтобы состав автоматически обновлялся при перемещении по основному списку заказов, нам необходимо связать параметры динамического списка товаров с текущей строкой списка заказов. В свойствах нашей новой таблицы состава настроим связь параметров выбора. В качестве источника выберем поле Элементы.Список.ТекущаяСтрока (или ТекущиеДанные.Ссылка), а в качестве приемника укажем наш параметр запроса Ссылка.

Преимущества этого подхода:

Недостатки и подводные камни:


Вариант 2. Профессиональное решение через обработчик ожидания (рекомендуется)

Для того чтобы интерфейс работал максимально плавно и не создавал избыточной нагрузки на сервер СУБД, профессиональные разработчики 1С используют паттерн отложенного вызова сервера с использованием обработчика ожидания. Разберем этот вариант подробнее.

Суть метода заключается в следующем: когда пользователь перемещается по списку заказов, мы не делаем запрос к серверу мгновенно. Мы запускаем небольшой таймер (например, на 0.3 секунды). Если в течение этого времени пользователь перешел на следующую строку, таймер сбрасывается и запускается заново. И только когда пользователь остановился на конкретном заказе дольше чем на 0.3 секунды, срабатывает процедура получения состава заказа.

Проанализируем программную реализацию этого метода. Для этого в модуле формы списка заказов в расширении напишем следующий код.

Сначала переопределим событие ПриАктивизацииСтроки для таблицы списка заказов:


&НаКлиенте
Процедура Расш1_СписокПриАктивизацииСтрокиПеред(Элемент)
    
    // При каждом изменении строки сбрасываем предыдущий обработчик ожидания
    ОтключитьОбработчикОжидания("ОбновитьСоставТекущегоЗаказа");
    
    // Подключаем однократный обработчик ожидания с задержкой 0.3 секунды
    ПодключитьОбработчикОжидания("ОбновитьСоставТекущегоЗаказа", 0.3, Истина);
    
КонецПроцедуры

Далее напишем саму процедуру, которая будет вызываться обработчиком ожидания. Обратите внимание, что обработчик ожидания может вызывать только клиентские процедуры без параметров:


&НаКлиенте
Процедура ОбновитьСоставТекущегоЗаказа()
    
    ТекущиеДанные = Элементы.Список.ТекущиеДанные;
    
    Если ТекущиеДанные = Неопределено Тогда
        // Если список пуст, очищаем таблицу состава на форме
        ОбъектСоставЗаказа.Очистить();
        Возврат;
    КонецЕсли;
    
    // Получаем ссылку на текущий выделенный заказ
    ТекущийЗаказ = ТекущиеДанные.Ссылка;
    
    // Вызываем неконтекстный серверный метод для получения данных
    ТаблицаТоваров = ПолучитьСоставЗаказаНаСервере(ТекущийЗаказ);
    
    // Заполняем коллекцию на форме (например, таблицу значений на форме)
    ЗначениеВРеквизитФормы(ТаблицаТоваров, "ОбъектСоставЗаказа");
    
КонецПроцедуры

Теперь реализуем серверную часть. Чтобы минимизировать трафик между сервером и клиентом и ускорить работу, используем директиву &НаСервереБезКонтекста. Это позволит избежать передачи всего контекста тяжелой формы списка заказов при каждом запросе:


&НаСервереБезКонтекста
Функция ПолучитьСоставЗаказаНаСервере(Знач СсылкаНаЗаказ)
    
    // Создаем таблицу значений для возврата данных на клиент
    ТаблицаРезультат = Новый ТаблицаЗначений;
    ТаблицаРезультат.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатуры"));
    ТаблицаРезультат.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисел(15, 3)));
    ТаблицаРезультат.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисел(15, 2)));
    ТаблицаРезультат.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисел(15, 2)));
    
    // Если ссылка пустая или не того типа, возвращаем пустую таблицу
    Если Не ЗначениеЗаполнено(СсылкаНаЗаказ) Тогда
        Возврат ТаблицаРезультат;
    КонецЕсли;
    
    // Выполняем легкий запрос к табличной части документа
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ЗаказТовары.Номенклатура КАК Номенклатура,
        |   ЗаказТовары.Количество КАК Количество,
        |   ЗаказТовары.Цена КАК Цена,
        |   ЗаказТовары.Сумма КАК Сумма
        |ИЗ
        |   Документ.ЗаказКлиента.Товары КАК ЗаказТовары
        |ГДЕ
        |   ЗаказТовары.Ссылка = &СсылкаНаЗаказ";
        
    Запрос.УстановитьПараметр("СсылкаНаЗаказ", СсылкаНаЗаказ);
    
    Выгрузка = Запрос.Выполнить().Выгрузить();
    
    Для Каждого Строка Из Выгрузка Цикл
        НоваяСтрока = ТаблицаРезультат.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка);
    КонецЦикла;
    
    Возврат ТаблицаРезультат;
    
КонецФункции

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


Развитие идеи: что еще можно вывести в панель состава?

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

Выясним причину, почему разработчики часто предостерегают от возможности редактирования состава прямо из списка. Как справедливо отмечено на форуме, вывод состава для просмотра — это простая и полезная задача. Однако попытка организовать полноценное редактирование табличной части документа прямо из этой панели приведет к необходимости реализации сложных транзакционных блокировок, постоянному пересчету итогов документа и вызову многочисленных обработчиков из Библиотеки Стандартных Подсистем (БСП). Поэтому лучшей практикой является вывод состава исключительно в режиме "Только просмотр".

← На главную