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