Почему в отчете СКД выводятся неверные начальные и конечные остатки при детализации до регистратора?

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

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

Анализ исходной ситуации и архитектурных ошибок

Проанализируем запрос, представленный автором темы. Мы видим использование временных таблиц и последующее левое соединение. В первом пакете запроса данные выбираются из виртуальной таблицы ОстаткиИОбороты регистра накопления ДО_ВзаиморасчетыСБанками.


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    ТИПЗНАЧЕНИЯ(ДО_ВзаиморасчетыСБанкамиОстаткиИОбороты.Регистратор.Ссылка) КАК ТипДокумента,
    ДО_ВзаиморасчетыСБанкамиОстаткиИОбороты.Регистратор,
    ДО_ВзаиморасчетыСБанкамиОстаткиИОбороты.Документ,
    ДО_ВзаиморасчетыСБанкамиОстаткиИОбороты.СуммаНачальныйОстаток,
    ДО_ВзаиморасчетыСБанкамиОстаткиИОбороты.СуммаКонечныйОстаток,
    ...
ПОМЕСТИТЬ ВТ_ВзаиморасчетыСБанками
ИЗ
    РегистрНакопления.ДО_ВзаиморасчетыСБанками.ОстаткиИОбороты(,, Регистратор, , ) КАК ДО_ВзаиморасчетыСБанкамиОстаткиИОбороты;

Первая критическая ошибка, которую мы можем заметить, заключается в том, что параметры виртуальной таблицы (начало и конец периода) оставлены пустыми в тексте запроса. Хотя в СКД существует механизм автозаполнения, использование временных таблиц часто «сбивает» этот механизм. Когда мы помещаем данные во временную таблицу, СКД перестает видеть, что поле СуммаНачальныйОстаток — это именно остаток на начало периода. Для системы это становится просто числовым полем.

Решение 1: Правильная передача параметров в виртуальную таблицу

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


ИЗ
    РегистрНакопления.ДО_ВзаиморасчетыСБанками.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Регистратор, , ) КАК ДО_ВзаиморасчетыСБанкамиОстаткиИОбороты

Важный нюанс: никогда не используйте условие ГДЕ для фильтрации по датам в итоговом запросе, если вы работаете с остатками. Если мы напишем ГДЕ Период МЕЖДУ &НачалоПериода И &КонецПериода вне виртуальной таблицы, мы просто отсечем записи, не входящие в интервал. Однако для расчета остатков СКД требуются движения за предыдущие периоды. Фильтрация должна происходить «внутри» виртуальной таблицы, чтобы механизм расчета итогов отработал корректно.

Решение 2: Настройка ролей полей (самый важный этап)

Поскольку автор использует временные таблицы, СКД «теряет» информацию о ролях полей. Нам необходимо вручную зайти на закладку «Набор данных» и настроить колонку «Роль» для ключевых полей. Выясним, какие настройки обязательны:

  1. Период: Укажите роль Период и установите порядковый номер 1.
  2. Регистратор: Укажите роль Период и установите порядковый номер 2. Также крайне желательно поставить галочку «Обязательное». Это скажет СКД, что данное поле является частью временной оси, и именно по нему нужно определять последовательность движений.
  3. Начальный остаток: В роли поля выберите тип Остаток, укажите имя (например, «Сумма»), тип остатка — «Начальный», и обязательно укажите поле периода (то самое, которому мы присвоили номер 1).
  4. Конечный остаток: Аналогично начальному, но тип остатка — «Конечный».

Если эти роли не заданы, СКД будет воспринимать остатки как обычные ресурсы (как приход или расход) и начнет их просто суммировать. В итоге в группировке по контрагенту вы получите сумму всех начальных остатков всех его документов, что фактически является бессмысленным числом.

Решение 3: Проблема «размножения» остатков при соединениях

Проанализируем финальную часть запроса автора, где происходит ЛЕВОЕ СОЕДИНЕНИЕ с таблицей ВТ_СтатусыДокументов. Рассмотрим риск: если для одного документа (объекта) в регистре сведений окажется две записи (например, история статусов или ошибка данных), то строка с документом в результате запроса продублируется.

Поскольку остаток — это ресурс, СКД просуммирует его по всем строкам. Если остаток по документу был 100 рублей, а после соединения появилось две строки, в отчете вы увидите 200 рублей. Как этого избежать?

Профессиональный подход в 1С заключается в разделении данных. Рекомендуется вынести получение статусов в отдельный набор данных. Затем на закладке «Связи наборов данных» нужно связать основной набор (с остатками) и дополнительный (со статусами) по полю Документ. В этом случае СКД сначала вычислит верные итоги по регистрам, а затем просто «подтянет» текстовые значения статусов, не влияя на арифметику остатков.

Решение 4: Настройка ресурсов и расчет по группировкам

Посмотрим на закладку «Ресурсы». Для полей остатков функция должна быть Сумма(СуммаНачальныйОстаток). Однако, чтобы избежать некорректного вывода на разных уровнях иерархии, полезно использовать колонку «Рассчитывать по...».

Для остатков не имеет смысла расчет по группировкам периодов (день, месяц), если они не являются самыми нижними в иерархии. Выясним причину: начальный остаток за месяц — это остаток на 1-е число, а не сумма начальных остатков всех дней месяца. Правильно настроенные роли (пункт 2) обычно решают это автоматически, но явное указание группировок в ресурсах дает дополнительный контроль.

Резюме: контрольный список для проверки отчета

Если ваш отчет на СКД показывает «странные» начальные остатки, пройдите по этому списку:

  1. Проверьте, передаются ли параметры &НачалоПериода и &КонецПериода непосредственно в виртуальную таблицу регистра.
  2. Убедитесь, что в запросе нет условий ГДЕ, которые могут отсекать движения, необходимые для расчета остатка.
  3. В наборе данных проверьте роли для полей Период (номер 1) и Регистратор (номер 2, обязательное).
  4. Убедитесь, что у полей остатков проставлены роли Остаток (Начальный/Конечный) с привязкой к полю периода.
  5. Если используется соединение с другими таблицами, проверьте, не происходит ли дублирования строк. Лучше используйте связь наборов данных.

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

← На главную