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