[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало процедура `УстановитьНачальнуюДатуЗапретаИзменения`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

Процедура УстановитьНачальнуюДатуЗапретаИзменения()
Экспорт

	УстановитьПривилегированныйРежим(Истина);

	НаборЗаписей = РегистрыСведений.ДатыЗапретаИзменения.СоздатьНаборЗаписей();
	НаборЗаписей.Прочитать();

	Если НаборЗаписей.Количество() <> 0 Тогда
		Возврат;
	КонецЕсли;

	ПустойРаздел = ПустаяСсылка(Тип("ПланВидовХарактеристикСсылка.РазделыДатЗапретаИзменения"));
    // TODO: допиши оставшуюся часть

[Assistant]
Процедура УстановитьНачальнуюДатуЗапретаИзменения() Экспорт

	УстановитьПривилегированныйРежим(Истина);

	НаборЗаписей = РегистрыСведений.ДатыЗапретаИзменения.СоздатьНаборЗаписей();
	НаборЗаписей.Прочитать();

	Если НаборЗаписей.Количество() <> 0 Тогда
		Возврат;
	КонецЕсли;

	ПустойРаздел = ПустаяСсылка(Тип("ПланВидовХарактеристикСсылка.РазделыДатЗапретаИзменения"));

	Запись = НаборЗаписей.Добавить();
	Запись.Пользователь = Перечисления.ВидыНазначенияДатЗапрета.ДляВсехПользователей;
	Запись.Раздел       = ПустойРаздел;
	Запись.Объект       = ПустойРаздел;
	Запись.ДатаЗапрета  = '19791231';

	ОбновлениеИнформационнойБазы.ЗаписатьДанные(НаборЗаписей);

КонецПроцедуры

// Обработчик преобразует план видов характеристик разделы дат запрета изменения.

Процедура ОчиститьПредопределенныеЭлементыРазделовДатЗапрета() Экспорт

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ ПЕРВЫЕ 1
	|	ИСТИНА КАК ЗначениеИстина
	|ИЗ
	|	ПланВидовХарактеристик.РазделыДатЗапретаИзменения КАК Разделы
	|ГДЕ
	|	Разделы.ИмяПредопределенныхДанных <> """"";

	Если Запрос.Выполнить().Пустой() Тогда
		Возврат;
	КонецЕсли;

	СвойстваРазделов = СвойстваРазделов();
	ИменаПредопределенных =
		Метаданные.ПланыВидовХарактеристик.РазделыДатЗапретаИзменения.ПолучитьИменаПредопределенных();

	Блокировка = Новый БлокировкаДанных;
	Блокировка.Добавить("ПланВидовХарактеристик.РазделыДатЗапретаИзменения");

	Запрос.Текст =
	"ВЫБРАТЬ
	|	Разделы.Ссылка КАК Ссылка,
	|	Разделы.ИмяПредопределенныхДанных КАК ИмяПредопределенныхДанных
	|ИЗ
	|	ПланВидовХарактеристик.РазделыДатЗапретаИзменения КАК Разделы
	|ГДЕ
	|	Разделы.ИмяПредопределенныхДанных <> """"";

	НачатьТранзакцию();
	Попытка
		Блокировка.Заблокировать();
		ОбновитьРазделыДатЗапретаИзменения();

		Выборка = Запрос.Выполнить().Выбрать();
		Пока Выборка.Следующий() Цикл
			Объект = Выборка.Ссылка.ПолучитьОбъект();
			Если ИменаПредопределенных.Найти(Выборка.ИмяПредопределенныхДанных) <> Неопределено Тогда
				Приставка = "Удалить";
				Если Не СтрНачинаетсяС(Выборка.ИмяПредопределенныхДанных, Приставка) Тогда
					Объект.ПометкаУдаления = Истина;
				Иначе
					ИскомоеИмя = Сред(Выборка.ИмяПредопределенныхДанных, СтрДлина(Приставка) + 1);
					СвойстваРаздела = СвойстваРазделов.Разделы.Получить(ИскомоеИмя); // см. ПланыВидовХарактеристик.РазделыДатЗапретаИзменения.СвойстваРаздела

					Если СвойстваРаздела = Неопределено Тогда
						Объект.ПометкаУдаления = Истина;

					ИначеЕсли Выборка.Ссылка <> СвойстваРаздела.Ссылка Тогда
						Объект.УдалитьНоваяСсылка = СвойстваРаздела.Ссылка;
						Объект.Наименование = "(" + НСтр("ru = 'не используется'") + ") " + СвойстваРаздела.Представление;
					КонецЕсли;
				КонецЕсли;
			ИначеЕсли СвойстваРазделов.Разделы.Получить(Выборка.Ссылка) = Неопределено Тогда
				Объект.ПометкаУдаления = Истина;
			КонецЕсли;
			Объект.ИмяПредопределенныхДанных = "";
			ОбновлениеИнформационнойБазы.ЗаписатьДанные(Объект, Ложь);
		КонецЦикла;
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;

КонецПроцедуры

// Обработчик заменяет разделы дат запрета регистре на новые.

Процедура ЗаменитьРазделыДатЗапретаНаНовые() Экспорт

	Блокировка = Новый БлокировкаДанных;
	Блокировка.Добавить("РегистрСведений.ДатыЗапретаИзменения");

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	Разделы.Ссылка КАК Ссылка,
	|	Разделы.УдалитьНоваяСсылка КАК УдалитьНоваяСсылка
	|ИЗ
	|	ПланВидовХарактеристик.РазделыДатЗапретаИзменения КАК Разделы
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ДатыЗапретаИзменения КАК ДатыЗапретаИзменения
	|		ПО (ДатыЗапретаИзменения.Раздел = Разделы.Ссылка)
	|			И (Разделы.УдалитьНоваяСсылка <> ЗНАЧЕНИЕ(ПланВидовХарактеристик.РазделыДатЗапретаИзменения.ПустаяСсылка))";

	НачатьТранзакцию();
	Попытка
		Блокировка.Заблокировать();
		Выборка = Запрос.Выполнить().Выбрать();
		Пока Выборка.Следующий() Цикл
			СтарыеЗаписи = РегистрыСведений.ДатыЗапретаИзменения.СоздатьНаборЗаписей();
			СтарыеЗаписи.Отбор.Раздел.Установить(Выборка.Ссылка);
			СтарыеЗаписи.Прочитать();
			НовыеЗаписи = РегистрыСведений.ДатыЗапретаИзменения.СоздатьНаборЗаписей();
			НовыеЗаписи.Отбор.Раздел.Установить(Выборка.УдалитьНоваяСсылка);
			НовыеЗаписи.Прочитать();
			Если НовыеЗаписи.Количество() > 0 Тогда
				СтарыеЗаписи.Очистить();
				ОбновлениеИнформационнойБазы.ЗаписатьДанные(СтарыеЗаписи, Ложь);
			Иначе
				Для Каждого СтараяЗапись Из СтарыеЗаписи Цикл
					НоваяЗапись = НовыеЗаписи.Добавить();
					ЗаполнитьЗначенияСвойств(НоваяЗапись, СтараяЗапись);
					НоваяЗапись.Раздел = Выборка.УдалитьНоваяСсылка;
					Если СтараяЗапись.Раздел = СтараяЗапись.Объект Тогда
						НоваяЗапись.Объект = Выборка.УдалитьНоваяСсылка;
					КонецЕсли;
				КонецЦикла;
				СтарыеЗаписи.Очистить();
				ОбновлениеИнформационнойБазы.ЗаписатьДанные(СтарыеЗаписи, Ложь);
				ОбновлениеИнформационнойБазы.ЗаписатьДанные(НовыеЗаписи, Ложь);
			КонецЕсли;
		КонецЦикла;
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;

КонецПроцедуры

// Дополняет настройки для пользователей, групп, узлов и планов обмена.

Процедура ДополнитьНастройкиУказанныхАдресатов() Экспорт

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	ДатыЗапретаИзменения.Пользователь,
	|	МАКСИМУМ(ДатыЗапретаИзменения.Комментарий) КАК Комментарий
	|ИЗ
	|	РегистрСведений.ДатыЗапретаИзменения КАК ДатыЗапретаИзменения
	|
	|СГРУППИРОВАТЬ ПО
	|	ДатыЗапретаИзменения.Пользователь
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	СоставыГруппПользователей.Пользователь КАК Пользователь,
	|	СоставыГруппПользователей.ГруппаПользователей КАК ГруппаПользователей
	|ИЗ
	|	РегистрСведений.СоставыГруппПользователей КАК СоставыГруппПользователей
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ДатыЗапретаИзменения КАК ДатыЗапретаИзменения
	|		ПО СоставыГруппПользователей.ГруппаПользователей = ДатыЗапретаИзменения.Пользователь
	|			И (СоставыГруппПользователей.ГруппаПользователей <> СоставыГруппПользователей.Пользователь)
	|;
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ДатыЗапретаИзменения.Пользователь КАК Пользователь,
	|	ДатыЗапретаИзменения.Раздел КАК Раздел,
	|	ДатыЗапретаИзменения.Объект КАК Объект,
	|	ДатыЗапретаИзменения.ДатаЗапрета КАК ДатаЗапрета,
	|	ДатыЗапретаИзменения.ОписаниеДатыЗапрета КАК ОписаниеДатыЗапрета
	|ИЗ
	|	РегистрСведений.ДатыЗапретаИзменения КАК ДатыЗапретаИзменения";

	Блокировка = Новый БлокировкаДанных;
	Блокировка.Добавить("РегистрСведений.ДатыЗапретаИзменения");

	НачатьТранзакцию();
	Попытка
		Блокировка.Заблокировать();
		РезультатыЗапроса = Запрос.ВыполнитьПакет();
		АдресатыНастроек    = РезультатыЗапроса[0].Выгрузить();
		ГруппыПользователей = РезультатыЗапроса[1].Выгрузить();
		Настройки           = РезультатыЗапроса[2].Выгрузить();
		НаборЗаписей = РегистрыСведений.ДатыЗапретаИзменения.СоздатьНаборЗаписей();
		ДобавитьНастройки(НаборЗаписей, Настройки, АдресатыНастроек, ГруппыПользователей, Истина);
		ДобавитьНастройки(НаборЗаписей, Настройки, АдресатыНастроек, ГруппыПользователей, Ложь);
		ОбновлениеИнформационнойБазы.ЗаписатьНаборЗаписей(НаборЗаписей, Ложь);
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;

КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// Вспомогательные процедуры и функции.

// Для функции ПроверкаДатЗапретаОтключена.


[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало процедура `ОтправитьОповещениеКлиенту`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

Процедура ОтправитьОповещениеКлиенту(ВидОповещения, ПередаваемоеЗначение,
			ФоновоеЗадание = Неопределено, ИдентификаторОсновногоЗадания = Неопределено)
Экспорт

	УстановитьОтключениеБезопасногоРежима(Истина);
	УстановитьПривилегированныйРежим(Истина);

	ЗаписатьСообщенияПользователю = ФоновоеЗадание <> Неопределено И ВидОповещения = "СообщениеПользователю";
	Если ЗаписатьСообщенияПользователю Тогда
		КлючСеансаРодителя = СерверныеОповещения.КлючСеанса();
	Иначе
		КлючСеансаРодителя = СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере(Ложь).Получить(
			"КлючСеансаРодителя");
		Если Не ЗначениеЗаполнено(КлючСеансаРодителя) Тогда
			Возврат;
		КонецЕсли;
		ФоновоеЗадание = ПолучитьТекущийСеансИнформационнойБазы().ПолучитьФоновоеЗадание();
		Если ФоновоеЗадание = Неопределено Тогда
			Возврат;
		КонецЕсли;
		ИдентификаторЗаданияМногопоточногоПроцесса =
			СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере(Ложь).Получить(
				"ИдентификаторЗаданияМногопоточногоПроцесса");
		ИдентификаторОсновногоЗадания = ?(ЗначениеЗаполнено(ИдентификаторЗаданияМногопоточногоПроцесса),
			ИдентификаторЗаданияМногопоточногоПроцесса, ИдентификаторОсновногоЗадания(ФоновоеЗадание));
	КонецЕсли;

	Если ВидОповещения = "ДлительнаяОперацияЗавершена" Тогда
		Если ЗначениеЗаполнено(ИдентификаторЗаданияМногопоточногоПроцесса) Тогда
			Если ИдентификаторЗаданияМногопоточногоПроцесса <> ИдентификаторОсновногоЗадания(ФоновоеЗадание)
			 Или ПередаваемоеЗначение.Статус = "Ошибка" Тогда
				Возврат;
			КонецЕсли;
		КонецЕсли;
		Результат = ПередаваемоеЗначение;
	Иначе
		Результат = НовыйРезультатВыполненияОперации();
	КонецЕсли;
	Если ВидОповещения = "СообщениеПользователю" Тогда
		Результат.Сообщения = Новый ФиксированныйМассив(
			ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(ПередаваемоеЗначение));
	ИначеЕсли ВидОповещения = "Прогресс" Тогда
		Сообщения = ФоновоеЗадание.ПолучитьСообщенияПользователю(Истина);
		Для Каждого Сообщение Из Сообщения Цикл
			// @skip-check query-in-loop - ветка с запросом вызывается только при первом вызове в сеансе
			ОтправитьОповещениеКлиенту("СообщениеПользователю", Сообщение);
		КонецЦикла;
		Результат.Сообщения = Новый ФиксированныйМассив(Новый Массив);
		Результат.Прогресс = ПередаваемоеЗначение;
	ИначеЕсли ВидОповещения = "ДлительнаяОперацияЗавершена" Тогда
		Сообщения = ФоновоеЗадание.ПолучитьСообщенияПользователю(Истина);
		Для Каждого Сообщение Из Сообщения Цикл
    // TODO: допиши оставшуюся часть

[Assistant]
Процедура ОтправитьОповещениеКлиенту(ВидОповещения, ПередаваемоеЗначение,
			ФоновоеЗадание = Неопределено, ИдентификаторОсновногоЗадания = Неопределено) Экспорт

	УстановитьОтключениеБезопасногоРежима(Истина);
	УстановитьПривилегированныйРежим(Истина);

	ЗаписатьСообщенияПользователю = ФоновоеЗадание <> Неопределено И ВидОповещения = "СообщениеПользователю";
	Если ЗаписатьСообщенияПользователю Тогда
		КлючСеансаРодителя = СерверныеОповещения.КлючСеанса();
	Иначе
		КлючСеансаРодителя = СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере(Ложь).Получить(
			"КлючСеансаРодителя");
		Если Не ЗначениеЗаполнено(КлючСеансаРодителя) Тогда
			Возврат;
		КонецЕсли;
		ФоновоеЗадание = ПолучитьТекущийСеансИнформационнойБазы().ПолучитьФоновоеЗадание();
		Если ФоновоеЗадание = Неопределено Тогда
			Возврат;
		КонецЕсли;
		ИдентификаторЗаданияМногопоточногоПроцесса =
			СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере(Ложь).Получить(
				"ИдентификаторЗаданияМногопоточногоПроцесса");
		ИдентификаторОсновногоЗадания = ?(ЗначениеЗаполнено(ИдентификаторЗаданияМногопоточногоПроцесса),
			ИдентификаторЗаданияМногопоточногоПроцесса, ИдентификаторОсновногоЗадания(ФоновоеЗадание));
	КонецЕсли;

	Если ВидОповещения = "ДлительнаяОперацияЗавершена" Тогда
		Если ЗначениеЗаполнено(ИдентификаторЗаданияМногопоточногоПроцесса) Тогда
			Если ИдентификаторЗаданияМногопоточногоПроцесса <> ИдентификаторОсновногоЗадания(ФоновоеЗадание)
			 Или ПередаваемоеЗначение.Статус = "Ошибка" Тогда
				Возврат;
			КонецЕсли;
		КонецЕсли;
		Результат = ПередаваемоеЗначение;
	Иначе
		Результат = НовыйРезультатВыполненияОперации();
	КонецЕсли;
	Если ВидОповещения = "СообщениеПользователю" Тогда
		Результат.Сообщения = Новый ФиксированныйМассив(
			ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(ПередаваемоеЗначение));
	ИначеЕсли ВидОповещения = "Прогресс" Тогда
		Сообщения = ФоновоеЗадание.ПолучитьСообщенияПользователю(Истина);
		Для Каждого Сообщение Из Сообщения Цикл
			// @skip-check query-in-loop - ветка с запросом вызывается только при первом вызове в сеансе
			ОтправитьОповещениеКлиенту("СообщениеПользователю", Сообщение);
		КонецЦикла;
		Результат.Сообщения = Новый ФиксированныйМассив(Новый Массив);
		Результат.Прогресс = ПередаваемоеЗначение;
	ИначеЕсли ВидОповещения = "ДлительнаяОперацияЗавершена" Тогда
		Сообщения = ФоновоеЗадание.ПолучитьСообщенияПользователю(Истина);
		Для Каждого Сообщение Из Сообщения Цикл
			// @skip-check query-in-loop - ветка с запросом вызывается только при первом вызове в сеансе
			ОтправитьОповещениеКлиенту("СообщениеПользователю", Сообщение);
		КонецЦикла;
	КонецЕсли;

	ПараметрыОповещения = Новый Структура;
	ПараметрыОповещения.Вставить("ВидОповещения", ВидОповещения);
	ПараметрыОповещения.Вставить("ИдентификаторЗадания", ИдентификаторОсновногоЗадания);
	ПараметрыОповещения.Вставить("Результат", Результат);
	ПараметрыОповещения.Вставить("ВремяОтправки", ТекущаяУниверсальнаяДатаВМиллисекундах());

	КлючиСеансов = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(КлючСеансаРодителя);
	Адресаты = Новый Соответствие;
	Адресаты.Вставить(ПользователиИнформационнойБазы.ТекущийПользователь().УникальныйИдентификатор, КлючиСеансов);

	ДополнительныеПараметрыОтправки = СерверныеОповещения.ДополнительныеПараметрыОтправки();
	ДополнительныеПараметрыОтправки.ИдентификаторГруппы  = ИдентификаторОсновногоЗадания;
	ДополнительныеПараметрыОтправки.ВидОповещенияВГруппе = ИдентификаторВидаОповещения(ВидОповещения);

	Если ВидОповещения = "Прогресс" Тогда
		ДополнительныеПараметрыОтправки.Заменить = Истина;
		ДополнительныеПараметрыОтправки.ОтсрочкаДоставки = 3;
		ДополнительныеПараметрыОтправки.СобытиеЖурналаПриОтсрочкеДоставки =
			НСтр("ru = 'Длительные операции.Отложенная доставка прогресса'",
				ОбщегоНазначения.КодОсновногоЯзыка());
		ДополнительныеПараметрыОтправки.КомментарийЖурналаПриОтсрочкеДоставки =
			НСтр("ru = 'Отправка прогресса чаще одного раза в 3 сек.'");
	КонецЕсли;

	СерверныеОповещения.ОтправитьСерверноеОповещениеСИдентификаторомГруппы(ИмяОповещения(),
		ПараметрыОповещения, Адресаты, Не ЗаписатьСообщенияПользователю, ДополнительныеПараметрыОтправки);

	УстановитьПривилегированныйРежим(Ложь);
	УстановитьОтключениеБезопасногоРежима(Ложь);

КонецПроцедуры

// Для процедуры ОтправитьОповещениеКлиенту и функции ПолучитьИзОповещений.

Функция ИдентификаторВидаОповещения(ВидОповещения)

	Если ВидОповещения = "СообщениеПользователю" Или ВидОповещения = "Сообщения" Тогда
		Возврат Новый УникальныйИдентификатор("0afef160-bfcb-459e-a890-a4afbb73b7ba");

	ИначеЕсли ВидОповещения = "Прогресс" Тогда
		Возврат Новый УникальныйИдентификатор("14076bb1-a1f5-4876-975a-3b7f69383f6c");

	ИначеЕсли ВидОповещения = "ДлительнаяОперацияЗавершена" Тогда
		Возврат Новый УникальныйИдентификатор("28e5ab5c-196b-44be-aab5-8fe7edb5225b");
	КонецЕсли;

	ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Неизвестный вид оповещения длительной операции ""%1"".'"), ВидОповещения);

	ВызватьИсключение ТекстОшибки;

КонецФункции

// Запись в очередь еще не записанных сообщений, которые были отправлены
// без использования процедуры ОбщегоНазначения.СообщитьПользователю.
//
// Параметры:
//  ИдентификаторЗадания - УникальныйИдентификатор
//

Процедура ЗаписатьОстаткиСообщенийПользователю(ИдентификаторЗадания)

	ПоследнийИдентификатор = ПоследнийИдентификатор(ИдентификаторЗадания);
	ФоновоеЗадание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ПоследнийИдентификатор);

	Если ФоновоеЗадание <> Неопределено
	   И Не МонопольныйРежимВФоновомЗадании(ФоновоеЗадание) Тогда

		Сообщения = ФоновоеЗадание.ПолучитьСообщенияПользователю(Истина);
		Для Каждого Сообщение Из Сообщения Цикл
			// @skip-check query-in-loop - ветка с запросом вызывается только при первом вызове в сеансе
			ОтправитьОповещениеКлиенту("СообщениеПользователю", Сообщение, ФоновоеЗадание, ИдентификаторЗадания);
		КонецЦикла;
	КонецЕсли;

КонецПроцедуры

// Параметры:
//  ФоновоеЗадание - ФоновоеЗадание - задание, активность которого нужно учесть.
//
// Возвращаемое значение:
//  Булево - если Истина, значит в сеансе установлен монопольный режим и
//    хотя бы одно фоновое задание активно (то есть запись в сеансе недоступна).
//

Функция МонопольныйРежимВФоновомЗадании(ФоновоеЗадание = Неопределено)

	Если Не МонопольныйРежим() Тогда
		Возврат Ложь;
	КонецЕсли;

	Если ФоновоеЗадание <> Неопределено
	   И ФоновоеЗадание.Состояние = СостояниеФоновогоЗадания.Активно Тогда
		Возврат Истина;
	КонецЕсли;

	Отбор = Новый Структура;
	Отбор.Вставить("Состояние", СостояниеФоновогоЗадания.Активно);

	Возврат ФоновыеЗадания.ПолучитьФоновыеЗадания(Отбор).Количество() > 0;

КонецФункции

Функция ЕстьФоновыеЗаданияВФайловойИБ()

	ЗапущеноЗаданийВФайловойИБ = 0;
	Если ОбщегоНазначения.ИнформационнаяБазаФайловая() Тогда
		Отбор = Новый Структура;
		Отбор.Вставить("Состояние", СостояниеФоновогоЗадания.Активно);
		ЗапущеноЗаданийВФайловойИБ = ФоновыеЗадания.ПолучитьФоновыеЗадания(Отбор).Количество();
	КонецЕсли;
	Возврат ЗапущеноЗаданийВФайловойИБ > 0;

КонецФункции

Функция ВозможноВыполнитьВФоне(ИмяПроцедуры)

	ЧастиИмени = СтрРазделить(ИмяПроцедуры, ".");
	Если ЧастиИмени.Количество() = 0 Тогда
		Возврат Ложь;
	КонецЕсли;

	Возврат Истина;

КонецФункции


[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало функция `ПараметрыПроверкиДлительныхОпераций`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

Функция ПараметрыПроверкиДлительныхОпераций(ОбсужденияАктивны, Интервал)
ТекущаяДата = ТекущаяДата(); // АПК:143 Дата сеанса не используется для проверки интервалов времени

	КонтролируемыеОперации = Новый Соответствие;
	ЗаданияДляПроверки = Новый Массив;
	ЗаданияДляОтмены = Новый Массив;

	ТекущиеДлительныеОперации = АктивныеДлительныеОперации();
	АктивныеДлительныеОперации = ТекущиеДлительныеОперации.Список;
	ТекущиеДлительныеОперации.КонтролируемыеОперации = КонтролируемыеОперации;

	Если Не ЗначениеЗаполнено(АктивныеДлительныеОперации) Тогда
		Возврат Неопределено;
	КонецЕсли;

	Для Каждого ДлительнаяОперация Из АктивныеДлительныеОперации Цикл

		ДлительнаяОперация = ДлительнаяОперация.Значение;

		Если ДлительнаяОперацияОтменена(ДлительнаяОперация) Тогда
			КонтролируемыеОперации.Вставить(ДлительнаяОперация.ИдентификаторЗадания, ДлительнаяОперация);
			ЗаданияДляОтмены.Добавить(ДлительнаяОперация.ИдентификаторЗадания);
		Иначе
			ИнтервалКонтроляОбсуждений = ИнтервалКонтроляОбсуждений();
			ДатаКонтроля = ДлительнаяОперация.Контроль
				+ ?(Не ОбсужденияАктивны Или ДлительнаяОперация.ТекущийИнтервал > ИнтервалКонтроляОбсуждений,
					0, ИнтервалКонтроляОбсуждений - ДлительнаяОперация.ТекущийИнтервал);
    // TODO: допиши оставшуюся часть

[Assistant]
Функция ПараметрыПроверкиДлительныхОпераций(ОбсужденияАктивны, Интервал)

	ТекущаяДата = ТекущаяДата(); // АПК:143 Дата сеанса не используется для проверки интервалов времени

	КонтролируемыеОперации = Новый Соответствие;
	ЗаданияДляПроверки = Новый Массив;
	ЗаданияДляОтмены = Новый Массив;

	ТекущиеДлительныеОперации = АктивныеДлительныеОперации();
	АктивныеДлительныеОперации = ТекущиеДлительныеОперации.Список;
	ТекущиеДлительныеОперации.КонтролируемыеОперации = КонтролируемыеОперации;

	Если Не ЗначениеЗаполнено(АктивныеДлительныеОперации) Тогда
		Возврат Неопределено;
	КонецЕсли;

	Для Каждого ДлительнаяОперация Из АктивныеДлительныеОперации Цикл

		ДлительнаяОперация = ДлительнаяОперация.Значение;

		Если ДлительнаяОперацияОтменена(ДлительнаяОперация) Тогда
			КонтролируемыеОперации.Вставить(ДлительнаяОперация.ИдентификаторЗадания, ДлительнаяОперация);
			ЗаданияДляОтмены.Добавить(ДлительнаяОперация.ИдентификаторЗадания);
		Иначе
			ИнтервалКонтроляОбсуждений = ИнтервалКонтроляОбсуждений();
			ДатаКонтроля = ДлительнаяОперация.Контроль
				+ ?(Не ОбсужденияАктивны Или ДлительнаяОперация.ТекущийИнтервал > ИнтервалКонтроляОбсуждений,
					0, ИнтервалКонтроляОбсуждений - ДлительнаяОперация.ТекущийИнтервал);

			Если ДатаКонтроля <= ТекущаяДата Тогда
				КонтролируемыеОперации.Вставить(ДлительнаяОперация.ИдентификаторЗадания, ДлительнаяОперация);
				ЗаданияДляПроверки.Добавить(ДлительнаяОперация.ИдентификаторЗадания);
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;

	Если Не ЗначениеЗаполнено(ЗаданияДляПроверки)
	   И Не ЗначениеЗаполнено(ЗаданияДляОтмены) Тогда

		УточнитьИнтервалОбработчикаОжидания(Интервал, АктивныеДлительныеОперации, ОбсужденияАктивны);
		Возврат Неопределено;
	КонецЕсли;

	Результат = Новый Структура;
	Результат.Вставить("ЗаданияДляПроверки", ЗаданияДляПроверки);
	Результат.Вставить("ЗаданияДляОтмены",   ЗаданияДляОтмены);

	Возврат Результат;

КонецФункции

Функция ДлительнаяОперацияОтменена(ДлительнаяОперация)

	Возврат ДлительнаяОперация.ОтменятьПриЗакрытииФормыВладельца
	    И ДлительнаяОперация.ФормаВладелец <> Неопределено
		И Не ДлительнаяОперация.ФормаВладелец.Открыта();

КонецФункции

Процедура ОбработатьРезультатОперации(АктивныеДлительныеОперации, Операция, Результат)

	Если АктивныеДлительныеОперации.Получить(Операция.ИдентификаторЗадания) = Неопределено Тогда
		Возврат;
	КонецЕсли;

	Попытка
		Если ОбработатьРезультатАктивнойОперации(Операция, Результат) Тогда
			АктивныеДлительныеОперации.Удалить(Операция.ИдентификаторЗадания);
		КонецЕсли;
	Исключение
		// далее не отслеживаем
		АктивныеДлительныеОперации.Удалить(Операция.ИдентификаторЗадания);
		ВызватьИсключение;
	КонецПопытки;

КонецПроцедуры

Процедура УточнитьИнтервалОбработчикаОжидания(Интервал, АктивныеДлительныеОперации, ОбсужденияАктивны)

	ТекущаяДата = ТекущаяДата(); // АПК:143 Дата сеанса не используется для проверки интервалов времени
	НовыйИнтервал = 120;
	Для каждого Операция Из АктивныеДлительныеОперации Цикл
		НовыйИнтервал = Макс(Мин(НовыйИнтервал, Операция.Значение.Контроль - ТекущаяДата), 1);
	КонецЦикла;

	ИнтервалКонтроляОбсуждений = ИнтервалКонтроляОбсуждений();
	Если ОбсужденияАктивны И НовыйИнтервал < ИнтервалКонтроляОбсуждений Тогда
		НовыйИнтервал = ИнтервалКонтроляОбсуждений;
	КонецЕсли;

	Если Интервал > НовыйИнтервал Тогда
		Интервал = НовыйИнтервал;
	КонецЕсли;

КонецПроцедуры

// Возвращаемое значение:
//  Число - число секунд контроля длительной операции
//          через общий серверный вызов, когда обсуждения
//          активны, но сообщений не поступило, например,
//          при операции дольше указанного числа секунд
//          или когда произошло аварийное завершение фонового задания и
//          сообщение через систему взаимодействия не было отправлено.
//

Функция ИнтервалКонтроляОбсуждений()

	Возврат 30;

КонецФункции

// См. СтандартныеПодсистемыКлиент.ПриПолученииСерверногоОповещения

Процедура ПриПолученииСерверногоОповещения(ИмяОповещения, Результат) Экспорт

	АктивныеДлительныеОперации = АктивныеДлительныеОперации().Список;
	Операция = АктивныеДлительныеОперации.Получить(Результат.ИдентификаторЗадания);
	Если Операция = Неопределено
	 Или ДлительнаяОперацияОтменена(Операция) Тогда
		Возврат;
	КонецЕсли;

	Если Результат.ВидОповещения = "Прогресс" Тогда
		Если Операция.ВремяОтправкиПоследнегоПрогресса < Результат.ВремяОтправки Тогда
			Операция.ВремяОтправкиПоследнегоПрогресса = Результат.ВремяОтправки;
		Иначе
			Возврат; // Устаревшее сообщение прогресса пропускается.
		КонецЕсли;
	КонецЕсли;

	ОбработатьРезультатОперации(АктивныеДлительныеОперации, Операция, Результат.Результат);

КонецПроцедуры

// Параметры:
//  ДлительнаяОперация - Структура:
//   * ФормаВладелец          - ФормаКлиентскогоПриложения
//                            - Неопределено
//   * Заголовок              - Строка
//   * ТекстСообщения         - Строка
//   * ВыводитьОкноОжидания   - Булево
//   * ВыводитьПрогрессВыполнения - Булево
//   * ОповещениеОПрогрессеВыполнения - ОписаниеОповещения
//                                    - Неопределено
//   * ВыводитьСообщения      - Булево
//   * Интервал               - Число
//   * ОповещениеПользователя - Структура:
//     ** Показать            - Булево
//     ** Текст               - Строка
//     ** НавигационнаяСсылка - Строка
//     ** Пояснение           - Строка
//     ** Картинка            - Картинка
//     ** Важное              - Булево
//
//   * ОтменятьПриЗакрытииФормыВладельца - Булево
//   * ПолучатьРезультат
//
//   * ИдентификаторЗадания  - УникальныйИдентификатор
//   * НакопленныеСообщения  - Массив
//   * ОповещениеОЗавершении - ОписаниеОповещения
//                           - Неопределено
//   * ТекущийИнтервал       - Число
//   * Контроль              - Дата
//
//   * ВремяОтправкиПоследнегоПрогресса - Число - универсальная дата в миллисекундах
//
//  Результат - см. ДлительныеОперации.НовыйРезультатВыполненияОперации
//


[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало процедура `ПередЗаписьюДополнительнойОбработки`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

Процедура ПередЗаписьюДополнительнойОбработки(Источник, Отказ)
Экспорт

	Если Источник.ОбменДанными.Загрузка Тогда
		Возврат;
	КонецЕсли;

	Если ОбщегоНазначения.ЭтоАвтономноеРабочееМесто() Тогда

		Если (Источник.ПометкаУдаления ИЛИ Источник.Публикация = Перечисления.ВариантыПубликацииДополнительныхОтчетовИОбработок.Отключена) И ЭтоОбработкаСервиса(Источник.Ссылка) Тогда

			ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
    // TODO: допиши оставшуюся часть

[Assistant]
Процедура ПередЗаписьюДополнительнойОбработки(Источник, Отказ) Экспорт

	Если Источник.ОбменДанными.Загрузка Тогда
		Возврат;
	КонецЕсли;

	Если ОбщегоНазначения.ЭтоАвтономноеРабочееМесто() Тогда

		Если (Источник.ПометкаУдаления ИЛИ Источник.Публикация = Перечисления.ВариантыПубликацииДополнительныхОтчетовИОбработок.Отключена) И ЭтоОбработкаСервиса(Источник.Ссылка) Тогда

			ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Дополнительный отчет или обработка %1 был загружен из сервиса и не может быть отключен из автономного рабочего места.
					|Для удаления дополнительного отчета или обработки выполните операцию отключения в
					|приложении сервиса и проведите синхронизацию данных автономного рабочего места с сервисом.'"),
				Источник.Наименование);

		КонецЕсли;

	КонецЕсли;

КонецПроцедуры

#КонецОбласти

#КонецОбласти

#КонецОбласти

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

// Регистрирует дополнительный отчет иди обработку в качестве обработки, полученной
// в автономное рабочее место из сервиса.
//
// Параметры:
//  Ссылка - СправочникСсылка.ДополнительныеОтчетыИОбработки.
//

Процедура ЗарегистрироватьОбработкуСервиса(Знач Ссылка)

	Набор = РегистрыСведений.ИспользованиеДополнительныхОтчетовИОбработокСервисаВАвтономномРабочемМесте.СоздатьНаборЗаписей();
	Набор.Отбор.ДополнительныйОтчетИлиОбработка.Установить(Ссылка);
	Запись = Набор.Добавить();
	Запись.ДополнительныйОтчетИлиОбработка = Ссылка;
	Запись.Поставляемый = Истина;
	Набор.Записать();

КонецПроцедуры

// Функция проверяет, была ли дополнительная обработка получена в автономное рабочее место из сервиса.
//
// Параметры:
//   Ссылка - СправочникСсылка.ДополнительныеОтчетыИОбработки.
//
// Возвращаемое значение:
//  Булево
//

Функция ЭтоОбработкаСервиса(Ссылка)

	Менеджер = РегистрыСведений.ИспользованиеДополнительныхОтчетовИОбработокСервисаВАвтономномРабочемМесте.СоздатьМенеджерЗаписи();
	Менеджер.ДополнительныйОтчетИлиОбработка = Ссылка;
	Менеджер.Прочитать();

	Если Менеджер.Выбран() Тогда
		Возврат Менеджер.Поставляемый;
	Иначе
		Возврат Ложь;
	КонецЕсли;

КонецФункции

#КонецОбласти

Tasks-develope/src/cf/CommonModules/ДополнительныеОтчетыИОбработкиВАвтономномРежиме/Ext/Module.bsl


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

Процедура ИмяФункции(Параметры) Экспорт

	Если Параметры.ТекущиеДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;

	Если Параметры.Поле.Имя = "Данные" Или Параметры.Поле.Имя = "ПредставлениеДанных" Тогда
		Если Параметры.ТекущиеДанные.Данные <> Неопределено
			И (ТипЗнч(Параметры.ТекущиеДанные.Данные) <> Тип("Строка")
			И ЗначениеЗаполнено(Параметры.ТекущиеДанные.Данные)) Тогда

			ОткрытьДанныеДляПросмотра(Параметры.ТекущиеДанные);
			Возврат;
		КонецЕсли;
	КонецЕсли;

	Если Параметры.Поле.Имя = "Дата" Тогда
		УстановитьИнтервалДатДляПросмотра(Параметры.ИнтервалДат, Параметры.ОтборЖурналаРегистрации);
		Возврат;
	КонецЕсли;

	ПросмотрТекущегоСобытияВОтдельномОкне(Параметры.ТекущиеДанные, Параметры.ХранилищеДанных);

КонецПроцедуры

// Заполняет отбор в соответствии с значением в текущей колонке событий.
//
// Параметры:
//  ТекущиеДанные - СтрокаТаблицыЗначений
//  ТекущийЭлемент - ПолеФормы - текущий элемент строки таблицы значений.
//  ОтборЖурналаРегистрации - Структура
//  КолонкиИсключения - СписокЗначений
//
// Возвращаемое значение:
//  Булево - Истина, если отбор установлен, Ложь - Иначе.
//

Функция УстановитьОтборПоЗначениюВТекущейКолонке(ТекущиеДанные, ТекущийЭлемент, ОтборЖурналаРегистрации, КолонкиИсключения) Экспорт

	Если ТекущиеДанные = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;

	ИмяКолонкиПредставления = ТекущийЭлемент.Имя;

	Если ИмяКолонкиПредставления = "ПредставлениеРазделенияДанныхСеанса" Тогда
		ОтборЖурналаРегистрации.Удалить("ПредставлениеРазделенияДанныхСеанса");
		ОтборЖурналаРегистрации.Вставить("РазделениеДанныхСеанса", ТекущиеДанные.РазделениеДанныхСеанса);
		ИмяКолонкиПредставления = "РазделениеДанныхСеанса";
	КонецЕсли;

	Если КолонкиИсключения.Найти(ИмяКолонкиПредставления) <> Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;
	ЗначениеОтбора = ТекущиеДанные[ИмяКолонкиПредставления];
	Представление  = ТекущиеДанные[ИмяКолонкиПредставления];

	ИмяЭлементаОтбора = ИмяКолонкиПредставления;
	Если ИмяКолонкиПредставления = "ИмяПользователя" Тогда
		ИмяЭлементаОтбора = "Пользователь";
		ЗначениеОтбора = ТекущиеДанные["Пользователь"];
	ИначеЕсли ИмяКолонкиПредставления = "ПредставлениеПриложения" Тогда
		ИмяЭлементаОтбора = "ИмяПриложения";
		ЗначениеОтбора = ТекущиеДанные["ИмяПриложения"];
	ИначеЕсли ИмяКолонкиПредставления = "ПредставлениеСобытия" Тогда
		ИмяЭлементаОтбора = "Событие";
		ЗначениеОтбора = ТекущиеДанные["Событие"];
	КонецЕсли;

	// По пустым строкам не отбираем.
	Если ТипЗнч(ЗначениеОтбора) = Тип("Строка") И ПустаяСтрока(ЗначениеОтбора) Тогда
		// Для пользователя по умолчанию имя пустое, разрешаем отбирать.
		Если ИмяКолонкиПредставления <> "ИмяПользователя" Тогда
			Возврат Ложь;
		КонецЕсли;
	КонецЕсли;

	ТекущееЗначение = Неопределено;
	Если ОтборЖурналаРегистрации.Свойство(ИмяЭлементаОтбора, ТекущееЗначение) Тогда
		// Уже установлен отбор
		ОтборЖурналаРегистрации.Удалить(ИмяЭлементаОтбора);
	КонецЕсли;

	Если ИмяЭлементаОтбора = "Данные" // Не списочные отборы, только 1 значение.
		Или ИмяЭлементаОтбора = "Комментарий"
		Или ИмяЭлементаОтбора = "Транзакция"
		Или ИмяЭлементаОтбора = "ПредставлениеДанных" Тогда
		ОтборЖурналаРегистрации.Вставить(ИмяЭлементаОтбора, ЗначениеОтбора);
	Иначе

		Если ИмяЭлементаОтбора = "РазделениеДанныхСеанса" Тогда
			СписокОтбора = ЗначениеОтбора.Скопировать();
		Иначе
			СписокОтбора = Новый СписокЗначений;
			СписокОтбора.Добавить(ЗначениеОтбора, Представление);
		КонецЕсли;

		ОтборЖурналаРегистрации.Вставить(ИмяЭлементаОтбора, СписокОтбора);
	КонецЕсли;

	Возврат Истина;

КонецФункции

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

// Только для внутреннего использования.
//
// Параметры:
//  Данные - ДанныеФормыЭлементКоллекции: см. Обработка.ЖурналРегистрации.Форма.ЖурналРегистрации.Журнал
//
// Возвращаемое значение:
//  Структура
//

Функция СобытиеЖурналаРегистрацииВСтруктуру(Данные)

	Если ТипЗнч(Данные) = Тип("Структура") Тогда
		Возврат Данные;
	КонецЕсли;

	ПараметрыФормы = Новый Структура;
	ПараметрыФормы.Вставить("Дата",                    Данные.Дата);
	ПараметрыФормы.Вставить("ИмяПользователя",         Данные.ИмяПользователя);
	ПараметрыФормы.Вставить("ПредставлениеПриложения", Данные.ПредставлениеПриложения);
	ПараметрыФормы.Вставить("Компьютер",               Данные.Компьютер);
	ПараметрыФормы.Вставить("Событие",                 Данные.Событие);
	ПараметрыФормы.Вставить("ПредставлениеСобытия",    Данные.ПредставлениеСобытия);
	ПараметрыФормы.Вставить("Комментарий",             Данные.Комментарий);
	ПараметрыФормы.Вставить("ПредставлениеМетаданных", Данные.ПредставлениеМетаданных);
	ПараметрыФормы.Вставить("Данные",                  Данные.Данные);
	ПараметрыФормы.Вставить("ПредставлениеДанных",     Данные.ПредставлениеДанных);
	ПараметрыФормы.Вставить("Транзакция",              Данные.Транзакция);
	ПараметрыФормы.Вставить("СтатусТранзакции",        Данные.СтатусТранзакции);
	ПараметрыФормы.Вставить("Сеанс",                   Данные.Сеанс);
	ПараметрыФормы.Вставить("РабочийСервер",           Данные.РабочийСервер);
	ПараметрыФормы.Вставить("ОсновнойIPПорт",          Данные.ОсновнойIPПорт);
	ПараметрыФормы.Вставить("ВспомогательныйIPПорт",   Данные.ВспомогательныйIPПорт);
	ПараметрыФормы.Вставить("Уровень",                 Данные.Уровень);

	Если Данные.Свойство("РазделениеДанныхСеанса") Тогда
		ПараметрыФормы.Вставить("РазделениеДанныхСеанса", Данные.РазделениеДанныхСеанса);
	КонецЕсли;

	Если ЗначениеЗаполнено(Данные.АдресДанных) Тогда
		ПараметрыФормы.Вставить("АдресДанных", Данные.АдресДанных);
	КонецЕсли;

	Возврат ПараметрыФормы;
КонецФункции

// Только для внутреннего использования.
//
// Параметры:
//  Результат - СтандартныйПериод
//            - Неопределено
//  ДополнительныеПараметры - Структура
//

Процедура УстановитьИнтервалДатДляПросмотраЗавершение(Результат, ДополнительныеПараметры) Экспорт

	ОтборЖурналаРегистрации = ДополнительныеПараметры.ОтборЖурналаРегистрации;
	ИнтервалУстановлен = Ложь;

	Если Результат <> Неопределено Тогда

		// Обновление текущего периода.
		ИнтервалДат = Результат;
		Если ИнтервалДат.ДатаНачала = '00010101000000' Тогда
			ОтборЖурналаРегистрации.Удалить("ДатаНачала");
		Иначе
			ОтборЖурналаРегистрации.Вставить("ДатаНачала", ИнтервалДат.ДатаНачала);
		КонецЕсли;

		Если ИнтервалДат.ДатаОкончания = '00010101000000' Тогда
			ОтборЖурналаРегистрации.Удалить("ДатаОкончания");
		Иначе
			ОтборЖурналаРегистрации.Вставить("ДатаОкончания", ИнтервалДат.ДатаОкончания);
		КонецЕсли;
		ИнтервалУстановлен = Истина;

	КонецЕсли;

	Если ДополнительныеПараметры.ОбработчикОповещения <> Неопределено Тогда
		ВыполнитьОбработкуОповещения(ДополнительныеПараметры.ОбработчикОповещения, ИнтервалУстановлен);
	КонецЕсли;

КонецПроцедуры

#КонецОбласти

[Assistant] Процедура СобытияВыбор(Параметры)


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

Функция ИмяФункции(Субъекты) Экспорт

	Субъекты = ОпределитьСубъектыДляУничтоженияПерсональныхДанных(Субъекты);

	Если Не ЗначениеЗаполнено(Субъекты) Тогда
		Возврат Неопределено;
	КонецЕсли;

	ТаблицаКатегорий = Новый ТаблицаЗначений();
	ТаблицаКатегорий.Колонки.Добавить("Субъект");
	ТаблицаКатегорий.Колонки.Добавить("КатегорияДанных", Новый ОписаниеТипов("Строка"));
	ТаблицаКатегорий.Колонки.Добавить("ИмяОбъекта", Новый ОписаниеТипов("Строка"));
	ТаблицаКатегорий.Колонки.Добавить("ИдентификаторОбъекта", Новый ОписаниеТипов("Строка"));

	УничтожаемыеДанные = УничтожаемыеПерсональныеДанные();

	// Добавим данные самих субъектов.
	Для Каждого Субъект Из Субъекты Цикл

		ИмяОбъекта = Субъект.Метаданные().ПолноеИмя();

		НайденныеСтроки = УничтожаемыеДанные.НайтиСтроки(Новый Структура("Объект", ИмяОбъекта));

		Для Каждого НайденнаяСтрока Из НайденныеСтроки Цикл
			НоваяСтрока = ТаблицаКатегорий.Добавить();
			НоваяСтрока.Субъект = Субъект;
			НоваяСтрока.КатегорияДанных = НайденнаяСтрока.КатегорияДанных;
			НоваяСтрока.ИмяОбъекта = ИмяОбъекта;
			НоваяСтрока.ИдентификаторОбъекта = Субъект.УникальныйИдентификатор();
		КонецЦикла;

	КонецЦикла;

	// Добавим данные объектов, в которых есть ссылки на субъекты.

	УстановитьПривилегированныйРежим(Истина);

	НайденныеОбъекты = НайтиПоСсылкам(Субъекты);

	Для Каждого НайденныеОбъект Из НайденныеОбъекты Цикл

		Субъект = НайденныеОбъект.Ссылка;
		ИмяОбъекта = НайденныеОбъект.Метаданные.ПолноеИмя();

		Если ОбщегоНазначения.ЭтоРегистр(НайденныеОбъект.Метаданные) Тогда
			НайденСубъект = Ложь;
			ИменаРеквизитовСодержащихСубъект = ИменаРеквизитовИсточникаСодержащихСубъект(ИмяОбъекта);

			Для Каждого ИмяРеквизита Из ИменаРеквизитовСодержащихСубъект Цикл
				Если НайденныеОбъект.Данные[ИмяРеквизита] = Субъект Тогда
					НайденСубъект = Истина;
					Прервать;
				КонецЕсли;
			КонецЦикла;

			Если Не НайденСубъект Тогда
				Продолжить;
			КонецЕсли;
		Иначе
			Если Не ЕстьСсылкаНаСубъектВОбъекте(Субъект, НайденныеОбъект.Данные, ИмяОбъекта) Тогда
				Продолжить;
			КонецЕсли;
		КонецЕсли;

		НайденныеСтроки = УничтожаемыеДанные.НайтиСтроки(Новый Структура("Объект", ИмяОбъекта));

		Для Каждого НайденнаяСтрока Из НайденныеСтроки Цикл
			НоваяСтрока = ТаблицаКатегорий.Добавить();
			НоваяСтрока.Субъект = Субъект;
			НоваяСтрока.КатегорияДанных = НайденнаяСтрока.КатегорияДанных;
			НоваяСтрока.ИмяОбъекта = ИмяОбъекта;
			Если ОбщегоНазначения.ЭтоРегистр(НайденныеОбъект.Метаданные) Тогда
				НоваяСтрока.ИдентификаторОбъекта = Новый УникальныйИдентификатор();
			Иначе
				НоваяСтрока.ИдентификаторОбъекта = НайденныеОбъект.Данные.УникальныйИдентификатор();
			КонецЕсли;
		КонецЦикла;

	КонецЦикла;

	Возврат ТаблицаКатегорий;

КонецФункции

// Возвращает информацию о том, есть в реквизитах объекта ссылки на субъекты или нет.
//
// Параметры:
//  Субъект - ОпределяемыйТип.СубъектПерсональныхДанных
//  ОбъектСсылка - СправочникСсылка, ДокументСсылка
//  ИмяОбъекта - Строка
//
// Возвращаемое значение:
//  Булево
//

Функция ЕстьСсылкаНаСубъектВОбъекте(Субъект, ОбъектСсылка, ИмяОбъекта)

	Объект = ОбъектСсылка.ПолучитьОбъект();

	ЕстьСсылка = Ложь;
	ИменаРеквизитовСодержащихСубъект = ИменаРеквизитовИсточникаСодержащихСубъект(ИмяОбъекта);

	Для Каждого ИмяРеквизита Из ИменаРеквизитовСодержащихСубъект Цикл

		ЧастиИмени = СтрРазделить(ИмяРеквизита, ".", Ложь);
		Если ЧастиИмени.Количество() > 1 Тогда
			ИмяТЧасти = ЧастиИмени[0];
			ИмяРеквизитаТЧ = ЧастиИмени[1];
			ЕстьСсылка = Объект[ИмяТЧасти].Найти(Субъект, ИмяРеквизитаТЧ) <> Неопределено;
		Иначе
			ЕстьСсылка = Объект[ИмяРеквизита] = Субъект;
		КонецЕсли;

		Если ЕстьСсылка Тогда
			Прервать;
		КонецЕсли;

	КонецЦикла;

	Возврат ЕстьСсылка;

КонецФункции

// См. ЗащитаПерсональныхДанныхПереопределяемый.ПередУничтожениемПерсональныхДанных

Процедура ПередУничтожениемПерсональныхДанных(Объект, Субъекты, ВыполнитьЗаписьОбъекта) Экспорт

	ЗащитаПерсональныхДанныхПереопределяемый.ПередУничтожениемПерсональныхДанных(Объект, Субъекты,
		ВыполнитьЗаписьОбъекта);

КонецПроцедуры

// См. ЗащитаПерсональныхДанныхПереопределяемый.ПослеУничтоженияПерсональныхДанных

Процедура ПослеУничтоженияПерсональныхДанных(Объект, Субъекты) Экспорт

	ЗащитаПерсональныхДанныхПереопределяемый.ПослеУничтоженияПерсональныхДанных(Объект, Субъекты);

КонецПроцедуры

// См. ЗащитаПерсональныхДанныхСлужебный.СведенияОПерсональныхДанных

Функция СведенияОПерсональныхДанных() Экспорт

	Возврат ЗащитаПерсональныхДанныхПовтИсп.СведенияОПерсональныхДанных();

КонецФункции

// См. ЗащитаПерсональныхДанныхСлужебный.УничтожаемыеПерсональныеДанные

Функция УничтожаемыеПерсональныеДанные() Экспорт

	Возврат ЗащитаПерсональныхДанныхПовтИсп.УничтожаемыеПерсональныеДанные();

КонецФункции

// См. ЗащитаПерсональныхДанныхСлужебный.ПредставлениеКатегорииПерсональныхДанных

Функция ПредставлениеКатегорииПерсональныхДанных(ИмяКатегории) Экспорт

	Возврат ЗащитаПерсональныхДанныхПовтИсп.ПредставлениеКатегорииПерсональныхДанных(ИмяКатегории);

КонецФункции

// См. ЗащитаПерсональныхДанныхСлужебный.ИменаРеквизитовИсточникаСодержащихСубъект

Функция ИменаРеквизитовИсточникаСодержащихСубъект(ИмяИсточника) Экспорт

	Возврат ЗащитаПерсональныхДанныхПовтИсп.ИменаРеквизитовИсточникаСодержащихСубъект(ИмяИсточника);

КонецФункции

// См. ЗащитаПерсональныхДанныхСлужебный.МетаданныеПоТипамСубъекта

Функция МетаданныеПоТипамСубъекта() Экспорт

	Возврат ЗащитаПерсональныхДанныхПовтИсп.МетаданныеПоТипамСубъекта();

КонецФункции

// См. ЗащитаПерсональныхДанныхПовтИсп.ТипыСубъектов

Функция ТипыСубъектов() Экспорт

	Возврат ЗащитаПерсональныхДанныхПовтИсп.ТипыСубъектов();

КонецФункции

// См. ЗащитаПерсональныхДанныхПовтИсп.ТипыСубъектовДоступныхПоФункциональнымОпциям

Функция ТипыСубъектовДоступныхПоФункциональнымОпциям() Экспорт

	Возврат ЗащитаПерсональныхДанныхПовтИсп.ТипыСубъектовДоступныхПоФункциональнымОпциям();

КонецФункции

// См. ЗащитаПерсональныхДанныхПовтИсп.СубъектДоступенПоФункциональнымОпциям

Функция СубъектДоступенПоФункциональнымОпциям(ИмяОбъекта) Экспорт

	Возврат ЗащитаПерсональныхДанныхПовтИсп.СубъектДоступенПоФункциональнымОпциям(ИмяОбъекта);

КонецФункции

// См. ЗащитаПерсональныхДанныхПовтИсп.ИменаМетаданныхПоТипамСубъекта

Функция ИменаМетаданныхПоТипамСубъекта() Экспорт

	Возврат ЗащитаПерсональныхДанныхПовтИсп.ИменаМетаданныхПоТипамСубъекта();

КонецФункции

// Возвращаемое значение:
//  Структура - описание данных субъекта:
//   * Субъект - ОпределяемыйТип.СубъектПерсональныхДанных
//   * ФИО - Строка
//   * Адрес - Строка
//   * ПаспортныеДанные - Строка
//

Функция ОписаниеДанныхСубъекта() Экспорт

	ДанныеСубъекта = Новый Структура;
	ДанныеСубъекта.Вставить("Субъект");
	ДанныеСубъекта.Вставить("ФИО", "");
	ДанныеСубъекта.Вставить("Адрес", "");
	ДанныеСубъекта.Вставить("ПаспортныеДанные", "");

	Возврат ДанныеСубъекта;

КонецФункции

// Возвращаемое значение:
//  Структура - описание регистрации согласия на обработку персональных данных:
//   * Организация - ОпределяемыйТип.Организация
//   * Субъект - ОпределяемыйТип.СубъектПерсональныхДанных
//   * ДатаРегистрации - Дата
//   * Действует - Булево
//   * СрокДействия - Дата
//

Функция ОписаниеРегистрацииСогласияНаОбработкуПерсональныхДанных() Экспорт

	Описание = Новый Структура;
	Описание.Вставить("Организация");
	Описание.Вставить("Субъект");
	Описание.Вставить("ДатаРегистрации", Дата(1, 1, 1));
	Описание.Вставить("Действует", Ложь);
	Описание.Вставить("СрокДействия", Дата(1, 1, 1));

	Возврат Описание;

КонецФункции

Процедура ЗарегистрироватьСведенияОСогласииНаОбработкуПерсональныхДанных(Движения, ОписаниеРегистрации) Экспорт

	НоваяЗапись = Движения.СогласияНаОбработкуПерсональныхДанных.Добавить();

	ЗаполнитьЗначенияСвойств(НоваяЗапись, ОписаниеРегистрации);
	НоваяЗапись.Период = ОписаниеРегистрации.ДатаРегистрации;

	Движения.СогласияНаОбработкуПерсональныхДанных.Записывать = Истина;

КонецПроцедуры

// Параметры:
//  Организация - ОпределяемыйТип.Организация
//

[Assistant] Функция КатегорииУничтожаемыхДанныхСубъектов(Субъекты)


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

Функция ИмяФункции(ТаблицаИсключений)

	Если Не ЗначениеЗаполнено(ТаблицаИсключений) Тогда
		Возврат Новый Массив;
	КонецЕсли;

	СубъектыИсключения = Новый Массив;

	Для Каждого СтрокаИсключения Из ТаблицаИсключений Цикл

		СубъектыИсключения.Добавить(СтрокаИсключения.Субъект);

		ТекстСообщения = НСтр("ru = 'Персональные данные субъекта ""%1"" не могут быть уничтожены по причине:
		|%2.'");
		ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстСообщения,
			СтрокаИсключения.Субъект, СтрокаИсключения.ПричинаОтменыУничтожения);
		ОбщегоНазначения.СообщитьПользователю(ТекстСообщения);

	КонецЦикла;

	Возврат СубъектыИсключения;

КонецФункции

// Определяет наличие уничтоженных персональных данных в реквизитах передаваемого объекта.
// Если в реквизитах объекта находится субъект с уничтоженными персональными данными, значит и сам объект
// был обработан в ходе уничтожения персональных данных.
//
// Параметры:
//  Объект - СправочникОбъект, ДокументОбъект - объект со ссылкой на субъект в табличной части.
//  ПолныеИменаРеквизитов - Массив из Строка - полные имена реквизитов, содержащих ссылку на субъект, разделенные запятой:
//		Например: "ФизическоеЛицо" или "ФизическиеЛица.ФизическоеЛицо".
//
// Возвращаемое значение:
//  Булево - признак наличия уничтоженных персональных данных.
//

Функция ЕстьУничтоженныеПерсональныеДанные(Объект, ПолныеИменаРеквизитов)

	ЕстьУничтоженные = Ложь;
	ЧастиИменРеквизитов = Новый Массив;

	Для Каждого ПолноеИмяРеквизита Из ПолныеИменаРеквизитов Цикл
		ПолноеИмяРеквизита = СокрЛП(ПолноеИмяРеквизита);
		ЧастиИмениРеквизита = СтрРазделить(ПолноеИмяРеквизита, ".", Ложь);
		ЧастиИменРеквизитов.Добавить(ЧастиИмениРеквизита);
	КонецЦикла;

	Если ЗначениеЗаполнено(ЧастиИменРеквизитов) Тогда

		Субъекты = Новый Массив;
		Для Каждого ЧастиИмени Из ЧастиИменРеквизитов Цикл

			Если ЧастиИмени.Количество() > 1 Тогда
				ТЧОбъекта = Объект[ЧастиИмени[0]];
				Если ТЧОбъекта.Количество() = 0 Тогда
					Продолжить;
				КонецЕсли;
				СубъектыТЧ = ТЧОбъекта.ВыгрузитьКолонку(ЧастиИмени[1]);
				ОбщегоНазначенияКлиентСервер.ДополнитьМассив(Субъекты, СубъектыТЧ);
			Иначе
				Субъект = Объект[ЧастиИмени[0]];
				Субъекты.Добавить(Субъект);
			КонецЕсли;

		КонецЦикла;

		ЕстьУничтоженные = РегистрыСведений.УничтоженныеПерсональныеДанные.ЕстьСубъектыСУничтоженнымиПерсональнымиДанными(
			Субъекты);

	КонецЕсли;

	Возврат ЕстьУничтоженные;

КонецФункции

// Параметры:
//  ТекстЗапроса - Строка
//
// Возвращаемое значение:
//  Массив из ОпределяемыйТип.СубъектПерсональныхДанных
//

Функция СубъектыПоЗапросу(ТекстЗапроса)

	МетаданныеСубъектов = МетаданныеПоТипамСубъекта();

	Субъекты = Новый Массив;

	Для Каждого МетаданныеСубъекта Из МетаданныеСубъектов Цикл
		Запрос = Новый Запрос;
		Запрос.Текст = ТекстЗапросаДляТипаСубъекта(МетаданныеСубъекта.Значение, ТекстЗапроса);
		//@skip-check query-in-loop - запрос в цикле по разным типам субъектов, проектное решение.
		РезультатЗапроса = Запрос.Выполнить();
		НовыеСубъекты = РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("Ссылка");
		ОбщегоНазначенияКлиентСервер.ДополнитьМассив(Субъекты, НовыеСубъекты);
	КонецЦикла;

	Возврат Субъекты;

КонецФункции

// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - метаданные субъекта.
//  ТекстЗапроса - Строка - исходный текст запроса.
//
// Возвращаемое значение:
//  Строка - итоговый текст запроса.
//

Функция ТекстЗапросаДляТипаСубъекта(ОбъектМетаданных, ТекстЗапроса)

	ПолноеИмя = ОбъектМетаданных.ПолноеИмя();

	СхемаЗапроса = Новый СхемаЗапроса;
	СхемаЗапроса.УстановитьТекстЗапроса(ТекстЗапроса);
	Пакет = СхемаЗапроса.ПакетЗапросов[0];
	Оператор = Пакет.Операторы[0];

	ТаблицаСубъекта = Пакет.ДоступныеТаблицы.Найти(ПолноеИмя);
	Оператор.Источники.Заменить(0, ТаблицаСубъекта);
	Оператор.Источники[0].Источник.Псевдоним = "Таблица";

	Если ОбъектМетаданных.Иерархический
		И ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(ОбъектМетаданных, "ВидИерархии")
		И ОбъектМетаданных["ВидИерархии"] = Метаданные.СвойстваОбъектов.ВидИерархии.ИерархияГруппИЭлементов Тогда

		Оператор.Отбор.Добавить("НЕ Таблица.ЭтоГруппа");

	КонецЕсли;

	Возврат СхемаЗапроса.ПолучитьТекстЗапроса();

КонецФункции

// Возвращаемое значение:
//  Строка
//

Функция ТекстЗапросаСубъектовСНеуничтоженнымиДанными()

	ТекстЗапроса =
		"ВЫБРАТЬ ПЕРВЫЕ 10000
		|	Таблица.Ссылка
		|ИЗ
		|	&ИмяТаблицы КАК Таблица
		|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.УничтоженныеПерсональныеДанные КАК УничтоженныеПерсональныеДанные
		|		ПО Таблица.Ссылка = УничтоженныеПерсональныеДанные.Субъект
		|ГДЕ
		|	УничтоженныеПерсональныеДанные.Субъект ЕСТЬ NULL";

	Возврат ТекстЗапроса;

КонецФункции

// Возвращаемое значение:
//  Строка
//

Функция ТекстЗапросаСубъектовДляРасчетаСроковХранения()

	ТекстЗапроса =
		"ВЫБРАТЬ ПЕРВЫЕ 10000
		|	Таблица.Ссылка
		|ИЗ
		|	&ИмяТаблицы КАК Таблица
		|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СубъектыДляРасчетаСроковХранения КАК СубъектыДляРасчетаСроковХранения
		|		ПО Таблица.Ссылка = СубъектыДляРасчетаСроковХранения.Субъект
		|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.УничтоженныеПерсональныеДанные КАК УничтоженныеПерсональныеДанные
		|		ПО Таблица.Ссылка = УничтоженныеПерсональныеДанные.Субъект
		|ГДЕ
		|	СубъектыДляРасчетаСроковХранения.Субъект ЕСТЬ NULL
		|	И УничтоженныеПерсональныеДанные.Субъект ЕСТЬ NULL";

	Возврат ТекстЗапроса;

КонецФункции

// Параметры:
//  УничтоженныеДанные - ТаблицаЗначений:
//   * Субъект - ОпределяемыйТип.СубъектПерсональныхДанных
//   * ДатаСкрытия - Дата
//

Процедура ЗаполнитьРегистрУничтоженныхДанных(УничтоженныеДанные)

	НаборЗаписей = РегистрыСведений.УничтоженныеПерсональныеДанные.СоздатьНаборЗаписей();

	Для Каждого СтрокаТаблицы Из УничтоженныеДанные Цикл

		НаборЗаписей.Отбор.Субъект.Установить(СтрокаТаблицы.Субъект);

		НоваяЗапись = НаборЗаписей.Добавить();
		НоваяЗапись.Субъект = СтрокаТаблицы.Субъект;
		НоваяЗапись.ДатаУничтожения = СтрокаТаблицы.ДатаСкрытия;

		ОбновлениеИнформационнойБазы.ЗаписатьДанные(НаборЗаписей);

		НаборЗаписей.Очистить();

	КонецЦикла;

КонецПроцедуры

Процедура ЗаполнитьУничтоженныеПерсональныеДанные()

	Блокировка = Новый БлокировкаДанных();
	Блокировка.Добавить(Метаданные.РегистрыСведений.СубъектыДляСкрытияПерсональныхДанных.ПолноеИмя());
	Блокировка.Добавить(Метаданные.РегистрыСведений.УничтоженныеПерсональныеДанные.ПолноеИмя());

	Запрос = Новый Запрос;
	Запрос.Текст =
		"ВЫБРАТЬ ПЕРВЫЕ 10000
		|	СубъектыДляСкрытияПерсональныхДанных.Субъект,
		|	СубъектыДляСкрытияПерсональныхДанных.ДатаСкрытия
		|ИЗ
		|	РегистрСведений.СубъектыДляСкрытияПерсональныхДанных КАК СубъектыДляСкрытияПерсональныхДанных
		|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.УничтоженныеПерсональныеДанные КАК УничтоженныеПерсональныеДанные
		|		ПО СубъектыДляСкрытияПерсональныхДанных.Субъект = УничтоженныеПерсональныеДанные.Субъект
		|ГДЕ
		|	УничтоженныеПерсональныеДанные.Субъект ЕСТЬ NULL
		|	И
		|		СубъектыДляСкрытияПерсональныхДанных.Состояние = ЗНАЧЕНИЕ(Перечисление.СостоянияСубъектовДляСкрытия.СкрытиеВыполнено)";

	Пока Истина Цикл

		НачатьТранзакцию();
		Попытка
			Блокировка.Заблокировать();
			РезультатЗапроса = Запрос.Выполнить();

			Если РезультатЗапроса.Пустой() Тогда
				ЗафиксироватьТранзакцию();
				Возврат;
			КонецЕсли;

			УничтоженныеДанные = РезультатЗапроса.Выгрузить();
			ЗаполнитьРегистрУничтоженныхДанных(УничтоженныеДанные);

			ЗафиксироватьТранзакцию();
		Исключение
			ОтменитьТранзакцию();
			ВызватьИсключение;
		КонецПопытки;

	КонецЦикла;

КонецПроцедуры

// Параметры:
//  Субъекты - Массив из ОпределяемыйТип.СубъектПерсональныхДанных
//

[Assistant] Функция ОбработатьТаблицуИсключений(ТаблицаИсключений)


[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало функция `ИменаРеквизитовИсточникаСодержащихСубъект`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

Функция ИменаРеквизитовИсточникаСодержащихСубъект(ИмяИсточника)
Экспорт

	ПоляСведений = ИменаПолейСведенийОПерсональныхДанныхОбъекта(ИмяИсточника);
	ПоляСодержащиеСубъект = ПоляСведений.ПоляСодержащиеСубъект;
	ПоляПерсональныхДанных = ПоляСведений.ПоляПерсональныхДанных;

	ИменаРеквизитовСодержащихСубъект = Новый Массив; // Массив из Строка
	МетаданныеПоТипамСубъекта = ЗащитаПерсональныхДанных.МетаданныеПоТипамСубъекта();

	МетаданныеИсточника = Метаданные.НайтиПоПолномуИмени(ИмяИсточника); // ОбъектМетаданныхДокумент, ОбъектМетаданныхСправочник, ОбъектМетаданныхРегистрСведений
	ИсточникЭтоРегистр = ОбщегоНазначения.ЭтоРегистр(МетаданныеИсточника);
	ТипыСсылкиИсточника = ?(ИсточникЭтоРегистр, Новый Массив, МетаданныеИсточника.СтандартныеРеквизиты.Ссылка.Тип.Типы());
	ИсточникИмеетВладельца = ОбщегоНазначения.ЭтоСправочник(МетаданныеИсточника)
		И МетаданныеИсточника.Владельцы.Количество() > 0;

	ИменаТЧСодержащихСведения = Новый Массив; // Массив из Строка

	Если Не ИсточникЭтоРегистр Тогда

		ИменаТабличныхЧастей = Новый Массив; // Массив из Строка
		ТабличныеЧасти = МетаданныеИсточника.ТабличныеЧасти;

		Для Каждого ТабличнаяЧасть Из ТабличныеЧасти Цикл
			ИменаТабличныхЧастей.Добавить(ТабличнаяЧасть.Имя);
		КонецЦикла;

		ИменаТЧСодержащихСведения = ИменаТЧОбъектаСодержащихСведенияОПерсональныхДанных(ИменаТабличныхЧастей,
			ПоляПерсональныхДанных, ПоляСодержащиеСубъект);

	КонецЕсли;

	Для Каждого ТипСубъектаИМетаданные Из МетаданныеПоТипамСубъекта Цикл

		ТипСубъекта = ТипСубъектаИМетаданные.Ключ; // Тип
		МетаданныеСубъекта = ТипСубъектаИМетаданные.Значение;

		ИменаРеквизитовИсточника = Новый Массив; // Массив из Строка
		ИменаРеквизитовТЧИсточника = Новый Соответствие;

		Если ИсточникЭтоРегистр Тогда

			ИменаИзмеренийТипа = ИменаИзмеренийРегистраПоТипу(МетаданныеИсточника, ТипСубъекта);
			ОбщегоНазначенияКлиентСервер.ДополнитьМассив(ИменаРеквизитовИсточника, ИменаИзмеренийТипа);

		Иначе

			Если ТипыСсылкиИсточника.Найти(ТипСубъекта) <> Неопределено Тогда
				ИменаРеквизитовИсточника.Добавить("Ссылка");
			Иначе

				Если ИсточникИмеетВладельца Тогда

					Если МетаданныеИсточника.Владельцы.Содержит(МетаданныеСубъекта) Тогда
						ИменаРеквизитовИсточника.Добавить("Владелец");
					КонецЕсли;

				КонецЕсли;

				Если ИменаРеквизитовИсточника.Количество() = 0 Тогда

					ИменаРеквизитовТипа = ИменаРеквизитовПоТипу(МетаданныеИсточника, ТипСубъекта);
					ОбщегоНазначенияКлиентСервер.ДополнитьМассив(ИменаРеквизитовИсточника, ИменаРеквизитовТипа);

				КонецЕсли;
    // TODO: допиши оставшуюся часть

[Assistant]
Функция ИменаРеквизитовИсточникаСодержащихСубъект(ИмяИсточника) Экспорт

	ПоляСведений = ИменаПолейСведенийОПерсональныхДанныхОбъекта(ИмяИсточника);
	ПоляСодержащиеСубъект = ПоляСведений.ПоляСодержащиеСубъект;
	ПоляПерсональныхДанных = ПоляСведений.ПоляПерсональныхДанных;

	ИменаРеквизитовСодержащихСубъект = Новый Массив; // Массив из Строка
	МетаданныеПоТипамСубъекта = ЗащитаПерсональныхДанных.МетаданныеПоТипамСубъекта();

	МетаданныеИсточника = Метаданные.НайтиПоПолномуИмени(ИмяИсточника); // ОбъектМетаданныхДокумент, ОбъектМетаданныхСправочник, ОбъектМетаданныхРегистрСведений
	ИсточникЭтоРегистр = ОбщегоНазначения.ЭтоРегистр(МетаданныеИсточника);
	ТипыСсылкиИсточника = ?(ИсточникЭтоРегистр, Новый Массив, МетаданныеИсточника.СтандартныеРеквизиты.Ссылка.Тип.Типы());
	ИсточникИмеетВладельца = ОбщегоНазначения.ЭтоСправочник(МетаданныеИсточника)
		И МетаданныеИсточника.Владельцы.Количество() > 0;

	ИменаТЧСодержащихСведения = Новый Массив; // Массив из Строка

	Если Не ИсточникЭтоРегистр Тогда

		ИменаТабличныхЧастей = Новый Массив; // Массив из Строка
		ТабличныеЧасти = МетаданныеИсточника.ТабличныеЧасти;

		Для Каждого ТабличнаяЧасть Из ТабличныеЧасти Цикл
			ИменаТабличныхЧастей.Добавить(ТабличнаяЧасть.Имя);
		КонецЦикла;

		ИменаТЧСодержащихСведения = ИменаТЧОбъектаСодержащихСведенияОПерсональныхДанных(ИменаТабличныхЧастей,
			ПоляПерсональныхДанных, ПоляСодержащиеСубъект);

	КонецЕсли;

	Для Каждого ТипСубъектаИМетаданные Из МетаданныеПоТипамСубъекта Цикл

		ТипСубъекта = ТипСубъектаИМетаданные.Ключ; // Тип
		МетаданныеСубъекта = ТипСубъектаИМетаданные.Значение;

		ИменаРеквизитовИсточника = Новый Массив; // Массив из Строка
		ИменаРеквизитовТЧИсточника = Новый Соответствие;

		Если ИсточникЭтоРегистр Тогда

			ИменаИзмеренийТипа = ИменаИзмеренийРегистраПоТипу(МетаданныеИсточника, ТипСубъекта);
			ОбщегоНазначенияКлиентСервер.ДополнитьМассив(ИменаРеквизитовИсточника, ИменаИзмеренийТипа);

		Иначе

			Если ТипыСсылкиИсточника.Найти(ТипСубъекта) <> Неопределено Тогда
				ИменаРеквизитовИсточника.Добавить("Ссылка");
			Иначе

				Если ИсточникИмеетВладельца Тогда

					Если МетаданныеИсточника.Владельцы.Содержит(МетаданныеСубъекта) Тогда
						ИменаРеквизитовИсточника.Добавить("Владелец");
					КонецЕсли;

				КонецЕсли;

				Если ИменаРеквизитовИсточника.Количество() = 0 Тогда

					ИменаРеквизитовТипа = ИменаРеквизитовПоТипу(МетаданныеИсточника, ТипСубъекта);
					ОбщегоНазначенияКлиентСервер.ДополнитьМассив(ИменаРеквизитовИсточника, ИменаРеквизитовТипа);

				КонецЕсли;

			КонецЕсли;

			Для Каждого ИмяТабличнойЧасти Из ИменаТЧСодержащихСведения Цикл

				ИменаРеквизитовТЧТипа = ИменаРеквизитовТЧОбъектаПоТипу(МетаданныеИсточника,	ИмяТабличнойЧасти,
					ТипСубъекта);
				Если ИменаРеквизитовТЧТипа.Количество() > 0 Тогда
					ИменаРеквизитовТЧИсточника.Вставить(ИмяТабличнойЧасти, ИменаРеквизитовТЧТипа);
				КонецЕсли;

			КонецЦикла;

		КонецЕсли;

		Для Каждого ИмяРеквизита Из ИменаРеквизитовИсточника Цикл

			Если ПоляСодержащиеСубъект.Найти(ИмяРеквизита) <> Неопределено Тогда
				ИменаРеквизитовСодержащихСубъект.Добавить(ИмяРеквизита);
			КонецЕсли;

		КонецЦикла;

		Для Каждого ТЧИРеквизиты Из ИменаРеквизитовТЧИсточника Цикл

			ИменаРеквизитовТЧ = ТЧИРеквизиты.Значение; // Массив из Строка
			Для Каждого ИмяРеквизита Из ИменаРеквизитовТЧ Цикл

				Если ПоляСодержащиеСубъект.Найти(ИмяРеквизита) <> Неопределено Тогда
					ИменаРеквизитовСодержащихСубъект.Добавить(ИмяРеквизита);
				КонецЕсли;

			КонецЦикла;

		КонецЦикла;

		Если ИменаРеквизитовСодержащихСубъект.Количество() > 0 Тогда
			Прервать;
		КонецЕсли;

	КонецЦикла;

	Возврат Новый ФиксированныйМассив(ИменаРеквизитовСодержащихСубъект);

КонецФункции

// Возвращает по полному имени объекта имена полей, содержащих уничтожаемые персональные данные субъекта,
// и имена полей, содержащих ссылку на субъекта.
//
// Параметры:
//  ИмяОбъекта - Строка - полное имя объекта метаданных. Пример: "Справочник.ФизическиеЛица".
//
// Возвращаемое значение:
//  Структура - имена полей скрываемых персональных данных объекта:
//   * ПоляПерсональныхДанных - Массив из Строка - например: "ИНН" или "ФизическиеЛица.ИНН".
//   * ПоляСодержащиеСубъект - Массив из Строка - например: "ФизическоеЛицо" или "ФизическиеЛица.ФизическоеЛицо".
//

Функция ИменаПолейСведенийОПерсональныхДанныхОбъекта(ИмяОбъекта)

	ИменаПолейСодержащихСубъект = Новый Массив; // Массив из Строка
	ИменаСкрываемыхПолей = Новый Массив; // Массив из Строка

	ТаблицаСведений = ЗащитаПерсональныхДанных.УничтожаемыеПерсональныеДанные();
	СтрокиСведений = ТаблицаСведений.НайтиСтроки(Новый Структура("Объект", ИмяОбъекта));

	Для Каждого СтрокаСведений Из СтрокиСведений Цикл

		Если ТипЗнч(СтрокаСведений.Поля) = Тип("Строка") Тогда
			СкрываемыеПоля = СтрРазделить(СтрокаСведений.Поля, ",");
		Иначе
			СкрываемыеПоля = СтрокаСведений.Поля;
		КонецЕсли;
		Для Каждого ИмяПоля Из СкрываемыеПоля Цикл
			ИменаСкрываемыхПолей.Добавить(КраткоеИмяПоля(ИмяПоля, ИмяОбъекта));
		КонецЦикла;

		ПоляСодержащиеСубъект = СтрРазделить(СтрокаСведений.ПолеСубъект, ",|");
		Для Каждого ИмяПоля Из ПоляСодержащиеСубъект Цикл
			ИменаПолейСодержащихСубъект.Добавить(КраткоеИмяПоля(ИмяПоля, ИмяОбъекта));
		КонецЦикла;

	КонецЦикла;

	Возврат Новый Структура("ПоляПерсональныхДанных,ПоляСодержащиеСубъект",
		ОбщегоНазначенияКлиентСервер.СвернутьМассив(ИменаСкрываемыхПолей),
		ОбщегоНазначенияКлиентСервер.СвернутьМассив(ИменаПолейСодержащихСубъект));

КонецФункции

Функция ИменаТЧОбъектаСодержащихСведенияОПерсональныхДанных(ИменаТЧОбъекта, Знач ИменаРеквизитов,
	Знач ПоляСодержащиеСубъект)

	ИменаТЧСодержащихСведения = Новый Массив; // Массив из Строка

	ОбщегоНазначенияКлиентСервер.ДополнитьМассив(ИменаРеквизитов, ПоляСодержащиеСубъект);

	Для Каждого ИмяТЧОбъекта Из ИменаТЧОбъекта Цикл

		ПодстрокаПоиска = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("%1.", ИмяТЧОбъекта);
		Для Каждого ИмяРеквизита Из ИменаРеквизитов Цикл

			Если СтрНайти(ИмяРеквизита, ПодстрокаПоиска) <> 0 Тогда

				ИменаТЧСодержащихСведения.Добавить(ИмяТЧОбъекта);
				Прервать;

			КонецЕсли;

		КонецЦикла;

	КонецЦикла;

	Возврат ИменаТЧСодержащихСведения;

КонецФункции

// Преобразует полное имя поля в краткую форму.
// Например, "Документ.АктОбУничтоженииПерсональныхДанных.ТабличнаяЧасть.КатегорииДанных.Реквизит.ИмяОбъекта"
// преобразуется в "КатегорииДанных.ИмяОбъекта".
//
// Параметры:
//  ПолноеИмяПоля - Строка, Произвольный - полное имя поля
//  ПолноеИмяОбъекта - Строка - полное имя объекта
//
// Возвращаемое значение:
//  Строка - краткое имя поля
//

Функция КраткоеИмяПоля(ПолноеИмяПоля, ПолноеИмяОбъекта) Экспорт

	ИмяПоля = СтрЗаменить(СокрЛП(ПолноеИмяПоля), ПолноеИмяОбъекта, "");

	Если СтрНайти(ИмяПоля, ".ТабличнаяЧасть.") > 0 Тогда
		ИмяПоля = СтрЗаменить(СтрЗаменить(ИмяПоля, ".Реквизит.", "."), ".ТабличнаяЧасть.", "");
	Иначе
		ИмяПоля = СтрЗаменить(ИмяПоля, ".Реквизит.", "");
		ИмяПоля = СтрЗаменить(ИмяПоля, ".Измерение.", "");
		ИмяПоля = СтрЗаменить(ИмяПоля, ".Ресурс.", "");
	КонецЕсли;

	Возврат ИмяПоля;

КонецФункции

// Возвращаемое значение:
//   ФиксированноеСоответствие из КлючИЗначение:
//    * Ключ - Тип
//    * Значение -  ОбъектМетаданных
//

Функция МетаданныеПоТипамСубъекта() Экспорт

	ТипыСубъектов = ЗащитаПерсональныхДанных.ТипыСубъектов();

	МетаданныеПоТипуСубъектов = Новый Соответствие;
	Для Каждого ТипСубъекта Из ТипыСубъектов Цикл
		МетаданныеПоТипуСубъектов.Вставить(ТипСубъекта, Метаданные.НайтиПоТипу(ТипСубъекта));
	КонецЦикла;

	Возврат Новый ФиксированноеСоответствие(МетаданныеПоТипуСубъектов);

КонецФункции

// Возвращаемое значение:
//   ФиксированныйМассив из Тип - типы субъектов персональных данных.
//

Функция ТипыСубъектов() Экспорт

	ТипыСубъектов = Метаданные.ОпределяемыеТипы.СубъектПерсональныхДанных.Тип.Типы();
	ОбщегоНазначенияКлиентСервер.УдалитьЗначениеИзМассива(ТипыСубъектов,
		Тип("СправочникСсылка.ИдентификаторыОбъектовМетаданных"));

	Возврат Новый ФиксированныйМассив(ТипыСубъектов);

КонецФункции


[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало процедура `НайтиЦиклическиеСсылки`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

Процедура НайтиЦиклическиеСсылки(ОбъектМетаданных, ПараметрыПроверки)
ПолноеИмя = ОбъектМетаданных.ПолноеИмя();
	Реквизиты = ОбъектМетаданных.Реквизиты;

	ТекстЗапроса =
	"ВЫБРАТЬ ПЕРВЫЕ 1000
	|	ПсевдонимЗаданнойТаблицы.Ссылка КАК ПроблемныйОбъект,
	|	ПРЕДСТАВЛЕНИЕССЫЛКИ(ПсевдонимЗаданнойТаблицы.Ссылка) КАК Представление,
	|	ПсевдонимЗаданнойТаблицы.Родитель КАК Родитель
	|ИЗ
	|	&ОбъектМетаданных КАК ПсевдонимЗаданнойТаблицы
	|ГДЕ
	|	ПсевдонимЗаданнойТаблицы.Ссылка > &Ссылка
	|
	|УПОРЯДОЧИТЬ ПО
	|	ПсевдонимЗаданнойТаблицы.Ссылка";

	ИмяТаблицы = СтрЗаменить(ОбъектМетаданных.ПолноеИмя(), ".", "");
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ПсевдонимЗаданнойТаблицы", ИмяТаблицы);
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ОбъектМетаданных", ПолноеИмя);

	Запрос = Новый Запрос(ТекстЗапроса);
	Запрос.УстановитьПараметр("Ссылка", "");

	Результат = Запрос.Выполнить().Выгрузить();

	ПроверенныеЭлементы = Новый Соответствие;
	Пока Результат.Количество() > 0 Цикл

		Для Каждого СтрокаРезультата Из Результат Цикл

			СсылкаНаОбъект = СтрокаРезультата.ПроблемныйОбъект;
			Если ПроверенныеЭлементы[СсылкаНаОбъект] <> Неопределено Тогда
				Продолжить;
			КонецЕсли;

			ПроверяемыеЭлементы = Новый Массив;
			Если ПроверитьЗацикливаниеУровней(СсылкаНаОбъект, СтрокаРезультата.Родитель, ПроверяемыеЭлементы) Тогда

				Путь = "";
				Для Каждого ЭлементЦикла Из ПроверяемыеЭлементы Цикл
    // TODO: допиши оставшуюся часть

[Assistant]
Процедура НайтиЦиклическиеСсылки(ОбъектМетаданных, ПараметрыПроверки)

	ПолноеИмя = ОбъектМетаданных.ПолноеИмя();
	Реквизиты = ОбъектМетаданных.Реквизиты;

	ТекстЗапроса =
	"ВЫБРАТЬ ПЕРВЫЕ 1000
	|	ПсевдонимЗаданнойТаблицы.Ссылка КАК ПроблемныйОбъект,
	|	ПРЕДСТАВЛЕНИЕССЫЛКИ(ПсевдонимЗаданнойТаблицы.Ссылка) КАК Представление,
	|	ПсевдонимЗаданнойТаблицы.Родитель КАК Родитель
	|ИЗ
	|	&ОбъектМетаданных КАК ПсевдонимЗаданнойТаблицы
	|ГДЕ
	|	ПсевдонимЗаданнойТаблицы.Ссылка > &Ссылка
	|
	|УПОРЯДОЧИТЬ ПО
	|	ПсевдонимЗаданнойТаблицы.Ссылка";

	ИмяТаблицы = СтрЗаменить(ОбъектМетаданных.ПолноеИмя(), ".", "");
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ПсевдонимЗаданнойТаблицы", ИмяТаблицы);
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ОбъектМетаданных", ПолноеИмя);

	Запрос = Новый Запрос(ТекстЗапроса);
	Запрос.УстановитьПараметр("Ссылка", "");

	Результат = Запрос.Выполнить().Выгрузить();

	ПроверенныеЭлементы = Новый Соответствие;
	Пока Результат.Количество() > 0 Цикл

		Для Каждого СтрокаРезультата Из Результат Цикл

			СсылкаНаОбъект = СтрокаРезультата.ПроблемныйОбъект;
			Если ПроверенныеЭлементы[СсылкаНаОбъект] <> Неопределено Тогда
				Продолжить;
			КонецЕсли;

			ПроверяемыеЭлементы = Новый Массив;
			Если ПроверитьЗацикливаниеУровней(СсылкаНаОбъект, СтрокаРезультата.Родитель, ПроверяемыеЭлементы) Тогда

				Путь = "";
				Для Каждого ЭлементЦикла Из ПроверяемыеЭлементы Цикл
					Путь = Путь + ?(ЗначениеЗаполнено(Путь), " -> ", "") + Строка(ЭлементЦикла);
					ПроверенныеЭлементы[ЭлементЦикла] = Истина;
				КонецЦикла;

				ПредставлениеОбъекта = СтрокаРезультата.Представление;
				Если ЗначениеЗаполнено(Путь) Тогда
					УточнениеПроблемы = ПредставлениеОбъекта + " -> " + Путь + " -> " + ПредставлениеОбъекта;
				Иначе
					УточнениеПроблемы = ПредставлениеОбъекта + " -> " + ПредставлениеОбъекта;
				КонецЕсли;

				Проблема = ОписаниеПроблемы(СсылкаНаОбъект, ПараметрыПроверки); // @skip-check query-in-loop - порционная проверка ведения учета

				Проблема.УточнениеПроблемы = УточнениеПроблемы;
				Если Реквизиты.Найти("Ответственный") <> Неопределено Тогда
					Проблема.Вставить("Ответственный", ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СсылкаНаОбъект, "Ответственный"));
				КонецЕсли;

				ЗаписатьПроблему(Проблема, ПараметрыПроверки); // @skip-check query-in-loop - порционная проверка ведения учета

			КонецЕсли;

		КонецЦикла;

		Запрос.УстановитьПараметр("Ссылка", СтрокаРезультата.ПроблемныйОбъект);
		Результат = Запрос.Выполнить().Выгрузить(); // @skip-check query-in-loop - порционная проверка ведения учета

	КонецЦикла;

КонецПроцедуры

Функция ПроверитьЗацикливаниеУровней(Знач СсылкаНаОбъект, Знач ТекущийРодитель, Знач ВсеЭлементы)

	Пока ЗначениеЗаполнено(ТекущийРодитель) Цикл
		Если СсылкаНаОбъект = ТекущийРодитель Тогда
			Возврат Истина;
		КонецЕсли;
		ВсеЭлементы.Добавить(ТекущийРодитель);
		ТекущийРодитель = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ТекущийРодитель, "Родитель");
	КонецЦикла;
	Возврат Ложь;

КонецФункции

// Параметры:
//   СтандартныеРеквизиты - ОписанияСтандартныхРеквизитов
// Возвращаемое значение:
//   Булево
//

Функция ЕстьИерархия(СтандартныеРеквизиты)

	ЕстьИерархия = Ложь;
	Для Каждого СтандартныйРеквизит Из СтандартныеРеквизиты Цикл
		Если СтандартныйРеквизит.Имя = "Родитель" Тогда
			ЕстьИерархия = Истина;
			Прервать;
		КонецЕсли;
	КонецЦикла;

	Возврат ЕстьИерархия;

КонецФункции

// Исправляет циклические ссылки по принципу: у кого больше терминальных элементов в подчинении,
// тот остается родителем.
//
// Параметры:
//   Проверка - СправочникСсылка.ПравилаПроверкиУчета - проверка, найденные проблемы которой
//              исправляются данным методом.
//

Процедура ИсправитьПроблемуЦиклическихСсылок(Проверка)

	ТаблицаПотомства = Новый ТаблицаЗначений;
	ТаблицаПотомства.Колонки.Добавить("ЭлементЦикла");
	ТаблицаПотомства.Колонки.Добавить("КоличествоДетей", Новый ОписаниеТипов("Число"));

	Запрос = Новый Запрос(
	"ВЫБРАТЬ
	|	РезультатыПроверкиУчета.ПроблемныйОбъект КАК ПроблемныйОбъект,
	|	ТИПЗНАЧЕНИЯ(РезультатыПроверкиУчета.ПроблемныйОбъект) КАК ТипСсылки
	|ИЗ
	|	РегистрСведений.РезультатыПроверкиУчета КАК РезультатыПроверкиУчета
	|ГДЕ
	|	НЕ РезультатыПроверкиУчета.ИгнорироватьПроблему
	|	И РезультатыПроверкиУчета.ПравилоПроверки = &ПравилоПроверки
	|ИТОГИ ПО
	|	ТипСсылки");

	Запрос.УстановитьПараметр("ПравилоПроверки", Проверка);
	Результат = Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);

	Для Каждого СтрокаТипОбъекта Из Результат.Строки Цикл
		ПолноеИмяТаблицы = Метаданные.НайтиПоТипу(СтрокаТипОбъекта.ТипСсылки).ПолноеИмя();
		Для Каждого СтрокаОбъект Из СтрокаТипОбъекта.Строки Цикл
			НачатьТранзакцию();
			Попытка
				Блокировка = Новый БлокировкаДанных;
				ЭлементБлокировки = Блокировка.Добавить(ПолноеИмяТаблицы);
				ЭлементБлокировки.УстановитьЗначение("Ссылка", СтрокаОбъект.ПроблемныйОбъект);
				Блокировка.Заблокировать();

				ПроблемныйОбъектСсылка = СтрокаОбъект.ПроблемныйОбъект;
				Родитель = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ПроблемныйОбъектСсылка, "Родитель");

				ПроверяемыеЭлементы = Новый Массив;
				Если Не ПроверитьЗацикливаниеУровней(ПроблемныйОбъектСсылка, Родитель, ПроверяемыеЭлементы) Тогда
					ОтменитьТранзакцию();
					Продолжить;
				КонецЕсли;

				ПоследнийОбъектЦикла = ПроверяемыеЭлементы[ПроверяемыеЭлементы.Количество() - 1];

				КоличествоДетейПервого = КоличествоДочернихЭлементов(ПроблемныйОбъектСсылка, Родитель); // @skip-check query-in-loop - порционная проверка ведения учета
				КоличествоДетейВторого = КоличествоДочернихЭлементов(ПоследнийОбъектЦикла, Родитель); // @skip-check query-in-loop - порционная проверка ведения учета

				ПроблемныйОбъект = ?(КоличествоДетейПервого > КоличествоДетейВторого, ПроблемныйОбъектСсылка, ПоследнийОбъектЦикла);
				ПроблемныйОбъект = ПроблемныйОбъект.ПолучитьОбъект();
				ПроблемныйОбъект.Родитель = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(ПроблемныйОбъектСсылка.Метаданные().ПолноеИмя()).ПустаяСсылка();
				ПроблемныйОбъект.ОбменДанными.Загрузка = Истина;
				ПроблемныйОбъект.Записать();

				ЗафиксироватьТранзакцию();
			Исключение
				ОтменитьТранзакцию();
				ВызватьИсключение;
			КонецПопытки;
		КонецЦикла;
	КонецЦикла;

КонецПроцедуры

Функция КоличествоДочернихЭлементов(СсылкаНаОбъект, ИсключениеВыборки, Знач НачальноеЗначение = 0)

	КоличествоДетей = НачальноеЗначение;

	Выгрузка = ДочерниеЭлементыРодителя(СсылкаНаОбъект, ИсключениеВыборки);
	КоличествоДетей = КоличествоДетей + Выгрузка.Количество();
	Для Каждого ЭлементПотомства Из Выгрузка Цикл
		КоличествоДетей = КоличествоДочернихЭлементов(ЭлементПотомства.Ссылка, ИсключениеВыборки, КоличествоДетей); // @skip-check query-in-loop - порционная проверка ведения учета
	КонецЦикла;
	Возврат КоличествоДетей;

КонецФункции

// Возвращаемое значение:
//   ТаблицаЗначений:
//   * Ссылка - ЛюбаяСсылка
//

Функция ДочерниеЭлементыРодителя(СсылкаНаОбъект, Знач ИсключениеВыборки)
	Перем Результат;
	ТекстЗапроса =
	"ВЫБРАТЬ
	|	ПсевдонимЗаданнойТаблицы.Ссылка КАК Ссылка
	|ИЗ
	|	&ОбъектМетаданных КАК ПсевдонимЗаданнойТаблицы
	|ГДЕ
	|	ПсевдонимЗаданнойТаблицы.Родитель = &Родитель
	|	И ПсевдонимЗаданнойТаблицы.Ссылка <> &ИсключениеВыборки";

	ПолноеИмя = СсылкаНаОбъект.Метаданные().ПолноеИмя();
	ИмяТаблицы = СтрЗаменить(ПолноеИмя, ".", "");
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ПсевдонимЗаданнойТаблицы", ИмяТаблицы);
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ОбъектМетаданных", ПолноеИмя);

	Запрос = Новый Запрос(ТекстЗапроса);
	Запрос.УстановитьПараметр("Родитель",          СсылкаНаОбъект);
	Запрос.УстановитьПараметр("ИсключениеВыборки", ИсключениеВыборки);
	Результат = Запрос.Выполнить();

	Выгрузка        = Результат.Выгрузить();
	Возврат Выгрузка
КонецФункции

#КонецОбласти

#Область ПроверкаОтсутствующихПредопределенныхЭлементов


[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало функция `АвторизоватьсяНаСервереМЧДРР`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

Функция АвторизоватьсяНаСервереМЧДРР(ЦельАвторизации = "")
Экспорт

	УстановитьПривилегированныйРежим(Истина);
	ПараметрыРезультатаАвторизации = ПараметрыСеанса.ПараметрыАвторизацииВРаспределенномРеестре;
	Если ПараметрыРезультатаАвторизации <> Неопределено И ПараметрыРезультатаАвторизации.ДатаСеанса <> Неопределено
		И ПараметрыРезультатаАвторизации.РезультатАвторизации <> Неопределено Тогда

		ДатаСеанса = ТекущаяДатаСеанса();
		Если ПараметрыРезультатаАвторизации.ДатаСеанса >= ДатаСеанса - 60 * 60
			И ПараметрыРезультатаАвторизации.ДатаСеанса <= ДатаСеанса Тогда

			Возврат Новый Структура(ПараметрыРезультатаАвторизации.РезультатАвторизации);
		КонецЕсли;
	КонецЕсли;

	СвойстваСервераМЧДРР = СвойстваСервераМЧДРР();

	Результат = Новый Структура;
	Результат.Вставить("АдресСервера", 			СвойстваСервераМЧДРР.АдресСервераБезАутентификации);
	Результат.Вставить("ТокенДоступа", 			"");
	Результат.Вставить("ТекстОтвета", 			"");
	Результат.Вставить("Ошибка");

	РесурсНаСервере = СвойстваСервераМЧДРР.РесурсКорняAPI + ?(СвойстваСервераМЧДРР.ИспользоватьРасширенияAPI,
		"/token", "/vst-oauth2/oauth/token");
	ПараметрыРесурсаНаСервере = "";
	Если СвойстваСервераМЧДРР.ИспользоватьРасширенияAPI Тогда
		ТикетАутентификацииИлиДанныеПользователя = ТикетАутентификацииИлиДанныеПользователяНаПорталеПоддержки();

		Если ТикетАутентификацииИлиДанныеПользователя = Неопределено Тогда
			ЗаголовокОшибки = ?(ЦельАвторизации = "", НСтр("ru='Не удается авторизоваться на сайте интернет поддержки'"), ЦельАвторизации);
			ПараметрыОшибкиМЧДРР = ПараметрыОшибкиМЧДРР(ЗаголовокОшибки, НСтр("ru='Не удается получить тикет аутентификации или данные пользователя.'"));
			Результат.Ошибка = ПолучитьИЗаписатьОшибкуМЧДРР(ПараметрыОшибкиМЧДРР);
			Возврат Результат;
		КонецЕсли;

		Если ТикетАутентификацииИлиДанныеПользователя.Свойство("Тикет") Тогда
			ПараметрыРесурсаНаСервере = "?ticket=" + КодироватьСтроку(ТикетАутентификацииИлиДанныеПользователя.Тикет,
				СпособКодированияСтроки.КодировкаURL);
		Иначе
			ПараметрыРесурсаНаСервере = "?login=" + КодироватьСтроку(ТикетАутентификацииИлиДанныеПользователя.Логин,
				СпособКодированияСтроки.КодировкаURL)
				+ "&password=" + КодироватьСтроку(ТикетАутентификацииИлиДанныеПользователя.Пароль,
				СпособКодированияСтроки.КодировкаURL)
		КонецЕсли;
	КонецЕсли;

	ЗаголовкиHTTP = Новый Соответствие();
	ЗаголовкиHTTP.Вставить("Content-Type", "application/json");
	ЗаголовкиHTTP.Вставить("Proxy-Connection", "Keep-Alive");
	ЗаголовкиHTTP.Вставить("Pragma", "no-cache");
	Если СвойстваСервераМЧДРР.ИспользоватьРасширенияAPI И ИспользуетсяРежимТестирования() Тогда
		ЗаголовкиHTTP.Вставить("poaservertype", СвойстваСервераМЧДРР.ТестовыйСервер);
	КонецЕсли;

	ЗапросHTTP = Новый HTTPЗапрос(РесурсНаСервере + ПараметрыРесурсаНаСервере, ЗаголовкиHTTP);
	Если НЕ СвойстваСервераМЧДРР.ИспользоватьРасширенияAPI Тогда
		СтруктураЗапроса = Новый Структура;
		СтруктураЗапроса.Вставить("username", СвойстваСервераМЧДРР.ЛогинОператора);
		СтруктураЗапроса.Вставить("password", СвойстваСервераМЧДРР.ПарольОператора);
		СтруктураЗапроса.Вставить("grant_type", "password");

		ТелоЗапроса = ОбщегоНазначения.ЗначениеВJSON(СтруктураЗапроса);
		ЗапросHTTP.УстановитьТелоИзСтроки(ТелоЗапроса);
	КонецЕсли;

	ОтветHTTP = Неопределено;

	Попытка
		СоединениеHTTP = СоединениеССерверомИнтернета(СвойстваСервераМЧДРР.АдресСервера);

		Если СвойстваСервераМЧДРР.ИспользоватьРасширенияAPI Тогда
			ОтветHTTP = СоединениеHTTP.Получить(ЗапросHTTP);
		Иначе
			ОтветHTTP = СоединениеHTTP.ВызватьHTTPМетод("POST", ЗапросHTTP);
		КонецЕсли;
	Исключение
		ПредставлениеОшибки = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		ПараметрыФайловДляРасследования = ПараметрыФайловДляРасследования();
		ПараметрыФайловДляРасследования.СоединениеHTTP = СоединениеHTTP;
		ПараметрыФайловДляРасследования.Запрос = ЗапросHTTP;
		ПараметрыФайловДляРасследования.Ответ = ОтветHTTP;
		ДополнительныеФайлы = ФайлыДляРасследования(ПараметрыФайловДляРасследования);
		ЗаголовокОшибки = ?(ЦельАвторизации = "", НСтр("ru='Не удается авторизоваться на сервере Распределенного реестра ФНС России'"), ЦельАвторизации);
    // TODO: допиши оставшуюся часть

[Assistant]
Функция АвторизоватьсяНаСервереМЧДРР(ЦельАвторизации = "") Экспорт

	УстановитьПривилегированныйРежим(Истина);
	ПараметрыРезультатаАвторизации = ПараметрыСеанса.ПараметрыАвторизацииВРаспределенномРеестре;
	Если ПараметрыРезультатаАвторизации <> Неопределено И ПараметрыРезультатаАвторизации.ДатаСеанса <> Неопределено
		И ПараметрыРезультатаАвторизации.РезультатАвторизации <> Неопределено Тогда

		ДатаСеанса = ТекущаяДатаСеанса();
		Если ПараметрыРезультатаАвторизации.ДатаСеанса >= ДатаСеанса - 60 * 60
			И ПараметрыРезультатаАвторизации.ДатаСеанса <= ДатаСеанса Тогда

			Возврат Новый Структура(ПараметрыРезультатаАвторизации.РезультатАвторизации);
		КонецЕсли;
	КонецЕсли;

	СвойстваСервераМЧДРР = СвойстваСервераМЧДРР();

	Результат = Новый Структура;
	Результат.Вставить("АдресСервера", 			СвойстваСервераМЧДРР.АдресСервераБезАутентификации);
	Результат.Вставить("ТокенДоступа", 			"");
	Результат.Вставить("ТекстОтвета", 			"");
	Результат.Вставить("Ошибка");

	РесурсНаСервере = СвойстваСервераМЧДРР.РесурсКорняAPI + ?(СвойстваСервераМЧДРР.ИспользоватьРасширенияAPI,
		"/token", "/vst-oauth2/oauth/token");
	ПараметрыРесурсаНаСервере = "";
	Если СвойстваСервераМЧДРР.ИспользоватьРасширенияAPI Тогда
		ТикетАутентификацииИлиДанныеПользователя = ТикетАутентификацииИлиДанныеПользователяНаПорталеПоддержки();

		Если ТикетАутентификацииИлиДанныеПользователя = Неопределено Тогда
			ЗаголовокОшибки = ?(ЦельАвторизации = "", НСтр("ru='Не удается авторизоваться на сайте интернет поддержки'"), ЦельАвторизации);
			ПараметрыОшибкиМЧДРР = ПараметрыОшибкиМЧДРР(ЗаголовокОшибки, НСтр("ru='Не удается получить тикет аутентификации или данные пользователя.'"));
			Результат.Ошибка = ПолучитьИЗаписатьОшибкуМЧДРР(ПараметрыОшибкиМЧДРР);
			Возврат Результат;
		КонецЕсли;

		Если ТикетАутентификацииИлиДанныеПользователя.Свойство("Тикет") Тогда
			ПараметрыРесурсаНаСервере = "?ticket=" + КодироватьСтроку(ТикетАутентификацииИлиДанныеПользователя.Тикет,
				СпособКодированияСтроки.КодировкаURL);
		Иначе
			ПараметрыРесурсаНаСервере = "?login=" + КодироватьСтроку(ТикетАутентификацииИлиДанныеПользователя.Логин,
				СпособКодированияСтроки.КодировкаURL)
				+ "&password=" + КодироватьСтроку(ТикетАутентификацииИлиДанныеПользователя.Пароль,
				СпособКодированияСтроки.КодировкаURL)
		КонецЕсли;
	КонецЕсли;

	ЗаголовкиHTTP = Новый Соответствие();
	ЗаголовкиHTTP.Вставить("Content-Type", "application/json");
	ЗаголовкиHTTP.Вставить("Proxy-Connection", "Keep-Alive");
	ЗаголовкиHTTP.Вставить("Pragma", "no-cache");
	Если СвойстваСервераМЧДРР.ИспользоватьРасширенияAPI И ИспользуетсяРежимТестирования() Тогда
		ЗаголовкиHTTP.Вставить("poaservertype", СвойстваСервераМЧДРР.ТестовыйСервер);
	КонецЕсли;

	ЗапросHTTP = Новый HTTPЗапрос(РесурсНаСервере + ПараметрыРесурсаНаСервере, ЗаголовкиHTTP);
	Если НЕ СвойстваСервераМЧДРР.ИспользоватьРасширенияAPI Тогда
		СтруктураЗапроса = Новый Структура;
		СтруктураЗапроса.Вставить("username", СвойстваСервераМЧДРР.ЛогинОператора);
		СтруктураЗапроса.Вставить("password", СвойстваСервераМЧДРР.ПарольОператора);
		СтруктураЗапроса.Вставить("grant_type", "password");

		ТелоЗапроса = ОбщегоНазначения.ЗначениеВJSON(СтруктураЗапроса);
		ЗапросHTTP.УстановитьТелоИзСтроки(ТелоЗапроса);
	КонецЕсли;

	ОтветHTTP = Неопределено;

	Попытка
		СоединениеHTTP = СоединениеССерверомИнтернета(СвойстваСервераМЧДРР.АдресСервера);

		Если СвойстваСервераМЧДРР.ИспользоватьРасширенияAPI Тогда
			ОтветHTTP = СоединениеHTTP.Получить(ЗапросHTTP);
		Иначе
			ОтветHTTP = СоединениеHTTP.ВызватьHTTPМетод("POST", ЗапросHTTP);
		КонецЕсли;
	Исключение
		ПредставлениеОшибки = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		ПараметрыФайловДляРасследования = ПараметрыФайловДляРасследования();
		ПараметрыФайловДляРасследования.СоединениеHTTP = СоединениеHTTP;
		ПараметрыФайловДляРасследования.Запрос = ЗапросHTTP;
		ПараметрыФайловДляРасследования.Ответ = ОтветHTTP;
		ДополнительныеФайлы = ФайлыДляРасследования(ПараметрыФайловДляРасследования);
		ЗаголовокОшибки = ?(ЦельАвторизации = "", НСтр("ru='Не удается авторизоваться на сервере Распределенного реестра ФНС России'"), ЦельАвторизации);

		ПараметрыОшибкиМЧДРР = ПараметрыОшибкиМЧДРР(ЗаголовокОшибки, ПредставлениеОшибки);
		ПараметрыОшибкиМЧДРР.ЗапросHTTP = ЗапросHTTP;
		ПараметрыОшибкиМЧДРР.ОтветHTTP = ОтветHTTP;
		ПараметрыОшибкиМЧДРР.ДополнительныеФайлы = ДополнительныеФайлы;
		Результат.Ошибка = ПолучитьИЗаписатьОшибкуМЧДРР(ПараметрыОшибкиМЧДРР);
		Возврат Результат;
	КонецПопытки;

	Попытка
		СтруктураОтвета = ПолучитьСтруктуруОтвета(ОтветHTTP);
		Результат.ТекстОтвета = ОтветHTTP.ПолучитьТелоКакСтроку();
		Результат.ТокенДоступа = ?(ТипЗнч(СтруктураОтвета) = Тип("Структура") И СтруктураОтвета.Свойство("access_token"),
			СтруктураОтвета.access_token, "");

		КодСостоянияПриНеверномЛогинеИлиПароле = 403;
		Если ОтветHTTP.КодСостояния = КодСостоянияПриНеверномЛогинеИлиПароле И СтруктураОтвета.Свойство("message") Тогда
			СброситьДанныеАутентификацииНаПорталеПоддержки();
		КонецЕсли;
	Исключение
		ПредставлениеОшибки = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		ПараметрыФайловДляРасследования = ПараметрыФайловДляРасследования();
		ПараметрыФайловДляРасследования.СоединениеHTTP = СоединениеHTTP;
		ПараметрыФайловДляРасследования.Запрос = ЗапросHTTP;
		ПараметрыФайловДляРасследования.Ответ = ОтветHTTP;
		ДополнительныеФайлы = ФайлыДляРасследования(ПараметрыФайловДляРасследования);
		ЗаголовокОшибки = ?(ЦельАвторизации = "", НСтр("ru='Отказ при получении токена доступа на сервере Распределенного реестра ФНС России'"), ЦельАвторизации);
		ПараметрыОшибкиМЧДРР = ПараметрыОшибкиМЧДРР(ЗаголовокОшибки, ПредставлениеОшибки);
		ПараметрыОшибкиМЧДРР.ЗапросHTTP = ЗапросHTTP;
		ПараметрыОшибкиМЧДРР.ОтветHTTP = ОтветHTTP;
		ПараметрыОшибкиМЧДРР.СтруктураОтвета = СтруктураОтвета;
		ПараметрыОшибкиМЧДРР.ДополнительныеФайлы = ДополнительныеФайлы;
		Результат.Ошибка = ПолучитьИЗаписатьОшибкуМЧДРР(ПараметрыОшибкиМЧДРР);
		Возврат Результат;
	КонецПопытки;

	Если НЕ ЗначениеЗаполнено(Результат.ТокенДоступа) Тогда
		ПараметрыФайловДляРасследования = ПараметрыФайловДляРасследования();
		ПараметрыФайловДляРасследования.СоединениеHTTP = СоединениеHTTP;
		ПараметрыФайловДляРасследования.Запрос = ЗапросHTTP;
		ПараметрыФайловДляРасследования.Ответ = ОтветHTTP;
		ДополнительныеФайлы = ФайлыДляРасследования(ПараметрыФайловДляРасследования);
		ЗаголовокОшибки = ?(ЦельАвторизации = "", НСтр("ru='Распределенный реестр ФНС России не предоставил токен для авторизации'"), ЦельАвторизации);
		ПараметрыОшибкиМЧДРР = ПараметрыОшибкиМЧДРР(ЗаголовокОшибки,
			НСтр("ru='Распределенный реестр ФНС России не предоставил токен для авторизации.'"));
		ПараметрыОшибкиМЧДРР.ЗапросHTTP = ЗапросHTTP;
		ПараметрыОшибкиМЧДРР.ОтветHTTP = ОтветHTTP;
		ПараметрыОшибкиМЧДРР.СтруктураОтвета = СтруктураОтвета;
		ПараметрыОшибкиМЧДРР.ДополнительныеФайлы = ДополнительныеФайлы;
		Результат.Ошибка = ПолучитьИЗаписатьОшибкуМЧДРР(ПараметрыОшибкиМЧДРР);
		Возврат Результат;
	КонецЕсли;

	ПараметрыРезультатаАвторизации = ПараметрыРезультатаАвторизацииНаСервереМЧД();
	ПараметрыРезультатаАвторизации.ДатаСеанса 			= ТекущаяДатаСеанса();
	ПараметрыРезультатаАвторизации.РезультатАвторизации = Новый ФиксированнаяСтруктура(Результат);
	ПараметрыСеанса.ПараметрыАвторизацииВРаспределенномРеестре = Новый ФиксированнаяСтруктура(ПараметрыРезультатаАвторизации);

	Возврат Результат;

КонецФункции


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

Процедура ИмяФункции(Знач Элемент, Знач ВыбранноеЗначение, Знач ДанныеФормыКоллекция=Неопределено) Экспорт

	Если ТипЗнч(ВыбранноеЗначение)<>Тип("Структура") Тогда
		Возврат;
	КонецЕсли;

	ИмяРеквизитаИдентификатора = ВыбранноеЗначение.ИмяРеквизита + "_Ключ";
	ИмяРеквизитаПредставления  = ВыбранноеЗначение.ИмяРеквизита;

	ТипЭлемента = ТипЗнч(Элемент);
	Если ТипЭлемента=Тип("ТаблицаФормы") Тогда

		Если ВыбранноеЗначение.РежимПодбора Тогда
			Если ДанныеФормыКоллекция<>Неопределено Тогда
				Фильтр = Новый Структура(ИмяРеквизитаИдентификатора, ВыбранноеЗначение.Идентификатор);
				СуществующиеСтроки = ДанныеФормыКоллекция.НайтиСтроки(Фильтр);
				Если СуществующиеСтроки.Количество() > 0 Тогда
					Возврат;
				КонецЕсли;
			КонецЕсли;

			Элемент.ДобавитьСтроку();
		КонецЕсли;

		ТекущиеДанные = Элемент.ТекущиеДанные;
		Если ТекущиеДанные<>Неопределено Тогда
			ТекущиеДанные[ИмяРеквизитаИдентификатора] = ВыбранноеЗначение.Идентификатор;
			ТекущиеДанные[ИмяРеквизитаПредставления]  = ВыбранноеЗначение.Представление;
		КонецЕсли;

	ИначеЕсли ТипЭлемента=Тип("ФормаКлиентскогоПриложения") Тогда
		Элемент[ИмяРеквизитаИдентификатора] = ВыбранноеЗначение.Идентификатор;
		Элемент[ИмяРеквизитаПредставления]  = ВыбранноеЗначение.Представление;

	КонецЕсли;

КонецПроцедуры

// Проверяет установку флага "Использовать" для всех строк таблицы.
//
// Параметры:
//  Таблица - ТаблицаЗначений - проверяемая таблица.
//
// Возвращаемое значение:
//  Булево - признак использования всех элементов.
//

Функция ВТаблицеОтмеченыВсеЭлементы(Таблица) Экспорт

	Для Каждого Элемент Из Таблица Цикл

		Если Элемент.Использовать = Ложь Тогда

			Возврат Ложь;

		КонецЕсли;

	КонецЦикла;

	Возврат Истина;
КонецФункции

// Выполняет удаление настройки синхронизации данных.
//
// Параметры:
//   УзелИнформационнойБазы - ПланОбменаСсылка - узел плана обмена, соответствующий отключаемому обмену.
//

Процедура УдалитьНастройкуСинхронизации(Знач УзелИнформационнойБазы) Экспорт

	Если ОбменДаннымиВызовСервера.УзелЯвляетсяГлавным(УзелИнформационнойБазы) Тогда
		ТекстПредупреждения = НСтр("ru = 'Отключение информационной базы от главного узла можно выполнить
			|с помощью параметра запуска конфигуратора /ResetMasterNode.'");
		ПоказатьПредупреждение(, ТекстПредупреждения);
	Иначе
		ПараметрыПомощника = Новый Структура;
		ПараметрыПомощника.Вставить("УзелОбмена", УзелИнформационнойБазы);

		ОткрытьФорму("Обработка.ПомощникСозданияОбменаДанными.Форма.УдалениеНастройкиСинхронизации", ПараметрыПомощника);
	КонецЕсли;

КонецПроцедуры

// Процедура-обработчик записи узла плана обмена. При необходимости выполняет запись узла при помощи длительной операции
//
// Параметры:
//  Форма - ФормаКлиентскогоПриложения - узел плана обмена.
//  Отказ - Булево - признак отказа от записи узла плана обмена.
//  ПараметрыЗаписи - Структура - произвольные параметры записи. См. описание события ПослеЗаписи в синтакс-помощнике.
//

Процедура ПередЗаписью(Форма, Отказ, ПараметрыЗаписи) Экспорт

	Если Отказ Тогда
		Возврат;
	КонецЕсли;

	РезультатПроверки = ОбменДаннымиВызовСервера.ПроверитьНеобходимостьОтложеннойЗаписиУзла(Форма.Объект);

	Если РезультатПроверки.ЕстьАктивноеФоновоеЗадание Тогда

		ТекстПредупреждения = НСтр("ru = 'Уже выполняется отложенная операция записи узла.
										|Повторите попытку позже'");

		ПоказатьПредупреждение(, ТекстПредупреждения);

		Отказ = Истина;

	ИначеЕсли РезультатПроверки.НеобходимаДлительнаяОперация Тогда

		Объект = Форма.Объект; //ПланОбменаОбъект

		ПараметрыОбработки = Новый Структура;
		ПараметрыОбработки.Вставить("Узел", 				Объект.Ссылка);
		ПараметрыОбработки.Вставить("АдресСтруктурыУзла", 	РезультатПроверки.АдресСтруктурыУзла);

		Форма.Модифицированность = Ложь;
		Форма.Закрыть();

		ОткрытьФорму("Обработка.ОтложеннаяЗаписьУзла.Форма.Форма", ПараметрыОбработки,,,,,,РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);

		Отказ = Истина;

	КонецЕсли;

КонецПроцедуры

// Процедура-обработчик навигационной ссылки в форме узла для элементов созданных программно.
// Только при работе в модели сервиса.
//
// Параметры:
//  Форма - ФормаКлиентскогоПриложения - узел плана обмена.
//  Элемент - ЭлементыФормы
//  НавигационнаяСсылка -  Строка - сформированная навигационная ссылка
//  СтандартнаяОбработка - Булево
//

Процедура ОбработкаНавигационнойСсылкиВФормеУзла(Форма, Элемент, НавигационнаяСсылка, СтандартнаяОбработка) Экспорт

	СтандартнаяОбработка = Ложь;

	Если ОбщегоНазначенияКлиент.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбменДаннымиВМоделиСервиса") Тогда
		МодульОбменДаннымиВнутренняяПубликацияКлиент = ОбщегоНазначенияКлиент.ОбщийМодуль("ОбменДаннымиВнутренняяПубликацияКлиент");
		МодульОбменДаннымиВнутренняяПубликацияКлиент.ОбработкаНавигационнойСсылкиВФормеУзла(
			Форма, НавигационнаяСсылка, СтандартнаяОбработка);
	КонецЕсли;

КонецПроцедуры

// Открывает панель настройки синхронизации данных.
//
// Параметры:
//  ПараметрКоманды - Структура
//                  - Неопределено
//  ПараметрыВыполненияКоманды - ПараметрыВыполненияКоманды
//

Процедура ОткрытьПанельСинхронизацииДанных(ПараметрКоманды, ПараметрыВыполненияКоманды) Экспорт

	ИмяОбработки      = "";
	ИмяФормыОбработки = "";

	Если СтандартныеПодсистемыКлиент.ПараметрыРаботыКлиента().ДоступноИспользованиеРазделенныхДанных Тогда
		Если ОбщегоНазначенияКлиент.ПодсистемаСуществует("ОбменДаннымиНастройкиПрограммы") Тогда
			ИмяОбработки      = "ПанельАдминистрированияБСД";
			ИмяФормыОбработки = "СинхронизацияДанных";
		ИначеЕсли ОбщегоНазначенияКлиент.ПодсистемаСуществует("СтандартныеПодсистемы.НастройкиПрограммы") Тогда
			ИмяОбработки      = "ПанельАдминистрированияБСП";
			ИмяФормыОбработки = "СинхронизацияДанных";
		КонецЕсли;
	Иначе
		Если Не ОбщегоНазначенияКлиент.ПодсистемаСуществует("ТехнологияСервиса") Тогда
			Возврат;
		КонецЕсли;

		ИмяОбработки      = "ПанельАдминистрированияБСПВМоделиСервиса";
		ИмяФормыОбработки = "СинхронизацияДанныхДляАдминистратораСервиса";
	КонецЕсли;

	Если ИмяОбработки = "" Тогда
		Возврат;
	КонецЕсли;

	ИмяОткрываемойФормы = "Обработка.[ИмяОбработки].Форма.[ИмяФормыОбработки]";
	ИмяОткрываемойФормы = СтрЗаменить(ИмяОткрываемойФормы, "[ИмяОбработки]", ИмяОбработки);
	ИмяОткрываемойФормы = СтрЗаменить(ИмяОткрываемойФормы, "[ИмяФормыОбработки]", ИмяФормыОбработки);

	ОткрытьФорму(
		ИмяОткрываемойФормы,
		Новый Структура,
		ПараметрыВыполненияКоманды.Источник,
		ИмяОткрываемойФормы + ?(ПараметрыВыполненияКоманды.Окно = Неопределено, ".ОтдельноеОкно", ""),
		ПараметрыВыполненияКоманды.Окно);

КонецПроцедуры

#КонецОбласти

#Область СлужебныйПрограммныйИнтерфейс

// Открывает модально журнал регистрации с отбором по событиям выгрузки или загрузки данных для заданного узла плана
// обмена.
//

Процедура ПерейтиВЖурналРегистрацииСобытийДанныхМодально(УзелИнформационнойБазы, Владелец, ДействиеПриОбмене) Экспорт

	// вызов сервера
	ПараметрыФормы = ОбменДаннымиВызовСервера.ДанныеОтбораЖурналаРегистрации(УзелИнформационнойБазы, ДействиеПриОбмене);

	ОткрытьФорму("Обработка.ЖурналРегистрации.Форма", ПараметрыФормы, Владелец);

КонецПроцедуры

// Возвращает имя формы сообщения о неудачном обновлении при ошибке в ПРО при выполнении обновления информационной базы.
//
// Возвращаемое значение:
//  Строка - имя формы сообщения о неудачном обновлении.
//

Функция ИмяФормыСообщенияОНеудачномОбновлении() Экспорт

	Возврат "РегистрСведений.ПравилаДляОбменаДанными.Форма.СообщениеОНеудачномОбновлении";

КонецФункции

// Обновляет конфигурацию базы данных.
//

[Assistant] Процедура ОбработчикВыбораЭлементовБазыКорреспондентаОбработкаВыбора(Знач Элемент, Знач ВыбранноеЗначение, Знач ДанныеФормыКоллекция=Неопределено)


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

Процедура ИмяФункции(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт

	Если Не ЗначениеЗаполнено(ВыбранныеФайлы) Тогда
		Возврат;
	КонецЕсли;

	Объект      = ДополнительныеПараметры.Объект;
	ИмяСвойства = ДополнительныеПараметры.ИмяСвойства;

	Результат = Неопределено;

	Если ВыбранныеФайлы.Количество() > 1 Тогда
		Результат = ВыбранныеФайлы;
	Иначе
		Результат = ВыбранныеФайлы[0];

		Объект[ИмяСвойства] = Результат;
	КонецЕсли;

	Если Не ДополнительныеПараметры.ОповещениеЗавершения = Неопределено Тогда
		ВыполнитьОбработкуОповещения(ДополнительныеПараметры.ОповещениеЗавершения, Результат);
	КонецЕсли;

КонецПроцедуры

// Передает файл на сервер интерактивно, без расширения для работы с файлами.
//
// Параметры:
//     ОповещениеЗавершения - ОписаниеОповещения - экспортная процедура, которая будет вызвано со следующими
//                                                 параметрами:
//                                Результат               - Структура - с полями Имя, Хранение, ОписаниеОшибки.
//                                ДополнительныеПараметры - Неопределено.
//
//     ПараметрыДиалога     - Структура                       - необязательные дополнительные параметры диалога выбора
//                                                              файлов.
//     ИдентификаторФормы   - Строка
//                          - УникальныйИдентификатор - параметр для хранилища.
//

Процедура ВыбратьИПередатьФайлНаСервер(ОповещениеЗавершения, Знач ПараметрыДиалога = Неопределено, Знач ИдентификаторФормы = Неопределено) Экспорт

	УмолчанияДиалога = Новый Структура;
	УмолчанияДиалога.Вставить("ПроверятьСуществованиеФайла", Истина);
	УмолчанияДиалога.Вставить("Заголовок",                   НСтр("ru = 'Выберите файл'"));
	УмолчанияДиалога.Вставить("МножественныйВыбор",          Ложь);
	УмолчанияДиалога.Вставить("ПредварительныйПросмотр",     Ложь);

	УстановитьЗначенияСтруктурыПоУмолчанию(ПараметрыДиалога, УмолчанияДиалога);

	ДополнительныеПараметры = Новый Структура;
	ДополнительныеПараметры.Вставить("ОповещениеЗавершения", ОповещениеЗавершения);

	Оповещение = Новый ОписаниеОповещения("ВыбратьИПередатьФайлНаСерверПослеВыбораВДиалогеЗавершение", ЭтотОбъект, ДополнительныеПараметры);

	ПараметрыЗагрузки = ФайловаяСистемаКлиент.ПараметрыЗагрузкиФайла();
	ПараметрыЗагрузки.ИдентификаторФормы = ИдентификаторФормы;
	ЗаполнитьЗначенияСвойств(ПараметрыЗагрузки.Диалог, ПараметрыДиалога);

	ФайловаяСистемаКлиент.ЗагрузитьФайл(Оповещение, ПараметрыЗагрузки);

КонецПроцедуры

// Обработчик немодального завершения выбора и передачи файлов на сервер.
//

Процедура ВыбратьИПередатьФайлНаСерверПослеВыбораВДиалогеЗавершение(ПомещенныйФайл, ДополнительныеПараметры) Экспорт

	Если ПомещенныйФайл = Неопределено Тогда
		Возврат;
	КонецЕсли;

	Результат  = Новый Структура("Имя, Хранение, ОписаниеОшибки");
	Результат.Имя      = ПомещенныйФайл.Имя;
	Результат.Хранение = ПомещенныйФайл.Хранение;

	// Оповещаем исходного вызывающего.
	ВыполнитьОбработкуОповещения(ДополнительныеПараметры.ОповещениеЗавершения, Результат);

КонецПроцедуры

// Добавляет поля в целевую структуру, если их там нет.
//
// Параметры:
//     Результат           - Структура - целевая структура.
//     ЗначенияПоУмолчанию - Структура
//

Процедура УстановитьЗначенияСтруктурыПоУмолчанию(Результат, Знач ЗначенияПоУмолчанию)

	Если Результат = Неопределено Тогда
		Результат = Новый Структура;
	КонецЕсли;

	Для Каждого КлючЗначение Из ЗначенияПоУмолчанию Цикл
		ИмяСвойства = КлючЗначение.Ключ;
		Если Не Результат.Свойство(ИмяСвойства) Тогда
			Результат.Вставить(ИмяСвойства, КлючЗначение.Значение);
		КонецЕсли;
	КонецЦикла;

КонецПроцедуры

// Открывает форму загрузки правил конвертации и регистрации единым файлом.
//

Процедура ЗагрузитьПравилаСинхронизацииДанных(Знач ИмяПланаОбмена) Экспорт

	ПараметрыФормы = Новый Структура;
	ПараметрыФормы.Вставить("ИмяПланаОбмена", ИмяПланаОбмена);

	ОткрытьФорму("РегистрСведений.ПравилаДляОбменаДанными.Форма.ЗагрузитьПравилаСинхронизацииДанных", ПараметрыФормы,, ИмяПланаОбмена);

КонецПроцедуры

// Открывает журнал регистрации с отбором по событиям выгрузки или загрузки данных для заданного узла плана обмена.
//

Процедура ПерейтиВЖурналРегистрацииСобытийДанных(УзелИнформационнойБазы, ПараметрыВыполненияКоманды, ДействиеПриОбменеСтрокой) Экспорт

	СобытиеЖурналаРегистрации = ОбменДаннымиВызовСервера.КлючСообщенияЖурналаРегистрацииПоСтрокеДействия(УзелИнформационнойБазы, ДействиеПриОбменеСтрокой);

	ПараметрыФормы = Новый Структура;
	ПараметрыФормы.Вставить("СобытиеЖурналаРегистрации", СобытиеЖурналаРегистрации);

	ОткрытьФорму("Обработка.ЖурналРегистрации.Форма", ПараметрыФормы, ПараметрыВыполненияКоманды.Источник, ПараметрыВыполненияКоманды.Уникальность, ПараметрыВыполненияКоманды.Окно);

КонецПроцедуры

Функция СобытиеЖурналаРегистрацииОбменДанными() Экспорт

	Возврат НСтр("ru = 'Обмен данными'", ОбщегоНазначенияКлиент.КодОсновногоЯзыка());

КонецФункции

// Открывает форму интерактивного выполнения обмена данными для заданного узла плана обмена.
//
// Параметры:
//  УзелИнформационнойБазы  - ПланОбменаСсылка - узел плана обмена, для которого необходимо открыть форму;
//  Владелец                - форма-владелец для открываемой формы;
//  ДополнительныеПараметры - Структура - структура дополнительных параметров открытия помощника:
//    * ПараметрыПомощника  - Структура - произвольная структура, которая будет передана в открываемую форму помощника;
//    * ОповещениеОЗакрытии - ОписаниеОповещения - описание оповещения, которое будет вызвано при закрытии формы помощника.
//

Процедура ОткрытьПомощникСопоставленияОбъектовОбработкаКоманды(УзелИнформационнойБазы,
		Владелец, ДополнительныеПараметры = Неопределено) Экспорт

	// Открываем форму помощника сопоставления объектов;
	// в качестве параметра формы задаем узел информационной базы;
	ПараметрыФормы = Новый Структура("УзелИнформационнойБазы", УзелИнформационнойБазы);
	ПараметрыФормы.Вставить("РасширенныйРежимДополненияВыгрузки", Истина);

	ОповещениеОЗакрытии = Неопределено;

	Если Не ДополнительныеПараметры = Неопределено Тогда

		Если ДополнительныеПараметры.Свойство("ПараметрыПомощника") Тогда
			Для Каждого ТекущийПараметр Из ДополнительныеПараметры.ПараметрыПомощника Цикл
				ПараметрыФормы.Вставить(ТекущийПараметр.Ключ, ТекущийПараметр.Значение);
			КонецЦикла;
		КонецЕсли;

		ДополнительныеПараметры.Свойство("ОповещениеОЗакрытии", ОповещениеОЗакрытии);

	КонецЕсли;

	ОткрытьФорму("Обработка.ПомощникИнтерактивногоОбменаДанными.Форма",
		ПараметрыФормы, Владелец, УзелИнформационнойБазы.УникальныйИдентификатор(), , , ОповещениеОЗакрытии, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);

КонецПроцедуры

// Открывает форму настройки новой синхронизации данных.
//

Процедура ОткрытьФормуНастройкиНовойСинхронизацииДанных(ФормаНовойСинхронизацииДанных = "", ДополнительныеПараметры = Неопределено) Экспорт

	Если ПустаяСтрока(ФормаНовойСинхронизацииДанных) Тогда
		ФормаНовойСинхронизацииДанных = "Обработка.ПомощникСозданияОбменаДанными.Форма.НоваяСинхронизацияДанных";
	КонецЕсли;

	ОткрытьФорму(ФормаНовойСинхронизацииДанных, ДополнительныеПараметры);

КонецПроцедуры

// Открывает форму списка сценариев выполнения обмена данными для заданного узла плана обмена.
//
// Параметры:
//  УзелИнформационнойБазы - ПланОбменаСсылка - узел плана обмена, для которого необходимо открыть форму;
//  Владелец               - форма-владелец для открываемой формы;
//

Процедура ОбработкаКомандыНастроитьРасписаниеВыполненияОбмена(УзелИнформационнойБазы, Владелец) Экспорт

	ПараметрыФормы = Новый Структура("УзелИнформационнойБазы", УзелИнформационнойБазы);

	ОткрытьФорму("Справочник.СценарииОбменовДанными.Форма.НастройкаРасписанияОбменовДанными", ПараметрыФормы, Владелец);

КонецПроцедуры

// Оповещает все открытые динамические списки о необходимости обновить отображаемые данные.
//

[Assistant] Процедура ОбработчикВыбораФайлаЗавершение(ВыбранныеФайлы, ДополнительныеПараметры)