Связка документов реализации и возвратов — одна из классических задач при построении аналитических отчетов в 1С. Основная сложность заключается в том, что возврат может произойти значительно позже реализации, выходя за рамки выбранного периода отчета. Кроме того, один документ возврата может содержать товары из нескольких разных реализаций.
В этой статье мы подробно разберем, как правильно составить запрос для получения данных о продажах и соответствующих им возвратах, рассмотрим различные подходы в зависимости от структуры метаданных и разберем нюансы оптимизации таких запросов.
Самый прямой способ получить данные — это обратиться непосредственно к документам. Проанализируем ситуацию: в документе ВозвратТоваровОтКлиента в табличной части Товары обычно присутствует реквизит ДокументПродажи (или ДокументРеализации). Именно по нему следует выполнять соединение, так как связь на уровне шапки документа может быть неточной, если возврат сборный.
Рассмотрим пример запроса, который выбирает возвраты за период и подтягивает к ним данные соответствующих реализаций:
ВЫБРАТЬ
ВозвратТовары.Ссылка КАК ДокументВозврата,
ВозвратТовары.Номенклатура КАК Номенклатура,
ВозвратТовары.Количество КАК КоличествоВозврат,
ВозвратТовары.Сумма КАК СуммаВозврат,
Реализация.Ссылка КАК ДокументРеализации,
Реализация.Дата КАК ДатаРеализации
ИЗ
Документ.ВозвратТоваровОтКлиента.Товары КАК ВозвратТовары
ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК Реализация
ПО ВозвратТовары.ДокументПродажи = Реализация.Ссылка
ГДЕ
ВозвратТовары.Ссылка.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
И ВозвратТовары.Ссылка.Проведен = ИСТИНА
Важный нюанс: как отмечалось в обсуждении, первичным объектом поиска лучше делать именно возврат. Если мы ищем возвраты по конкретным реализациям за период, логика меняется: мы выбираем реализации и левым соединением добавляем к ним возвраты, которые могут датироваться любым числом (даже за пределами периода реализации).
В современных конфигурациях (УТ 11, ERP, КА) для анализа финансовых результатов лучше использовать регистр ВыручкаИСебестоимостьПродаж. В нем информация о возвратах уже корректно сопоставлена с аналитикой продаж.
Проанализируем преимущества использования виртуальных таблиц оборотов регистра:
ДокументПродажи, что избавляет от необходимости соединять таблицы вручную.Рассмотрим пример запроса к регистру накопления:
ВЫБРАТЬ
ВыручкаОбороты.АналитикаУчетаНоменклатуры.Номенклатура КАК Номенклатура,
ВыручкаОбороты.ЗаказКлиента КАК Заказ,
ВыручкаОбороты.КоличествоОборот КАК Количество,
ВыручкаОбороты.ВыручкаОборот КАК Сумма
ИЗ
РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты(&НачалоПериода, &КонецПериода, , ) КАК ВыручкаОбороты
Выясним причину, по которой запрос к регистру ТоварыНаСкладах может быть неэффективным. Если в программе используется ордерная схема, то документ реализации только фиксирует финансовое обязательство, а фактическое списание товара со склада происходит документом РасходныйОрдерНаТовары. В этом случае в регистре ТоварыНаСкладах регистратором будет выступать ордер, а не реализация.
Если вам необходимо видеть именно движение физического товара, придется строить цепочку связей: Реализация -> Расходный Ордер -> Товары на складах. Однако для большинства управленческих отчетов достаточно данных из регистров продаж или документов реализации.
Часто возникает вопрос: как получить общую сумму документа, работая с его табличной частью? Рассмотрим два варианта:
ВозвратТовары.Ссылка.СуммаДокумента. Это удобно, но при левом соединении, если в документе 10 строк, сумма документа продублируется 10 раз. Это нужно учитывать при группировке.Сумма из табличной части Товары. Это более надежный метод для отчетов, где важна детализация по каждой позиции.Если стоит задача показать реализации за июль и все возвраты, которые по ним когда-либо были (даже в августе или сентябре), использование одного запроса с жестким периодом не подойдет. Проанализируем, как это решить в Системе компоновки данных (СКД):
Мы можем создать два набора данных:
РеализацияТоваровУслуг за выбранный пользователем период.ВозвратТоваровОтКлиента без ограничения по периоду (или с очень широким периодом), где ДокументПродажи входит в список ссылок из первого набора.Связь между наборами настраивается на закладке "Связи наборов данных" по полю Ссылка (из первого набора) и ДокументПродажи (из второго).
Посмотрим на ситуацию с точки зрения производительности. Поля ДокументПродажи или ДокументОснование в табличных частях документов в типовых конфигурациях 1С не всегда индексируются. Если база данных содержит сотни тысяч документов, прямой запрос к табличной части может выполняться очень долго.
Чтобы ускорить процесс, рекомендуется сначала отобрать ссылки на нужные реализации во временную таблицу, проиндексировать их, и только потом соединять с табличными частями возвратов:
// Помещаем реализации во временную таблицу
ВЫБРАТЬ
Реализация.Ссылка КАК Ссылка
ПОМЕСТИТЬ ВТ_Реализации
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
ИНДЕКСИРОВАТЬ ПО
Ссылка
;
// Соединяем с возвратами
ВЫБРАТЬ
ВозвратТовары.Ссылка КАК Возврат,
ВТ_Реализации.Ссылка КАК Реализация
ИЗ
ВТ_Реализации КАК ВТ_Реализации
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ВозвратТоваровОтКлиента.Товары КАК ВозвратТовары
ПО ВТ_Реализации.Ссылка = ВозвратТовары.ДокументПродажи
Подведем итоги: для решения задачи связки реализаций и возвратов всегда определяйте, что является "точкой входа". Если важен факт возврата — идите от возвратов к реализациям. Если важна судьба проданного товара — идите от реализаций, используя левое соединение или механизмы связей наборов данных в СКД. И всегда помните про проверку на пометку удаления и проведение документов, чтобы не включить в отчет мусорные данные.