Почему в СКД на платформе 8.3.27 ломаются итоги и как это исправить

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

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

Суть проблемы: когда остатки превращаются в "кашу"

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

Проанализируем исходный запрос, который вызывает проблему:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    НАЧАЛОПЕРИОДА(ПартииТоваровНаСкладахОстаткиИОбороты.Период, МЕСЯЦ) КАК Период,
    ПартииТоваровНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура,
    ПартииТоваровНаСкладахОстаткиИОбороты.Склад КАК Склад,
    СУММА(ПартииТоваровНаСкладахОстаткиИОбороты.КоличествоНачальныйОстаток) КАК НачальныйОстаток,
    СУММА(ПартииТоваровНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток) КАК КонечныйОстаток,
    РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(&НачалоПериода, МЕСЯЦ), КОНЕЦПЕРИОДА(&КонецПериода, МЕСЯЦ), ДЕНЬ) + 1 КАК ДнейВПериоде
ИЗ
    РегистрНакопления.ПартииТоваровНаСкладах.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Месяц, , {(Склад).* КАК Склад, (Номенклатура).* КАК Номенклатура}) КАК ПартииТоваровНаСкладахОстаткиИОбороты
СГРУППИРОВАТЬ ПО
    НАЧАЛОПЕРИОДА(ПартииТоваровНаСкладахОстаткиИОбороты.Период, МЕСЯЦ),
    ПартииТоваровНаСкладахОстаткиИОбороты.Номенклатура,
    ПартииТоваровНаСкладахОстаткиИОбороты.Склад

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

Изменение логики оптимизатора в 1С 8.3.27

Начиная с релизов ветки 8.3.27, разработчики платформы внедрили более агрессивную оптимизацию SQL-запросов, генерируемых СКД. Теперь система пытается максимально сократить текст запроса к СУБД, выбрасывая те поля и группировки, которые не участвуют в финальном отображении данных.

Если в схеме компоновки данных для полей измерений (Склад, Номенклатура) или периода не указаны жесткие правила их поведения, СКД может решить, что их можно не учитывать при расчете промежуточных итогов. В результате вместо получения срезов на начало и конец периода, платформа выполняет простое сложение всех записей, попадающих в выборку. Именно наличие расчетного поля (такого как РАЗНОСТЬДАТ) часто "заставляло" оптимизатор выполнять запрос более полно, что скрывало проблему в старых версиях платформы.

Способ 1: Настройка ролей полей (Основное решение)

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

  1. Перейдем на закладку "Наборы данных".
  2. В списке полей найдем наши измерения: Склад и Номенклатура.
  3. В колонке "Роль" нажмем на кнопку редактирования.
  4. Убедимся, что установлены флажки "Измерение".
  5. Критически важно: установим флаг "Обязательное". Этот флаг запрещает оптимизатору СКД исключать поле из запроса, даже если оно не выбрано пользователем в настройках.
  6. Аналогичную операцию проведем для поля Период. В роли поля периода должен быть указан тип периода (например, "День", "Месяц") и также установлен флаг "Обязательное".

После установки флага Обязательное, структура группировок в SQL-запросе сохранится неизменной, что позволит виртуальной таблице ОстаткиИОбороты корректно вычислить значения ресурсов.

Способ 2: Включение оборотных полей в запрос

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


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    ПартииТоваровНаСкладахОстаткиИОбороты.Период КАК Период,
    ПартииТоваровНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура,
    ПартииТоваровНаСкладахОстаткиИОбороты.Склад КАК Склад,
    ПартииТоваровНаСкладахОстаткиИОбороты.КоличествоНачальныйОстаток КАК НачальныйОстаток,
    ПартииТоваровНаСкладахОстаткиИОбороты.КоличествоПриход КАК Приход,
    ПартииТоваровНаСкладахОстаткиИОбороты.КоличествоРасход КАК Расход,
    ПартииТоваровНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток КАК КонечныйОстаток
ИЗ
    РегистрНакопления.ПартииТоваровНаСкладах.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Месяц, , ) КАК ПартииТоваровНаСкладахОстаткиИОбороты

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

Способ 3: Отказ от ручной группировки

Заметим, что в исходном запросе автора присутствовала конструкция СГРУППИРОВАТЬ ПО. В СКД использование ручной группировки в основном тексте запроса при работе с виртуальными таблицами остатков часто является избыточным или даже вредным.

Рассмотрим рекомендации:

Проверка механизма "Автозаполнение"

При использовании платформы 8.3.27 рекомендуется выполнить "перезагрузку" метаданных схемы:

  1. Откройте схему компоновки данных.
  2. Снимите флаг "Автозаполнение" у набора данных.
  3. Установите его обратно.
  4. Проверьте, какие роли система назначила полям автоматически.
  5. Если для полей остатков роли не заполнились (не указано "Начальный остаток" / "Конечный остаток" в свойствах роли), проставьте их вручную, связав с соответствующими полями и измерениями.

Выясним также важный момент: если вы используете расчетные выражения для периодов (как НАЧАЛОПЕРИОДА(Период, МЕСЯЦ)), убедитесь, что в параметрах виртуальной таблицы указана соответствующая периодичность (в нашем случае Месяц). Несоответствие периодичности виртуальной таблицы и группировок в запросе — частая причина "бредовых" остатков.

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

← На главную