Files
SSL/SSL/src/DataProcessors/УдалениеПомеченныхОбъектов/ManagerModule.bsl
T
2021-11-19 11:10:00 +03:00

1850 lines
128 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2021, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
#Область СлужебныеПроцедурыИФункции
Функция УдалитьПомеченныеОбъекты(ПараметрыВыполнения, ИдентификаторЗадания = Неопределено) Экспорт
Если НЕ Пользователи.ЭтоПолноправныйПользователь() Тогда
ВызватьИсключение НСтр("ru = 'Недостаточно прав для выполнения операции.'");
КонецЕсли;
Замер = ТекущаяУниверсальнаяДатаВМиллисекундах();
УдалениеПомеченныхОбъектовПереопределяемый.ПередПоискомПомеченныхНаУдаление(ПараметрыВыполнения);
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
МодульУправлениеДоступом = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступом");
МодульУправлениеДоступом.ОтключитьОбновлениеКлючейДоступа(Истина);
КонецЕсли;
Попытка
УдаляемыеОбъекты = ПараметрыВыполнения.ПользовательскиеОбъекты;
ПараметрыУдаления = ПараметрыУдаления(УдаляемыеОбъекты, ПараметрыВыполнения);
// Для отмены задания с клиента
Если ЗначениеЗаполнено(ИдентификаторЗадания)Тогда
ПараметрыУдаления.ИдентификаторЗадания = ИдентификаторЗадания;
КонецЕсли;
Если ПараметрыУдаления.Монопольно Тогда
УдалитьПомеченныеОбъектыМонопольно(УдаляемыеОбъекты, ПараметрыУдаления);
Иначе
УдалитьПомеченныеОбъектыКонкурентно(УдаляемыеОбъекты, ПараметрыУдаления);
КонецЕсли;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
МодульУправлениеДоступом = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступом");
МодульУправлениеДоступом.ОтключитьОбновлениеКлючейДоступа(Ложь);
КонецЕсли;
Исключение
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
МодульУправлениеДоступом = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступом");
МодульУправлениеДоступом.ОтключитьОбновлениеКлючейДоступа(Ложь);
КонецЕсли;
ВызватьИсключение;
КонецПопытки;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Взаимодействия") Тогда
МодульВзаимодействия = ОбщегоНазначения.ОбщийМодуль("Взаимодействия");
МодульВзаимодействия.ПослеУдаленияПомеченных(ПараметрыУдаления);
КонецЕсли;
Замер = ТекущаяУниверсальнаяДатаВМиллисекундах() - Замер;
ОтправитьСтатистику(ПараметрыВыполнения.Режим, Замер, ПараметрыУдаления.Всего);
Возврат ПараметрыУдаления;
КонецФункции
#Область КонкурентноеУдаление
// Параметры:
// УдаляемыеОбъекты - Массив из ЛюбаяСсылка
// ПараметрыУдаления - см. ПараметрыУдаления
//
Процедура УдалитьПомеченныеОбъектыКонкурентно(УдаляемыеОбъекты, ПараметрыУдаления)
СведенияОМетаданных = СведенияОМетаданных(ПараметрыУдаления, УдаляемыеОбъекты);
УдаляемыеОбъекты = УдаляемыеОбъекты(УдаляемыеОбъекты, СведенияОМетаданных);
РезультатОбработки = ОбработатьУдаляемыеОбъекты(ПараметрыУдаления, УдаляемыеОбъекты, СведенияОМетаданных);
ОтразитьМестаИспользования(ПараметрыУдаления, РезультатОбработки.МестаИспользования);
ОтразитьНеУдаленные(ПараметрыУдаления, РезультатОбработки.НеудаленныеОбъекты);
ПараметрыУдаления.Удаленные = Новый Массив(Новый ФиксированныйМассив(РезультатОбработки.УдаленныеОбъекты));
КонецПроцедуры
#Область ПреобразованиеКФорматуРезультата
// Параметры:
// ПараметрыУдаления - см. ПараметрыУдаления
// НеУдаленные - см. РезультатОбработки
//
Процедура ОтразитьНеУдаленные(ПараметрыУдаления, НеУдаленные)
Если Не (ПараметрыУдаления.Свойство("ИнформацияОТипах")) Тогда
ПараметрыУдаления.Вставить("ИнформацияОТипах", Новый Соответствие);
КонецЕсли;
Для Каждого Элемент Из НеУдаленные Цикл
Если Элемент = Неопределено Тогда
Продолжить;
КонецЕсли;
// Объект может быть не удален из-за ПометкаУдаления = Ложь,
// но удален как подчиненный
Если ОбъектУдален(Элемент.УдаляемыйСсылка) Тогда
Продолжить;
КонецЕсли;
ПараметрыУдаления.Неудаленные.Добавить(Элемент.УдаляемыйСсылка);
Если Элемент.РезультатУдаления <> КодыРезультатаУдаления().НеПомеченНаУдаление Тогда
РегистрыСведений.НеудаленныеОбъекты.Добавить(Элемент.УдаляемыйСсылка);
КонецЕсли;
Если Элемент.РезультатУдаления = КодыРезультатаУдаления().ОшибкаПриУдалении Тогда
Причина = ПараметрыУдаления.ПрепятствующиеУдалению.Добавить();
Причина.УдаляемыйСсылка = Элемент.УдаляемыйСсылка;
Причина.ОписаниеОшибки = КраткоеПредставлениеОшибки(Элемент.ИнформацияОбОшибке) + Элемент.Сообщения;
Причина.ПодробноеОписаниеОшибки = ПодробноеПредставлениеОшибки(Элемент.ИнформацияОбОшибке);
ИначеЕсли Элемент.РезультатУдаления = КодыРезультатаУдаления().НеПомеченНаУдаление Тогда
Причина = ПараметрыУдаления.ПрепятствующиеУдалению.Добавить();
Причина.УдаляемыйСсылка = Элемент.УдаляемыйСсылка;
Причина.ОписаниеОшибки = НСтр("ru='Удаляемый объект не помечен на удаление'");
КонецЕсли;
СформироватьИнформациюОТипах(ПараметрыУдаления, ТипЗнч(Элемент.УдаляемыйСсылка))
КонецЦикла;
КонецПроцедуры
Процедура ОтразитьМестаИспользования(ПараметрыУдаления, МестаИспользования)
ПрепятствующиеУдалению = ПараметрыУдаления.ПрепятствующиеУдалению;
Для Каждого СведенияОМестеИспользования Из МестаИспользования Цикл
Если ОбъектУдален(СведенияОМестеИспользования.МестоИспользования) Тогда
Продолжить;
КонецЕсли;
Причина = ПрепятствующиеУдалению.Добавить();
Причина.УдаляемыйСсылка = СведенияОМестеИспользования.УдаляемыйСсылка;
Причина.МестоИспользования = СведенияОМестеИспользования.МестоИспользования;
Причина.Метаданные = СведенияОМестеИспользования.Метаданные;
КонецЦикла;
КолонкиПрепятствующиеУдалению = Новый Массив;
Для каждого Колонка Из ПрепятствующиеУдалению.Колонки Цикл
КолонкиПрепятствующиеУдалению.Добавить(Колонка.Имя);
КонецЦикла;
// Группируем таблицу для исключения дублей, т.к.
// Не выполняем поиск повторений между пакетами
ПрепятствующиеУдалению.Свернуть(СтрСоединить(КолонкиПрепятствующиеУдалению, ","));
КонецПроцедуры
#КонецОбласти
#Область УдалениеОбъектов
// Параметры:
// ПараметрыУдаления - см. ПараметрыУдаления
// УдаляемыеОбъекты - см. УдаляемыеОбъекты
// СведенияОМетаданных - см. СведенияОМетаданных
//
// Возвращаемое значение:
// см. РезультатОбработки
//
Функция ОбработатьУдаляемыеОбъекты(ПараметрыУдаления, УдаляемыеОбъекты, СведенияОМетаданных)
РезультатыУдаления = РезультатОбработки();
Пакет = ПакетУдаляемыхОбъектов();
ОбъектыСЗапретомУдаления = ПакетУдаляемыхОбъектов();
Для Каждого ЭлементОчереди Из УдаляемыеОбъекты Цикл
Если НЕ Пакет.Найти(ЭлементОчереди.УдаляемыйСсылка,"УдаляемыйСсылка") <> Неопределено Тогда
ЭлементОчередиВПакете = ЭлементОчередиВПакет(ЭлементОчереди, СведенияОМетаданных, Пакет);
Если ЗапрещенаОбработкаЭлемента(ЭлементОчередиВПакете) Тогда
ОбъектыСЗапретомУдаления = ОбъединениеТаблиц(
ОбъектыСЗапретомУдаления,
ЭлементОчередиВПакете);
Иначе
Пакет = ОбъединениеТаблиц(Пакет, ЭлементОчередиВПакете, Истина);
КонецЕсли;
КонецЕсли;
Если Пакет.Количество() >= ПараметрыУдаления.РазмерПакета
ИЛИ УдаляемыеОбъекты.Индекс(ЭлементОчереди) = УдаляемыеОбъекты.Количество()-1 Тогда
РезультатОбработкиПакета = ОбработатьПакет(ПараметрыУдаления, Пакет);
РезультатыУдаления = ОбъединитьРезультатУдаления(
РезультатыУдаления,
РезультатОбработкиПакета);
Пакет.Очистить();
КонецЕсли;
КонецЦикла;
РезультатыУдаления = ОбъединитьРезультатУдаления(
РезультатыУдаления,
РезультатУдаленияИзНеобработанногоПакета(ПараметрыУдаления, ОбъектыСЗапретомУдаления));
// Попробуем удалить объекты, образующие циклические ссылки в одной транзакции
КоличествоНеудаленныхЭлементов = 0;
Пока РезультатыУдаления.НеудаленныеОбъекты.Количество() <> КоличествоНеудаленныхЭлементов Цикл
КоличествоНеудаленныхЭлементов = РезультатыУдаления.НеудаленныеОбъекты.Количество();
Пакет = ЦиклическиеСсылки(РезультатыУдаления.НеудаленныеОбъекты, РезультатыУдаления.МестаИспользования);
РезультатОбработкиЦиклическихСсылок = ОбработатьПакетВОднойТранзакции(ПараметрыУдаления, Пакет);
Если РезультатОбработкиЦиклическихСсылок.УдаленныеОбъекты.Количество() > 0 Тогда
РезультатыУдаления = РезультатПослеУдаленияЦиклическихСсылок(РезультатыУдаления, РезультатОбработкиЦиклическихСсылок);
КонецЕсли;
КонецЦикла;
Возврат РезультатыУдаления;
КонецФункции
Функция РезультатУдаленияИзНеобработанногоПакета(ПараметрыУдаления, ОбъектыСЗапретомУдаления)
РезультатыУдаления = РезультатОбработки();
РезультатыУдаления.НеудаленныеОбъекты = ОбъединениеТаблиц(
РезультатыУдаления.НеудаленныеОбъекты,
ОбъектыСЗапретомУдаления);
РезультатыУдаления.МестаИспользования = ОбъединениеТаблиц(
РезультатыУдаления.МестаИспользования,
ОставшиесяМестаИспользованияУдаляемогоОбъекта(ПараметрыУдаления,
МестаИспользованияЭлементовПакета(ПараметрыУдаления, ОбъектыСЗапретомУдаления)));
Возврат РезультатыУдаления;
КонецФункции
Функция ЗапрещенаОбработкаЭлемента(ЭлементОчередиВПакете)
Возврат (ЭлементОчередиВПакете.Количество() > 0 И ЭлементОчередиВПакете[ЭлементОчередиВПакете.Количество()
- 1].РезультатУдаления <> КодыРезультатаУдаления().Успешно);
КонецФункции
Функция ЭлементОчередиВПакет(ЭлементОчереди, СведенияОМетаданных, Исключения)
Пакет = ПакетУдаляемыхОбъектов();
РезультатУдаления = Неопределено;
// Пропускаем если объект удален или был добавлен в пакет как подчиненный объект
Если НЕ ОбъектУдален(ЭлементОчереди.УдаляемыйСсылка)
И Исключения.Найти(ЭлементОчереди.УдаляемыйСсылка, "УдаляемыйСсылка") = Неопределено Тогда
ИнформацияОМетаданных = СведенияОМетаданных.Найти(ЭлементОчереди.Тип, "Тип");
ПометкаУдаления = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ЭлементОчереди.УдаляемыйСсылка, "ПометкаУдаления");
ДочерниеПодчиненныеЭлементы = ?(ПометкаУдаления,
ДочерниеПодчиненныеЭлементы(ЭлементОчереди.УдаляемыйСсылка, ИнформацияОМетаданных),
ТаблицаДочернихПодчиненныхЭлементов());
Если НЕ ПометкаУдаления Тогда
РезультатУдаления = КодыРезультатаУдаления().НеПомеченНаУдаление;
ИначеЕсли РазрешеноУдалениеЭлемента(ДочерниеПодчиненныеЭлементы) Тогда
РезультатУдаления = КодыРезультатаУдаления().Успешно;
ДополнитьПакетДочернимиИПодчиненнымиЭлементами(Пакет, ЭлементОчереди.УдаляемыйСсылка, ДочерниеПодчиненныеЭлементы, Исключения);
Иначе
РезультатУдаления = КодыРезультатаУдаления().ЕстьДочерниеПодчиненныеЭлементыНепомеченныеНаУдаление;
КонецЕсли;
ЭлементПакета = Пакет.Добавить();
ЭлементПакета.УдаляемыйСсылка = ЭлементОчереди.УдаляемыйСсылка;
ЭлементПакета.ЕстьДочерниеОбъекты = ИнформацияОМетаданных.Иерархический;
ЭлементПакета.ЕстьПодчиненныеОбъекты = ИнформацияОМетаданных.ЕстьПодчиненныеОбъекты;
ЭлементПакета.ДочерниеПодчиненныеОбъекты = ДочерниеПодчиненныеЭлементы;
ЭлементПакета.РезультатУдаления = РезультатУдаления;
ЭлементПакета.ЭтоОсновнойОбъект = Истина;
ЭлементПакета.ОсновнойЭлементСсылка = ЭлементОчереди.УдаляемыйСсылка;
КонецЕсли;
Возврат Пакет;
КонецФункции
Функция ОбработатьПакет(ПараметрыУдаления, Пакет)
РезультатОбработкиПакета = РезультатОбработки();
Если ЗначениеЗаполнено(ПараметрыУдаления.ИдентификаторЗадания) И ОбщегоНазначения.РежимОтладки() Тогда
Идентификатор = ПараметрыУдаления.ИдентификаторЗадания;
Иначе
УстановитьПривилегированныйРежим(Истина);
Сеанс = ПолучитьТекущийСеансИнформационнойБазы();
ФоновоеЗадание = Сеанс.ПолучитьФоновоеЗадание();
Если ФоновоеЗадание = Неопределено Тогда
Идентификатор = Новый УникальныйИдентификатор;
Иначе
Идентификатор = ФоновоеЗадание.УникальныйИдентификатор;
КонецЕсли;
УстановитьПривилегированныйРежим(Ложь);
КонецЕсли;
ПередОбработкойПакета(Пакет, Идентификатор);
МестаИспользования = МестаИспользованияЭлементовПакета(ПараметрыУдаления, Пакет);
ОсновнойИПодчиненныеОбъекты = Новый Массив;
СсылкиНаУдаляемыеОбъекты = Новый Массив;
Для Каждого Элемент Из Пакет Цикл
ОсновнойИПодчиненныеОбъекты.Добавить(Элемент);
СсылкиНаУдаляемыеОбъекты.Добавить(Элемент.УдаляемыйСсылка);
Если НЕ Элемент.ЭтоОсновнойОбъект Тогда
Продолжить;
КонецЕсли;
СтандартнаяОбработка = Истина;
Контекст = Новый Структура;
ПередУдалениемГруппыОбъектов(
Контекст,
ОбщегоНазначения.ФиксированныеДанные(СсылкиНаУдаляемыеОбъекты, Ложь),
СтандартнаяОбработка);
Если Не СтандартнаяОбработка Тогда
Продолжить;
КонецЕсли;
НельзяУдалятьОсновнойОбъект = Ложь;
НеудаленныеЭлементы = Новый Массив;
НачатьТранзакцию();
Попытка
ОсновнойОбъект = ОсновнойИПодчиненныеОбъекты[ОсновнойИПодчиненныеОбъекты.ВГраница()];
Для каждого УдаляемыйСсылка Из ОсновнойИПодчиненныеОбъекты Цикл
Фильтр = Новый Структура("УдаляемыйСсылка", УдаляемыйСсылка.УдаляемыйСсылка);
РезультатУдаления = УдалитьЭлементПакета(
ПараметрыУдаления,
УдаляемыйСсылка,
МестаИспользования.Скопировать(Фильтр),
НеудаленныеЭлементы);
ОтразитьРезультатУдаленияЭлементаПакета(
ПараметрыУдаления,
РезультатОбработкиПакета,
РезультатУдаления);
Если НЕ УдаляемыйСсылка.ЭтоОсновнойОбъект И РезультатУдаления.Код = КодыРезультатаУдаления().ОшибкаПриУдалении Тогда
// Если удаление подчиненного элемента завершилось с ошибкой, то удаление других элементов невозможно.
// Возвращаем основной элемент с единственной причиной неудаления - неудаленным дочерним или подчиненным элементом.
НельзяУдалятьОсновнойОбъект = Истина;
НеудаленныеЭлементы.Добавить(РезультатУдаления.УдаляемыйСсылка);
РезультатУдаленияОсновногоЭлемента = РезультатУдаленияЭлемента(ОсновнойОбъект);
РезультатУдаленияОсновногоЭлемента.Код = КодыРезультатаУдаления().ЕстьМестаИспользования;
Фильтр = Новый Структура("УдаляемыйСсылка, МестоИспользования", ОсновнойОбъект.УдаляемыйСсылка, УдаляемыйСсылка.УдаляемыйСсылка);
РезультатУдаленияОсновногоЭлемента.МестаИспользования = МестаИспользования.Скопировать(Фильтр);
ОтразитьРезультатУдаленияЭлементаПакета(
ПараметрыУдаления,
РезультатОбработкиПакета,
РезультатУдаленияОсновногоЭлемента);
Прервать;
ИначеЕсли РезультатУдаления.Код <> КодыРезультатаУдаления().Успешно Тогда
НельзяУдалятьОсновнойОбъект = Истина;
НеудаленныеЭлементы.Добавить(РезультатУдаления.УдаляемыйСсылка);
КонецЕсли;
КонецЦикла;
Если НЕ НельзяУдалятьОсновнойОбъект Тогда
ЗафиксироватьТранзакцию();
ПослеУдаленияГруппыОбъектов(Контекст, Истина);
Иначе
ОтменитьТранзакцию();
ПослеУдаленияГруппыОбъектов(Контекст, Ложь);
КонецЕсли;
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
ОсновнойИПодчиненныеОбъекты.Очистить();
СсылкиНаУдаляемыеОбъекты.Очистить();
КонецЦикла;
ПослеОбработкиПакета(ПараметрыУдаления, Идентификатор);
ОчиститьСсылкиНаУдаляемыеОбъекты(ПараметрыУдаления, РезультатОбработкиПакета);
Возврат РезультатОбработкиПакета;
КонецФункции
// см. УдалениеПомеченныхОбъектовПереопределяемый.ПередУдалениемГруппыОбъектов
Процедура ПередУдалениемГруппыОбъектов(Контекст, СвязанныеОбъекты, СтандартнаяОбработка)
ИнтеграцияПодсистемБСП.ПередУдалениемГруппыОбъектов(Контекст, СвязанныеОбъекты, СтандартнаяОбработка);
КонецПроцедуры
// см. УдалениеПомеченныхОбъектовПереопределяемый.ПослеУдаленияГруппыОбъектов
Процедура ПослеУдаленияГруппыОбъектов(Контекст, Успешно)
ИнтеграцияПодсистемБСП.ПослеУдаленияГруппыОбъектов(Контекст, Успешно);
КонецПроцедуры
Функция РезультатУдаленияЭлемента(Знач Элемент)
Результат = Новый Структура();
Результат.Вставить("УдаляемыйСсылка", Элемент.УдаляемыйСсылка);
Результат.Вставить("Код", КодыРезультатаУдаления().Успешно);
Результат.Вставить("МестаИспользования", МестаИспользования());
Результат.Вставить("Сообщения", Новый ФиксированныйМассив(Новый Массив));
Результат.Вставить("ЭтоОсновнойОбъект", Элемент.ЭтоОсновнойОбъект);
Результат.Вставить("ИнформацияОбОшибке");
Возврат Результат;
КонецФункции
#Область ОчисткаСсылокНаУдаляемыеОбъекты
// Параметры:
// ПараметрыУдаления - см. ПараметрыУдаления
// РезультатОбработкиПакета - см. РезультатОбработки
//
Процедура ОчиститьСсылкиНаУдаляемыеОбъекты(ПараметрыУдаления, РезультатОбработкиПакета)
Если Не ПараметрыУдаления.ОчищатьСсылкиВМестахИспользования
Или РезультатОбработкиПакета.МестаОчисткиСсылок.Количество() = 0 Тогда
Возврат;
КонецЕсли;
МестаИспользования = РезультатОбработкиПакета.МестаОчисткиСсылок;
МестаИспользования.Сортировать("МестоИспользования", Новый СравнениеЗначений());
УдаляемыеОбъектыВМестеИспользования = Новый Массив;
ПозицияТекущегоМестаИспользования = 0;
Для Каждого СведениеОМестеИспользования Из МестаИспользования Цикл
Если МестаИспользования[ПозицияТекущегоМестаИспользования].МестоИспользования
<> СведениеОМестеИспользования.МестоИспользования Тогда
ОчиститьСсылкиВМестеИспользования(МестаИспользования[ПозицияТекущегоМестаИспользования].МестоИспользования,
УдаляемыеОбъектыВМестеИспользования);
ПозицияТекущегоМестаИспользования = МестаИспользования.Индекс(СведениеОМестеИспользования);
УдаляемыеОбъектыВМестеИспользования.Очистить();
КонецЕсли;
УдаляемыеОбъектыВМестеИспользования.Добавить(СведениеОМестеИспользования.УдаляемыйСсылка);
Если МестаИспользования.Индекс(СведениеОМестеИспользования) = МестаИспользования.Количество() - 1 Тогда
ОчиститьСсылкиВМестеИспользования(СведениеОМестеИспользования.МестоИспользования,
УдаляемыеОбъектыВМестеИспользования);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ОчиститьСсылкиВМестеИспользования(МестоИспользование, УдаляемыеОбъектыВМестеИспользования)
Если ОбъектУдален(МестоИспользование) Тогда
Возврат;
КонецЕсли;
РедактируемыйОбъект = МестоИспользование.ПолучитьОбъект();
МетаданныеОбъекта = РедактируемыйОбъект.Метаданные();
ОчиститьСсылкиВКоллекцииРеквизитов(РедактируемыйОбъект, МетаданныеОбъекта.СтандартныеРеквизиты, УдаляемыеОбъектыВМестеИспользования);
ОчиститьСсылкиВКоллекцииРеквизитов(РедактируемыйОбъект, МетаданныеОбъекта.Реквизиты, УдаляемыеОбъектыВМестеИспользования);
Для Каждого ТабличнаяЧасть Из МетаданныеОбъекта.ТабличныеЧасти Цикл
ОчиститьСсылкиВТабличнойЧасти(РедактируемыйОбъект[ТабличнаяЧасть.Имя], ТабличнаяЧасть.Реквизиты, УдаляемыеОбъектыВМестеИспользования);
КонецЦикла;
ЕстьСтандартныеТабличныеЧасти = ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(МетаданныеОбъекта,
"СтандартныеТабличныеЧасти");
СтандартныеТабличныеЧасти = ?(ЕстьСтандартныеТабличныеЧасти,
МетаданныеОбъекта.СтандартныеТабличныеЧасти,
Новый Массив);
Для Каждого ТабличнаяЧасть Из СтандартныеТабличныеЧасти Цикл
ОчиститьСсылкиВТабличнойЧасти(РедактируемыйОбъект[ТабличнаяЧасть.Имя], ТабличнаяЧасть.СтандартныеРеквизиты, УдаляемыеОбъектыВМестеИспользования);
КонецЦикла;
ЗаписатьРедактируемыйОбъект(МестоИспользование, РедактируемыйОбъект);
КонецПроцедуры
Процедура ЗаписатьРедактируемыйОбъект(МестоИспользование, РедактируемыйОбъект)
РедактируемыйОбъект.ДополнительныеСвойства.Вставить("НеВыполнятьКонтрольУдаляемых");
РедактируемыйОбъект.ОбменДанными.Загрузка = Истина;
НачатьТранзакцию();
Попытка
Блокировка = Новый БлокировкаДанных();
Элемент = Блокировка.Добавить(МестоИспользование.Метаданные().ПолноеИмя());
Элемент.УстановитьЗначение("Ссылка", МестоИспользование);
Блокировка.Заблокировать();
РедактируемыйОбъект.Записать();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ЗаписатьПредупреждение(МестоИспользование, ИнформацияОбОшибке());
КонецПопытки;
КонецПроцедуры
Процедура ОчиститьСсылкиВТабличнойЧасти(РедактируемыйОбъект, КоллекцияРеквизитов, УдаляемыеОбъектыВМестеИспользования)
Для Каждого СтрокаТЧ Из РедактируемыйОбъект Цикл
ОчиститьСсылкиВКоллекцииРеквизитов(СтрокаТЧ, КоллекцияРеквизитов, УдаляемыеОбъектыВМестеИспользования);
КонецЦикла;
КонецПроцедуры
Процедура ОчиститьСсылкиВКоллекцииРеквизитов(РедактируемыйОбъект, КоллекцияРеквизитов, УдаляемыеОбъектыВМестеИспользования)
Для Каждого Реквизит Из КоллекцияРеквизитов Цикл
Если УдаляемыеОбъектыВМестеИспользования.Найти(РедактируемыйОбъект[Реквизит.Имя]) <> Неопределено Тогда
РедактируемыйОбъект[Реквизит.Имя] = Реквизит.Тип.ПривестиЗначение(Неопределено);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Параметры:
// РезультатыУдаления - см. РезультатОбработки
// РезультатОбработкиЦиклическихСсылок - см. РезультатОбработки
//
// Возвращаемое значение:
// см. РезультатОбработки
//
Функция РезультатПослеУдаленияЦиклическихСсылок(РезультатыУдаления, РезультатОбработкиЦиклическихСсылок)
Результат = РезультатОбработки();
Результат.УдаленныеОбъекты = Новый Массив(Новый ФиксированныйМассив(РезультатыУдаления.УдаленныеОбъекты));
Для Каждого Элемент Из РезультатыУдаления.НеудаленныеОбъекты Цикл
Если РезультатОбработкиЦиклическихСсылок.УдаленныеОбъекты.Найти(Элемент.УдаляемыйСсылка) <> Неопределено Тогда
Результат.УдаленныеОбъекты.Добавить(Элемент.УдаляемыйСсылка);
Иначе
ЗаполнитьЗначенияСвойств(Результат.НеудаленныеОбъекты.Добавить(), Элемент);
Для Каждого МестоИспользования Из РезультатыУдаления.МестаИспользования.НайтиСтроки(Новый Структура("УдаляемыйСсылка", Элемент.УдаляемыйСсылка)) Цикл
ЗаполнитьЗначенияСвойств(Результат.МестаИспользования.Добавить(), МестоИспользования);
КонецЦикла;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
#КонецОбласти
#Область ФормированиеДочернихПодчиненныхЭлементов
// Параметры:
// ЭлементОчереди - см. УдаляемыеОбъекты
// ИнформацияОМетаданных - см. СведенияОМетаданных
//
// Возвращаемое значение:
// см. ТаблицаДочернихПодчиненныхЭлементов
//
Функция ДочерниеПодчиненныеЭлементы(УдаляемыйСсылка, ИнформацияОМетаданных)
УстановитьПривилегированныйРежим(Истина);
ДочерниеПодчиненныеЭлементы = ТаблицаДочернихПодчиненныхЭлементов();
ПакетыЗапроса = Новый Массив;
Если ИнформацияОМетаданных.Иерархический Тогда
ПакетыЗапроса.Добавить(ТекстЗапросаДочернихЭлементов(ИнформацияОМетаданных));
КонецЕсли;
Если ИнформацияОМетаданных.ОписаниеПодчиненныхОбъектов.Количество() > 0 Тогда
ПакетыЗапроса.Добавить(ТекстЗапросаПодчиненныхЭлементов(ИнформацияОМетаданных));
КонецЕсли;
Если ПакетыЗапроса.Количество() > 0 Тогда
ТекстЗапроса = СтрСоединить(ПакетыЗапроса, ОбщегоНазначения.РазделительПакетаЗапросов());
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("Родитель", УдаляемыйСсылка);
Запрос.УстановитьПараметр("Ссылка", УдаляемыйСсылка);
РезультатПакета = Запрос.ВыполнитьПакет();
Если ИнформацияОМетаданных.ОписаниеПодчиненныхОбъектов.Количество() > 0 Тогда
ВыборкаПодчиненныхЭлементов = РезультатПакета[РезультатПакета.Количество()-1].Выбрать();
ДочерниеПодчиненныеЭлементы = ОбъединениеТаблиц(ДочерниеПодчиненныеЭлементы, ПодчиненныеЭлементы(ВыборкаПодчиненныхЭлементов));
КонецЕсли;
Если ИнформацияОМетаданных.Иерархический Тогда
ВыборкаДочернихЭлементов = РезультатПакета[0].Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
ДочерниеПодчиненныеЭлементы = ОбъединениеТаблиц(ДочерниеПодчиненныеЭлементы, ДочерниеЭлементы(УдаляемыйСсылка, ВыборкаДочернихЭлементов));
КонецЕсли;
КонецЕсли;
Возврат ДочерниеПодчиненныеЭлементы;
КонецФункции
// Рекурсивно формирует таблицу дочерних элементов.
//
// Параметры:
// РезультатПакета - ДеревоЗначений
//
// Возвращаемое значение:
// см. ТаблицаДочернихПодчиненныхЭлементов
//
Функция ДочерниеЭлементы(ОсновнойЭлемент, РезультатПакета)
Результат = ТаблицаДочернихПодчиненныхЭлементов();
Для Каждого СтрокаДерева Из РезультатПакета.Строки Цикл
Если СтрокаДерева.Элемент = ОсновнойЭлемент Тогда
ДочерниеЭлементы = ДочерниеЭлементы(ОсновнойЭлемент, СтрокаДерева);
Результат = ОбъединениеТаблиц(Результат, ДочерниеЭлементы)
Иначе
ЗаписьРезультата = Результат.Добавить();
ЗаполнитьЗначенияСвойств(ЗаписьРезультата, СтрокаДерева);
ЗаписьРезультата.ДочерниеЭлементы = ДочерниеЭлементы(ОсновнойЭлемент, СтрокаДерева);
Результат = ОбъединениеТаблиц(ЗаписьРезультата.ДочерниеЭлементы, Результат, Истина);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
// Параметры:
// РезультатПакета - ВыборкаИзРезультатаЗапроса
//
// Возвращаемое значение:
// см. ТаблицаДочернихПодчиненныхЭлементов
//
Функция ПодчиненныеЭлементы(РезультатПакета)
ДочерниеПодчиненныеЭлементы = ТаблицаДочернихПодчиненныхЭлементов();
Пока РезультатПакета.Следующий() Цикл
ЗаполнитьЗначенияСвойств(ДочерниеПодчиненныеЭлементы.Добавить(), РезультатПакета);
КонецЦикла;
Возврат ДочерниеПодчиненныеЭлементы;
КонецФункции
// Возвращаемое значение:
// ТаблицаЗначений :
// * Элемент - ЛюбаяСсылка
// * ДочерниеЭлементы - см. ТаблицаДочернихПодчиненныхЭлементов
// * ПометкаУдаления - Булево
// * ТипЭлемента - Строка
//
Функция ТаблицаДочернихПодчиненныхЭлементов()
ДочерниеПодчиненныеЭлементы = Новый ТаблицаЗначений();
ДочерниеПодчиненныеЭлементы.Колонки.Добавить("Элемент");
ДочерниеПодчиненныеЭлементы.Колонки.Добавить("ДочерниеЭлементы", Новый ОписаниеТипов("ТаблицаЗначений"));
ДочерниеПодчиненныеЭлементы.Колонки.Добавить("ПометкаУдаления", Новый ОписаниеТипов("Булево"));
ДочерниеПодчиненныеЭлементы.Колонки.Добавить("ТипЭлемента", Новый ОписаниеТипов("Строка"));
Возврат ДочерниеПодчиненныеЭлементы
КонецФункции
Функция ТекстЗапросаДочернихЭлементов(ИнформацияОМетаданных)
ШаблонЗапроса = "ВЫБРАТЬ
| Таб.Ссылка КАК Элемент,
| Таб.ПометкаУдаления КАК ПометкаУдаления,
| ""Дочерний"" КАК ТипЭлемента
|ИЗ
| &ИмяТаблицы КАК ТАБ
|ГДЕ
| Таб.Ссылка В ИЕРАРХИИ (&Родитель)
|УПОРЯДОЧИТЬ ПО
| Элемент ИЕРАРХИЯ";
Таблица = ИнформацияОМетаданных.Метаданные.ПолноеИмя();
ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "&ИмяТаблицы", Таблица);
Возврат ТекстЗапроса;
КонецФункции
// Параметры:
// ИнформацияОМетаданных - см. СведенияОМетаданных
//
// Возвращаемое значение:
// Строка
//
Функция ТекстЗапросаПодчиненныхЭлементов(ИнформацияОМетаданных)
ТекстыЗапросов = Новый Массив;// Массив из Строка
ШаблонУсловияСвязи = "Таб.%1 = &Ссылка";
ШаблонЗапроса = "ВЫБРАТЬ
| Таб.Ссылка КАК Элемент,
| Таб.ПометкаУдаления КАК ПометкаУдаления,
| ""Подчиненный"" КАК ТипЭлемента
|ИЗ
| &ИмяТаблицы КАК ТАБ
|ГДЕ
| Таб.Ссылка <> &Ссылка
| И &УсловиеСвязи";
УсловиеСвязи = "ЛОЖЬ";
Для Каждого ПодчиненныйОбъект Из ИнформацияОМетаданных.ОписаниеПодчиненныхОбъектов Цикл
УсловиеСвязи = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонУсловияСвязи, ПодчиненныйОбъект.ИмяРеквизита);
ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "&ИмяТаблицы", ПодчиненныйОбъект.Метаданные.ПолноеИмя());
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеСвязи", УсловиеСвязи);
ТекстыЗапросов.Добавить(ТекстЗапроса);
КонецЦикла;
Возврат СтрСоединить(ТекстыЗапросов, Символы.ПС + "ОБЪЕДИНИТЬ ВСЕ" + Символы.ПС);
КонецФункции
#КонецОбласти
// Параметры:
// РезультатыУдаления - см. РезультатОбработки
// РезультатОбработки - см. РезультатОбработки
//
Функция ОбъединитьРезультатУдаления(РезультатыУдаления, РезультатОбработки)
Результат = РезультатОбработки();
Результат.НеудаленныеОбъекты = ОбъединениеТаблиц(
РезультатыУдаления.НеудаленныеОбъекты,
РезультатОбработки.НеудаленныеОбъекты);
Результат.МестаИспользования = ОбъединениеТаблиц(
РезультатыУдаления.МестаИспользования,
РезультатОбработки.МестаИспользования);
Результат.УдаленныеОбъекты = УдалениеПомеченныхОбъектовСлужебный.ОбъединениеМассивов(
РезультатыУдаления.УдаленныеОбъекты,
РезультатОбработки.УдаленныеОбъекты);
Возврат Результат;
КонецФункции
// Параметры:
// Приемник - ТаблицаЗначений
// Источник - ТаблицаЗначений
// КолонкаПриемника - Строка
// КолонкаИсточника - Строка
//
// Возвращаемое значение:
// Булево
//
Функция ИсточникаПодмножествоПриемника(Приемник, Источник, КолонкаПриемника, КолонкаИсточника)
Результат = Истина;
Для Каждого СведенияОМестеИспользования Из Источник Цикл
Если НЕ ОбъектУдален(СведенияОМестеИспользования.МестоИспользования)
И Приемник.Найти(СведенияОМестеИспользования[КолонкаИсточника], КолонкаПриемника) = Неопределено Тогда
Результат = Ложь;
Прервать;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция РазрешеноУдалениеЭлемента(ДополнительныеСведения)
Результат = Истина;
Для Каждого Элемент Из ДополнительныеСведения Цикл
Если НЕ Элемент.ПометкаУдаления И НЕ Элемент.ТипЭлемента = "Подчиненный" Тогда
Результат = Ложь;
Прервать;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ОбъектУдален(УдаляемыйСсылка)
Возврат ЗначениеЗаполнено(УдаляемыйСсылка)
И (ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(УдаляемыйСсылка, "ВерсияДанных")
И НЕ ЗначениеЗаполнено(УдаляемыйСсылка.ВерсияДанных));
КонецФункции
// Параметры:
// ПараметрыУдаления - см. ПараметрыУдаления
// РезультатОбработкиПакета - см. РезультатОбработки
// Элемент - см. ПакетУдаляемыхОбъектов
// РезультатУдаления - см. УдалитьЭлементПакета
//
Процедура ОтразитьРезультатУдаленияЭлементаПакета(ПараметрыУдаления, РезультатОбработкиПакета, РезультатУдаления)
Если НЕ РезультатУдаления.ЭтоОсновнойОбъект И РезультатУдаления.Код = КодыРезультатаУдаления().Успешно Тогда
Возврат;
КонецЕсли;
Если РезультатУдаления.Код <> КодыРезультатаУдаления().Успешно Тогда
НеудаленныйЭлемент = РезультатОбработкиПакета.НеудаленныеОбъекты.Добавить();
ЗаполнитьЗначенияСвойств(НеудаленныйЭлемент, РезультатУдаления);
НеудаленныйЭлемент.РезультатУдаления = РезультатУдаления.Код;
НеудаленныйЭлемент.ИнформацияОбОшибке = РезультатУдаления.ИнформацияОбОшибке;
НеудаленныйЭлемент.Сообщения = СообщенияПользователяВСтроку(РезультатУдаления.Сообщения);
РезультатОбработкиПакета.МестаИспользования = ОбъединениеТаблиц(
РезультатОбработкиПакета.МестаИспользования,
РезультатУдаления.МестаИспользования);
Иначе
РезультатОбработкиПакета.УдаленныеОбъекты.Добавить(РезультатУдаления.УдаляемыйСсылка);
РезультатОбработкиПакета.МестаОчисткиСсылок = ОбъединениеТаблиц(
РезультатОбработкиПакета.МестаОчисткиСсылок,
РезультатУдаления.МестаИспользования);
КонецЕсли;
Если РезультатУдаления.ЭтоОсновнойОбъект Тогда
ПараметрыУдаления.КоличествоОбработанных = ПараметрыУдаления.КоличествоОбработанных + 1;
КонецЕсли;
ОповеститьОПрогрессе(ПараметрыУдаления);
КонецПроцедуры
Функция СообщенияПользователяВСтроку(Сообщения)
Результат = "";
Для Каждого Элемент Из Сообщения Цикл
Результат = Символы.ПС + Результат + Элемент.Текст;
КонецЦикла;
Возврат Результат;
КонецФункции
// Обработать пакет в одной транзакции.
//
// Параметры:
// ПараметрыУдаления - см. ПараметрыУдаления
// Пакет - см. ПакетУдаляемыхОбъектов
//
// Возвращаемое значение:
// см. РезультатОбработки
//
Функция ОбработатьПакетВОднойТранзакции(ПараметрыУдаления, Пакет)
Результат = РезультатОбработки();
СтандартнаяОбработка = Истина;
Контекст = Новый Структура;
УдаляемыеОбъекты = Пакет.ВыгрузитьКолонку("УдаляемыйСсылка");
ПередУдалениемГруппыОбъектов(Контекст, УдаляемыеОбъекты, СтандартнаяОбработка);
Если НЕ СтандартнаяОбработка Тогда
Возврат РезультатОбработки();
КонецЕсли;
НачатьТранзакцию();
Попытка
Для Каждого ЭлементПакета Из Пакет Цикл
Блокировка = Новый БлокировкаДанных();
Элемент = Блокировка.Добавить(ЭлементПакета.УдаляемыйСсылка.Метаданные().ПолноеИмя());
Элемент.УстановитьЗначение("Ссылка", ЭлементПакета.УдаляемыйСсылка);
Блокировка.Заблокировать();
Объект = ЭлементПакета.УдаляемыйСсылка.ПолучитьОбъект();
Если Объект <> Неопределено Тогда
УдалитьОбъект(Объект);
Результат.УдаленныеОбъекты.Добавить(ЭлементПакета.УдаляемыйСсылка);
КонецЕсли;
КонецЦикла;
ЗафиксироватьТранзакцию();
ПослеУдаленияГруппыОбъектов(Контекст, Истина);
Исключение
// Не смогли удалить ни один объект
// Будем отображать ошибку, произошедшую на предыдущем этапе удаления
ОтменитьТранзакцию();
Результат.НеудаленныеОбъекты = Пакет.Скопировать();
ПослеУдаленияГруппыОбъектов(Контекст, Истина);
КонецПопытки;
Возврат Результат;
КонецФункции
// Параметры:
// ПараметрыУдаления - см. ПараметрыУдаления
// Элемент - СтрокаТаблицыЗначений: см. ПакетУдаляемыхОбъектов
// МестаИспользования - см. МестаИспользования
// НеудаленныеЭлементы - Массив из ЛюбаяСсылка
//
// Возвращаемое значение:
// Структура:
// * Код - Строка
// * МестаИспользования - см. МестаИспользованияЭлементовПакета
// * Сообщения - Массив из СообщениеПользователю
// * ИнформацияОбОшибке - Неопределено
// - ИнформацияОбОшибке
//
Функция УдалитьЭлементПакета(ПараметрыУдаления, Элемент, МестаИспользования, НеудаленныеЭлементы)
Результат = РезультатУдаленияЭлемента(Элемент);
// Объект был удален ранее
Если ОбъектУдален(Элемент.УдаляемыйСсылка) Тогда
Возврат Результат;
КонецЕсли;
// У элемента есть неудаленные дочерние или подчиненные объекты
Для Каждого ДочернийПодчиненныйЭлемент Из Элемент.ДочерниеПодчиненныеОбъекты Цикл
Если НЕ ОбъектУдален(ДочернийПодчиненныйЭлемент.Элемент)
ИЛИ НеудаленныеЭлементы.Найти(ДочернийПодчиненныйЭлемент.Элемент) <> Неопределено Тогда
Результат.Код = КодыРезультатаУдаления().ЕстьМестаИспользования;
Результат.МестаИспользования = ОставшиесяМестаИспользованияУдаляемогоОбъекта(
ПараметрыУдаления,
МестаИспользования,
ДочернийПодчиненныйЭлемент.Элемент);
Возврат Результат;
КонецЕсли;
КонецЦикла;
МестаОчисткиСсылок = МестаОчисткиСсылок(ПараметрыУдаления, МестаИспользования);
Попытка
Блокировка = Новый БлокировкаДанных();
ЭлементБлокировки = Блокировка.Добавить(Элемент.УдаляемыйСсылка.Метаданные().ПолноеИмя());
ЭлементБлокировки.УстановитьЗначение("Ссылка", Элемент.УдаляемыйСсылка);
Блокировка.Заблокировать();
Объект = Элемент.УдаляемыйСсылка.ПолучитьОбъект();
УдалитьОбъект(Объект);
Исключение
ИнформацияОбОшибке = ИнформацияОбОшибке();
Результат.Сообщения = ДлительныеОперации.СообщенияПользователю(Истина);
Результат.ИнформацияОбОшибке = ИнформацияОбОшибке;
Результат.Код = КодыРезультатаУдаления().ОшибкаПриУдалении;
Возврат Результат;
КонецПопытки;
ОставшиесяМестаИспользования = ОставшиесяМестаИспользованияУдаляемогоОбъекта(
ПараметрыУдаления,
МестаИспользования);
Если ОставшиесяМестаИспользования.Количество() = 0
Или МестаОчисткиСсылок.Количество() = ОставшиесяМестаИспользования.Количество() Тогда
Результат.МестаИспользования = МестаОчисткиСсылок;
Иначе
Результат.МестаИспользования = ОставшиесяМестаИспользования;
Результат.Код = КодыРезультатаУдаления().ЕстьМестаИспользования;
КонецЕсли;
Возврат Результат;
КонецФункции
Процедура УдалитьОбъект(Объект)
Объект.ДополнительныеСвойства.Вставить("НеВыполнятьКонтрольУдаляемых");
Объект.Удалить();
КонецПроцедуры
Функция ЗаписьСуществует(СведенияОМестеИспользования)
МенеджерРегистра = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(СведенияОМестеИспользования.Метаданные.ПолноеИмя());// РегистрСведенийМенеджер, РегистрБухгалтерииМенеджер, РегистрРасчетаМенеджер, РегистрНакопленияМенеджер
Набор = МенеджерРегистра.СоздатьНаборЗаписей();
Для Сч = 0 По Набор.Отбор.Количество() - 1 Цикл
ЭлементОтбора = Набор.Отбор[Сч];
ЭлементОтбора.Установить(СведенияОМестеИспользования.МестоИспользования[ЭлементОтбора.Имя]);
КонецЦикла;
Набор.Прочитать();
Возврат Набор.Количество() > 0;
КонецФункции
Функция СсылкаВВедущемИзмерении(СведенияОМестеИспользования)
Результат = Ложь;
МетаданныеМестаИспользования = СведенияОМестеИспользования.Метаданные;
Контейнер = Новый Структура("Измерения", Новый Массив);
ЗаполнитьЗначенияСвойств(Контейнер, МетаданныеМестаИспользования);
Измерения = Контейнер.Измерения; // КоллекцияОбъектовМетаданных
Для каждого Измерение Из Измерения Цикл
Контейнер = Новый Структура();
Контейнер.Вставить("Ведущее", Ложь);
Контейнер.Вставить(Измерение.Имя);
ЗаполнитьЗначенияСвойств(Контейнер, Измерение);
ЗаполнитьЗначенияСвойств(Контейнер, СведенияОМестеИспользования.МестоИспользования);
Если Контейнер.Ведущее
И Контейнер[Измерение.Имя] = СведенияОМестеИспользования.УдаляемыйСсылка Тогда
Результат = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
// Параметры:
// ПараметрыУдаления - Структура
// Пакет - см. ПакетУдаляемыхОбъектов
//
// Возвращаемое значение:
// см. МестаИспользования
//
Функция МестаИспользованияЭлементовПакета(ПараметрыУдаления, Пакет)
Результат = МестаИспользования();
УстановитьПривилегированныйРежим(Истина);
ПараметрыПоискаМестИспользования = ОбщегоНазначения.ПараметрыПоискаМестИспользования();
ПараметрыПоискаМестИспользования.ОтменаИсключенийПоискаСсылок = ОтменаИсключенийПоискаСсылокПриУдаленииОбъектов();
МестаИспользования = ОбщегоНазначения.МестаИспользования(Пакет.ВыгрузитьКолонку("УдаляемыйСсылка"),,ПараметрыПоискаМестИспользования);
МестаИспользования.Колонки[0].Имя = "УдаляемыйСсылка";
МестаИспользования.Колонки[1].Имя = "МестоИспользования";
МестаИспользования.Колонки[2].Имя = "Метаданные";
ОбщегоНазначенияКлиентСервер.ДополнитьТаблицу(МестаИспользования, Результат);
Возврат Результат;
КонецФункции
// Параметры:
// Пакет - см. ПакетУдаляемыхОбъектов
// ДочерниеПодчиненныеЭлементы - см. ДочерниеПодчиненныеЭлементы
//
Процедура ДополнитьПакетДочернимиИПодчиненнымиЭлементами(Пакет, ОсновнойЭлемент, ДочерниеПодчиненныеЭлементы, Исключения)
Для Каждого ОписаниеЭлемента Из ДочерниеПодчиненныеЭлементы Цикл
Если Пакет.Найти(ОписаниеЭлемента.Элемент, "УдаляемыйСсылка") <> Неопределено
ИЛИ Исключения.Найти(ОписаниеЭлемента.Элемент, "УдаляемыйСсылка") <> Неопределено Тогда
Продолжить;
КонецЕсли;
ЭлементПакета = Пакет.Добавить();
ЭлементПакета.ОсновнойЭлементСсылка = ОсновнойЭлемент;
ЭлементПакета.УдаляемыйСсылка = ОписаниеЭлемента.Элемент;
ЭлементПакета.ДочерниеПодчиненныеОбъекты = ОписаниеЭлемента.ДочерниеЭлементы;
КонецЦикла;
КонецПроцедуры
// Параметры:
// ПараметрыУдаления - см. ПараметрыУдаления
//
Процедура ОповеститьОПрогрессе(ПараметрыВыполнения)
ТекущееВремя = ТекущаяУниверсальнаяДатаВМиллисекундах();
Если ПараметрыВыполнения.ЭтоРегламентноеЗадание
ИЛИ ТекущееВремя - ПараметрыВыполнения.ВремяОповещения <= ПараметрыВыполнения.ПериодОповещения Тогда
Возврат;
КонецЕсли;
ПараметрыВыполнения.Всего = ПараметрыВыполнения.КоличествоУдаляемых;
ОтметитьПрогрессОбходаКоллекции(ПараметрыВыполнения, "ПользовательскиеОбъекты");
ПараметрыВыполнения.ВремяОповещения = ТекущееВремя;
КонецПроцедуры
#КонецОбласти
#Область ФильтрыКоллекций
// Параметры:
// Пакет - см. ПакетУдаляемыхОбъектов
// МестаИспользования - см. МестаИспользования
//
// Возвращаемое значение:
// см. ПакетУдаляемыхОбъектов
//
Функция ЦиклическиеСсылки(Пакет, МестаИспользования)
Результат = СсылкиТолькоНаЭлементыВнутриПакета(Пакет, МестаИспользования);
КоличествоВПакете = Пакет.Количество();
Пока (Результат[0].Количество() <> КоличествоВПакете) Цикл
КоличествоВПакете = Результат[0].Количество();
Результат = СсылкиТолькоНаЭлементыВнутриПакета(Результат[0], Результат[1]);
КонецЦикла;
Возврат Результат[0];
КонецФункции
// Параметры:
// ПараметрыУдаления - Структура:
// * РазмерПакета - Число
// * ИсключенияПоискаСсылок - Массив
// МестаИспользования - см. МестаИспользованияЭлементовПакета
//
// Возвращаемое значение:
// см. МестаИспользования
//
Функция ОставшиесяМестаИспользованияУдаляемогоОбъекта(ПараметрыУдаления, МестаИспользования, СсылкаИсключение = Неопределено)
Результат = МестаИспользования.СкопироватьКолонки();
Для Каждого СведенияОМестеИспользования Из МестаИспользования Цикл
ЭтоСсылка = СведенияОМестеИспользования.МестоИспользования <> Неопределено
И ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(СведенияОМестеИспользования.МестоИспользования, "ВерсияДанных");
ЭтоКонстанта = Метаданные.Константы.Содержит(СведенияОМестеИспользования.Метаданные);
Если ЭтоСсылка
И (НЕ ОбъектУдален(СведенияОМестеИспользования.МестоИспользования)
ИЛИ СведенияОМестеИспользования.МестоИспользования = СсылкаИсключение)
И НЕ СведенияОМестеИспользования.ЭтоСлужебныеДанные Тогда
ЗаполнитьЗначенияСвойств(Результат.Добавить(), СведенияОМестеИспользования);
КонецЕсли;
Если ОбщегоНазначения.ЭтоПоследовательность(СведенияОМестеИспользования.Метаданные) Тогда
// Если ссылка есть в таблице границ, но больше её нигде нет, то данные можно удалить.
Продолжить;
КонецЕсли;
Если НЕ ЭтоСсылка
И НЕ ЭтоКонстанта
И ЗаписьСуществует(СведенияОМестеИспользования)
И НЕ СведенияОМестеИспользования.ЭтоСлужебныеДанные
И НЕ СсылкаВВедущемИзмерении(СведенияОМестеИспользования) Тогда
ЗаполнитьЗначенияСвойств(Результат.Добавить(), СведенияОМестеИспользования);
КонецЕсли;
Если НЕ ЭтоСсылка
И ЭтоКонстанта
И СведенияОМестеИспользования.МестоИспользования = Неопределено Тогда
ЗаполнитьЗначенияСвойств(Результат.Добавить(), СведенияОМестеИспользования);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция МестаОчисткиСсылок(ПараметрыУдаления, МестаИспользования)
Результат = МестаИспользования();
Если Не ПараметрыУдаления.ОчищатьСсылкиВМестахИспользования Тогда
Возврат Результат;
КонецЕсли;
МестаИспользования.Сортировать("Метаданные");
Для Каждого СведенияОМестеИспользования Из МестаИспользования Цикл
ТипМестаИспользования = ТипЗнч(СведенияОМестеИспользования.МестоИспользования);
ЭтоСсылка = ОбщегоНазначения.ЭтоСсылка(ТипМестаИспользования);
Если ЭтоСсылка
И НЕ ОбъектУдален(СведенияОМестеИспользования.МестоИспользования)
И ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СведенияОМестеИспользования.МестоИспользования, "ПометкаУдаления")
И Не СведенияОМестеИспользования.ЭтоСлужебныеДанные Тогда
ЗаполнитьЗначенияСвойств(Результат.Добавить(), СведенияОМестеИспользования);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция СсылкиТолькоНаЭлементыВнутриПакета(Пакет, МестаИспользования)
Результат = Новый Массив;
НовыйПакет = ПакетУдаляемыхОбъектов();
МестаИспользованияКандидатов = МестаИспользования();
Для Каждого Элемент Из Пакет Цикл
Если Элемент.РезультатУдаления <> КодыРезультатаУдаления().ЕстьМестаИспользования
И Элемент.РезультатУдаления <> КодыРезультатаУдаления().ЕстьДочерниеПодчиненныеЭлементы Тогда
Продолжить;
КонецЕсли;
МестаИспользованияЭлемента = МестаИспользования.Скопировать(Новый Структура("УдаляемыйСсылка", Элемент.УдаляемыйСсылка), "МестоИспользования");
Если ИсточникаПодмножествоПриемника(Пакет, МестаИспользованияЭлемента, "УдаляемыйСсылка", "МестоИспользования") ИЛИ МестаИспользования.Количество() = 0 Тогда
ЗаполнитьЗначенияСвойств(НовыйПакет.Добавить(), Элемент);
Для Каждого Элемент Из МестаИспользованияЭлемента Цикл
ЗаполнитьЗначенияСвойств(МестаИспользованияКандидатов.Добавить(), Элемент);
КонецЦикла;
КонецЕсли;
КонецЦикла;
Результат.Добавить(НовыйПакет);
Результат.Добавить(МестаИспользования);
Возврат Результат;
КонецФункции
#КонецОбласти
#Область ОбработчикиСобытийКонкурентногоОбновления
Процедура ПослеОбработкиПакета(ПараметрыУдаления, Идентификатор)
УдалениеПомеченныхОбъектовСлужебный.СнятьБлокировкуИспользованияУдаляемыхОбъектов(Идентификатор);
ПараметрыСеанса.ВыполняетсяУдалениеОбъектов = Ложь;
КонецПроцедуры
Процедура ПередОбработкойПакета(Пакет, Идентификатор)
ПараметрыСеанса.ВыполняетсяУдалениеОбъектов = Истина;
УдалениеПомеченныхОбъектовСлужебный.УстановитьБлокировкуИспользованияУдаляемыхОбъектов(Пакет, Идентификатор);
КонецПроцедуры
#КонецОбласти
#Область Конструкторы
// Параметры:
// УдаляемыеОбъекты - Массив из ЛюбаяСсылка
// Параметры - Структура
//
// Возвращаемое значение:
// Структура:
// * КоличествоНеудаленных - Число
// * ПовторноУдаляемые - Массив из ЛюбаяСсылка
// * ПрепятствующиеУдалению - ТаблицаЗначений:
// ** УдаляемыйСсылка - ЛюбаяСсылка
// ** МестоИспользования - ЛюбаяСсылка
// ** ОбнаруженныйСтатус - Строка
// ** ПодробноеОписаниеОшибки - Строка
// ** ОписаниеОшибки - Строка
// * НеУдаленные - Массив
// * Удаленные - Массив
// * ПользовательскиеОбъекты - Массив
// * Монопольно - Булево
// * ОчищатьСсылкиВМестахИспользования - Булево
// * КешИнформацииОТипах - Соответствие
// * РазмерПакета - Число
// * ИсключенияПоискаСсылок - Массив из ОбъектМетаданных
// * ИдентификаторЗадания - УникальныйИдентификатор
// * ВремяОповещения - Число - время последнего оповещения в миллисекундах
// * ПериодОповещения - Число - количество миллисекунд между оповещениями
//
Функция ПараметрыУдаления(УдаляемыеОбъекты, Параметры)
ИсключенияПоискаСсылок = ИсключенияПоискаСсылокПриУдалении();
ПараметрыОбработки = Новый Структура;
ПараметрыОбработки.Вставить("Монопольно",
ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(Параметры, "Монопольно", Ложь));
ПараметрыОбработки.Вставить("ИсключающиеПравила", Новый Соответствие);
ПараметрыОбработки.Вставить("ИсключенияПоискаСсылок", ИсключенияПоискаСсылок);
ПараметрыОбработки.Вставить("РазмерПакета", ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(Параметры,
"РазмерПакета", 100));
ПараметрыОбработки.Вставить("КешИнформацииОТипах", Новый Соответствие);
ПараметрыОбработки.Вставить("ОчищатьСсылкиВМестахИспользования", ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(
Параметры, "ОчищатьСсылкиВМестахИспользования", Ложь));
ПараметрыОбработки.Вставить("ПользовательскиеОбъекты", Новый Массив);
ПрепятствующиеУдалению = Новый ТаблицаЗначений;
ПрепятствующиеУдалению.Колонки.Добавить("УдаляемыйСсылка");
ПрепятствующиеУдалению.Колонки.Добавить("МестоИспользования");
ПрепятствующиеУдалению.Колонки.Добавить("ОбнаруженныйСтатус", Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(10)));
ПрепятствующиеУдалению.Колонки.Добавить("ОписаниеОшибки", Новый ОписаниеТипов("Строка"));
ПрепятствующиеУдалению.Колонки.Добавить("ПодробноеОписаниеОшибки", Новый ОписаниеТипов("Строка"));
ТипыКолонкиМетаданные = Новый Массив;
ТипыКолонкиМетаданные.Добавить("ОбъектМетаданных");
ТипыКолонкиМетаданные.Добавить("Неопределено");
ПрепятствующиеУдалению.Колонки.Добавить("Метаданные", Новый ОписаниеТипов(ТипыКолонкиМетаданные));
ПрепятствующиеУдалению.Индексы.Добавить("УдаляемыйСсылка");
ПрепятствующиеУдалению.Индексы.Добавить("МестоИспользования");
ПараметрыОбработки.Вставить("Удаленные", Новый Массив);
ПараметрыОбработки.Вставить("НеУдаленные", Новый Массив);
ПараметрыОбработки.Вставить("ПрепятствующиеУдалению", ПрепятствующиеУдалению);
ПараметрыОбработки.Вставить("ПовторноУдаляемые", Новый Массив);
ПараметрыОбработки.Вставить("КоличествоУдаляемых", УдаляемыеОбъекты.Количество());
ПараметрыОбработки.Вставить("КоличествоНеудаленных", 0);
ПараметрыОбработки.Вставить("КоличествоОбработанных", 0);
ПараметрыОбработки.Вставить("Всего", 0);
ПараметрыОбработки.Вставить("Номер", 0);
ПараметрыОбработки.Вставить("ИдентификаторЗадания", "");
// Уменьшение расхода памяти rmngr на хранение сообщений
ПараметрыОбработки.Вставить("ВремяОповещения", 0);
ПараметрыОбработки.Вставить("ПериодОповещения", 60000); // миллисекунды
ПараметрыОбработки.Вставить("ЭтоРегламентноеЗадание", ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(
Параметры, "ЭтоРегламентноеЗадание", Ложь));
Возврат ПараметрыОбработки;
КонецФункции
Функция ИсключенияПоискаСсылокПриУдалении()
ИсключенияПоискаСсылок = ОбщегоНазначения.ИсключенияПоискаСсылок();
Для Каждого Элемент Из УдалениеПомеченныхОбъектовСлужебный.ИсключенияПоискаСсылокРазрешающихУдаление() Цикл
ИсключенияПоискаСсылок.Вставить(Элемент, "*");
КонецЦикла;
ИсключенияПоискаСсылок.Удалить(Метаданные.Справочники.ВнешниеПользователи);
Возврат ИсключенияПоискаСсылок;
КонецФункции
// Возвращаемое значение:
// Структура:
// * МестаИспользования - см. ПакетУдаляемыхОбъектов
// * НеудаленныеОбъекты - см. МестаИспользования
// * УдаленныеОбъекты - Массив из ЛюбаяСсылка
//
Функция РезультатОбработки()
РезультатОбработкиПакета = Новый Структура();
РезультатОбработкиПакета.Вставить("УдаленныеОбъекты", Новый Массив);
РезультатОбработкиПакета.Вставить("НеудаленныеОбъекты", ПакетУдаляемыхОбъектов());
РезультатОбработкиПакета.Вставить("МестаИспользования", МестаИспользования());
РезультатОбработкиПакета.Вставить("МестаОчисткиСсылок", МестаИспользования());
Возврат РезультатОбработкиПакета
КонецФункции
// Возвращаемое значение:
// ТаблицаЗначений:
// * УдаляемыйСсылка - ЛюбаяСсылка
// * МестоИспользования - ЛюбаяСсылка
// * Метаданные - ОбъектМетаданных
// * ЭтоСлужебныеДанные - Булево
//
Функция МестаИспользования() Экспорт
Таблица = Новый ТаблицаЗначений();
Таблица.Колонки.Добавить("УдаляемыйСсылка");
Таблица.Колонки.Добавить("МестоИспользования");
Таблица.Колонки.Добавить("Метаданные");
Таблица.Колонки.Добавить("ЭтоСлужебныеДанные", Новый ОписаниеТипов("Булево"));
Таблица.Индексы.добавить("УдаляемыйСсылка");
Таблица.Индексы.добавить("МестоИспользования");
Возврат Таблица;
КонецФункции
// Возвращаемое значение:
// ТаблицаЗначений:
// * УдаляемыйСсылка - ЛюбаяСсылка
// * ЕстьДочерниеОбъекты - Булево
// * ЕстьПодчиненныеОбъекты - Булево
// * ИнформацияОбОшибке - ИнформацияОбОшибке
// * Сообщения - Строка
// * РезультатУдаления - Число
// * ДочерниеПодчиненныеОбъекты - см. ТаблицаДочернихПодчиненныхЭлементов
// * ЭтоОсновнойОбъект - Булево
//
Функция ПакетУдаляемыхОбъектов()
Пакет = Новый ТаблицаЗначений;
Пакет.Колонки.Добавить("УдаляемыйСсылка");
Пакет.Колонки.Добавить("ЕстьДочерниеОбъекты", , Новый ОписаниеТипов("Булево"));
Пакет.Колонки.Добавить("ЕстьПодчиненныеОбъекты", Новый ОписаниеТипов("Булево"));
Пакет.Колонки.Добавить("ИнформацияОбОшибке", Новый ОписаниеТипов("ИнформацияОбОшибке"));
Пакет.Колонки.Добавить("Сообщения", Новый ОписаниеТипов("Строка"));
Пакет.Колонки.Добавить("РезультатУдаления", Новый ОписаниеТипов("Число"));
Пакет.Колонки.Добавить("ДочерниеПодчиненныеОбъекты", Новый ОписаниеТипов("ТаблицаЗначений"));
Пакет.Колонки.Добавить("ЭтоОсновнойОбъект", Новый ОписаниеТипов("Булево"));
Пакет.Колонки.Добавить("ОсновнойЭлементСсылка");
Возврат Пакет;
КонецФункции
Функция КодыРезультатаУдаления()
ТипыОшибок = Новый Структура;
ТипыОшибок.Вставить("Успешно", -1);
ТипыОшибок.Вставить("ЕстьМестаИспользования", 0);
ТипыОшибок.Вставить("ОшибкаПриУдалении", 1);
ТипыОшибок.Вставить("ЕстьДочерниеПодчиненныеЭлементы", 2);
ТипыОшибок.Вставить("ЕстьДочерниеПодчиненныеЭлементыНепомеченныеНаУдаление", 3);
ТипыОшибок.Вставить("НеПомеченНаУдаление", 4);
Возврат ТипыОшибок;
КонецФункции
// Параметры:
// МассивУдаляемыхОбъектов - Массив из ЛюбаяСсылка
// СведенияОМетаданных - ТаблицаЗначений:
// * Метаданные - ОбъектМетаданных
// * Иерархический - Булево
// * Приоритет - Число
// * Тип - Тип
//
// Возвращаемое значение:
// ТаблицаЗначений:
// * УдаляемыйСсылка - ЛюбаяСсылка
// * Приоритет - Число
// * Тип - Тип
//
Функция УдаляемыеОбъекты(МассивУдаляемыхОбъектов, СведенияОМетаданных)
УдаляемыеОбъекты = Новый ТаблицаЗначений;
УдаляемыеОбъекты.Колонки.Добавить("УдаляемыйСсылка");
УдаляемыеОбъекты.Колонки.Добавить("Приоритет", Новый ОписаниеТипов("Число"));
УдаляемыеОбъекты.Колонки.Добавить("КоличествоПопыток", Новый ОписаниеТипов("Число"));
УдаляемыеОбъекты.Колонки.Добавить("Тип", Новый ОписаниеТипов("Тип"));
УдаляемыеОбъекты.Индексы.Добавить("УдаляемыйСсылка");
КоличествоПопытокОбъектов = РегистрыСведений.НеудаленныеОбъекты.КоличествоПопытокОбъектов(МассивУдаляемыхОбъектов);
Для Каждого Элемент Из МассивУдаляемыхОбъектов Цикл
ТипЭлемента = ТипЗнч(Элемент);
ЭлементОчереди = УдаляемыеОбъекты.Добавить();
ЭлементОчереди.УдаляемыйСсылка = Элемент;
ЭлементОчереди.Приоритет = СведенияОМетаданных.НайтиСтроки(Новый Структура("Тип", ТипЭлемента))[0].Приоритет;
ЭлементОчереди.Тип = ТипЭлемента;
КоличествоПопыток = КоличествоПопытокОбъектов.Найти(Элемент, "УдаляемыйСсылка");
ЭлементОчереди.КоличествоПопыток = ?(КоличествоПопыток = Неопределено, 0, КоличествоПопыток.КоличествоПопыток);
КонецЦикла;
УдаляемыеОбъекты.Сортировать("КоличествоПопыток, Приоритет");
Возврат УдаляемыеОбъекты;
КонецФункции
#КонецОбласти
#Область ФормированиеСведенийОМетаданных
// Параметры:
// ПараметрыУдаления - Структура
// УдаляемыеОбъекты - Массив из ЛюбаяСсылка
//
// Возвращаемое значение:
// ТаблицаЗначений:
// * Метаданные - ОбъектМетаданных
// * Иерархический - Булево
// * Приоритет - Число
// * Тип - Тип
// * ОписаниеПодчиненныхОбъектов - ТаблицаЗначений
//
Функция СведенияОМетаданных(ПараметрыУдаления, УдаляемыеОбъекты)
СведенияОМетаданных = Новый ТаблицаЗначений();
СведенияОМетаданных.Колонки.Добавить("Метаданные", Новый ОписаниеТипов("ОбъектМетаданных"));
СведенияОМетаданных.Колонки.Добавить("Иерархический", Новый ОписаниеТипов("Булево"));
СведенияОМетаданных.Колонки.Добавить("Приоритет", Новый ОписаниеТипов("Число"));
СведенияОМетаданных.Колонки.Добавить("ЕстьПодчиненныеОбъекты", Новый ОписаниеТипов("Булево"));
СведенияОМетаданных.Колонки.Добавить("Тип", Новый ОписаниеТипов("Тип"));
СведенияОМетаданных.Колонки.Добавить("ОписаниеПодчиненныхОбъектов", Новый ОписаниеТипов("ТаблицаЗначений"));
СведенияОМетаданных.Индексы.Добавить("Тип");
СведенияОМетаданных.Индексы.Добавить("Метаданные");
ЗаполнитьСведенияОМетаданных(СведенияОМетаданных, УдаляемыеОбъекты);
Возврат СведенияОМетаданных;
КонецФункции
// Возвращаемое значение:
// ТаблицаЗначений:
// * Тип - Тип
// * ПодчиненныеМетаданные - ОбъектМетаданных
// * Реквизиты - Массив
//
Функция ТаблицаПоискаПодчиненныхОбъектов()
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Тип", Новый ОписаниеТипов("Тип"));
Таблица.Колонки.Добавить("Метаданные", Новый ОписаниеТипов("ОбъектМетаданных"));
Таблица.Колонки.Добавить("ИмяРеквизита", Новый ОписаниеТипов("Строка"));
Возврат Таблица;
КонецФункции
Процедура ЗаполнитьСведенияОМетаданных(СведенияОМетаданных, УдаляемыеОбъекты)
ПодчиненныеОбъекты = ОбщегоНазначения.ПодчиненныеОбъекты();
Для Каждого Элемент Из УдаляемыеОбъекты Цикл
Если СведенияОМетаданных.Найти(Элемент.Метаданные(), "Метаданные") = Неопределено Тогда
ИнформацияОМетаданных = СведенияОМетаданных.Добавить();
ИнформацияОМетаданных.Метаданные = Элемент.Метаданные();
ИнформацияОМетаданных.Приоритет = 0;
ИнформацияОМетаданных.Тип = ТипЗнч(Элемент);
ИнформацияОМетаданных.ОписаниеПодчиненныхОбъектов = ТаблицаПоискаПодчиненныхОбъектов();
Кеш = Новый Структура("Иерархический");
Если ОбщегоНазначения.ЭтоПланСчетов(ИнформацияОМетаданных.Метаданные) Тогда
Кеш.Иерархический = Истина;
Иначе
ЗаполнитьЗначенияСвойств(Кеш, ИнформацияОМетаданных.Метаданные);
КонецЕсли;
ИнформацияОМетаданных.Иерархический = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(Кеш, "Иерархический", Ложь);
КонецЕсли;
КонецЦикла;
Для Каждого ОбъектМетаданных Из Метаданные.Справочники Цикл
ОписаниеПодчиненногоОбъекта = ПодчиненныеОбъекты.Найти(ОбъектМетаданных, "ПодчиненныйОбъект");
Если ОписаниеПодчиненногоОбъекта = Неопределено
И ОбъектМетаданных.Владельцы.Количество() > 0 Тогда
ОписаниеПодчиненногоОбъекта = ПодчиненныеОбъекты.Добавить();
ОписаниеПодчиненногоОбъекта.ПодчиненныйОбъект = ОбъектМетаданных;
ОписаниеПодчиненногоОбъекта.ПоляСвязей = "Владелец";
ИначеЕсли ОбъектМетаданных.Владельцы.Количество() > 0 Тогда
ОписаниеПодчиненногоОбъекта.ПоляСвязей = ?(СтрНайти(ОписаниеПодчиненногоОбъекта.ПоляСвязей, "Владелец") > 0,
ОписаниеПодчиненногоОбъекта.ПоляСвязей,
ОписаниеПодчиненногоОбъекта.ПоляСвязей + ",Владелец");
КонецЕсли;
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.СтандартныеРеквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.Реквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ОбъектМетаданных.ТабличныеЧасти);
КонецЦикла;
Для Каждого ОбъектМетаданных Из Метаданные.Документы Цикл
ОписаниеПодчиненногоОбъекта = ПодчиненныеОбъекты.Найти(ОбъектМетаданных, "ПодчиненныйОбъект");
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.СтандартныеРеквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.Реквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ОбъектМетаданных.ТабличныеЧасти);
КонецЦикла;
Для Каждого ОбъектМетаданных Из Метаданные.ПланыВидовХарактеристик Цикл
ОписаниеПодчиненногоОбъекта = ПодчиненныеОбъекты.Найти(ОбъектМетаданных, "ПодчиненныйОбъект");
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.СтандартныеРеквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.Реквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ОбъектМетаданных.ТабличныеЧасти);
КонецЦикла;
Для Каждого ОбъектМетаданных Из Метаданные.ПланыВидовРасчета Цикл
ОписаниеПодчиненногоОбъекта = ПодчиненныеОбъекты.Найти(ОбъектМетаданных, "ПодчиненныйОбъект");
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.СтандартныеРеквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.Реквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ОбъектМетаданных.СтандартныеТабличныеЧасти);
ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ОбъектМетаданных.ТабличныеЧасти);
КонецЦикла;
Для Каждого ОбъектМетаданных Из Метаданные.ПланыСчетов Цикл
ОписаниеПодчиненногоОбъекта = ПодчиненныеОбъекты.Найти(ОбъектМетаданных, "ПодчиненныйОбъект");
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.СтандартныеРеквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.Реквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ОбъектМетаданных.СтандартныеТабличныеЧасти);
ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ОбъектМетаданных.ТабличныеЧасти);
КонецЦикла;
Для Каждого ОбъектМетаданных Из Метаданные.БизнесПроцессы Цикл
ОписаниеПодчиненногоОбъекта = ПодчиненныеОбъекты.Найти(ОбъектМетаданных, "ПодчиненныйОбъект");
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.СтандартныеРеквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.Реквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ОбъектМетаданных.ТабличныеЧасти);
КонецЦикла;
Для Каждого ОбъектМетаданных Из Метаданные.Задачи Цикл
ОписаниеПодчиненногоОбъекта = ПодчиненныеОбъекты.Найти(ОбъектМетаданных, "ПодчиненныйОбъект");
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.СтандартныеРеквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.РеквизитыАдресации, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ОбъектМетаданных.Реквизиты, ОписаниеПодчиненногоОбъекта);
ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ОбъектМетаданных.ТабличныеЧасти);
КонецЦикла;
КонецПроцедуры
Процедура ЗарегистрироватьРеквизитыТабличныхЧастей(СведенияОМетаданных, ТабличныеЧасти)
Для Каждого ТабличнаяЧасть Из ТабличныеЧасти Цикл
Если ТипЗнч(ТабличнаяЧасть) = Тип("ОбъектМетаданных") Тогда
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ТабличнаяЧасть.Реквизиты);
Иначе
ЗарегистрироватьРеквизиты(СведенияОМетаданных, ТабличнаяЧасть.СтандартныеРеквизиты);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ЗарегистрироватьРеквизиты(СведенияОМетаданных, КоллекцияРеквизитов, ОписаниеПодчиненногоОбъекта = Неопределено)
Для Каждого Реквизит Из КоллекцияРеквизитов Цикл
ЗарегистрироватьРеквизит(СведенияОМетаданных, Реквизит, ОписаниеПодчиненногоОбъекта);
КонецЦикла;
КонецПроцедуры
Процедура ЗарегистрироватьРеквизит(СведенияОМетаданных, Реквизит,
ОписаниеПодчиненногоОбъекта)
ИменаПолейСвязи = ?(ЗначениеЗаполнено(ОписаниеПодчиненногоОбъекта), СтрРазделить(ОписаниеПодчиненногоОбъекта.ПоляСвязей, ","), Новый Массив);
ЭтоПолеСвязиПодчиненногоОбъекта = ИменаПолейСвязи.Найти(Реквизит.Имя) <> Неопределено;
Для Каждого Тип Из Реквизит.Тип.Типы() Цикл
Если УдалениеПомеченныхОбъектовСлужебный.ЭтоПростойТип(Тип) Тогда
Продолжить;
КонецЕсли;
НайденныеСведения = СведенияОМетаданных.Найти(Тип, "Тип");
Если НайденныеСведения <> Неопределено Тогда
НайденныеСведения.Приоритет = НайденныеСведения.Приоритет + 1;
Если ЭтоПолеСвязиПодчиненногоОбъекта Тогда
Связь = НайденныеСведения.ОписаниеПодчиненныхОбъектов.Добавить();
Связь.Тип = Тип;
Связь.Метаданные = ОписаниеПодчиненногоОбъекта.ПодчиненныйОбъект;
Связь.ИмяРеквизита = Реквизит.Имя;
НайденныеСведения.ЕстьПодчиненныеОбъекты = Истина;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
#КонецОбласти
#КонецОбласти
#Область МонопольноеУдаление
// Основная механика удаления помеченных объектов.
//
Процедура УдалитьПомеченныеОбъектыМонопольно(УдаляемыеОбъекты, ПараметрыВыполнения)
ПараметрыВыполнения.ИсключенияПоискаСсылок = ОбщегоНазначения.ИсключенияПоискаСсылок();
Для каждого ОтменаИсключения Из ОтменаИсключенийПоискаСсылокПриУдаленииОбъектов() Цикл
ПараметрыВыполнения.ИсключенияПоискаСсылок.Удалить(ОтменаИсключения);
КонецЦикла;
Если Не ПараметрыВыполнения.Свойство("ИсключающиеПравила") Тогда
ПараметрыВыполнения.Вставить("ИсключающиеПравила", Новый Соответствие); // Кэш правил исключений поиска.
КонецЕсли;
СведенияОМетаданных = СведенияОМетаданных(ПараметрыВыполнения, УдаляемыеОбъекты);
ПодчиненныеОбъекты = Новый Массив;
Для Сч = -(УдаляемыеОбъекты.Количество() - 1) По 0 Цикл
УдаляемыйОбъект = УдаляемыеОбъекты[-Сч];
Если НЕ ОбъектУдален(УдаляемыйОбъект)
И НЕ ОбщегоНазначения.ЗначениеРеквизитаОбъекта(УдаляемыйОбъект, "ПометкаУдаления") Тогда
ПричинаНеудаления = Новый Структура;
ПричинаНеудаления.Вставить("УдаляемыйСсылка", УдаляемыйОбъект);
ПричинаНеудаления.Вставить("МестоИспользования", НСтр("ru='Удаляемый объект не помечен на удаление'"));
ПричинаНеудаления.Вставить("ОбнаруженныйМетаданные");
ЗаписатьПричинуВРезультат(ПараметрыВыполнения, ПричинаНеудаления);
УдаляемыеОбъекты.Удалить(-Сч);
Продолжить;
КонецЕсли;
ИнформацияОМетаданных = СведенияОМетаданных.Найти(ТипЗнч(УдаляемыйОбъект), "Тип");
ИнформацияОМетаданных.Иерархический = Ложь;// Выполняем поиск только подчиненных элементов
ДочерниеПодчиненныеОбъекты = ДочерниеПодчиненныеЭлементы(
УдаляемыйОбъект, ИнформацияОМетаданных);
Для Каждого ПодчиненныйОбъект Из ДочерниеПодчиненныеОбъекты Цикл
Если ПодчиненныйОбъект.ПометкаУдаления ИЛИ ПодчиненныйОбъект.ТипЭлемента = "Подчиненный" Тогда
ПодчиненныеОбъекты.Добавить(ПодчиненныйОбъект.Элемент);
КонецЕсли;
КонецЦикла;
КонецЦикла;
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(
УдаляемыеОбъекты, ПодчиненныеОбъекты);
Контекст = Новый Структура;
СтандартнаяОбработка = Истина;
ПередУдалениемГруппыОбъектов(Контекст, УдаляемыеОбъекты, СтандартнаяОбработка);
Пока УдаляемыеОбъекты.Количество() > 0 Цикл
ПрепятствующиеУдалению = Новый ТаблицаЗначений;
// Попытка удалить с контролем ссылочной целостности.
УстановитьПривилегированныйРежим(Истина);
Попытка
УдалитьОбъекты(УдаляемыеОбъекты, Истина, ПрепятствующиеУдалению);
Исключение
ИнформацияОбОшибке = ИнформацияОбОшибке();
ЗаписатьПредупреждение(Неопределено, ИнформацияОбОшибке);
ОписаниеОшибки = КраткоеПредставлениеОшибки(ИнформацияОбОшибке);
Сообщения = ДлительныеОперации.СообщенияПользователю(Истина);
Для каждого Сообщение Из Сообщения Цикл
ОписаниеОшибки = ОписаниеОшибки + Символы.ПС + Символы.ПС + Сообщение.Текст;
КонецЦикла;
ПослеУдаленияГруппыОбъектов(Контекст, Ложь);
ВызватьИсключение ОписаниеОшибки;
КонецПопытки;
УстановитьПривилегированныйРежим(Ложь);
Если ПрепятствующиеУдалению.Колонки.Количество() < 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'"), КоличествоУдаляемыхЭлементов));
КонецПроцедуры
Функция ОтменаИсключенийПоискаСсылокПриУдаленииОбъектов()
ОтменаИсключений = Новый Массив;
ОтменаИсключений.Добавить(Метаданные.Справочники.ВнешниеПользователи);
Возврат ОтменаИсключений;
КонецФункции
#КонецОбласти
#КонецЕсли