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