В процессе разработки отчетов в 1С:Комплексная автоматизация 1.3 (КА 1.3) программисты часто сталкиваются с задачей вывода актуальной (последней) цены закупки рядом с данными об оборотах за период. Основная сложность заключается в том, что стандартная виртуальная таблица ОстаткиИОбороты регистра накопления Закупки выдает агрегированные данные, а нам нужно получить значение из конкретного, самого свежего документа.
В этой статье мы подробно разберем, как правильно составить запрос, чтобы избежать типичных ошибок новичков, таких как получение максимальной цены вместо последней или дублирование строк при наличии нескольких поступлений в один день.
Рассмотрим распространенную ситуацию: разработчик пытается использовать функцию МАКСИМУМ(Цена) в группировке по номенклатуре. Проанализируем, почему это неверно. Если товар вчера стоил 100 рублей, а сегодня — 80 рублей, то функция МАКСИМУМ вернет 100. Однако для анализа закупок нам критически важно видеть именно актуальную цену (80 рублей), независимо от того, выше она или ниже предыдущих. Для решения этой задачи нам необходимо сначала вычислить дату последнего документа, а затем «вытащить» цену именно из него.
Наиболее надежный и производительный способ решения данной задачи — использование механизма временных таблиц. Разделим наш алгоритм на три логических этапа: сбор данных о закупках, поиск даты последнего поступления и соединение этих данных.
Шаг 1. Получение основных данных по закупкам
Сначала подготовим таблицу с данными, которые составят основу нашего отчета: контрагент, номенклатура, количество и сумма.
ВЫБРАТЬ
Закупка.Контрагент КАК Контрагент,
Закупка.Номенклатура КАК Номенклатура,
Закупка.КоличествоПриход КАК Количество,
Закупка.ЦенаПриход КАК Цена,
Закупка.СуммаПриход КАК Сумма
ПОМЕСТИТЬ втЗакупки
ИЗ
РегистрНакопления.Закупки.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, , , ) КАК Закупка
;
Шаг 2. Поиск даты последнего поступления
Теперь создадим вторую временную таблицу. Нам нужно найти максимальную дату документа ПоступлениеТоваровУслуг для каждой позиции номенклатуры, которая фигурировала в закупках. Это позволит нам точно идентифицировать самый «свежий» документ.
ВЫБРАТЬ
ПоступлениеТоваровУслугТовары.Номенклатура КАК Номенклатура,
МАКСИМУМ(ПоступлениеТоваровУслугТовары.Ссылка.Дата) КАК МаксДата
ПОМЕСТИТЬ втПоследниеДаты
ИЗ
Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТоваровУслугТовары
ГДЕ
ПоступлениеТоваровУслугТовары.Ссылка.Проведен = ИСТИНА
И ПоступлениеТоваровУслугТовары.Номенклатура В (ВЫБРАТЬ втЗакупки.Номенклатура ИЗ втЗакупки)
СГРУППИРОВАТЬ ПО
ПоступлениеТоваровУслугТовары.Номенклатура
;
Шаг 3. Получение цены из конкретного документа и финальное объединение
На финальном этапе мы соединяем наши закупки с ценами из документов, соответствующих найденным максимальным датам. Обратите внимание: если за одну секунду было проведено два документа с разной ценой, мы дополнительно используем МАКСИМУМ(Цена) для страховки от дублей, хотя в реальном учете такая ситуация встречается редко.
ВЫБРАТЬ
втЗакупки.Контрагент,
втЗакупки.Номенклатура,
втЗакупки.Количество,
втЗакупки.Цена,
втЗакупки.Сумма,
ЕСТЬNULL(втЦены.ПоследняяЦена, 0) КАК ПоследняяЦена
ИЗ
втЗакупки КАК втЗакупки
ЛЕВОЕ СОЕДИНЕНИЕ (
ВЫБРАТЬ
ТабТовары.Номенклатура КАК Номенклатура,
МАКСИМУМ(ТабТовары.Цена) КАК ПоследняяЦена
ИЗ
втПоследниеДаты КАК Даты
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваровУслуг.Товары КАК ТабТовары
ПО Даты.Номенклатура = ТабТовары.Номенклатура
И Даты.МаксДата = ТабТовары.Ссылка.Дата
СГРУППИРОВАТЬ ПО
ТабТовары.Номенклатура
) КАК втЦены
ПО втЗакупки.Номенклатура = втЦены.Номенклатура
В конфигурации Комплексная автоматизация 1.3 существует более архитектурно правильный способ получения цен. Документы поступления при проведении обычно записывают данные в регистр сведений ЦеныНоменклатурыКонтрагентов. Проанализируем преимущества этого метода:
СрезПоследних работает значительно быстрее, чем ручной поиск максимума по табличной части документов.Посмотрим на пример запроса с использованием этого регистра:
ВЫБРАТЬ
втЗакупки.Контрагент,
втЗакупки.Номенклатура,
втЗакупки.Количество,
втЗакупки.Цена КАК ЦенаЗаПериод,
ЦеныСрезПоследних.Цена КАК АктуальнаяЦена
ИЗ
втЗакупки КАК втЗакупки
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатурыКонтрагентов.СрезПоследних(&КонецПериода, ) КАК ЦеныСрезПоследних
ПО втЗакупки.Номенклатура = ЦеныСрезПоследних.Номенклатура
И втЗакупки.Контрагент = ЦеныСрезПоследних.Контрагент
При реализации любого из предложенных подходов следует учитывать несколько критически важных моментов:
1. Использование Момента времени. В системе 1С несколько документов могут иметь одну и ту же дату (секунду). Для системы они различаются по Моменту времени. Если ваш отчет требует абсолютной точности, вместо МАКСИМУМ(Дата) лучше использовать связку Период и Регистратор из регистра накопления или последовательности.
2. Обработка пустых значений. При использовании ЛЕВОЕ СОЕДИНЕНИЕ, если по товару не было поступлений (например, он был введен остатками), в поле цены придет значение NULL. Чтобы отчет выглядел корректно, всегда используйте функцию ЕСТЬNULL(Поле, 0).
3. Сравнение по ссылке, а не по наименованию. Никогда не делайте связь таблиц ПО втЗакупки.Номенклатура.Наименование = втПоступление.Номенклатура.Наименование. Это катастрофически замедляет запрос и приводит к ошибкам, если есть товары с одинаковыми названиями. Всегда соединяйте таблицы по ссылочным полям: ПО втЗакупки.Номенклатура = втПоступление.Номенклатура.
4. Валютный учет. Помните, что в КА 1.3 цены в регистре Закупки могут храниться в валюте управленческого учета, а в документах — в валюте взаиморасчетов. При выводе «Последней цены» убедитесь, что вы приводите все данные к единой валюте, иначе отчет потеряет смысл.
Разберем ситуацию, когда вам нужно получить цену именно из регистра Закупки, а не из документов. Это полезно, если вы хотите учитывать не только поступления, но и, например, оприходования. В этом случае вместо таблицы Документ.ПоступлениеТоваровУслуг.Товары используйте физическую таблицу регистра РегистрНакопления.Закупки, фильтруя ее по виду движения Приход.
Таким образом, комбинируя работу с временными таблицами и понимание структуры метаданных КА 1.3, можно построить эффективный и точный отчет, который покажет не просто обороты, но и актуальную рыночную ситуацию по каждой позиции номенклатуры.