Читайте дальше...
Базовый запрос к виртуальной таблице оборотов регистра накопления
// Получение оборотов по регистру накопления за период
Процедура ПолучитьОборотыТоваров()
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Обороты.Номенклатура,
| Обороты.Склад,
| Обороты.КоличествоОборот КАК Количество,
| Обороты.СуммаОборот КАК Сумма
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Обороты(&ДатаНачала, &ДатаОкончания) КАК Обороты
|ГДЕ
| Обороты.КоличествоОборот > 0";
Запрос.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("ДатаОкончания", ТекущаяДата());
Результат = Запрос.Выполнить().Выгрузить();
Сообщить("Обороты за период:");
Для Каждого Строка Из Результат Цикл
Сообщить(Строка.Номенклатура + " | " + Строка.Склад +
" | кол-во: " + Строка.Количество +
" | сумма: " + Строка.Сумма);
КонецЦикла;
КонецПроцедуры
Обороты с разделением по видам движения
// Получение приходных и расходных оборотов отдельно
Процедура ПолучитьОборотыПоВидамДвижения()
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Обороты.Номенклатура,
| СУММА(ВЫБОР КОГДА Обороты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
| ТОГДА Обороты.КоличествоОборот
| ИНАЧЕ 0 КОНЕЦ) КАК ПриходКол,
| СУММА(ВЫБОР КОГДА Обороты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
| ТОГДА Обороты.СуммаОборот
| ИНАЧЕ 0 КОНЕЦ) КАК ПриходСумм,
| СУММА(ВЫБОР КОГДА Обороты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)
| ТОГДА Обороты.КоличествоОборот
| ИНАЧЕ 0 КОНЕЦ) КАК РасходКол,
| СУММА(ВЫБОР КОГДА Обороты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)
| ТОГДА Обороты.СуммаОборот
| ИНАЧЕ 0 КОНЕЦ) КАК РасходСумм
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Обороты(&ДатаНачала, &ДатаОкончания,) КАК Обороты
|СГРУППИРОВАТЬ ПО
| Обороты.Номенклатура";
Запрос.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("ДатаОкончания", ТекущаяДата());
Результат = Запрос.Выполнить().Выгрузить();
Сообщико("Обороты с разделением по приходу и расходу:");
Для Каждого Строка Из Результат Цикл
Сообщить(Строка.Номенклатура +
" | Приход: " + Строка.ПриходКол + " (" + Строка.ПриходСумм + ")" +
" | Расход: " + Строка.РасходКол + " (" + Строка.РасходСумм + ")");
КонецЦикла;
КонецПроцедуры
Обороты с отбором по измерениям
// Получение оборотов по конкретному складу и товару
Процедура ПолучитьОборотыПоСкладуИТовару()
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Обороты.Номенклатура,
| Обороты.Склад,
| Обороты.ВидДвижения,
| Обороты.КоличествоОборот КАК Количество,
| Обороты.СуммаОборот КАК Сумма
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Обороты(&ДатаНачала, &ДатаОкончания, Склад = &Склад) КАК Обороты
|ГДЕ
| Обороты.Номенклатура = &Номенклатура";
Запрос.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("ДатаОкончания", ТекущаяДата());
Запрос.УстановитьПараметр("Склад", Справочники.Склады.НайтиПоНаименованию("Основной склад"));
Запрос.УстановитьПараметр("Номенклатура", Справочники.Номенклатура.НайтиПоНаименованию("Ноутбук"));
Результат = Запрос.Выполнить().Выгрузить();
Для Каждого Строка Из Результат Цикл
Вид = ?(Строка.ВидДвижения = ВидДвиженияНакопления.Приход, "Приход", "Расход");
Сообщить(Вид + ": " + Строка.Количество + " шт. на сумму " + Строка.Сумма);
КонецЦикла;
КонецПроцедуры
Обороты с детализацией по регистраторам
// Получение оборотов с детализацией по документам-регистраторам
Процедура ПолучитьОборотыСДетализациейПоДокументам()
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Обороты.Регистратор,
| Обороты.Номенклатура,
| Обороты.ВидДвижения,
| Обороты.КоличествоОборот КАК Количество,
| Обороты.СуммаОборот КАК Сумма
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Обороты(&ДатаНачала, &ДатаОкончания,, Регистратор) КАК Обороты
|ГДЕ
| Обороты.Номенклатура = &Номенклатура
|УПОРЯДОЧИТЬ ПО
| Обороты.Регистратор";
Запрос.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("ДатаОкончания", ТекущаяДата());
Запрос.УстановитьПараметр("Номенклатура", Справочники.Номенклатура.НайтиПоНаименованию("Ноутбук"));
Результат = Запрос.Выполнить().Выгрузить();
Сообщить("Движения товара по документам:");
Для Каждого Строка Из Результат Цикл
Вид = ?(Строка.ВидДвижения = ВидДвиженияНакопления.Приход, "Приход", "Расход");
Сообщико(Строка.Регистратор + " | " + Вид +
" | " + Строка.Количество + " шт. | " + Строка.Сумма);
КонецЦикла;
КонецПроцедуры
Обороты по периодам (день, неделя, месяц)
// Получение оборотов с группировкой по периодам
Процедура ПолучитьОборотыПоПериодам()
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| ВЫРАЗИТЬ(Обороты.Период КАК ДАТА) КАК Дата,
| НАЧАЛОНЕДЕЛИ(Обороты.Период) КАК Неделя,
| НАЧАЛОМЕСЯЦА(Обороты.Период) КАК Месяц,
| СУММА(ВЫБОР КОГДА Обороты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
| ТОГДА Обороты.СуммаОборот
| ИНАЧЕ 0 КОНЕЦ) КАК ПриходДень,
| СУММА(ВЫБОР КОГДА Обороты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)
| ТОГДА Обороты.СуммаОборот
| ИНАЧЕ 0 КОНЕЦ) КАК РасходДень
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Обороты(&ДатаНачала, &ДатаОкончания,) КАК Обороты
|СГРУППИРОВАТЬ ПО
| ВЫРАЗИТЬ(Обороты.Период КАК ДАТА),
| НАЧАЛОНЕДЕЛИ(Обороты.Период),
| НАЧАЛОМЕСЯЦА(Обороты.Период)
|УПОРЯДОЧИТЬ ПО
| Дата";
Запрос.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата())-30);
Запрос.УстановитьПараметр("ДатаОкончания", ТекущаяДата());
Результат = Запрос.Выполнить().Выгрузить();
Сообщико("Обороты по дням:");
Для Каждого Строка Из Результат Цикл
Сообщить(Строка.Дата + " | Приход: " + Строка.ПриходДень +
" | Расход: " + Строка.РасходДень);
КонецЦикла;
КонецПроцедуры
Обороты регистра бухгалтерии
// Получение оборотов по счетам бухгалтерского учета
Процедура ПолучитьОборотыБухгалтерии()
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Обороты.Счет КАК Счет,
| Обороты.Субконто1 КАК Субконто,
| Обороты.СуммаНачальныйОстаток КАК НачальныйОстаток,
| Обороты.СуммаОборотДебет КАК ОборотДебет,
| Обороты.СуммаОборотКредит КАК ОборотКредит,
| Обороты.СуммаКонечныйОстаток КАК КонечныйОстаток
|ИЗ
| РегистрБухгалтерии.Хозрасчет.Обороты(&ДатаНачала, &ДатаОкончания) КАК Обороты
|ГДЕ
| Обороты.СуммаОборотДебет <> 0 ИЛИ Обороты.СуммаОборотКредит <> 0";
Запрос.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("ДатаОкончания", ТекущаяДата());
Результат = Запрос.Выполнить().Выгрузить();
Сообщико("Бухгалтерские обороты за период:");
Для Каждого Строка Из Результат Цикл
Сообщить("Счет: " + Строка.Счет + ", субконто: " + Строка.Субконто +
" | Дебет: " + Строка.ОборотДебет +
" | Кредит: " + Строка.ОборотКредит +
" | Нач.ост: " + Строка.НачальныйОстаток +
" | Кон.ост: " + Строка.КонечныйОстаток);
КонецЦикла;
КонецПроцедуры
Объединение остатков и оборотов
// Получение начальных остатков, оборотов и конечных остатков в одном запросе
Процедура ПолучитьОстаткиИОбороты()
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| ВТ.Номенклатура,
| СУММА(ВТ.НачальныйОстаток) КАК НачальныйОстаток,
| СУММА(ВТ.Приход) КАК Приход,
| СУММА(ВТ.Расход) КАК Расход,
| СУММА(ВТ.НачальныйОстаток) + СУММА(ВТ.Приход) - СУММА(ВТ.Расход) КАК КонечныйОстаток
|ИЗ
| (ВЫБРАТЬ
| Остатки.Номенклатура,
| Остатки.Количество КАК НачальныйОстаток,
| 0 КАК Приход,
| 0 КАК Расход
| ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаНачала) КАК Остатки
|
| ОБЪЕДИНИТЬ ВСЕ
|
| ВЫБРАТЬ
| Обороты.Номенклатура,
| 0 КАК НачальныйОстаток,
| ВЫБОР КОГДА Обороты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
| ТОГДА Обороты.КоличествоОборот
| ИНАЧЕ 0 КОНЕЦ КАК Приход,
| ВЫБОР КОГДА Обороты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)
| ТОГДА Обороты.КоличествоОборот
| ИНАЧЕ 0 КОНЕЦ КАК Расход
| ИЗ
| РегистрНакопления.ТоварыНаСкладах.Обороты(&ДатаНачала, &ДатаОкончания,) КАК Обороты
| ) КАК ВТ
|СГРУППИРОВАТЬ ПО
| ВТ.Номенклатура
|ИМЕЮЩИЕ
| СУММА(ВТ.НачальныйОстаток) + СУММА(ВТ.Приход) - СУММА(ВТ.Расход) <> 0";
Запрос.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("ДатаОкончания", ТекущаяДата());
Результат = Запрос.Выполнить().Выгрузить();
Сообщико("Остатки и обороты по товарам:");
Для Каждого Строка Из Результат Цикл
Сообщить(Строка.Номенклатура +
" | Нач.ост: " + Строка.НачальныйОстаток +
" | Приход: " + Строка.Приход +
" | Расход: " + Строка.Расход +
" | Кон.ост: " + Строка.КонечныйОстаток);
КонецЦикла;
КонецПроцедуры
Обороты с использованием временных таблиц
// Сложный анализ оборотов через временные таблицы
Процедура АнализОборотовЧерезВременныеТаблицы()
МенеджерВТ = Новый МенеджерВременныхТаблиц;
// Шаг 1: получаем обороты по товарам
Запрос1 = Новый Запрос;
Запрос1.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос1.Текст = "
|ВЫБРАТЬ
| Обороты.Номенклатура,
| СУММА(ВЫБОР КОГДА Обороты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
| ТОГДА Обороты.СуммаОборот
| ИНАЧЕ 0 КОНЕЦ) КАК СуммаПрихода,
| СУММА(ВЫБОР КОГДА Обороты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)
| ТОГДА Обороты.СуммаОборот
| ИНАЧЕ 0 КОНЕЦ) КАК СуммаРасхода
|ПОМЕСТИТЬ ВТ_ОборотыПоТоварам
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Обороты(&ДатаНачала, &ДатаОкончания,) КАК Обороты
|СГРУППИРОВАТЬ ПО
| Обороты.Номенклатура";
Запрос1.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата()));
Запрос1.УстановитьПараметр("ДатаОкончания", ТекущаяДата());
Запрос1.Выполнить();
// Шаг 2: добавляем информацию о товарах
Запрос2 = Новый Запрос;
Запрос2.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос2.Текст = "
|ВЫБРАТЬ
| Номенклатура.Ссылка КАК Товар,
| Номенклатура.Наименование,
| Номенклатура.Цена КАК Цена,
| ВТ_ОборотыПоТоварам.СуммаПрихода,
| ВТ_ОборотыПоТоварам.СуммаРасхода,
| ВТ_ОборотыПоТоварам.СуммаПрихода - ВТ_ОборотыПоТоварам.СуммаРасхода КАК Сальдо
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ОборотыПоТоварам КАК ВТ_ОборотыПоТоварам
| ПО Номенклатура.Ссылка = ВТ_ОборотыПоТоварам.Номенклатура
|ГДЕ
| Номенклатура.ЭтоГруппа = ЛОЖЬ
| И ВТ_ОборотыПоТоварам.СуммаПрихода <> 0";
Результат = Запрос2.Выполнить().Выгрузить();
Сообщико("Анализ оборотов с информацией о товарах:");
Для Каждого Строка Из Результат Цикл
Сообщить(Строка.Наименование + " (цена " + Строка.Цена + ")" +
" | Приход: " + Строка.СуммаПрихода +
" | Расход: " + Строка.СуммаРасхода +
" | Сальдо: " + Строка.Сальдо);
КонецЦикла;
КонецПроцедуры
Обороты с расчетом среднего чека
// Расчет среднего чека и количества операций на основе оборотов
Процедура РассчитатьСреднийЧек()
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Обороты.Регистратор,
| ВЫРАЗИТЬ(Обороты.Регистратор КАК Документ.РеализацияТоваров) КАК Документ,
| СУММА(Обороты.СуммаОборот) КАК СуммаДокумента,
| СУММА(Обороты.КоличествоОборот) КАК КоличествоТоваров
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Обороты(&ДатаНачала, &ДатаОкончания,, Регистратор) КАК Обороты
|ГДЕ
| Обороты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)
|СГРУППИРОВАТЬ ПО
| Обороты.Регистратор,
| ВЫРАЗИТЬ(Обороты.Регистратор КАК Документ.РеализацияТоваров)";
Запрос.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("ДатаОкончания", ТекущаяДата());
Результат = Запрос.Выполнить().Выгрузить();
// Вычисляем общие показатели
ОбщаяСумма = 0;
ОбщееКоличествоДокументов = Результат.Количество();
Для Каждого Строка Из Результат Цикл
ОбщаяСумма = ОбщаяСумма + Строка.СуммаДокумента;
КонецЦикла;
СреднийЧек = ?(ОбщееКоличествоДокументов > 0,
ОбщаяСумма / ОбщееКоличествоДокументов, 0);
Сообщить("Анализ продаж за период:");
Сообщить("Количество документов: " + ОбщееКоличествоДокументов);
Сообщить("Общая сумма продаж: " + ОбщаяСумма);
Сообщить("Средний чек: " + СреднийЧек);
// Выводим топ-5 документов по сумме
Результат.Сортировать("СуммаДокумента УБЫВ");
Сообщить("Топ-5 документов по сумме:");
Для Инд = 0 По Мин(4, Результат.Количество() - 1) Цикл
Строка = Результат[Инд];
Сообщить(Строка.Документ + ": " + Строка.СуммаДокумента);
КонецЦикла;
КонецПроцедуры
Обороты с динамическим периодом
// Получение оборотов за произвольный период с автоматическим определением границ
Функция ПолучитьОборотыЗаПериод(ПериодТип, Товар = Неопределено)
// Определяем границы периода
ТекущаяДата = ТекущаяДата();
Если ПериодТип = "День" Тогда
ДатаНачала = НачалоДня(ТекущаяДата);
ДатаОкончания = КонецДня(ТекущаяДата);
ИначеЕсли ПериодТип = "Неделя" Тогда
ДатаНачала = НачалоНедели(ТекущаяДата);
ДатаОкончания = КонецНедели(ТекущаяДата);
ИначеЕсли ПериодТип = "Месяц" Тогда
ДатаНачала = НачалоМесяца(ТекущаяДата);
ДатаОкончания = КонецМесяца(ТекущаяДата);
ИначеЕсли ПериодТип = "Квартал" Тогда
ДатаНачала = НачалоКвартала(ТекущаяДата);
ДатаОкончания = КонецКвартала(ТекущаяДата);
ИначеЕсли ПериодТип = "Год" Тогда
ДатаНачала = НачалоГода(ТекущаяДата);
ДатаОкончания = КонецГода(ТекущаяДата);
Иначе
Возврат Неопределено;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Обороты.Номенклатура,
| СУММА(ВЫБОР КОГДА Обороты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
| ТОГДА Обороты.КоличествоОборот
| ИНАЧЕ 0 КОНЕЦ) КАК ПриходКол,
| СУММА(ВЫБОР КОГДА Обороты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
| ТОГДА Обороты.СуммаОборот
| ИНАЧЕ 0 КОНЕЦ) КАК ПриходСумм,
| СУММА(ВЫБОР КОГДА Обороты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)
| ТОГДА Обороты.КоличествоОборот
| ИНАЧЕ 0 КОНЕЦ) КАК РасходКол,
| СУММА(ВЫБОР КОГДА Обороты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)
| ТОГДА Обороты.СуммаОборот
| ИНАЧЕ 0 КОНЕЦ) КАК РасходСумм
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Обороты(&ДатаНачала, &ДатаОкончания,) КАК Обороты";
// Добавляем условие по товару, если нужно
Если Товар <> Неопределено Тогда
Запрос.Текст = Запрос.Текст + "
|ГДЕ
| Обороты.Номенклатура = &Товар";
Запрос.УстановитьПараметр("Товар", Товар);
КонецЕсли;
Запрос.Текст = Запрос.Текст + "
|СГРУППИРОВАТЬ ПО
| Обороты.Номенклатура";
Запрос.УстановитьПараметр("ДатаНачала", ДатаНачала);
Запрос.УстановитьПараметр("ДатаОкончания", ДатаОкончания);
Результат = Запрос.Выполнить().Выгрузить();
Возврат Результат;
КонецФункции
// Пример использования
Процедура ТестДинамическогоПериода()
// Получаем обороты за текущий месяц
ОборотыЗаМесяц = ПолучитьОборотыЗаПериод("Месяц");
Сообщить("Обороты за текущий месяц:");
Для Каждого Строка Из ОборотыЗаМесяц Цикл
Сообщить(Строка.Номенклатура +
" | Приход: " + Строка.ПриходКол + " (" + Строка.ПриходСумм + ")" +
" | Расход: " + Строка.РасходКол + " (" + Строка.РасходСумм + ")");
КонецЦикла;
// Получаем обороты по конкретному товару за неделю
Товар = Справочники.Номенклатура.НайтиПоНаименованию("Ноутбук");
Если Товар <> Неопределено Тогда
ОборотыПоТовару = ПолучитьОборотыЗаПериод("Неделя", Товар);
// Обработка результата...
КонецЕсли;
КонецПроцедуры
Примечания
// Важные особенности работы с виртуальными таблицами оборотов:
// 1. Виртуальная таблица Обороты рассчитывает итоги по движениям за указанный период
// 2. Синтаксис: РегистрНакопления.ИмяРегистра.Обороты(<ДатаНачала>, <ДатаОкончания>, <ОтборПоИзмерениям>, <Детализация>)
// 3. Параметр <ОтборПоИзмерениям> позволяет фильтровать данные на уровне СУБД (оптимально)
// 4. Параметр <Детализация> задает разрезы: Период, Регистратор, Измерения
// 5. Для регистров бухгалтерии доступны поля СуммаОборотДебет и СуммаОборотКредит
// 6. Обороты не включают начальные остатки, только движения за период
// 7. Для расчета конечных остатков нужно объединять Остатки и Обороты
// 8. При указании детализации по Регистратору можно получить документы-движения
// 9. Виртуальная таблица Обороты оптимальна для построения отчетов и анализа движения
// 10. При работе с большими периодами рекомендуется использовать отборы по измерениям
// 11. Для регистров сведений виртуальная таблица Обороты недоступна
// 12. Типовые конфигурации могут иметь расширенные возможности виртуальных таблиц оборотов








