В типовой конфигурации «1С:Управление торговлей 10.3» часто возникает задача оперативного получения цен, по которым товар приходил в последний раз. Стандартные отчеты, такие как «Анализ цен», опираются на регистр сведений ЦеныНоменклатурыКонтрагентов. Однако на практике пользователи часто забывают ставить флаг «Регистрировать цены поставщика» в документе «Поступление товаров и услуг» (ПТУ), из-за чего регистр остается пустым, а стандартные отчеты — бесполезными.
В этой статье мы подробно разберем, как получить данные напрямую из документов поступления, проанализируем нюансы работы с запросами и рассмотрим способы оптимизации для больших баз данных.
Если в вашей базе не ведется строгий учет партий или не всегда заполняются регистры цен, самым надежным источником данных становятся сами документы ПоступлениеТоваровУслуг. Нам необходимо найти для каждой номенклатуры самый свежий документ и вытащить из него цену.
Разберем логику построения такого запроса по шагам. Основная сложность заключается в том, что в одном запросе нельзя просто выбрать МАКСИМУМ(Дата) и Цена, так как группировка по цене выдаст все уникальные цены, а не цену конкретной даты. Поэтому мы будем использовать временные таблицы.
Проанализируем пример кода, который эффективно решает эту задачу:
// Шаг 1. Собираем все даты поступлений по нужной номенклатуре
ВЫБРАТЬ
ПоступлениеТоваровУслугТовары.Номенклатура КАК Номенклатура,
ПоступлениеТоваровУслугТовары.Ссылка.Дата КАК ДатаПоступления,
ПоступлениеТоваровУслугТовары.Цена КАК Цена
ПОМЕСТИТЬ ВтЦеныПоступлений
ИЗ
Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТоваровУслугТовары
ГДЕ
ПоступлениеТоваровУслугТовары.Ссылка.Проведен = ИСТИНА;
////////////////////////////////////////////////////////////////////////////////
// Шаг 2. Выбираем только максимальную дату для каждой позиции
ВЫБРАТЬ
ВтЦеныПоступлений.Номенклатура КАК Номенклатура,
МАКСИМУМ(ВтЦеныПоступлений.ДатаПоступления) КАК ДатаПоступления
ПОМЕСТИТЬ ВтДатыПоследнихПоступлений
ИЗ
ВтЦеныПоступлений КАК ВтЦеныПоступлений
СГРУППИРОВАТЬ ПО
ВтЦеныПоступлений.Номенклатура;
////////////////////////////////////////////////////////////////////////////////
// Шаг 3. Соединяем максимальные даты с исходными данными для получения цены
ВЫБРАТЬ
ВтДатыПоследнихПоступлений.Номенклатура,
ВтДатыПоследнихПоступлений.ДатаПоступления,
МАКСИМУМ(ВтЦеныПоступлений.Цена) КАК Цена
ИЗ
ВтДатыПоследнихПоступлений КАК ВтДатыПоследнихПоступлений
ЛЕВОЕ СОЕДИНЕНИЕ ВтЦеныПоступлений КАК ВтЦеныПоступлений
ПО ВтЦеныПоступлений.Номенклатура = ВтДатыПоследнихПоступлений.Номенклатура
И ВтЦеныПоступлений.ДатаПоступления = ВтДатыПоследнихПоступлений.ДатаПоступления
СГРУППИРОВАТЬ ПО
ВтДатыПоследнихПоступлений.Номенклатура,
ВтДатыПоследнихПоступлений.ДатаПоступления
Рассмотрим, почему в финальном шаге мы снова используем МАКСИМУМ(Цена). Это необходимо на случай, если в одну и ту же секунду были проведены два разных документа поступления по одной и той же номенклатуре с разными ценами. Функция МАКСИМУМ позволит запросу вернуть корректную (наивысшую) цену, не вызывая дублирования строк в отчете.
При использовании первого метода мы сталкиваемся с серьезной проблемой: в документах поступления цены могут быть указаны в разных валютах (USD, EUR, RUB). Просто сравнивать числовые значения из колонки Цена некорректно. Кроме того, в одном документе цена может включать НДС, а в другом — нет.
Чтобы получить релевантные данные, нам нужно привести все цены к единому знаменателю. Выясним, как это сделать в запросе:
Курс и делить на Кратность из шапки документа.СуммаВключаетНДС. Если он ложный, к цене нужно прибавить сумму налога (например, умножить на 1.20 для ставки 20%).Рассмотрим пример того, как должна вычисляться цена в первом пакете запроса:
ВЫБРАТЬ
ПоступлениеТоваровУслугТовары.Номенклатура,
ВЫБОР
КОГДА ПоступлениеТоваровУслугТовары.Ссылка.СуммаВключаетНДС
ТОГДА ПоступлениеТоваровУслугТовары.Цена
ИНАЧЕ ПоступлениеТоваровУслугТовары.Цена * (1 + ПоступлениеТоваровУслугТовары.СтавкаНДС.Ставка / 100)
КОНЕЦ * ПоступлениеТоваровУслугТовары.Ссылка.КурсВзаиморасчетов / ПоступлениеТоваровУслугТовары.Ссылка.КратностьВзаиморасчетов КАК ЦенаУпр
...
Обращение напрямую к табличным частям документов (Документ.ПоступлениеТоваровУслуг.Товары) — это «тяжелая» операция для SQL-сервера, особенно если документов в базе сотни тысяч. Профессиональные разработчики рекомендуют использовать регистр накопления «Закупки».
Преимущества использования регистра «Закупки»:
Стоимость и Количество. Цена вычисляется как Стоимость / Количество.Однако помните, что если в вашей базе регистр «Закупки» не закрывается или данные в нем искажены из-за корректировок, результаты могут отличаться от первичных документов.
Использование только даты документа (МАКСИМУМ(Дата)) может быть недостаточно точным. В 1С документы с одинаковой датой и временем различаются по позиции на временной оси (Момент времени).
Для получения абсолютно точного «последнего» поступления, в запросе рекомендуется использовать соединение по полю МоментВремени. Если ваша версия платформы позволяет, во временную таблицу лучше помещать именно МАКСИМУМ(МоментВремени), а затем соединяться по нему для получения ссылки на документ и цены.
Если в «1С:Управлении торговлей 10.3» вы ведете учет по характеристикам (размеры, цвета), крайне важно добавить поле ХарактеристикаНоменклатуры во все группировки и условия связи запроса. Без этого система выдаст вам случайную цену одного из последних поступлений этого товара, проигнорировав разницу в характеристиках.
Важный совет по производительности: При работе с временными таблицами (пакетные запросы), всегда используйте конструкцию ИНДЕКСИРОВАТЬ ПО. Например:
ПОМЕСТИТЬ ВтДатыПоследнихПоступлений
ИНДЕКСИРОВАТЬ ПО
Номенклатура
Это позволит SQL-серверу мгновенно выполнять левое соединение, даже если в списке на получение цен находятся десятки тысяч позиций номенклатуры.
Таким образом, мы разобрали основные подходы к получению цен последнего поступления. Наиболее быстрым и простым способом для разовой задачи является запрос к табличным частям через временные таблицы с поиском максимальной даты, а для постоянного использования в отчетах лучше настроить автоматическую регистрацию цен в регистре ЦеныНоменклатурыКонтрагентов.