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