Почему в 1С появляются дубликаты номеров документов при включенном контроле уникальности?

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

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

Анализ визуальной и технической идентичности номеров

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

  1. Разная раскладка символов. Символы «С», «А», «О», «Е» в кириллице и латинице выглядят идентично, но имеют разные коды. Платформа воспринимает их как разные строки, и контроль уникальности не срабатывает.
  2. Скрытые пробелы и непечатные знаки. Номер может содержать неразрывный пробел или случайный перенос строки в конце. Визуально в списке документов это не заметно.

Для диагностики рекомендуем выполнить программное сравнение кодов символов. Рассмотрим пример кода, который поможет увидеть реальное содержимое номера:


Для Индекс = 1 По СтрДлина(НомерДокумента) Цикл
    Сообщить("Символ: " + Сред(НомерДокумента, Индекс, 1) + " Код: " + КодСимвола(НомерДокумента, Индекс));
КонецЦикла;

Проанализируем результаты: если коды символов в двух "одинаковых" номерах различаются, значит, проблема в данных, а не в сбое платформы.

Влияние режима записи ОбменДанными.Загрузка

Одной из самых частых причин появления дублей при программном создании документов является использование свойства ОбменДанными.Загрузка. Рассмотрим, как это работает:

Когда в коде обработки или при обмене данными устанавливается значение Объект.ОбменДанными.Загрузка = Истина, платформа отключает большинство стандартных проверок, включая контроль уникальности номера и проверку заполнения обязательных полей. Это делается для ускорения загрузки больших массивов данных, предполагая, что данные уже проверены в источнике.

Если ваша обработка создания документов использует этот режим, ответственность за уникальность полностью ложится на алгоритм обработки. Если же вы уверены, что Загрузка = Ложь, перейдем к следующим пунктам.

Особенности работы платформенного контроля и транзакций

Важно понимать, что 1С:Предприятие выполняет проверку уникальности программно на уровне сервера приложений перед фиксацией транзакции записи. В СУБД (например, MS SQL Server) для поля Номер обычно не создается физический индекс уникальности (Unique Constraint).

Это может приводить к так называемой "состоянию гонки" (race condition). Представим ситуацию: два пользователя или два фоновых задания одновременно начинают создавать документ. Оба сеанса считывают текущий максимальный номер, прибавляют единицу и получают, например, "001". Оба сеанса проверяют, есть ли в базе "001". Поскольку транзакции еще не завершены, база отвечает, что номера нет. В итоге оба документа записываются с одинаковым номером.

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

  1. Используйте метод УстановитьНовыйНомер() непосредственно перед вызовом метода Записать(), а не в начале формирования документа.
  2. Применяйте механизм БлокировкаДанных. Установите исключительную блокировку на область нумерации для данного типа документа, чтобы другие сеансы ждали завершения вашей транзакции.

Проверка периодичности нумерации

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

Если вы меняете дату уже записанного документа, переводя его из одного периода в другой (например, из 2023 в 2024 год), платформа должна выполнить повторную проверку. Однако в старых релизах платформы (включая 8.3.9) наблюдались особенности, когда при простом перепроведении без изменения номера проверка не инициировалась повторно.

Гарантированный способ контроля через подписку на события

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

  1. Создадим общую функцию, которая будет выполнять запрос к базе данных.
  2. Проверим наличие документов с таким же номером, исключая текущую ссылку.

Пример логики запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ ПЕРВЫЕ 1
|   РеализацияТоваровУслуг.Ссылка
|ИЗ
|   Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
|   РеализацияТоваровУслуг.Номер = &Номер
|   И РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода
|   И РеализацияТоваровУслуг.Ссылка <> &Ссылка";

Запрос.УстановитьПараметр("Номер", Источник.Номер);
Запрос.УстановитьПараметр("Ссылка", Источник.Ссылка);
// Установка параметров периода в зависимости от настройки метаданных
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
    Отказ = Истина;
    Сообщение = Новый СообщениеПользователю;
    Сообщение.Текст = "Внимание! Нарушена уникальность номера документа.";
    Сообщение.Сообщить();
КонецЕсли;

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

← На главную