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