Как в 1С:УТ 11.4 получить все документы по конкретному виду номенклатуры

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

В процессе разработки на платформе 1С 8.3 часто возникает задача поиска документов, содержащих определенные данные в своих табличных частях. Одной из таких задач является поиск всех проведенных документов, в которых фигурирует номенклатура конкретного Вида номенклатуры. Ситуация осложняется тем, что в 1С:Управление торговлей 11.4 данные распределены по множеству типов документов (приобретения, реализации, перемещения, сборки и т.д.).

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

Метод 1. Динамическое формирование запроса через объединение таблиц

Самый очевидный способ — это составить запрос, который объединяет результаты поиска по всем интересующим нас документам. Поскольку структура табличных частей «Товары» у большинства документов в УТ 11.4 схожа, мы можем использовать конструкцию ОБЪЕДИНИТЬ ВСЕ.

Проанализируем ситуацию: нам нужно не просто получить список ссылок, но и наложить фильтр на реквизит номенклатуры (ее вид) и проверить статус проведения документа. Напишем код, который будет перебирать массив имен документов и склеивать текст запроса.


СписокТиповДокументов = Новый Массив;
СписокТиповДокументов.Добавить("ПриобретениеТоваровУслуг");
СписокТиповДокументов.Добавить("ВозвратТоваровОтКлиента");
СписокТиповДокументов.Добавить("ВозвратТоваровПоставщику");
СписокТиповДокументов.Добавить("ПеремещениеТоваров");
СписокТиповДокументов.Добавить("СборкаТоваров");
СписокТиповДокументов.Добавить("ПрочееОприходованиеТоваров");

ТекстЗапроса = "";

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

Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("ВидНоменклатуры", ВыбранныйВидНоменклатуры);

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    // Обработка полученных ссылок
КонецЦикла;

Разберем, что здесь происходит. Мы используем ВЫБРАТЬ РАЗЛИЧНЫЕ, так как в одном документе может быть несколько строк с номенклатурой одного и того же вида, а нам нужна только одна ссылка на документ. Фильтр ДокТаблица.Ссылка.Проведен гарантирует, что мы работаем только с актуальными данными учета.

Метод 2. Использование шаблона запроса и функции СтрЗаменить

Если документов много, ручная склейка строк выглядит громоздко. Рассмотрим более элегантный способ, который позволяет использовать возможности конструктора запросов для создания «эталонного» блока кода. Мы подготовим шаблон запроса для одного документа и будем заменять в нем имя таблицы в цикле.

Выясним причину удобства этого метода: вы можете отладить запрос в консоли для одного вида документа (например, ПриобретениеТоваровУслуг), а затем просто тиражировать его программно.


ШаблонЗапроса = 
"ВЫБРАТЬ РАЗЛИЧНЫЕ
|	ТЧ.Ссылка КАК Ссылка
|ИЗ
|	Документ.ИмяДокументаШаблон.Товары КАК ТЧ
|ГДЕ
|	ТЧ.Ссылка.Проведен
|	И ТЧ.Номенклатура.ВидНоменклатуры = &ВидНоменклатуры";

ТекстЗапроса = "";
Для каждого ИмяДокумента Из СписокТиповДокументов Цикл
    Если ТекстЗапроса <> "" Тогда
        ТекстЗапроса = ТекстЗапроса + "
        |ОБЪЕДИНИТЬ ВСЕ
        |";
    КонецЕсли;
    
    ТекстЗапроса = ТекстЗапроса + СтрЗаменить(ШаблонЗапроса, "ИмяДокументаШаблон", ИмяДокумента);
КонецЦикла;

Этот подход минимизирует риск опечаток в названиях полей и делает код значительно чище. Важно помнить: при использовании ОБЪЕДИНИТЬ ВСЕ порядок и количество полей во всех блоках ВЫБРАТЬ должны строго совпадать.

Метод 3. Программный обход метаданных (Универсальный поиск)

Если мы не хотим жестко прописывать массив имен документов, мы можем заставить систему саму найти все документы, у которых есть табличная часть Товары с реквизитом Номенклатура. Это сделает наш инструмент универсальным — он автоматически начнет искать данные даже в новых документах, добавленных в расширениях или при обновлении конфигурации.

Рассмотрим, как это реализовать через объект Метаданные:


СписокТипов = Новый Массив;

Для каждого МетаДанныеДокумента Из Метаданные.Документы Цикл
    ТабличнаяЧасть = МетаДанныеДокумента.ТабличныеЧасти.Найти("Товары");
    Если ТабличнаяЧасть <> Неопределено Тогда
        // Проверяем наличие реквизита Номенклатура в этой ТЧ
        Если ТабличнаяЧасть.Реквизиты.Найти("Номенклатура") <> Неопределено Тогда
            СписокТипов.Добавить(МетаДанныеДокумента.Имя);
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

После того как массив СписокТипов заполнен, мы можем применить Метод 2 для формирования итогового запроса. Такой подход максимально соответствует принципам разработки в крупных типовых решениях, таких как ERP или УТ 11.

Оптимизация и работа с индексами

Проанализируем ситуацию с точки зрения производительности. Прямой поиск по табличным частям всех документов — это ресурсоемкая операция (Full Scan таблиц SQL). Если база данных большая, запрос может выполняться очень долго.

Посмотрим на альтернативные варианты ускорения процесса:

  1. Использование регистров накопления: В УТ 11.4 почти все движения товаров отражаются в регистре ТоварыНаСкладах или ВыручкаИПродажи. Вместо поиска по ТЧ документов, попробуем обратиться к регистру. В нем есть измерение Номенклатура и регистратор. Один запрос к виртуальной таблице оборотов регистра будет работать в десятки раз быстрее, чем объединение 20 таблиц документов.
  2. Критерии отбора: В конфигураторе можно создать объект КритерийОтбора, указав в нем номенклатуру как состав реквизитов поиска. Тогда получение списка документов сведется к одной функции: КритерииОтбора.СвязанныеДокументы.Найти(СсылкаНаНоменклатуру).
  3. Временные таблицы: Если вам нужно фильтровать документы по сложному списку номенклатуры, сначала выгрузите этот список во временную таблицу, проиндексируйте его по ссылке, а затем соединяйте с табличными частями документов. Это поможет планировщику SQL выбрать оптимальный план запроса.

Нюансы с политиками учета серий и FEFO

Автор исходной проблемы упоминал, что для склада установлена политика «Управление по FEFO остатками серий», но в самом виде номенклатуры серии не используются. В 1С:УТ 11.4 это означает, что система может вести партионный учет в разрезе сроков годности или дат поступления «под капотом».

Проанализируем, где еще могут скрываться нужные нам документы:

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

Используя предложенные выше методы (особенно сочетание обхода метаданных и шаблонных запросов), вы сможете быстро и гибко получать списки любых документов в системе 1С:Предприятие 8.3.

← На главную