К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как проверить вид движения в запросе 1С

Разбираем, как проверить вид движения в запросе 1С: работа с ВидДвиженияНакопления, ВидДвиженияБухгалтерии, условиями ГДЕ и виртуальными таблицами регистров.

Вид движения — системное свойство записей регистров 1С, которое показывает, приходная это операция или расходная (для регистров накопления), дебетовая или кредитовая (для регистров бухгалтерии). Проверка вида движения в запросе нужна постоянно: при формировании отчётов по оборотам, при анализе проводок документа, при поиске «лишних» движений после перепроведения.

Главная сложность в том, что вид движения — это перечисление, и сравнивать его нужно не строкой «Приход» или «Расход», а через значение перечисления, полученное с помощью функции ЗНАЧЕНИЕ(). Ошибка в этом месте — самая частая причина «пустых» результатов запроса, когда разработчик уверен, что данные в базе есть.

Ниже разобраны практические приёмы: как отфильтровать записи по виду движения, как вывести его в результат, как работать с виртуальными таблицами оборотов, где вид движения вообще не хранится, и какие ошибки чаще всего встречаются у начинающих разработчиков.

Какие виды движения существуют в 1С

Прежде чем писать условие, нужно понимать, с каким именно перечислением вы работаете. В 1С:Предприятии их два, и они не взаимозаменяемы.

Для регистров накопления с видом «Остатки» используется перечисление ВидДвиженияНакопления со значениями Приход и Расход. Каждая запись физической таблицы регистра обязательно содержит это поле — без него запись просто не может существовать.

Для регистров бухгалтерии применяется перечисление ВидДвиженияБухгалтерии со значениями Дебет и Кредит. Важно: в самой таблице движений регистра бухгалтерии отдельного поля «ВидДвижения» нет — дебетовая или кредитовая природа проводки определяется счётом дебета и счётом кредита. Перечисление ВидДвиженияБухгалтерии в основном используется в коде, например при программном формировании проводок или в функциях вроде Обороты() встроенного языка.

Регистры сведений и регистры накопления с видом «Обороты» вообще не имеют вида движения — там каждая запись самодостаточна, и проверять нечего.

Как отфильтровать записи по виду движения через ГДЕ

Базовый сценарий — выбрать только приходные или только расходные записи регистра накопления. Условие пишется в секции ГДЕ с использованием конструкции ЗНАЧЕНИЕ():

ВЫБРАТЬ

Товары.Номенклатура,

Товары.Количество,

Товары.Регистратор

ИЗ

РегистрНакопления.ТоварыНаСкладах КАК Товары

ГДЕ

Товары.ВидДвижения = ЗНАЧЕНИЕ(Перечисление.ВидДвиженияНакопления.Приход)

Такой запрос вернёт только записи прихода. Замените Приход на Расход — получите расходные движения. Это удобно, когда нужно, например, построить отчёт «все поступления товара за период» без обращения к документам.

Если нужно исключить один вид движения, используйте оператор неравенства:

ГДЕ

Товары.ВидДвижения <> ЗНАЧЕНИЕ(Перечисление.ВидДвиженияНакопления.Расход)

Условие по виду движения можно комбинировать с отбором по периоду, регистратору и измерениям через И. Порядок условий на результат не влияет, но для читаемости отбор по периоду обычно ставят первым.

bsl
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Движения.Номенклатура КАК Номенклатура,
| СУММА(Движения.Количество) КАК Количество
|ИЗ
| РегистрНакопления.ТоварыНаСкладах КАК Движения
|ГДЕ
| Движения.ВидДвижения = ЗНАЧЕНИЕ(Перечисление.ВидДвиженияНакопления.Приход)
|СГРУППИРОВАТЬ ПО
| Движения.Номенклатура";
Результат = Запрос.Выполнить().Выгрузить();

Как вывести вид движения в результат запроса

Иногда фильтровать не нужно — достаточно показать вид движения как колонку, например в аналитическом отчёте по движениям документа. Поле ВидДвижения выбирается как обычное поле таблицы:

ВЫБРАТЬ

Движения.ВидДвижения КАК ВидДвижения,

Движения.Номенклатура,

Движения.Количество

ИЗ

РегистрНакопления.ТоварыНаСкладах КАК Движения

В результате запроса колонка будет содержать ссылки на перечисление. При выводе в табличный документ или таблицу значений платформа автоматически покажет представление — «Приход» или «Расход». Если нужна именно строка для дальнейшей обработки, используйте функцию ПРЕДСТАВЛЕНИЕ():

ВЫБРАТЬ

ПРЕДСТАВЛЕНИЕ(Движения.ВидДвижения) КАК ВидДвиженияСтрокой

Для агрегирования удобен приём с ВЫБОР: суммировать приход и расход отдельными колонками, чтобы в одной строке видеть оборот по обоим направлениям. Это стандартный шаблон для отчётов типа «приход-расход-сальдо»:

ВЫБРАТЬ

Движения.Номенклатура,

СУММА(ВЫБОР

КОГДА Движения.ВидДвижения = ЗНАЧЕНИЕ(Перечисление.ВидДвиженияНакопления.Приход)

ТОГДА Движения.Количество ИНАЧЕ 0 КОНЕЦ) КАК Приход,

СУММА(ВЫБОР

КОГДА Движения.ВидДвижения = ЗНАЧЕНИЕ(Перечисление.ВидДвиженияНакопления.Расход)

ТОГДА Движения.Количество ИНАЧЕ 0 КОНЕЦ) КАК Расход

ИЗ

РегистрНакопления.ТоварыНаСкладах КАК Движения

СГРУППИРОВАТЬ ПО

Движения.Номенклатура

Конструкция ВЫБОР с разворотом прихода и расхода в отдельные колонки работает быстрее, чем два отдельных запроса с фильтрами, потому что таблица читается один раз. На больших регистрах разница заметна.
ПЗ
Практическое замечание

Как проверить вид движения через параметр запроса

Когда вид движения заранее неизвестен и задаётся из кода (например, пользователь выбирает на форме, что показать), значение передаётся через параметр. В этом случае условие выглядит так:

ГДЕ

Движения.ВидДвижения = &ВидДвижения

В коде параметр устанавливается через объект Перечисления:

Запрос.УстановитьПараметр("ВидДвижения", Перечисления.ВидДвиженияНакопления.Расход);

Типичная ошибка — передать в параметр строку "Расход" вместо значения перечисления. Запрос при этом не упадёт с ошибкой, но не вернёт ни одной записи, потому что строка никогда не равна ссылке на перечисление. Если запрос «молча» возвращает пустоту — первым делом проверяйте тип параметра.

Второй рабочий вариант — передать в запрос массив или список значений с несколькими видами движения и использовать оператор В. Для видов движения это редко нужно (значений всего два), но приём полезен для симметричных отборов по другим перечислениям.

Типичные ошибки
01
Сравнение со строкой: ВидДвижения = "Приход" — запрос не находит записей, так как поле хранит ссылку на перечисление
02
Передача строки в параметр вместо Перечисления.ВидДвиженияНакопления.Расход — пустой результат без сообщения об ошибке
03
Попытка обратиться к полю ВидДвижения в виртуальной таблице Обороты — ошибка построения запроса, поля там нет
04
Сравнение с перечислением другого типа, например ВидДвиженияБухгалтерии вместо ВидДвиженияНакопления

Почему в виртуальных таблицах нет вида движения

Виртуальные таблицы Остатки, Обороты и ОстаткиИОбороты строятся платформой как свёртка физических записей. Оборот — это уже сумма приходов или расходов за период, поэтому отдельного поля ВидДвижения там нет и быть не может. Попытка написать Обороты.ВидДвижения приведёт к ошибке «Поле не найдено».

В таблице Обороты направление движения зашито в имена полей ресурсов: КоличествоПриход, КоличествоРасход, СуммаОборот и так далее. Если нужен отдельно приход и расход — берите соответствующие поля, а не фильтруйте по виду движения:

ВЫБРАТЬ

Обороты.Номенклатура,

Обороты.КоличествоПриход,

Обороты.КоличествоРасход

ИЗ

РегистрНакопления.ТоварыНаСкладах.Обороты(&Начало, &Конец, , ) КАК Обороты

Правило выбора простое: если нужен анализ по отдельным записям (какой документ, когда, какое направление) — работайте с физической таблицей регистра и фильтруйте по ВидДвижения. Если нужны итоги за период — используйте виртуальные таблицы, они на порядки быстрее, потому что читают предрассчитанные итоги, а не все записи.

Сравнение вариантов

Физическая таблица регистра

Есть поле ВидДвижения, виден каждый регистратор. Подходит для анализа движений документов, но медленно на больших объёмах

Виртуальная таблица Обороты

Вида движения нет, приход и расход уже разнесены по полям ресурсов. Быстро, подходит для отчётов за период

Виртуальная таблица ОстаткиИОбороты

Даёт сальдо на начало и конец плюс обороты. Вид движения недоступен, но покрывает большинство задач отчётности

Как проверить вид движения для регистра бухгалтерии

С регистрами бухгалтерии ситуация иная: в таблице движений нет поля ВидДвижения, а направление проводки определяется заполненностью счёта дебета и счёта кредита. Поэтому «проверить вид движения» здесь означает проверить, какая сторона проводки заполнена.

На практике отбор по дебетовой стороне выглядит как условие на счёт дебета:

ВЫБРАТЬ

Проводки.СчетДт,

Проводки.СчетКт,

Проводки.Сумма

ИЗ

РегистрБухгалтерии.Хозрасчетный КАК Проводки

ГДЕ

Проводки.СчетДт = &Счет

Если нужно выбрать проводки, где счёт участвует в любом качестве — и по дебету, и по кредиту, — комбинируйте условия через ИЛИ. Для корреспонденций удобнее виртуальная таблица ОборотыДтКт, где стороны проводки уже являются измерениями.

Перечисление ВидДвиженияБухгалтерии при этом остаётся актуальным для встроенного языка: например, его значения принимают некоторые методы и параметры при программной работе с проводками. Но в тексте запроса к таблице движений регистра бухгалтерии оно не используется — искать там поле ВидДвижения бессмысленно.

Как проверить результат и отладить запрос

Самый быстрый способ убедиться, что условие по виду движения работает, — консоль запросов. В типовых конфигурациях она часто доступна как внешняя обработка, в режиме разработчика запрос проверяется прямо в модуле с выводом результата в таблицу значений.

Порядок отладки такой. Сначала выполните запрос вообще без условия по виду движения и убедитесь, что записи в регистре есть. Затем добавьте поле ВидДвижения в выборку и посмотрите фактические значения. После этого добавьте условие ГДЕ — если результат стал пустым, проблема в способе сравнения: строка вместо перечисления, неверное значение или отбор по несуществующему полю.

Дополнительная проверка — сгруппировать записи по виду движения и посчитать количество:

ВЫБРАТЬ

Движения.ВидДвижения,

КОЛИЧЕСТВО(*) КАК ЧислоЗаписей

ИЗ

РегистрНакопления.ТоварыНаСкладах КАК Движения

СГРУППИРОВАТЬ ПО

Движения.ВидДвижения

Такой запрос за секунды показывает, есть ли в регистре записи обоих видов и в каком соотношении. Если одна из строк отсутствует — значит, в базе просто нет движений этого направления, и пустой результат отфильтрованного запроса является нормой, а не ошибкой.

Контрольные точки

Как проверить результат

Запрос с условием ГДЕ по виду движения
Норма

Возвращает записи, в колонке ВидДвижения только выбранное значение

Тревожный признак

Пустой результат при заведомо существующих движениях — проверьте тип сравниваемого значения

Группировка по ВидДвижения
Норма

Две строки: Приход и Расход с количеством записей

Тревожный признак

Одна строка или ни одной — в регистре нет движений нужного направления

Обращение к виртуальной таблице
Норма

Используются поля ресурсов Приход/Расход

Тревожный признак

Ошибка «Поле не найдено» при обращении к ВидДвижения

Частые вопросы

Можно ли сравнить вид движения со строкой "Приход"?

Нет. Поле ВидДвижения хранит ссылку на значение перечисления, а не текст. Сравнение со строкой не вызовет ошибку, но никогда не выполнится, и запрос вернёт пустой результат. Используйте ЗНАЧЕНИЕ(Перечисление.ВидДвиженияНакопления.Приход) или параметр с типом перечисления.

Как получить вид движения в запросе к виртуальной таблице Обороты?

Никак — этого поля там нет, потому что данные уже свёрнуты. Направление движения отражено в именах полей ресурсов: КоличествоПриход, КоличествоРасход, СуммаПриход и так далее. Выбирайте нужные поля напрямую.

Почему запрос с условием по виду движения возвращает пустоту?

Чаще всего причины три: сравнение со строкой вместо значения перечисления, передача строки в параметр вместо Перечисления.ВидДвиженияНакопления или фактическое отсутствие записей нужного направления в регистре. Проверьте данные группировкой по ВидДвижения без фильтра.

Есть ли вид движения у регистра сведений?

Нет. Записи регистра сведений не имеют направления — это просто строки данных, привязанные к измерениям (и периоду, если регистр периодический). Проверять там нечего, условие по ВидДвижения вызовет ошибку построения запроса.

Как в запросе определить дебетовую или кредитовую сторону проводки?

В таблице движений регистра бухгалтерии поля ВидДвижения нет. Сторона проводки определяется полями СчетДт и СчетКт: отбирайте записи условием по нужному счёту дебета или кредита, либо используйте виртуальную таблицу ОборотыДтКт для анализа корреспонденций.

Что быстрее: фильтр по виду движения или виртуальная таблица?

Для итогов за период виртуальные таблицы быстрее, так как платформа читает предрассчитанные итоги. Фильтр по ВидДвижения в физической таблице оправдан, когда нужны отдельные записи с регистраторами и точными моментами времени — там виртуальные таблицы детализацию не дадут.

Итог

Что важно запомнить

Вид движения проверяется сравнением поля ВидДвижения со значением перечисления через ЗНАЧЕНИЕ() или параметр правильного типа — никогда строкой. В виртуальных таблицах и регистрах бухгалтерии этого поля нет: там используйте поля ресурсов Приход/Расход или счета Дт/Кт. Перед отладкой убедитесь группировкой, что записи нужного направления вообще есть в регистре.