Как в СКД получить остатки на дату документа, если передается только один параметр со ссылкой на документ?

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

При разработке проверок проведения, встроенных отчетов или механизмов валидации данных в 1С разработчики часто сталкиваются с ограничением: вызывающий механизм передает в схему компоновки данных (СКД) только один параметр — ссылку на текущий документ (например, &ТекущийОбъект). Возникает задача: получить остатки по номенклатуре из табличной части этого документа на момент его даты, не имея возможности явно передать отдельный параметр &Период из встроенного языка 1С.

Разберем, почему попытка обратиться через точку к реквизиту объекта прямо в тексте запроса вызывает ошибку, и рассмотрим рабочие способы решения этой задачи.

Почему конструкция &ТекущийОбъект.Дата не работает в параметрах виртуальной таблицы

В языке запросов 1С действуют строгие синтаксические ограничения на параметры виртуальных таблиц. Если в секции ГДЕ допускается разыменование ссылок (например, Поле.Ссылка = &ТекущийОбъект), то в параметрах виртуальных таблиц (таких как РегистрБухгалтерии.Хозрасчетный.Остатки(&Период, ...)) использование обращений через точку вида &ТекущийОбъект.Дата запрещено синтаксисом платформы.

Параметр виртуальной таблицы принимает только простые имена параметров, литералы или значения NULL. Кроме того, язык запросов не позволяет передать значение даты из временной таблицы одного запроса пакета в параметры виртуальной таблицы другого запроса пакета.

Однако возможности схемы компоновки данных позволяют элегантно обойти это ограничение несколькими путями.

Способ 1. Использование вычисляемых выражений в параметрах СКД

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

Проанализируем пошаговую настройку схемы:

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

При выполнении отчета СКД сначала вычислит значение параметра &ТекущийОбъект, затем автоматически рассчитает зависимый параметр &Период и передаст его в виртуальную таблицу остатков.

Способ 2. Связи наборов данных (многонаборная схема СКД)

Если логика выборки требует динамического сопоставления или работы со списком документов, применим механизм связей наборов данных.

Разберем реализацию схемы из двух наборов данных:

  1. НаборДанных1 (Запрос): извлекает данные документа и его дату.
    
    ВЫБРАТЬ
        ДокументПоступление.Дата КАК ДатаДокумента,
        ПоступлениеТовары.Номенклатура КАК Номенклатура,
        ПоступлениеТовары.Количество КАК Количество
    ИЗ
        Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТовары
            ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваровУслуг КАК ДокументПоступление
            ПО ПоступлениеТовары.Ссылка = ДокументПоступление.Ссылка
    ГДЕ
        ПоступлениеТовары.Ссылка = &ТекущийОбъект
    
  2. НаборДанных2 (Запрос): выбирает остатки с параметризованным отбором.
    
    ВЫБРАТЬ
        ХозрасчетныйОстатки.Субконто1 КАК Номенклатура,
        ХозрасчетныйОстатки.КоличествоОстаток КАК Остаток
    ИЗ
        РегистрБухгалтерии.Хозрасчетный.Остатки(
            &ПериодОстатков,
            Счет = ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.ТоварыНаСкладах),
            ,
            Субконто1 = &Номенклатура
        ) КАК ХозрасчетныйОстатки
    
  3. На вкладке «Связи наборов данных» настроим связь:
    • Источник связи: НаборДанных1
    • Приемник связи: НаборДанных2
    • Условие связи: поле Номенклатура связывается с параметром приемника &Номенклатура.
    • Связь по дате: поле ДатаДокумента источника связывается с параметром приемника &ПериодОстатков.

В этом случае платформа сама выполнит передачу вычисленной даты из первой выборки в параметры виртуальной таблицы остатков для каждой записи.

Способ 3. Выборка из реальной таблицы движений регистра

В ситуациях, когда обращение к виртуальным таблицам остатков невозможно из-за специфических ограничений вызывающего механизма, можно обратиться напрямую к таблице движений с субконто (РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто).

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


ВЫБРАТЬ
    ПоступлениеТовары.Номенклатура КАК Номенклатура,
    СУММА(ЕСТЬNULL(Движения.Количество, 0)) КАК ОстатокНаДату
ИЗ
    Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТовары
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто КАК Движения
        ПО ПоступлениеТовары.Номенклатура = Движения.Субконто1
            И Движения.Счет = ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.ТоварыНаСкладах)
            И Движения.Период <= &ТекущийОбъект.Дата
            И Движения.Активность = ИСТИНА
ГДЕ
    ПоступлениеТовары.Ссылка = &ТекущийОбъект
СГРУППИРОВАТЬ ПО
    ПоступлениеТовары.Номенклатура

Важно: этот способ создает повышенную нагрузку на СУБД при больших объемах базы, так как платформа сканирует физическую таблицу всех проводок за всю историю вместо использования предварительно рассчитанных итогов. Рекомендуется использовать вычисляемые выражения СКД (Способ 1) как наиболее быстродействующее и масштабируемое решение.

← На главную