В разработке на платформе 1С часто возникает задача: при создании нового элемента справочника необходимо автоматически сформировать значение определенного реквизита (например, Артикула), включив в него автоматически генерируемый Код товара и определенный префикс. Основная сложность заключается в том, что по умолчанию Код присваивается объекту только в момент его записи в базу данных. Если пытаться обратиться к коду в процедурах на клиенте или в начале транзакции записи, он будет пустым.
Разберем по шагам наиболее эффективные и правильные способы решения этой задачи, а также проанализируем типичные ошибки.
Это самый корректный метод с точки зрения архитектуры платформы 1С. Событие ПриУстановкеНовогоКода расположено в модуле объекта справочника. Оно срабатывает ровно в тот момент, когда система генерирует новый уникальный номер (код) для элемента.
Проанализируем ситуацию: когда вызывается это событие, параметр СтандартнаяОбработка еще равен Истина, и платформа уже определила, каким будет следующий код. Мы можем использовать это значение для формирования нашего реквизита.
Пример кода в модуле объекта:
Процедура ПриУстановкеНовогоКода(СтандартнаяОбработка, Префикс)
// Позволяем платформе сформировать код
// После завершения стандартной обработки Код будет доступен
КонецПроцедуры
Однако, так как код записывается в свойство объекта окончательно чуть позже, для гарантированного результата лучше комбинировать этот подход с методом принудительной установки кода.
Если нам нужно заполнить Артикул именно в момент записи, мы можем использовать процедуру ПередЗаписью в модуле объекта. Чтобы Код перестал быть пустым до фактического появления записи в базе, используем метод УстановитьНовыйКод().
Разберем этот алгоритм подробнее:
ЭтотОбъект.УстановитьНовыйКод().Артикул, складывая префикс и уже полученный Код.Пример реализации в модуле объекта:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ЭтоНовый() Тогда
// Принудительно получаем следующий номер из серии нумерации
ЭтотОбъект.УстановитьНовыйКод("TR-");
// Теперь свойство Код заполнено, и мы можем его использовать
Если ЗначениеЗаполнено(ЭтотОбъект.Код) Тогда
ЭтотОбъект.Артикул = "TR-" + ЭтотОбъект.Код;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Важный момент: при использовании этого метода нужно учитывать длину реквизита Артикул. Если длина кода 10 символов, а префикс "TR-" занимает 3 символа, то длина реквизита Артикул в метаданных должна быть не менее 13 символов, иначе строка будет обрезана.
Рассмотрим ситуацию, описанную пользователями: при нажатии кнопки "Записать" в форме данные обновляются, а при "Записать и закрыть" поле кажется пустым или возникают вопросы с его отображением. Это происходит из-за нюансов клиент-серверного взаимодействия.
Если реквизит заполняется в модуле объекта на сервере, клиентская форма может "не знать" об изменениях, если она не была перечитана. Чтобы пользователь увидел сформированный артикул сразу после нажатия кнопки "Записать" (без закрытия формы), в модуле формы в обработчике ПослеЗаписиНаСервере рекомендуется вызвать обновление данных:
&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
// Читаем обновленные данные из базы в форму
ЗначениеВРеквизитФормы(ТекущийОбъект, "Объект");
КонецПроцедуры
Некоторые разработчики предлагают записать объект, получить код, заполнить артикул и записать снова. Выясним причину, почему это плохая практика:
ЭтотОбъект.Записать() внутри обработчика ПередЗаписью или ПриЗаписи приведет к бесконечному циклу и аварийному завершению работы.Если ваша конфигурация использует БСП, рекомендуется обратить внимание на общий модуль ПрефиксацияОбъектовСобытия. Использование стандартных механизмов префиксации позволит избежать проблем при работе в распределенных информационных базах (РИБ), где к коду могут добавляться префиксы узлов или организаций. В этом случае логику формирования сложных представлений лучше выносить в переопределяемые модули БСП.
Резюме: Для автоматического заполнения реквизита на основании кода используйте процедуру ПередЗаписью модуля объекта совместно с методом УстановитьНовыйКод(). Это обеспечит наличие кода еще до завершения транзакции и позволит корректно сформировать зависимые данные за один проход.