Как при проведении документа записать его ссылку в реквизит другого документа в 1С

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

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

Рассмотрим подробно, как правильно реализовать эту логику программно, на какие технологические риски следует обратить внимание и какие существуют альтернативные архитектурные решения.

Программный алгоритм записи ссылки при проведении

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

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

Разберем пример кода, который помещается в модуль проводимого (второго) документа:


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

КонецПроцедуры

Очистка ссылки при отмене проведения

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

Рассмотрим код для отмены проведения:


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

КонецПроцедуры

Ограничения платформы и технические риски

Проанализируем технические нюансы, с которыми можно столкнуться при перезаписи одного документа из модуля проведения другого:

  1. Конфликт блокировок и транзакций: проведение второго документа происходит внутри транзакции. Если первый документ в этот момент открыт и редактируется другим пользователем, возникнет исключение блокировки данных.
  2. Конфликт версий данных: если у пользователя открыта форма первого документа, то после модификации этого документа кодом проведения при попытке сохранить форму вручную вызовет ошибку «Данные были изменены или удалены другим пользователем».
  3. Права доступа (RLS): у пользователя, проводящего второй документ, может не быть прав на запись первого документа. В таком случае потребуется использовать метод УстановитьПривилегированныйРежим(Истина).
  4. Период запрета изменения: если первый документ попал в закрытый период, вызов метода Записать() вернет ошибку и отменит проведение текущего документа.

Альтернативные архитектурные решения

Запись ссылки в уже записанный и проведенный документ считается не всегда оптимальной практикой, так как меняется исторический объект. Рассмотрим более надежные подходы:

1. Использование механизма «Ввод на основании»
Если Второй Документ создается на основании Первого, то во Втором Документе достаточно хранить реквизит ДокументОснование. Платформа 1С и стандартный отчет «Структура подчиненности» автоматически покажут связь документов без необходимости записывать встречные ссылки.

2. Использование регистра сведений для хранения связей
Вместо изменения реквизита первого документа создается независимый или подчиненный регистратору регистр сведений (например, СвязиДокументов):

  1. Измерение: Документ1 (тип: ссылка на первый документ).
  2. Ресурс или измерение: Документ2 (тип: ссылка на второй документ).

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

← На главную