При работе с регистрами накопления в системе 1С:Предприятие, особенно при анализе оборотов за определенный период, разработчики и аналитики часто сталкиваются с задачей корректного отбора данных, включающих как основные документы, так и их корректировки. Мы с вами разберем типовую ситуацию, когда необходимо собрать информацию о количестве и сумме проданной номенклатуры за заданный период, учитывая при этом специфику работы документов корректировки.
Предположим, перед нами стоит задача получить данные по количеству и сумме проданной номенклатуры за определенный период, например, за сентябрь. В выборку должны попасть как документы реализации товаров и услуг, так и документы корректировки реализации, но только те, которые относятся к продажам, совершенным внутри заданного периода.
Наш первоначальный запрос, который мы рассмотрим и проанализируем, выглядит следующим образом:
ВЫБРАТЬ
ПродажиОбороты.Регистратор,
ПродажиОбороты.КоличествоОборот,
ПродажиОбороты.СтоимостьОборот,
ПродажиОбороты.СтоимостьБезСкидокОборот,
ПродажиОбороты.НДСОборот
ИЗ
РегистрНакопления.Продажи.Обороты(
&НачалоПериода,
&КонецПериода,
Регистратор,
ДокументПродажи.Дата МЕЖДУ &НачалоПеиода И &КонецПериода
) КАК ПродажиОбороты
ГДЕ
(ПродажиОбороты.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
ИЛИ ПродажиОбороты.Регистратор ССЫЛКА Документ.КорректировкаРеализации)
УПОРЯДОЧИТЬ ПО
ПродажиОбороты.Регистратор АВТОУПОРЯДОЧИВАНИЕ
На первый взгляд, этот запрос кажется достаточно полным, но у нас возникают вопросы относительно его "уместности" и корректности, особенно в контексте обработки корректировочных документов. Основная проблема, которую мы наблюдаем, заключается в том, что, обозначив период в регистре накопления, мы все равно получаем записи корректировок, которые формально лежат в указанном периоде (по дате проведения самой корректировки), но относятся к документам продаж, лежащим вне заданного периода.
Для глубокого понимания проблемы, мы должны четко различать два ключевых понятия при работе с регистрами накопления в 1С:
Период записи регистра: Это поле, которое платформа 1С автоматически устанавливает для каждой записи регистра накопления. Оно указывает на момент времени, когда произошло движение по регистру. Как правило, в большинстве стандартных конфигураций, Период записи регистра совпадает с датой документа-регистратора. Однако, существуют важные исключения.Дата документа-регистратора: Это дата самого документа, который создал движения в регистре. Для типовых документов, таких как РеализацияТоваровУслуг, Период записи регистра и Дата регистратора обычно совпадают.Суть проблемы с корректировками:
Мы выясним, что сложность возникает при работе с документами типа КорректировкаРеализации или КорректировкаЗаписейРегистров. Представьте следующую ситуацию: документ РеализацияТоваровУслуг был проведен в августе. Спустя месяц, в сентябре, был создан и проведен документ КорректировкаРеализации, который вносит изменения в эту августовскую продажу.
Период записи, созданной КорректировкойРеализации, будет относиться к сентябрю (то есть к дате проведения самой корректировки).ДокументПродажи.Дата (или аналогичное поле, которое ссылается на дату исходной реализации, к которой применяется корректировка) для этой корректировки будет указывать на август.Если мы в запросе к виртуальной таблице Обороты укажем только отбор по Периоду (&НачалоПериода, &КонецПериода), например, за сентябрь, то записи корректировок, проведенных в сентябре, но ссылающихся на августовские продажи, попадут в выборку. А нам, согласно задаче, нужны только те корректировки, которые относятся к продажам, совершенным именно в сентябре (или другом заданном периоде). Это объясняет, почему мы все равно получаем записи, которые "лежат вне периода" в контексте даты исходного документа продажи.
Рассмотрим, почему запрос, предложенный автором, является уместным и правильным для решения поставленной задачи.
Обороты:
Мы видим, что в виртуальной таблице РегистрНакопления.Продажи.Обороты() используются следующие параметры:
РегистрНакопления.Продажи.Обороты(
&НачалоПериода,
&КонецПериода,
Регистратор,
ДокументПродажи.Дата МЕЖДУ &НачалоПериода И &КонецПериода
)
&НачалоПериода, &КонецПериода: Эти первые два параметра осуществляют отбор по Периоду самой записи регистра. То есть, они гарантируют, что в выборку попадут только те движения, которые были зарегистрированы в указанном диапазоне дат. Это наш первый уровень фильтрации.ДокументПродажи.Дата МЕЖДУ &НачалоПериода И &КонецПериода: Этот четвертый параметр (после параметра "ПолеГруппировки", в данном случае — Регистратор) является критически важным и ключевым для решения нашей задачи. Он позволяет отфильтровать записи таким образом, чтобы в выборку попали только те движения (как реализации, так и их корректировки), у которых дата исходного документа продажи (на который ссылается движение через измерение или реквизит регистра) находится в пределах нашего интересующего периода. Именно это условие позволяет нам "отсеять" корректировки, проведенные в текущем периоде, но относящиеся к продажам из прошлых периодов.Таким образом, мы с вами используем двойной механизм отбора: сначала по дате регистрации самого движения (Период записи), а затем по дате исходного документа, что позволяет точно выполнить требование задачи — получить данные о продажах и их корректировках, относящихся к продажам именно за указанный период.
ГДЕ:
Условие в секции ГДЕ также играет важную роль в нашем запросе:
ГДЕ
(ПродажиОбороты.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
ИЛИ ПродажиОбороты.Регистратор ССЫЛКА Документ.КорректировкаРеализации)
Мы четко указываем, что нас интересуют только движения, созданные документами РеализацияТоваровУслуг и КорректировкаРеализации. Это условие исключает из выборки другие типы документов, которые могли бы также создавать движения в регистре Продажи, тем самым сужая результат до релевантных сущностей.
Как видим, такой запрос действительно уместен. Он грамотно учитывает различия между датой регистрации движения и датой документа, который корректируется, что крайне важно для получения корректной аналитики по продажам. Отбор ДокументПродажи.Дата МЕЖДУ &НачалоПериода И &КонецПериода внутри виртуальной таблицы является необходимым и адекватным способом получить требуемый результат.
Рассмотрим подробнее некоторые важные моменты, связанные с датами и периодами в регистрах 1С, которые помогут нам глубже понять логику построения подобных запросов:
Период движения регистра совпадает с Датой документа, который это движение создал, существуют исключения. Особенно это касается документов корректировки. Например, документ "Корректировка" (который в разных конфигурациях может называться "Корректировка документов", "Корректировка записей регистров" или "Корректировка реализации") позволяет напрямую добавлять записи регистров с любыми значениями их периода. Таким образом, Период записи может быть выставлен разработчиком или системой на дату проведения корректировки, в то время как корректируемый документ был проведен гораздо раньше. Также бывают документы с дополнительными реквизитами-датами (например, дата оплаты или дата отгрузки), которые могут влиять на Период записей по отдельным регистрам, особенно управленческого характера. В таких случаях Период записи регистра по одним регистрам будет совпадать с датой документа, а по другим может отличаться.КОНЕЦПЕРИОДА(). Например, если параметр &КонецПериода задан как 30.09.2023 00:00:00, то для того, чтобы в выборку попали все записи за 30 сентября (включая те, что были созданы в конце дня), нам необходимо использовать КОНЕЦПЕРИОДА(&КонецПериода, ДЕНЬ). Это гарантирует, что верхняя граница периода будет расширена до 30.09.2023 23:59:59, и все записи за указанный день будут учтены.Для обеспечения максимальной производительности запроса к регистру накопления мы с вами рассмотрим несколько важных рекомендаций, которые помогут получить данные не только корректно, но и быстро:
РегистрНакопления.Продажи.Обороты()). Платформа 1С транслирует эти параметры в условия на уровне СУБД, что позволяет базе данных применять фильтрацию на самых ранних этапах выполнения запроса, значительно сокращая объем обрабатываемых данных. Использование условий в секции ГДЕ, которые можно было бы передать в параметры виртуальной таблицы, может привести к тому, что сначала будут выбраны избыточные данные, а затем к ним применится отбор, что негативно скажется на производительности. Например, условия по Регистратору и ДокументПродажи.Дата, если они не являются измерениями или реквизитами регистра, которые можно передать в параметры, должны быть в ГДЕ. Однако, если платформа позволяет передать отбор по ссылочным полям через параметры (как в нашем случае ДокументПродажи.Дата), это всегда предпочтительнее.КОНЕЦПЕРИОДА(): Как мы уже упоминали, это критически важно для корректного включения всего последнего дня периода. Всегда используйте, например, КОНЕЦПЕРИОДА(&КонецПериода, ДЕНЬ) для параметров, отвечающих за конец периода, чтобы избежать потери данных за последний день.Период, по всем измерениям регистра, а также по Регистратору. Наш запрос, который фильтрует данные по Периоду, Регистратору и измерению, связанному с датой продажи (ДокументПродажи.Дата, если это измерение или реквизит с индексацией), эффективно задействует эти индексы, что способствует быстрой выборке данных.В заключение мы подтверждаем, что предложенный автором запрос является полностью уместным и корректным решением для поставленной задачи. Он учитывает все необходимые нюансы работы с регистрами накопления, в частности, разницу между Периодом записи и Датой документа-регистратора, что позволяет точно отбирать данные о продажах и их корректировках за интересующий период. Фильтрация ДокументПродажи.Дата внутри параметров виртуальной таблицы Обороты является адекватным способом получения именно тех данных, которые соответствуют требованиям.
Следуя представленным рекомендациям по оптимизации, мы можем обеспечить не только корректность, но и высокую производительность наших запросов к регистрам накопления в 1С:Предприятие, что является ключевым для эффективной работы с большими объемами данных.