При разработке отчетов на Системе Компоновки Данных (СКД) для конфигураций на базе ERP (Управление торговлей 11, Комплексная автоматизация 2, ERP) программисты часто сталкиваются с ситуацией, когда математика отчета "ломается". Вроде бы запрос написан верно, используются виртуальные таблицы остатков и оборотов, но при переходе через дату остаток не сходится: конечный остаток одного дня не равен начальному остатку следующего, или общие итоги отображаются некорректно.
Особенно часто это проявляется при работе с регистрами накопления новой архитектуры, такими как ТоварыОрганизаций, где измерениями являются не сами сущности (Номенклатура, Склад), а ссылки на справочники-ключи аналитики (например, АналитикаУчетаНоменклатуры).
В этой статье мы подробно разберем, почему возникает такая ошибка, и пошагово настроим схему компоновки данных так, чтобы отчет формировался корректно.
Рассмотрим ситуацию, с которой столкнулся автор. Имеется простой отчет, выбирающий данные из регистра накопления ТоварыОрганизаций.ОстаткиИОбороты. Запрос выглядит логично:
ВЫБРАТЬ
ТоварыОрганизаций.ОстаткиИОбороты.Организация КАК Организация,
ТоварыОрганизаций.ОстаткиИОбороты.КоличествоНачальныйОстаток,
ТоварыОрганизаций.ОстаткиИОбороты.КоличествоКонечныйОстаток,
ТоварыОрганизаций.ОстаткиИОбороты.КоличествоРасход,
ТоварыОрганизаций.ОстаткиИОбороты.АналитикаУчетаНоменклатуры.Номенклатура КАК Номенклатура,
ТоварыОрганизаций.ОстаткиИОбороты.Период
ИЗ
РегистрНакопления.ТоварыОрганизаций.ОстаткиИОбороты(&Начало, &Конец, День, , ) КАК ТоварыОрганизаций
Однако при формировании отчета мы видим странное поведение: 28-го числа происходит реализация, она попадает в расход, но 29-го числа начальный остаток не соответствует конечному остатку за 28-е. Физически в регистре запись есть, но СКД "теряет" переходящий остаток или дублирует его.
Причина кроется в механизме работы СКД с разадресованными полями (когда мы обращаемся через точку: АналитикаУчетаНоменклатуры.Номенклатура) и отсутствии четкой хронологии для расчета остатков внутри системы компоновки.
Первое, что нам необходимо сделать — это обеспечить СКД достаточным количеством данных для правильного выстраивания хронологической последовательности. Если мы используем периодичность Авто (что рекомендуется) или хотим видеть детальные записи, нам нужны поля периодов разной детальности.
Одной из главных ошибок является отсутствие поля ПериодСекунда и поля Регистратор, если отчет предполагает детализацию или если движения происходят в один момент времени.
Давайте изменим запрос. Нам необходимо:
Авто. Это позволит СКД самой выбирать оптимальный разрез данных.ПериодСекунда, ПериодДень (или другие периоды, если нужны).Регистратор. Оно критически важно для однозначного определения порядка записей.Правильный текст запроса будет выглядеть так:
ВЫБРАТЬ
ТоварыОрганизаций.ОстаткиИОбороты.Организация КАК Организация,
ТоварыОрганизаций.ОстаткиИОбороты.КоличествоНачальныйОстаток КАК КоличествоНачальныйОстаток,
ТоварыОрганизаций.ОстаткиИОбороты.КоличествоКонечныйОстаток КАК КоличествоКонечныйОстаток,
ТоварыОрганизаций.ОстаткиИОбороты.КоличествоРасход КАК КоличествоРасход,
ТоварыОрганизаций.ОстаткиИОбороты.АналитикаУчетаНоменклатуры.Номенклатура КАК Номенклатура,
ТоварыОрганизаций.ОстаткиИОбороты.АналитикаУчетаНоменклатуры.СкладскаяТерритория КАК Склад,
ТоварыОрганизаций.ОстаткиИОбороты.ПериодСекунда КАК ПериодСекунда,
ТоварыОрганизаций.ОстаткиИОбороты.ПериодДень КАК ПериодДень,
ТоварыОрганизаций.ОстаткиИОбороты.Регистратор КАК Регистратор
ИЗ
РегистрНакопления.ТоварыОрганизаций.ОстаткиИОбороты(&Начало, &Конец, Авто, , ) КАК ТоварыОрганизаций
Обратите внимание: даже если пользователь не просит выводить регистратор в отчет, это поле необходимо для внутренних расчетов движка СКД.
Самого изменения запроса часто недостаточно. Если просто добавить поля, результат может не измениться. Магия происходит на вкладке Наборы данных при настройке колонок в таблице полей. Нам нужно правильно сконфигурировать колонку Роль.
СКД должна понимать, какое поле является "старшим" в иерархии времени, а какое "младшим". Это делается с помощью нумерации периодов.
Разберем настройку ролей для наших полей времени:
Регистратор
Это самая детальная единица измерения времени (момент возникновения записи). Для него устанавливаем роль Период, и обязательно ставим номер 1.
Также рекомендуется для поля Регистратор установить флаг Обязательное, если вы хотите гарантировать корректный расчет остатков даже при сворачивании группировок, хотя в современных платформах это обрабатывается лучше.
ПериодСекунда
В настройках роли указываем, что это Период, и ставим номер 2.
Важный момент: убедитесь, что флажок Дополнительный снят (если он там есть по умолчанию).
ПериодДень (и другие периоды: Месяц, Год...)
Устанавливаем роль Период и ставим номер 3 (для месяца — 4 и т.д.).
Почему это важно?
Когда СКД рассчитывает НачальныйОстаток и КонечныйОстаток, она фактически строит временную ось. Если у нее нет четкого указания, что Регистратор вложен в Секунду, а Секунда в День, она может неправильно сгруппировать записи. Например, приход и расход внутри одной секунды могут схлопнуться, и конечный остаток рассчитается неверно, если не будет указан Регистратор как определяющий фактор порядка записей.
В конфигурации УТ 11/ERP регистр ТоварыОрганизаций имеет измерение АналитикаУчетаНоменклатуры. Это справочник, содержащий комбинацию Номенклатуры, Характеристики и Серии.
Когда в запросе мы пишем АналитикаУчетаНоменклатуры.Номенклатура, происходит неявное соединение с таблицей справочника.
Если в базе данных по одной Номенклатуре есть остатки на двух разных ключах аналитики (например, разные серии, которые мы не выводим в отчет), СКД должна сначала рассчитать остатки по ключам, а потом сложить их.
Для корректной работы в сложных случаях рекомендуется:
АналитикаУчетаНоменклатуры (можно не выводить его пользователю, но оно должно быть в запросе).Однако, как показала практика обсуждения, при правильной настройке ролей периодов (Шаг 2), проблема с "плывущими" остатками решается даже при простой группировке по Номенклатуре.
Если вы столкнулись с тем, что отчет на СКД показывает неверные итоги или остатки:
Регистратор: Период, 1.ПериодСекунда: Период, 2.ПериодДень: Период, 3.Сумма(КоличествоНачальныйОстаток) и т.д.).После выполнения этих действий пересчет итогов в отчете начнет работать корректно, и остатки будут "биться" день в день.