Почему запрос по получению документа основания по приходному ордеру не возвращает данные и как это исправить

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

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

Анализ исходного кода запроса

Рассмотрим типовой пример запроса, который может быть использован для получения данных из документа ПриходныйОрдерНаТовары. Проанализируем структуру текста запроса и способ передачи параметров:


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|    ПриходныйОрдерНаТовары.ДокументОснование,
|    ПриходныйОрдерНаТовары.ДокументОснование.Номер,
|    ПриходныйОрдерНаТовары.ДокументОснование.Ссылка
|ИЗ
|    Документ.ПриходныйОрдерНаТовары КАК ПриходныйОрдерНаТовары
|ГДЕ
|    ПриходныйОрдерНаТовары.Номер = &Номер
|    И ПриходныйОрдерНаТовары.Дата МЕЖДУ &Дата И &ДатаН";

Запрос.УстановитьПараметр("Номер", НомерДок);
Запрос.УстановитьПараметр("Дата", ДатаДок);
Запрос.УстановитьПараметр("ДатаН", КонецДня(ДатаДок));
Результат = Запрос.Выполнить().Выбрать();
Пока Результат.Следующий() Цикл
    ТекДокумент = Результат.Ссылка;    
КонецЦикла;

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

Причина 1: Различие данных в рабочей и тестовой базах

Проанализируем ситуацию, которая часто встречается при разработке: программист запускает Консоль запросов в одной информационной базе (например, в актуальной «боевой»), а отладку кода проводит в другой (старой копии или тестовом контуре). Выясним, почему это приводит к ошибкам:

  1. Несоответствие номеров документов: В разных базах один и тот же документ может иметь разные номера из-за перенумерации или особенностей обмена данными.
  2. Отсутствие документа: В тестовой базе искомого документа может просто не существовать, даже если параметры (номер и дата) кажутся правильными.
  3. Разница в часовых поясах: Если сервер 1С и сервер СУБД настроены на разные часовые пояса, границы периода МЕЖДУ могут смещаться, исключая документ из выборки.

Совет: Всегда проверяйте, в каком контексте запущен отладчик. Убедитесь, что значения переменных НомерДок и ДатаДок в коде соответствуют тем значениям, которые вы вводите в консоли запросов именно в этой базе данных.

Причина 2: Проблемы со строковыми номерами и префиксами

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

Лидирующие нули: Номер, который визуально выглядит как "13571", в базе данных может храниться как "00000013571". Если в переменную &Номер передается значение без нулей, простое равенство в запросе не сработает.

Префиксы организации и информационных баз: Часто номера имеют вид "УТ-000123". При программном формировании номера важно учитывать, как именно он записан в базе. Разберем, как подготовить номер перед передачей в запрос:


// Использование стандартных функций для приведения номера к нужному формату
НужныйНомер = СокрЛП(НомерДок);
// Если мы знаем, какая длина номера установлена в метаданных, можно добавить нули программно
// Но лучше использовать штатные механизмы конфигурации

Для гарантированного поиска рекомендуется использовать функцию ПрефиксацияОбъектовКлиентСервер.СформироватьПолныйНомер() (в современных типовых конфигурациях) или проверять длину номера через метаданные объекта.

Причина 3: Особенности работы с периодами и границами дня

Проанализируем условие ПриходныйОрдерНаТовары.Дата МЕЖДУ &Дата И &ДатаН. Если параметр &Дата передается с временем (например, 12:00:00), а документ был создан в 08:00:00 того же дня, он не попадет в выборку.

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


Запрос.УстановитьПараметр("Дата", НачалоДня(ДатаДок));
Запрос.УстановитьПараметр("ДатаН", КонецДня(ДатаДок));

Это обеспечит поиск документа в течение всех суток, независимо от времени его создания и времени, переданного в переменной ДатаДок.

Причина 4: Ограничение прав доступа (RLS)

Выясним еще одну неочевидную причину: Row Level Security (RLS). Если вы запускаете Консоль запросов под пользователем с полными правами, запрос вернет данные. Но если ваша обработка выполняется под пользователем с ограниченными правами (например, «Кладовщик»), система 1С автоматически добавит скрытые условия в запрос, отсекая документы по определенным организациям или складам.

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

Причина 5: Работа с составными типами данных

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

Обращение через точку (ДокументОснование.Номер) заставляет систему выполнять LEFT JOIN со всеми таблицами документов, входящими в составной тип. Если ссылочная целостность нарушена (так называемая «битая ссылка»), обращение к полям через точку вернет NULL, а сам документ может не отобразиться корректно в выборке.

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

Итоговый чек-лист для проверки запроса

Если ваш запрос не возвращает данные, пройдите по следующим шагам:

  1. Убедитесь, что код выполняется в той же базе данных, где вы проверяете данные вручную.
  2. Сравните типы данных: переменная &Номер должна быть строкой точно такого же формата (с нулями и префиксами), как в базе.
  3. Проверьте границы периода: используйте НачалоДня() и КонецДня().
  4. Проверьте наличие прав доступа (RLS) у пользователя, под которым запускается код.
  5. Убедитесь, что реквизит ДокументОснование заполнен в искомом объекте.

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

← На главную