Как записать в Регистр сведений две одинаковые строки в одной транзакции, если он требует уникальности?

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Управленческий учет
← К списку

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

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

Решение 1: Расширение состава измерений Регистра сведений

Это основной и наиболее правильный подход. Мы должны добавить в регистр сведений новое измерение (или несколько измерений), которое обеспечит уникальность каждой записи, соответствующей нашей бизнес-логике.

  1. Добавление бизнес-специфичного измерения.

    Рассмотрим ситуацию, когда "одинаковые" строки относятся к разным бизнес-контекстам. Например, если в документе "Установка цен" мы устанавливаем одну и ту же номенклатуру с одной и той же ценой, но для разных заказов клиентов или разных назначений. В этом случае, очевидно, записи не являются абсолютно одинаковыми.

    Разберем по шагам, как это можно реализовать:

    • Выясняем причину уникальности: Задайте себе вопрос: что отличает одну "одинаковую" строку от другой с точки зрения пользователя или бизнес-процесса? Если это разные заказы, проекты, контракты или любые другие признаки, которые влияют на дальнейшее использование данных, то это и есть наше скрытое измерение.

    • Добавляем измерение в регистр: Например, если в документе есть колонка "Назначение", куда ставят "ЗаказКлиента", то мы можем добавить измерение ЗаказКлиента в наш регистр сведений.

      Пример: Если наш регистр хранит цены номенклатуры, и нам нужно хранить разные цены одной и той же номенклатуры для разных заказов клиента, то добавляем измерение ЗаказКлиента с типом ДокументСсылка.ЗаказКлиента.

    Таким образом, комбинация Номенклатура, Характеристика, ЗаказКлиента (и, возможно, других измерений) сделает каждую запись уникальной.

  2. Добавление технического измерения: НомерСтроки или УИД Регистратора.

    Иногда бизнес-логика не предоставляет явного "скрытого" измерения, но нам нужно хранить все строки документа, даже если они выглядят идентично по основным измерениям. В таких случаях мы можем использовать технические измерения, которые гарантируют уникальность записей, если они относятся к разным строкам одного и того же документа.

    • Использование НомерСтроки: Мы можем добавить измерение НомерСтроки в регистр сведений. Это измерение будет хранить номер строки табличной части документа-регистратора, из которой была сформирована запись. Поскольку каждая строка табличной части имеет свой уникальный номер, это обеспечит уникальность записей в регистре.

      Пример:

      
      // При записи движений регистра из табличной части документа
      Для Каждого СтрокаТЧ Из Объект.ТабличнаяЧастьДокумента Цикл
          Движение = Движения.НашРегистрСведений.Добавить();
          Движение.Период = Объект.Дата;
          Движение.Номенклатура = СтрокаТЧ.Номенклатура;
          Движение.Цена = СтрокаТЧ.Цена;
          Движение.НомерСтроки = СтрокаТЧ.НомерСтроки; // Добавляем измерение НомерСтроки
          // ... другие измерения и ресурсы
      КонецЦикла;
      
    • Комбинация УИД Регистратора и НомерСтроки: Это еще более надежный способ обеспечения уникальности, особенно если регистр может заполняться из разных документов. Измерение УИДРегистратора (с типом Строка или УникальныйИдентификатор) будет хранить уникальный идентификатор документа, а НомерСтроки — номер строки внутри этого документа.

      Пример:

      
      // При записи движений регистра из табличной части документа
      Для Каждого СтрокаТЧ Из Объект.ТабличнаяЧастьДокумента Цикл
          Движение = Движения.НашРегистрСведений.Добавить();
          Движение.Период = Объект.Дата;
          Движение.Номенклатура = СтрокаТЧ.Номенклатура;
          Движение.Цена = СтрокаТЧ.Цена;
          Движение.УИДРегистратора = Объект.УникальныйИдентификатор; // Измерение УИД регистратора
          Движение.НомерСтроки = СтрокаТЧ.НомерСтроки;             // Измерение НомерСтроки
          // ... другие измерения и ресурсы
      КонецЦикла;
      
  3. Использование механизма "Позиция регистратора" (БСП/ERP).

    Если вы работаете с типовыми конфигурациями на основе Библиотеки стандартных подсистем (БСП) или ERP (например, ERP 2.4, 2.5), то для решения подобных задач уже существует стандартный механизм — "Позиция регистратора".

    • Что это такое: Механизм "Позиция регистратора" позволяет хранить в регистрах сведений информацию, привязанную к конкретной строке документа-регистратора. Для этого в регистр добавляется специальное измерение, которое имеет тип СтрокаТабличнойЧастиДокумента (или аналогичный, зависящий от конкретной конфигурации).

    • Как это работает: Платформа 1С автоматически заполняет это измерение ссылкой на конкретную строку табличной части документа. Это обеспечивает уникальность записей для каждой строки документа, даже если остальные измерения совпадают. Этот механизм особенно актуален для регистров, хранящих данные, которые могут быть разными для каждой строки документа (например, цены, скидки, характеристики), даже если номенклатура или другие основные измерения совпадают.

    • Применение: Мы можем использовать этот механизм, если наша конфигурация его поддерживает. Обычно это делается через свойства регистра сведений в конфигураторе, где указывается, что регистр использует "Позицию регистратора", и выбирается соответствующая табличная часть документа.

    Важно: Всегда тщательно анализируйте бизнес-требования. Добавление произвольных измерений типа НомерСтроки без глубокого понимания бизнес-логики может усложнить дальнейшую работу с данными. Старайтесь найти наиболее осмысленное дополнительное измерение, которое отражает суть данных.

Решение 2: Альтернативные подходы и их применение

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

  1. Использование Регистра накопления вместо Регистра сведений.

    Иногда, если наша задача не просто хранить уникальные характеристики, а учитывать количество или суммы, и "одинаковые" строки представляют собой разные "движения" (приходы/расходы), то возможно, нам нужен Регистр накопления.

    • Когда подходит: Регистр накопления идеально подходит для учета остатков и оборотов. Он позволяет хранить несколько записей с одинаковыми измерениями, но разными видами движений (Приход/Расход) или разными суммами/количествами.

    • Когда не подходит: Для хранения уникальных характеристик, таких как цены, регистр накопления не всегда является лучшим выбором. Главный недостаток — отсутствие прямого механизма "среза последних" (как у регистров сведений) для получения актуальной информации. Хотя можно получить последние данные с помощью запросов, это будет менее удобно и производительно, чем у РС.

  2. Хранение только "последней" или "максимальной" записи (агрегация).

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

    • Пример: Если нам нужно хранить только актуальную цену для номенклатуры, а не всю историю цен из одного документа, мы можем выбрать максимальную цену из строк документа.

      Посмотрим на пример запроса, который выбирает максимальную цену для каждой номенклатуры в документе:

      
      ВЫБРАТЬ
          ТЧ.Номенклатура,
          МАКСИМУМ(ТЧ.Цена) КАК Цена
      ИЗ
          Документ.ИмяДокумента.ТабличнаяЧасть КАК ТЧ
      ГДЕ
          ТЧ.Ссылка = &СсылкаНаДокумент
      СГРУППИРОВАТЬ ПО
          ТЧ.Номенклатура
      

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

    • Ограничения: Этот подход подходит, если бизнес-логика допускает потерю информации о других "одинаковых" записях. Если же все записи важны, то этот метод не применим.

  3. Хранение данных только в табличной части документа.

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

    • Когда подходит: Этот вариант является самым простым, если данные не являются учетными или аналитическими, а служат лишь для формирования печатной формы или выполнения расчетов внутри документа.

    • Ограничения: Если к этим данным нужен быстрый доступ из других объектов системы, необходимо строить отчеты по ним в разрезе различных аналитик, или они являются частью сквозного учета, то регистр сведений все же предпочтительнее.

Рекомендации по проектированию

В заключение, хотим подчеркнуть несколько важных моментов, которые помогут нам в процессе проектирования:

  1. Тщательный анализ бизнес-требований: Всегда начинайте с глубокого анализа того, почему возникают "одинаковые" строки. Какая информация отличает одну запись от другой с точки зрения пользователя? Ответы на эти вопросы помогут выбрать наиболее осмысленное дополнительное измерение.

  2. Избегание избыточности: Добавление слишком большого количества измерений может усложнить запросы, снизить производительность и затруднить понимание структуры данных. Важно найти минимально необходимый набор измерений, который обеспечивает уникальность и адекватно отражает суть хранимых данных.

  3. Стандартные механизмы: Если вы работаете с типовыми конфигурациями, всегда проверяйте наличие стандартных механизмов (например, "Позиция регистратора" в БСП/ERP), которые уже разработаны для решения подобных задач. Использование типовых решений часто является наиболее эффективным и поддерживаемым подходом.

Надеемся, что этот подробный разбор поможет вам найти оптимальное решение для вашей конкретной задачи!

← К списку