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

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

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

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

Разбор типичных ошибок логики запроса

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

Ошибка 1: Сопоставление разных типов ссылок. В коде автора встречается условие: ПО ЗаказКлиента.Ссылка = ВложенныйЗапрос.Поступления.Ссылка. Важно понимать, что в 1С:Предприятие ссылки документов разных типов (например, Заказ и Поступление) имеют разные уникальные идентификаторы (GUID). Такое равенство никогда не будет истинным, и результат запроса будет пустым.

Ошибка 2: Нарушение уникальности ключа динамического списка. Динамический список требует, чтобы каждая строка имела уникальный ключ (как правило, это Ссылка основной таблицы документа). Если у одного Заказа клиента есть две Реализации, то при использовании ЛЕВОЕ СОЕДИНЕНИЕ в результате запроса появятся две строки с одинаковой ссылкой на заказ. Это приведет к тому, что динамический список либо выдаст ошибку "Ключ записи не является уникальным", либо отобразит только одну случайную строку, скрыв остальные.

Решение 1: Использование вложенных запросов с агрегацией

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

Проанализируем пример правильной структуры запроса, где мы получаем суммарное количество товара по всем реализациям, связанным с заказом:


ВЫБРАТЬ
    ЗаказКлиента.Ссылка КАК Ссылка,
    ЗаказКлиента.СуммаДокумента КАК СуммаДокумента,
    ЗаказКлиента.Валюта КАК Валюта,
    ЕСТЬNULL(ВложенныйЗапросРеализации.КоличествоРеализовано, 0) КАК КоличествоРеализовано
ИЗ
    Документ.ЗаказКлиента КАК ЗаказКлиента
    ЛЕВОЕ СОЕДИНЕНИЕ (
        ВЫБРАТЬ
            РеализацияТоваровУслуг.ЗаказКлиента КАК ЗаказКлиента,
            СУММА(РеализацияТоваровУслугТовары.Количество) КАК КоличествоРеализовано
        ИЗ
            Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
            ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
            ПО РеализацияТоваровУслугТовары.Ссылка = РеализацияТоваровУслуг.Ссылка
        ГДЕ
            РеализацияТоваровУслугТовары.Номенклатура = &Номенклатура
        СГРУППИРОВАТЬ ПО
            РеализацияТоваровУслуг.ЗаказКлиента
    ) КАК ВложенныйЗапросРеализации
    ПО ЗаказКлиента.Ссылка = ВложенныйЗапросРеализации.ЗаказКлиента
ГДЕ
    ЗаказКлиента.Ссылка В (
        ВЫБРАТЬ ТЧ.Ссылка ИЗ Документ.ЗаказКлиента.Товары КАК ТЧ ГДЕ ТЧ.Номенклатура = &Номенклатура
    )

В данном примере мы сначала группируем все реализации по полю ЗаказКлиента (которое является основанием) и суммируем количество. Таким образом, на каждый заказ приходится ровно одна запись из вложенного запроса, что сохраняет уникальность ключа в динамическом списке.

Решение 2: Корректная связь с документами поступления

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

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

Рассмотрим вариант связи через регистр (более надежный способ для УТ 11):


ВЫБРАТЬ
    ЗаказКлиента.Ссылка,
    ЕСТЬNULL(ДанныеПоступлений.КоличествоПоступило, 0) КАК КоличествоПоступило
ИЗ
    Документ.ЗаказКлиента КАК ЗаказКлиента
    ЛЕВОЕ СОЕДИНЕНИЕ (
        ВЫБРАТЬ
            ЗапасыИПотребности.Заказ КАК Заказ,
            СУММА(ЗапасыИПотребности.Количество) КАК КоличествоПоступило
        ИЗ
            РегистрНакопления.ЗапасыИПотребности КАК ЗапасыИПотребности
        ГДЕ
            ЗапасыИПотребности.Номенклатура = &Номенклатура
            И ЗапасыИПотребности.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
        СГРУППИРОВАТЬ ПО
            ЗапасыИПотребности.Заказ
    ) КАК ДанныеПоступлений
    ПО ЗаказКлиента.Ссылка = ДанныеПоступлений.Заказ

Рекомендации по оптимизации динамического списка

Работа с динамическими списками в 1С 8.3 накладывает определенные ограничения на производительность. Рассмотрим основные правила:

  1. Избегайте лишних соединений. Каждое ЛЕВОЕ СОЕДИНЕНИЕ с тяжелой таблицей (особенно с табличными частями) замедляет открытие формы. Если данных много, лучше использовать данные регистров накопления, которые специально оптимизированы для быстрых итогов.
  2. Ограничивайте выборку. Всегда используйте параметры (например, &Номенклатура) не только во внешнем запросе, но и внутри вложенных запросов. Это позволит SQL-серверу эффективнее строить план запроса.
  3. Используйте функцию ЕСТЬNULL. При левом соединении, если данных в правой таблице нет, система вернет NULL. В динамическом списке это может привести к тому, что тип колонки не определится правильно. Всегда оборачивайте числовые поля в ЕСТЬNULL(Значение, 0), а ссылочные в ЕСТЬNULL(Ссылка, ЗНАЧЕНИЕ(Документ.ИмяДокумента.ПустаяСсылка)).
  4. Основная таблица. Убедитесь, что в настройках динамического списка указана "Основная таблица". Это позволит платформе автоматически генерировать стандартные команды (открыть, пометить на удаление) и оптимизировать получение данных.

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

← На главную