Получение актуальной цены номенклатуры на дату в 1С: СрезПоследних, соединения и СКД

Устали искать цену номенклатуры на дату? Разбираем СрезПоследних, СКД и джойны регистров — чтобы отчеты строил за секунды, а не часы.

Бесплатная консультация юриста

+7 (800) 301-07-30

Реклама jurik.ru

Получение актуальной цены номенклатуры на определенную дату — одна из самых частых задач при разработке отчетов‚ обработок и документов в 1С. В этой статье подробно разберем основные подходы: использование виртуальных таблиц СрезПоследних‚ соединение таблиц продаж и цен‚ а также особенности работы в СКД (Системе компоновки данных).

Основные источники данных о ценах

В типовых конфигурациях (УТ 11‚ ERP‚ КА 2‚ Розница) цены обычно хранятся в регистрах сведений:

  • ЦеныНоменклатуры — основной регистр цен (периодический‚ измерения: Номенклатура‚ ВидЦены‚ Характеристика и др.).
  • ЦеныТоваров — регистр для розничных цен (часто используется в Рознице).
  • Табличные части документов ПоступлениеТоваровУслуг‚ РеализацияТоваровУслуг — для получения цен конкретного документа.

Способ 1: Виртуальная таблица СрезПоследних (Самый частый сценарий)

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

Пример запроса: Получение цены на конкретную дату

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

Параметры:

  • &Дата, дата‚ на которую нужна цена (обычно ДатаДокумента или ТекущаяДата).
  • &ВидЦены — ссылка на вид цены (Розница‚ Опт‚ Закупка и т.д.).
  • &СписокНоменклатуры — список товаров для отбора (для производительности).

Важный нюанс: Характеристики номенклатуры

Если номенклатура имеет характеристики (размер‚ цвет‚ модификация)‚ в запрос обязательно нужно добавить измерение Характеристика в выборку и в условие отбора‚ иначе запрос вернет цену для «пустой» характеристики или произвольную строку.

Способ 2: Цена на каждую дату продажи (Для отчетов динамики)

Если нужно построить отчет «Продажи с ценой на дату каждой продажи»‚ простого среза последних недостаточно — нужно соединить таблицу продаж с регистром цен по условию «ДатаЦены <= ДатаПродажи» и взять максимальную дату цены для каждой продажи.

Алгоритм (часто используется в СКД):

  1. Получаем таблицу продаж (Период‚ Товар‚ Характеристика‚ Количество…).
  2. Левое соединение с регистром Цены по Товар‚ Характеристика‚ ВидЦены И Цены.Период <= Продажи.Период.
  3. Группировка по строке продажи + МАКСИМУМ(Цены.Период) — находим дату последней актуальной цены.
  4. Вторичное соединение (или вложенный запрос) для получения самой Цены по найденной максимальной дате.

Пример структуры запроса для СКД (Два набора данных):

Набор 1 (Источник — Продажи):

ВЫБРАТЬ
 Продажи.Период КАК ПериодПродажи‚
 Продажи.Номенклатура КАК Номенклатура‚
 Продажи.Характеристика КАК Характеристика‚
 Продажи.Количество КАК Количество
ИЗ
 РегистрНакопления.Продажи КАК Продажи
ГДЕ
 Продажи.Период МЕЖДУ &НачалоПериода И &КонецПериода

Набор 2 (Приемник — Цены‚ параметр — ДатаПродажи):

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

В СКД настройка «Параметры данных» связывает поле ПериодПродажи из Набора 1 с параметром &ДатаПродажи Набора 2.

Способ 3: Получение цены из табличной части документа (Поступление/Реализация)

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

Пример: Цена из документа ПоступлениеТоваровУслуг

ВЫБРАТЬ
 ПоступлениеТовары.Номенклатура КАК Номенклатура‚
 ПоступлениеТовары.Характеристика КАК Характеристика‚
 ПоступлениеТовары.Цена КАК ЦенаЗакупки‚
 ПоступлениеТовары.Количество КАК Количество
ИЗ
 Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТовары
ГДЕ
 ПоступлениеТовары.Ссылка = &СсылкаНаДокумент

Проблема задвоения строк (Несколько документов за один день)

Если за один день по одному товару прошло несколько поступлений‚ простой запрос даст несколько строк. Чтобы получить последнюю цену за день‚ используют подзапрос с МАКСИМУМ(НомерСтроки) или МАКСИМУМ(Период) (если есть секундная точность).

ВЫБРАТЬ
 ВТ_ПоследнийДокумент.Номенклатура‚
 ВТ_ПоследнийДокумент.Характеристика‚
 ВТ_ПоследнийДокумент.Цена
ИЗ
 (ВЫБРАТЬ
 ПоступлениеТовары.Номенклатура КАК Номенклатура‚
 ПоступлениеТовары.Характеристика КАК Характеристика‚
 МАКСИМУМ(ПоступлениеТовары.НомерСтроки) КАК МаксНомерСтроки
 ИЗ
 Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТовары
 ГДЕ
 ПоступлениеТовары.Ссылка.Дата = &ДатаДок
 И ПоступлениеТовары.Номенклатура В &СписокТоваров
 СГРУППИРОВАТЬ ПО
 ПоступлениеТовары.Номенклатура‚
 ПоступлениеТовары.Характеристика) КАК ВТ_Ключи
ВНУТРЕННЕЕ СОЕДИНЕНИЕ
 Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТовары
ПО
 ВТ_Ключи.Номенклатура = ПоступлениеТовары.Номенклатура
 И ВТ_Ключи.Характеристика = ПоступлениеТовары.Характеристика
 И ВТ_Ключи.МаксНомерСтроки = ПоступлениеТовары.НомерСтроки

Способ 4: Программное получение цены на сервере (Для форм/обработок)

Частая задача: при выборе номенклатуры в форме документа автоматически подставить цену.

Клиентская процедура (ПриИзменении):

&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
 СтрокаТЧ = Элементы.Товары.ТекущиеДанные;
 Если СтрокаТЧ = Неопределено Тогда Возврат; КонецЕсли;
  // Асинхронный вызов сервера
 ПолучитьЦенуНаСервере(СтрокаТЧ.Номенклатура‚ СтрокаТЧ.Характеристика‚ Объект.ВидЦены‚ Объект.Дата);
КонецПроцедуры

Серверная функция:

&НаСервере
Функция ПолучитьЦенуНаСервере(Номенклатура‚ Характеристика‚ ВидЦены‚ Дата)
 Запрос = Новый Запрос;
 Запрос.Текст = 
 "ВЫБРАТЬ ПЕРВЫЕ 1
 | ЦеныНоменклатурыСрезПоследних.Цена КАК Цена
 |ИЗ
 | РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата‚ ВидЦены = &ВидЦены 
 | И Номенклатура = &Номенклатура 
 | И Характеристика = &Характеристика) КАК ЦеныНоменклатурыСрезПоследних";
 
 Запрос.УстановитьПараметр("Дата"‚ Дата);
 Запрос.УстановитьПараметр("ВидЦены"‚ ВидЦены);
 Запрос.УстановитьПараметр("Номенклатура"‚ Номенклатура);
 Запрос.УстановитьПараметр("Характеристика"‚ Характеристика);
 
 Результат = Запрос.Выполнить.Выбрать;
 Если Результат.Следующий Тогда
 Возврат Результат.Цена;
 КонецЕсли;
 Возврат 0;
КонецФункции

Типичные ошибки и лучшие практики

  • Игнорирование Характеристики: Всегда добавляйте Характеристику в измерения соединения и отборы‚ если конфигурация их использует.
  • Отсутствие ВидаЦены: В регистре ЦеныНоменклатуры ВидЦены — измерение. Без отбора по нему запрос вернет цены по всем видам сразу (задвоение строк).
  • Производительность СрезПоследних: Всегда передавайте условие отбора по Номенклатуре (И Номенклатура В &Список) во второй параметр виртуальной таблицы. Это позволяет СУБД использовать индексы эффективно.
  • Пустые ссылки: Используйте ЕСТЬNULL(Цена‚ 0) в запросе или проверку на клиенте‚ чтобы избежать ошибок «Поле не найдено» или нулевых цен в расчетах.
  • Кеширование: В циклах (например‚ заполнение ТЧ) не выполняйте запрос на каждой итерации. Соберите массив номенклатуры и сделайте один запрос с условием В &МассивНоменклатуры‚ затем разберите результат в соответствие (Map).

Резюме: какой способ выбрать?

Задача Рекомендуемый метод
Цена на текущий момент / на дату документа (один товар или список) СрезПоследних(&Дата‚ Условие), самый быстрый и правильный.
Отчет «Продажи с ценой на дату продажи» (много строк) СКД: 2 набора данных (Продажи -> Параметр Дата -> СрезПоследних Цен) или Один запрос с МАКСИМУМ(Период).
Цена конкретного документа (Закупка/Реализация) Чтение Табличной части документа (Документ.Имя.Товары).
Автозаполнение цены в форме выбора товара Серверная функция + СрезПоследних + асинхронный вызов с клиента.

Грамотное использование виртуальных таблиц регистров сведений и понимание механизма «Среза последних», ключ к быстрым и надежным отчетам и обработкам в 1С.