В процессе работы с программами «1С:Предприятие» пользователи часто сталкиваются с системным сообщением: «Значение поля "Номер" не уникально». Особенно остро эта проблема встает при ведении кадрового учета, когда номера приказов должны соответствовать определенной внутренней номенклатуре предприятия, которая не всегда совпадает с логикой автонумерации системы. В этой статье мы подробно разберем, как решить проблему дублирования номеров, проанализируем технические риски и выберем оптимальный путь реализации задачи.
Прежде чем вносить изменения в конфигурацию, давайте разберем фундаментальное различие, которое часто упускают начинающие разработчики и пользователи. В современных типовых решениях (например, в «1С:Зарплата и управление персоналом 3.1») предусмотрено два разных поля для идентификации документа:
Проанализируем ситуацию: если вы получаете ошибку уникальности, скорее всего, вы пытаетесь записать «красивый» номер в системное поле Номер. Проверьте форму документа — возможно, в ней есть отдельное поле «Номер приказа». В этом случае системный номер следует оставить для автоматического заполнения программой, а ваш номер вбивать в соответствующий реквизит.
Если специфика вашей задачи требует, чтобы именно системный номер мог дублироваться, нам придется обратиться к настройкам метаданных документа. Рассмотрим этот процесс по шагам:
Однако, прежде чем сохранить изменения, проанализируем свойство «Периодичность». Если в организации установлена периодичность «Год», то уникальность проверяется только внутри текущего календарного года. Возможно, вам не нужно отключать контроль, а достаточно просто изменить префикс или убедиться, что вы не пытаетесь повторно использовать номер, который уже был в этом году.
Существует технический способ записать документ с любым номером, даже если контроль уникальности включен. Для этого используется свойство объекта ОбменДанными.Загрузка. Рассмотрим пример кода:
НовыйДокумент = Документы.ПриказНаОтпуск.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Номер = "362-к"; // Допустим, такой номер уже есть
НовыйДокумент.ОбменДанными.Загрузка = Истина;
НовыйДокумент.Записать();
Разберем, что происходит в этот момент. Установка флага Загрузка = Истина сообщает системе, что данные поступают из внешнего источника и их нужно «просто положить в базу», минуя большинство проверок. Важно понимать последствия:
Как справедливо отмечено в обсуждении, если попытаться провести такой документ обычным способом (нажав кнопку в интерфейсе), система может снова выдать ошибку уникальности или заблокировать проведение, так как флаг Загрузка работает только в момент выполнения конкретной транзакции записи.
Если вы хотите избежать внесения правок в код и сохранить типовую конфигурацию на поддержке, мы рекомендуем использовать механизм префиксов. В 1С номер часто формируется по шаблону [Префикс][Номер]. Если в базе ведется учет по нескольким организациям, добавление префикса организации (например, «ОФ-» и «ТД-») позволяет иметь документы с одинаковой цифровой частью, но разными строковыми представлениями.
Для реализации «визуально одинаковых» номеров иногда применяют хитрость с добавлением невидимых символов (например, неразрывного пробела) в конец номера. Пользователь в печатной форме видит «362-к», а для базы данных «362-к » (с пробелом) — это уже другой, уникальный номер.
Чтобы автоматизировать процесс и не заставлять пользователя вручную менять номера, можно использовать обработчик события ПередЗаписью в модуле объекта. Проанализируем пример логики, которая проверяет уникальность и модифицирует номер:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Проверяем, существует ли уже такой номер в базе
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ПриказНаОтпуск.Ссылка
|ИЗ
| Документ.ПриказНаОтпуск КАК ПриказНаОтпуск
|ГДЕ
| ПриказНаОтпуск.Номер = &Номер
| И ПриказНаОтпуск.Ссылка <> &Ссылка";
Запрос.УстановитьПараметр("Номер", ЭтотОбъект.Номер);
Запрос.УстановитьПараметр("Ссылка", ЭтотОбъект.Ссылка);
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
// Если номер найден, добавляем суффикс или выводим предупреждение
// В данном примере просто разрешаем запись, если контроль в метаданных снят,
// либо программно меняем номер для уникальности
// ЭтотОбъект.Номер = СокрЛП(ЭтотОбъект.Номер) + "/дубль";
КонецЕсли;
КонецПроцедуры
Вернемся к предупреждению из сообщений форума. Почему опытные разработчики предостерегают от бездумного отключения контроля уникальности? Выясним причины:
Номер является индексируемым. При наличии большого количества одинаковых значений эффективность индекса падает, что может замедлить работу журналов документов.Подводя итог, разберем последовательность действий при возникновении задачи по дублированию номеров:
Помните, что платформа 1С создана для обеспечения целостности данных, и обход ее защитных механизмов всегда должен быть обоснован реальной бизнес-необходимостью, а не просто желанием «сделать как в бумажном журнале».