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

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

В практике разработчика 1С часто возникает ситуация, когда ссылку на документ необходимо получить еще до того, как он будет физически записан в базу данных. Типичный пример: отправка электронного письма или уведомления в мессенджер в момент нажатия пользователем кнопки «Записать», где в тексте сообщения должна быть рабочая навигационная ссылка на этот самый документ.

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

Анализ проблемы: почему ссылка остается пустой?

Многие начинающие разработчики пытаются получить ссылку в обработчике ПередЗаписью, просто обращаясь к ЭтотОбъект.Ссылка. Однако для нового документа это значение будет пустым, так как уникальный идентификатор (GUID) присваивается объекту системой непосредственно в момент фиксации транзакции записи в таблицу базы данных.

В обсуждении на форуме мы видим типичную ошибку: попытку создать «левый» объект через менеджер документа:


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

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

Правильное решение через метод УстановитьСсылкуНового

Чтобы зарезервировать конкретную ссылку за текущим объектом, нам необходимо использовать метод УстановитьСсылкуНового(). Разберем по шагам, как это реализовать в модуле объекта документа.

Рассмотрим пример кода в процедуре ПередЗаписью:


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

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

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

Особенности работы с навигационными ссылками

Выясним причину, по которой метод ПолучитьНавигационнуюСсылку() может не работать так, как ожидается. Сама по себе функция возвращает внутренний адрес объекта в формате e1cib/data/Документ.ИмяДокумента?ref=....

Если вы планируете отправлять письмо внешнему пользователю, который должен открыть документ в веб-браузере или тонком клиенте, такой ссылки недостаточно. Вам необходимо добавить префикс информационной базы (адрес публикации на веб-сервере). Полная ссылка должна выглядеть примерно так: https://server.com/base_name/#e1cib/data/Документ.Имя....

Риски использования ПередЗаписью для отправки уведомлений

Проанализируем ситуацию с транзакциями. Процедура ПередЗаписью выполняется внутри транзакции. Если после отправки письма выполнение кода прервется ошибкой или переменная Отказ примет значение Истина, запись документа в базу данных не произойдет.

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

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

Пример передачи ссылки через свойства объекта:


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

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

Альтернативный метод: получение ссылки в форме

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

В модуле формы (на клиенте) также доступен метод УстановитьСсылкуНового(), который можно вызвать перед вызовом Записать(). Это позволяет «забронировать» идентификатор объекта заранее, что бывает полезно при интеграции с внешними API или сложными веб-сервисами.

Подводя итог, отметим: получение ссылки на незаписанный документ в 1С — это абсолютно решаемая задача, требующая лишь понимания механизмов генерации УникальныйИдентификатор и правильного использования метода УстановитьСсылкуНового применительно к текущему экземпляру объекта.

← На главную