Как получить последнюю актуальную цену номенклатуры в 1С:Розница 2.2 с учетом характеристик?

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

В конфигурации 1С:Розница 2.2 механизм ценообразования тесно связан с характеристиками товаров. Часто возникает ситуация, когда переоценка происходит не для всей номенклатуры целиком, а только для определенных партий или позиций (например, пришел новый размер обуви по другой цене). В результате в регистре сведений ЦеныНоменклатуры для одной и той же позиции могут храниться разные цены на разные характеристики. Перед разработчиком встает задача: как правильно вытянуть запросом именно актуальную цену, учитывая эти особенности.

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

Особенности хранения цен в 1С:Розница 2.2

Для начала проанализируем структуру хранения данных. Цены хранятся в периодическом регистре сведений ЦеныНоменклатуры. Измерениями регистра являются ВидЦены, Номенклатура и Характеристика. Если в настройках программы включено использование характеристик, то цена может устанавливаться как для пустой характеристики (общая цена на товар), так и для конкретной.

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

Решение 1. Прямое получение цен по характеристикам

Если нам необходимо получить цены в разрезе каждой характеристики, мы используем стандартное обращение к виртуальной таблице. Рассмотрим пример запроса, который позволяет получить последние цены для конкретной номенклатуры:


ВЫБРАТЬ
    ЦеныНоменклатурыСрезПоследних.Номенклатура КАК Номенклатура,
    ЦеныНоменклатурыСрезПоследних.Характеристика КАК Характеристика,
    ЦеныНоменклатурыСрезПоследних.Цена КАК Цена
ИЗ
    РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, ВидЦены = &ВидЦены И Номенклатура = &Номенклатура) КАК ЦеныНоменклатурыСрезПоследних

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

Решение 2. Получение «единой» последней цены для всей номенклатуры

Иногда бизнес-логика требует показать в отчете только одну «самую актуальную» цену товара, игнорируя различия в характеристиках. Например, если компания стремится к единой ценовой политике. В этом случае использование простого среза последних может быть недостаточно. Нам нужно найти запись с максимальной датой периода среди всех характеристик этой номенклатуры.

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

  1. Выбираем максимальный период из регистра для данной номенклатуры и вида цены.
  2. Соединяем полученный результат с физической таблицей регистра для получения значения цены.

Пример реализации такой логики в запросе:


ВЫБРАТЬ ПЕРВЫЕ 1
    ЦеныНоменклатурыСрезПоследних.Номенклатура КАК Номенклатура,
    ЦеныНоменклатурыСрезПоследних.Цена КАК Цена,
    ЦеныНоменклатурыСрезПоследних.Период КАК Период
ИЗ
    РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ВидЦены = &ВидЦены И Номенклатура = &Номенклатура) КАК ЦеныНоменклатурыСрезПоследних
УПОРЯДОЧИТЬ ПО
    Период УБЫВ

Внимание: использование конструкции ВЫБРАТЬ ПЕРВЫЕ 1 подходит только в том случае, если вы делаете запрос по одной конкретной позиции номенклатуры. Если позиций много, такой подход не сработает в рамках одного запроса.

Решение 3. Оптимизированный запрос для списка номенклатуры (через ВТ)

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

Разберем по шагам:

  1. Сначала мы помещаем интересующий нас список товаров во временную таблицу и обязательно индексируем поле Номенклатура.
  2. Затем обращаемся к виртуальной таблице СрезПоследних, передавая список номенклатуры в параметры таблицы. Это критически важно для производительности.

// Предположим, что ВТ_Товары уже создана и проиндексирована
ВЫБРАТЬ
    Цены.Номенклатура КАК Номенклатура,
    Цены.Характеристика КАК Характеристика,
    Цены.Цена КАК Цена,
    Цены.Период КАК Период
ИЗ
    РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
        &Период, 
        ВидЦены = &ВидЦены 
        И Номенклатура В (ВЫБРАТЬ ВТ.Номенклатура ИЗ ВТ_Товары КАК ВТ)
    ) КАК Цены

Проанализируем ситуацию: если в результате этого запроса по одной номенклатуре вышло несколько строк (из-за разных характеристик), а вам нужна только одна, можно применить дополнительную группировку «снаружи» запроса или использовать вложенный запрос для выбора МАКСИМУМ(Период).

Технические советы по оптимизации

Работа с ценами в 1С:Розница может замедляться при росте базы данных. Чтобы избежать зависаний отчетов, рекомендуем придерживаться следующих правил:

Использование программного метода

Если вам нужно получить цену программно (в коде модуля), а не в запросе, удобнее использовать встроенный метод регистра. Это работает быстрее для единичных получений данных:


СтруктураОтбора = Новый Структура;
СтруктураОтбора.Вставить("Номенклатура", ТекущийТовар);
СтруктураОтбора.Вставить("ВидЦены", НужныйВидЦены);
СтруктураОтбора.Вставить("Характеристика", ТекущаяХарактеристика);

ПоследниеДанные = РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(ТекущаяДата, СтруктураОтбора);
АктуальнаяЦена = ПоследниеДанные.Цена;

Этот метод оптимален, когда вы перебираете небольшое количество строк в цикле, хотя для массовой обработки данных запрос все равно остается предпочтительным. Выяснив причину различия цен в характеристиках и применив правильную фильтрацию в запросе, вы сможете построить точный и производительный отчет по ценам в «1С:Розница 2.2».

← На главную