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