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