Почему запрос к оборотам регистра «Движения номенклатуры» с отбором по хозяйственной операции не возвращает данные?

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Управленческий учет IT и автоматизация бизнеса
← На главную

При разработке отчетов и обработок в конфигурациях на платформе «1С:Предприятие 8.3» (таких как «1С:ERP Управление предприятием» или «1С:Комплексная автоматизация») программисты часто сталкиваются с ситуацией, когда правильно написанный, на первый взгляд, запрос к виртуальной таблице оборотов возвращает пустой результат. Особенно часто это происходит при попытке наложить фильтр по измерению ХозяйственнаяОперация.

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

Причина 1. Неправильное наложение условий на виртуальную таблицу (ГДЕ vs Параметры)

Рассмотрим типичную ошибку начинающих разработчиков. Попытка наложить условие фильтрации через стандартное предложение ГДЕ после выбора данных из виртуальной таблицы:


ВЫБРАТЬ
    ДвиженияНоменклатураНоменклатураОбороты.АналитикаУчетаНоменклатуры.Номенклатура КАК Номенклатура,
    ДвиженияНоменклатураНоменклатураОбороты.АналитикаУчетаНоменклатуры.Характеристика КАК Характеристика,
    ДвиженияНоменклатураНоменклатураОбороты.КоличествоОборот КАК Количество
ИЗ
    РегистрНакопления.ДвиженияНоменклатураНоменклатура.Обороты КАК ДвиженияНоменклатураНоменклатураОбороты
ГДЕ
    ДвиженияНоменклатураНоменклатураОбороты.ХозяйственнаяОперация = &ХозяйственнаяОперация

Проанализируем, почему этот подход неэффективен и может приводить к неверным результатам. Когда мы используем предложение ГДЕ, СУБД сначала полностью рассчитывает итоги по всей виртуальной таблице оборотов за указанный период (или за все время, если период не задан), строит временный результирующий набор данных и только затем начинает построчно фильтровать его по хозяйственной операции.

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

Перепишем запрос правильно, используя параметры виртуальной таблицы:


ВЫБРАТЬ
    ДвиженияНоменклатураОбороты.АналитикаУчетаНоменклатуры.Номенклатура КАК Номенклатура,
    ДвиженияНоменклатураОбороты.АналитикаУчетаНоменклатуры.Характеристика КАК Характеристика,
    ДвиженияНоменклатураОбороты.КоличествоОборот КАК Количество,
    ДвиженияНоменклатураОбороты.ХозяйственнаяОперация КАК ХозяйственнаяОперация
ИЗ
    РегистрНакопления.ДвиженияНоменклатураНоменклатура.Обороты(, , , ХозяйственнаяОперация = &ХозОперация) КАК ДвиженияНоменклатураОбороты

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


Запрос.УстановитьПараметр("ХозОперация", Перечисления.ХозяйственныеОперации.ПередачаПродукцииИзПроизводства);

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


ВЫБРАТЬ
    ДвиженияНоменклатураОбороты.АналитикаУчетаНоменклатуры.Номенклатура КАК Номенклатура,
    ДвиженияНоменклатураОбороты.АналитикаУчетаНоменклатуры.Характеристика КАК Характеристика,
    ДвиженияНоменклатураОбороты.КоличествоОборот КАК Количество
ИЗ
    РегистрНакопления.ДвиженияНоменклатураНоменклатура.Обороты(, , , ХозяйственнаяОперация = ЗНАЧЕНИЕ(Перечисление.ХозяйственныеОперации.ПередачаПродукцииИзПроизводства)) КАК ДвиженияНоменклатураОбороты

Причина 2. Отложенное проведение и регламентные задания (Оффлайн-заполнение)

Регистр накопления ДвиженияНоменклатураНоменклатура (в архитектуре ERP его часто называют регистром «Н-Н») имеет важнейшую особенность: он относится к финансовому контуру и контуру партионного учета.

Выясним важный нюанс: в отличие от обычных регистров товарных запасов (таких как «Товары на складах»), движения по регистру «Н-Н» не формируются оперативно в момент проведения первичных документов («Выпуск продукции», «Передача материалов в производство» и т. д.).

Заполнение этого регистра происходит при выполнении регламентной процедуры **«Расчет себестоимости товаров»** (в рамках закрытия месяца) или при запуске фонового задания расчета партий. Если расчет себестоимости за выбранный период не выполнялся, физическая таблица регистра ДвиженияНоменклатураНоменклатура будет абсолютно пустой. Соответственно, любой запрос к его оборотам вернет пустое значение.

Для проверки этой гипотезы выполним следующие шаги:

  1. Перейдем в раздел «Финансовый результат и контроллинг» -> «Закрытие месяца».
  2. Проверим статус выполнения этапов «Расчет себестоимости» и «Распределение затрат» за интересующий нас период.
  3. При необходимости запустим процедуру закрытия месяца.

Причина 3. Сворачивание нулевых оборотов в виртуальной таблице

Виртуальная таблица .Обороты возвращает сгруппированные данные. Платформа рассчитывает разницу между дебетовыми и кредитовыми движениями (приходом и расходом) за указанный период в разрезе измерений.

Проанализируем ситуацию: если по одной и той же номенклатуре, характеристике и хозяйственной операции в течение периода были сделаны как положительные движения, так и корректирующие (записи сторно или обратные движения на ту же сумму/количество), итоговый оборот математически станет равен 0.

По умолчанию оптимизатор платформы 1С **не выводит строки с нулевыми итогами** из виртуальной таблицы оборотов. Физические записи в базе данных есть, но в виртуальной таблице вы их не увидите.

Чтобы исключить эту проблему, временно обратимся к реальной (физической) таблице регистра с помощью следующего диагностического запроса:


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

Если этот запрос вернул строки, значит, физические записи существуют, и проблема действительно кроется в группировке и расчете итогов виртуальной таблицы. В таком случае попробуем использовать в параметрах виртуальной таблицы периодичность Регистратор или Запись.

Причина 4. Несовпадение хозяйственной операции в реальном учете

Разработчики часто ожидают увидеть в регистре операцию ПередачаПродукцииИзПроизводства, однако в 1С:ERP логика заполнения хозяйственных операций зависит от настроек структуры предприятия и складов.

Рассмотрим пример по шагам:

  1. Если выпуск продукции оформляется на склад, который в системе зарегистрирован как «Цеховая кладовая» выпускающего подразделения, то операция запишется в регистр со значением ВыпускПродукции или ВыпускПродукцииВПодразделение.
  2. Операция ПередачаПродукцииИзПроизводства возникнет только тогда, когда готовая продукция передается непосредственно из производственного подразделения на удаленный (внешний) склад, минуя цеховую кладовую.

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


ВЫБРАТЬ РАЗЛИЧНЫЕ
    ДвиженияНоменклатураОбороты.ХозяйственнаяОперация КАК ХозяйственнаяОперация
ИЗ
    РегистрНакопления.ДвиженияНоменклатураНоменклатура.Обороты КАК ДвиженияНоменклатураОбороты

Посмотрим на результат выполнения этого запроса. Вполне вероятно, что вы увидите другие значения перечисления ХозяйственныеОперации, под которые вам и нужно будет скорректировать ваш отбор.

Причина 5. Влияние механизма ограничения прав на уровне записей (RLS)

Если запрос запускается под пользователем с ограниченными правами, в работу вступает механизм RLS (Row Level Security). Платформа на уровне СУБД автоматически модифицирует ваш запрос, добавляя скрытые условия фильтрации по организациям, складам, подразделениям или группам доступа номенклатуры.

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

Чтобы проверить влияние RLS, выполним следующие действия:


УстановитьПривилегированныйРежим(Истина);
// Выполнение запроса
УстановитьПараметр...
Результат = Запрос.Выполнить();
УстановитьПривилегированныйРежим(Ложь);

Резюме и чеклист для диагностики проблемы

Если ваш запрос к оборотам регистра «Движения номенклатуры» не возвращает данные по хозяйственной операции, последовательно выполните следующие шаги:

  1. Убедитесь, что отбор наложен внутри параметров виртуальной таблицы Обороты(,, , ХозяйственнаяОперация = &ХозОперация), а не в предложении ГДЕ.
  2. Проверьте тип передаваемого параметра: он должен строго соответствовать типу перечисления ПеречислениеСсылка.ХозяйственныеОперации.
  3. Проверьте, выполнен ли в базе данных «Расчет себестоимости» за анализируемый период (регистр заполняется в офлайн-режиме).
  4. Выполните прямой запрос к физической таблице регистра без отборов, чтобы убедиться в физическом наличии записей.
  5. Проанализируйте, какие именно хозяйственные операции записывают ваши документы, сделав выборку уникальных значений через ВЫБРАТЬ РАЗЛИЧНЫЕ.
  6. Проверьте влияние механизма RLS, выполнив этот же код под полными правами.
← На главную