Как получить последние цены из документов реализации в 1С

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

Задача получения актуальных цен из документов реализации является одной из самых частых при разработке отчетов или механизмов заполнения цен в 1С. Начинающие разработчики часто допускают ошибку, пытаясь использовать конструкцию ВЫБРАТЬ ПЕРВЫЕ 1, что приводит к получению только одной строки для всего результата запроса вместо последних цен по каждой позиции номенклатуры. В этой статье мы разберем правильные архитектурные подходы к решению этой задачи.

Почему простая выборка из документов работает некорректно

Разберем ситуацию, представленную в исходном вопросе. Когда мы пишем запрос к табличной части Документ.РеализацияТоваровУслуг.Товары и указываем ВЫБРАТЬ ПЕРВЫЕ 1 с сортировкой по дате, система находит самый последний документ и берет из него первую попавшуюся строку. Если нам нужно получить список из 100 товаров с их последними ценами, такой подход не сработает.

Для корректного решения нам необходимо сначала определить, какой документ был последним для каждой номенклатурной позиции, а затем уже «вытащить» цену именно из этой строки. Проанализируем, как это сделать максимально эффективно.

Способ 1. Использование вложенного запроса (классический метод)

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

Рассмотрим пример построения такого запроса по шагам:

  1. Создаем временную таблицу с максимальными датами документов для каждой номенклатуры.
  2. Соединяем эту таблицу с основной таблицей товаров документа по полям Номенклатура и Дата.

ВЫБРАТЬ
    РеализацияТовары.Номенклатура КАК Номенклатура,
    МАКСИМУМ(РеализацияТовары.Ссылка.Дата) КАК МаксДата
ПОМЕСТИТЬ ВТ_ПоследниеДаты
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары
ГДЕ
    РеализацияТовары.Ссылка.Проведен = ИСТИНА
    И РеализацияТовары.Ссылка.Дата МЕЖДУ &НачалоПериода И &КонецПериода
СГРУППИРОВАТЬ ПО
    РеализацияТовары.Номенклатура
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_ПоследниеДаты.Номенклатура,
    РеализацияТовары.Цена,
    РеализацияТовары.Ссылка КАК ДокументРеализации
ИЗ
    ВТ_ПоследниеДаты КАК ВТ_ПоследниеДаты
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары
        ПО ВТ_ПоследниеДаты.Номенклатура = РеализацияТовары.Номенклатура
            И ВТ_ПоследниеДаты.МаксДата = РеализацияТовары.Ссылка.Дата
ГДЕ
    РеализацияТовары.Ссылка.Проведен = ИСТИНА

Важный нюанс: Если в одну и ту же секунду проведено несколько документов реализации по одной и той же номенклатуре, запрос может вернуть несколько строк. Чтобы этого избежать, вместо Дата лучше использовать МоментВремени.

Способ 2. Момент времени вместо даты

В системе 1С МоментВремени — это комбинация даты и уникальной ссылки на документ. Это гарантирует уникальность точки на временной шкале. Проанализируем, как изменить запрос для использования момента времени.

В запросах 1С мы не можем напрямую использовать функцию МАКСИМУМ к объекту типа «Момент времени», поэтому разработчики часто используют связку МАКСИМУМ(Дата) и МАКСИМУМ(Ссылка) внутри этой даты. Однако в современных версиях платформы 8.3 для решения этой задачи в компоновке данных (СКД) предусмотрены специальные механизмы ролей полей периода.

Способ 3. Использование регистров сведений (СрезПоследних)

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

Пример запроса к регистру сведений:


ВЫБРАТЬ
    ЦеныНоменклатурыСрезПоследних.Номенклатура,
    ЦеныНоменклатурыСрезПоследних.Цена
ИЗ
    РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ) КАК ЦеныНоменклатурыСрезПоследних

Способ 4. Регистры накопления (для ERP и УТ 11)

В современных управленческих конфигурациях (Управление торговлей 11, ERP, Комплексная автоматизация) данные о продажах фиксируются в регистре накопления ВыручкаИСебестоимостьПродаж. Выясним, почему выгодно брать данные оттуда:

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

Критически важные детали при расчете цены

Рассмотрим подробнее нюансы, которые часто забывают при написании запросов, что приводит к ошибкам в данных:

  1. Характеристики номенклатуры: Если в программе ведется учет по характеристикам (цвет, размер), цена в реализации привязывается именно к связке Номенклатура + Характеристика. Обязательно добавляйте группировку по характеристике, иначе вы получите неверную цену для товаров с разными свойствами.
  2. Коэффициенты единиц измерения: Цена в документе может быть указана за штуку, а в другом — за упаковку (например, коробку из 10 штук). Чтобы цены были сопоставимы, всегда приводите их к базовой единице измерения, деля Цена на Коэффициент из справочника упаковок.
  3. Налоговый учет (НДС): Выясним причину расхождений в суммах. В одном документе может быть установлен флаг «Цена включает НДС», а в другом — нет. Для получения сопоставимых данных в отчете необходимо программно приводить все цены к единому виду (либо все с налогом, либо все без налога).
  4. Статус документа: Всегда фильтруйте документы по условию Проведен = ИСТИНА и ПометкаУдаления = ЛОЖЬ. Непроведенные документы не являются фактом совершения сделки и не должны влиять на актуальную цену.

Использование Системы Компоновки Данных (СКД)

Посмотрим на ситуацию со стороны создания отчета. В СКД реализован мощный механизм для получения последних значений. Если вы укажете в настройках набора данных роль для поля периода («Период») и правильно настроите ресурсы, СКД сможет самостоятельно рассчитать последнее значение цены для каждой строки группировки. Это избавит вас от необходимости писать громоздкие вложенные запросы вручную.

Подводя итог, можно сказать, что выбор метода зависит от архитектуры вашей базы данных. Если есть возможность использовать специализированные регистры — используйте их. Если же нужно тянуть данные напрямую из документов, всегда помните о группировке по Моменту времени и необходимости фильтрации проведенных документов.

← На главную