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

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

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

Использование виртуальной таблицы «СрезПоследних»

Для получения актуальных сведений из периодического регистра сведений на заданную дату в платформе 1С предусмотрена виртуальная таблица СрезПоследних. Если необходимо получить цены для строк табличной части конкретного документа, обращение к виртуальной таблице РегистрСведений.ЦеныНоменклатуры.СрезПоследних с передачей даты документа в параметр периода является наиболее правильным и эффективным подходом.

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


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

Почему нельзя заменить срез последних условием по физической таблице

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

  1. Цена на номенклатуру была установлена документами ценообразования 8 августа.
  2. Документ продажи или поступления создается 10 августа.

Если написать запрос к физической таблице регистра с условием равенства дат (Период = &ДатаДокумента), запрос не вернет ни одной записи, так как 10 августа цены не менялись. Если же написать условие Период <= &ДатаДокумента, запрос вернет абсолютно все исторические записи по данной номенклатуре за все время до 10 августа, что приведет к дублированию строк в итоговом результате. Чтобы найти именно последнее значение, придется вручную группировать данные по максимальному периоду. Виртуальная таблица СрезПоследних делает эту работу автоматически на уровне СУБД.

Оптимизация производительности запросов

Разберем основные правила оптимизации при работе с регистром цен:

  1. Отбор в параметрах виртуальной таблицы. Передавайте условия по виду цен, номенклатуре и характеристикам прямо в параметры виртуальной таблицы (второй параметр среза), а не в секцию ГДЕ или условия соединения ПО. Если отбор не указан в параметрах таблицы, СУБД сформирует срез последних по всем существующим позициям в базе, что приведет к сильному падению скорости.
  2. Использование временных таблиц. Для больших табличных частей рекомендуется сначала поместить список позиций документа во временную таблицу, проиндексировать её и использовать список позиций в качестве фильтра при вызове среза.
  3. Обработка отсутствующих значений. Если для номенклатуры цена ранее никогда не устанавливалась, соединение вернет NULL. Обязательно используйте функцию ЕСТЬNULL(ТаблицаЦен.Цена, 0) для защиты от ошибок в последующих расчетах.
  4. Точность даты и объект «Граница». В параметре даты следует учитывать точное время документа. Если требуется исключить или включить цены, зафиксированные в ту же секунду, в коде программы вместо простой даты можно передавать объект Граница с указанием вида границы (ВидГраницы.Включая или ВидГраницы.Исключая).

Архитектурные особенности редакций «Управление торговлей»

При написании запросов важно брать во внимание версию конфигурации:

В конфигурации УТ 10.3 используется измерение ТипЦен, а периодичность регистра, как правило, составляет один день. Запрос к регистру сведений ЦеныНоменклатуры.СрезПоследних работает напрямую и возвращает зафиксированные значения.

В конфигурации УТ 11 ценообразование устроено сложнее. Измерение называется ВидЦены. Кроме того, виды цен могут быть динамическими (например, рассчитываемыми по формуле от базовой цены). Физических записей в регистре для таких цен не создается, поэтому прямой запрос к регистру сведений вернет пустое значение. Для УТ 11 при работе с произвольными видами цен рекомендуется использовать типовые программные модули ценообразования (например, ОбработкаТабличнойЧастиСервер.ЗаполнитьЦены... или программные функции получения цен).

← На главную