Как программно получить розничную цену номенклатуры в 1С:Торговля и Склад 7.7?

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

При переносе данных, выгрузке прайс-листов или формировании документов в конфигурации «Торговля и Склад 7.7» разработчики нередко сталкиваются с ситуацией, когда требуется программно получить розничную цену товара. Попытки обратиться к цене напрямую через реквизит номенклатуры вроде Номенклатура.Цена или через регистр остатков приводят к ошибкам либо возвращают нулевые значения. Проанализируем, как устроено хранение цен в платформе 1С:Предприятие 7.7, и разберем корректные способы программного извлечения розничных цен.

Почему не удается получить цену напрямую из номенклатуры или регистра?

Для понимания логики работы системы рассмотрим внутреннюю структуру метаданных конфигурации «Торговля и Склад 7.7»:

  1. Справочник «Номенклатура» не содержит реквизита цены. Один и тот же товар может иметь множество видов цен: закупочную, мелкооптовую, оптовую, розничную. Поэтому цены вынесены в отдельный подчиненный справочник.
  2. Иерархия подчинения: справочник Цены является подчиненным по отношению к справочнику Номенклатура. Каждый элемент справочника цен принадлежит конкретной позиции номенклатуры (владельцу) и ссылается на определенный тип цен через реквизит ТипЦен (ссылка на Справочник.ТипыЦен).
  3. Периодичность реквизита: реквизит Цена в справочнике Цены является периодическим. Это означает, что цена привязана ко времени (истории значений), и для ее чтения всегда необходимо указывать дату актуальности.
  4. Особенности регистра «ПартииНаличие»: измерение ЦенаПрод (цена продажи) заполняется исключительно при движениях по складам с типом «Розничный». Если списание или остатки формируются по оптовому складу, учет ведется строго по себестоимости, и измерение ЦенаПрод всегда будет равно 0. Кроме того, в регистре фиксируется историческая стоимость партии, а не действующая цена из прайс-листа.

Способ 1. Прямой поиск через подчиненный справочник «Цены»

Разберем классический алгоритм прямого обращения к объектам метаданных. Перед обходом строк необходимо один раз инициализировать объект типа цен и справочник цен, чтобы избежать лишнего создания COM-объектов в цикле. Внутри цикла установим владельца, найдем нужную запись по типу цен и запросим значение периодического реквизита на требуемую дату.

Посмотрим на пример реализации:


// 1. Инициализация объектов до начала цикла
РозничныйТипЦен = СоздатьОбъект("Справочник.ТипыЦен");
Если РозничныйТипЦен.НайтиПоНаименованию("Розничная", 0) = 0 Тогда
    Если РозничныйТипЦен.НайтиПоНаименованию("Розничные", 0) = 0 Тогда
        Сообщить("Тип цен не найден в справочнике!");
    КонецЕсли;
КонецЕсли;

СпрЦены = СоздатьОбъект("Справочник.Цены");
ДатаАктуальности = ТекущаяДата(); // Либо ДатаДокумента

// 2. Обработка позиций внутри цикла
Пока РегистрыДокумента.ПолучитьДвижение() = 1 Цикл
    // ... Пропуск лишних движений ...
    
    Номенклатура = РегистрыДокумента.Номенклатура;
    
    // Устанавливаем владельца для подчиненного справочника
    СпрЦены.ИспользоватьВладельца(Номенклатура);
    
    // Ищем цену с нужным типом (0 - поиск по всей длине реквизита)
    Если СпрЦены.НайтиПоРеквизиту("ТипЦен", РозничныйТипЦен.ТекущийЭлемент(), 0) = 1 Тогда
        // Получаем значение периодического реквизита на дату
        Таблица.Цена = СпрЦены.Цена.Получить(ДатаАктуальности);
    Иначе
        Таблица.Цена = 0;
    КонецЕсли;
КонецЦикла;

Альтернативный вариант работы с периодическим реквизитом — использование метода ИспользоватьДату():


СпрЦены.ИспользоватьВладельца(Номенклатура);
СпрЦены.ИспользоватьДату(ДатаАктуальности);
Если СпрЦены.НайтиПоРеквизиту("ТипЦен", РозничныйТипЦен.ТекущийЭлемент(), 0) = 1 Тогда
    Таблица.Цена = СпрЦены.Цена; // Значение автоматически позиционировано на дату
КонецЕсли;

Способ 2. Использование типовой функции глобального модуля «глВернутьЦену»

В типовой конфигурации «Торговля и Склад 7.7» реализован стандартный механизм для определения цен — глобальная функция глВернутьЦену. Использование этой функции предпочтительнее ручного поиска по нескольким причинам:

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

Рассмотрим синтаксис и практическое применение функции:


РозничныйТипЦен = СоздатьОбъект("Справочник.ТипыЦен");
РозничныйТипЦен.НайтиПоНаименованию("Розничная", 0);

ДатаЦены = ТекущаяДата();

// Переменные для приема возвращаемых значений
ЦенаВозврат = 0;
ЕдВозврат   = 0;
ВалВозврат  = 0;

// Вызываем штатную функцию
СтатусЦены = глВернутьЦену(Номенклатура, РозничныйТипЦен.ТекущийЭлемент(), ДатаЦены, ЦенаВозврат, ЕдВозврат, ВалВозврат);

Если СтатусЦены = 1 Тогда
    Таблица.Цена = ЦенаВозврат;
ИначеЕсли СтатусЦены = -1 Тогда
    // Цена помечена на удаление
    Таблица.Цена = 0;
Иначе
    // Цена не задана
    Таблица.Цена = 0;
КонецЕсли;

Важные нюансы: единицы измерения и валюты

При выгрузке цен в сторонние системы (например, в «1С:Розница 2.2») необходимо контролировать соответствие единиц измерения и валют:

  1. Коэффициенты единиц: в 1С 7.7 цена может быть установлена за упаковку, ящик или штуку (реквизит Единица справочника Цены). Если в новую базу данные переносятся в базовых единицах (например, в штуках), а цена назначена за коробку из 10 штук, необходимо скорректировать цену: ЦенаЗаБазовую = ЦенаВозврат / ЕдВозврат.Коэффициент.
  2. Валюта цены: реквизит Валюта в справочнике цен может иметь значение «USD» или «EUR». Если розничная цена ведется в валюте, перед передачей данных в документ розницы ее следует пересчитать в рубли по курсу на дату выгрузки через функцию глПересчет() или прямое чтение периодического реквизита Курс справочника Валюты.

Оптимизация производительности при больших объемах данных

Если выгрузка остатков и цен охватывает десятки тысяч позиций номенклатуры, последовательный вызов методов НайтиПоРеквизиту и Получить внутри цикла существенно замедлит выполнение обработки из-за множественных обращений к таблицам базы данных (к файлам 1SCONST и SC* в файловом варианте или отдельным SQL-запросам в клиент-серверном).

Для ускорения процесса рекомендуется предварительно сформировать таблицу актуальных цен одним запросом к справочнику Цены с установленным фильтром по типу цен, либо выгрузить итоги периодических реквизитов во временную ТаблицаЗначений с последующим поиском через НайтиЗначение().

← На главную