В практике разработки на платформе 1С:Предприятие часто возникает ситуация: программист пишет код для создания нового элемента справочника, заполняет все необходимые реквизиты, вызывает метод Записать(), но в итоге обнаруживает, что поле Код осталось пустым. При этом, если открыть этот же элемент вручную в интерфейсе и нажать «Записать», код благополучно присваивается. Рассмотрим подробнее, почему так происходит и какие механизмы платформы на это влияют.
Проанализируем наиболее частую причину этой проблемы, которая как раз и встретилась автору вопроса. В коде была использована следующая конструкция:
НоменОбъект = Справочники.Номенклатура.СоздатьЭлемент();
НоменОбъект.ОбменДанными.Загрузка = Истина;
// Заполнение реквизитов...
НоменОбъект.Записать();
Когда мы устанавливаем свойство ОбменДанными.Загрузка в значение Истина, мы сообщаем платформе, что данный объект загружается из внешнего источника (например, при обмене данными между базами). В этом режиме платформа сознательно отключает большинство автоматических проверок и механизмов, включая автонумерацию.
Логика платформы здесь проста: если данные «пришли» из другой базы, значит, у них уже должен быть свой код или номер, и система не должна его пересчитывать или изменять, чтобы не нарушить синхронизацию. Именно поэтому при записи объекта с включенным режимом загрузки метод УстановитьНовыйКод() не вызывается системой автоматически.
Чтобы решить эту проблему, мы должны либо отказаться от режима загрузки (если он не критичен), либо вызвать установку кода принудительно. Рассмотрим правильный порядок действий, проверенный на практике:
УстановитьНовыйКод().ОбменДанными.Загрузка = Истина.Пример корректного кода:
НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
// Сначала устанавливаем код, пока система работает в обычном режиме
НовыйЭлемент.УстановитьНовыйКод();
// Теперь можно включить режим загрузки, если нужно обойти другие проверки модуля объекта
НовыйЭлемент.ОбменДанными.Загрузка = Истина;
НовыйЭлемент.Наименование = "Новый товар";
НовыйЭлемент.Записать();
Иногда даже вызов УстановитьНовыйКод() не дает результата. Выясним причину такого поведения. Это может быть связано с настройками самого справочника в конфигураторе. Разберем по шагам, что нужно проверить:
ПриУстановкеНовогоКода параметру СтандартнаяОбработка присваивается значение Ложь, системный механизм генерации кода будет проигнорирован.Посмотрим на пример того, как может выглядеть обработчик в модуле объекта, который блокирует код:
Процедура ПриУстановкеНовогоКода(СтандартнаяОбработка, Префикс)
// Если какая-то логика не выполняется, отменяем стандартную генерацию
Если Не ЗначениеЗаполнено(Организация) Тогда
СтандартнаяОбработка = Ложь;
КонецЕсли;
КонецПроцедуры
В этом случае, если вы программно создаете элемент и не заполнили реквизит Организация перед вызовом установки кода, код останется пустым.
Если мы работаем в современных конфигурациях, использующих Библиотеку стандартных подсистем (БСП), обычного метода платформы может быть недостаточно для соблюдения всех правил префиксации. В таких системах рекомендуется использовать программный интерфейс БСП.
Проанализируем ситуацию: в крупных базах коды часто содержат префиксы информационной базы, префиксы организации или подразделения. Чтобы код сформировался правильно («00УТ-00001»), лучше вызвать метод общего модуля:
// Вместо Объект.УстановитьНовыйКод();
ПрефиксацияОбъектов.УстановитьПрефиксИНовыйКод(НовыйЭлемент);
НовыйЭлемент.Записать();
Этот метод самостоятельно проанализирует настройки программы, найдет нужные префиксы и применит их к объекту, что исключит путаницу в нумерации при обмене между филиалами. Для автоматизации передачи изменений поверх настроенных планов обмена задействуется программа регулярной синхронизации баз по расписанию.
Разберем еще один важный момент. Поведение автонумерации сильно зависит от свойства «Серии кодов» в метаданных справочника. Рассмотрим варианты:
УстановитьНовыйКод() можно вызывать в любой момент создания объекта.УстановитьНовыйКод() только ПОСЛЕ того, как заполнили реквизит Владелец.Родитель), а потом вызывайте установку кода.Бывает так, что программный код написан верно, но система выдает ошибку уникальности или присваивает странные номера. Это происходит из-за «битых» кодов, введенных пользователями вручную. Если кто-то вручную создал элемент с кодом «99999», то следующий автоматический номер платформа попытается сделать равным «100000», что может не влезть в длину поля, либо просто нарушит логику.
Проанализируем ситуацию: метод УстановитьНовыйКод() всегда ищет максимальный существующий код. Если в базе есть код, нарушающий маску (например, содержащий буквы там, где их быть не должно), автонумератор может «застрять» на одном и том же значении. В таком случае поможет только перенумерация справочника специальными обработками. Для диагностики и устранения таких сбоев автонумерации подойдёт обработка для анализа максимального кода и исправления автонумерации.
Подводя итог, для гарантированного получения кода при программном создании объекта следуйте алгоритму:
Организация, Владелец, Родитель).Объект.УстановитьНовыйКод() или воспользуйтесь методами БСП.ОбменДанными.Загрузка = Истина, если он вам необходим.Записать().Такой подход обеспечит корректную работу системы нумерации и избавит от необходимости ручного исправления данных после программного импорта. В случаях, когда импорт нужен для разовой точечной миграции, для гибкого сопоставления загружаемых объектов используется обработка для переноса данных между похожими конфигурациями 1С.