При работе с регистрами накопления в системе «1С:Предприятие 8» начинающие разработчики часто сталкиваются с ситуацией, когда привычные поля, такие как ВидДвижения (Приход или Расход), отсутствуют в списке доступных полей конструктора запроса. Особенно часто это происходит при анализе продаж в конфигурации «Управление торговлей 10.3» или аналогичных решениях на базе обычных форм. Давайте разберем, почему так происходит, и научимся правильно настраивать фильтрацию данных для получения корректной аналитики по возвратам и реализациям.
Прежде чем приступать к написанию запроса, нам необходимо проанализировать структуру метаданных. В 1С существуют два основных типа регистров накопления:
ТоварыНаСкладах). У таких регистров есть физическое поле ВидДвижения, которое может принимать значения Приход (увеличение остатка) или Расход (уменьшение остатка).Продажи). В этих регистрах нет понятия «остаток», а значит, нет и направления движения «приход/расход» в техническом понимании платформы. Каждая запись — это просто зафиксированный оборот.Рассмотрим ситуацию автора: попытка отобрать «Расход» в регистре Продажи не имеет смысла, так как этот регистр является оборотным. В нем фиксируется сумма и количество проданного товара, а возвраты обычно записываются либо отдельным типом документа, либо стонирующими (отрицательными) записями.
Если наша задача — выделить возвраты покупателей в регистре Продажи, наиболее правильным путем будет установка фильтра по типу документа, который сформировал запись. Разберем по шагам, как это сделать в конструкторе запроса:
Продажи.Обороты.Регистратор.ССЫЛКА, чтобы ограничить выборку конкретным типом метаданных.В тексте запроса это будет выглядеть следующим образом:
ГДЕ
ПродажиОбороты.Регистратор ССЫЛКА Документ.ВозвратТоваровОтПокупателя
Проанализируем это решение. Данный подход позволяет нам четко отделить записи, созданные специализированным документом возврата. Однако, как справедливо заметили опытные участники обсуждения, в системе могут существовать и другие документы, влияющие на продажи, например, КорректировкаЗаписейРегистров (КЗР). Если мы ограничимся только «Возвратом», данные из КЗР не попадут в отчет.
Для повышения производительности системы мы рекомендуем накладывать условия не в секции ГДЕ, а непосредственно в параметрах виртуальной таблицы. Выясним причину: когда условие стоит в ГДЕ, СУБД сначала выбирает все записи из таблицы оборотов, а потом фильтрует их. Если же условие передано в параметры виртуальной таблицы, платформа 1С старается максимально оптимизировать SQL-запрос, чтобы отсечь лишние данные на самом раннем этапе.
Чтобы реализовать это в конструкторе:
ПродажиОбороты.
Регистратор ССЫЛКА Документ.ВозвратТоваровОтПокупателя
Важный нюанс: Если вам нужно отобрать несколько типов документов (например, возвраты и корректировки реализации), используйте оператор В с перечислением типов или проверку на массив типов, хотя в параметрах виртуальных таблиц чаще всего используется простое перечисление через логическое «ИЛИ».
В некоторых учетных схемах возврат может оформляться не отдельным документом, а тем же документом РеализацияТоваровУслуг, но с отрицательным количеством (сторно). В этом случае фильтрация по типу регистратора нам не поможет. Рассмотрим, как в таком случае выделить «возвраты» (отрицательные движения).
Проанализируем ситуацию: в регистре оборотов поле КоличествоОборот (или СтоимостьОборот) будет иметь отрицательное значение при сторнировании. Мы можем добавить условие на знак числа:
ВЫБРАТЬ
ПродажиОбороты.Номенклатура,
ПродажиОбороты.КоличествоОборот КАК Количество
ИЗ
РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК ПродажиОбороты
ГДЕ
ПродажиОбороты.КоличествоОборот < 0
Этот метод хорош тем, что он «видит» любые уменьшения продаж, независимо от того, каким документом они были сделаны. Но будьте осторожны: если ваша цель — получить чистую выручку, то такие фильтры вообще не нужны. Платформа 1С в виртуальной таблице Обороты автоматически складывает положительные и отрицательные значения, выдавая итоговый результат за период.
Если бы мы работали с регистром остатков (например, ТоварыНаСкладах), то совет из сообщения №10 был бы абсолютно верным. В конструкторе запроса для физической таблицы регистра или таблицы ДвиженияССубконто (для бухгалтерии) мы бы использовали обращение к системному перечислению. Посмотрим на пример кода для такого случая:
ВЫБРАТЬ
ТоварыНаСкладах.Номенклатура,
ТоварыНаСкладах.Количество
ИЗ
РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах
ГДЕ
ТоварыНаСкладах.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)
Однако помните, что в регистре Продажи поля ВидДвижения не существует. Попытка написать такое условие приведет к ошибке: «Поле не найдено "ВидДвижения"».
Для решения задачи автора в «УТ 10.3» по регистру Продажи мы рекомендуем использовать следующий алгоритм:
Регистратор ССЫЛКА Документ.ВозвратТоваровОтПокупателя в параметрах виртуальной таблицы.КоличествоОборот < 0.КоличествоОборот и ВыручкаОборот без лишних фильтров по виду движения, так как система сама вычтет возвраты из реализаций при расчете итогового оборота.Такой комплексный подход позволит вам строить гибкие и производительные отчеты, избегая типичных ошибок, связанных с непониманием архитектуры регистров накопления.