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