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