#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
#Область СлужебныеПроцедурыИФункции
Функция УдалитьПомеченныеОбъекты(ПараметрыУдаления, ИдентификаторЗадания = Неопределено) Экспорт
Если НЕ Пользователи.ЭтоПолноправныйПользователь() Тогда
ВызватьИсключение(НСтр("ru = 'Недостаточно прав для выполнения операции.'"), КатегорияОшибки.НарушениеПравДоступа);
КонецЕсли;
Замер = ТекущаяУниверсальнаяДатаВМиллисекундах();
УдалениеПомеченныхОбъектовПереопределяемый.ПередПоискомПомеченныхНаУдаление(ПараметрыУдаления);
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
МодульУправлениеДоступом = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступом");
МодульУправлениеДоступом.ОтключитьОбновлениеКлючейДоступа(Истина);
КонецЕсли;
Попытка
УдаляемыеОбъекты = ПараметрыУдаления.ПользовательскиеОбъекты;
РезультатУдаления = РезультатУдаления(УдаляемыеОбъекты, ПараметрыУдаления);
Если ЗначениеЗаполнено(ИдентификаторЗадания)Тогда
РезультатУдаления.ИдентификаторЗадания = ИдентификаторЗадания;
КонецЕсли;
Если РезультатУдаления.Монопольно Тогда
УдалитьПомеченныеОбъектыМонопольно(УдаляемыеОбъекты, РезультатУдаления);
Иначе
УдалитьПомеченныеОбъектыКонкурентно(УдаляемыеОбъекты, РезультатУдаления);
КонецЕсли;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
МодульУправлениеДоступом = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступом");
МодульУправлениеДоступом.ОтключитьОбновлениеКлючейДоступа(Ложь);
КонецЕсли;
Исключение
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
МодульУправлениеДоступом = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступом");
МодульУправлениеДоступом.ОтключитьОбновлениеКлючейДоступа(Ложь);
КонецЕсли;
ВызватьИсключение;
КонецПопытки;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Взаимодействия") Тогда
МодульВзаимодействия = ОбщегоНазначения.ОбщийМодуль("Взаимодействия");
МодульВзаимодействия.ПослеУдаленияПомеченных(РезультатУдаления);
КонецЕсли;
Замер = ТекущаяУниверсальнаяДатаВМиллисекундах() - Замер;
ОтправитьСтатистику(ПараметрыУдаления.Режим, Замер, РезультатУдаления.Всего);
Возврат РезультатУдаления;
КонецФункции
#Область КонкурентноеУдаление
Процедура УдалитьПомеченныеОбъектыКонкурентно(УдаляемыеОбъекты, ПараметрыУдаления)
СведенияОМетаданных = СведенияОМетаданных(ПараметрыУдаления, УдаляемыеОбъекты);
УдаляемыеОбъекты = УдаляемыеОбъекты(УдаляемыеОбъекты, СведенияОМетаданных);
РезультатОбработки = ОбработатьУдаляемыеОбъекты(ПараметрыУдаления, УдаляемыеОбъекты, СведенияОМетаданных);
ОтразитьМестаИспользования(ПараметрыУдаления, РезультатОбработки.МестаИспользования);
ОтразитьНеУдаленные(ПараметрыУдаления, РезультатОбработки.НеудаленныеОбъекты);
ПараметрыУдаления.Удаленные = Новый Массив(Новый ФиксированныйМассив(РезультатОбработки.УдаленныеОбъекты));
КонецПроцедуры
#Область ПреобразованиеКФорматуРезультата
Процедура ОтразитьНеУдаленные(ПараметрыУдаления, НеУдаленные)
ВерсииДанных = СтандартныеПодсистемыСервер.ЗначенияРеквизитовОбъектовЕслиСуществуют(
НеУдаленные.ВыгрузитьКолонку("УдаляемыйСсылка"), "ВерсияДанных");
Для Каждого Элемент Из НеУдаленные Цикл
Если ОбъектУдален(Элемент.УдаляемыйСсылка, ВерсииДанных) Тогда
Продолжить;
КонецЕсли;
ПараметрыУдаления.Неудаленные.Добавить(Элемент.УдаляемыйСсылка);
Если Элемент.РезультатУдаления <> КодыРезультатаУдаления().НеПомеченНаУдаление Тогда
РегистрыСведений.НеудаленныеОбъекты.Добавить(Элемент.УдаляемыйСсылка);
КонецЕсли;
Если Элемент.РезультатУдаления = КодыРезультатаУдаления().ОшибкаПриУдалении Тогда
Причина = ПараметрыУдаления.ПрепятствующиеУдалению.Добавить();
Причина.УдаляемыйСсылка = Элемент.УдаляемыйСсылка;
Причина.ОписаниеОшибки = ОбработкаОшибок.КраткоеПредставлениеОшибки(Элемент.ИнформацияОбОшибке) + Элемент.Сообщения;
Причина.ПодробноеОписаниеОшибки = ОбработкаОшибок.ПодробноеПредставлениеОшибки(Элемент.ИнформацияОбОшибке);
ИначеЕсли Элемент.РезультатУдаления = КодыРезультатаУдаления().НеПомеченНаУдаление Тогда
Причина = ПараметрыУдаления.ПрепятствующиеУдалению.Добавить();
Причина.УдаляемыйСсылка = Элемент.УдаляемыйСсылка;
Причина.ОписаниеОшибки = НСтр("ru='Удаляемый объект не помечен на удаление.'");
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ОтразитьМестаИспользования(ПараметрыУдаления, МестаИспользования)
ВерсииДанных = СтандартныеПодсистемыСервер.ЗначенияРеквизитовОбъектовЕслиСуществуют(
МестаИспользования.ВыгрузитьКолонку("МестоИспользования"), "ВерсияДанных");
ПрепятствующиеУдалению = ПараметрыУдаления.ПрепятствующиеУдалению;
Для Каждого СведенияОМестеИспользования Из МестаИспользования Цикл
Если ОбъектУдален(СведенияОМестеИспользования.МестоИспользования, ВерсииДанных) Тогда
Продолжить;
КонецЕсли;
Причина = ПрепятствующиеУдалению.Добавить();
Причина.УдаляемыйСсылка = СведенияОМестеИспользования.УдаляемыйСсылка;
Причина.МестоИспользования = СведенияОМестеИспользования.МестоИспользования;
Причина.Метаданные = СведенияОМестеИспользования.Метаданные;
КонецЦикла;
КолонкиПрепятствующиеУдалению = Новый Массив;
Для каждого Колонка Из ПрепятствующиеУдалению.Колонки Цикл
КолонкиПрепятствующиеУдалению.Добавить(Колонка.Имя);
КонецЦикла;
ПрепятствующиеУдалению.Свернуть(СтрСоединить(КолонкиПрепятствующиеУдалению, ","));
КонецПроцедуры
#КонецОбласти
#Область УдалениеОбъектов
Функция ОбработатьУдаляемыеОбъекты(ПараметрыУдаления, УдаляемыеОбъекты, СведенияОМетаданных)
РезультатыУдаления = РезультатОбработки();
Пакет = ПакетУдаляемыхОбъектов();
ОбъектыСЗапретомУдаления = ПакетУдаляемыхОбъектов();
Для Каждого ЭлементОчереди Из УдаляемыеОбъекты Цикл
Если НЕ Пакет.Найти(ЭлементОчереди.УдаляемыйСсылка, "УдаляемыйСсылка") <> Неопределено Тогда
ЭлементОчередиВПакете = ЭлементОчередиВПакет(ЭлементОчереди, СведенияОМетаданных, Пакет);
Если ЗапрещенаОбработкаЭлемента(ЭлементОчередиВПакете) Тогда
ОбъектыСЗапретомУдаления = ОбъединениеТаблиц(ОбъектыСЗапретомУдаления, ЭлементОчередиВПакете);
Иначе
Пакет = ОбъединениеТаблиц(Пакет, ЭлементОчередиВПакете, Истина);
КонецЕсли;
КонецЕсли;
Если Пакет.Количество() >= ПараметрыУдаления.РазмерПакета
ИЛИ УдаляемыеОбъекты.Индекс(ЭлементОчереди) = УдаляемыеОбъекты.Количество()-1 Тогда
РезультатОбработкиПакета = ОбработатьПакет(ПараметрыУдаления, Пакет);
ОбъединитьРезультатУдаления(РезультатыУдаления, РезультатОбработкиПакета);
Пакет.Очистить();
КонецЕсли;
КонецЦикла;
РезультатУдаленияИзНеобработанногоПакета = РезультатУдаленияИзНеобработанногоПакета(ПараметрыУдаления, ОбъектыСЗапретомУдаления);
ОбъединитьРезультатУдаления(РезультатыУдаления, РезультатУдаленияИзНеобработанногоПакета);
КоличествоНеудаленныхЭлементов = 0;
Пока РезультатыУдаления.НеудаленныеОбъекты.Количество() <> КоличествоНеудаленныхЭлементов Цикл
КоличествоНеудаленныхЭлементов = РезультатыУдаления.НеудаленныеОбъекты.Количество();
Пакет = ЦиклическиеСсылки(РезультатыУдаления.НеудаленныеОбъекты, РезультатыУдаления.МестаИспользования);
РезультатОбработкиЦиклическихСсылок = ОбработатьПакетВОднойТранзакции(ПараметрыУдаления, Пакет);
Если РезультатОбработкиЦиклическихСсылок.УдаленныеОбъекты.Количество() > 0 Тогда
РезультатыУдаления = РезультатПослеУдаленияЦиклическихСсылок(РезультатыУдаления, РезультатОбработкиЦиклическихСсылок);
КонецЕсли;
КонецЦикла;
Возврат РезультатыУдаления;
КонецФункции
Функция РезультатУдаленияИзНеобработанногоПакета(ПараметрыУдаления, ОбъектыСЗапретомУдаления)
РезультатыУдаления = РезультатОбработки();
РезультатыУдаления.НеудаленныеОбъекты = ОбъединениеТаблиц(
РезультатыУдаления.НеудаленныеОбъекты,
ОбъектыСЗапретомУдаления);
РезультатыУдаления.МестаИспользования = ОбъединениеТаблиц(
РезультатыУдаления.МестаИспользования,
ОставшиесяМестаИспользованияУдаляемогоОбъекта(ПараметрыУдаления,
МестаИспользованияЭлементовПакета(ПараметрыУдаления, ОбъектыСЗапретомУдаления)));
Возврат РезультатыУдаления;
КонецФункции
Функция ЗапрещенаОбработкаЭлемента(ЭлементОчередиВПакете)
Возврат (ЭлементОчередиВПакете.Количество() > 0
И ЭлементОчередиВПакете[ЭлементОчередиВПакете.Количество() - 1].РезультатУдаления
<> КодыРезультатаУдаления().Успешно);
КонецФункции
Функция ЭлементОчередиВПакет(ЭлементОчереди, СведенияОМетаданных, Исключения)
Пакет = ПакетУдаляемыхОбъектов();
РезультатУдаления = Неопределено;
Если НЕ ОбъектУдален(ЭлементОчереди.УдаляемыйСсылка)
И Исключения.Найти(ЭлементОчереди.УдаляемыйСсылка, "УдаляемыйСсылка") = Неопределено Тогда
ИнформацияОМетаданных = СведенияОМетаданных.Найти(ЭлементОчереди.Тип, "Тип");
ПометкаУдаления = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ЭлементОчереди.УдаляемыйСсылка, "ПометкаУдаления");
ДочерниеПодчиненныеЭлементы = ?(ПометкаУдаления,
ДочерниеПодчиненныеЭлементы(ЭлементОчереди.УдаляемыйСсылка, ИнформацияОМетаданных),
ТаблицаДочернихПодчиненныхЭлементов());
Если НЕ ПометкаУдаления Тогда
РезультатУдаления = КодыРезультатаУдаления().НеПомеченНаУдаление;
ИначеЕсли РазрешеноУдалениеЭлемента(ДочерниеПодчиненныеЭлементы) Тогда
РезультатУдаления = КодыРезультатаУдаления().Успешно;
ДополнитьПакетДочернимиИПодчиненнымиЭлементами(Пакет, ЭлементОчереди.УдаляемыйСсылка, ДочерниеПодчиненныеЭлементы, Исключения);
Иначе
РезультатУдаления = КодыРезультатаУдаления().ЕстьДочерниеПодчиненныеЭлементыНепомеченныеНаУдаление;
КонецЕсли;
ЭлементПакета = Пакет.Добавить();
ЭлементПакета.УдаляемыйСсылка = ЭлементОчереди.УдаляемыйСсылка;
ЭлементПакета.ЕстьДочерниеОбъекты = ИнформацияОМетаданных.Иерархический;
ЭлементПакета.ЕстьПодчиненныеОбъекты = ИнформацияОМетаданных.ЕстьПодчиненныеОбъекты;
ЭлементПакета.ДочерниеПодчиненныеОбъекты = ДочерниеПодчиненныеЭлементы;
ЭлементПакета.РезультатУдаления = РезультатУдаления;
ЭлементПакета.ЭтоОсновнойОбъект = Истина;
ЭлементПакета.ОсновнойЭлементСсылка = ЭлементОчереди.УдаляемыйСсылка;
КонецЕсли;
Возврат Пакет;
КонецФункции
Функция ОбработатьПакет(ПараметрыУдаления, Пакет)
РезультатОбработкиПакета = РезультатОбработки();
Если ЗначениеЗаполнено(ПараметрыУдаления.ИдентификаторЗадания) И ОбщегоНазначения.РежимОтладки() Тогда
Идентификатор = ПараметрыУдаления.ИдентификаторЗадания;
Иначе
УстановитьПривилегированныйРежим(Истина);
ФоновоеЗадание = ПолучитьТекущийСеансИнформационнойБазы().ПолучитьФоновоеЗадание();
Идентификатор = ?(ФоновоеЗадание <> Неопределено, ФоновоеЗадание.УникальныйИдентификатор, Новый УникальныйИдентификатор);
УстановитьПривилегированныйРежим(Ложь);
КонецЕсли;
ПередОбработкойПакета(Пакет, Идентификатор);
МестаИспользования = МестаИспользованияЭлементовПакета(ПараметрыУдаления, Пакет);
ОсновнойИПодчиненныеОбъекты = Новый Массив;
СсылкиНаУдаляемыеОбъекты = Новый Массив;
Для Каждого Элемент Из Пакет Цикл
ОсновнойИПодчиненныеОбъекты.Добавить(Элемент);
СсылкиНаУдаляемыеОбъекты.Добавить(Элемент.УдаляемыйСсылка);
Если НЕ Элемент.ЭтоОсновнойОбъект Тогда
Продолжить;
КонецЕсли;
Контекст = Новый Структура;
ПередУдалениемГруппыОбъектов(Контекст, ОбщегоНазначения.ФиксированныеДанные(СсылкиНаУдаляемыеОбъекты, Ложь));
НельзяУдалятьОсновнойОбъект = Ложь;
НеудаленныеЭлементы = Новый Массив;
ТранзакцияОтменена = Ложь;
НачатьТранзакцию();
Попытка
ОсновнойОбъект = ОсновнойИПодчиненныеОбъекты[ОсновнойИПодчиненныеОбъекты.ВГраница()];
Для каждого УдаляемыйЭлемент Из ОсновнойИПодчиненныеОбъекты Цикл
Фильтр = Новый Структура("УдаляемыйСсылка", УдаляемыйЭлемент.УдаляемыйСсылка);
РезультатУдаления = УдалитьЭлементПакета(ПараметрыУдаления, УдаляемыйЭлемент,
МестаИспользования.Скопировать(Фильтр), НеудаленныеЭлементы);
Если РезультатУдаления.ИнформацияОбОшибке <> Неопределено Тогда
ОтменитьТранзакцию();
ТранзакцияОтменена = Истина;
КонецЕсли;
ОтразитьРезультатУдаленияЭлементаПакета(ПараметрыУдаления, РезультатОбработкиПакета, РезультатУдаления);
Если НЕ УдаляемыйЭлемент.ЭтоОсновнойОбъект И РезультатУдаления.Код = КодыРезультатаУдаления().ОшибкаПриУдалении Тогда
НельзяУдалятьОсновнойОбъект = Истина;
НеудаленныеЭлементы.Добавить(РезультатУдаления.УдаляемыйСсылка);
РезультатУдаленияОсновногоЭлемента = РезультатУдаленияЭлемента(ОсновнойОбъект);
РезультатУдаленияОсновногоЭлемента.Код = КодыРезультатаУдаления().ЕстьМестаИспользования;
Фильтр = Новый Структура("УдаляемыйСсылка, МестоИспользования", ОсновнойОбъект.УдаляемыйСсылка, УдаляемыйЭлемент.УдаляемыйСсылка);
РезультатУдаленияОсновногоЭлемента.МестаИспользования = МестаИспользования.Скопировать(Фильтр);
ОтразитьРезультатУдаленияЭлементаПакета(ПараметрыУдаления, РезультатОбработкиПакета,
РезультатУдаленияОсновногоЭлемента);
Прервать;
ИначеЕсли РезультатУдаления.Код <> КодыРезультатаУдаления().Успешно Тогда
НельзяУдалятьОсновнойОбъект = Истина;
НеудаленныеЭлементы.Добавить(РезультатУдаления.УдаляемыйСсылка);
КонецЕсли;
КонецЦикла;
Если Не ТранзакцияОтменена Тогда
Если НЕ НельзяУдалятьОсновнойОбъект Тогда
ЗафиксироватьТранзакцию();
Иначе
ОтменитьТранзакцию();
КонецЕсли;
КонецЕсли;
Исключение
Если Не ТранзакцияОтменена Тогда
ОтменитьТранзакцию();
КонецЕсли;
ВызватьИсключение;
КонецПопытки;
ПослеУдаленияГруппыОбъектов(Контекст, НЕ НельзяУдалятьОсновнойОбъект);
ОсновнойИПодчиненныеОбъекты.Очистить();
СсылкиНаУдаляемыеОбъекты.Очистить();
КонецЦикла;
ПослеОбработкиПакета(ПараметрыУдаления, Идентификатор);
ОчиститьСсылкиНаУдаляемыеОбъекты(ПараметрыУдаления, РезультатОбработкиПакета);
Возврат РезультатОбработкиПакета;
КонецФункции
Процедура ПередУдалениемГруппыОбъектов(Контекст, УдаляемыеОбъекты)
ИнтеграцияПодсистемБСП.ПередУдалениемГруппыОбъектов(Контекст, УдаляемыеОбъекты);
УдалениеПомеченныхОбъектовПереопределяемый.ПередУдалениемГруппыОбъектов(Контекст, УдаляемыеОбъекты);
КонецПроцедуры
Процедура ПослеУдаленияГруппыОбъектов(Контекст, Успешно)
ИнтеграцияПодсистемБСП.ПослеУдаленияГруппыОбъектов(Контекст, Успешно);
УдалениеПомеченныхОбъектовПереопределяемый.ПослеУдаленияГруппыОбъектов(Контекст, Успешно);
КонецПроцедуры
Функция РезультатУдаленияЭлемента(Знач Элемент)
Результат = Новый Структура();
Результат.Вставить("УдаляемыйСсылка", Элемент.УдаляемыйСсылка);
Результат.Вставить("Код", КодыРезультатаУдаления().Успешно);
Результат.Вставить("МестаИспользования", МестаИспользования());
Результат.Вставить("Сообщения", Новый ФиксированныйМассив(Новый Массив));
Результат.Вставить("ЭтоОсновнойОбъект", Элемент.ЭтоОсновнойОбъект);
Результат.Вставить("ИнформацияОбОшибке");
Возврат Результат;
КонецФункции
#Область ОчисткаСсылокНаУдаляемыеОбъекты
Процедура ОчиститьСсылкиНаУдаляемыеОбъекты(ПараметрыУдаления, РезультатОбработкиПакета)
Если Не ПараметрыУдаления.ОчищатьСсылкиВМестахИспользования
Или РезультатОбработкиПакета.МестаОчисткиСсылок.Количество() = 0 Тогда
Возврат;
КонецЕсли;
МестаИспользования = РезультатОбработкиПакета.МестаОчисткиСсылок;
МестаИспользования.Сортировать("МестоИспользования", Новый СравнениеЗначений());
УдаляемыеОбъектыВМестеИспользования = Новый Массив;
ПозицияТекущегоМестаИспользования = 0;
Для Каждого СведениеОМестеИспользования Из МестаИспользования Цикл
Если МестаИспользования[ПозицияТекущегоМестаИспользования].МестоИспользования
<> СведениеОМестеИспользования.МестоИспользования Тогда
ОчиститьСсылкиВМестеИспользования(МестаИспользования[ПозицияТекущегоМестаИспользования].МестоИспользования,
УдаляемыеОбъектыВМестеИспользования);
ПозицияТекущегоМестаИспользования = МестаИспользования.Индекс(СведениеОМестеИспользования);
УдаляемыеОбъектыВМестеИспользования.Очистить();
КонецЕсли;
УдаляемыеОбъектыВМестеИспользования.Добавить(СведениеОМестеИспользования.УдаляемыйСсылка);
Если МестаИспользования.Индекс(СведениеОМестеИспользования) = МестаИспользования.Количество() - 1 Тогда
ОчиститьСсылкиВМестеИспользования(СведениеОМестеИспользования.МестоИспользования,
УдаляемыеОбъектыВМестеИспользования);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ОчиститьСсылкиВМестеИспользования(МестоИспользования, УдаляемыеОбъекты)
НачатьТранзакцию();
Попытка
МетаданныеОбъекта = МестоИспользования.Метаданные();
Блокировка = Новый БлокировкаДанных();
Элемент = Блокировка.Добавить(МестоИспользования.Метаданные().ПолноеИмя());
Элемент.УстановитьЗначение("Ссылка", МестоИспользования);
Блокировка.Заблокировать();
МестоИспользованияОбъект = МестоИспользования.ПолучитьОбъект();
Если МестоИспользованияОбъект = Неопределено Тогда
ЗафиксироватьТранзакцию();
Возврат;
КонецЕсли;
ОчиститьСсылкиВКоллекцииРеквизитов(МестоИспользованияОбъект, МетаданныеОбъекта.СтандартныеРеквизиты, УдаляемыеОбъекты);
ОчиститьСсылкиВКоллекцииРеквизитов(МестоИспользованияОбъект, МетаданныеОбъекта.Реквизиты, УдаляемыеОбъекты);
Для Каждого ТабличнаяЧасть Из МетаданныеОбъекта.ТабличныеЧасти Цикл
ОчиститьСсылкиВТабличнойЧасти(МестоИспользованияОбъект[ТабличнаяЧасть.Имя], ТабличнаяЧасть.Реквизиты, УдаляемыеОбъекты);
КонецЦикла;
ЕстьСтандартныеТабличныеЧасти = ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(МетаданныеОбъекта,
"СтандартныеТабличныеЧасти");
СтандартныеТабличныеЧасти = ?(ЕстьСтандартныеТабличныеЧасти,
МетаданныеОбъекта.СтандартныеТабличныеЧасти,
Новый Массив);
Для Каждого ТабличнаяЧасть Из СтандартныеТабличныеЧасти Цикл
ОчиститьСсылкиВТабличнойЧасти(МестоИспользованияОбъект[ТабличнаяЧасть.Имя], ТабличнаяЧасть.СтандартныеРеквизиты, УдаляемыеОбъекты);
КонецЦикла;
МестоИспользованияОбъект.ДополнительныеСвойства.Вставить("НеВыполнятьКонтрольУдаляемых");
МестоИспользованияОбъект.ОбменДанными.Загрузка = Истина;
МестоИспользованияОбъект.Записать();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ЗаписатьПредупреждение(НСтр("ru = 'Не удалось очистить ссылки на удаляемый объект в ""%1"" по причине:'"),
МестоИспользования, ИнформацияОбОшибке());
КонецПопытки;
КонецПроцедуры
Процедура ОчиститьСсылкиВТабличнойЧасти(МестоИспользованияОбъект, КоллекцияРеквизитов, УдаляемыеОбъекты)
Для Каждого СтрокаТЧ Из МестоИспользованияОбъект Цикл
ОчиститьСсылкиВКоллекцииРеквизитов(СтрокаТЧ, КоллекцияРеквизитов, УдаляемыеОбъекты);
КонецЦикла;
КонецПроцедуры
Процедура ОчиститьСсылкиВКоллекцииРеквизитов(МестоИспользованияОбъект, КоллекцияРеквизитов, УдаляемыеОбъекты)
Для Каждого Реквизит Из КоллекцияРеквизитов Цикл
Если УдаляемыеОбъекты.Найти(МестоИспользованияОбъект[Реквизит.Имя]) <> Неопределено Тогда
МестоИспользованияОбъект[Реквизит.Имя] = Реквизит.Тип.ПривестиЗначение(Неопределено);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция РезультатПослеУдаленияЦиклическихСсылок(РезультатыУдаления, РезультатОбработкиЦиклическихСсылок)
Результат = РезультатОбработки();
Результат.УдаленныеОбъекты = Новый Массив(Новый ФиксированныйМассив(РезультатыУдаления.УдаленныеОбъекты));
Для Каждого Элемент Из РезультатыУдаления.НеудаленныеОбъекты Цикл
Если РезультатОбработкиЦиклическихСсылок.УдаленныеОбъекты.Найти(Элемент.УдаляемыйСсылка) <> Неопределено Тогда
Результат.УдаленныеОбъекты.Добавить(Элемент.УдаляемыйСсылка);
Иначе
ЗаполнитьЗначенияСвойств(Результат.НеудаленныеОбъекты.Добавить(), Элемент);
Для Каждого МестоИспользования Из РезультатыУдаления.МестаИспользования.НайтиСтроки(Новый Структура("УдаляемыйСсылка", Элемент.УдаляемыйСсылка)) Цикл
ЗаполнитьЗначенияСвойств(Результат.МестаИспользования.Добавить(), МестоИспользования);
КонецЦикла;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
#КонецОбласти
#Область ФормированиеДочернихПодчиненныхЭлементов
Функция ДочерниеПодчиненныеЭлементы(УдаляемыйСсылка, ИнформацияОМетаданных)
УстановитьПривилегированныйРежим(Истина);
ДочерниеПодчиненныеЭлементы = ТаблицаДочернихПодчиненныхЭлементов();
ПакетыЗапроса = Новый Массив;
Если ИнформацияОМетаданных.Иерархический Тогда
ПакетыЗапроса.Добавить(ТекстЗапросаДочернихЭлементов(ИнформацияОМетаданных));
КонецЕсли;
Если ИнформацияОМетаданных.ОписаниеПодчиненныхОбъектов.Количество() > 0 Тогда
ПакетыЗапроса.Добавить(ТекстЗапросаПодчиненныхЭлементов(ИнформацияОМетаданных));
КонецЕсли;
Если ПакетыЗапроса.Количество() > 0 Тогда
ТекстЗапроса = СтрСоединить(ПакетыЗапроса, ОбщегоНазначения.РазделительПакетаЗапросов());
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("Родитель", УдаляемыйСсылка);
Запрос.УстановитьПараметр("Ссылка", УдаляемыйСсылка);
РезультатПакета = Запрос.ВыполнитьПакет();
Если ИнформацияОМетаданных.ОписаниеПодчиненныхОбъектов.Количество() > 0 Тогда
ВыборкаПодчиненныхЭлементов = РезультатПакета[РезультатПакета.Количество()-1].Выбрать();
ДочерниеПодчиненныеЭлементы = ОбъединениеТаблиц(ДочерниеПодчиненныеЭлементы,
ПодчиненныеЭлементы(ВыборкаПодчиненныхЭлементов));
КонецЕсли;
Если ИнформацияОМетаданных.Иерархический Тогда
ВыборкаДочернихЭлементов = РезультатПакета[0].Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
ДочерниеПодчиненныеЭлементы = ОбъединениеТаблиц(ДочерниеПодчиненныеЭлементы,
ДочерниеЭлементы(УдаляемыйСсылка, ВыборкаДочернихЭлементов));
КонецЕсли;
КонецЕсли;
Возврат ДочерниеПодчиненныеЭлементы;
КонецФункции
Функция ДочерниеЭлементы(ОсновнойЭлемент, РезультатПакета)
Результат = ТаблицаДочернихПодчиненныхЭлементов();
Для Каждого СтрокаДерева Из РезультатПакета.Строки Цикл
Если СтрокаДерева.Элемент = ОсновнойЭлемент Тогда
ДочерниеЭлементы = ДочерниеЭлементы(ОсновнойЭлемент, СтрокаДерева);
Результат = ОбъединениеТаблиц(Результат, ДочерниеЭлементы)
Иначе
ЗаписьРезультата = Результат.Добавить();
ЗаполнитьЗначенияСвойств(ЗаписьРезультата, СтрокаДерева);
ЗаписьРезультата.ДочерниеЭлементы = ДочерниеЭлементы(ОсновнойЭлемент, СтрокаДерева);
Результат = ОбъединениеТаблиц(ЗаписьРезультата.ДочерниеЭлементы, Результат, Истина);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ПодчиненныеЭлементы(РезультатПакета)
ДочерниеПодчиненныеЭлементы = ТаблицаДочернихПодчиненныхЭлементов();
Пока РезультатПакета.Следующий() Цикл
ЗаполнитьЗначенияСвойств(ДочерниеПодчиненныеЭлементы.Добавить(), РезультатПакета);
КонецЦикла;
Возврат ДочерниеПодчиненныеЭлементы;
КонецФункции
Функция ТаблицаДочернихПодчиненныхЭлементов()
ДочерниеПодчиненныеЭлементы = Новый ТаблицаЗначений();
ДочерниеПодчиненныеЭлементы.Колонки.Добавить("Элемент");
ДочерниеПодчиненныеЭлементы.Колонки.Добавить("ДочерниеЭлементы", Новый ОписаниеТипов("ТаблицаЗначений"));
ДочерниеПодчиненныеЭлементы.Колонки.Добавить("ПометкаУдаления", Новый ОписаниеТипов("Булево"));
ДочерниеПодчиненныеЭлементы.Колонки.Добавить("ТипЭлемента", Новый ОписаниеТипов("Строка"));
Возврат ДочерниеПодчиненныеЭлементы
КонецФункции
Функция ТекстЗапросаДочернихЭлементов(ИнформацияОМетаданных)
ШаблонЗапроса = "ВЫБРАТЬ
| Таб.Ссылка КАК Элемент,
| Таб.ПометкаУдаления КАК ПометкаУдаления,
| ""Дочерний"" КАК ТипЭлемента
|ИЗ
| &ИмяТаблицы КАК ТАБ
|ГДЕ
| Таб.Ссылка В ИЕРАРХИИ (&Родитель)
|УПОРЯДОЧИТЬ ПО
| Элемент ИЕРАРХИЯ";
Таблица = ИнформацияОМетаданных.Метаданные.ПолноеИмя();
ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "&ИмяТаблицы", Таблица);
Возврат ТекстЗапроса;
КонецФункции
Функция ТекстЗапросаПодчиненныхЭлементов(ИнформацияОМетаданных)
ТекстыЗапросов = Новый Массив;
ШаблонУсловияСвязи = "Таб.%1 = &Ссылка";
ШаблонЗапроса = "ВЫБРАТЬ
| Таб.Ссылка КАК Элемент,
| Таб.ПометкаУдаления КАК ПометкаУдаления,
| ""Подчиненный"" КАК ТипЭлемента
|ИЗ
| &ИмяТаблицы КАК ТАБ
|ГДЕ
| Таб.Ссылка <> &Ссылка
| И &УсловиеСвязи";
УсловиеСвязи = "ЛОЖЬ";
Для Каждого ПодчиненныйОбъект Из ИнформацияОМетаданных.ОписаниеПодчиненныхОбъектов Цикл
УсловиеСвязи = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонУсловияСвязи, ПодчиненныйОбъект.ИмяРеквизита);
ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "&ИмяТаблицы", ПодчиненныйОбъект.Метаданные.ПолноеИмя());
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеСвязи", УсловиеСвязи);
ТекстыЗапросов.Добавить(ТекстЗапроса);
КонецЦикла;
Возврат СтрСоединить(ТекстыЗапросов, Символы.ПС + "ОБЪЕДИНИТЬ ВСЕ" + Символы.ПС);
КонецФункции
#КонецОбласти
Процедура ОбъединитьРезультатУдаления(РезультатыУдаления, РезультатОбработки)
РезультатыУдаления.НеудаленныеОбъекты = ОбъединениеТаблиц(РезультатыУдаления.НеудаленныеОбъекты, РезультатОбработки.НеудаленныеОбъекты);
РезультатыУдаления.МестаИспользования = ОбъединениеТаблиц(РезультатыУдаления.МестаИспользования, РезультатОбработки.МестаИспользования);
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(РезультатыУдаления.УдаленныеОбъекты, РезультатОбработки.УдаленныеОбъекты);
КонецПроцедуры
Функция ИсточникаПодмножествоПриемника(Приемник, Источник, КолонкаПриемника, КолонкаИсточника)
Результат = Истина;
ВерсииДанных = СтандартныеПодсистемыСервер.ЗначенияРеквизитовОбъектовЕслиСуществуют(
Источник.ВыгрузитьКолонку("МестоИспользования"), "ВерсияДанных");
Для Каждого СведенияОМестеИспользования Из Источник Цикл
Если НЕ ОбъектУдален(СведенияОМестеИспользования.МестоИспользования, ВерсииДанных)
И Приемник.Найти(СведенияОМестеИспользования[КолонкаИсточника], КолонкаПриемника) = Неопределено Тогда
Результат = Ложь;
Прервать;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция РазрешеноУдалениеЭлемента(ДополнительныеСведения)
Результат = Истина;
Для Каждого Элемент Из ДополнительныеСведения Цикл
Если НЕ Элемент.ПометкаУдаления И НЕ Элемент.ТипЭлемента = "Подчиненный" Тогда
Результат = Ложь;
Прервать;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ОбъектУдален(УдаляемыйСсылка, ВерсииДанных = Неопределено)
Возврат ЗначениеЗаполнено(УдаляемыйСсылка)
И ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(УдаляемыйСсылка, "ВерсияДанных")
И ?(ВерсииДанных <> Неопределено, Не ЗначениеЗаполнено(ВерсииДанных[УдаляемыйСсылка])
Или Не ЗначениеЗаполнено(ВерсииДанных[УдаляемыйСсылка].ВерсияДанных),
Не ЗначениеЗаполнено(ОбщегоНазначения.ЗначениеРеквизитаОбъекта(УдаляемыйСсылка, "ВерсияДанных")));
КонецФункции
Процедура ОтразитьРезультатУдаленияЭлементаПакета(ПараметрыУдаления, РезультатОбработкиПакета, РезультатУдаления)
Если НЕ РезультатУдаления.ЭтоОсновнойОбъект И РезультатУдаления.Код = КодыРезультатаУдаления().Успешно Тогда
Возврат;
КонецЕсли;
Если РезультатУдаления.Код <> КодыРезультатаУдаления().Успешно Тогда
НеудаленныйЭлемент = РезультатОбработкиПакета.НеудаленныеОбъекты.Добавить();
ЗаполнитьЗначенияСвойств(НеудаленныйЭлемент, РезультатУдаления);
НеудаленныйЭлемент.РезультатУдаления = РезультатУдаления.Код;
НеудаленныйЭлемент.ИнформацияОбОшибке = РезультатУдаления.ИнформацияОбОшибке;
НеудаленныйЭлемент.Сообщения = СообщенияПользователяВСтроку(РезультатУдаления.Сообщения);
РезультатОбработкиПакета.МестаИспользования = ОбъединениеТаблиц(
РезультатОбработкиПакета.МестаИспользования,
РезультатУдаления.МестаИспользования);
Иначе
РезультатОбработкиПакета.УдаленныеОбъекты.Добавить(РезультатУдаления.УдаляемыйСсылка);
РезультатОбработкиПакета.МестаОчисткиСсылок = ОбъединениеТаблиц(
РезультатОбработкиПакета.МестаОчисткиСсылок,
РезультатУдаления.МестаИспользования);
КонецЕсли;
Если РезультатУдаления.ЭтоОсновнойОбъект Тогда
ПараметрыУдаления.КоличествоОбработанных = ПараметрыУдаления.КоличествоОбработанных + 1;
КонецЕсли;
ОповеститьОПрогрессе(ПараметрыУдаления);
КонецПроцедуры
Функция СообщенияПользователяВСтроку(Сообщения)
Результат = "";
Для Каждого Элемент Из Сообщения Цикл
Результат = Символы.ПС + Результат + Элемент.Текст;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ОбработатьПакетВОднойТранзакции(ПараметрыУдаления, Пакет)
Результат = РезультатОбработки();
Контекст = Новый Структура;
УдаляемыеОбъекты = Пакет.ВыгрузитьКолонку("УдаляемыйСсылка");
ПередУдалениемГруппыОбъектов(Контекст, УдаляемыеОбъекты);
ПредставлениеЭлемента = "";
НачатьТранзакцию();
Попытка
Для Каждого ЭлементПакета Из Пакет Цикл
УдаляемыйЭлемент = ЭлементПакета.УдаляемыйСсылка;
ПредставлениеЭлемента = ОбщегоНазначения.ПредметСтрокой(УдаляемыйЭлемент);
Блокировка = Новый БлокировкаДанных();
Элемент = Блокировка.Добавить(УдаляемыйЭлемент.Метаданные().ПолноеИмя());
Элемент.УстановитьЗначение("Ссылка", УдаляемыйЭлемент);
Блокировка.Заблокировать();
Объект = УдаляемыйЭлемент.ПолучитьОбъект();
Если Объект <> Неопределено Тогда
УдалитьОбъект(Объект);
Результат.УдаленныеОбъекты.Добавить(УдаляемыйЭлемент);
КонецЕсли;
КонецЦикла;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Результат.НеудаленныеОбъекты = Пакет.Скопировать();
ЗаписатьПредупреждение(НСтр("ru = 'Не удалось удалить ""%1"" по причине:'"),
ПредставлениеЭлемента, ИнформацияОбОшибке());
КонецПопытки;
ПослеУдаленияГруппыОбъектов(Контекст, Истина);
Возврат Результат;
КонецФункции
Функция УдалитьЭлементПакета(ПараметрыУдаления, Элемент, МестаИспользования, НеудаленныеЭлементы)
Результат = РезультатУдаленияЭлемента(Элемент);
Если ОбъектУдален(Элемент.УдаляемыйСсылка) Тогда
Возврат Результат;
КонецЕсли;
Если Элемент.ДочерниеПодчиненныеОбъекты.Количество() > 0 Тогда
ВерсииДанных = СтандартныеПодсистемыСервер.ЗначенияРеквизитовОбъектовЕслиСуществуют(
Элемент.ДочерниеПодчиненныеОбъекты.ВыгрузитьКолонку("Элемент"), "ВерсияДанных");
КонецЕсли;
Для Каждого ДочернийПодчиненныйЭлемент Из Элемент.ДочерниеПодчиненныеОбъекты Цикл
Если НЕ ОбъектУдален(ДочернийПодчиненныйЭлемент.Элемент, ВерсииДанных)
ИЛИ НеудаленныеЭлементы.Найти(ДочернийПодчиненныйЭлемент.Элемент) <> Неопределено Тогда
Результат.Код = КодыРезультатаУдаления().ЕстьМестаИспользования;
Результат.МестаИспользования = ОставшиесяМестаИспользованияУдаляемогоОбъекта(
ПараметрыУдаления, МестаИспользования, ДочернийПодчиненныйЭлемент.Элемент);
Возврат Результат;
КонецЕсли;
КонецЦикла;
МестаОчисткиСсылок = МестаОчисткиСсылок(ПараметрыУдаления, МестаИспользования);
ПредставлениеЭлемента = ОбщегоНазначения.ПредметСтрокой(Элемент.УдаляемыйСсылка);
Попытка
Блокировка = Новый БлокировкаДанных();
ЭлементБлокировки = Блокировка.Добавить(Элемент.УдаляемыйСсылка.Метаданные().ПолноеИмя());
ЭлементБлокировки.УстановитьЗначение("Ссылка", Элемент.УдаляемыйСсылка);
Блокировка.Заблокировать();
Объект = Элемент.УдаляемыйСсылка.ПолучитьОбъект();
УдалитьОбъект(Объект);
Исключение
ИнформацияОбОшибке = ИнформацияОбОшибке();
ЗаписатьПредупреждение(НСтр("ru = 'Не удалось удалить ""%1"" по причине:'"), ПредставлениеЭлемента, ИнформацияОбОшибке);
Результат.Сообщения = ДлительныеОперации.СообщенияПользователю(Истина);
Результат.ИнформацияОбОшибке = ИнформацияОбОшибке;
Результат.Код = КодыРезультатаУдаления().ОшибкаПриУдалении;
Возврат Результат;
КонецПопытки;
ОставшиесяМестаИспользования = ОставшиесяМестаИспользованияУдаляемогоОбъекта(ПараметрыУдаления, МестаИспользования);
Если ОставшиесяМестаИспользования.Количество() = 0
Или МестаОчисткиСсылок.Количество() = ОставшиесяМестаИспользования.Количество() Тогда
Результат.МестаИспользования = МестаОчисткиСсылок;
Иначе
Результат.МестаИспользования = ОставшиесяМестаИспользования;
Результат.Код = КодыРезультатаУдаления().ЕстьМестаИспользования;
КонецЕсли;
Возврат Результат;
КонецФункции
Процедура УдалитьОбъект(Объект)
Объект.ДополнительныеСвойства.Вставить("НеВыполнятьКонтрольУдаляемых");
Объект.Удалить();
КонецПроцедуры
Функция ЗаписьСуществует(СведенияОМестеИспользования)
МенеджерРегистра = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(СведенияОМестеИспользования.Метаданные.ПолноеИмя());
Набор = МенеджерРегистра.СоздатьНаборЗаписей();
Для Индекс = 0 По Набор.Отбор.Количество() - 1 Цикл
ЭлементОтбора = Набор.Отбор[Индекс];
ЭлементОтбора.Установить(СведенияОМестеИспользования.МестоИспользования[ЭлементОтбора.Имя]);
КонецЦикла;
Набор.Прочитать();
Возврат Набор.Количество() > 0;
КонецФункции
Функция СсылкаВВедущемИзмерении(СведенияОМестеИспользования)
ИменаИзмерений = УдалениеПомеченныхОбъектовПовтИсп.ВедущиеИзмеренияРегистра(СведенияОМестеИспользования.Метаданные.ПолноеИмя());
Измерения = Новый Структура(ИменаИзмерений);
ЗаполнитьЗначенияСвойств(Измерения, СведенияОМестеИспользования.МестоИспользования);
Для каждого Измерение Из Измерения Цикл
Если Измерение.Значение = СведенияОМестеИспользования.УдаляемыйСсылка Тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
Возврат Ложь;
КонецФункции
Функция МестаИспользованияЭлементовПакета(ПараметрыУдаления, Пакет)
Результат = МестаИспользования();
УстановитьПривилегированныйРежим(Истина);
ПараметрыПоискаМестИспользования = ОбщегоНазначения.ПараметрыПоискаМестИспользования();
ПараметрыПоискаМестИспользования.ОтменаИсключенийПоискаСсылок = ОтменаИсключенийПоискаСсылокПриУдаленииОбъектов();
МестаИспользования = ОбщегоНазначения.МестаИспользования(Пакет.ВыгрузитьКолонку("УдаляемыйСсылка"),,ПараметрыПоискаМестИспользования);
МестаИспользования.Колонки[0].Имя = "УдаляемыйСсылка";
МестаИспользования.Колонки[1].Имя = "МестоИспользования";
МестаИспользования.Колонки[2].Имя = "Метаданные";
ОбщегоНазначенияКлиентСервер.ДополнитьТаблицу(МестаИспользования, Результат);
Возврат Результат;
КонецФункции
Процедура ДополнитьПакетДочернимиИПодчиненнымиЭлементами(Пакет, ОсновнойЭлемент, ДочерниеПодчиненныеЭлементы, Исключения)
Для Каждого ОписаниеЭлемента Из ДочерниеПодчиненныеЭлементы Цикл
Если Пакет.Найти(ОписаниеЭлемента.Элемент, "УдаляемыйСсылка") <> Неопределено
ИЛИ Исключения.Найти(ОписаниеЭлемента.Элемент, "УдаляемыйСсылка") <> Неопределено Тогда
Продолжить;
КонецЕсли;
ЭлементПакета = Пакет.Добавить();
ЭлементПакета.ОсновнойЭлементСсылка = ОсновнойЭлемент;
ЭлементПакета.УдаляемыйСсылка = ОписаниеЭлемента.Элемент;
ЭлементПакета.ДочерниеПодчиненныеОбъекты = ОписаниеЭлемента.ДочерниеЭлементы;
КонецЦикла;
КонецПроцедуры
Процедура ОповеститьОПрогрессе(ПараметрыВыполнения)
ТекущееВремя = ТекущаяУниверсальнаяДатаВМиллисекундах();
Если ПараметрыВыполнения.ЭтоРегламентноеЗадание
ИЛИ ТекущееВремя - ПараметрыВыполнения.ВремяОповещения <= ПараметрыВыполнения.ПериодОповещения Тогда
Возврат;
КонецЕсли;
ПараметрыВыполнения.Всего = ПараметрыВыполнения.КоличествоУдаляемых;
ОтметитьПрогрессОбходаКоллекции(ПараметрыВыполнения, "ПользовательскиеОбъекты");
ПараметрыВыполнения.ВремяОповещения = ТекущееВремя;
КонецПроцедуры
#КонецОбласти
#Область ФильтрыКоллекций
Функция ЦиклическиеСсылки(Пакет, МестаИспользования)
Результат = СсылкиТолькоНаЭлементыВнутриПакета(Пакет, МестаИспользования);
КоличествоВПакете = Пакет.Количество();
Пока (Результат[0].Количество() <> КоличествоВПакете) Цикл
КоличествоВПакете = Результат[0].Количество();
Результат = СсылкиТолькоНаЭлементыВнутриПакета(Результат[0], Результат[1]);
КонецЦикла;
Возврат Результат[0];
КонецФункции
Функция ОставшиесяМестаИспользованияУдаляемогоОбъекта(ПараметрыУдаления, МестаИспользования, СсылкаИсключение = Неопределено)
Результат = МестаИспользования.СкопироватьКолонки();
ВерсииДанных = СтандартныеПодсистемыСервер.ЗначенияРеквизитовОбъектовЕслиСуществуют(
МестаИспользования.ВыгрузитьКолонку("МестоИспользования"), "ВерсияДанных");
Для Каждого СведенияОМестеИспользования Из МестаИспользования Цикл
ЭтоСсылка = СведенияОМестеИспользования.МестоИспользования <> Неопределено
И ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(СведенияОМестеИспользования.МестоИспользования, "ВерсияДанных");
ЭтоКонстанта = Метаданные.Константы.Содержит(СведенияОМестеИспользования.Метаданные);
Если ЭтоСсылка
И (НЕ ОбъектУдален(СведенияОМестеИспользования.МестоИспользования, ВерсииДанных)
ИЛИ СведенияОМестеИспользования.МестоИспользования = СсылкаИсключение)
И НЕ СведенияОМестеИспользования.ЭтоСлужебныеДанные Тогда
ЗаполнитьЗначенияСвойств(Результат.Добавить(), СведенияОМестеИспользования);
КонецЕсли;
Если ОбщегоНазначения.ЭтоПоследовательность(СведенияОМестеИспользования.Метаданные) Тогда
Продолжить;
КонецЕсли;
Если НЕ ЭтоСсылка И НЕ ЭтоКонстанта И НЕ СведенияОМестеИспользования.ЭтоСлужебныеДанные
И ЗаписьСуществует(СведенияОМестеИспользования)
И НЕ СсылкаВВедущемИзмерении(СведенияОМестеИспользования) Тогда
ЗаполнитьЗначенияСвойств(Результат.Добавить(), СведенияОМестеИспользования);
КонецЕсли;
Если НЕ ЭтоСсылка И ЭтоКонстанта
И СведенияОМестеИспользования.МестоИспользования = Неопределено Тогда
ЗаполнитьЗначенияСвойств(Результат.Добавить(), СведенияОМестеИспользования);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция МестаОчисткиСсылок(ПараметрыУдаления, МестаИспользования)
Результат = МестаИспользования();
Если Не ПараметрыУдаления.ОчищатьСсылкиВМестахИспользования Тогда
Возврат Результат;
КонецЕсли;
ВерсииДанных = СтандартныеПодсистемыСервер.ЗначенияРеквизитовОбъектовЕслиСуществуют(
МестаИспользования.ВыгрузитьКолонку("МестоИспользования"), "ВерсияДанных");
МестаИспользования.Сортировать("Метаданные");
Для Каждого СведенияОМестеИспользования Из МестаИспользования Цикл
ТипМестаИспользования = ТипЗнч(СведенияОМестеИспользования.МестоИспользования);
ЭтоСсылка = ОбщегоНазначения.ЭтоСсылка(ТипМестаИспользования);
Если ЭтоСсылка
И НЕ ОбъектУдален(СведенияОМестеИспользования.МестоИспользования, ВерсииДанных)
И ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СведенияОМестеИспользования.МестоИспользования, "ПометкаУдаления")
И Не СведенияОМестеИспользования.ЭтоСлужебныеДанные Тогда
ЗаполнитьЗначенияСвойств(Результат.Добавить(), СведенияОМестеИспользования);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция СсылкиТолькоНаЭлементыВнутриПакета(Пакет, МестаИспользования)
Результат = Новый Массив;
НовыйПакет = ПакетУдаляемыхОбъектов();
МестаИспользованияКандидатов = МестаИспользования();
Для Каждого Элемент Из Пакет Цикл
Если Элемент.РезультатУдаления <> КодыРезультатаУдаления().ЕстьМестаИспользования
И Элемент.РезультатУдаления <> КодыРезультатаУдаления().ЕстьДочерниеПодчиненныеЭлементы Тогда
Продолжить;
КонецЕсли;
МестаИспользованияЭлемента = МестаИспользования.Скопировать(Новый Структура("УдаляемыйСсылка", Элемент.УдаляемыйСсылка), "МестоИспользования");
Если ИсточникаПодмножествоПриемника(Пакет, МестаИспользованияЭлемента, "УдаляемыйСсылка", "МестоИспользования") ИЛИ МестаИспользования.Количество() = 0 Тогда
ЗаполнитьЗначенияСвойств(НовыйПакет.Добавить(), Элемент);
Для Каждого Элемент Из МестаИспользованияЭлемента Цикл
ЗаполнитьЗначенияСвойств(МестаИспользованияКандидатов.Добавить(), Элемент);
КонецЦикла;
КонецЕсли;
КонецЦикла;
Результат.Добавить(НовыйПакет);
Результат.Добавить(МестаИспользования);
Возврат Результат;
КонецФункции
#КонецОбласти
#Область ОбработчикиСобытийКонкурентногоОбновления
Процедура ПослеОбработкиПакета(ПараметрыУдаления, Идентификатор)
УдалениеПомеченныхОбъектовСлужебный.СнятьБлокировкуИспользованияУдаляемыхОбъектов(Идентификатор);
ПараметрыСеанса.ВыполняетсяУдалениеОбъектов = Ложь;
КонецПроцедуры
Процедура ПередОбработкойПакета(Пакет, Идентификатор)
ПараметрыСеанса.ВыполняетсяУдалениеОбъектов = Истина;
УдалениеПомеченныхОбъектовСлужебный.УстановитьБлокировкуИспользованияУдаляемыхОбъектов(Пакет, Идентификатор);
КонецПроцедуры
#КонецОбласти
#Область Конструкторы
Функция ПараметрыУдаления() Экспорт
Результат = Новый Структура;
Результат.Вставить("ПользовательскиеОбъекты", Новый Массив);
Результат.Вставить("Монопольно", Ложь);
Результат.Вставить("ОчищатьСсылкиВМестахИспользования", Ложь);
Результат.Вставить("Режим", "");
Результат.Вставить("ЭтоРегламентноеЗадание", Ложь);
Результат.Вставить("РазмерПакета", 100);
Возврат Результат;
КонецФункции
Функция РезультатУдаления(УдаляемыеОбъекты, ПараметрыУдаления)
ИсключенияПоискаСсылок = ИсключенияПоискаСсылокПриУдалении();
ПараметрыОбработки = Новый Структура;
ПараметрыОбработки.Вставить("Монопольно", ПараметрыУдаления.Монопольно);
ПараметрыОбработки.Вставить("ИсключающиеПравила", Новый Соответствие);
ПараметрыОбработки.Вставить("ИсключенияПоискаСсылок", ИсключенияПоискаСсылок);
ПараметрыОбработки.Вставить("РазмерПакета", ПараметрыУдаления.РазмерПакета);
ПараметрыОбработки.Вставить("КешИнформацииОТипах", Новый Соответствие);
ПараметрыОбработки.Вставить("ОчищатьСсылкиВМестахИспользования", ПараметрыУдаления.ОчищатьСсылкиВМестахИспользования);
ПараметрыОбработки.Вставить("ПользовательскиеОбъекты", Новый Массив);
ПрепятствующиеУдалению = Новый ТаблицаЗначений;
ПрепятствующиеУдалению.Колонки.Добавить("УдаляемыйСсылка");
ПрепятствующиеУдалению.Колонки.Добавить("МестоИспользования");
ПрепятствующиеУдалению.Колонки.Добавить("ОбнаруженныйСтатус", Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(10)));
ПрепятствующиеУдалению.Колонки.Добавить("ОписаниеОшибки", Новый ОписаниеТипов("Строка"));
ПрепятствующиеУдалению.Колонки.Добавить("ПодробноеОписаниеОшибки", Новый ОписаниеТипов("Строка"));
ТипыКолонкиМетаданные = Новый Массив;
ТипыКолонкиМетаданные.Добавить("ОбъектМетаданных");
ТипыКолонкиМетаданные.Добавить("Неопределено");
ПрепятствующиеУдалению.Колонки.Добавить("Метаданные", Новый ОписаниеТипов(ТипыКолонкиМетаданные));
ПрепятствующиеУдалению.Индексы.Добавить("УдаляемыйСсылка");
ПрепятствующиеУдалению.Индексы.Добавить("МестоИспользования");
ПараметрыОбработки.Вставить("Удаленные", Новый Массив);
ПараметрыОбработки.Вставить("НеУдаленные", Новый Массив);
ПараметрыОбработки.Вставить("ПрепятствующиеУдалению", ПрепятствующиеУдалению);
ПараметрыОбработки.Вставить("ПовторноУдаляемые", Новый Массив);
ПараметрыОбработки.Вставить("КоличествоУдаляемых", УдаляемыеОбъекты.Количество());
ПараметрыОбработки.Вставить("КоличествоНеудаленных", 0);
ПараметрыОбработки.Вставить("КоличествоОбработанных", 0);
ПараметрыОбработки.Вставить("Всего", 0);
ПараметрыОбработки.Вставить("Номер", 0);
ПараметрыОбработки.Вставить("ИдентификаторЗадания", "");
ПараметрыОбработки.Вставить("ВремяОповещения", 0);
ПараметрыОбработки.Вставить("ПериодОповещения", 60000);
ПараметрыОбработки.Вставить("ЭтоРегламентноеЗадание", ПараметрыУдаления.ЭтоРегламентноеЗадание);
Возврат ПараметрыОбработки;
КонецФункции
Функция ИсключенияПоискаСсылокПриУдалении()
ИсключенияПоискаСсылок = ОбщегоНазначения.ИсключенияПоискаСсылок();
Для Каждого Элемент Из УдалениеПомеченныхОбъектовСлужебный.ИсключенияПоискаСсылокРазрешающихУдаление() Цикл
ИсключенияПоискаСсылок.Вставить(Элемент, "*");
КонецЦикла;
ИсключенияПоискаСсылок.Удалить(Метаданные.Справочники.ВнешниеПользователи);
Возврат ИсключенияПоискаСсылок;
КонецФункции
Функция РезультатОбработки()
Результат = Новый Структура();
Результат.Вставить("УдаленныеОбъекты", Новый Массив);
Результат.Вставить("НеудаленныеОбъекты", ПакетУдаляемыхОбъектов());
Результат.Вставить("МестаИспользования", МестаИспользования());
Результат.Вставить("МестаОчисткиСсылок", МестаИспользования());
Возврат Результат;
КонецФункции
Функция МестаИспользования() Экспорт
Таблица = Новый ТаблицаЗначений();
Таблица.Колонки.Добавить("УдаляемыйСсылка");
Таблица.Колонки.Добавить("МестоИспользования");
Таблица.Колонки.Добавить("Метаданные");
Таблица.Колонки.Добавить("ЭтоСлужебныеДанные", Новый ОписаниеТипов("Булево"));
Таблица.Индексы.Добавить("УдаляемыйСсылка");
Таблица.Индексы.Добавить("МестоИспользования");
Возврат Таблица;
КонецФункции
Функция ПакетУдаляемыхОбъектов()
Пакет = Новый ТаблицаЗначений;
Пакет.Колонки.Добавить("УдаляемыйСсылка");
Пакет.Колонки.Добавить("ЕстьДочерниеОбъекты", , Новый ОписаниеТипов("Булево"));
Пакет.Колонки.Добавить("ЕстьПодчиненныеОбъекты", Новый ОписаниеТипов("Булево"));
Пакет.Колонки.Добавить("ИнформацияОбОшибке", Новый ОписаниеТипов("ИнформацияОбОшибке"));
Пакет.Колонки.Добавить("Сообщения", Новый ОписаниеТипов("Строка"));
Пакет.Колонки.Добавить("РезультатУдаления", Новый ОписаниеТипов("Число"));
Пакет.Колонки.Добавить("ДочерниеПодчиненныеОбъекты", Новый ОписаниеТипов("ТаблицаЗначений"));
Пакет.Колонки.Добавить("ЭтоОсновнойОбъект", Новый ОписаниеТипов("Булево"));
Пакет.Колонки.Добавить("ОсновнойЭлементСсылка");
Пакет.Индексы.Добавить("УдаляемыйСсылка");
Возврат Пакет;
КонецФункции
Функция КодыРезультатаУдаления()
ТипыОшибок = Новый Структура;
ТипыОшибок.Вставить("Успешно", -1);
ТипыОшибок.Вставить("ЕстьМестаИспользования", 0);
ТипыОшибок.Вставить("ОшибкаПриУдалении", 1);
ТипыОшибок.Вставить("ЕстьДочерниеПодчиненныеЭлементы", 2);
ТипыОшибок.Вставить("ЕстьДочерниеПодчиненныеЭлементыНепомеченныеНаУдаление", 3);
ТипыОшибок.Вставить("НеПомеченНаУдаление", 4);
Возврат ТипыОшибок;
КонецФункции
Функция УдаляемыеОбъекты(МассивУдаляемыхОбъектов, СведенияОМетаданных)
УдаляемыеОбъекты = Новый ТаблицаЗначений;
УдаляемыеОбъекты.Колонки.Добавить("УдаляемыйСсылка");
УдаляемыеОбъекты.Колонки.Добавить("Приоритет", Новый ОписаниеТипов("Число"));
УдаляемыеОбъекты.Колонки.Добавить("КоличествоПопыток", Новый ОписаниеТипов("Число"));
УдаляемыеОбъекты.Колонки.Добавить("Тип", Новый ОписаниеТипов("Тип"));
УдаляемыеОбъекты.Индексы.Добавить("УдаляемыйСсылка");
КоличествоПопытокОбъектов = РегистрыСведений.НеудаленныеОбъекты.КоличествоПопытокОбъектов(МассивУдаляемыхОбъектов);
Для Каждого Элемент Из МассивУдаляемыхОбъектов Цикл
ТипЭлемента = ТипЗнч(Элемент);
ЭлементОчереди = УдаляемыеОбъекты.Добавить();
ЭлементОчереди.УдаляемыйСсылка = Элемент;
ЭлементОчереди.Приоритет = СведенияОМетаданных.НайтиСтроки(Новый Структура("Тип", ТипЭлемента))[0].Приоритет;
ЭлементОчереди.Тип = ТипЭлемента;
КоличествоПопыток = КоличествоПопытокОбъектов.Найти(Элемент, "УдаляемыйСсылка");
ЭлементОчереди.КоличествоПопыток = ?(КоличествоПопыток = Неопределено, 0, КоличествоПопыток.КоличествоПопыток);
КонецЦикла;
УдаляемыеОбъекты.Сортировать("КоличествоПопыток, Приоритет");
Возврат УдаляемыеОбъекты;
КонецФункции
#КонецОбласти
#Область ФормированиеСведенийОМетаданных
Функция СведенияОМетаданных(ПараметрыУдаления, УдаляемыеОбъекты)
Результат = Новый ТаблицаЗначений();
Результат.Колонки.Добавить("Метаданные", Новый ОписаниеТипов("ОбъектМетаданных"));
Результат.Колонки.Добавить("Иерархический", Новый ОписаниеТипов("Булево"));
Результат.Колонки.Добавить("Приоритет", Новый ОписаниеТипов("Число"));
Результат.Колонки.Добавить("ЕстьПодчиненныеОбъекты", Новый ОписаниеТипов("Булево"));
Результат.Колонки.Добавить("Тип", Новый ОписаниеТипов("Тип"));
Результат.Колонки.Добавить("ОписаниеПодчиненныхОбъектов", Новый ОписаниеТипов("ТаблицаЗначений"));
Результат.Индексы.Добавить("Тип");
Результат.Индексы.Добавить("Метаданные");
ЗаполнитьСведенияОМетаданных(Результат, УдаляемыеОбъекты);
Возврат Результат;
КонецФункции
Функция ТаблицаПоискаПодчиненныхОбъектов()
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Тип", Новый ОписаниеТипов("Тип"));
Таблица.Колонки.Добавить("Метаданные", Новый ОписаниеТипов("ОбъектМетаданных"));
Таблица.Колонки.Добавить("ИмяРеквизита", Новый ОписаниеТипов("Строка"));
Возврат Таблица;
КонецФункции
Процедура ЗаполнитьСведенияОМетаданных(СведенияОМетаданных, УдаляемыеОбъекты)
ПодчиненныеОбъекты = ОбщегоНазначения.ПодчиненныеОбъекты();
Для Каждого Элемент Из УдаляемыеОбъекты Цикл
Если СведенияОМетаданных.Найти(Элемент.Метаданные(), "Метаданные") = Неопределено Тогда
ИнформацияОМетаданных = СведенияОМетаданных.Добавить();
ИнформацияОМетаданных.Метаданные = Элемент.Метаданные();
ИнформацияОМетаданных.Приоритет = 0;
ИнформацияОМетаданных.Тип = ТипЗнч(Элемент);
ИнформацияОМетаданных.ОписаниеПодчиненныхОбъектов = ТаблицаПоискаПодчиненныхОбъектов();
ИнформацияОМетаданных.Иерархический = ЭтоИерархическийОбъектМетаданных(ИнформацияОМетаданных.Метаданные);
КонецЕсли;
КонецЦикла;
Для Каждого ОбъектМетаданных Из Метаданные.Справочники Цикл
ОписаниеПодчиненногоОбъекта = ПодчиненныеОбъекты.Найти(ОбъектМетаданных, "ПодчиненныйОбъект");
Если ОписаниеПодчиненногоОбъекта = Неопределено
И ОбъектМетаданных.Владельцы.Количество() > 0 Тогда
ОписаниеПодчиненногоОбъекта = ПодчиненныеОбъекты.Добавить();
ОписаниеПодчиненногоОбъекта.ПодчиненныйОбъект = ОбъектМетаданных;
ОписаниеПодчиненногоОбъекта.ПоляСвязей = "Владелец";
ИначеЕсли ОбъектМетаданных.Владельцы.Количество() > 0 Тогда
ОписаниеПодчиненногоОбъекта.ПоляСвязей = ?(СтрНайти(ОписаниеПодчиненногоОбъекта.ПоляСвязей, "Владелец") > 0,
ОписаниеПодчиненногоОбъекта.ПоляСвязей,
ОписаниеПодчиненногоОбъекта.ПоляСвязей + ",Владелец");
КонецЕсли;
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.СтандартныеРеквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.Реквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ОбъектМетаданных.ТабличныеЧасти);
КонецЦикла;
Для Каждого ОбъектМетаданных Из Метаданные.Документы Цикл
ОписаниеПодчиненногоОбъекта = ПодчиненныеОбъекты.Найти(ОбъектМетаданных, "ПодчиненныйОбъект");
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.СтандартныеРеквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.Реквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ОбъектМетаданных.ТабличныеЧасти);
КонецЦикла;
Для Каждого ОбъектМетаданных Из Метаданные.ПланыВидовХарактеристик Цикл
ОписаниеПодчиненногоОбъекта = ПодчиненныеОбъекты.Найти(ОбъектМетаданных, "ПодчиненныйОбъект");
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.СтандартныеРеквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.Реквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ОбъектМетаданных.ТабличныеЧасти);
КонецЦикла;
Для Каждого ОбъектМетаданных Из Метаданные.ПланыВидовРасчета Цикл
ОписаниеПодчиненногоОбъекта = ПодчиненныеОбъекты.Найти(ОбъектМетаданных, "ПодчиненныйОбъект");
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.СтандартныеРеквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.Реквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ОбъектМетаданных.СтандартныеТабличныеЧасти);
ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ОбъектМетаданных.ТабличныеЧасти);
КонецЦикла;
Для Каждого ОбъектМетаданных Из Метаданные.ПланыСчетов Цикл
ОписаниеПодчиненногоОбъекта = ПодчиненныеОбъекты.Найти(ОбъектМетаданных, "ПодчиненныйОбъект");
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.СтандартныеРеквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.Реквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ОбъектМетаданных.СтандартныеТабличныеЧасти);
ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ОбъектМетаданных.ТабличныеЧасти);
КонецЦикла;
Для Каждого ОбъектМетаданных Из Метаданные.БизнесПроцессы Цикл
ОписаниеПодчиненногоОбъекта = ПодчиненныеОбъекты.Найти(ОбъектМетаданных, "ПодчиненныйОбъект");
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.СтандартныеРеквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.Реквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ОбъектМетаданных.ТабличныеЧасти);
КонецЦикла;
Для Каждого ОбъектМетаданных Из Метаданные.Задачи Цикл
ОписаниеПодчиненногоОбъекта = ПодчиненныеОбъекты.Найти(ОбъектМетаданных, "ПодчиненныйОбъект");
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.СтандартныеРеквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.РеквизитыАдресации, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.Реквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ОбъектМетаданных.ТабличныеЧасти);
КонецЦикла;
КонецПроцедуры
Процедура ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ТабличныеЧасти)
Для Каждого ТабличнаяЧасть Из ТабличныеЧасти Цикл
Если ТипЗнч(ТабличнаяЧасть) = Тип("ОбъектМетаданных") Тогда
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ТабличнаяЧасть.Реквизиты);
Иначе
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ТабличнаяЧасть.СтандартныеРеквизиты);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ЗарегистрироватьРеквизиты(СведенияОМетаданных, КоллекцияРеквизитов, ОписаниеПодчиненногоОбъекта = Неопределено)
Для Каждого Реквизит Из КоллекцияРеквизитов Цикл
ЗарегистрироватьРеквизит(СведенияОМетаданных, Реквизит, ОписаниеПодчиненногоОбъекта);
КонецЦикла;
КонецПроцедуры
Процедура ЗарегистрироватьРеквизит(СведенияОМетаданных, Реквизит,
ОписаниеПодчиненногоОбъекта)
ИменаПолейСвязи = ?(ЗначениеЗаполнено(ОписаниеПодчиненногоОбъекта), СтрРазделить(ОписаниеПодчиненногоОбъекта.ПоляСвязей, ","), Новый Массив);
ЭтоПолеСвязиПодчиненногоОбъекта = ИменаПолейСвязи.Найти(Реквизит.Имя) <> Неопределено;
Для Каждого Тип Из Реквизит.Тип.Типы() Цикл
Если УдалениеПомеченныхОбъектовСлужебный.ЭтоПростойТип(Тип) Тогда
Продолжить;
КонецЕсли;
НайденныеСведения = СведенияОМетаданных.Найти(Тип, "Тип");
Если НайденныеСведения <> Неопределено Тогда
НайденныеСведения.Приоритет = НайденныеСведения.Приоритет + 1;
Если ЭтоПолеСвязиПодчиненногоОбъекта Тогда
Связь = НайденныеСведения.ОписаниеПодчиненныхОбъектов.Добавить();
Связь.Тип = Тип;
Связь.Метаданные = ОписаниеПодчиненногоОбъекта.ПодчиненныйОбъект;
Связь.ИмяРеквизита = Реквизит.Имя;
НайденныеСведения.ЕстьПодчиненныеОбъекты = Истина;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ЭтоИерархическийОбъектМетаданных(ОбъектМетаданных)
Если ОбщегоНазначения.ЭтоПланСчетов(ОбъектМетаданных) Тогда
Возврат Истина;
Иначе
ЗначениеРеквизита = Новый Структура("Иерархический");
ЗаполнитьЗначенияСвойств(ЗначениеРеквизита, ОбъектМетаданных);
Возврат ЗначениеРеквизита.Иерархический;
КонецЕсли;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область МонопольноеУдаление
Процедура УдалитьПомеченныеОбъектыМонопольно(УдаляемыеОбъекты, ПараметрыВыполнения)
ПараметрыВыполнения.ИсключенияПоискаСсылок = ОбщегоНазначения.ИсключенияПоискаСсылок();
Для каждого ОтменаИсключения Из ОтменаИсключенийПоискаСсылокПриУдаленииОбъектов() Цикл
ПараметрыВыполнения.ИсключенияПоискаСсылок.Удалить(ОтменаИсключения);
КонецЦикла;
Если Не ПараметрыВыполнения.Свойство("ИсключающиеПравила") Тогда
ПараметрыВыполнения.Вставить("ИсключающиеПравила", Новый Соответствие);
КонецЕсли;
СведенияОМетаданных = СведенияОМетаданных(ПараметрыВыполнения, УдаляемыеОбъекты);
ИнформацияОТипах = УдалениеПомеченныхОбъектовСлужебный.ИнформацияОТипах(УдаляемыеОбъекты);
ПодчиненныеОбъекты = Новый Массив;
СведенияОбУдаляемыхОбъектах = СтандартныеПодсистемыСервер.ЗначенияРеквизитовОбъектовЕслиСуществуют(УдаляемыеОбъекты,
"ПометкаУдаления,ВерсияДанных");
Для Индекс = -(УдаляемыеОбъекты.Количество() - 1) По 0 Цикл
УдаляемыйОбъект = УдаляемыеОбъекты[-Индекс];
СведенияОбУдаляемомОбъекте = Новый Соответствие;
СведенияОбУдаляемомОбъекте[УдаляемыйОбъект] = Новый Структура("ВерсияДанных");
СведенияОбУдаляемомОбъекте[УдаляемыйОбъект].ВерсияДанных =
?(ЗначениеЗаполнено(СведенияОбУдаляемыхОбъектах[УдаляемыйОбъект]),
СведенияОбУдаляемыхОбъектах[УдаляемыйОбъект].ВерсияДанных, Неопределено);
Если НЕ ОбъектУдален(УдаляемыйОбъект, СведенияОбУдаляемомОбъекте)
И НЕ СведенияОбУдаляемыхОбъектах[УдаляемыйОбъект].ПометкаУдаления Тогда
ПричинаНеудаления = Новый Структура;
ПричинаНеудаления.Вставить("УдаляемыйСсылка", УдаляемыйОбъект);
ПричинаНеудаления.Вставить("МестоИспользования", НСтр("ru='Удаляемый объект не помечен на удаление.'"));
ПричинаНеудаления.Вставить("ОбнаруженныйМетаданные");
ЗаписатьПричинуВРезультат(ПараметрыВыполнения, ПричинаНеудаления, ИнформацияОТипах);
УдаляемыеОбъекты.Удалить(-Индекс);
Продолжить;
КонецЕсли;
ИнформацияОМетаданных = СведенияОМетаданных.Найти(ТипЗнч(УдаляемыйОбъект), "Тип");
ИнформацияОМетаданных.Иерархический = Ложь;
ДочерниеПодчиненныеОбъекты = ДочерниеПодчиненныеЭлементы(УдаляемыйОбъект, ИнформацияОМетаданных);
Для Каждого ПодчиненныйОбъект Из ДочерниеПодчиненныеОбъекты Цикл
Если ПодчиненныйОбъект.ПометкаУдаления ИЛИ ПодчиненныйОбъект.ТипЭлемента = "Подчиненный" Тогда
ПодчиненныеОбъекты.Добавить(ПодчиненныйОбъект.Элемент);
КонецЕсли;
КонецЦикла;
КонецЦикла;
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(УдаляемыеОбъекты, ПодчиненныеОбъекты);
Контекст = Новый Структура;
ПередУдалениемГруппыОбъектов(Контекст, УдаляемыеОбъекты);
ИнформацияОТипах = Новый Соответствие;
Пока УдаляемыеОбъекты.Количество() > 0 Цикл
ПрепятствующиеУдалению = Новый ТаблицаЗначений;
УстановитьПривилегированныйРежим(Истина);
Попытка
УдалитьОбъекты(УдаляемыеОбъекты, Истина, ПрепятствующиеУдалению);
Исключение
ИнформацияОбОшибке = ИнформацияОбОшибке();
ЗаписатьПредупреждение(НСтр("ru = 'Не удалось удалить элементы по причине:'"), Неопределено, ИнформацияОбОшибке);
ОписаниеОшибки = ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке);
Сообщения = ДлительныеОперации.СообщенияПользователю(Истина);
Для каждого Сообщение Из Сообщения Цикл
ОписаниеОшибки = ОписаниеОшибки + Символы.ПС + Символы.ПС + Сообщение.Текст;
КонецЦикла;
ПослеУдаленияГруппыОбъектов(Контекст, Ложь);
ВызватьИсключение ОписаниеОшибки;
КонецПопытки;
УстановитьПривилегированныйРежим(Ложь);
Если ПрепятствующиеУдалению.Колонки.Количество() < 3 Тогда
ВызватьИсключение НСтр("ru = 'Не удалось выполнить удаление объектов.'");
КонецЕсли;
СлужебныеСвязиДанных = ОбщегоНазначения.СлужебныеСвязиДанных(ПрепятствующиеУдалению, ПараметрыВыполнения.ИсключенияПоискаСсылок);
ПрепятствующиеУдалению.Колонки[0].Имя = "УдаляемыйСсылка";
ПрепятствующиеУдалению.Колонки[1].Имя = "МестоИспользования";
ПрепятствующиеУдалению.Колонки[2].Имя = "Метаданные";
ВсеСвязиВИсключениях = Истина;
ПослеУдаленияГруппыОбъектов(Контекст, ПрепятствующиеУдалению.Количество() = 0);
ИнформацияОТипах = УдалениеПомеченныхОбъектовСлужебный.ИнформацияОТипах(
ПрепятствующиеУдалению.ВыгрузитьКолонку("УдаляемыйСсылка"), ИнформацияОТипах);
Для Каждого СтрокаТаблицы Из ПрепятствующиеУдалению Цикл
Если СлужебныеСвязиДанных[СтрокаТаблицы] <> Неопределено
ИЛИ СвязьТолькоСВедущимиИзмерениямиРегистров(СтрокаТаблицы)
ИЛИ ОбщегоНазначения.ЭтоПоследовательность(СтрокаТаблицы.Метаданные) Тогда
Продолжить;
КонецЕсли;
Индекс = УдаляемыеОбъекты.Найти(СтрокаТаблицы.МестоИспользования);
Если Индекс <> Неопределено Тогда
Продолжить;
КонецЕсли;
ВсеСвязиВИсключениях = Ложь;
Индекс = УдаляемыеОбъекты.Найти(СтрокаТаблицы.УдаляемыйСсылка);
Если Индекс <> Неопределено Тогда
УдаляемыеОбъекты.Удалить(Индекс);
КонецЕсли;
ЗаписатьПричинуВРезультат(ПараметрыВыполнения, СтрокаТаблицы, ИнформацияОТипах);
КонецЦикла;
Если ВсеСвязиВИсключениях Тогда
УстановитьПривилегированныйРежим(Истина);
УдалитьОбъекты(УдаляемыеОбъекты, Ложь);
ПослеУдаленияГруппыОбъектов(Контекст, Истина);
УстановитьПривилегированныйРежим(Ложь);
Прервать;
КонецЕсли;
КонецЦикла;
ПараметрыВыполнения.Вставить("Удаленные", УдаляемыеОбъекты);
КонецПроцедуры
Процедура ЗаписатьПредупреждение(Знач Описание, Знач ПредставлениеЭлемента, Знач ИнформацияОбОшибке)
Если ТипЗнч(ИнформацияОбОшибке) = Тип("ИнформацияОбОшибке") Тогда
ТекстДляЖурнала = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке);
Иначе
ТекстДляЖурнала = ИнформацияОбОшибке;
КонецЕсли;
ТекстДляЖурнала = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(Описание, ПредставлениеЭлемента)
+ Символы.ПС + ТекстДляЖурнала;
ЗаписьЖурналаРегистрации(НСтр("ru = 'Удаление помеченных'", ОбщегоНазначения.КодОсновногоЯзыка()),
УровеньЖурналаРегистрации.Предупреждение,,, ТекстДляЖурнала);
КонецПроцедуры
Процедура ЗаписатьПричинуВРезультат(ПараметрыВыполнения, СтрокаТаблицы, ИнформацияОТипах)
ТипОбъекта = ТипЗнч(СтрокаТаблицы.УдаляемыйСсылка);
ИнформацияОТипе = ИнформацияОТипах[ТипОбъекта];
Если ИнформацияОТипе.Технический Тогда
Возврат;
КонецЕсли;
Если ПараметрыВыполнения.НеУдаленные.Найти(СтрокаТаблицы.УдаляемыйСсылка) = Неопределено Тогда
ПараметрыВыполнения.НеУдаленные.Добавить(СтрокаТаблицы.УдаляемыйСсылка);
КонецЕсли;
Причина = ПараметрыВыполнения.ПрепятствующиеУдалению.Добавить();
ЗаполнитьЗначенияСвойств(Причина, СтрокаТаблицы);
МестоИспользования = СтрокаТаблицы.МестоИспользования;
Если ТипЗнч(МестоИспользования) = Тип("Строка") Тогда
Причина.ОписаниеОшибки = МестоИспользования;
Причина.МестоИспользования = Неопределено;
КонецЕсли;
Если МестоИспользования = Неопределено
И НЕ Метаданные.Константы.Содержит(СтрокаТаблицы.Метаданные) Тогда
Причина.ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Обнаружены неразрешимые ссылки (%1)'"),
СтрокаТаблицы.Метаданные.Представление());
КонецЕсли;
КонецПроцедуры
Функция СвязьТолькоСВедущимиИзмерениямиРегистров(ОписаниеСвязиДанных)
Результат = Ложь;
Если Не ОбщегоНазначения.ЭтоРегистр(ОписаниеСвязиДанных.Метаданные) Тогда
Возврат Результат;
КонецЕсли;
Для каждого Измерение Из ОписаниеСвязиДанных.Метаданные.Измерения Цикл
Если ОписаниеСвязиДанных.МестоИспользования[Измерение.Имя] = ОписаниеСвязиДанных.УдаляемыйСсылка
И Измерение.Ведущее Тогда
Результат = Истина;
Прервать;
КонецЕсли;
Если ОписаниеСвязиДанных.МестоИспользования["Регистратор"] = ОписаниеСвязиДанных.УдаляемыйСсылка Тогда
Результат = Истина;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
#Область ПередачаИнформацииНаКлиент
Процедура ОтметитьПрогрессОбходаКоллекции(ПараметрыВыполнения, ИмяКоллекции)
ПараметрыВыполнения.Номер = ПараметрыВыполнения.Номер + 1;
Процент = Окр(100 * (ПараметрыВыполнения.КоличествоОбработанных)
/ ПараметрыВыполнения.КоличествоУдаляемых);
ДополнительныеПараметры = Неопределено;
Если ИмяКоллекции = "ПередПоискомПомеченныхНаУдаление" Тогда
Текст = НСтр("ru = 'Подготовка к поиску объектов, помеченных на удаление.'");
ИначеЕсли ИмяКоллекции = "НайтиПомеченныеНаУдаление" Тогда
Текст = НСтр("ru = 'Поиск объектов, помеченных на удаление.'");
ИначеЕсли ИмяКоллекции = "ВсеПомеченныеНаУдаление" Тогда
Текст = НСтр("ru = 'Анализ помеченных на удаление.'");
ИначеЕсли ИмяКоллекции = "МонопольноеУдаление" Тогда
Текст = НСтр("ru = 'Выполняется удаление объектов.'");
ИначеЕсли ИмяКоллекции = "ПользовательскиеОбъекты" Тогда
ДополнительныеПараметры = Новый Структура;
ДополнительныеПараметры.Вставить("НомерСеанса", НомерСеансаИнформационнойБазы());
ДополнительныеПараметры.Вставить("КоличествоОбработанных", ПараметрыВыполнения.КоличествоОбработанных);
Текст = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Обработано %1 из %2'"),
ПараметрыВыполнения.КоличествоОбработанных,
ПараметрыВыполнения.КоличествоУдаляемых);
ИначеЕсли ИмяКоллекции = "ПовторноУдаляемые" Тогда
Текст = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Повторная проверка не удаленных объектов: %1 из %2.'"),
Формат(ПараметрыВыполнения.Номер, "ЧН=0; ЧГ="),
Формат(ПараметрыВыполнения.Всего, "ЧН=0; ЧГ="));
ИначеЕсли ИмяКоллекции = "ПрепятствующиеУдалению" Тогда
Текст = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Анализ объектов, препятствующих удалению: %1 из %2.'"),
Формат(ПараметрыВыполнения.Номер, "ЧН=0; ЧГ="),
Формат(ПараметрыВыполнения.Всего, "ЧН=0; ЧГ="));
Иначе
Возврат;
КонецЕсли;
ДлительныеОперации.СообщитьПрогресс(Процент, Текст, ДополнительныеПараметры);
КонецПроцедуры
#КонецОбласти
#КонецОбласти
Функция ОбъединениеТаблиц(Таблица1, Таблица2, СохранятьПорядок = Ложь)
Возврат УдалениеПомеченныхОбъектовСлужебный.ОбъединениеТаблиц(Таблица1, Таблица2, СохранятьПорядок);
КонецФункции
Процедура ОтправитьСтатистику(РежимУдаления, ВремяВыполнения, КоличествоУдаляемыхЭлементов)
Если НЕ ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЦентрМониторинга") Тогда
Возврат;
КонецЕсли;
МодульЦентрМониторинга = ОбщегоНазначения.ОбщийМодуль("ЦентрМониторинга");
МодульЦентрМониторинга.ЗаписатьОперациюБизнесСтатистики(
"БазоваяФункциональность.УдалениеПомеченных."+РежимУдаления, ВремяВыполнения,
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru='Количество элементов: %1'"), КоличествоУдаляемыхЭлементов));
КонецПроцедуры
Функция ОтменаИсключенийПоискаСсылокПриУдаленииОбъектов()
ОтменаИсключений = Новый Массив;
ОтменаИсключений.Добавить(Метаданные.Справочники.ВнешниеПользователи);
Возврат ОтменаИсключений;
КонецФункции
#КонецОбласти
#КонецЕсли