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