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