Почему СрезПоследних в регистре цен номенклатуры не отбирает цены по единице измерения?

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

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

Выясним, почему так происходит, как устроена архитектура регистра и какими способами можно корректно получить цены с учетом единицы измерения или устранить проблемы с копеечными отклонениями.

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

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

В типовых конфигурациях (таких как «1С:Управление торговлей», «1С:Комплексная автоматизация» или «1С:УПП») реквизитный состав регистра сведений ЦеныНоменклатуры обычно настроен следующим образом:

  1. Измерения: Номенклатура, ХарактеристикаНоменклатуры, СерияНоменклатуры, ТипЦен (или ВидЦены).
  2. Ресурсы: Цена.
  3. Реквизиты/Ресурсы: ЕдиницаИзмерения, Валюта, ПроцентСкидкиНаценки.

Поскольку поле ЕдиницаИзмерения является ресурсом или реквизитом, а не измерением регистра, платформа не использует его в качестве уникального ключа при построении среза. В результате для одной комбинации Номенклатура + ТипЦен виртуальная таблица вернет строго одну запись — самую свежую по дате периода, полностью проигнорировав различия в единицах измерения.

Анализ запроса разработчика

Проанализируем пример запроса, который не дает ожидаемого результата:


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

В данном запросе, даже если в регистре записаны две цены на одну дату (одна в штуках, другая в килограммах), виртуальная таблица СрезПоследних вернет только ту запись, которая оказалась последней. Запись с другой единицей измерения будет проигнорирована.

Способ 1. Запрос к физической таблице с эмуляцией среза последних

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

Рассмотрим, как реализовать такой запрос с помощью временных таблиц:


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

ВЫБРАТЬ
	Цены.Номенклатура КАК Номенклатура,
	Цены.ТипЦен КАК ТипЦен,
	Цены.ЕдиницаИзмерения КАК ЕдиницаИзмерения,
	Цены.Цена КАК Цена
ИЗ
	ВТ_МаксимальныеДаты КАК МаксДаты
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК Цены
		ПО МаксДаты.Номенклатура = Цены.Номенклатура
			И МаксДаты.ТипЦен = Цены.ТипЦен
			И МаксДаты.ЕдиницаИзмерения = Цены.ЕдиницаИзмерения
			И МаксДаты.Период = Цены.Период

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

Способ 2. Расчет цены через коэффициенты пересчета

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

Посмотрим на формулу расчета цены за необходимую единицу:

ЦенаЗаЕдиницу = (БазоваяЦена * КоэффициентЦелевойЕдиницы) / КоэффициентБазовойЕдиницы

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

Способ 3. Решение проблемы копеечных отклонений в печатных формах

Часто необходимость получать цену за килограмм возникает из-за требований контрагентов выводить в накладных (ТОРГ-12, УПД) данные в весовых единицах, в то время как учет ведется в штуках. При обратном расчете цены (деление общей суммы на вес) нередко появляются расхождения в 1 копейку из-за округления.

Разберем методически верный подход к формированию печатной формы:

  1. Фиксация итоговой суммы: Сумма строки документа рассчитывается в первичных единицах учета (в штуках) и остается неизменной.
  2. Расчет цены для печатной формы: Для отображения цены за килограмм итоговая сумма строки делится на количество в килограммах прямо при заполнении табличного документа:
    ЦенаВПечатнойФорме = СуммаСтрокиДокумента / КоличествоВКилограммах

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

← На главную