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

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

Разработка механизмов контроля ссылочной целостности в 1С — задача ответственная. Часто стандартного механизма платформы «Обнаружены ссылки на объект» недостаточно, особенно если нужно реализовать специфическую бизнес-логику или вывести детальный отчет в виде табличного документа. Основная сложность заключается в том, что событие ПередУдалением выполняется на сервере внутри транзакции, где невозможно вызвать клиентский метод Показать() для табличного документа.

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

Проблема контекста: Почему нельзя просто вызвать форму?

Проанализируем ситуацию: когда срабатывает подписка на событие ПередУдалением, система уже открыла транзакцию базы данных. Если в коде подписки мы обнаружим связи, мешающие удалению, и установим параметр Отказ = Истина, транзакция будет отменена. Любые попытки открыть форму или показать диалоговое окно напрямую из этого места приведут к ошибке, так как серверный контекст не имеет доступа к экранным формам пользователя. Более того, при отказе все изменения в базе данных (например, запись отчета в регистр сведений) будут аннулированы.

Решение 1: Использование «СообщенияПользователю» с навигационными ссылками

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

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


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

В этом случае пользователь увидит внизу экрана список сообщений. Нажав на любое из них, он автоматически откроет форму объекта, который мешает удалению. Это решает проблему «невозможности открыть объект», хотя и не является полноценным отчетом в табличном документе.

Решение 2: Перехват исключения и сериализация данных

Если нам принципиально нужно показать красивый отчет (табличный документ), проанализируем стратегию передачи данных через текст исключения. Это более сложный, но гибкий путь. Суть его в том, чтобы собрать данные о ссылках на сервере, упаковать их в строку (например, JSON) и передать в клиентский блок Попытка...Исключение.

Шаг 1. Серверная часть (Подписка):


// В подписке ПередУдалением
Если НайденыСсылочныеСвязи Тогда
    ДанныеДляОтчета = Новый Массив;
    Для Каждого СсылкаНаОбъект Из СписокСсылок Цикл
        ДанныеДляОтчета.Добавить(Строка(СсылкаНаОбъект.УникальныйИдентификатор()));
    КонецЦикла;
    
    // Сериализуем данные в JSON
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    ЗаписатьJSON(ЗаписьJSON, ДанныеДляОтчета);
    СтрокаДанных = ЗаписьJSON.Закрыть();
    
    // Передаем маркер и данные в тексте ошибки
    ВызватьИсключение "ОШИБКА_УДАЛЕНИЯ_МАРКЕР|" + СтрокаДанных;
КонецЕсли;

Шаг 2. Клиентская часть (Форма или Команда):

Выясним, как поймать это на клиенте. Нам нужно обернуть вызов удаления в попытку:


&НаКлиенте
Процедура УдалитьОбъектИнтерактивно()
    Попытка
        Объект.Записать(РежимЗаписиОбъекта.Удаление); // Или программное удаление ссылки
    Исключение
        ТекстОшибки = ИнформацияОбОшибке().Описание;
        Если Найти(ТекстОшибки, "ОШИБКА_УДАЛЕНИЯ_МАРКЕР|") > 0 Тогда
            Части = СтрРазделить(ТекстОшибки, "|");
            ДанныеJSON = Части[1];
            
            // Здесь вызываем процедуру формирования и показа ТабДока
            ПоказатьОтчетПоСсылками(ДанныеJSON);
        Иначе
            Сообщить(ТекстОшибки);
        КонецЕсли;
    КонецПопытки;
КонецПроцедуры

Решение 3: Подмена стандартной команды удаления

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

Для этого выполним следующие действия:

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

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

Решение 4: Журнал регистрации как хранилище вне транзакции

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

Посмотрим на алгоритм:

  1. В подписке ПередУдалением, обнаружив ссылки, мы записываем подробный отчет (в формате XML или просто текст) в Журнал регистрации с определенным именем события (например, "КонтрольУдаления").
  2. Устанавливаем Отказ = Истина.
  3. На клиенте в блоке Исключение вызываем серверный метод, который читает последнюю запись из Журнала регистрации по текущему пользователю и объекту.
  4. Формируем на основе этих данных табличный документ и показываем его.

Решение 5: Использование механизмов БСП

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

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

← На главную