Почему метод ПолучитьПоследнее возвращает 0 при получении цены номенклатуры из регистра сведений?

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

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

Главная причина: передача строки наименования вместо ссылки

Рассмотрим исходный фрагмент кода, в котором возникает ошибка:


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

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    Наименование = Объект.Наименование;
    Цена = ПолучитьЦенуПродажи(Наименование);
    Сообщить(Цена); 
КонецПроцедуры

В приведенном примере в функцию передается значение Объект.Наименование, имеющее строковый тип. Измерение Номенклатура в регистре сведений ЦеныНоменклатуры имеет тип ссылки (СправочникСсылка.Номенклатура).

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

Зачем измерение регистра требует именно ссылку? В базе данных может существовать несколько товаров с одинаковым наименованием (например, «Помидоры»). Строка не обеспечивает уникальность элемента, тогда как Ссылка однозначно идентифицирует конкретную позицию справочника.

Исправление ошибки в коде

Разберем по шагам, как исправить алгоритм. Передавать в структуру отбора необходимо непосредственно ссылку на объект номенклатуры (Объект.Ссылка).

Кроме того, в управляемом приложении вызов менеджера регистра сведений РегистрыСведений.ЦеныНоменклатуры недоступен на клиенте. Вызов функции чтения цены должен производиться на сервере.

Правильный вариант реализации функции и вызова процедур:


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

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    Если ЗначениеЗаполнено(Объект.Ссылка) Тогда
        Цена = ПолучитьЦенуПродажиНаСервере(Объект.Ссылка);
        Сообщить(Цена);
    КонецЕсли;
КонецПроцедуры

Другие возможные причины получения нулевой цены

Если после передачи ссылки метод ПолучитьПоследнее() все равно возвращает 0, рекомендуем проверить следующие моменты:

  1. Несохраненный элемент справочника: Если форма открыта для нового объекта, Объект.Ссылка содержит пустую ссылку. Для нового элемента записей в регистре сведений быть не может.
  2. Состав измерений регистра: Регистры цен обычно содержат дополнительные измерения, такие как ВидЦены (или ТипЦен) и Характеристика. Если в регистре задан вид цены, но он не указан в структуре отбора, метод вернет нулевое значение или некорректную запись.
  3. Время установки цены: Значения типа Дата в 1С содержат время. Если запросить цену на начало дня (00:00:00), а документ установки цен записан в течение дня (например, в 12:00:00), система не найдет запись и вернет 0.
  4. Производительность и использование запросов: Метод ПолучитьПоследнее() выполняет точечное обращение к БД и подходит только для разового получения цены одного товара. Для обработки списков или табличных частей следует использовать один запрос к виртуальной таблице СрезПоследних, чтобы избежать снижения производительности.
← На главную