Как в запросе 1С сделать отбор по поставщику, магазину и получить актуальные розничные цены

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

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

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

Причина ошибки «Недопустимое значение параметра» в Построителе отчета

Проанализируем типовую ошибку, которая часто возникает при программной настройке фильтров в обработках:

Ошибка при вызове метода контекста (Добавить): СтрокаОтбора = СтруктураПараметров.ПостроительОтчета.Отбор.Добавить("Магазин"); по причине: Недопустимое значение параметра (параметр номер '1')

Данная ошибка означает, что ПостроительОтчета не находит в тексте переданного ему запроса поле с именем Магазин. Если в запросе поле названо как Подразделения.Наименование или Склады.Ссылка, объектная модель построителя не сможет сопоставить переданный строковый идентификатор с доступными полями выборки.

Разберем способы устранения этой проблемы:

  1. Задать явный псевдоним в списке полей выборки: переименуем поле в запросе, указав Склады.Ссылка КАК Магазин или Подразделения.Ссылка КАК Магазин.
  2. Использовать секцию инструкций построителя отчета: чтобы поле было доступно для отбора даже без обязательного вывода в результат выборки, опишем его в специальных фигурных скобках {ГДЕ ...}.

Посмотрим на пример описания доступных полей отбора в тексте запроса для построителя:


ВЫБРАТЬ
    Остатки.Склад КАК Магазин,
    Остатки.Номенклатура КАК Номенклатура,
    Цены.Цена КАК Цена
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК Остатки
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ) КАК Цены
        ПО Остатки.Номенклатура = Цены.Номенклатура
{ГДЕ
    Остатки.Склад.* КАК Магазин,
    Остатки.Номенклатура.ОсновнойПоставщик.* КАК Поставщик,
    Остатки.Номенклатура.* КАК Номенклатура}

Откуда получать данные о поставщике номенклатуры

Выясним, где в структуре метаданных хранится привязка товара к контрагенту-поставщику. В зависимости от специфики учета выделяют два основных подхода:

  1. Основной поставщик из карточки товара: реквизит ОсновнойПоставщик справочника Номенклатура. Это наиболее простой вариант, подходящий для случаев, когда за каждой позицией номенклатуры закреплен один постоянный контрагент. Отбор в этом случае накладывается через реквизит: Номенклатура.ОсновнойПоставщик = &Поставщик.
  2. Фактический поставщик из партий поступления: если один и тот же товар может поступать от разных контрагентов и в конфигурации ведется партионный учет, обратимся к регистру накопления ПартииТоваровНаСкладах.Остатки. Измерение ДокументОприходования содержит ссылку на документ поступления, из которого мы получаем реквизит Контрагент.
  3. Штрихкоды и серии поставщика: в специализированных (например, ювелирных) конфигурациях уникальные данные по весу, размеру и штрихкоду поставщика хранятся в справочнике СерииНоменклатуры или подчиненных регистрах сведений.

Как связать розничные цены с магазинами и остатками

Часто в разных магазинах (подразделениях или торговых точках) действуют разные розничные цены на один и тот же товар. В типовых конфигурациях подразделение напрямую не входит в регистр ЦеныНоменклатуры.

Разберем логику связывания данных по шагам:

  1. Каждый розничный магазин представлен элементом справочника Склады с признаком розничного склада (АТТ или НТТ).
  2. В карточке склада указан реквизит ТипЦенРозничнойТорговли (или ТипЦен).
  3. Мы выбираем остатки товаров в разрезе складов, а затем соединяем их с регистром сведений ЦеныНоменклатуры.СрезПоследних сразу по двум полям: по номенклатуре и по типу цен склада.

Рассмотрим комплексный пример запроса, объединяющего остатки, характеристики, розничные цены магазинов и отбор по поставщику:


ВЫБРАТЬ
    ОстаткиТоваров.Склад КАК Магазин,
    ОстаткиТоваров.Номенклатура.Артикул КАК Артикул,
    ОстаткиТоваров.Номенклатура КАК Номенклатура,
    ОстаткиТоваров.Номенклатура.ОсновнойПоставщик КАК ОсновнойПоставщик,
    ОстаткиТоваров.СерияНоменклатуры.ювРазмер КАК Размер,
    ОстаткиТоваров.СерияНоменклатуры.ювВес КАК Вес,
    ОстаткиТоваров.СерияНоменклатуры.ювШтрихкодПоставщика КАК Штрихкод,
    ОстаткиТоваров.КоличествоОстаток КАК Количество,
    ЕСТЬNULL(ЦеныСрез.Валюта, ЗНАЧЕНИЕ(Справочник.Валюты.ПустаяСсылка)) КАК Валюта,
    ЕСТЬNULL(ЦеныСрез.Цена, 0) КАК РознЦена
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(
        &Период,
        {Склад.* КАК Магазин, Номенклатура.* КАК Номенклатура}
    ) КАК ОстаткиТоваров

    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
        &Период,
        {Номенклатура.* КАК Номенклатура}
    ) КАК ЦеныСрез
        ПО ОстаткиТоваров.Номенклатура = ЦеныСрез.Номенклатура
        И ОстаткиТоваров.Склад.ТипЦенРозничнойТорговли = ЦеныСрез.ТипЦен
{ГДЕ
    ОстаткиТоваров.Склад.* КАК Магазин,
    ОстаткиТоваров.Номенклатура.ОсновнойПоставщик.* КАК Поставщик,
    ОстаткиТоваров.Номенклатура.* КАК Номенклатура}

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

Для обеспечения высокой скорости формирования отчета и исключения блокировок базы данных учтем следующие правила:

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