Почему нельзя создавать месяцы как ресурсы в регистрах 1С и как правильно решить задачу?

Программист IT и автоматизация бизнеса
← На главную

Рассмотрим весьма показательную и поучительную ситуацию, с которой нередко сталкиваются начинающие разработчики 1С. Допустим, стоит задача: пользователи должны вводить данные о перемещении сумм с одного месяца на другой, а в отчете эти данные нужно видеть в классическом табличном виде, где колонками выступают месяцы (Январь, Февраль, Март и так далее до Декабря).

Пытаясь решить эту задачу «в лоб», разработчик может добавить в структуру регистра накопления новое измерение Дата, а ресурсы назвать Январь, Февраль, Март. Проанализируем, почему такой подход является грубейшей архитектурной ошибкой и выясним причину, по которой профессиональное сообщество 1С категорически не рекомендует так делать. После этого мы подробно разберем по шагам, как правильно реализовать подобный механизм.

Почему создание месяцев в виде ресурсов — это антипаттерн?

Создание колонок (ресурсов), жестко привязанных к конкретным названиям месяцев, нарушает базовые принципы проектирования баз данных и логику работы платформы 1С. Рассмотрим основные проблемы этого подхода:

  1. Нарушение нормализации баз данных. Если мы жестко пропишем в метаданных ресурсы с названиями месяцев, наша структура будет привязана к одному году. Как только потребуется перенести сумму с декабря текущего года на январь следующего, нам придется добавлять в конфигуратор новые ресурсы вида «Январь 2020», «Февраль 2020» и так до бесконечности. Это приведет к постоянной реструктуризации базы данных и ее необоснованному разрастанию.
  2. Дублирование стандартных механизмов платформы. У любого регистра накопления в 1С уже есть системное поле Период. Именно по нему платформа строит внутренние индексы и рассчитывает виртуальные таблицы остатков и оборотов. Если добавить собственное измерение с типом «Дата», платформа воспримет его просто как обычную аналитику (срез), а не как координату на оси времени.
  3. Сложность написания запросов. Если данные «размазаны» по двенадцати ресурсам, то для получения общей суммы за год или за произвольный период в запросе придется вручную прописывать сложение всех этих полей через условия, что многократно усложнит код и снизит производительность системы.
  4. Некорректная работа остатков. Из-за использования кастомного измерения Дата остатки перестанут «перетекать» на следующие периоды, а будут зависать в разрезе конкретных дат. Механизм виртуальных таблиц не сможет работать правильно.

Как правильно спроектировать регистр накопления?

Задачи, связанные с отображением данных по периодам в виде колонок, в 1С всегда решаются на уровне представления данных (отчетов), а не на уровне хранения данных (таблиц БД). Разберем по шагам, как должна выглядеть правильная структура регистра:

  1. Откажитесь от ресурсов с названиями месяцев. В регистре должен быть только один числовой ресурс — Сумма.
  2. Удалите самописное измерение Дата. В качестве даты операции платформа будет использовать стандартное поле Период, которое есть у регистра по умолчанию.
  3. Оставьте в измерениях только реальную аналитику: например, Контрагент, Проект, СтатьяЗатрат и т.д.

Теперь посмотрим на пример логики проведения документа. Как отразить операцию «перемещения» суммы из одного месяца в другой? Это делается двумя записями (движениями) в регистр:


// 1. Списание суммы из исходного месяца
ДвижениеМинус = Движения.НашРегистрОстатков.Добавить();
ДвижениеМинус.ВидДвижения = ВидДвиженияНакопления.Расход;
ДвижениеМинус.Период = ДатаИсходногоМесяца;
ДвижениеМинус.Сумма = СуммаПеремещения;
ДвижениеМинус.Аналитика = ЗначениеАналитики;

// 2. Поступление суммы в целевой месяц
ДвижениеПлюс = Движения.НашРегистрОстатков.Добавить();
ДвижениеПлюс.ВидДвижения = ВидДвиженияНакопления.Приход;
ДвижениеПлюс.Период = ДатаЦелевогоМесяца;
ДвижениеПлюс.Сумма = СуммаПеремещения;
ДвижениеПлюс.Аналитика = ЗначениеАналитики;

Таким образом, мы фиксируем отток средств в одном периоде и приток в другом, используя стандартные механизмы движений регистра накопления.

Как вывести месяцы в колонки отчета через СКД?

Мы спроектировали правильную базу. Теперь проанализируем ситуацию с отчетом. Пользователь хочет видеть привычную "шахматку", где строки — это аналитика, а колонки — названия месяцев. Настроим Систему компоновки данных (СКД):

  1. В наборе данных СКД напишем запрос к виртуальной таблице оборотов или остатков и оборотов регистра.
  2. Чтобы получить данные именно в разрезе месяцев, используем в запросе стандартную функцию языка запросов 1С: НАЧАЛОПЕРИОДА(Таблица.Период, МЕСЯЦ). Назовем это поле, например, ПериодМесяц.
  3. Перейдем на вкладку «Настройки» в схеме СКД. Добавим элемент структуры отчета типа Таблица (кросс-таблица).
  4. В «Строки» таблицы добавим наше измерение (аналитику).
  5. В «Колонки» добавим поле ПериодМесяц.
  6. В качестве группировки выведем наш ресурс Сумма.

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

Красивое оформление заголовков колонок

Если мы просто выведем ПериодМесяц, то в шапке колонок пользователь увидит даты вида «01.01.2019 00:00:00». Чтобы сделать отчет понятным и красивым, зададим формат. Зайдем в настройки поля ПериодМесяц на вкладке «Наборы данных» и в свойстве «Оформление» найдем параметр Формат.

Пропишем форматную строку: ДФ='ММММ гггг'. Теперь вместо безликих дат в заголовках колонок будет выводиться понятный текст: «Январь 2019», «Февраль 2019» и так далее.

Применяя этот подход, мы получаем масштабируемую, быструю систему хранения данных, полностью соответствующую стандартам 1С, а всю визуальную работу перекладываем на мощный механизм СКД.

← На главную