При разработке отчетов и обработок в решениях на платформе «1С:Предприятие» (например, «Управление торговлей 10.3» и отраслевых конфигурациях) часто требуется сформировать выборку, включающую остатки товаров, штрихкоды, характеристики и розничные цены конкретных магазинов, а также предоставить пользователю возможность фильтровать данные по поставщику.
В этой статье мы подробно разберем, почему возникает ошибка при добавлении отбора в ПостроительОтчета, откуда правильно получать данные о поставщике и как грамотно связать таблицы остатков, складов и цен номенклатуры.
Проанализируем типовую ошибку, которая часто возникает при программной настройке фильтров в обработках:
Ошибка при вызове метода контекста (Добавить): СтрокаОтбора = СтруктураПараметров.ПостроительОтчета.Отбор.Добавить("Магазин"); по причине: Недопустимое значение параметра (параметр номер '1')
Данная ошибка означает, что ПостроительОтчета не находит в тексте переданного ему запроса поле с именем Магазин. Если в запросе поле названо как Подразделения.Наименование или Склады.Ссылка, объектная модель построителя не сможет сопоставить переданный строковый идентификатор с доступными полями выборки.
Разберем способы устранения этой проблемы:
Склады.Ссылка КАК Магазин или Подразделения.Ссылка КАК Магазин.{ГДЕ ...}.Посмотрим на пример описания доступных полей отбора в тексте запроса для построителя:
ВЫБРАТЬ
Остатки.Склад КАК Магазин,
Остатки.Номенклатура КАК Номенклатура,
Цены.Цена КАК Цена
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК Остатки
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ) КАК Цены
ПО Остатки.Номенклатура = Цены.Номенклатура
{ГДЕ
Остатки.Склад.* КАК Магазин,
Остатки.Номенклатура.ОсновнойПоставщик.* КАК Поставщик,
Остатки.Номенклатура.* КАК Номенклатура}
Выясним, где в структуре метаданных хранится привязка товара к контрагенту-поставщику. В зависимости от специфики учета выделяют два основных подхода:
ОсновнойПоставщик справочника Номенклатура. Это наиболее простой вариант, подходящий для случаев, когда за каждой позицией номенклатуры закреплен один постоянный контрагент. Отбор в этом случае накладывается через реквизит: Номенклатура.ОсновнойПоставщик = &Поставщик.ПартииТоваровНаСкладах.Остатки. Измерение ДокументОприходования содержит ссылку на документ поступления, из которого мы получаем реквизит Контрагент.СерииНоменклатуры или подчиненных регистрах сведений.Часто в разных магазинах (подразделениях или торговых точках) действуют разные розничные цены на один и тот же товар. В типовых конфигурациях подразделение напрямую не входит в регистр ЦеныНоменклатуры.
Разберем логику связывания данных по шагам:
Склады с признаком розничного склада (АТТ или НТТ).ТипЦенРозничнойТорговли (или ТипЦен).ЦеныНоменклатуры.СрезПоследних сразу по двум полям: по номенклатуре и по типу цен склада.Рассмотрим комплексный пример запроса, объединяющего остатки, характеристики, розничные цены магазинов и отбор по поставщику:
ВЫБРАТЬ
ОстаткиТоваров.Склад КАК Магазин,
ОстаткиТоваров.Номенклатура.Артикул КАК Артикул,
ОстаткиТоваров.Номенклатура КАК Номенклатура,
ОстаткиТоваров.Номенклатура.ОсновнойПоставщик КАК ОсновнойПоставщик,
ОстаткиТоваров.СерияНоменклатуры.ювРазмер КАК Размер,
ОстаткиТоваров.СерияНоменклатуры.ювВес КАК Вес,
ОстаткиТоваров.СерияНоменклатуры.ювШтрихкодПоставщика КАК Штрихкод,
ОстаткиТоваров.КоличествоОстаток КАК Количество,
ЕСТЬNULL(ЦеныСрез.Валюта, ЗНАЧЕНИЕ(Справочник.Валюты.ПустаяСсылка)) КАК Валюта,
ЕСТЬNULL(ЦеныСрез.Цена, 0) КАК РознЦена
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(
&Период,
{Склад.* КАК Магазин, Номенклатура.* КАК Номенклатура}
) КАК ОстаткиТоваров
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
&Период,
{Номенклатура.* КАК Номенклатура}
) КАК ЦеныСрез
ПО ОстаткиТоваров.Номенклатура = ЦеныСрез.Номенклатура
И ОстаткиТоваров.Склад.ТипЦенРозничнойТорговли = ЦеныСрез.ТипЦен
{ГДЕ
ОстаткиТоваров.Склад.* КАК Магазин,
ОстаткиТоваров.Номенклатура.ОсновнойПоставщик.* КАК Поставщик,
ОстаткиТоваров.Номенклатура.* КАК Номенклатура}
Для обеспечения высокой скорости формирования отчета и исключения блокировок базы данных учтем следующие правила:
ГДЕ после соединения, если их можно передать в параметры таблиц Остатки() и СрезПоследних(). Это предотвратит чтение избыточных записей из базы.ЛЕВОЕ СОЕДИНЕНИЕ обязательно оборачивайте числовые и ссылочные поля цен в функцию ЕСТЬNULL(), чтобы избежать пустых ячеек в результирующей таблице.Номенклатура и Склад.