Стоит ли добавлять даты в измерения регистра накопления, если они есть не во всех документах?

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

При проектировании или доработке системы на платформе 1С:Предприятие часто возникает задача расширения аналитики существующего учета. Рассмотрим классическую проблему: у нас есть работающий регистр накопления (остатки), и бизнес требует добавить в отчеты разбивку по периодам (например, "Дата начала аренды" и "Дата окончания аренды").

Сложность заключается в том, что эти даты присутствуют только в части документов (например, в документе реализации или специальном документе начисления), но отсутствуют в стандартных документах прихода или списания. Проанализируем, как правильно реализовать такую задачу, чтобы не "сломать" учет и сохранить производительность системы.

Суть проблемы: измерения против реквизитов

Рассмотрим ситуацию, описанную автором. Появилась потребность проводить один документ на будущие периоды, создавая несколько записей в регистре с разными датами начала и конца. Если не добавить эти поля в структуру регистра, записи свернутся (схлопнутся), и мы потеряем детальную информацию для отчета.

Перед нами встает выбор из трех вариантов:

  1. Добавить даты как Измерения регистра.
  2. Добавить даты как Реквизиты регистра.
  3. Создать отдельный регистр (сведений или накопления) для этой задачи.

Давайте подробно разберем каждый вариант и выясним, почему прямая модификация измерений — это, как правило, плохое решение.

Вариант 1: Добавление дат в измерения

На первый взгляд, это кажется самым логичным решением: добавили измерение, записали данные, построили отчет. Однако, как верно подмечено в обсуждении, здесь кроется фундаментальная ошибка проектирования регистров остатков.

Принцип закрываемости регистра (Message 9)

Главный принцип регистра накопления вида "Остатки" — закрытие движений в ноль. Таблица остатков виртуальна, она рассчитывается как сумма приходов минус сумма расходов.

Если вы добавите измерение ДатаНачала, то система будет считать уникальным ключом записи набор всех измерений, включая эту дату.

Представим ситуацию:

Результат: Регистр не закроется. В отчете "Остатки и обороты" вы увидите две строки:

В сумме это дает ноль, но для пользователя отчет будет выглядеть как "разъехавшаяся" аналитика. Это недопустимо для складского или финансового учета. Чтобы этого избежать, вам пришлось бы при списании программно подбирать пустую дату (что теряет смысл добавления измерения) или при приходе провидчески знать будущую дату расхода (что невозможно).

Проблема производительности (Message 10)

Даты в измерениях — это потенциальная проблема "Cardinality" (селективности). Таблица итогов регистра накопления эффективна, когда количество комбинаций измерений ограничено. Если даты разнообразны (особенно если там есть время), таблица итогов раздувается до размеров таблицы движений, и смысл использования регистра накопления теряется.

Вариант 2: Добавление дат в реквизиты

Если мы запишем даты в Реквизиты регистра, мы избежим проблемы с незакрытыми остатками. Реквизиты не участвуют в формировании уникального ключа остатков. Приход и расход по товару "Стул" схлопнутся в ноль, даже если у них разные реквизиты.

Однако здесь возникает проблема получения данных:

  1. Виртуальные таблицы (Остатки, Обороты, ОстаткиИОбороты) не позволяют делать отбор или группировку по реквизитам напрямую в параметрах.
  2. Чтобы вытащить реквизит в отчет, вам придется соединять виртуальную таблицу с реальной таблицей движений регистра по регистратору.

Пример запроса, который придется писать (псевдокод):


ВЫБРАТЬ
	ТоварыНаСкладахОстаткиИОбороты.Номенклатура,
	ТоварыНаСкладахОстаткиИОбороты.КоличествоОборот,
	ТоварыНаСкладах.ДатаНачалаАренды // Реквизит
ИЗ
	РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты AS ТоварыНаСкладахОстаткиИОбороты
		ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах AS ТоварыНаСкладах
		ПО ТоварыНаСкладахОстаткиИОбороты.Регистратор = ТоварыНаСкладах.Регистратор
		И ТоварыНаСкладахОстаткиИОбороты.НомерСтроки = ТоварыНаСкладах.НомерСтроки

Это рабочее решение, но оно значительно утяжеляет запросы в отчетах. Если таких отчетов много и база большая, производительность упадет.

Вариант 3: Отдельный регистр (Рекомендуемое решение)

Наиболее правильным подходом, который советуют опытные разработчики (Message 4, 10), является разделение потоков данных. Не стоит пытаться "впихнуть" аналитику одного конкретного документа в общий регистр, где она не нужна для 90% других операций.

Мы рекомендуем использовать один из двух подходов:

А. Использование Регистра Сведений (Паттерн "Расширение")

Создайте независимый (или подчиненный регистратору) регистр сведений, например, СрокиАрендыПоДокументам.

При проведении документа с датами вы пишите движения и в основной РН (только суммы/количества), и в этот РС (даты). В отчетах вы просто соединяете данные РН с этим РС.

Б. Создание специализированного оборотного регистра

Если ваша задача — анализировать именно обороты (сколько услуг оказано в разрезе периодов), создайте отдельный Регистр накопления (Обороты), например ПродажиПоПериодамАренды.

Итоговый алгоритм принятия решения

Подводя итог обсуждения, сформулируем алгоритм действий:

  1. Проверка на закрываемость: Если даты есть в "Расходном" документе, но нет в "Приходном" (или наоборот), добавлять их в Измерения регистра остатков категорически нельзя. Остатки не закроются.
  2. Анализ использования: Если даты нужны только для справочной информации в отчете (отобразить колонку), используйте Реквизиты регистра или дополнительный Регистр сведений.
  3. Аналитическая отчетность: Если вам нужно строить сложную аналитику по этим датам (группировать, суммировать продажи по месяцам аренды), создайте отдельный Оборотный регистр накопления. Это не повлияет на основной складской учет и даст максимальную скорость работы отчетов.

Разделение ответственности между объектами метаданных — залог стабильной и масштабируемой системы. Лучше иметь два специализированных регистра, чем один "супер-регистр" с кучей пустых полей и медленной работой.

← На главную