При автоматическом создании, старте или записи бизнес-процессов и связанных с ними объектов разработчики нередко сталкиваются с неприятной ситуацией: платформа 1С:Предприятие генерирует исключение «Значение "..." поля "Номер" не уникально». Особенность этой ошибки часто заключается в том, что при каждой следующей попытке номер автоматически инкрементируется (увеличивается на единицу), но запись всё равно завершается аварийно. Разберем детально, почему это происходит, в каких объектах на самом деле возникает коллизия и как по шагам восстановить корректную работу механизма нумерации.
Для эффективного устранения неполадки выясним внутреннюю механику работы нумераторов платформы 1С. В большинстве случаев ошибка вызвана одной из следующих причин:
rphost заранее резервирует диапазон свободных номеров. Если информационная база была восстановлена из резервной копии СУБД (например, средствами Microsoft SQL Server или PostgreSQL) без перезапуска службы сервера 1С (ragent), кэш считает свободными те номера, которые уже записаны в СУБД.Задачи.ЗадачаИсполнителя) или вложенные бизнес-процессы. Номер может быть занят именно в подчиненной таблице, а не в основном бизнес-процессе.ПередСозданиемВложенныхБизнесПроцессов. Если разработчик вручную вызывает метод Записать() или Старт() для подчиненного процесса, а затем платформа пытается выполнить штатную запись объекта по карте маршрута, происходит повторная попытка захвата того же номера в одной транзакции.2809147 вместо 002809147) либо создали документ с номером из далекого будущего диапазона, строковое сравнение платформы сбивается, натыкаясь на занятые позиции при каждом последующем шаге автоинкремента.Проанализируем данные информационной базы, чтобы точно выяснить, какой объект метаданных вызывает исключение. Для этого выполним запрос через консоль запросов или внешнюю обработку сразу по нескольким таблицам, которые участвуют в маршруте бизнес-процесса.
Посмотрим на пример диагностического запроса:
ВЫБРАТЬ
"Основной процесс" КАК ТипОбъекта,
БП.Ссылка КАК Ссылка,
БП.Номер КАК Номер,
БП.Дата КАК Дата
ИЗ
БизнесПроцесс.Согласование КАК БП
ГДЕ
БП.Номер ПОДОБНО "%280914%"
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
"Вложенный процесс",
Вложенный.Ссылка,
Вложенный.Номер,
Вложенный.Дата
ИЗ
БизнесПроцесс.Утверждение КАК Вложенный
ГДЕ
Вложенный.Номер ПОДОБНО "%280914%"
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
"Задачи исполнителей",
Задачи.Ссылка,
Задачи.Номер,
Задачи.Дата
ИЗ
Задача.ЗадачаИсполнителя КАК Задачи
ГДЕ
Задачи.Номер ПОДОБНО "%280914%"
Данный запрос позволяет сразу определить, в какой именно таблице уже существует объект с конфликтующим номером. Часто оказывается, что номер занят не в основном процессе, а в создаваемой платформой задаче.
Если база данных недавно восстанавливалась из бэкапа или в кластере серверов произошел сбой, необходимо принудительно обновить нумерацию. Метод глобального контекста ОбновитьНумерациюОбъектов() без параметров сбрасывает кэш для всей базы, однако надежнее вызывать его точечно для конкретных метаданных.
Разберем программный пример сброса кэша для бизнес-процессов и задач:
// Сброс кэша для основного процесса
ОбновитьНумерациюОбъектов(Метаданные.БизнесПроцессы.Согласование);
// Сброс кэша для вложенного процесса
ОбновитьНумерациюОбъектов(Метаданные.БизнесПроцессы.Утверждение);
// Сброс кэша для задач
ОбновитьНумерациюОбъектов(Метаданные.Задачи.ЗадачаИсполнителя);
Сообщить("Кэш нумерации объектов успешно обновлен.");
Если выполнение метода в пользовательском режиме не помогло избавиться от ошибки на стороне сервера, выполним перезапуск службы 1C:Enterprise Server Agent (ragent) в диспетчере служб операционной системы. Это гарантированно очистит внутреннюю память всех рабочих процессов rphost.
Рассмотрим типовую ошибку при работе с обработчиком события ПередСозданиемВложенныхБизнесПроцессов на карте маршрута бизнес-процесса. Платформа самостоятельно управляет жизненным циклом и транзакцией создания подчиненных процессов.
Посмотрим на пример ошибочного и корректного заполнения параметров вложенного процесса:
// ОШИБОЧНЫЙ ВАРИАНТ:
// Ручное создание и запись вызывают конфликт номеров в системной транзакции
Процедура ВложенныйПроцессПередСозданием(ТочкаМаршрутаБизнесПроцесса, ФормируемыеБизнесПроцессы, Отказ)
НовыйПроцесс = БизнесПроцессы.Утверждение.СоздатьБизнесПроцесс();
НовыйПроцесс.Дата = ТекущаяДатаСеанса();
НовыйПроцесс.ГлавнаяЗадача = ТочкаМаршрутаБизнесПроцесса;
// ОШИБКА: метод Записать() здесь вызывать нельзя!
НовыйПроцесс.Записать();
КонецПроцедуры
// КОРРЕКТНЫЙ ВАРИАНТ:
// Настройка переданных платформой объектов без явной записи
Процедура ВложенныйПроцессПередСозданиемКорректно(ТочкаМаршрутаБизнесПроцесса, ФормируемыеБизнесПроцессы, Отказ)
Для Каждого Процесс Из ФормируемыеБизнесПроцессы Цикл
Процесс.Дата = ТекущаяДатаСеанса();
Процесс.Предмет = ЭтотОбъект.Предмет;
Процесс.Автор = ЭтотОбъект.Автор;
// Запись и старт процесса платформа выполнит автоматически
КонецЦикла;
КонецПроцедуры
Обратим внимание на то, что если в коде требуется программно переопределить или сформировать номер, следует использовать метод УстановитьНовыйНомер() вместо прямой модификации строкового реквизита Номер.
// Корректная программная инициализация номера
ОбъектПроцесс = БизнесПроцессы.Согласование.СоздатьБизнесПроцесс();
ОбъектПроцесс.Дата = ТекущаяДатаСеанса();
ОбъектПроцесс.УстановитьНовыйНомер();
ОбъектПроцесс.Записать();
Если в базе присутствуют записи с нарушенной структурой номера (пропущены лидирующие нули, введены недопустимые символы вручную), платформа не может корректно рассчитать следующий номер по порядку.
Разберем алгоритм восстановления целостности нумерации:
01.01.0001), платформа ищет свободный номер в нулевом периоде, где уже могут быть зафиксированы старые ошибочные записи.Номер. Проверим, нет ли в конце списка некорректных номеров с девятками (999999999) или тестовых записей.ОбновитьНумерациюОбъектов(), чтобы сервер 1С зафиксировал новое максимальное значение в таблицах базы данных.Соблюдение этих правил и последовательная диагностика позволяют быстро устранить блокирующую ошибку уникальности номера и обеспечить стабильное прохождение маршрутов бизнес-процессов в 1С.