Как выбрать документы реализации за день при превышении суммарного количества номенклатуры?

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

При разработке отчетов и обработок в 1С часто возникает задача: отобрать документы не по количеству в каждой отдельной строке или накладной, а по общему итогу за период (например, за день). Если за сутки клиент приобрел определенные позиции номенклатуры в суммарном объеме больше порогового значения (например, более 50 штук суммарно по нескольким накладным), в результат должны попасть все эти документы с соответствующими строками.

Рассмотрим несколько способов реализации такого отбора: с помощью пакетного запроса к табличным частям документов, через виртуальные таблицы регистров накопления и средствами системы компоновки данных (СКД).

Способ 1. Пакетный запрос с использованием временных таблиц

Разберем по шагам классический подход. Главная ошибка при решении этой задачи — попытка наложить фильтр ИМЕЮЩИЕ СУММА(Количество) > 50 в одном запросе с детализацией по документам. В таком случае отсекутся накладные, в которых количество меньше 50, даже если за весь день суммарный объем превысил порог.

Правильный алгоритм строится в два этапа:

  1. Расчет итогов за день во временной таблице: группируем продажи по контрагенту и началу дня, суммируем количество по списку номенклатуры и отсекаем дни условием в секции ИМЕЮЩИЕ.
  2. Выборка документов: соединяем табличную часть документов с подготовленной временной таблицей по полям контрагента и даты, приведенной к началу дня.

Посмотрим на пример текста пакетного запроса:


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

ИНДЕКСИРОВАТЬ ПО
    Контрагент,
    ПериодДень
;

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

Важные детали реализации:

  1. Обязательно используем функцию НАЧАЛОПЕРИОДА(Дата, ДЕНЬ), чтобы объединить все реализации за конкретные календарные сутки независимо от времени проведения.
  2. Условие РеализацияТовары.Ссылка.Проведен = ИСТИНА гарантирует, что непроведенные и помеченные на удаление документы не повлияют на суммарный расчет.
  3. Индексация временной таблицы ИНДЕКСИРОВАТЬ ПО повышает производительность при соединении с большой табличной частью.

Способ 2. Запрос к регистру накопления «Продажи»

Если в базе ведется оперативный учет, обращение к таблицам документов менее эффективно, чем работа с регистром накопления (например, РегистрНакопления.Продажи). В регистре количество хранится в базовых единицах, а таблицы оптимизированы для быстрых агрегатных расчетов.

Проанализируем структуру запроса к регистру накопления с отбором регистраторов типа Документ.РеализацияТоваровУслуг:


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

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

Здесь в первой таблице обороты рассчитываются с периодичностью День, а во втором запросе — с детализацией до Регистратор, что исключает попадание лишних дней и документов.

Способ 3. Реализация через Систему компоновки данных (СКД)

Если задача заключается в формировании отчета, можно обойтись без сложных соединений в тексте запроса и настроить отбор на уровне группировок СКД:

  1. В схеме компоновки данных пишем простой запрос, выбирающий поля: Контрагент, Период (с периодичностью День), Регистратор, Номенклатура и Количество.
  2. На вкладке Настройки выстраиваем иерархическую структуру группировок:
    — Группировка 1: Контрагент
    —— Группировка 2: ПериодДень
    ——— Группировка 3: Регистратор
    ———— Группировка 4: Номенклатура
  3. Выделяем группировку ПериодДень, переходим на ее вкладку Отбор и добавляем условие:
    Сумма(Количество) Больше 50.

При таком подходе СКД автоматически рассчитает сумму на уровне группировки дня и скроет все дни (вместе со вложенными документами), в которых общее количество проданного товара не достигло 50 единиц.

← На главную