Как исправить ошибку «Запись с такими ключевыми полями существует!» при проведении документа

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

При разработке механизмов проведения документов в системе «1С:Предприятие 8» программисты часто сталкиваются с ошибкой «Запись с такими ключевыми полями существует!». Эта ситуация особенно характерна для работы с регистрами сведений. В рамках данной статьи мы подробно разберем, почему возникает эта ошибка, как проанализировать проблемный код и какие методы существуют для её эффективного устранения.

Выясним причину возникновения ошибки

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

Регистр сведений, подчиненный регистратору, имеет уникальный ключ записи, который состоит из:

  1. Регистратора (ссылка на сам документ).
  2. Измерений (например, Номенклатура и Склад).
  3. Периода (если регистр периодический).

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

Анализируем типичные ошибки в коде проведения

Посмотрим на пример кода, который часто становится источником проблем. Рассмотрим процедуру ОбработкаПроведения, где разработчик пытается записать данные в два регистра: УчетаТоваров (регистр сведений) и РегистрНакопленияУчетТоваров (регистр накопления). Если вам сложно быстро разобраться в чужом коде, можно использовать AI-Анализатор 1C, который поможет расшифровать логику работы объектов.


Процедура ОбработкаПроведения(Отказ, Режим)
    // Регистр УчетаТоваров
    Движения.УчетаТоваров.Записывать = Истина;
    Движения.УчетаТоваров.Очистить();
    Движения.Записать(); // Избыточный вызов
    
    Для Каждого ТекСтрокаНоменклатура Из Номенклатура Цикл
        ДвижениеУчетаТоваров = Движения.УчетаТоваров.Добавить();
        ДвижениеУчетаТоваров.Номенклатура = ТекСтрокаНоменклатура.Номенклатура;
        ДвижениеУчетаТоваров.Склад = Склад;
        ДвижениеУчетаТоваров.Количество = ТекСтрокаНоменклатура.Количество;
    КонецЦикла;
КонецПроцедуры

В данном примере мы видим несколько критических моментов:

Решение №1: Использование метода Свернуть()

Самый простой и быстрый способ избавиться от дублей — это предварительная подготовка данных перед заполнением регистра. Мы можем выгрузить табличную часть во временную таблицу значений и объединить одинаковые строки.

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


// 1. Выгружаем данные из табличной части в таблицу значений
ТаблицаДвижений = Номенклатура.Выгрузить();

// 2. Сворачиваем таблицу по измерениям, суммируя ресурсы
// В данном случае группируем по Номенклатуре и Складу, суммируем Количество
ТаблицаДвижений.Свернуть("Номенклатура", "Количество");

// 3. Заполняем движения уже из свернутой таблицы
Для Каждого ТекСтрока Из ТаблицаДвижений Цикл
    Движение = Движения.УчетаТоваров.Добавить();
    Движение.Номенклатура = ТекСтрока.Номенклатура;
    Движение.Склад = Склад; // Общий реквизит из шапки
    Движение.Количество = ТекСтрока.Количество;
КонецЦикла;

Этот метод гарантирует, что в набор записей попадет только одна строка для каждой уникальной пары «Номенклатура + Склад», а общее количество товара будет корректно просуммировано.

Решение №2: Использование запроса (Профессиональный подход)

В крупных конфигурациях и высоконагруженных системах обход табличных частей в цикле считается плохим тоном. Более правильный путь — использование объекта Запрос. Это позволяет не только избежать дублей (с помощью предложения СГРУППИРОВАТЬ ПО), но и одновременно получить дополнительные данные (например, цены или остатки). Для быстрой отладки и проверки таких конструкций незаменима Консоль запросов с поддержкой пакетных запросов — удобнее через универсальная консоль запросов и кода для разработчика.

Разберем пример реализации через запрос:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ТЧ.Номенклатура КАК Номенклатура,
    |   СУММА(ТЧ.Количество) КАК Количество
    |ИЗ
    |   Документ.РасходнаяНакладная.Номенклатура КАК ТЧ
    |ГДЕ
    |   ТЧ.Ссылка = &Ссылка
    |СГРУППИРОВАТЬ ПО
    |   ТЧ.Номенклатура";

Запрос.УстановитьПараметр("Ссылка", Ссылка);
РезультатЗапроса = Запрос.Выполнить();

Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
    Движение = Движения.УчетаТоваров.Добавить();
    Движение.Номенклатура = Выборка.Номенклатура;
    Движение.Склад = Склад;
    Движение.Количество = Выборка.Количество;
КонецЦикла;

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

Советы по отладке

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

  1. Установите точку останова на строке КонецПроцедуры.
  2. Откройте Табло (клавиши Shift+F9).
  3. Введите выражение: Движения.УчетаТоваров.Выгрузить().
  4. Просмотрите полученную таблицу. Если вы увидите в ней две строки с одинаковой номенклатурой — это и есть причина ошибки.

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

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

Таким образом, мы проанализировали основные причины нарушения уникальности записей. Использование метода Свернуть() или группировки в запросе полностью решает проблему «Запись с такими ключевыми полями существует» и делает механизм проведения документа стабильным.

← На главную