Как автоматически скопировать код в артикул при записи номенклатуры?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

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

Почему стандартный подход «ПриЗаписи» не работает напрямую?

Рассмотрим ситуацию, с которой сталкивается большинство разработчиков: попытка присвоить значение артикулу в процедуре ПриЗаписи. Проблема заключается в жизненном цикле записи объекта. Когда управление передается в процедуру ПриЗаписи, объект уже физически записан в таблицу базы данных. Если мы просто напишем Артикул = Код;, значение в памяти объекта изменится, но в базе данных останется старое (пустое) значение, так как команда записи уже была выполнена.

Проанализируем основные этапы записи нового объекта с включенной автонумерацией:

  1. Вызов метода Записать().
  2. Начало транзакции базы данных.
  3. Обработка события ПередЗаписью. Важно: на этом этапе поле Код еще пустое, так как система еще не зарезервировала номер.
  4. Присвоение нового кода платформой (внутри транзакции).
  5. Физическая запись полей в таблицу БД.
  6. Обработка события ПриЗаписи. Здесь код уже есть, но запись в БД уже совершена.
  7. Фиксация (Commit) транзакции.

Теперь, когда мы понимаем механику, рассмотрим способы реализации нашей задачи.

Способ 1. Использование метода УстановитьНовыйКод() в «ПередЗаписью»

Это самый корректный и производительный метод. Его суть заключается в том, чтобы заставить систему сгенерировать новый код чуть раньше — до того, как данные уйдут в базу. Мы делаем это в процедуре ПередЗаписью модуля объекта.

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


Процедура ПередЗаписью(Отказ)
    
    // Проверяем, что это новый элемент, чтобы не менять артикул у старых
    Если ЭтоНовый() Тогда
        
        // Принудительно генерируем новый код
        // Если в справочнике используются префиксы, их можно передать в параметре
        ЭтотОбъект.УстановитьНовыйКод();
        
        // Теперь, когда код получен, копируем его в артикул
        Если ЗначениеЗаполнено(ЭтотОбъект.Код) Тогда
            ЭтотОбъект.Артикул = ЭтотОбъект.Код;
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Важный нюанс: метод УстановитьНовыйКод() может принимать строковый параметр — префикс. Если в вашей конфигурации используется префиксация (например, по организации или узлу распределенной информационной базы), крайне важно передать правильный префикс, иначе нумерация может сбиться.

Способ 2. Повторная запись в обработчике «ПриЗаписи»

Этот метод считается менее элегантным («костылем»), но он также встречается в практике. Его суть: дождаться, когда платформа сама присвоит код, а затем изменить артикул и записать объект еще раз. Разберем пример кода:


Процедура ПриЗаписи(Отказ)
    
    // Проверяем, нужно ли нам заполнять артикул
    Если ПустаяСтрока(Артикул) И ЗначениеЗаполнено(Код) Тогда
        
        // Устанавливаем значение
        Артикул = Код;
        
        // Вызываем повторную запись. 
        // ВНИМАНИЕ: это может привести к рекурсии, если не поставить условие выше!
        Попытка
            ЭтотОбъект.Записать();
        Исключение
            Сообщить("Не удалось обновить артикул: " + ОписаниеОшибки());
        КонецПопытки;
        
    КонецЕсли;
    
КонецПроцедуры

Посмотрим на риски этого метода:

  1. Рекурсия: Если условие ПустаяСтрока(Артикул) не сработает или артикул не запишется, процедура Записать() будет вызывать ПриЗаписи бесконечно.
  2. Производительность: Система делает два обращения к серверу базы данных вместо одного. При массовой загрузке товаров это замедлит процесс вдвое.
  3. Подписки на события: Если в конфигурации есть сторонние механизмы, реагирующие на запись номенклатуры (например, выгрузка на сайт), они сработают дважды.

Способ 3. Использование Подписок на события

Если вы работаете с типовой конфигурацией (например, 1С:Управление торговлей или 1С:ERP), крайне не рекомендуется вносить изменения напрямую в модуль объекта. Это усложнит дальнейшие обновления. Вместо этого проанализируем ситуацию и создадим Подписку на событие.

Рассмотрим алгоритм действий:

  1. Создаем новый Общий модуль (например, РаботаСНоменклатуройСобытия).
  2. В модуле пишем процедуру, которая будет принимать два параметра: Источник и Отказ.
  3. Создаем объект метаданных Подписка на событие.
  4. В поле Источник выбираем СправочникОбъект.Номенклатура.
  5. В поле Событие выбираем ПередЗаписью.
  6. В поле Обработчик указываем нашу процедуру в общем модуле.

Пример кода в общем модуле:


Процедура НоменклатураПриЗаписиПередЗаписью(Источник, Отказ) Экспорт
    
    // Источник — это и есть наш объект справочника
    Если Источник.ЭтоНовый() Тогда
        Источник.УстановитьНовыйКод();
        Источник.Артикул = Источник.Код;
    КонецЕсли;
    
КонецПроцедуры

Особенности для конфигураций на БСП (Библиотека стандартных подсистем)

В современных решениях 1С нумерация часто управляется не просто платформой, а механизмами БСП. Выясним причину: это позволяет гибко настраивать префиксы без изменения кода. В таких случаях вызов УстановитьНовыйКод() может сработать некорректно, если не учесть программные префиксы.

Проанализируем, как получить префикс в БСП. Обычно используется функция ПрефиксацияОбъектовКлиентСервер.СформироватьПолныйПрефикс(Организация). Если вы видите, что номера в вашей базе имеют вид "УТ00-00001", значит, префиксация задействована.

Рекомендации и лучшие практики

Подводя итоги нашего разбора, сформулируем основные правила:

Таким образом, мы рассмотрели все основные сценарии автоматизации заполнения артикула. Выбор конкретного метода зависит от архитектуры вашей конфигурации и требований к производительности системы.

← На главную