1850 lines
128 KiB
Plaintext
1850 lines
128 KiB
Plaintext
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// 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'"), КоличествоУдаляемыхЭлементов));
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция ОтменаИсключенийПоискаСсылокПриУдаленииОбъектов()
|
||
|
||
ОтменаИсключений = Новый Массив;
|
||
ОтменаИсключений.Добавить(Метаданные.Справочники.ВнешниеПользователи);
|
||
Возврат ОтменаИсключений;
|
||
|
||
КонецФункции
|
||
|
||
#КонецОбласти
|
||
|
||
#КонецЕсли
|