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

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

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

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

Вариант 1: Использование коллекции Движения и флага записи

Если документ в метаданных указан как регистратор для регистра сведений, платформа автоматически создает для него коллекцию Движения. Самый чистый и правильный с точки зрения транзакционности способ — это использование этой коллекции непосредственно в модуле объекта документа. Даже если документ не является «проводимым» в классическом понимании (у него отключено проведение), он все равно может делать записи в регистры при сохранении.

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

  1. В модуле объекта используем обработчик ПередЗаписью или ПриЗаписи.
  2. Наполняем коллекцию движений нужными данными.
  3. Устанавливаем свойство Записывать = Истина для соответствующего набора записей.

Посмотрим на пример кода в модуле объекта:


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

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

Вариант 2: Получение ссылки до фактической записи (УстановитьСсылкуНового)

Часто разработчики переживают, что «ссылки еще нет», и поэтому пытаются сначала записать пустой документ, а потом обновлять его. Это плохая практика, порождающая лишние действия в БД. Платформа 1С позволяет получить ссылку для нового объекта еще до того, как он будет записан на диск.

Для этого в форме документа (или в обработке заполнения) можно использовать метод УстановитьСсылкуНового(). Разберем по шагам, как это работает:

  1. Мы генерируем новый уникальный идентификатор.
  2. Создаем на его основе ссылку нужного типа.
  3. Назначаем эту ссылку объекту.

Пример программного кода:


// В коде, который создает документ (например, в команде создания)
НовыйДок = Документы.НашДокумент.СоздатьОбъект();
НоваяСсылка = Документы.НашДокумент.ПолучитьСсылку(Новый УникальныйИдентификатор());
НовыйДок.УстановитьСсылкуНового(НоваяСсылка);

// Теперь НоваяСсылка — это полноценная ссылка, которую можно передать 
// в измерения регистра сведений еще до вызова метода Записать()

Важный нюанс: если вы используете этот метод и передаете ссылку в регистр, но пользователь нажмет «Отмена» в форме документа, в регистре может остаться запись с «битой» ссылкой (Объект не найден), если вы записывали регистр независимым набором записей вне транзакции документа. Поэтому всегда старайтесь привязывать запись регистра к транзакции записи регистратора.

Вариант 3: Передача данных через ДополнительныеСвойства

Проанализируем ситуацию, когда данные для регистра выбираются в отдельной форме перед созданием документа. Как передать их в модуль объекта, не создавая лишних реквизитов в самом документе? Для этого идеально подходит структура ДополнительныеСвойства.

Рассмотрим последовательность действий:

  1. Открываем общую форму выбора варианта модально или через описание оповещения.
  2. Получаем результат выбора.
  3. При открытии формы документа или программном создании заполняем ДополнительныеСвойства объекта.

В форме документа на сервере это выглядит так:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Если это новый документ и переданы параметры
    Если Объект.Ссылка.Пустая() И Параметры.Свойство("ВыбранныйВариант") Тогда
        
        // Помещаем данные в объект, чтобы они уехали на сервер при записи
        ДокОбъект = РеквизитВЗначение("Объект");
        ДокОбъект.ДополнительныеСвойства.Вставить("ДанныеРегистра", Параметры.ВыбранныйВариант);
        ЗначениеВРеквизит(ДокОбъект, "Объект");
        
    КонецЕсли;
    
КонецПроцедуры

Теперь при нажатии кнопки «Записать» данные будут доступны в модуле объекта в процедуре ПриЗаписи, где мы и выполним наполнение регистра, как описано в первом варианте.

Вариант 4: Подход по аналогии с документом «Операция»

Выясним причину, по которой иногда стоит отказаться от табличных частей в пользу прямого редактирования регистра. В типовых конфигурациях (например, БП 3.0) документ ОперацияБух не имеет табличной части для проводок. Вместо этого на форму выведен набор записей регистра бухгалтерии.

Мы можем поступить так же:

Архитектурные рекомендации

Проанализируем ситуацию с точки зрения долгосрочной поддержки кода. Если вы боитесь, что структура регистра будет часто меняться и вам придется переделывать множество документов, использование подчиненного регистра — это правильный ход. Однако помните о следующих правилах:

  1. Транзакционность: Всегда стремитесь к тому, чтобы запись в регистр происходила в обработчиках модуля объекта документа. Избегайте явного вызова НаборЗаписей.Записать() в коде формы, если это не обосновано специфической логикой.
  2. Проверка заполнения: Не забывайте, что данные в регистре тоже должны проходить валидацию. Используйте обработчик ОбработкаПроверкиЗаполнения в документе, чтобы убедиться, что данные для регистра корректны.
  3. Очистка при удалении: Если регистр подчинен регистратору, платформа сама очистит записи при удалении документа. Если же вы решите сделать регистр независимым, вам придется вручную описывать логику удаления записей в подписке на событие ПередУдалением.

Таким образом, самым надежным и современным способом является сочетание передачи параметров через ДополнительныеСвойства и управление записью через коллекцию Движения в модуле объекта с установкой флага Записывать = Истина.

← На главную