Сформулируем требования к решению:
- решение не должно требовать изменения типовых форм и объектов;
- инструмент решения должен быть доступен пользователю в точке обнаружения проблемы на расстоянии «одного клика»;
- исполнитель не должен обладать квалификацией разработчика при исправлении ошибки.
Сложности:
В платформе отсутствует возможность прямо обработать исключения такого рода и запрограммировать решение. Попытка открытия «битой ссылки» в управляемых формах, выглядит примерно так:
Блуждание в отладчике выявило возможность, которая позволяет решить вопрос лаконично и универсально.
Техническое решение:
- Создать подписку на событие модуля менеджера. В моем случае, подписка организована на все справочники системы, что бы не возвращаться к вопросу в аналогичной ситуации. Вы, для своих целей, можете в источнике указать менеджеры отдельных справочников, если это где-то нежелательно.
- Создать обработчик в подписке, который определит ошибочный случай и восстановит запись объекта, которую предоставит пользователю в штатном окне.
Способ использования:
Пользователь встречаясь с указанием на потерянные данные по ссылке, выполняет стандартную команду открытия формы потерянного элемента. Система автоматически создает объект в системе, со ссылкой восстановленной из доступных сведений, наименование помечает в формате "Восстановлен: ххххх", где ХХХ - представление внутреннего идентификатора элемента и открывает текущую форму справочника. Если у оператора сеанса есть права на изменение элемента, он может вручную заполнить критичные сведения, и продолжить рабочую эксплуатацию системы. Далее инцидент в рабочем порядке обрабатывается сотрудниками ИТ-отдела.
Исходный текст модулей:
//Обработчик подписки на событие
Процедура ОбработкаПолученияФормыСправочников(парИсточник, парВидФормы, парПараметры, парВыбраннаяФорма, парДополнительнаяИнформация, парСтандартнаяОбработка) Экспорт
Перем пКлюч;
УстановитьПривилегированныйРежим(Истина);
Если парВидФормы = "ФормаОбъекта" Тогда
Если парПараметры.Свойство("Ключ", пКлюч) Тогда //Существующий элемент или создание нового?
пГУИДБитойСсылки = артисСервер.ГУИДБитойСсылки(пКлюч.Ссылка);
Иначе
Возврат;
КонецЕсли;
Если пГУИДБитойСсылки <> Неопределено Тогда
Если парПараметры.ЭтоГруппа Тогда
пОбъект = парИсточник.СоздатьГруппу();
Иначе
пОбъект = парИсточник.СоздатьЭлемент();
КонецЕсли;
пОбъект.УстановитьСсылкуНового(парИсточник.ПолучитьСсылку(Новый УникальныйИдентификатор(пГУИДБитойСсылки)));
пОбъект.ОбменДанными.Загрузка = Истина;
пОбъект.Наименование = "Восстановлен: " + парПараметры.Ключ.Ссылка;
пОбъект.Записать();
Сообщить("Восстановлена запись удаленного элемента, заполните реквизиты и сохраните объект!");
КонецЕсли;
КонецЕсли;
КонецПроцедуры
// Возвращает строку-ГУИД из первичного сообщения системы, например: <Объект не найден> (84:bf5600145e3710ab11dda4c605dbe824)
// Параметры:
// парНачальноеПредставлениеУдаленнойСсылки - строка вида: <Объект не найден> (84:bf5600145e3710ab11dda4c605dbe824)
Функция ПолучитьГУИДПоПредставлениюУдаленнойСсылки(парНачальноеПредставлениеУдаленнойСсылки) Экспорт
пГУИДУдОбъктаСтр = СтрЗаменить(СокрЛП(парНачальноеПредставлениеУдаленнойСсылки),"<Объект не найден> (","");
пГУИДУдОбъктаСтр = СтрЗаменить(пГУИДУдОбъктаСтр,")","");
пГУИДУдОбъктаСтр = СтрЗаменить(пГУИДУдОбъктаСтр,"0x","");
пГУИДУдОбъктаСтр = Сред(пГУИДУдОбъктаСтр, Найти(пГУИДУдОбъктаСтр,":")+1, СтрДлина(пГУИДУдОбъктаСтр));
// Преобразуем GUID
Возврат Сред(пГУИДУдОбъктаСтр,25,8)+"-"+Сред(пГУИДУдОбъктаСтр,21,4)+"-"+Сред(пГУИДУдОбъктаСтр,17,4)+"-"+Сред(пГУИДУдОбъктаСтр,1,4)+"-"+Сред(пГУИДУдОбъктаСтр,5,12); //и получаем ГУИД = 05dbe824-a4c6-11dd-bf56-00145e3710ab
КонецФункции
// Проверяет ссылку на признак <Объект не найден>
// В случае отсутствия элемента, создает текстовый параметр для Новый УникальныйИдентификатор()
// этот способ работает быстрее, чем попытка создания объекта, как это предлагается в некоторых рекомендациях
// Параметры:
// парСсылка - ссылка системы, для которой необходимо создать объект, в случае если объект удален
// Возврат:
// Неопределено - ссылка реальная и не требует создания экземпляра или
// НормальныйГУИД, готовый для: Объект.УстановитьСсылкуНового(Новый УникальныйИдентификатор(УникальныйИд));
Функция ГУИДБитойСсылки(парСсылка) Экспорт
пПредставлениеСсылки = СокрЛП(парСсылка);
Если Лев(пПредставлениеСсылки, 20) = "<Объект не найден> (" Тогда
Возврат ПолучитьГУИДПоПредставлениюУдаленнойСсылки(пПредставлениеСсылки);
Иначе
Возврат Неопределено;
КонецЕсли;
КонецФункции
Спасибо всем за внимание.