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