Как добавить фильтр по цвету в запрос по остаткам и ценам в 1С:Управление торговлей 10.3

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

При работе с переписанными конфигурациями на базе 1С:Управление торговлей 10.3 часто возникает необходимость оперативного изменения логики выгрузки данных, например, при отправке прайс-листов. Одной из типичных задач является исключение определенной номенклатуры из отчета на основе свойств, хранящихся в связанных справочниках. Рассмотрим, как правильно модифицировать запрос, чтобы отсечь товары с определенным цветом, и проанализируем основные ошибки, возникающие при этом.

Анализ исходной ситуации и структуры запроса

В нашем распоряжении имеется запрос, который выбирает остатки товаров из регистра накопления ТоварыНаСкладах.Остатки и соединяет их с актуальными ценами из регистра сведений ЦеныНоменклатуры.СрезПоследних. Нам необходимо добавить условие: если у номенклатуры выбран цвет с определенным кодом (например, 000000003), она не должна попадать в результат.

Проанализируем структуру типового запроса для решения этой задачи. Важно помнить, что в 1С фильтры по ссылочным полям лучше всего устанавливать непосредственно в параметрах виртуальной таблицы. Это существенно повышает производительность системы, так как отсечение данных происходит на уровне СУБД еще до начала формирования основной выборки.

Решение 1: Фильтрация через параметры виртуальной таблицы

Рассмотрим наиболее правильный с точки зрения архитектуры 1С способ решения проблемы. Мы установим фильтр прямо в скобках виртуальной таблицы Остатки(). Для этого нам потребуется заранее найти нужный элемент справочника по коду и передать его в запрос как параметр.


// 1. Сначала находим нужный цвет по коду
НужныйЦвет = Справочники.Цвета.НайтиПоКоду("000000003");

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

Запрос.УстановитьПараметр("Цвет", НужныйЦвет);
Запрос.УстановитьПараметр("Склады", МассивСкладов);
Запрос.УстановитьПараметр("ТипЦен", РозничнаяЦена);
Запрос.УстановитьПараметр("ИсключаемаяГруппа", Справочники.Номенклатура.НайтиПоКоду("00000099105"));

В данном примере мы используем конструкцию НЕ Номенклатура.Цвет = &Цвет внутри параметров виртуальной таблицы. Обратите внимание, что если реквизит Цвет в вашей конфигурации находится не в самой Номенклатуре, а в подчиненном справочнике, логика запроса потребует использования временных таблиц.

Решение 2: Использование временной таблицы (для подчиненных справочников)

Если справочник Цвета является подчиненным по отношению к номенклатуре, то простое обращение через точку может не сработать. В этом случае мы сначала соберем весь список номенклатуры, обладающей "нежелательным" цветом, во временную таблицу, а затем исключим её из основного запроса.

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

  1. Создаем первый запрос в пакете для поиска всех владельцев цвета.
  2. Помещаем результат во временную таблицу ТаблицаЗеленых.
  3. В основном запросе добавляем условие НЕ Номенклатура В (ВЫБРАТЬ Номенклатура ИЗ ТаблицаЗеленых).

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

Почему фильтр может не работать: типичные ошибки

Разберем ситуацию, когда вы добавили код, но "зеленые" товары все равно попадают в прайс или, наоборот, пропадает слишком много позиций. Выясним основные причины:

1. Ошибка поиска по коду. Метод НайтиПоКоду("000000003") чувствителен к длине строки. Если в справочнике код имеет длину 11 символов, а вы ищете 9, система вернет ПустуюСсылку. В результате условие НЕ Номенклатура.Цвет = &Цвет превратится в "Цвет не равен пустоте", что пропустит все заполненные карточки. Всегда проверяйте результат поиска: Если НужныйЦвет.Пустая() Тогда Сообщить("Цвет не найден!"); КонецЕсли;.

2. Проблема иерархии. Использование НЕ Номенклатура В ИЕРАРХИИ (&Номенклатура) при пустом параметре может привести к непредсказуемым результатам — иногда 1С исключает всю номенклатуру без родителя (корневые элементы). Если исключение групп не требуется, это условие лучше убрать.

3. Использование характеристик. В типовой УТ 10.3 цвет часто выносят в Характеристики номенклатуры. Если это так, то фильтровать нужно не Номенклатура.Цвет, а ХарактеристикаНоменклатуры.Цвет (или другое свойство). Проверьте в конфигураторе, где именно в регистре ТоварыНаСкладах хранится информация о цвете — в измерении Номенклатура или ХарактеристикаНоменклатуры.

4. Регистрозависимость при использовании ПОДОБНО. Если вы решили фильтровать по наименованию (Цвет.Наименование ПОДОБНО "%Зеленый%"), помните, что "Зеленый" и "зеленый" для SQL-сервера могут быть разными значениями. Кроме того, лишние пробелы в названии (как в случае автора темы: "Зеленый заказной") сделают фильтрацию некорректной.

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

При работе с большими базами данных 1С следует придерживаться следующих правил при написании запросов:

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

← На главную