При получении сведений из периодических регистров 1С разработчики часто сталкиваются с ситуацией, когда метод ПолучитьПоследнее() возвращает значение 0 вместо ожидавшейся цены товара. Проанализируем причины этой проблемы, разберем частые ошибки в коде и рассмотрим правильный порядок получения цен.
Рассмотрим исходный фрагмент кода, в котором возникает ошибка:
Функция ПолучитьЦенуПродажи(Номенклатура, Знач Дата = Неопределено)
Дата = ?(Дата = Неопределено, ТекущаяДата(), Дата);
Структура = Новый Структура();
Структура.Вставить("Номенклатура", Номенклатура);
Данные = РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(Дата, Структура);
Возврат Данные.ЦенаПродажи;
КонецФункции
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Наименование = Объект.Наименование;
Цена = ПолучитьЦенуПродажи(Наименование);
Сообщить(Цена);
КонецПроцедуры
В приведенном примере в функцию передается значение Объект.Наименование, имеющее строковый тип. Измерение Номенклатура в регистре сведений ЦеныНоменклатуры имеет тип ссылки (СправочникСсылка.Номенклатура).
При передаче строки вместо ссылки система не находит совпадений по ключу отбора. В платформе 1С метод ПолучитьПоследнее() при отсутствии записей по заданному отбору не вызывает ошибку выполнения и не возвращает Неопределено. Он возвращает структуру с ключами всех ресурсов и реквизитов регистра, заложенными значениями по умолчанию (для числовых полей это число 0). В результате обращение к Данные.ЦенаПродажи дает нулевой результат.
Зачем измерение регистра требует именно ссылку? В базе данных может существовать несколько товаров с одинаковым наименованием (например, «Помидоры»). Строка не обеспечивает уникальность элемента, тогда как Ссылка однозначно идентифицирует конкретную позицию справочника.
Разберем по шагам, как исправить алгоритм. Передавать в структуру отбора необходимо непосредственно ссылку на объект номенклатуры (Объект.Ссылка).
Кроме того, в управляемом приложении вызов менеджера регистра сведений РегистрыСведений.ЦеныНоменклатуры недоступен на клиенте. Вызов функции чтения цены должен производиться на сервере.
Правильный вариант реализации функции и вызова процедур:
&НаСервере
Функция ПолучитьЦенуПродажиНаСервере(НоменклатураСсылка, Знач Дата = Неопределено)
Дата = ?(Дата = Неопределено, ТекущаяДата(), Дата);
СтруктураОтбора = Новый Структура();
СтруктураОтбора.Вставить("Номенклатура", НоменклатураСсылка);
Данные = РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(Дата, СтруктураОтбора);
Возврат Данные.ЦенаПродажи;
КонецФункции
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если ЗначениеЗаполнено(Объект.Ссылка) Тогда
Цена = ПолучитьЦенуПродажиНаСервере(Объект.Ссылка);
Сообщить(Цена);
КонецЕсли;
КонецПроцедуры
Если после передачи ссылки метод ПолучитьПоследнее() все равно возвращает 0, рекомендуем проверить следующие моменты:
Объект.Ссылка содержит пустую ссылку. Для нового элемента записей в регистре сведений быть не может.ВидЦены (или ТипЦен) и Характеристика. Если в регистре задан вид цены, но он не указан в структуре отбора, метод вернет нулевое значение или некорректную запись.Дата в 1С содержат время. Если запросить цену на начало дня (00:00:00), а документ установки цен записан в течение дня (например, в 12:00:00), система не найдет запись и вернет 0.ПолучитьПоследнее() выполняет точечное обращение к БД и подходит только для разового получения цены одного товара. Для обработки списков или табличных частей следует использовать один запрос к виртуальной таблице СрезПоследних, чтобы избежать снижения производительности.