///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2024, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

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

// Возвращает наименование субъекта РФ для адреса или пустую строку, если субъект не определен.
// Если переданная строка не содержит информации об адресе, то будет вызвано исключение.
//
// Параметры:
//    Адрес - Строка
//          - Структура - строка в формате JSON или XML соответствующая XDTO пакету Адрес.
//
// Возвращаемое значение:
//    Строка
//
Функция РегионАдресаКонтактнойИнформации(Знач Адрес) Экспорт
	
	Если ТипЗнч(Адрес) = Тип("Строка") Тогда
		
		Если ПустаяСтрока(Адрес) Тогда
			Возврат "";
		КонецЕсли;
	
		Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВXML(Адрес) Тогда
			Адрес = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияВJSON(Адрес, Перечисления.ТипыКонтактнойИнформации.Адрес);
		КонецЕсли;
		
		Адрес = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(Адрес, Перечисления.ТипыКонтактнойИнформации.Адрес);
		
	ИначеЕсли ТипЗнч(Адрес) <> Тип("Структура") Тогда
		
		ВызватьИсключение НСтр("ru = 'Невозможно определить субъект РФ, ожидается адрес.'");
		
	КонецЕсли;
	
	СубъектРФ = СокрЛП(Адрес.area + " " + Адрес.areaType);
	Возврат СубъектРФ;
	
КонецФункции

// Возвращает наименование города для адреса РФ или пустую строку для иностранного адреса.
// Если переданная строка не содержит информации об адресе, то будет вызвано исключение.
//
// Параметры:
//    Адрес - Строка
//          - Структура - строка в формате JSON или строка XML соответствующая XDTO пакету Адрес.
//
// Возвращаемое значение:
//    Строка
//
Функция ГородАдресаКонтактнойИнформации(Знач Адрес) Экспорт
	
	Если ТипЗнч(Адрес) = Тип("Строка") Тогда
		
		Если ПустаяСтрока(Адрес) Тогда
			Возврат "";
		КонецЕсли;
	
		Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВXML(Адрес) Тогда
			Адрес = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияВJSON(Адрес, Перечисления.ТипыКонтактнойИнформации.Адрес);
		КонецЕсли;
		
		Адрес = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(Адрес, Перечисления.ТипыКонтактнойИнформации.Адрес);
		
	ИначеЕсли ТипЗнч(Адрес) <> Тип("Структура") Тогда
		
		ВызватьИсключение НСтр("ru = 'Невозможно определить город, ожидается адрес.'");
		
	КонецЕсли;
	
	Регион = СокрЛП(Адрес.area + " " + Адрес.areaType);
	
	Если ЭтоГородФедеральногоЗначения(Регион)
		 Или СтрСравнить(Адрес.AddressType, УправлениеКонтактнойИнформациейКлиентСервер.ИностранныйАдрес()) = 0 Тогда
			Возврат Регион;
	КонецЕсли;
	
	Город = СокрЛП(Адрес.City + " " + Адрес.CityType);
	
	Возврат Город;
	
КонецФункции

// Возвращает сведения об адресе в виде отдельных частей адреса и различных кодов (код региона, ОКТМО и др.).
//
// Параметры:
//   Адреса                 - Массив - адреса во внутреннем формате JSON или в XML, соответствующий XDTO-пакету Адрес
//                                     или XDTO объектов, соответствующих XDTO-пакету Адрес. 
//                                     Массив может содержать до 1000 элементов.
//   ДополнительныеПараметры - Структура - для уточнения возвращаемого значения. Может содержать только поля,
//       отличающиеся от значений по умолчанию:
//       * БезПредставлений - Булево - если Истина, то поле Представление будет отсутствовать. По умолчанию, Ложь.
//       * КодыАдреса       - Булево - если Истина, то результат содержит поля ИдентификаторАдресногоОбъекта, ИдентификаторДома
//                                     и структура с кодами адреса(Идентификаторы, ДополнительныеКоды, КодыКЛАДР).
//                                     Подробнее см. в возвращаемом значении структуры Идентификаторы и
//                                     ДополнительныеКоды. По умолчанию, Ложь. Если в адресе отсутствуют идентификаторы
//                                     и в программу не загружены идентификаторы адресных объектов адреса, то получение
//                                     идентификаторов может инициировать http запрос к веб-сервису 1С orgaddress.
//       * КодыКЛАДР        - Булево - если Истина, то возвращается структура КодыКЛАДР. По умолчанию Ложь.
//                                     Если в адресе отсутствуют коды и в программу не загружены адресные объекты адреса,
//                                     Получение кодов может инициировать http запрос к веб-сервису 1С orgaddress.
//       * НаименованиеВключаетСокращение - Булево - если Истина, то поля содержат сокращения в наименованиях адресных объектов.
//       * ПроверитьАдрес   - Булево - если Истина, то адрес будет проверен на соответствие адресному классификатору. По
//                                     умолчанию, Ложь. Если в программу не загружены проверяемые адресные объекты,
//                                     то проверка адреса может инициировать http запрос к веб-сервису 1С orgaddress.
//       * ПолноеНаименованиеСокращений - Булево - устаревший параметр. Следует использовать свойства свойства
//                                     возвращаемого значения с постфиксами ТипПолный и ТипКраткий. По умолчанию, Ложь.
//
// Возвращаемое значение:
//   Массив из см. РаботаСАдресами.СведенияОбАдресе
//
Функция СведенияОбАдресах(Адреса, ДополнительныеПараметры = Неопределено) Экспорт
	Возврат СведенияОбАдресахВВидеСтруктуры(Адреса, ДополнительныеПараметры);
КонецФункции

// Возвращает сведения об адресе в виде отдельных частей адреса и различных кодов (код региона, ОКТМО и др.).
// Для преобразования полученных полей адреса в во внутренний формат JSON следует использовать функцию ПоляАдресаВJSON.
//
// Параметры:
//   Адрес                  - Строка - адрес во внутреннем формате JSON или в XML, соответствующем XDTO-пакету Адрес.
//                          - ОбъектXDTO - XDTO-объект, соответствующий XDTO пакету Адрес.
//                          - Неопределено - конструктор для получения пустых полей адреса.
//   ДополнительныеПараметры - Структура - для уточнения возвращаемого значения. Может содержать только поля,
//       отличающиеся от значений по умолчанию:
//       * БезПредставлений - Булево - если Истина, то поле Представление будет отсутствовать. По умолчанию Ложь.
//       * КодыАдреса       - Булево - если Истина, то результат содержит поля ИдентификаторАдресногоОбъекта, ИдентификаторДома
//                                     и структура с кодами адреса(Идентификаторы, ДополнительныеКоды, КодыКЛАДР).
//                                     Подробнее см. в возвращаемом значении структуры Идентификаторы и
//                                     ДополнительныеКоды. По умолчанию, Ложь. Если в адресе отсутствуют идентификаторы
//                                     и в программу не загружены идентификаторы адресных объектов адреса, то получение
//                                     идентификаторов может инициировать http запрос к веб-сервису 1С orgaddress.
//       * КодыКЛАДР        - Булево - если Истина, то возвращается структура КодыКЛАДР. По умолчанию Ложь.
//                                     Если в адресе отсутствуют коды и в программу не загружены адресные объекты адреса,
//                                     Получение кодов может инициировать http запрос к веб-сервису 1С orgaddress.
//       * НаименованиеВключаетСокращение - Булево - если Истина, то поля содержат сокращениям в наименованиях адресных объектов.
//       * ПроверитьАдрес   - Булево - если Истина, то адрес будет проверен на соответствие адресному классификатору. По
//                                     умолчанию Ложь. Если в программу не загружены проверяемые адресные объекты,
//                                     то проверка адреса может инициировать http запрос к веб-сервису 1С orgaddress.
//       * ПолноеНаименованиеСокращений - Булево - устаревший параметр. Следует использовать свойства свойства
//                                     возвращаемого значения с постфиксами ТипПолный и ТипКраткий. По умолчанию, Ложь.
//
// Возвращаемое значение:
//   Структура:
//        * Представление    - Строка - текстовое представление адреса по административно-территориальному делению.
//        * МуниципальноеПредставление - Строка - текстовое представление адреса по муниципальному делению.
//        * ТипАдреса        - Строка - основной тип адреса (только для адресов РФ).
//                                      Варианты: "Муниципальный", "Административно-территориальный".
//        * Страна           - Строка - текстовое представление страны.
//        * КодСтраны        - Строка - код страны по ОКСМ.
//        * Индекс           - Строка - почтовый индекс.
//        * КодРегиона       - Строка - код региона РФ.
//        * Регион           - Строка - текстовое представление региона РФ. Для получения полного наименования региона
//                                      следует использовать функцию РегионАдресаКонтактнойИнформации.
//        * РегионТипПолный  - Строка - полное наименование типа региона. Например: "область".
//        * РегионТипКраткий - Строка - краткое наименование типа региона. Например: "обл".
//        * РегионСокращение - Строка - устаревшее свойство. Сокращение региона, например: "обл", если
//                                      ДополнительныеПараметры.ПолноеНаименованиеСокращений = ЛОЖЬ, или "область", если
//                                      ДополнительныеПараметры.ПолноеНаименованиеСокращений = ИСТИНА.
//        * Округ            - Строка - устаревшее свойство. Текстовое представление округа.
//        * ОкругСокращение  - Строка - устаревшее свойство. Сокращение округа.
//        * Район            - Строка - текстовое представление района у адресов по административно-территориальному делению.
//        * РайонТипПолный   - Строка - полное наименование типа района для адреса по административно-территориальному
//                                      делению. Например: "район".
//        * РайонТипКраткий  - Строка - краткое наименование типа района для адреса по административно-территориальному
//                                      делению. Например: "р-н".
//        * РайонСокращение  - Строка - устаревшее свойство. Сокращение района для адреса по
//                                      административно-территориальному делению, например: "р-н", если
//                                      ДополнительныеПараметры.ПолноеНаименованиеСокращений = ЛОЖЬ, или "район", если
//                                      ДополнительныеПараметры.ПолноеНаименованиеСокращений = ИСТИНА.
//        * МуниципальныйРайон - Строка - текстовое представление муниципального района для адреса по муниципальному делению.
//        * МуниципальныйРайонТипПолный - Строка - полное наименование типа муниципального района по муниципальному
//                                                 делению. Например: "городской округ".
//        * МуниципальныйРайонТипКраткий - Строка - краткое наименование типа муниципального района для адреса по
//                                                  муниципальному делению. Например: "мун.р-н".
//        * МуниципальныйРайонСокращение - Строка - устаревшее свойство. Сокращение муниципального района для адреса по
//                                         муниципальному делению, например: "мун.р-н", если
//                                         ДополнительныеПараметры.ПолноеНаименованиеСокращений = ЛОЖЬ, или
//                                         "муниципальный район", если
//                                         ДополнительныеПараметры.ПолноеНаименованиеСокращений = ИСТИНА.
//        * КодМуниципальногоРайона - Строка - код муниципального района:
//                                             1- муниципальный район; 2- городской округ; 3 - внутригородская территория 
//                                             города федерального значения; 4 - муниципальный округ;
//                                             5 - федеральная территория.
//                                             Если не удалось определить код, то возвращается пустая строка.
//        * Город            - Строка - текстовое представление города у адресов по административно-территориальному делению.
//        * ГородТипПолный   - Строка - полное наименование типа города у адресов по административно-территориальному делению.
//        * ГородТипКраткий  - Строка - текстовое представление города у адресов по административно-территориальному делению.
//        * ГородСокращение  - Строка - сокращение города  у адресов по административно-территориальному делению.
//        * Поселение            - Строка - текстовое представление поселения у адресов по муниципальному делению.
//        * ПоселениеТипПолный  - Строка - полное наименование типа сельского поселения по муниципальному делению.
//                                         Например: "сельское поселение".
//        * ПоселениеТипКраткий  - Строка - краткое наименование типа муниципального района для адреса по муниципальному
//                                          делению. Например: "с. п.".
//        * ПоселениеСокращение  - Строка - устаревшее свойство. Сокращение сельского поселения для адреса по
//                                         муниципальному делению, например: "с. п.", если
//                                         ДополнительныеПараметры.ПолноеНаименованиеСокращений = ЛОЖЬ, или "сельское
//                                         поселение", если ДополнительныеПараметры.ПолноеНаименованиеСокращений = ИСТИНА
//        * КодПоселения       - Строка - код поселения: 1 - городское поселение; 2 - сельское поселение; 3-  межселенная
//                                     территория в составе муниципального района; 4 - внутригородской район городского округа;
//        * ВнутригородскойРайон - Строка  - текстовое представление внутригородского района.
//        * ВнутригородскойРайонТипПолный  - Строка - полное наименование типа внутригородского района. Например: "микрорайон".
//        * ВнутригородскойРайонТипКраткий - Строка - краткое наименование типа внутригородского района. Например: "мкр".
//        * ВнутригородскойРайонСокращение - Строка - устаревшее свойство. Сокращение внутригородского района, например:
//                                                    "мкр", если ДополнительныеПараметры.ПолноеНаименованиеСокращений =
//                                                    ЛОЖЬ, или "микрорайон", если
//                                                    ДополнительныеПараметры.ПолноеНаименованиеСокращений = ИСТИНА
//        * НаселенныйПункт  - Строка - текстовое представление населенного пункта.
//        * НаселенныйПунктТипПолный - Строка - полное наименование типа населенного пункта. Например: "деревня".
//        * НаселенныйПунктТипКраткий - Строка - краткое наименование типа  населенного пункта. Например: "д".
//        * НаселенныйПунктСокращение - Строка - устаревшее свойство. Сокращение населенного пункта, например: "д",
//                                               если ДополнительныеПараметры.ПолноеНаименованиеСокращений = ЛОЖЬ,
//                                               или "деревня", если
//                                               ДополнительныеПараметры.ПолноеНаименованиеСокращений = ИСТИНА
//        * Территория            - Строка - текстовое представление территории.
//        * ТерриторияТипПолный  - Строка - полное наименование типа территории. Например: "Гаражно-строительный кооп.".
//        * ТерриторияТипКраткий  - Строка - краткое наименование типа территории. Например: "гск".
//        * ТерриторияСокращение  - Строка - устаревшее свойство. Сокращение населенного пункта, например: "гск",
//                                               если ДополнительныеПараметры.ПолноеНаименованиеСокращений = ЛОЖЬ,
//                                               или "Гаражно-строительный кооп.", если
//                                               ДополнительныеПараметры.ПолноеНаименованиеСокращений = ИСТИНА
//        * Улица            - Строка - текстовое представление улицы.
//        * УлицаТипПолный  - Строка - полное наименование типа улицы. Например: "Улица".
//        * УлицаТипКраткий  - Строка - краткое наименование типа улицы. Например: "ул".
//        * УлицаСокращение  - Строка - устаревшее свойство. Сокращение улицы, например: "гск",
//                                     если ДополнительныеПараметры.ПолноеНаименованиеСокращений = ЛОЖЬ,
//                                     или "Улица", если ДополнительныеПараметры.ПолноеНаименованиеСокращений = ИСТИНА
//        * ДополнительнаяТерритория - Строка - устаревшее свойство. Текстовое представление дополнительной территории.
//        * ДополнительнаяТерриторияСокращение - Строка - устаревшее свойство. Сокращение дополнительной территории.
//        * ЭлементДополнительнойТерритории - Строка - устаревшее свойство. Текстовое представление элемента
//                                                     дополнительной территории.
//        * ЭлементДополнительнойТерриторииСокращение - Строка - устаревшее свойство. Сокращение элемента дополнительной
//                                                               территории.
//        * Здание - Структура - структура с информацией о здании адреса:
//            ** ТипЗдания - Строка - тип объекта адресации адреса РФ согласно приказу Минфина России от 5.11.2015 г. N171н.
//            ** Номер - Строка  - текстовое представление номера дома (только для адресов РФ).
//        * Корпуса   - Массив - содержит структуры (поля структуры: ТипКорпуса, Номер) с перечнем корпусов адреса.
//        * Помещения - Массив - содержит структуры (поля структуры: ТипПомещения, Номер) с перечнем помещений адреса.
//        * НомерЗемельногоУчастка - Строка - текстовое представление номера земельного участка (только для адресов РФ).
//        * Комментарий - Строка - комментарий об адресе.
//        * ИдентификаторАдресногоОбъекта - УникальныйИдентификатор - идентификационный код последнего адресного объекта
//                                        в иерархи адреса. Например, для адреса: Москва г., Дмитровское ш., д.9 это
//                                        будет идентификатор улицы.
//                                        Поле отсутствует, если дополнительный параметр КодыАдреса равен Ложь.
//        * ИдентификаторДома             - УникальныйИдентификатор - идентификационный код дома(строения) адресного объекта.
//                                        Поле отсутствует, если дополнительный параметр КодыАдреса равен Ложь.
//                                        Пустая строка если значение отсутствует.
//        * ИдентификаторЗемельногоУчастка - УникальныйИдентификатор - идентификационный код земельного участка
//                                       адресного объекта. При отсутствии значения - пустая строка.
//        * Идентификаторы - Структура - где: 
//                                       Идентификаторы адресных объектов адреса, если установлен параметр КодыАдреса
//                                       или КодыКЛАДР. Поле отсутствует, если дополнительный параметр КодыАдреса или
//                                       КодыКЛАДР равен Ложь:
//            ** Регион               - УникальныйИдентификатор - идентификатор региона.
//            ** Район                - УникальныйИдентификатор - идентификатор района.
//            ** МуниципальныйРайон   - УникальныйИдентификатор - идентификатор муниципального района.
//            ** Город                - УникальныйИдентификатор - идентификатор города.
//            ** Поселение            - УникальныйИдентификатор - идентификатор поселения.
//            ** ВнутригородскойРайон - УникальныйИдентификатор - идентификатор внутригородского района.
//            ** НаселенныйПункт      - УникальныйИдентификатор - идентификатор населенного пункта.
//            ** Территория           - УникальныйИдентификатор - идентификатор территории.
//            ** Улица                - УникальныйИдентификатор - идентификатор улица.
//        * КодыКЛАДР           - Структура - коды КЛАДР, если параметр КодыКЛАДР установлен в Истина. Где:
//           ** Регион          - Строка    - код КЛАДР региона.
//           ** Район           - Строка    - код КЛАДР район.
//           ** Город           - Строка    - код КЛАДР города.
//           ** НаселенныйПункт - Строка    - код КЛАДР населенного пункта.
//           ** Улица           - Строка    - код КЛАДР улицу.
//        * ДополнительныеКоды  - Структура - коды ОКТМО, ОКТМОБюджетополучателя, ОКАТО,
//                                            КодИФНСФЛ, КодИФНСЮЛ, КодУчасткаИФНСФЛ, КодУчасткаИФНСЮЛ.
//                                            Поле отсутствует, если дополнительный параметр КодыАдреса равен Ложь.
//        * РезультатПроверкиАдреса - Строка - "Успех", если адрес корректный, "Ошибка" - при наличии ошибок проверки,
//                                             "Отказ", если не удалось проверить адрес, т.к. недоступен классификатор.
//                                             Пустая строка, если в параметре ДополнительныеПараметры.ПроверитьАдрес не
//                                             установлен флаг ПроверитьАдрес.
//        * ОшибкиПроверкиАдреса - Строка  - описание ошибок в адресе, выявленных в ходе проверки.
//
Функция СведенияОбАдресе(Адрес, ДополнительныеПараметры = Неопределено) Экспорт
	Возврат СведенияОбАдресеВВидеСтруктуры(Адрес, ДополнительныеПараметры);
КонецФункции

// Возвращает сведения об адресе в виде отдельных частей адреса и различных кодов (код региона, ОКТМО и др.), где
// типы адресных объектов (свойство ТипКраткий), типы домов, зданий и помещений соответствуют приказу Минфина РФ N 171н.
//
// Параметры:
//  Адрес - Строка - адрес во внутреннем формате JSON или в XML, соответствующем XDTO-пакету Адрес.
//        - см. РаботаСАдресами.СведенияОбАдресе
//  ДополнительныеПараметры - см. РаботаСАдресами.СведенияОбАдресе.ДополнительныеПараметры
// 
// Возвращаемое значение:
//   см. РаботаСАдресами.СведенияОбАдресе
//
Функция СведенияОбАдресеПриказМинфинаРФ171н(Адрес, ДополнительныеПараметры = Неопределено) Экспорт
	
	Параметры = ИнициализироватьПараметрыСведенийОбАдресе(ДополнительныеПараметры);
	
	Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВJSON(Адрес) Тогда
		АдресПоПолям = СведенияОбАдресе(Адрес, Параметры);
	ИначеЕсли ТипЗнч(Адрес) = Тип("Структура") Тогда
		АдресПоПолям = Адрес;
	КонецЕсли;
	
	ПереченьЭлементов = Новый ФиксированноеСоответствие(Новый Соответствие);
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.АдресныйКлассификатор") Тогда
		
		МодульАдресныйКлассификаторСлужебный = ОбщегоНазначения.ОбщийМодуль("АдресныйКлассификаторСлужебный");
		
		ПереченьЭлементов = МодульАдресныйКлассификаторСлужебный.АдресныеСокращенияПриказМинфинаРФ171н();
		
		Сокращение = НРег(СокрЛП(АдресПоПолям.МуниципальныйРайонТипКраткий));
		АдресПоПолям.МуниципальныйРайон = МодульАдресныйКлассификаторСлужебный.КраткоеНаписаниеМуниципальныхРайонов(АдресПоПолям.МуниципальныйРайон, Сокращение);
		
		Сокращение = НРег(СокрЛП(АдресПоПолям.ПоселениеТипКраткий));
		АдресПоПолям.Поселение = МодульАдресныйКлассификаторСлужебный.КраткоеНаписаниеПоселений(АдресПоПолям.Поселение, Сокращение);
		
	КонецЕсли;
	
	УровниАдреса = ПорядокУровнейПоУмолчанию();
	
	Для каждого УровеньАдреса Из УровниАдреса Цикл
		
		ТипПолный = АдресПоПолям[УровеньАдреса + "ТипПолный"];
		ТипКраткий = ПереченьЭлементов.Получить(ВРег(ТипПолный));
		Если ЗначениеЗаполнено(ТипКраткий) Тогда
			АдресПоПолям[УровеньАдреса + "ТипКраткий"] = ТипКраткий;
			АдресПоПолям[УровеньАдреса + "Сокращение"] = ТипКраткий;
		КонецЕсли;
		
	КонецЦикла;
	
	СокращенияЗданийИПомещений = РаботаСАдресамиКлиентСервер.СокращенияЗданийИПомещений();
	
	Если ТипЗнч(АдресПоПолям.Здание) = Тип("Структура") Тогда
		
		ТипКраткий = СокращенияЗданийИПомещений[ВРег(АдресПоПолям.Здание.ТипЗдания)];
		
		Если ЗначениеЗаполнено(ТипКраткий) Тогда
			АдресПоПолям.Здание.ТипЗдания = ТипКраткий;
		КонецЕсли;
	КонецЕсли;
	
	Если ТипЗнч(АдресПоПолям.Корпуса) = Тип("Массив") Тогда
		Для каждого Корпус Из АдресПоПолям.Корпуса Цикл
			
			ТипКраткий = СокращенияЗданийИПомещений[ВРег(Корпус.ТипКорпуса)];
			
			Если ЗначениеЗаполнено(ТипКраткий) Тогда
				Корпус.ТипКорпуса = ТипКраткий;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	Если ТипЗнч(АдресПоПолям.Помещения) = Тип("Массив") Тогда
		Для каждого Корпус Из АдресПоПолям.Помещения Цикл
			
			ТипКраткий = СокращенияЗданийИПомещений[ВРег(Корпус.ТипПомещения)];
			
			Если ЗначениеЗаполнено(ТипКраткий) Тогда
				Корпус.ТипПомещения = ТипКраткий;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	Если Не Параметры.БезПредставлений Тогда
		
		АдресJSON = ПоляАдресаВJSON(АдресПоПолям);
		АдресИзJSON = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(АдресJSON, Перечисления.ТипыКонтактнойИнформации.Адрес);
		
		ВключатьСтрануВПредставление = Ложь;
		
		АдресПоПолям.Представление = РаботаСАдресамиКлиентСервер.ПредставлениеАдреса(АдресИзJSON,
			ВключатьСтрануВПредставление, РаботаСАдресамиКлиентСервер.АдминистративноТерриториальныйАдрес());
			
		АдресПоПолям.МуниципальноеПредставление = РаботаСАдресамиКлиентСервер.ПредставлениеАдреса(АдресИзJSON ,
			ВключатьСтрануВПредставление, РаботаСАдресамиКлиентСервер.МуниципальныйАдрес());
		
	КонецЕсли;
	
	Возврат АдресПоПолям;
	
КонецФункции

// Проверяет адрес на соответствие требованиям к адресной информации.
//
// Параметры:
//   Адрес              - Строка - строка JSON или XML контактной информации, соответствующая XDTO-пакету КонтактнаяИнформация.
//   ПараметрыПроверки  - Структура
//                      - СправочникСсылка.ВидыКонтактнойИнформации - флаги проверки адреса:
//          ТолькоНациональныйАдрес - Булево - адрес должен быть только российским. По умолчанию Истина.
//          ФорматАдреса - Строка - устарело. По какому классификатору проверять.
// Возвращаемое значение:
//   Структура:
//        * Результат - Строка - результат проверки: "Корректный", "НеПроверен", "СодержитОшибки".
//        * СписокОшибок - СписокЗначений - информация о ошибках.
//
Функция ПроверитьАдрес(Знач Адрес, ПараметрыПроверки = Неопределено) Экспорт
	Возврат УправлениеКонтактнойИнформациейСлужебный.ПроверитьАдрес(Адрес, ПараметрыПроверки);
КонецФункции

// Проверяет адреса на соответствие адресному классификатору и для устаревших адресов возвращает актуальные варианты.
// Если адресные сведения региона адреса не загружены в программу, то проверка адреса будет 
// выполнена через веб-сервис orgaddress и может занимать до 120 секунд.
// Поэтому для исключения зависаний пользовательского интерфейса, например при открытии формы,
// функцию следует вызвать в фоновом задании.
//
// Параметры:
//   Адреса - Соответствие из КлючИЗначение:
//     * Ключ - Число - уникальный идентификатор адреса;
//     * Значение - Строка - проверяемый адрес во внутреннем формате JSON.
//                               В целях обратной совместимости допускается передача адреса в виде XML,
//                               соответствующем XDTO-пакету Адрес (http://www.v8.1c.ru/ssl/contactinfo),
//                               но это негативно сказывается на времени выполнения функции.
//   ДополнительныеПараметры - Структура:
//     * ПроверятьУстареваниеАдресов - Булево - если адрес устарел, то свойство АктуальныеАдреса будут содержать актуальные
//                                    варианты адреса. Для загруженных регионов адресного классификатора должна быть загружена
//                                    история изменений адресных сведений. По умолчанию, Ложь.
//     * ВключатьСтрануВПредставление - Булево - в поле Представление у свойства АктуальныеАдреса включать страну
//                                             в представление актуального адреса. По умолчанию, Ложь.
//
// Возвращаемое значение:
//   Соответствие из КлючИЗначение:
//    * Ключ - Число - уникальный идентификатор адреса;
//    * Значение - Структура:
//       * АдресПроверен  - Булево - признак, что адрес был проверен в классификаторе или через веб-сервис.
//       * АдресКорректный - Булево - признак, что адрес соответствует адресному классификатору. Устаревшие адреса
//                                    считаются некорректными.
//       * Ошибки - Массив из Строка - список ошибок в адресе.
//       * АктуальныеАдреса - Массив из Структура - где: 
//           Если адрес устарел, то содержит варианты актуального адреса в виде полей адреса, где:
//           * Представление - Строка - представление актуального варианта адреса;
//           * Адрес - Строка - адрес во внутреннем формате JSON.
//
Функция ПроверитьАдреса(Знач Адреса, ДополнительныеПараметры = Неопределено) Экспорт
	
	Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.АдресныйКлассификатор") Тогда
		Возврат ПроверитьАдресаКлассификаторНедоступен(Адреса);
	КонецЕсли;
	
	ПараметрыПроверки = Новый Структура;
	ПараметрыПроверки.Вставить("ПроверятьУстареваниеАдресов", Ложь);
	ПараметрыПроверки.Вставить("ВключатьСтрануВПредставление", Ложь);
	Если ТипЗнч(ДополнительныеПараметры) = Тип("Структура") Тогда
		ЗаполнитьЗначенияСвойств(ПараметрыПроверки, ДополнительныеПараметры);
	КонецЕсли;
	
	МодульАдресныйКлассификаторСлужебный = ОбщегоНазначения.ОбщийМодуль("АдресныйКлассификаторСлужебный");
	
	АдресаПолями = Новый Соответствие;
	Для каждого ПроверяемыйАдрес Из Адреса Цикл
		Адрес = ПроверяемыйАдрес.Значение;
		
		Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВXML(Адрес) Тогда
			Адрес = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияВJSON(Адрес, Перечисления.ТипыКонтактнойИнформации.Адрес);
		КонецЕсли;
		
		АдресПоПолям = МодульАдресныйКлассификаторСлужебный.КонтактнаяИнформацияВСтруктуруJSON(Адрес);
		АдресаПолями.Вставить(ПроверяемыйАдрес.Ключ, АдресПоПолям);
		
	КонецЦикла;
	
	РезультатыПроверки = МодульАдресныйКлассификаторСлужебный.ПроверкаАдресов(АдресаПолями, ПараметрыПроверки.ПроверятьУстареваниеАдресов);
	
	Результат = Новый Соответствие;
	
	Для каждого КлючЗначение Из РезультатыПроверки Цикл
		
		СтрокаАдреса = КлючЗначение.Значение;
		
		ОписаниеРезультатаПроверки = ОписаниеРезультатаПроверкиАдреса();
		ЗаполнитьЗначенияСвойств(ОписаниеРезультатаПроверки, СтрокаАдреса, "АдресПроверен,АдресКорректный");
		
		Для Каждого ОписаниеОшибки Из СтрокаАдреса.Ошибки Цикл
			ОписаниеРезультатаПроверки.Ошибки.Добавить(ОписаниеОшибки.Текст);
		КонецЦикла;
		
		Для Каждого ОписаниеВарианта Из СтрокаАдреса.Варианты Цикл
			
			Представление = РаботаСАдресамиКлиентСервер.ПредставлениеАдреса(ОписаниеВарианта, ПараметрыПроверки.ВключатьСтрануВПредставление);
			ОписаниеВарианта.value = Представление;
			Адрес = УправлениеКонтактнойИнформациейСлужебный.СтруктураВСтрокуJSON(ОписаниеВарианта);
			
			АктуальныйАдрес = Новый Структура;
			АктуальныйАдрес.Вставить("Адрес", Адрес);
			АктуальныйАдрес.Вставить("Представление", Представление);
			
			ОписаниеРезультатаПроверки.АктуальныеАдреса.Добавить(АктуальныйАдрес);
			
		КонецЦикла;
		
		Результат.Вставить(КлючЗначение.Ключ, ОписаниеРезультатаПроверки);
		
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

// Преобразует структуру полей адреса, полученную функций СведенияОбАдресе или
// РаботаСАдресамиКлиентСервер.ПоляАдреса во внутренний формат хранения контактной информации JSON.
// 
//
// Параметры:
//  ПоляАдреса - см. РаботаСАдресамиКлиентСервер.ПоляАдреса.
// 
// Возвращаемое значение:
//  Строка - адрес во внутреннем формате JSON.
//
Функция ПоляАдресаВJSON(ПоляАдреса) Экспорт
	
	Результат = РаботаСАдресамиКлиентСервер.ОписаниеНовойКонтактнойИнформации(
		Перечисления.ТипыКонтактнойИнформации.Адрес);
	
	ТипУникальныйИдентификатор = Тип("УникальныйИдентификатор");
	
	Результат.AddressType = ПоляАдреса.ТипАдреса;
	Если ПоляАдреса.ТипАдреса <> РаботаСАдресамиКлиентСервер.МуниципальныйАдрес()
		И ПоляАдреса.ТипАдреса <> РаботаСАдресамиКлиентСервер.АдминистративноТерриториальныйАдрес() Тогда
		ТекстИсключения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Некорректный тип адреса (%1)'"),
			ПоляАдреса.ТипАдреса);
		ВызватьИсключение ТекстИсключения;
	КонецЕсли;
	
	Если ПоляАдреса.ТипАдреса <> РаботаСАдресамиКлиентСервер.АдминистративноТерриториальныйАдрес() Тогда
		Результат.Value = ПоляАдреса.Представление;
	Иначе
		Результат.Value = ПоляАдреса.МуниципальноеПредставление;
	КонецЕсли;
	
	Результат.Comment     = ПоляАдреса.Комментарий;
	
	Результат.Country     = ПоляАдреса.Страна;
	Результат.CountryCode = ПоляАдреса.КодСтраны;
	
	Результат.ZIPcode     = ПоляАдреса.Индекс;
	
	Результат.areaCode    = ПоляАдреса.КодРегиона;
	
	Результат.area     = ПоляАдреса.Регион;
	Результат.areaType = ПоляАдреса.РегионСокращение;
	
	Результат.City     = ПоляАдреса.Город;
	Результат.CityType = ПоляАдреса.ГородСокращение;
	
	Результат.Street     = ПоляАдреса.Улица;
	Результат.StreetType = ПоляАдреса.УлицаСокращение;
	
	Результат.District     = ПоляАдреса.Район;
	Результат.DistrictType = ПоляАдреса.РайонСокращение;
	
	Результат.MunDistrict     = ПоляАдреса.МуниципальныйРайон;
	Результат.MunDistrictType = ПоляАдреса.МуниципальныйРайонСокращение;
	
	Результат.Settlement     = ПоляАдреса.Поселение;
	Результат.SettlementType = ПоляАдреса.ПоселениеСокращение;
	
	Результат.CityDistrict     = ПоляАдреса.ВнутригородскойРайон;
	Результат.CityDistrictType = ПоляАдреса.ВнутригородскойРайонСокращение;
	
	Результат.Locality     = ПоляАдреса.НаселенныйПункт;
	Результат.LocalityType = ПоляАдреса.НаселенныйПунктСокращение;
	
	Результат.Territory     = ПоляАдреса.Территория;
	Результат.TerritoryType = ПоляАдреса.ТерриторияСокращение;
	
	Результат.Stead = ПоляАдреса.НомерЗемельногоУчастка;
	
	Результат.HouseType   = ПоляАдреса.Здание.ТипЗдания;
	Результат.HouseNumber = ПоляАдреса.Здание.Номер;
	
	Если ПоляАдреса.Свойство("Идентификаторы") Тогда
		Если ТипЗнч(ПоляАдреса.Идентификаторы.РегионИдентификатор) = ТипУникальныйИдентификатор
			И ЗначениеЗаполнено(ПоляАдреса.Идентификаторы.РегионИдентификатор) Тогда
			Результат.areaID = Формат(ПоляАдреса.Идентификаторы.РегионИдентификатор, "ЧРГ=' '; ЧГ=0");
			Результат.ID = Результат.areaID;
		КонецЕсли;
		
		Если ТипЗнч(ПоляАдреса.Идентификаторы.РайонИдентификатор) = ТипУникальныйИдентификатор
			И ЗначениеЗаполнено(ПоляАдреса.Идентификаторы.РайонИдентификатор) Тогда
			Результат.DistrictID = Строка(ПоляАдреса.Идентификаторы.РайонИдентификатор);
			Результат.ID         = Результат.DistrictID;
		КонецЕсли;
		
		Если ТипЗнч(ПоляАдреса.Идентификаторы.ГородИдентификатор) = ТипУникальныйИдентификатор
			И ЗначениеЗаполнено(ПоляАдреса.Идентификаторы.ГородИдентификатор) Тогда
			Результат.CityID = Строка(ПоляАдреса.Идентификаторы.ГородИдентификатор);
			Результат.ID     = Результат.CityID;
		КонецЕсли;
		
		Если ТипЗнч(ПоляАдреса.Идентификаторы.МуниципальныйРайонИдентификатор) = ТипУникальныйИдентификатор
			И ЗначениеЗаполнено(ПоляАдреса.Идентификаторы.МуниципальныйРайонИдентификатор) Тогда
			Результат.MunDistrictID = Строка(ПоляАдреса.Идентификаторы.МуниципальныйРайонИдентификатор);
			Результат.ID            = Результат.MunDistrictID;
		КонецЕсли;
		
		Если ТипЗнч(ПоляАдреса.Идентификаторы.ПоселениеИдентификатор) = ТипУникальныйИдентификатор
			И ЗначениеЗаполнено(ПоляАдреса.Идентификаторы.ПоселениеИдентификатор) Тогда
			Результат.SettlementID = Строка(ПоляАдреса.Идентификаторы.ПоселениеИдентификатор);
			Результат.ID           = Результат.SettlementID;
		КонецЕсли;
		
		Если ТипЗнч(ПоляАдреса.Идентификаторы.ВнутригородскойРайонИдентификатор) = ТипУникальныйИдентификатор
			И ЗначениеЗаполнено(ПоляАдреса.Идентификаторы.ВнутригородскойРайонИдентификатор) Тогда
			Результат.CityDistrictID = Строка(ПоляАдреса.Идентификаторы.ВнутригородскойРайонИдентификатор);
			Результат.ID             = Результат.CityDistrictID;
		КонецЕсли;
		
		Если ТипЗнч(ПоляАдреса.Идентификаторы.НаселенныйПунктИдентификатор) = ТипУникальныйИдентификатор
			И ЗначениеЗаполнено(ПоляАдреса.Идентификаторы.НаселенныйПунктИдентификатор) Тогда
			Результат.LocalityID = Строка(ПоляАдреса.Идентификаторы.НаселенныйПунктИдентификатор);
			Результат.ID         = Результат.LocalityID;
		КонецЕсли;
		
		Если ТипЗнч(ПоляАдреса.Идентификаторы.ТерриторияИдентификатор) = ТипУникальныйИдентификатор
			И ЗначениеЗаполнено(ПоляАдреса.Идентификаторы.ТерриторияИдентификатор) Тогда
			Результат.TerritoryID = Строка(ПоляАдреса.Идентификаторы.ТерриторияИдентификатор);
			Результат.ID          = Результат.TerritoryID;
		КонецЕсли;
		
		Если ТипЗнч(ПоляАдреса.Идентификаторы.УлицаИдентификатор) = ТипУникальныйИдентификатор
			И ЗначениеЗаполнено(ПоляАдреса.Идентификаторы.УлицаИдентификатор) Тогда
			Результат.StreetID = Строка(ПоляАдреса.Идентификаторы.УлицаИдентификатор);
			Результат.ID       = Результат.StreetID;
		КонецЕсли;
	КонецЕсли;
	
	Если ПоляАдреса.Свойство("ИдентификаторЗемельногоУчастка")
		И ТипЗнч(ПоляАдреса.ИдентификаторЗемельногоУчастка) = ТипУникальныйИдентификатор
		И ЗначениеЗаполнено(ПоляАдреса.ИдентификаторЗемельногоУчастка) Тогда
		Результат.steadId = Строка(ПоляАдреса.ИдентификаторЗемельногоУчастка);
	КонецЕсли;
	
	Если ПоляАдреса.Свойство("ИдентификаторДома")
		И ТипЗнч(ПоляАдреса.ИдентификаторДома) = ТипУникальныйИдентификатор
		И ЗначениеЗаполнено(ПоляАдреса.ИдентификаторДома) Тогда
		Результат.HouseID = Строка(ПоляАдреса.ИдентификаторДома);
	КонецЕсли;
	
	Если ПоляАдреса.Свойство("ИдентификаторАдресногоОбъекта")
		И ТипЗнч(ПоляАдреса.ИдентификаторАдресногоОбъекта) = ТипУникальныйИдентификатор
		И ЗначениеЗаполнено(ПоляАдреса.ИдентификаторАдресногоОбъекта) Тогда
		Результат.ID = Строка(ПоляАдреса.ИдентификаторАдресногоОбъекта);
	КонецЕсли;
	
	Для Каждого ТекущийКорпус Из ПоляАдреса.Корпуса Цикл
		Результат.Buildings.Добавить(УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения(ТекущийКорпус.ТипКорпуса, ТекущийКорпус.Номер));
	КонецЦикла;
	
	Для Каждого ТекущееПомещение Из ПоляАдреса.Помещения Цикл
		Результат.Apartments.Добавить(УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения(ТекущееПомещение.ТипПомещения, ТекущееПомещение.Номер));
	КонецЦикла;
	
	// Заполнение кода КЛАДР последнего в иерархии адресного объекта.
	Если ПоляАдреса.Свойство("КодыКЛАДР") Тогда
		Если Не ПустаяСтрока(ПоляАдреса.КодыКЛАДР.Улица) Тогда
			Результат.CodeKLADR = ПоляАдреса.КодыКЛАДР.Улица;
		ИначеЕсли Не ПустаяСтрока(ПоляАдреса.КодыКЛАДР.НаселенныйПункт) Тогда
			Результат.CodeKLADR = ПоляАдреса.КодыКЛАДР.НаселенныйПункт;
		ИначеЕсли Не ПустаяСтрока(ПоляАдреса.КодыКЛАДР.Город) Тогда
			Результат.CodeKLADR = ПоляАдреса.КодыКЛАДР.Город;
		ИначеЕсли Не ПустаяСтрока(ПоляАдреса.КодыКЛАДР.Район) Тогда
			Результат.CodeKLADR = ПоляАдреса.КодыКЛАДР.Район;
		ИначеЕсли Не ПустаяСтрока(ПоляАдреса.КодыКЛАДР.Регион) Тогда
			Результат.CodeKLADR = ПоляАдреса.КодыКЛАДР.Регион;
		КонецЕсли;
	КонецЕсли;
	
	Если ПоляАдреса.Свойство("ДополнительныеКоды") Тогда
		Результат.OKTMO          = ПоляАдреса.ДополнительныеКоды.ОКТМО;
		Результат.OKATO          = ПоляАдреса.ДополнительныеКоды.ОКАТО;
		Результат.IFNSFLCode     = ПоляАдреса.ДополнительныеКоды.КодИФНСФЛ;
		Результат.IFNSULCode     = ПоляАдреса.ДополнительныеКоды.КодИФНСЮЛ;
		Результат.IFNSFLAreaCode = ПоляАдреса.ДополнительныеКоды.КодУчасткаИФНСФЛ;
		Результат.IFNSULAreaCode = ПоляАдреса.ДополнительныеКоды.КодУчасткаИФНСЮЛ;
	КонецЕсли;
	
	Если Не ЗначениеЗаполнено(Результат.Value) Тогда
		ОбновитьПредставлениеАдреса(Результат, Ложь);
	КонецЕсли;
	
	Возврат УправлениеКонтактнойИнформациейСлужебный.СтруктураВСтрокуJSON(Результат);
	
КонецФункции

// Возвращает адрес в виде строки XML в соответствии со структурой XDTO КонтактнаяИнформация и Адрес.
//
// Параметры:
//  ИдентификаторАдреса - Строка - глобальный уникальный идентификационный код адресного объекта.
//  ДополнительнаяИнформацияАдреса - Структура - поля адреса, которые будет добавлены в адрес:
//   * АдресВJSON               - Булево - возвращает адрес в формате JSON.
//   * ДополнительнаяИнформация - Строка - комментарий адреса.
//   * Страна                   - Строка - наименование страны адреса.
//   * НомерДома                - Строка - номер дома.
//   * НомерОфиса               - Строка - номер офиса.
//   * НомерСтроения            - Строка - номер строения.
//   * ПочтовыйИндекс           - Строка - почтовый индекс адреса.
//   * АбонентскийЯщик          - Строка - абонентский ящик адреса.
//   * Муниципальный            - Булево - если Истина, адрес будет сформирован в муниципальном формате.
//                                         По умолчанию Ложь.
//
// Возвращаемое значение:
//  Строка - XML в соответствии со структурой XDTO пакетов КонтактнаяИнформация и Адрес.
//           JSON, если в ДополнительнаяИнформацияАдреса параметр АдресВJSON установлен в Истина.
//  Неопределено - если не удалось сформировать адрес по идентификатору.
//
Функция АдресПоИдентификатору(ИдентификаторАдреса, ДополнительнаяИнформацияАдреса = Неопределено) Экспорт
	
	Если ДополнительнаяИнформацияАдреса = Неопределено Тогда
		ДополнительнаяИнформацияАдреса = Новый Структура();
	КонецЕсли;
	
	Муниципальный = ?(ДополнительнаяИнформацияАдреса.Свойство("Муниципальный"), Булево(ДополнительнаяИнформацияАдреса.Муниципальный), Ложь);
	
	МодульАдресныйКлассификаторСлужебный = ОбщегоНазначения.ОбщийМодуль("АдресныйКлассификаторСлужебный");
	Сведения = МодульАдресныйКлассификаторСлужебный.СведенияОбАдресномОбъекта(ИдентификаторАдреса);
	Сведения.Муниципальный = Муниципальный;
	Сведения.ЗагруженныеДанные = Истина;
	
	ПолученныеАдрес = МодульАдресныйКлассификаторСлужебный.АктуальныеАдресныеСведения(Сведения);
	
	Если ПолученныеАдрес.Отказ Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Адрес = ПолученныеАдрес.Данные;
	
	Если ДополнительнаяИнформацияАдреса.Свойство("НомерДома") И ЗначениеЗаполнено(ДополнительнаяИнформацияАдреса.НомерДома) Тогда
		
		ОписаниеДома = РазделитьДомаСтроения(ДополнительнаяИнформацияАдреса.НомерДома, "Дом");
		Адрес.Вставить("houseType",   ОписаниеДома.Тип);
		Адрес.Вставить("houseNumber", ОписаниеДома.Номер);
		Адрес.Вставить("houseId",     "");
		
	КонецЕсли;
	
	Если ДополнительнаяИнформацияАдреса.Свойство("НомерСтроения") И ЗначениеЗаполнено(ДополнительнаяИнформацияАдреса.НомерСтроения) Тогда
		
		ОписаниеСтроения = РазделитьДомаСтроения(ДополнительнаяИнформацияАдреса.НомерСтроения, "Корпус");
		Строение = УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения(ОписаниеСтроения.Тип,  ОписаниеСтроения.Номер);
		СписокСтроенийАдреса = Адрес.buildings; // Массив
		СписокСтроенийАдреса.Добавить(Строение);
		
	КонецЕсли;
	
	Если ДополнительнаяИнформацияАдреса.Свойство("НомерОфиса") И ЗначениеЗаполнено(ДополнительнаяИнформацияАдреса.НомерОфиса) Тогда
		
		ОписаниеПомещения = РазделитьДомаСтроения(ДополнительнаяИнформацияАдреса.НомерОфиса, "Офис");
		Помещение = УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения(ОписаниеПомещения.Тип,  ОписаниеПомещения.Номер);
		СписокПомещенийАдреса = Адрес.apartments; // Массив
		СписокПомещенийАдреса.Добавить(Помещение);
		
	КонецЕсли;
	
	Если ДополнительнаяИнформацияАдреса.Свойство("АбонентскийЯщик") И ЗначениеЗаполнено(ДополнительнаяИнформацияАдреса.АбонентскийЯщик) Тогда
		
		ОписаниеАбонентскийЯщик = РазделитьДомаСтроения(ДополнительнаяИнформацияАдреса.АбонентскийЯщик, "А/Я");
		АбонентскийЯщик = УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения(ОписаниеАбонентскийЯщик.Тип,  ОписаниеАбонентскийЯщик.Номер);
		СписокПомещенийАдреса = Адрес.apartments; // Массив
		СписокПомещенийАдреса.Добавить(АбонентскийЯщик);
	КонецЕсли;

	Если ДополнительнаяИнформацияАдреса.Свойство("ПочтовыйИндекс") И ЗначениеЗаполнено(ДополнительнаяИнформацияАдреса.ПочтовыйИндекс) Тогда
		Адрес.ZIPcode = ДополнительнаяИнформацияАдреса.ПочтовыйИндекс;
	КонецЕсли;
	
	Если ДополнительнаяИнформацияАдреса.Свойство("ДополнительнаяИнформация") И ЗначениеЗаполнено(ДополнительнаяИнформацияАдреса.ДополнительнаяИнформация) Тогда
		Адрес.comment = ДополнительнаяИнформацияАдреса.ДополнительнаяИнформация;
	КонецЕсли;
	
	Если ДополнительнаяИнформацияАдреса.Свойство("Страна")  И ЗначениеЗаполнено(ДополнительнаяИнформацияАдреса.Страна) Тогда
		Адрес.country = ВРег(ДополнительнаяИнформацияАдреса.Страна);
	КонецЕсли;
	
	РасчетноеПредставление = УправлениеКонтактнойИнформациейСлужебный.ПредставлениеКонтактнойИнформации(Адрес);
	Адрес.value = РасчетноеПредставление;
	
	Если ДополнительнаяИнформацияАдреса.Свойство("АдресВJSON") И ДополнительнаяИнформацияАдреса.АдресВJSON = Истина Тогда
		
		Возврат УправлениеКонтактнойИнформациейСлужебный.СтруктураВСтрокуJSON(Адрес);
		
	КонецЕсли;
	
	Результат = Неопределено;
	УправлениеКонтактнойИнформациейЛокализация.ПриКонвертированииКонтактнуюИнформациюИзJSONВXML(Адрес, Результат, Перечисления.ТипыКонтактнойИнформации.Адрес);
	
	Возврат Результат;
	
КонецФункции

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

////////////////////////////////////////////////////////////////////////////////
// Обратная совместимость.

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

// Устарела. Следует использовать РаботаСАдресами.СведенияОбАдресе.
// Преобразует данные формата XML в предыдущий формат контактной информации.
//
// Параметры:
//    Данные                 - Строка - строка XML соответствующая XDTO пакету Адрес.
//    СокращенныйСоставПолей - Булево - если Ложь, то из состава полей будут исключены
//                                      поля, отсутствующие в версиях БСП младше 2.1.3.
//
// Возвращаемое значение:
//    Строка - набор пар ключ-значение, разделенных переносом строки.
//
Функция ПредыдущийФорматКонтактнойИнформацииXML(Знач Данные, Знач СокращенныйСоставПолей = Ложь) Экспорт
	
	Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВXML(Данные) Тогда
		СтарыйФормат = Обработки.РасширенныйВводКонтактнойИнформации.КонтактнаяИнформацияВСтаруюСтруктуру(Данные, СокращенныйСоставПолей);
		Возврат ПреобразоватьСписокПолейВСтроку(СтарыйФормат.ЗначенияПолей, Ложь);
	КонецЕсли;
	
	Возврат Данные;
КонецФункции

// Устарела. Следует использовать РаботаСАдресами.СведенияОбАдресе.
// Преобразует данные нового формата XML контактной информации в структуру старого формата.
//
// Параметры:
//   Данные                  - Строка - строка XML соответствующая XDTO пакету Адрес.
//   ВидКонтактнойИнформации - СправочникСсылка.ВидыКонтактнойИнформации
//                           - Структура - параметры контактной информации:
//     * Тип - ПеречислениеСсылка.ТипыКонтактнойИнформации - тип контактной информации.
//
// Возвращаемое значение:
//   Структура - состав свойств для адреса:
//     * Страна           - Строка - представление страны.
//     * КодСтраны        - Строка - код страны по ОКСМ.
//     * Индекс           - Строка - почтовый индекс (только для адресов РФ).
//     * Регион           - Строка - представление региона РФ (только для адресов РФ).
//     * КодРегиона       - Строка - код региона РФ (только для адресов РФ).
//     * РегионСокращение - Строка - сокращение региона (если СтарыйСоставПолей = Ложь).
//     * Район            - Строка - представление района (только для адресов РФ).
//     * РайонСокращение  - Строка - сокращение района (если СтарыйСоставПолей = Ложь).
//     * Город            - Строка - представление города (только для адресов РФ).
//     * ГородСокращение  - Строка - сокращение города (только для адресов РФ).
//     * НаселенныйПункт  - Строка - представление населенного пункта (только для адресов РФ).
//     * НаселенныйПунктСокращение - Строка - сокращение населенного пункта (если СтарыйСоставПолей = Ложь).
//     * Улица            - Строка - представление улицы (только для адресов РФ).
//     * УлицаСокращение  - Строка - сокращение улицы (если СтарыйСоставПолей = Ложь).
//     * ТипДома          - см. РаботаСАдресами.ТипыОбъектовАдресацииАдресаРФ.
//     * Дом              - Строка - представление дома (только для адресов РФ).
//     * ТипКорпуса       - см. РаботаСАдресами.ТипыОбъектовАдресацииАдресаРФ.
//     * Корпус           - Строка - представление корпуса (только для адресов РФ).
//     * ТипКвартиры      - см. РаботаСАдресами.ТипыОбъектовАдресацииАдресаРФ.
//     * Квартира         - Строка - представление квартиры (только для адресов РФ).
//    Состав свойств для телефона:
//     * КодСтраны        - Строка - код страны. Например, +7.
//     * КодГорода        - Строка - код города. Например, 495.
//     * НомерТелефона    - Строка - номер телефона.
//     * Добавочный       - Строка - добавочный номер телефона.
//
Функция ПредыдущаяСтруктураКонтактнойИнформацииXML(Знач Данные, Знач ВидКонтактнойИнформации = Неопределено) Экспорт
	
	Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВXML(Данные) Тогда
		// Новый формат КИ
		Возврат УправлениеКонтактнойИнформациейСлужебный.СтруктураЗначенийПолей(
			ПредыдущийФорматКонтактнойИнформацииXML(Данные));
		
	КонецЕсли;
	
	Если ВидКонтактнойИнформации <> Неопределено
		И ((ТипЗнч(ВидКонтактнойИнформации) = Тип("Структура") И ВидКонтактнойИнформации.Свойство("Тип"))
		ИЛИ ТипЗнч(ВидКонтактнойИнформации) = Тип("СправочникСсылка.ВидыКонтактнойИнформации")) Тогда
			ТипКонтактнойИнформации = ВидКонтактнойИнформации.Тип;
	Иначе
		ТипКонтактнойИнформации = Неопределено;
	КонецЕсли;
	
	Если ПустаяСтрока(Данные)  Тогда
		// Генерируем по типу
		Возврат РаботаСАдресамиКлиентСервер.СтруктураКонтактнойИнформацииПоТипу(ТипКонтактнойИнформации);
		
	КонецЕсли;
	
	// Возвращаем полную структуру для данного вида с заполненными полями.
	Результат = РаботаСАдресамиКлиентСервер.СтруктураКонтактнойИнформацииПоТипу(ТипКонтактнойИнформации);
	СтруктураЗначенийПолей = УправлениеКонтактнойИнформациейСлужебный.СтруктураЗначенийПолей(Данные, ВидКонтактнойИнформации);
	Если ТипКонтактнойИнформации <> Неопределено Тогда
		ЗаполнитьЗначенияСвойств(Результат, СтруктураЗначенийПолей);
		Возврат Результат;
	КонецЕсли;
	
	Возврат СтруктураЗначенийПолей;
	
КонецФункции

// Устарела. Следует использовать РаботаСАдресами.СведенияОбАдресе.
// Преобразует адреса формата XML в адрес формата КЛАДР.
//
// Параметры:
//   Данные                  - Строка - строка XML соответствующая XDTO пакету Адрес.
//
// Возвращаемое значение:
//   Структура - набор пар ключ-значение. Состав свойств для адреса:
//    * Страна           - Строка - представление страны.
//    * КодСтраны        - Строка - код страны по ОКСМ.
//    * Индекс           - Строка - почтовый индекс (только для адресов РФ).
//    * Регион           - Строка - представление региона РФ (только для адресов РФ).
//    * КодРегиона       - Строка - код региона РФ (только для адресов РФ).
//    * РегионСокращение - Строка - сокращение региона.
//    * Район            - Строка - представление района (только для адресов РФ).
//    * РайонСокращение  - Строка - сокращение района.
//    * Город            - Строка - представление города (только для адресов РФ).
//    * ГородСокращение  - Строка - сокращение города (только для адресов РФ).
//    * НаселенныйПункт  - Строка - представление населенного пункта (только для адресов РФ).
//    * НаселенныйПунктСокращение - Строка - сокращение населенного пункта.
//    * Улица            - Строка - представление улицы (только для адресов РФ).
//    * УлицаСокращение  - Строка - сокращение улицы.
//    * ТипДома          - см. РаботаСАдресами.ТипыОбъектовАдресацииАдресаРФ.
//    * Дом              - Строка - представление дома (только для адресов РФ).
//    * ТипКорпуса       - см. РаботаСАдресами.ТипыОбъектовАдресацииАдресаРФ.
//    * Корпус           - Строка - представление корпуса (только для адресов РФ).
//    * ТипКвартиры      - см. РаботаСАдресами.ТипыОбъектовАдресацииАдресаРФ.
//    * Квартира         - Строка - представление квартиры (только для адресов РФ).
//    * АдресРФ          - Булево - если Истина, то адрес российский.
//    * Представление    - Строка - представление адреса.
//
Функция АдресВФорматеКЛАДР(Знач Данные) Экспорт
	
	Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВXML(Данные) Тогда
		// Новый формат КИ
		Результат = УправлениеКонтактнойИнформациейСлужебный.СтруктураЗначенийПолей(
				ПредыдущийФорматКонтактнойИнформацииXML(Данные));
			Представление = УправлениеКонтактнойИнформацией.ПредставлениеКонтактнойИнформации(Данные);
			
	ИначеЕсли ПустаяСтрока(Данные) Тогда
		// Генерируем пустую структуру по виду
		Результат = РаботаСАдресамиКлиентСервер.СтруктураКонтактнойИнформацииПоТипу(
			Перечисления.ТипыКонтактнойИнформации.Адрес);
		Представление = "";
	КонецЕсли;
	
	НазваниеОсновнойСтраны = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(РаботаСАдресамиКлиентСервер.ОсновнаяСтрана(), "Наименование");
	Если Результат.Свойство("Страна") И СтрСравнить(Результат.Страна, НазваниеОсновнойСтраны) = 0 Тогда
		Результат.Вставить("АдресРФ", Истина);
	Иначе
		Результат.Вставить("АдресРФ", Ложь);
	КонецЕсли;
	Результат.Вставить("Представление", Представление);
	
	Возврат Результат;
КонецФункции

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

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

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

// См. КонтрольВеденияУчетаПереопределяемый.ПриОпределенииПроверок
Процедура ПриОпределенииПроверок(ГруппыПроверок, Проверки) Экспорт
	
	ГруппаПроверок = ГруппыПроверок.Найти("КонтактнаяИнформация", "Идентификатор");
	Если ГруппаПроверок = Неопределено Тогда
		ГруппаПроверок = ГруппыПроверок.Добавить();
		ГруппаПроверок.Наименование                 = НСтр("ru = 'Контактная информация'");
		ГруппаПроверок.Идентификатор                = "КонтактнаяИнформация";
		ГруппаПроверок.КонтекстПроверокВеденияУчета = "_КонтактнаяИнформация";
	КонецЕсли;
	
	Проверка = Проверки.Добавить();
	Проверка.ИдентификаторГруппы          = "КонтактнаяИнформация";
	Проверка.Наименование                 = НСтр("ru = 'Исправление адресов содержащих устаревший тип здания Литер.'");
	Проверка.Причины                      = НСтр("ru = 'В октябре 2019 г. в федеральной информационной адресной системе тип здания ""Литер"" был переименован в ""Литера"".'");
	Проверка.Рекомендация                 = НСтр("ru = 'Исправить в адресе Литер на Литера (для этого нажать ссылку ниже).
		|При этом следует оставлять без изменений юридически значимые адреса (адрес ЕГРЮЛ, место регистрации, рождения и др.).
		|
		|Если работа ведется в распределенной информационной базе (РИБ), то исправление следует запускать только в главном узле.
		|Затем выполнить синхронизацию с подчиненными узлами.'");
	Проверка.Идентификатор                = "РаботаСАдресами.ИсправитьТипЗданияЛитерВАдресах";
	Проверка.ОбработчикПроверки           = "РаботаСАдресами.ПроверитьАдресаНаТипЗданияЛитер";
	Проверка.ОбработчикПереходаКИсправлению = "Обработка.РасширенныйВводКонтактнойИнформации.Форма.ИсправлениеАдресов";
	Проверка.КонтекстПроверокВеденияУчета = "_КонтактнаяИнформация";
	Проверка.Отключена                    = Истина;
	
	Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.АдресныйКлассификатор") Тогда
		Возврат;
	КонецЕсли;
	
	МодульАдресныйКлассификаторСлужебный = ОбщегоНазначения.ОбщийМодуль("АдресныйКлассификаторСлужебный");
	НавигационнаяСсылкаЗагрузкиАдресногоКлассификатора = МодульАдресныйКлассификаторСлужебный.НавигационнаяСсылкаЗагрузкиАдресногоКлассификатора();
	
	Проверка = Проверки.Добавить();
	Проверка.ИдентификаторГруппы          = "КонтактнаяИнформация";
	Проверка.Наименование                 = НСтр("ru = 'Выявление устаревших адресов контактной информации'");
	Проверка.Причины                      = НСтр("ru = 'Переподчинение адресных объектов (улиц, населенных пунктов), их переименование или упразднение влечет за собой внесение изменений в 
		|Государственном адресном реестре (ГАР). После этого ранее введенные адреса перестают проходить проверку на соответствие адресному классификатору.'");
	Проверка.Рекомендация                 = НСтр("ru = 'Для автоматической замены устаревших адресов на актуальные нажать ссылку ниже.
		|При этом следует оставлять без изменений юридически значимые адреса (адрес ЕГРЮЛ, место регистрации, рождения и др.).
		|
		|Если работа ведется в распределенной информационной базе (РИБ), то исправление следует запускать только в главном узле.
		|Затем выполнить синхронизацию с подчиненными узлами.'");
	Проверка.Идентификатор                = "РаботаСАдресами.ВыявитьУстаревшиеАдреса";
	Проверка.ОбработчикПроверки           = "РаботаСАдресами.ВыявитьУстаревшиеАдреса";
	Проверка.ОбработчикПереходаКИсправлению = "Обработка.РасширенныйВводКонтактнойИнформации.Форма.ИсправлениеАдресов";
	Проверка.КонтекстПроверокВеденияУчета = "_КонтактнаяИнформация";
	Проверка.Отключена                    = Истина;
	
	Проверка = Проверки.Добавить();
	Проверка.ИдентификаторГруппы          = "КонтактнаяИнформация";
	Проверка.Наименование                 = НСтр("ru = 'Проверка адресов на соответствие адресному классификатору.'");
	Проверка.Причины                      = НСтр("ru = 'Адрес контактной информации введен некорректно, устарел, был некорректно загружен из других источников или еще не внесен в Федеральную информационную адресную систему.'");
	Рекомендация                          = НСтр("ru = 'В зависимости от ситуации следует выбрать один из вариантов:
		|•	Убедиться, что адрес введен корректно, проверив  адрес на сайте ФНС России: %1
		|О некорректных или неполных адресных сведениях на сайте ФНС России рекомендуется сообщать в органы местного самоуправления или в службу технической  поддержки online-сервисов ФНС России.
		|•	Если адрес устарел вследствие переименования, переподчинения или упразднения адресных объектов (улиц, населенных пунктов), то введите актуальный адрес.
		|•	Если не удалось автоматически исправить адрес, то его следует ввести вручную, открыв форму ввода адреса.
		|
		|Если адресный классификатор загружен в приложение, то: 
		|•	предварительно следует его обновить до последней версии адресных сведений (Раздел Администрирование);
		|•	для выявления и автоматического исправления устаревших адресов загрузить историю изменения адресов объектов
		|Ссылка для быстрого перехода %2
		|
		|Если работа ведется в распределенной информационной базе (РИБ), то исправления следует вносить только в главном узле.
		|Затем выполнить синхронизацию с подчиненными узлами.'");
	Проверка.Рекомендация                 = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(Рекомендация,
		"https://fias.nalog.ru/ExtendedSearch",
		НавигационнаяСсылкаЗагрузкиАдресногоКлассификатора);
	
	Проверка.Идентификатор                = "РаботаСАдресами.ПроверитьАдресаНаСоответствиеАдресномуКлассификатору";
	Проверка.ОбработчикПроверки           = "РаботаСАдресами.ПроверитьАдресаНаСоответствиеАдресномуКлассификатору";
	Проверка.ОбработчикПереходаКИсправлению = "Обработка.РасширенныйВводКонтактнойИнформации.Форма.ИсправлениеАдресов";
	Проверка.КонтекстПроверокВеденияУчета = "_КонтактнаяИнформация";
	Проверка.Отключена                    = Истина;
	
КонецПроцедуры

// Возвращает пространство имен для оперирования с XDTO контактной информации.
//
// Возвращаемое значение:
//      Строка - пространство имен.
//
Функция ПространствоИмен() Экспорт
	Возврат "http://www.v8.1c.ru/ssl/contactinfo_ru";
КонецФункции

// Преобразует XML. Обратная совместимость.
//
// Параметры:
//   ТекстXML - Строка
// Возвращаемое значение:
//   Строка
//
Функция ПередЧтениемXDTOКонтактнаяИнформация(ТекстXML) Экспорт
	
	Если СтрНайти(ТекстXML, "Адрес") = 0 Тогда
		Возврат ТекстXML;
	КонецЕсли;
	
	Если СтрНайти(ТекстXML, "http://www.v8.1c.ru/ssl/contactinfo_ru") > 0 Тогда
		Возврат ТекстXML;
	КонецЕсли;
	
	ТекстXML = СтрЗаменить(ТекстXML, "xsi:type=""АдресРФ""", "xmlns:rf=""http://www.v8.1c.ru/ssl/contactinfo_ru"" xsi:type=""rf:АдресРФ""");
	
	ТекстXML = СтрЗаменить(ТекстXML, "<СубъектРФ", "<rf:СубъектРФ");
	ТекстXML = СтрЗаменить(ТекстXML, "/СубъектРФ>", "/rf:СубъектРФ>");
	ТекстXML = СтрЗаменить(ТекстXML, "<СубъектРФ/>", "<rf:СубъектРФ/>");
	
	ТекстXML = СтрЗаменить(ТекстXML, "<Округ", "<rf:Округ");
	ТекстXML = СтрЗаменить(ТекстXML, "/Округ>", "/rf:Округ>");
	ТекстXML = СтрЗаменить(ТекстXML, "<Округ/>", "<rf:Округ/>");
	
	ТекстXML = СтрЗаменить(ТекстXML, "<СвРайМО", "<rf:СвРайМО");
	ТекстXML = СтрЗаменить(ТекстXML, "/СвРайМО>", "/rf:СвРайМО>");
	ТекстXML = СтрЗаменить(ТекстXML, "<СвРайМО/>", "<rf:СвРайМО/>");
	
	ТекстXML = СтрЗаменить(ТекстXML, "<Район", "<rf:Район");
	ТекстXML = СтрЗаменить(ТекстXML, "/Район>", "/rf:Район>");
	ТекстXML = СтрЗаменить(ТекстXML, "</Район>", "</rf:Район>");
	
	ТекстXML = СтрЗаменить(ТекстXML, "<Город", "<rf:Город");
	ТекстXML = СтрЗаменить(ТекстXML, "/Город>", "/rf:Город>");
	ТекстXML = СтрЗаменить(ТекстXML, "<Город/>", "<rf:Город/>");
	
	ТекстXML = СтрЗаменить(ТекстXML, "ВнутригРайон", "rf:ВнутригРайон");
	
	ТекстXML = СтрЗаменить(ТекстXML, "НаселПункт", "rf:НаселПункт");
	
	ТекстXML = СтрЗаменить(ТекстXML, "<Улица", "<rf:Улица");
	ТекстXML = СтрЗаменить(ТекстXML, "/Улица>", "/rf:Улица>");
	ТекстXML = СтрЗаменить(ТекстXML, "<Улица/>", "<rf:Улица/>");
	
	ТекстXML = СтрЗаменить(ТекстXML, "ОКТМО", "rf:ОКТМО");
	ТекстXML = СтрЗаменить(ТекстXML, "ОКАТО", "rf:ОКАТО");
	
	ТекстXML = СтрЗаменить(ТекстXML, "ДопАдрЭл", "rf:ДопАдрЭл");
	
	ТекстXML = СтрЗаменить(ТекстXML, "<Номер", "<rf:Номер");
	ТекстXML = СтрЗаменить(ТекстXML, "/Номер>", "/rf:Номер>");
	ТекстXML = СтрЗаменить(ТекстXML, "<Номер/>", "<rf:Номер/>");
	
	ТекстXML = СтрЗаменить(ТекстXML, "<Местоположение", "<rf:Местоположение");
	ТекстXML = СтрЗаменить(ТекстXML, "/Местоположение>", "/rf:Местоположение>");
	ТекстXML = СтрЗаменить(ТекстXML, "<Местоположение/>", "<rf:Местоположение/>");
	
	Возврат ТекстXML;
	
КонецФункции

Функция ПередЗаписьюXDTOКонтактнаяИнформация(ТекстXML) Экспорт
	
	Позиция = СтрНайти(ТекстXML, "АдресРФ""");
	Если Позиция > 0 Тогда
		ПозицияНачало = СтрНайти(ТекстXML, """", НаправлениеПоиска.СКонца, Позиция);
		Префикс = Сред(ТекстXML, ПозицияНачало + 1, Позиция - ПозицияНачало - 2);
		
		ТекстXML = СтрЗаменить(ТекстXML, Префикс +":", "");
		ТекстXML = СтрЗаменить(ТекстXML, " xmlns:"+ Префикс + "=""http://www.v8.1c.ru/ssl/contactinfo_ru""", "");
	КонецЕсли;
	
	Возврат ТекстXML;
КонецФункции

Функция ДополнительныеПравилаПреобразования() Экспорт
	
	КодыДополнительныхАдресныхЭлементов = Новый ТекстовыйДокумент;
	Для Каждого ДополнительныйАдресныйЭлемент Из ТипыОбъектовАдресацииАдресаРФ() Цикл
		КодыДополнительныхАдресныхЭлементов.ДобавитьСтроку("<data:item data:title=""" + ДополнительныйАдресныйЭлемент.Наименование + """>" + ДополнительныйАдресныйЭлемент.Код + "</data:item>");
		КодыДополнительныхАдресныхЭлементов.ДобавитьСтроку("<data:item data:title=""" + НРег(ДополнительныйАдресныйЭлемент.Наименование) + """>" + ДополнительныйАдресныйЭлемент.Код + "</data:item>");
	КонецЦикла;
	
	КодыРегионов = Новый ТекстовыйДокумент;
	ВсеРегионы = ВсеРегионы();
	Если ВсеРегионы <> Неопределено Тогда
		Для Каждого Регион Из ВсеРегионы Цикл
			КодыРегионов.ДобавитьСтроку("<data:item data:code=""" + Формат(Регион.КодСубъектаРФ, "ЧН=; ЧГ=") + """>" 
				+ Регион.Представление + "</data:item>");
		КонецЦикла;
	КонецЕсли;
	
	РасширенныйТекстПреобразования = "
	|  <xsl:template match=""/"" mode=""domestic"">
	|    <xsl:element name=""Состав"">
	|      <xsl:attribute name=""xsi:type"">АдресРФ</xsl:attribute>
	|    
	|      <xsl:element name=""СубъектРФ"">
	|        <xsl:variable name=""value"" select=""tns:Structure/tns:Property[@name='Регион']/tns:Value/text()"" />
	|
	|        <xsl:choose>
	|          <xsl:when test=""0=count($value)"">
	|            <xsl:variable name=""regioncode"" select=""tns:Structure/tns:Property[@name='КодРегиона']/tns:Value/text()""/>
	|            <xsl:variable name=""regiontitle"" select=""$enum-regioncode-nodes/data:item[@data:code=number($regioncode)]"" />
	|              <xsl:if test=""0!=count($regiontitle)"">
	|                <xsl:value-of select=""$regiontitle""/>
	|              </xsl:if>
	|          </xsl:when>
	|          <xsl:otherwise>
	|            <xsl:value-of select=""$value"" />
	|          </xsl:otherwise> 
	|        </xsl:choose>
	|
	|      </xsl:element>
	|   
	|      <xsl:element name=""Округ"">
	|        <xsl:value-of select=""tns:Structure/tns:Property[@name='Округ']/tns:Value/text()""/>
	|      </xsl:element>
	|
	|      <xsl:element name=""СвРайМО"">
	|        <xsl:element name=""Район"">
	|          <xsl:value-of select=""tns:Structure/tns:Property[@name='Район']/tns:Value/text()""/>
	|        </xsl:element>
	|      </xsl:element>
	|  
	|      <xsl:element name=""Город"">
	|        <xsl:value-of select=""tns:Structure/tns:Property[@name='Город']/tns:Value/text()""/>
	|      </xsl:element>
	|    
	|      <xsl:element name=""ВнутригРайон"">
	|        <xsl:value-of select=""tns:Structure/tns:Property[@name='ВнутригРайон']/tns:Value/text()""/>
	|      </xsl:element>
	|
	|      <xsl:element name=""НаселПункт"">
	|        <xsl:value-of select=""tns:Structure/tns:Property[@name='НаселенныйПункт']/tns:Value/text()""/>
	|      </xsl:element>
	|
	|      <xsl:element name=""Улица"">
	|        <xsl:value-of select=""tns:Structure/tns:Property[@name='Улица']/tns:Value/text()""/>
	|      </xsl:element>
	|
	|      <xsl:variable name=""index"" select=""tns:Structure/tns:Property[@name='Индекс']/tns:Value/text()"" />
	|      <xsl:if test=""0!=count($index)"">
	|        <xsl:element name=""ДопАдрЭл"">
	|          <xsl:attribute name=""ТипАдрЭл"">" + КодСериализацииПочтовогоИндекса() + "</xsl:attribute>
	|          <xsl:attribute name=""Значение""><xsl:value-of select=""$index""/></xsl:attribute>
	|        </xsl:element>
	|      </xsl:if>
	|
	|      <xsl:call-template name=""add-elem-number"">
	|        <xsl:with-param name=""source"" select=""tns:Structure/tns:Property[@name='ТипДома']/tns:Value/text()"" />
	|        <xsl:with-param name=""defsrc"" select=""'Дом'"" />
	|        <xsl:with-param name=""value""  select=""tns:Structure/tns:Property[@name='Дом']/tns:Value/text()"" />
	|      </xsl:call-template>
	|
	|      <xsl:call-template name=""add-elem-number"">
	|        <xsl:with-param name=""source"" select=""tns:Structure/tns:Property[@name='ТипКорпуса']/tns:Value/text()"" />
	|        <xsl:with-param name=""defsrc"" select=""'Корпус'"" />
	|        <xsl:with-param name=""value""  select=""tns:Structure/tns:Property[@name='Корпус']/tns:Value/text()"" />
	|      </xsl:call-template>
	|
	|      <xsl:call-template name=""add-elem-number"">
	|        <xsl:with-param name=""source"" select=""tns:Structure/tns:Property[@name='ТипКвартиры']/tns:Value/text()"" />
	|        <xsl:with-param name=""defsrc"" select=""'Квартира'"" />
	|        <xsl:with-param name=""value""  select=""tns:Structure/tns:Property[@name='Квартира']/tns:Value/text()"" />
	|      </xsl:call-template>
	|    
	|    </xsl:element>
	|  </xsl:template>
	|
	|  <xsl:param name=""enum-codevalue"">
	|" + КодыДополнительныхАдресныхЭлементов.ПолучитьТекст() + "
	|  </xsl:param>
	|  <xsl:variable name=""enum-codevalue-nodes"" select=""exsl:node-set($enum-codevalue)"" />
	|
	|  <xsl:param name=""enum-regioncode"">
	|" + КодыРегионов.ПолучитьТекст() + "
	|  </xsl:param>
	|  <xsl:variable name=""enum-regioncode-nodes"" select=""exsl:node-set($enum-regioncode)"" />
	|  
	|  <xsl:template name=""add-elem-number"">
	|    <xsl:param name=""source"" />
	|    <xsl:param name=""defsrc"" />
	|    <xsl:param name=""value"" />
	|
	|    <xsl:if test=""0!=count($value)"">
	|
	|      <xsl:choose>
	|        <xsl:when test=""0!=count($source)"">
	|          <xsl:variable name=""type-code"" select=""$enum-codevalue-nodes/data:item[@data:title=$source]"" />
	|          <xsl:element name=""ДопАдрЭл"">
	|            <xsl:element name=""Номер"">
	|              <xsl:attribute name=""Тип""><xsl:value-of select=""$type-code"" /></xsl:attribute>
	|              <xsl:attribute name=""Значение""><xsl:value-of select=""$value""/></xsl:attribute>
	|            </xsl:element>
	|          </xsl:element>
	|
	|        </xsl:when>
	|        <xsl:otherwise>
	|          <xsl:variable name=""type-code"" select=""$enum-codevalue-nodes/data:item[@data:title=$defsrc]"" />
	|          <xsl:element name=""ДопАдрЭл"">
	|            <xsl:element name=""Номер"">
	|              <xsl:attribute name=""Тип""><xsl:value-of select=""$type-code"" /></xsl:attribute>
	|              <xsl:attribute name=""Значение""><xsl:value-of select=""$value""/></xsl:attribute>
	|            </xsl:element>
	|          </xsl:element>
	|
	|        </xsl:otherwise>
	|      </xsl:choose>
	|
	|    </xsl:if>
	|  
	|  </xsl:template>
	|  
	|</xsl:stylesheet>";
	
	Возврат РасширенныйТекстПреобразования;
КонецФункции

#Область ДляВызоваИзДругихПодсистем

// ИнтернетПоддержкаПользователей.РаботаСКлассификаторами

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

	Описание.Идентификатор              = ИдентификаторКлассификатора();
	Описание.Наименование               = НСтр("ru = 'Общероссийский классификатор стран мира'");
	Описание.ОбновлятьАвтоматически     = Истина;
	Описание.ОбщиеДанные                = Истина;
	Описание.СохранятьФайлВКэш          = Истина;
	Описание.ОбработкаРазделенныхДанных = Ложь;
	
	Классификаторы.Добавить(Описание);
	
КонецПроцедуры

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

// Конец ИнтернетПоддержкаПользователей.РаботаСКлассификаторами

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

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

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

// Параметры:
//  СписокВыбора - СписокЗначений
//
Процедура ЗаполнитьМаскиНомераТелефона(СписокВыбора) Экспорт
	
	МаскаНомера = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru='+7(999) 999-99-99, <span style=""color: %1""> (Пример: +7(910) 123-23-23)</span>'"),
					"ПоясняющийТекст");
	СписокВыбора.Добавить("+7(999) 999-99-99", СтроковыеФункции.ФорматированнаяСтрока(МаскаНомера));
	
	МаскаНомера = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru='##(99999) 999-99-99, <span style=""color: %1""> (Пример: 8(4822) 12-34-56)</span>'"),
					"ПоясняющийТекст");
	СписокВыбора.Добавить("##(99999) 999-99-99", СтроковыеФункции.ФорматированнаяСтрока(МаскаНомера));
	
	МаскаНомера = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru='999999999, <span style=""color: %1""> (Пример: 9001234567)</span>'"),
					"ПоясняющийТекст");
	СписокВыбора.Добавить("(999) 999-9999", СтроковыеФункции.ФорматированнаяСтрока(МаскаНомера));
	
КонецПроцедуры

// При начальном заполнении элементов.
// 
// Параметры:
//  КодыЯзыков - см. СправочникМенеджер.СтраныМира.ПриНачальномЗаполненииЭлементов.КодыЯзыков
//  Элементы - см. СправочникМенеджер.СтраныМира.ПриНачальномЗаполненииЭлементов.Элементы
//  ТабличныеЧасти - см. СправочникМенеджер.СтраныМира.ПриНачальномЗаполненииЭлементов.ТабличныеЧасти
//
Процедура ПриНачальномЗаполненииЭлементов(КодыЯзыков, Элементы, ТабличныеЧасти) Экспорт
	
	Элемент = Элементы.Добавить();
	Элемент.ИмяПредопределенныхДанных = "Россия";
	Элемент.Код                       = "643";
	Элемент.Наименование              = НСтр("ru = 'РОССИЯ'", ОбщегоНазначения.КодОсновногоЯзыка());
	Элемент.НаименованиеПолное        = НСтр("ru = 'Российская Федерация'", ОбщегоНазначения.КодОсновногоЯзыка());
	Элемент.КодАльфа2                 = "RU";
	Элемент.КодАльфа3                 = "RUS";
	Элемент.УчастникЕАЭС              = Истина;
	Элемент.МеждународноеНаименование = НСтр("ru = 'The Russian Federation'", ОбщегоНазначения.КодОсновногоЯзыка());
	
КонецПроцедуры

Функция ИдентификаторКлассификатора() Экспорт
	Возврат "Countries";
КонецФункции

// Возвращает XPath для района.
//
// Возвращаемое значение:
//      Строка - XPath
//
Функция XPathРайона() Экспорт
	
	Возврат "СвРайМО/Район";
	
КонецФункции

// Возвращает массив структур с информацией о частях адреса согласно приказу ФНС ММВ-7-1/525 от 31.08.2011.
//
// Возвращаемое значение:
//   Массив из Структура:
//    * Код - Строка
//    * Наименование - Строка
//    * Тип - Строка
//    * Порядок - Строка
//    * КодАдресногоКлассификатора - Строка
//    * Сокращение - Строка
//    * Ключ - Строка
//
Функция ТипыОбъектовАдресацииАдресаРФ() Экспорт
	
	Результат = Новый Массив;
	
	// Код, Наименование, Тип, Порядок, КодАдресногоКлассификатора
	// Тип: 1 - владение, 2 - здание, 3 - помещение.
	
	Результат.Добавить(СтрокаОбъектаАдресации("1010", "Дом",          1, 1, 2)); // Тип владения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("1020", "Владение",     1, 2, 1)); // Тип владения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("1030", "Домовладение", 1, 3, 3)); // Тип владения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("1034", "Гараж",        1, 4, 4)); // Тип владения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("1036", "Здание",       1, 5, 5)); // Тип владения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("1038", "Шахта",        1, 6, 6)); // Тип владения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("1039", РаботаСАдресамиКлиентСервер.НаименованиеЗемельногоУчастка()
		, 1, 9, 9));
	Результат.Добавить(СтрокаОбъектаАдресации("1011", "Строение",     1, 1, 7)); // Тип владения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("1012", "Сооружение",   1, 1, 7)); // Тип владения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("1013", "Литера",       1, 1, 7)); // Тип владения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("1014", "Корпус",       1, 1, 7)); // Тип владения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("1015", "Подвал",       1, 1, 8)); // Тип владения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("1016", "Котельная",    1, 1, 8)); // Тип владения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("1017", "Погреб",       1, 1, 8)); // Тип владения не локализуется
	
	Результат.Добавить(СтрокаОбъектаАдресации("1050", "Корпус",     2, 1)); // Тип здания не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("1060", "Строение",   2, 2, 1)); // Тип здания не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("1080", "Литера",     2, 3, 3)); // Тип здания не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("1090", "Литер",      2, 6, 3)); // Тип здания не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("1070", "Сооружение", 2, 4, 2)); // Тип здания не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("1040", "Участок",    2, 5)); // Тип здания не локализуется
	
	Результат.Добавить(СтрокаОбъектаАдресации("2010", "Квартира",  3, 1)); // Тип помещения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("2030", "Офис",      3, 2)); // Тип помещения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("2040", "Бокс",      3, 3)); // Тип помещения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("2020", "Помещение", 3, 4)); // Тип помещения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("2050", "Комната",   3, 5)); // Тип помещения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("2060", "Этаж",      3, 6)); // Тип помещения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("2070", "А/я",       3, 7)); // Тип помещения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("2080", "В/ч",       3, 8)); // Тип помещения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("2090", "П/о",       3, 9)); // Тип помещения не локализуется
	//  Наши сокращения для поддержки обратной совместимости при парсинге.
	Результат.Добавить(СтрокаОбъектаАдресации("2010", "кв.",       3, 6)); // Тип помещения не локализуется
	Результат.Добавить(СтрокаОбъектаАдресации("2030", "оф.",       3, 7)); // Тип помещения не локализуется
	// Ввод помещения вручную.
	Результат.Добавить(СтрокаОбъектаАдресации("2000", "",          3, 0));
	
	// Уточняющие объекты
	Результат.Добавить(СтрокаОбъектаАдресации("10100000", НСтр("ru = 'Почтовый индекс'")));
	Результат.Добавить(СтрокаОбъектаАдресации("10200000", НСтр("ru = 'Адресная точка'")));
	Результат.Добавить(СтрокаОбъектаАдресации("10300000", НСтр("ru = 'Садовое товарищество'")));
	Результат.Добавить(СтрокаОбъектаАдресации("10400000", НСтр("ru = 'Элемент улично-дорожной сети, планировочной структуры дополнительного адресного элемента'")));
	Результат.Добавить(СтрокаОбъектаАдресации("10500000", НСтр("ru = 'Промышленная зона'")));
	Результат.Добавить(СтрокаОбъектаАдресации("10600000", НСтр("ru = 'Гаражно-строительный кооператив'")));
	Результат.Добавить(СтрокаОбъектаАдресации("10700000", НСтр("ru = 'Территория'")));
	
	Возврат Результат;
КонецФункции

// Возвращает форматированное представление адреса.
// Вызовы функции необходимо выполнять из общего модуля УправлениеКонтактнойИнформацией
//
// Функция формирует строковое представление адреса в соответствии 
// с указанным порядком полей. Поддерживает различные форматы вывода,
// включая обратный порядок (от номера дома к региону) и сокращенные варианты.
//
// Параметры:
//   Адрес - Строка - адрес в формате JSON.
//         - Структура - перечень полей адреса, где ключ соответствует 
//             именам полей из функции СведенияОбАдресе. Например: Город.
//   Поля - Массив - список полей для формирования адреса в нужном порядке. Например, "Регион", "Город".
//        - Строка - предопределенные варианты: "НаселенныйПункт" - возвращает адрес до уровня населенного 
//              пункта (без улицы и номера дома).
//        - Неопределено - набор полей по умолчанию.
// Возвращаемое значение:
//   Строка - сформированное представление адреса. Если переданный адрес некорректен, будет возвращена пустая строка.
//
Функция ПредставлениеАдреса(АдресПоПолям, ТипАдреса, ПараметрыПредставления = Неопределено) Экспорт
	
	ПоляПредставления = Новый Массив();
	ПостфиксТипаАдреса = ПараметрыПредставления.ПостфиксТипаАдреса;
	Если ПустаяСтрока(ПостфиксТипаАдреса) Тогда
		ПостфиксТипаАдреса = "ТипКраткий";
	КонецЕсли;
	
	ПорядокПолей = ОпределитьПорядокУровнейДляПредставления(ПараметрыПредставления, ТипАдреса);
	
	Для Каждого ИмяПоля Из ПорядокПолей Цикл
		
		Если СтрСравнить(ИмяПоля, "Дом") = 0 Тогда
			
			ПоляПредставления.Добавить(
				УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеАдресногоОбъекта(АдресПоПолям.Здание, "Номер", "ТипЗдания", Истина));
			
			Для Каждого Корпус Из АдресПоПолям.Корпуса Цикл
				ПоляПредставления.Добавить(
					УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеАдресногоОбъекта(Корпус, "Номер", "ТипКорпуса", Истина));
			КонецЦикла;
			
		ИначеЕсли СтрСравнить(ИмяПоля, "Помещения") = 0 Тогда
			Для Каждого Помещение Из АдресПоПолям.Помещения Цикл
				ПоляПредставления.Добавить(
					УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеАдресногоОбъекта(Помещение, "Номер", "ТипПомещения", Истина));
			КонецЦикла;
		ИначеЕсли СтрСравнить(ИмяПоля, "Индекс") = 0 Или СтрСравнить(ИмяПоля, "Страна") = 0 Тогда
			ПоляПредставления.Добавить(АдресПоПолям[ИмяПоля]);
		ИначеЕсли АдресПоПолям.Свойство(ИмяПоля) И ЗначениеЗаполнено(АдресПоПолям[ИмяПоля]) Тогда
			
			Если СтрСравнить(ИмяПоля, "Регион") <> 0 Тогда
				ЗначениеОбъекта = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеАдресногоОбъекта(АдресПоПолям, ИмяПоля, ПостфиксТипаАдреса);
			Иначе
			
				ЗначениеОбъекта = "";
				Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.АдресныйКлассификатор") Тогда
					МодульАдресныйКлассификаторСлужебный = ОбщегоНазначения.ОбщийМодуль("АдресныйКлассификаторСлужебный");
					СведенияОРегионе = МодульАдресныйКлассификаторСлужебный.СведенияОРегионе(АдресПоПолям[ИмяПоля], АдресПоПолям[ИмяПоля + ПостфиксТипаАдреса]);
					ЗначениеОбъекта  = СведенияОРегионе.ПолноеНаименование;
				КонецЕсли;
				
				Если ПустаяСтрока(ЗначениеОбъекта) Тогда
					ЗначениеОбъекта = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеАдресногоОбъекта(АдресПоПолям, ИмяПоля, ПостфиксТипаАдреса);
				КонецЕсли;
			КонецЕсли;
			ПоляПредставления.Добавить(ЗначениеОбъекта);
			
		КонецЕсли;
	КонецЦикла;
	
	Возврат СтрСоединить(ПоляПредставления, ", ");
	
КонецФункции

// Порядок уровней по умолчанию.
// 
// Параметры:
//  ПараметрыПредставленияАдреса - см. НовыеПараметрыПредставленияАдреса
// 
// Возвращаемое значение:
//  Массив - порядок уровней по умолчанию
//
Функция ОпределитьПорядокУровнейДляПредставления(ПараметрыПредставленияАдреса, ТипАдреса)
	
	УровниАдреса = Новый Массив;
		
	Если ПараметрыПредставленияАдреса.СписокПолей.Количество() > 0 Тогда
		УровниАдреса = Новый Массив(Новый ФиксированныйМассив(ПараметрыПредставленияАдреса.СписокПолей));
	ИначеЕсли ПараметрыПредставленияАдреса.ПочтовыйАдрес Тогда
		УровниАдреса.Добавить("Улица");
		УровниАдреса.Добавить("Дом");
		УровниАдреса.Добавить("Помещения");
		УровниАдреса.Добавить("НаселенныйПункт");
		УровниАдреса.Добавить("Город");
		УровниАдреса.Добавить("Район");
		
		Если РаботаСАдресамиКлиентСервер.ЭтоМуниципальныйАдрес(ТипАдреса) Тогда
			УровниАдреса.Добавить("Поселение");
			УровниАдреса.Добавить("МуниципальныйРайон");
		Иначе
			УровниАдреса.Добавить("Район");
		КонецЕсли;
		
		УровниАдреса.Добавить("Регион");
		УровниАдреса.Добавить("Страна");
		УровниАдреса.Добавить("Индекс");
	Иначе
		УровниАдреса.Добавить("Страна");
		УровниАдреса.Добавить("Индекс");
		УровниАдреса.Добавить("Регион");
		
		Если РаботаСАдресамиКлиентСервер.ЭтоМуниципальныйАдрес(ТипАдреса) Тогда
			УровниАдреса.Добавить("МуниципальныйРайон");
			УровниАдреса.Добавить("Поселение");
		Иначе
			УровниАдреса.Добавить("Район");
		КонецЕсли;
		
		УровниАдреса.Добавить("Город");
		УровниАдреса.Добавить("НаселенныйПункт");
		УровниАдреса.Добавить("Улица");
		УровниАдреса.Добавить("Дом");
		УровниАдреса.Добавить("Помещения");
	КонецЕсли;
	
	Если Не ПараметрыПредставленияАдреса.ВключатьСтрану Тогда
		
		Позиция = УровниАдреса.Найти("Страна");
		Если Позиция <> Неопределено Тогда 
			УровниАдреса.Удалить(УровниАдреса.Найти("Страна"));
		КонецЕсли;
		
	КонецЕсли;
	
	Если Не ПараметрыПредставленияАдреса.ВключатьПочтовыйИндекс Тогда
		
		Позиция = УровниАдреса.Найти("Индекс");
		Если Позиция <> Неопределено Тогда 
			УровниАдреса.Удалить(УровниАдреса.Найти("Индекс"));
		КонецЕсли;
		
	КонецЕсли;
	
	Если ПараметрыПредставленияАдреса.ТолькоНаселенныйПункт Тогда
		
		Позиция = УровниАдреса.Найти("Улица");
		Если Позиция <> Неопределено Тогда 
			УровниАдреса.Удалить(УровниАдреса.Найти("Улица"));
		КонецЕсли;
		
		Позиция = УровниАдреса.Найти("Дом");
		Если Позиция <> Неопределено Тогда 
			УровниАдреса.Удалить(УровниАдреса.Найти("Дом"));
		КонецЕсли;
		
		Позиция = УровниАдреса.Найти("Помещения");
		Если Позиция <> Неопределено Тогда 
			УровниАдреса.Удалить(УровниАдреса.Найти("Помещения"));
		КонецЕсли;
		
	КонецЕсли;
	
	
	Возврат УровниАдреса;
	
КонецФункции

Функция ПорядокУровнейПоУмолчанию(ТолькоНаселенныйПункт = Ложь)
	
	УровниАдреса = Новый Массив;
	УровниАдреса.Добавить("Регион");
	УровниАдреса.Добавить("Район");
	УровниАдреса.Добавить("МуниципальныйРайон");
	УровниАдреса.Добавить("Город");
	УровниАдреса.Добавить("Поселение");
	УровниАдреса.Добавить("НаселенныйПункт");
	УровниАдреса.Добавить("Территория");
	Если Не ТолькоНаселенныйПункт Тогда
		УровниАдреса.Добавить("Улица");
	КонецЕсли;

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

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

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

// Возвращает код дополнительной части адреса для почтового индекса.
//
// Возвращаемое значение:
//      Строка - код
//
Функция КодСериализацииПочтовогоИндекса() Экспорт
	
	Возврат КодСериализацииОбъектаАдресации(НСтр("ru = 'Почтовый индекс'"));
	
КонецФункции

// Возвращает XPath для почтового индекса.
//
// Возвращаемое значение:
//      Строка - XPath
//
Функция XPathПочтовогоИндекса() Экспорт
	
	Возврат "ДопАдрЭл[ТипАдрЭл='" + КодСериализацииПочтовогоИндекса() + "']";
	
КонецФункции

// Возвращает XPath для номера дополнительного объекта адресации.
//
//  Параметры:
//      СтрокаЗначения - Строка - искомый тип, например "Дом", "Корпус".
//
// Возвращаемое значение:
//      Строка - XPath
//
Функция XPathНомераДополнительногоОбъектаАдресации(СтрокаЗначения) Экспорт
	
	Код = КодСериализацииОбъектаАдресации(СтрокаЗначения);
	Если Код = Неопределено Тогда
		Код = СтрЗаменить(СтрокаЗначения, "'", "");
	КонецЕсли;
	
	Возврат "ДопАдрЭл/Номер[Тип='" + Код + "']";
КонецФункции

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


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

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

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

// Внутреннее для сериализации.
Функция КонвертироватьАдресИзJSONВXML(Знач ЗначенияПолей, Знач Представление, Знач ОжидаемыйТип = Неопределено) Экспорт
	
	// Старый формат через разделитель строк и равенство.
	ПространствоИмен = УправлениеКонтактнойИнформациейЛокализация.ПространствоИмен();
	
	Результат = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип(ПространствоИмен, "КонтактнаяИнформация"));
	Результат.Состав      = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип(ПространствоИмен, "Адрес"));
	
	ОсновнаяСтрана = РаботаСАдресамиКлиентСервер.ОсновнаяСтрана();
	НазваниеОсновнойСтраны  = ВРег(ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ОсновнаяСтрана, "Наименование"));
	
	// Национальный
	НациональныйАдрес = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип(ПространствоИмен(), "АдресРФ"));
	
	// Общий состав
	Адрес = Результат.Состав;
	Адрес.Страна = НазваниеОсновнойСтраны; // Страна по умолчанию
	АдресНациональный = Истина;
	
	ПолеПредставления      = "";
	
	Для Каждого ЭлементСписка Из ЗначенияПолей Цикл
		
		Если ПустаяСтрока(ЭлементСписка.Значение) Тогда
			Продолжить;
		КонецЕсли;
		
		ИмяПоля = ВРег(ЭлементСписка.Ключ);
		
		Если СтрСравнить(ИмяПоля, "ZIPCODE") = 0 Тогда
			ЭлементИндекс = СоздатьДопАдрЭлемента(НациональныйАдрес);
			ЭлементИндекс.ТипАдрЭл = КодСериализацииПочтовогоИндекса();
			ЭлементИндекс.Значение = ЭлементСписка.Значение;
			
		ИначеЕсли СтрСравнить(ИмяПоля, "COMMENT") =0 Тогда
			Результат.Комментарий = ЭлементСписка.Значение;
			
		ИначеЕсли ИмяПоля = "COUNTRY" Тогда
			Адрес.Страна = Строка(ЭлементСписка.Значение);
			Если ВРег(ЭлементСписка.Значение) <> НазваниеОсновнойСтраны Тогда
				АдресНациональный = Ложь;
			КонецЕсли;
			
		ИначеЕсли ИмяПоля = "COUNTRYCODE" Тогда
			// действия не требуется
			
		ИначеЕсли ИмяПоля = "AREACODE" Тогда
			Если ПустаяСтрока(НациональныйАдрес.СубъектРФ) Тогда
				НациональныйАдрес.СубъектРФ = РегионКода(ЭлементСписка.Значение);
			КонецЕсли;
			
		ИначеЕсли ИмяПоля = "AREA" Тогда
			НациональныйАдрес.СубъектРФ = ЭлементСписка.Значение + " " + ЗначенияПолей.areaType;
			
		ИначеЕсли ИмяПоля = "DISTRICT" Тогда
			Если НациональныйАдрес.СвРайМО = Неопределено Тогда
				НациональныйАдрес.СвРайМО = ФабрикаXDTO.Создать(НациональныйАдрес.Тип().Свойства.Получить("СвРайМО").Тип)
			КонецЕсли;
			НациональныйАдрес.СвРайМО.Район = СокрЛП(ЭлементСписка.Значение + " " + ЗначенияПолей.DistrictType);
			
		ИначеЕсли ИмяПоля = "CITY" Тогда
			Если ЗначениеЗаполнено(ЭлементСписка.Значение) Тогда
				НациональныйАдрес.Город = СокрЛП(ЭлементСписка.Значение + " " + ЗначенияПолей.CityType);
			КонецЕсли;
			
		ИначеЕсли ИмяПоля = "TERRITORY" Тогда
			
			ПутьXPath = XPathДополнительногоОбъектаАдресации(90, ЗначенияПолей.TerritoryType);
			Обработки.РасширенныйВводКонтактнойИнформации.УстановитьXDTOРеквизитОбъекта(НациональныйАдрес, ПутьXPath, 
			ЭлементСписка.Значение + " " + ЗначенияПолей.TerritoryType);
			
		ИначеЕсли ИмяПоля = "LOCALITY" Тогда
			НациональныйАдрес.НаселПункт = СокрЛП(ЭлементСписка.Значение + " " + ЗначенияПолей.LocalityType);
			
		ИначеЕсли ИмяПоля = "CITYDISTRICT" Тогда
			НациональныйАдрес.ВнутригРайон = СокрЛП(ЭлементСписка.Значение + " " + ЗначенияПолей.CityDistrictType);
			
		ИначеЕсли ИмяПоля = "STREET" Тогда
			НациональныйАдрес.Улица = СокрЛП(ЭлементСписка.Значение  + " " + ЗначенияПолей.StreetType);
			
		ИначеЕсли ИмяПоля = "HOUSETYPE" Тогда
			
			ЭлементДом = СоздатьНомерДопАдрЭлемента(НациональныйАдрес);
			ЭлементДом.Тип = КодСериализацииОбъектаАдресации(ЭлементСписка.Значение);
			Если ЭлементДом.Тип = Неопределено Тогда
				ЭлементДом.Тип = КодСериализацииОбъектаАдресации("Дом");
			КонецЕсли;
			ЭлементДом.Значение = ЗначенияПолей.HouseNumber;
			
		ИначеЕсли ИмяПоля = "BUILDINGS" Тогда
			
			Для каждого СписокСтроение Из ЭлементСписка.Значение Цикл
				
				// тип корпуса
				ЭлементКорпус          = СоздатьНомерДопАдрЭлемента(НациональныйАдрес);
				ЭлементКорпус.Тип      = КодСериализацииОбъектаАдресации(СписокСтроение.Type);
				Если ЭлементКорпус.Тип = Неопределено Тогда
					ЭлементКорпус.Тип  = КодСериализацииОбъектаАдресации("Корпус");
				КонецЕсли;
				ЭлементКорпус.Значение = СписокСтроение.Number;
				
			КонецЦикла;
			
		ИначеЕсли ИмяПоля = "APARTMENTS" Тогда
			
			Для каждого СписокСтроение Из ЭлементСписка.Значение Цикл
				
				// тип квартиры
				ЭлементКвартира          = СоздатьНомерДопАдрЭлемента(НациональныйАдрес);
				ЭлементКвартира.Тип      = КодСериализацииОбъектаАдресации(СписокСтроение.Type);
				Если ЭлементКвартира.Тип = Неопределено Тогда
					ЭлементКвартира.Тип  = КодСериализацииОбъектаАдресации("Квартира");
				КонецЕсли;
				ЭлементКвартира.Значение = СписокСтроение.Number;
				
			КонецЦикла;
			
		ИначеЕсли ИмяПоля = "OKTMO" И ЗначениеЗаполнено(ЭлементСписка.Значение) Тогда
			ТипЧисло = Новый ОписаниеТипов("Число");
			НациональныйАдрес.ОКТМО = ТипЧисло.ПривестиЗначение(ЭлементСписка.Значение);
			
		ИначеЕсли ИмяПоля = "ОКАТО" И ЗначениеЗаполнено(ЭлементСписка.Значение) Тогда
			НациональныйАдрес.ОКАТО = ЭлементСписка.Значение;
			
		ИначеЕсли ИмяПоля = "VALUE" И ЗначениеЗаполнено(ЭлементСписка.Значение) Тогда
			ПолеПредставления = СокрЛП(ЭлементСписка.Значение);
			
		КонецЕсли;
		
	КонецЦикла;
	
	// Представление с приоритетами.
	Если Не ПустаяСтрока(Представление) Тогда
		Результат.Представление = Представление;
	Иначе
		Результат.Представление = ПолеПредставления;
	КонецЕсли;
	
	Адрес.Состав = ?(АдресНациональный, НациональныйАдрес, Результат.Представление);
	
	Возврат Результат;
КонецФункции

// Преобразует формат из XML в JSON
//
Функция КонтактнаяИнформацияВСтруктуруJSON(КонтактнаяИнформация, Знач Тип = Неопределено, НастройкиКонвертации = Неопределено) Экспорт
	
	Если НастройкиКонвертации = Неопределено Тогда
		НастройкиКонвертации = УправлениеКонтактнойИнформацией.НастройкиКонвертацииКонтактнойИнформации();
	КонецЕсли;
	
	Если Тип <> Неопределено И ТипЗнч(Тип) <> Тип("ПеречислениеСсылка.ТипыКонтактнойИнформации") Тогда
		Тип = УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ТипВидаКонтактнойИнформации(Тип);
	КонецЕсли;
	
	Если Тип = Неопределено Тогда
		
		Если ТипЗнч(КонтактнаяИнформация) = Тип("Строка") Тогда
			Тип = УправлениеКонтактнойИнформацией.ТипКонтактнойИнформации(КонтактнаяИнформация);
		ИначеЕсли ТипЗнч(КонтактнаяИнформация) = Тип("ОбъектXDTO") Тогда
			ПространствоИмен = УправлениеКонтактнойИнформациейЛокализация.ПространствоИмен();
			
			НайденТип = ?(КонтактнаяИнформация.Состав = Неопределено, Неопределено, КонтактнаяИнформация.Состав.Тип());
			Тип = УправлениеКонтактнойИнформациейЛокализация.СоответствиеXDTOТиповКонтактнойИнформации(НайденТип);
			
		КонецЕсли;
		
	КонецЕсли;
	
	Если УправлениеКонтактнойИнформациейСлужебныйПовтИсп.ДоступныМодулиРаботаСАдресами() Тогда
		МодульРаботаСАдресамиКлиентСервер = ОбщегоНазначения.ОбщийМодуль("РаботаСАдресамиКлиентСервер");
		Результат = МодульРаботаСАдресамиКлиентСервер.ОписаниеНовойКонтактнойИнформации(Тип);
		ОсновнаяСтрана = МодульРаботаСАдресамиКлиентСервер.ОсновнаяСтрана();
	Иначе
		Результат = УправлениеКонтактнойИнформациейКлиентСервер.ОписаниеНовойКонтактнойИнформации(Тип);
		ОсновнаяСтрана = "";
	КонецЕсли;
	
	НаименованиеСтраны = "";
	Формат9Запятых = Ложь;
	
	Если ТипЗнч(КонтактнаяИнформация) = Тип("Строка") Тогда
		
		Если УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВXML(КонтактнаяИнформация) Тогда
			// XML
			РезультатПреобразования = Новый Структура;
			
			XDTOКонтактнаяИнформация = УправлениеКонтактнойИнформациейЛокализация.КонтактнаяИнформацияИзXML(КонтактнаяИнформация, Тип, РезультатПреобразования,
				 НастройкиКонвертации);
			Результат.Value   = XDTOКонтактнаяИнформация.Представление;
			Результат.Comment = XDTOКонтактнаяИнформация.Комментарий;
		Иначе
			Если СтрЧислоВхождений(КонтактнаяИнформация, ",") = 9 И СтрНайти(КонтактнаяИнформация, "=") = 0 Тогда
				Формат9Запятых = Истина;
				АдресРФ        = КонтактнаяИнформация;
			Иначе
				// ключ-значение формат
				Результат = ПреобразоватьКлючЗначениеВСтруктуру(КонтактнаяИнформация, НастройкиКонвертации.Представление);
				Возврат Результат;
			КонецЕсли;
		КонецЕсли;
		
	ИначеЕсли ТипЗнч(КонтактнаяИнформация) = Тип("Структура") Тогда
		
		Возврат СтруктураАдресаВСтруктуруJSON(КонтактнаяИнформация);
		
	ИначеЕсли ТипЗнч(КонтактнаяИнформация) = Тип("ОбъектXDTO") Тогда
		
		XDTOКонтактнаяИнформация = КонтактнаяИнформация;
		Результат.Value          = XDTOКонтактнаяИнформация.Представление;
		Результат.Comment        = XDTOКонтактнаяИнформация.Комментарий;
		
	КонецЕсли;
	
	Если Тип <> Перечисления.ТипыКонтактнойИнформации.Адрес И Тип <> Перечисления.ТипыКонтактнойИнформации.Телефон Тогда
		Возврат Результат;
	КонецЕсли;

	Если НЕ Формат9Запятых Тогда
		
		ПространствоИмен = УправлениеКонтактнойИнформациейЛокализация.ПространствоИмен();
		Состав = XDTOКонтактнаяИнформация.Состав;
		
		Если Состав = Неопределено Тогда
			Возврат Результат;
		КонецЕсли;
		
		XDTOТип = Состав.Тип();
		
		Если XDTOТип = ФабрикаXDTO.Тип(ПространствоИмен, "Адрес") Тогда
			
			Результат.Вставить("Country", Состав.Страна);
			Страна = ?(ПустаяСтрока(Состав.Страна),
					ОсновнаяСтрана,
					Справочники.СтраныМира.НайтиПоНаименованию(Состав.Страна, Истина));
			НаименованиеСтраны = Страна.Наименование;
			Результат.Вставить("CountryCode", СокрЛП(Страна.Код));
			
			АдресРФ = Состав.Состав;
			
		ИначеЕсли 
			XDTOТип = ФабрикаXDTO.Тип(УправлениеКонтактнойИнформациейЛокализация.ПространствоИмен(), "НомерТелефона")
			Или XDTOТип = ФабрикаXDTO.Тип(УправлениеКонтактнойИнформациейЛокализация.ПространствоИмен(), "НомерФакса") Тогда
			
			Результат.CountryCode = Состав.КодСтраны;
			Результат.areaCode    = Состав.КодГорода;
			Результат.Number      = Состав.Номер;
			Результат.ExtNumber   = Состав.Добавочный;
			
			Возврат Результат;
			
		ИначеЕсли XDTOТип = ФабрикаXDTO.Тип(ПространствоИмен(), "АдресРФ") Тогда
			АдресРФ = Состав;
		Иначе
			Возврат Результат;
		КонецЕсли;
		
		Если АдресРФ = Неопределено Тогда
			Возврат Результат;
		ИначеЕсли ТипЗнч(АдресРФ) = Тип("Строка") Тогда
			
			Если СтрЧислоВхождений(АдресРФ, ",") = 9 Тогда
				
				Если УправлениеКонтактнойИнформацией.ЭтоСтранаУчастникЕАЭС(Результат.Country) Тогда
					Результат.AddressType = УправлениеКонтактнойИнформациейКлиентСервер.АдресЕАЭС();
				Иначе
					Результат.AddressType = УправлениеКонтактнойИнформациейКлиентСервер.ИностранныйАдрес();
				КонецЕсли;
				
				ЧастиАдреса = СтрРазделить(АдресРФ, ",");
				Результат.ZIPCode = ЧастиАдреса[1];
				
				НаименованиеСокращение = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(ЧастиАдреса[2]);
				Результат.area     = НаименованиеСокращение.Наименование;
				Результат.areaType = НаименованиеСокращение.Сокращение;
				
				НаименованиеСокращение = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(ЧастиАдреса[3]);
				Результат.District     = НаименованиеСокращение.Наименование;
				Результат.DistrictType = НаименованиеСокращение.Сокращение;
				
				НаименованиеСокращение = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(ЧастиАдреса[4]);
				Результат.City         = НаименованиеСокращение.Наименование;
				Результат.CityType     = НаименованиеСокращение.Сокращение;
				
				НаименованиеСокращение = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(ЧастиАдреса[5]);
				Результат.Locality     = НаименованиеСокращение.Наименование;
				Результат.LocalityType = НаименованиеСокращение.Сокращение;
				
				НаименованиеСокращение = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(ЧастиАдреса[6]);
				Результат.Street       = НаименованиеСокращение.Наименование;
				Результат.StreetType   = НаименованиеСокращение.Сокращение;
				
				НаименованиеСокращение = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(ЧастиАдреса[7]);
				Результат.HouseNumber  = НаименованиеСокращение.Сокращение;
				Результат.HouseType    = НаименованиеСокращение.Наименование;
				
				Если ЗначениеЗаполнено(ЧастиАдреса[8]) Тогда
					НаименованиеСокращение = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(ЧастиАдреса[8]);
					Результат.Buildings.Добавить(УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения(
						НаименованиеСокращение.Наименование, НаименованиеСокращение.Сокращение));
				КонецЕсли;
				
				Если ЗначениеЗаполнено(ЧастиАдреса[9]) Тогда
					НаименованиеСокращение = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(ЧастиАдреса[9]);
					Результат.Apartments.Добавить(УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения(
						НаименованиеСокращение.Наименование, НаименованиеСокращение.Сокращение));
				КонецЕсли;
			КонецЕсли;
		Иначе
			
			Если ЗначениеЗаполнено(АдресРФ.Адрес_по_документу) Или (ПустаяСтрока(АдресРФ.СубъектРФ) И ЗначениеЗаполнено(Результат.Value)) Тогда
				Результат.AddressType = УправлениеКонтактнойИнформациейКлиентСервер.АдресВСвободнойФорме();
			Иначе
				Результат.AddressType = РаботаСАдресамиКлиентСервер.АдминистративноТерриториальныйАдрес();
			КонецЕсли;
			
			Результат.Country = НаименованиеСтраны;
			Результат.ZIPCode = Обработки.РасширенныйВводКонтактнойИнформации.ПочтовыйИндексАдреса(АдресРФ);
			Результат.OKTMO = Формат(АдресРФ.ОКТМО, "ЧГ=0");
			Результат.OKATO = Формат(АдресРФ.ОКАТО, "ЧГ=0");
			
			СубъектРФ = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(АдресРФ.СубъектРФ);
			Результат.area     = Строка(СубъектРФ.Наименование);
			Результат.areaType = Строка(СубъектРФ.Сокращение);
			
			РайонАдреса = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(РайонАдреса(АдресРФ));
			Результат.District     = Строка(РайонАдреса.Наименование);
			Результат.DistrictType = Строка(РайонАдреса.Сокращение);
			
			Город = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(АдресРФ.Город);
			Результат.City     = Строка(Город.Наименование);
			Результат.CityType = Строка(Город.Сокращение);
			
			НаселПункт = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(АдресРФ.НаселПункт);
			Результат.Locality     = Строка(НаселПункт.Наименование);
			Результат.LocalityType = Строка(НаселПункт.Сокращение);
			
			Улица = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(АдресРФ.Улица);
			Результат.Street     = Строка(Улица.Наименование);
			Результат.StreetType = Строка(Улица.Сокращение);
			
			ВнутригРайон = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(АдресРФ.ВнутригРайон);
			Результат.CityDistrict     = Строка(ВнутригРайон.Наименование);
			Результат.CityDistrictType = Строка(ВнутригРайон.Сокращение);
			
			ЗначениеДополнительныхЭлементов = Обработки.РасширенныйВводКонтактнойИнформации.ЗначениеДополнительныхЭлементов(АдресРФ);
			Если ЗначениеЗаполнено(ЗначениеДополнительныхЭлементов.ДополнительныйЭлемент) Тогда
				ДополнительныйЭлемент = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(ЗначениеДополнительныхЭлементов.ДополнительныйЭлемент);
				Результат.Territory     = Строка(ДополнительныйЭлемент.Наименование);
				Результат.TerritoryType = Строка(ДополнительныйЭлемент.Сокращение);
			КонецЕсли;
			Если ЗначениеЗаполнено(ЗначениеДополнительныхЭлементов.ПодчиненныйЭлемент) Тогда
				ПодчиненныйЭлемент = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(ЗначениеДополнительныхЭлементов.ПодчиненныйЭлемент);
				Результат.Street     = Строка(ПодчиненныйЭлемент.Наименование);
				Результат.StreetType = Строка(ПодчиненныйЭлемент.Сокращение);
			КонецЕсли;
			
			ЗданияИПомещения = Обработки.РасширенныйВводКонтактнойИнформации.ЗданияИПомещенияАдреса(АдресРФ);
			Для каждого Здание Из ЗданияИПомещения.Здания Цикл
				Если Здание.Вид = 1 И ПустаяСтрока(Результат.HouseNumber) Тогда
					Результат.HouseType = Здание.Тип;
					Результат.HouseNumber = Здание.Значение;
				Иначе
					Результат.Buildings.Добавить(УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения(Здание.Тип, Здание.Значение));
				КонецЕсли;
			КонецЦикла;
			
			Для каждого Помещение Из ЗданияИПомещения.Помещения Цикл
				Результат.Apartments.Добавить(УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения(Помещение.Тип, Помещение.Значение));
			КонецЦикла;
			
		КонецЕсли;
	КонецЕсли;
	
	Если НастройкиКонвертации.ОбновлятьИдентификаторы И ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.АдресныйКлассификатор") Тогда
		МодульАдресныйКлассификаторСлужебный = ОбщегоНазначения.ОбщийМодуль("АдресныйКлассификаторСлужебный");
		МодульАдресныйКлассификаторСлужебный.УстановитьИдентификаторыАдреса(Результат);
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

Функция ПреобразоватьКлючЗначениеВСтруктуру(Знач ЗначенияПолей, Знач Представление)
	

	// Старый формат через разделитель строк и равенство.
	
	Результат = РаботаСАдресамиКлиентСервер.ОписаниеНовойКонтактнойИнформации(Перечисления.ТипыКонтактнойИнформации.Адрес);
	Результат.Comment = "";
	
	НазваниеОсновнойСтраны  = ВРег(ОбщегоНазначения.ЗначениеРеквизитаОбъекта(РаботаСАдресамиКлиентСервер.ОсновнаяСтрана(), 
		"Наименование"));
	ЭлементКвартира = Неопределено;
	ЭлементКорпус   = Неопределено;
	ЭлементДом      = Неопределено;
	
	Результат.Country = НазваниеОсновнойСтраны; // Страна по умолчанию
	АдресРоссийский = Истина;
	
	ТипЗначенийПолей = ТипЗнч(ЗначенияПолей);
	Если ТипЗначенийПолей = Тип("СписокЗначений") Тогда
		СписокПолей = ЗначенияПолей;
	ИначеЕсли ТипЗначенийПолей = Тип("Структура") Тогда
		СписокПолей = УправлениеКонтактнойИнформациейСлужебный.ПреобразоватьСтрокуВСписокПолей(
			СтрокаПолей(ЗначенияПолей, Ложь));
	Иначе
		// Уже преобразовано в строку
		СписокПолей = УправлениеКонтактнойИнформациейСлужебный.ПреобразоватьСтрокуВСписокПолей(ЗначенияПолей);
	КонецЕсли;
	
	ТипКвартирыНеопределен = Истина;
	ТипКорпусаНеопределен  = Истина;
	ТипДомаНеопределен     = Истина;
	ПолеПредставления      = "";
	
	Для Каждого ЭлементСписка Из СписокПолей Цикл
		ИмяПоля = ВРег(ЭлементСписка.Представление);
		
		Если ИмяПоля = "ИНДЕКС" Тогда
			Результат.ZIPcode = ЭлементСписка.Значение;
			
		ИначеЕсли ИмяПоля = "СТРАНА" Тогда
			Результат.Country = ЭлементСписка.Значение;
			Если ВРег(ЭлементСписка.Значение) <> НазваниеОсновнойСтраны Тогда
				АдресРоссийский = Ложь;
			КонецЕсли;
			
		ИначеЕсли ИмяПоля = "КОДСТРАНЫ" Тогда
			
			Результат.countryCode =  ЭлементСписка.Значение;
			
		ИначеЕсли ИмяПоля = "КОДРЕГИОНА" Тогда
			
			Результат.areaCode = ЭлементСписка.Значение;
			Если ПустаяСтрока(Результат.area) Тогда
				НаименованиеИТип = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(
					РегионКода(ЭлементСписка.Значение));
				Результат.area = НаименованиеИТип.Наименование;
				Результат.areaType = СокрЛП(НаименованиеИТип.Сокращение);
			КонецЕсли;
			
		ИначеЕсли ИмяПоля = "РЕГИОН" Тогда
			
			НаименованиеИТип = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(ЭлементСписка.Значение);
			Результат.area = НаименованиеИТип.Наименование;
			Результат.areaType = НаименованиеИТип.Сокращение;
			
			Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.АдресныйКлассификатор") Тогда
				МодульАдресныйКлассификатор = ОбщегоНазначения.ОбщийМодуль("АдресныйКлассификатор");
				Результат.areaCode = МодульАдресныйКлассификатор.КодРегионаПоНаименованию(ЭлементСписка.Значение);
				Результат.areaValue = МодульАдресныйКлассификатор.НаименованиеРегионаПоКоду(Результат.areaCode);
			КонецЕсли;
			
		ИначеЕсли ИмяПоля = "РАЙОН" Тогда
			
			НаименованиеИТип = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(ЭлементСписка.Значение);
			Результат.district = НаименованиеИТип.Наименование;
			Результат.districtType = НаименованиеИТип.Сокращение;
			
		ИначеЕсли ИмяПоля = "ГОРОД" Тогда
			
			НаименованиеИТип = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(ЭлементСписка.Значение);
			Результат.city = НаименованиеИТип.Наименование;
			Результат.cityType = НаименованиеИТип.Сокращение;
			
		ИначеЕсли ИмяПоля = "НАСЕЛЕННЫЙПУНКТ" Тогда
			
			НаименованиеИТип = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(ЭлементСписка.Значение);
			Результат.locality = НаименованиеИТип.Наименование;
			Результат.localityType = НаименованиеИТип.Сокращение;
			
		ИначеЕсли ИмяПоля = "УЛИЦА" Тогда
			
			НаименованиеИТип = УправлениеКонтактнойИнформациейКлиентСервер.НаименованиеСокращение(ЭлементСписка.Значение);
			Результат.street = НаименованиеИТип.Наименование;
			Результат.streetType = НаименованиеИТип.Сокращение;
			
		ИначеЕсли ИмяПоля = "ТИПДОМА" Тогда
			
			Результат.houseType = ТРег(СокрЛП(ЭлементСписка.Значение));
			
		ИначеЕсли ИмяПоля = "ДОМ" Тогда
			Результат.houseNumber = ЭлементСписка.Значение;
			
		ИначеЕсли ИмяПоля = "ТИПКОРПУСА" Тогда
			Если ЭлементКорпус = Неопределено Тогда
				ЭлементКорпус = УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения("", "");
				Результат.buildings.Добавить(ЭлементКорпус);
			КонецЕсли;
			ЭлементКорпус.type = ТРег(СокрЛП(ЭлементСписка.Значение));
			ТипКорпусаНеопределен = Ложь;
			
		ИначеЕсли ИмяПоля = "КОРПУС" Тогда
			Если ЭлементКорпус = Неопределено Тогда
				ЭлементКорпус = УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения("", "");
				Результат.buildings.Добавить(ЭлементКорпус);
			КонецЕсли;
			ЭлементКорпус.number = ЭлементСписка.Значение;
			
		ИначеЕсли ИмяПоля = "ТИПКВАРТИРЫ" Тогда
			Если ЭлементКвартира = Неопределено Тогда
				ЭлементКвартира = УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения("", "");
				Результат.apartments.Добавить(ЭлементКвартира);
			КонецЕсли;
			ЭлементКвартира.type = ТРег(СокрЛП(ЭлементСписка.Значение));
			ТипКвартирыНеопределен = Ложь;
			
		ИначеЕсли ИмяПоля = "КВАРТИРА" Тогда
			Если ЭлементКвартира = Неопределено Тогда
				ЭлементКвартира = УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения("", "");
				Результат.apartments.Добавить(ЭлементКвартира);
			КонецЕсли;
			ЭлементКвартира.number = ЭлементСписка.Значение;
			
		ИначеЕсли ИмяПоля = "ПРЕДСТАВЛЕНИЕ" Тогда
			ПолеПредставления = СокрЛП(ЭлементСписка.Значение);
			Результат.value = ПолеПредставления;
			
		КонецЕсли;
		
	КонецЦикла;
	
	// Умолчания
	Если ТипДомаНеопределен И ЭлементДом <> Неопределено Тогда
		Результат.houseType = "Дом";
	КонецЕсли;
	
	Если ТипКорпусаНеопределен И ЭлементКорпус <> Неопределено Тогда
		ЭлементКорпус.type = "Корпус";
	КонецЕсли;
	
	Если ТипКвартирыНеопределен И ЭлементКвартира <> Неопределено Тогда
		ЭлементКвартира.type = "Квартира";
	КонецЕсли;
	
	ТипАдреса = ?(АдресРоссийский, РаботаСАдресамиКлиентСервер.АдминистративноТерриториальныйАдрес(),
		УправлениеКонтактнойИнформациейКлиентСервер.ИностранныйАдрес());
	Результат.addressType = ТипАдреса;
		
	// Представление с приоритетами.
	Если Не ПустаяСтрока(Представление) Тогда
		Результат.value = Представление;
	ИначеЕсли ЗначениеЗаполнено(ПолеПредставления) Тогда
		Результат.value = ПолеПредставления;
	Иначе
		Результат.value = РаботаСАдресамиКлиентСервер.ПредставлениеАдреса(Результат,
			Ложь, ТипАдреса);
	КонецЕсли;
	Возврат Результат;

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

Функция ПодготовитьАдресДляВвода(Данные) Экспорт
	
	Если Не УправлениеКонтактнойИнформациейКлиентСервер.ЭтоИностранныйАдресИлиЕАЭС(Данные.addressType)
	   И Не УправлениеКонтактнойИнформациейКлиентСервер.ЭтоАдресВСвободнойФорме(Данные.addressType) Тогда
		Если Данные.Свойство("id") И ПустаяСтрока(Данные.id) И ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.АдресныйКлассификатор") Тогда
			МодульАдресныйКлассификаторСлужебный = ОбщегоНазначения.ОбщийМодуль("АдресныйКлассификаторСлужебный");
			МодульАдресныйКлассификаторСлужебный.УстановитьИдентификаторыАдреса(Данные);
		КонецЕсли;
	КонецЕсли;
	
	НаселенныйПунктДетально = РаботаСАдресамиКлиентСервер.ОписаниеНовойКонтактнойИнформации(ПредопределенноеЗначение("Перечисление.ТипыКонтактнойИнформации.Адрес"));
	ЗаполнитьЗначенияСвойств(НаселенныйПунктДетально, Данные);
	
	Если ТипЗнч(НаселенныйПунктДетально.Buildings) <> Тип("Массив") Тогда
		НаселенныйПунктДетально.Buildings = Новый Массив;
	КонецЕсли;
	
	Если ТипЗнч(НаселенныйПунктДетально.Apartments) <> Тип("Массив") Тогда
		НаселенныйПунктДетально.Buildings = Новый Массив;
	КонецЕсли;
	
	Для каждого ЭлементАдреса Из НаселенныйПунктДетально Цикл
		
		Если СтрЗаканчиваетсяНа(ЭлементАдреса.Ключ, "Id")
			И ТипЗнч(ЭлементАдреса.Значение) = Тип("Строка")
			И СтрДлина(ЭлементАдреса.Значение) = 36 Тогда
				НаселенныйПунктДетально[ЭлементАдреса.Ключ] = Новый УникальныйИдентификатор(ЭлементАдреса.Значение);
		КонецЕсли;
		
	КонецЦикла;
	
	Если Данные.Свойство("house") Тогда
		НаселенныйПунктДетально.HouseNumber = Данные.house;
	КонецЕсли;
	
	Возврат НаселенныйПунктДетально;
	
КонецФункции

// Читает и устанавливает район адреса.
//
//  Параметры:
//      XDTOАдрес     - ОбъектXDTO - контактная информация или XDTO адреса.
//      НовоеЗначение - Строка - устанавливаемое значение.
//
//  Возвращаемое значение:
//      Строка - новое значение.
//
Функция РайонАдреса(XDTOАдрес, НовоеЗначение = Неопределено)
	
	Если НовоеЗначение = Неопределено Тогда
		
		XDTOТип = XDTOАдрес.Тип();
		Если XDTOТип = ФабрикаXDTO.Тип(ПространствоИмен(), "АдресРФ") Тогда
			АдресРФ = XDTOАдрес;
		Иначе
			АдресРФ = XDTOАдрес.Состав;
		КонецЕсли;
		
		Если ТипЗнч(АдресРФ) = Тип("ОбъектXDTO") Тогда
			Возврат ПолучитьXDTOРеквизитОбъекта(АдресРФ, XPathРайона());
		КонецЕсли;
		
		Возврат Неопределено;
	КонецЕсли;
	
	// Запись
	Запись = СвРайМО(XDTOАдрес);
	Запись.Район = НовоеЗначение;
	Возврат НовоеЗначение;
	
КонецФункции

// Получение глубокого свойства объекта.
// 
// Параметры:
//  ОбъектXTDO - ОбъектXDTO
//  XPath -Строка
// 
// Возвращаемое значение:
//  ОбъектXDTO
//
Функция ПолучитьXDTOРеквизитОбъекта(ОбъектXTDO, XPath)
	
	// Переносов строки в XPath не ожидаем.
	СтрокаСвойств = СтрЗаменить(СтрЗаменить(XPath, "/", Символы.ПС), Символы.ПС + Символы.ПС, "/");
	
	ЧислоСвойств = СтрЧислоСтрок(СтрокаСвойств);
	Если ЧислоСвойств = 1 Тогда
		Результат = ОбъектXTDO.Получить(СтрокаСвойств);
		Если ТипЗнч(Результат) = Тип("ОбъектXDTO") Тогда 
			Возврат Результат.Значение;
		КонецЕсли;
		Возврат Результат;
	КонецЕсли;
	
	Результат = ?(ЧислоСвойств = 0, Неопределено, ОбъектXTDO);
	Для Индекс = 1 По ЧислоСвойств Цикл
		Результат = Результат.Получить(СтрПолучитьСтроку(СтрокаСвойств, Индекс));
		Если Результат = Неопределено Тогда 
			Прервать;
		КонецЕсли;
	КонецЦикла;
	
	Возврат Результат;
КонецФункции

Функция СвРайМО(АдресРФ)
	Если АдресРФ.СвРайМО <> Неопределено Тогда
		Возврат АдресРФ.СвРайМО;
	КонецЕсли;
	
	АдресРФ.СвРайМО = ФабрикаXDTO.Создать( АдресРФ.Свойства().Получить("СвРайМО").Тип);
	Возврат АдресРФ.СвРайМО;
КонецФункции

// Возвращает XPath для дополнительного объекта адресации по умолчанию.
//
//  Параметры:
//      Уровень - Число - уровень объекта.
//
// Возвращаемое значение:
//      Строка - XPath
//
Функция XPathДополнительногоОбъектаАдресации(Уровень, ТипаАдресногоЭлемента = "") Экспорт
	КодСериализации = КодСериализацииДополнительногоОбъектаАдресации(Уровень, ТипаАдресногоЭлемента);
	Возврат "ДопАдрЭл[ТипАдрЭл='" + КодСериализации + "']";
КонецФункции

Функция КодСериализацииДополнительногоОбъектаАдресации(Уровень, ТипаАдресногоЭлемента = "")
	
	Если Уровень = 90 Тогда
		Если ВРег(ТипаАдресногоЭлемента) = "ГСК" Тогда
			Возврат "10600000";
		ИначеЕсли ВРег(ТипаАдресногоЭлемента) = "СНТ" Тогда
			Возврат "10300000";
		ИначеЕсли ВРег(ТипаАдресногоЭлемента) = "ТЕР" Тогда
			Возврат "10700000";
		Иначе
			Возврат "10200000";
		КонецЕсли;
	ИначеЕсли Уровень = 91 Тогда
		Возврат "10400000";
	КонецЕсли;
	
	// Все остальное - считаем ориентиром.
	Возврат "Местоположение";
КонецФункции

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

Функция СоздатьНомерДопАдрЭлемента(АдресРФ)
	ДопАдрЭл = СоздатьДопАдрЭлемента(АдресРФ);
	ДопАдрЭл.Номер = ФабрикаXDTO.Создать(ДопАдрЭл.Тип().Свойства.Получить("Номер").Тип);
	Возврат ДопАдрЭл.Номер;
КонецФункции

Функция СоздатьДопАдрЭлемента(АдресРФ)
	СвойствоДопАдрЭлемента = АдресРФ.ДопАдрЭл.ВладеющееСвойство;
	ДопАдрЭлемента = ФабрикаXDTO.Создать(СвойствоДопАдрЭлемента.Тип);
	АдресРФ.ДопАдрЭл.Добавить(ДопАдрЭлемента);
	Возврат ДопАдрЭлемента;
КонецФункции

// Возвращает наименование региона по его коду.
//
//  Параметры:
//      Код - Строка
//          - Число - код региона.
//
// Возвращаемое значение:
//      Строка - полное наименование региона с сокращением.
//      Неопределено - если нет ни одной подсистемы адресного классификатора.
// 
Функция РегионКода(Знач Код)
	
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.АдресныйКлассификатор") Тогда
		МодульАдресныйКлассификатор = ОбщегоНазначения.ОбщийМодуль("АдресныйКлассификатор");
		Возврат МодульАдресныйКлассификатор.НаименованиеРегионаПоКоду(Код);
	КонецЕсли;
	
	Возврат Неопределено;
	
КонецФункции

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

// Возвращает сведения об адресах в виде структуру частей адреса и кодов КЛАДР.
//
Функция СведенияОбАдресахВВидеСтруктуры(Адреса, ДополнительныеПараметры)
	
	ОбщегоНазначенияКлиентСервер.ПроверитьПараметр("СведенияОбАдресах", "Адреса", Адреса, Тип("Массив"));
	
	Если Адреса.Количество() = 0 Тогда
		Возврат Новый Массив;
	КонецЕсли;
	
	ТаблицаАдресов = Новый ТаблицаЗначений;
	ТаблицаАдресов.Колонки.Добавить("ИндексАдреса", ОбщегоНазначения.ОписаниеТипаЧисло(10));
	ТаблицаАдресов.Колонки.Добавить("АдресJSON", Новый ОписаниеТипов("Структура"));
	ТаблицаАдресов.Колонки.Добавить("Адрес", Новый ОписаниеТипов("Структура"));
	ТаблицаАдресов.Индексы.Добавить("ИндексАдреса");
	
	ПодготовленныеПоляАдреса = РаботаСАдресамиКлиентСервер.ПоляАдреса();
	Параметры = ИнициализироватьПараметрыСведенийОбАдресе(ДополнительныеПараметры);
	СформироватьПоляСведенийОбАдресе(ПодготовленныеПоляАдреса, Параметры);
	
	АдресаБезИдентификаторов = Новый Соответствие;
	
	Для ИндексАдреса = 0 По Адреса.ВГраница() Цикл
		АдресСтрокой = Адреса.Получить(ИндексАдреса);
		
		Если НЕ (ТипЗнч(АдресСтрокой) = Тип("Структура") И АдресСтрокой.Свойство("Value")) Тогда
			
			Если НЕ УправлениеКонтактнойИнформациейКлиентСервер.ЭтоКонтактнаяИнформацияВJSON(АдресСтрокой) Тогда
				АдресСтрокой = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияВJSON(АдресСтрокой, Перечисления.ТипыКонтактнойИнформации.Адрес);
			КонецЕсли;
			
		КонецЕсли;
		
		АдресИзJSON = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(АдресСтрокой, Перечисления.ТипыКонтактнойИнформации.Адрес);
		
		СтрокаАдреса = ТаблицаАдресов.Добавить();
		СтрокаАдреса.ИндексАдреса = ИндексАдреса;
		СтрокаАдреса.АдресJSON    = АдресИзJSON; 
		
		Если ПустаяСтрока(АдресИзJSON.ID) И Параметры.ВозвращатьКоды Тогда
			АдресаБезИдентификаторов.Вставить(ИндексАдреса, АдресИзJSON);
		КонецЕсли;
		
	КонецЦикла;

	Если АдресаБезИдентификаторов.Количество() > 0 Тогда
		Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.АдресныйКлассификатор") Тогда
			МодульАдресныйКлассификаторСлужебный = ОбщегоНазначения.ОбщийМодуль("АдресныйКлассификаторСлужебный");
			МодульАдресныйКлассификаторСлужебный.УстановитьИдентификаторыАдресов(АдресаБезИдентификаторов);
		КонецЕсли;
	КонецЕсли;
	
	СоответствиеУровней = СоответствиеУровней();
	СоответствиеСокращений   = Новый Соответствие;
	
	Если Параметры.ВозвращатьКоды Тогда
		Идентификаторы = Новый Структура();
		ПодготовленныеПоляАдреса.Идентификаторы = Идентификаторы;
	КонецЕсли;
	
	Для каждого СтрокаАдреса Из ТаблицаАдресов Цикл
		
		АдресИзJSON = СтрокаАдреса.АдресJSON;
		
		АдресПоПолям = Новый Структура(Новый ФиксированнаяСтруктура(ПодготовленныеПоляАдреса)); // см. РаботаСАдресамиКлиентСервер.ПоляАдреса
	
		// Основные сведения
		АдресПоПолям.Комментарий = АдресИзJSON.Comment;
		АдресПоПолям.Индекс      = АдресИзJSON.ZipCode;
		АдресПоПолям.ТипАдреса   = АдресИзJSON.AddressType;
		АдресПоПолям.Страна      = АдресИзJSON.Country;
		АдресПоПолям.КодСтраны   = КодыСтраны(АдресИзJSON);
		НаименованиеРегиона      = СокрЛП(АдресИзJSON["area"] + " " +АдресИзJSON["areaType"]);
		
		НазваниеОсновнойСтраны = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(РаботаСАдресамиКлиентСервер.ОсновнаяСтрана(), "Наименование");
		ЭтоНациональныйАдрес = ?(СтрСравнить(АдресИзJSON.Country, НазваниеОсновнойСтраны) = 0, Истина, Ложь);
		АдресПоПолям.КодРегиона = ?(ЭтоНациональныйАдрес, КодРегиона(НаименованиеРегиона), "");
		
		ИдентификаторАдресногоОбъекта = "";
		МаксимальныйУровеньИдентификатора = 0;
		Для каждого ЧастьАдреса Из СоответствиеУровней Цикл
			
			ИдентификаторТекущегоУровня = АдресИзJSON[ЧастьАдреса.Ключ + "Id"];
			
			// АПК:1297-выкл НСтр не требуется, т.к. данные ГАР не переводятся.
			Если ЧастьАдреса.Ключ = "area" И СтрНачинаетсяС(АдресИзJSON[ЧастьАдреса.Ключ], "Кемеровская область -") Тогда
				НаименованиеУровня = "Кемеровская область - Кузбасс";
			// АПК:1297-вкл
				ТипКраткий = "обл";
			Иначе
				ТипКраткий = АдресИзJSON[ЧастьАдреса.Ключ + "Type"];
				НаименованиеУровня = ?(Параметры.НаименованиеВключаетСокращение, СокрЛП(АдресИзJSON[ЧастьАдреса.Ключ] + " " + ТипКраткий),
					АдресИзJSON[ЧастьАдреса.Ключ]);
			КонецЕсли;
			
			АдресПоПолям[ЧастьАдреса.Значение.Имя] = НаименованиеУровня;
			АдресПоПолям[ЧастьАдреса.Значение.Имя + "Сокращение"] = ТипКраткий;
			АдресПоПолям[ЧастьАдреса.Значение.Имя + "ТипКраткий"] = ТипКраткий;
			СоответствиеСокращений.Вставить(ЧастьАдреса.Значение.Уровень, ТипКраткий);
			
			Если Параметры.КодыАдреса Или Параметры.КодыКЛАДР Тогда
				Идентификаторы.Вставить(ЧастьАдреса.Значение.Имя + "Идентификатор", ИдентификаторТекущегоУровня);
				Идентификаторы.Вставить(ЧастьАдреса.Значение.Имя, ИдентификаторТекущегоУровня);
			КонецЕсли;
			
			УровеньИдентификатора = ?(ЧастьАдреса.Значение.Уровень < 10, ЧастьАдреса.Значение.Уровень * 10, ЧастьАдреса.Значение.Уровень);
			Если ЗначениеЗаполнено(ИдентификаторТекущегоУровня) И МаксимальныйУровеньИдентификатора < УровеньИдентификатора Тогда
				ИдентификаторАдресногоОбъекта = ИдентификаторТекущегоУровня;
				МаксимальныйУровеньИдентификатора = УровеньИдентификатора;
			КонецЕсли;
			
		КонецЦикла;
		
		// Коды мун. уровней
		АдресПоПолям.КодМуниципальногоРайона = КодМуниципальногоРайона(АдресИзJSON.munDistrictType, АдресИзJSON.oktmo,
			ЭтоГородФедеральногоЗначения(НаименованиеРегиона));
		АдресПоПолям.КодПоселения = КодПоселения(АдресИзJSON.settlementType);
		
		Если Параметры.КодыАдреса Тогда
			АдресПоПолям.ИдентификаторАдресногоОбъекта = ИдентификаторАдресногоОбъекта;
			АдресПоПолям.ИдентификаторДома             = ?(ЗначениеЗаполнено(АдресИзJSON.houseId), АдресИзJSON.houseId, "");
		КонецЕсли;
		
		// Установка полных наименований типов
		Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.АдресныйКлассификатор") Тогда
			МодульАдресныйКлассификаторСлужебный = ОбщегоНазначения.ОбщийМодуль("АдресныйКлассификаторСлужебный");
			МодульАдресныйКлассификаторСлужебный.ПолныеНаименованияСокращений(СоответствиеСокращений);
			
			Для каждого ЧастьАдреса Из СоответствиеУровней Цикл
				
				АдресПоПолям[ЧастьАдреса.Значение.Имя + "ТипПолный"] = СоответствиеСокращений[ЧастьАдреса.Значение.Уровень];
				
				Если Параметры.ПолноеНаименованиеСокращений  = Истина Тогда
					АдресПоПолям[ЧастьАдреса.Значение.Имя + "Сокращение"] = СоответствиеСокращений[ЧастьАдреса.Значение.Уровень];
				КонецЕсли;
				
			КонецЦикла;
			
		КонецЕсли;
		
		АдресПоПолям.НомерЗемельногоУчастка         = АдресИзJSON.stead;
		АдресПоПолям.ИдентификаторЗемельногоУчастка = АдресИзJSON.steadId;
		
		// Дома, здания, строения
		АдресПоПолям.Здание.Вставить("ТипЗдания", АдресИзJSON.HouseType);
		АдресПоПолям.Здание.Вставить("Номер",     АдресИзJSON.HouseNumber);
		
		Для каждого Корпус Из АдресИзJSON.Buildings Цикл
			АдресПоПолям.Корпуса.Добавить(Новый Структура("ТипКорпуса, Номер", Корпус.Type, Корпус.Number));
		КонецЦикла;
		
		Для каждого Корпус Из АдресИзJSON.Apartments Цикл
			АдресПоПолям.Помещения.Добавить(Новый Структура("ТипПомещения, Номер", Корпус.Type, Корпус.Number));
		КонецЦикла;
		
		Если ЭтоНациональныйАдрес Тогда
			
			Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.АдресныйКлассификатор") Тогда
				МодульАдресныйКлассификаторСлужебный = ОбщегоНазначения.ОбщийМодуль("АдресныйКлассификаторСлужебный");
				Если Параметры.ВозвращатьКоды Тогда
					ДополнительныеКоды = МодульАдресныйКлассификаторСлужебный.КодыАдресаИКодыКЛАДР(АдресИзJSON, ИдентификаторАдресногоОбъекта);
					АдресПоПолям.Вставить("ДополнительныеКоды", ДополнительныеКоды.КодыАдреса);
					АдресПоПолям.Вставить("КодыКЛАДР",          ДополнительныеКоды.КодыКЛАДР);
					Если Параметры.КодыАдреса И ДополнительныеКоды.КодыАдреса.Свойство("ИдентификаторДома") Тогда
						АдресПоПолям.ИдентификаторДома = ДополнительныеКоды.КодыАдреса.ИдентификаторДома;
					КонецЕсли;
				КонецЕсли;
			Иначе
				ЗаполнитьКодыАдреса(АдресПоПолям, АдресИзJSON);
			КонецЕсли;
			
			Если Параметры.ПроверитьАдрес Тогда
				
				РезультатПроверки = СведенияОбПроверкеАдреса(АдресСтрокой);
				АдресПоПолям.РезультатПроверкиАдреса = РезультатПроверки.Результат;
				АдресПоПолям.ОшибкиПроверкиАдреса = РезультатПроверки.СписокОшибок;
				
			КонецЕсли;
			
		КонецЕсли;
		
		Если Не Параметры.БезПредставлений Тогда
			
			АдресПоПолям.Представление = РаботаСАдресамиКлиентСервер.ПредставлениеАдреса(АдресИзJSON,
				Параметры.ВключатьСтрануВПредставление, РаботаСАдресамиКлиентСервер.АдминистративноТерриториальныйАдрес());
				
			Если ПустаяСтрока(АдресПоПолям.Представление) Тогда
				АдресПоПолям.Представление = АдресИзJSON.value;
			КонецЕсли;
			
			АдресПоПолям.МуниципальноеПредставление = РаботаСАдресамиКлиентСервер.ПредставлениеАдреса(АдресИзJSON,
				Параметры.ВключатьСтрануВПредставление, РаботаСАдресамиКлиентСервер.МуниципальныйАдрес());
				
			Если ПустаяСтрока(АдресПоПолям.МуниципальноеПредставление) Тогда
				АдресПоПолям.МуниципальноеПредставление = АдресИзJSON.value;
			КонецЕсли;
			
		КонецЕсли;
		
		// АПК:1297-выкл НСтр не требуется, т.к. данные ГАР не переводятся.
		АдресПоПолям.Регион = СтрЗаменить(АдресПоПолям.Регион, "Кемеровская область - Кузбасс обл", "Кемеровская область - Кузбасс");
		// АПК:1297-вкл
		УправлениеКонтактнойИнформациейСлужебный.ЗаменитьВСтруктуреНеопределеноНаПустуюСтроку(АдресПоПолям);
		СтрокаАдреса.Адрес = АдресПоПолям;

	КонецЦикла;
	
	ТаблицаАдресов.Сортировать("ИндексАдреса");
	НаборАдресов = Новый Массив;
	Для НомерСтроки = 0 По ТаблицаАдресов.Количество() - 1 Цикл
		НаборАдресов.Добавить(ТаблицаАдресов.Получить(НомерСтроки).Адрес);
	КонецЦикла;
	
	Возврат НаборАдресов;
	
КонецФункции

Процедура УстановкаТипаОбластьКемеровскойОбласти(КонтактнаяИнформацияПоПолям) Экспорт
	
	// АПК:1297-выкл НСтр не требуется, т.к. данные ГАР не переводятся.
	Если СтрСравнить(КонтактнаяИнформацияПоПолям.area, "Кемеровская область -") = 0 Тогда
		КонтактнаяИнформацияПоПолям.area = "Кемеровская область - Кузбасс";
	// АПК:1297-вкл
		КонтактнаяИнформацияПоПолям.areaType= "обл";
	КонецЕсли;
	
КонецПроцедуры

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

// Возвращаемое значение:
//  Соответствие из Структура:
//   * Ключ - Строка
//   * Значение - Структура:
//      ** Имя - Строка
//      ** Уровень - Число
//
Функция СоответствиеУровней()
	
	СоответствиеУровней = Новый Соответствие;
	СоответствиеУровней.Вставить("area",         Новый Структура("Имя, Уровень", "Регион", 1));
	СоответствиеУровней.Вставить("district",     Новый Структура("Имя, Уровень", "Район", 3));
	СоответствиеУровней.Вставить("munDistrict",  Новый Структура("Имя, Уровень", "МуниципальныйРайон", 31));
	СоответствиеУровней.Вставить("city",         Новый Структура("Имя, Уровень", "Город", 4));
	СоответствиеУровней.Вставить("settlement",   Новый Структура("Имя, Уровень", "Поселение", 41));
	СоответствиеУровней.Вставить("cityDistrict", Новый Структура("Имя, Уровень", "ВнутригородскойРайон", 5));
	СоответствиеУровней.Вставить("locality",     Новый Структура("Имя, Уровень", "НаселенныйПункт", 6));
	СоответствиеУровней.Вставить("territory",    Новый Структура("Имя, Уровень", "Территория", 65));
	СоответствиеУровней.Вставить("street",       Новый Структура("Имя, Уровень", "Улица", 7));
	Возврат СоответствиеУровней;
	
КонецФункции

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

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

Функция КодМуниципальногоРайона(Знач ТипМуниципальногоРайона, ОКТМО, ЭтоГородФедеральногоЗначения)
	
	КодМуниципальногоРайона = "";
	
	// АПК: 1297-выкл Данные адресного классификатора, не локализуются
	Если СтрСравнить(ТипМуниципальногоРайона, "м.р-н") = 0 Тогда
		КодМуниципальногоРайона = "1";
	ИначеЕсли СтрСравнить(ТипМуниципальногоРайона, "г.о.") = 0 Тогда
		КодМуниципальногоРайона = "2";
	ИначеЕсли СтрСравнить(ТипМуниципальногоРайона, "вн.тер.") = 0
		Или СтрСравнить(ТипМуниципальногоРайона, "вн.тер. г.") = 0 Тогда
		КодМуниципальногоРайона = "3";
	ИначеЕсли СтрСравнить(ТипМуниципальногоРайона, "мун. окр.") = 0
		Или СтрСравнить(ТипМуниципальногоРайона, "м.о.") = 0 Тогда
		КодМуниципальногоРайона = "4";
	ИначеЕсли СтрСравнить(ТипМуниципальногоРайона, "ф.т.") = 0 Тогда
		КодМуниципальногоРайона = "5";
	КонецЕсли;
	// АПК: 1297-вкл
	
	Если ЗначениеЗаполнено(КодМуниципальногоРайона) Тогда
		Возврат КодМуниципальногоРайона;
	КонецЕсли;
	
	ОКТМОСтрокой = ОКТМОСтрокой(ОКТМО);
	
	Если СтрДлина(ОКТМОСтрокой) > 3 Тогда
		
		КодВторойСтупениКлассификации = Сред(ОКТМОСтрокой, 3, 1);
		Если КодВторойСтупениКлассификации = "3"
			ИЛИ ЭтоГородФедеральногоЗначения И КодВторойСтупениКлассификации = "9" Тогда
			КодМуниципальногоРайона = "3";
		ИначеЕсли КодВторойСтупениКлассификации = "6" Тогда
			КодМуниципальногоРайона = "1";
		ИначеЕсли КодВторойСтупениКлассификации = "7" Тогда
			КодМуниципальногоРайона = "2";
		ИначеЕсли КодВторойСтупениКлассификации = "9" И НЕ ЭтоГородФедеральногоЗначения Тогда
			КодМуниципальногоРайона = "4";
		ИначеЕсли КодВторойСтупениКлассификации = "5" Тогда
			КодМуниципальногоРайона = "4";
		КонецЕсли;
		
	КонецЕсли;
	
	Возврат КодМуниципальногоРайона;
	
КонецФункции

Функция ОКТМОСтрокой(ОКТМО)
	
	Результат = СокрЛП(ОКТМО);
	Если СтрДлина(Результат) = 7 Или СтрДлина(Результат) = 10 Тогда
		Результат = "0" + Результат;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

Функция КодПоселения(Знач ТипПоселения)
	
	КодПоселения = "";
	
	// АПК: 1297-выкл Данные адресного классификатора, не локализуются
	Если СтрСравнить(ТипПоселения, "г.п.") = 0 Или СтрСравнить(ТипПоселения, "г. п.") = 0 Тогда
		КодПоселения = "1";
	ИначеЕсли СтрСравнить(ТипПоселения, "с.п.") = 0 Тогда
		КодПоселения = "2";
	ИначеЕсли СтрСравнить(ТипПоселения, "меж.тер.") = 0 Тогда
		КодПоселения = "3";
	ИначеЕсли СтрСравнить(ТипПоселения, "вн.р-н") = 0 Тогда
		КодПоселения = "4";
	КонецЕсли;
	// АПК: 1297-вкл
	
	Возврат КодПоселения;
	
КонецФункции

Функция КодыСтраны(Знач Адрес)
	
	КодСтраны = Адрес.CountryCode;
	
	Если НЕ ЗначениеЗаполнено(КодСтраны) Тогда
		СведенияОСтране = УправлениеКонтактнойИнформацией.ДанныеСтраныМира(Неопределено, Адрес.Country);
		Если СведенияОСтране <> Неопределено Тогда
			КодСтраны = СведенияОСтране.Код;
		КонецЕсли;
	КонецЕсли;
	
	Возврат КодСтраны;
	
КонецФункции

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

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

Функция СтруктураАдресаВСтруктуруJSON(Знач КонтактнаяИнформация)
	
	ОписаниеКонтактнойИнформации = РаботаСАдресамиКлиентСервер.ОписаниеНовойКонтактнойИнформации(Перечисления.ТипыКонтактнойИнформации.Адрес);
	
	СоответствиеПолей = Новый Соответствие();
	СоответствиеПолей.Вставить("ТипАдреса",                      "addressType");
	СоответствиеПолей.Вставить("Представление",                  "value");
	СоответствиеПолей.Вставить("Комментарий",                    "comment");
	СоответствиеПолей.Вставить("НаименованиеСтраны",             "country");
	СоответствиеПолей.Вставить("Страна",                         "country");
	СоответствиеПолей.Вставить("Индекс",                         "ZIPCode");
	СоответствиеПолей.Вставить("ОКТМО",                          "oktmo");
	СоответствиеПолей.Вставить("ОКТМОБюджетополучателя",         "oktmoBudget");
	СоответствиеПолей.Вставить("ОКАТО",                          "okato");
	СоответствиеПолей.Вставить("Регион",                         "area");
	СоответствиеПолей.Вставить("РегионСокращение",               "areaType");
	СоответствиеПолей.Вставить("Район",                          "district");
	СоответствиеПолей.Вставить("РайонСокращение",                "districtType");
	СоответствиеПолей.Вставить("Город",                          "city");
	СоответствиеПолей.Вставить("ГородСокращение",                "cityType");
	СоответствиеПолей.Вставить("НаселенныйПункт",                "locality");
	СоответствиеПолей.Вставить("НаселенныйПунктСокращение",      "localityType");
	СоответствиеПолей.Вставить("Улица",                          "street");
	СоответствиеПолей.Вставить("УлицаСокращение",                "streetType");
	СоответствиеПолей.Вставить("КодРегиона",                     "areaCode");
	СоответствиеПолей.Вставить("МуниципальныйРайон",             "munDistrict");
	СоответствиеПолей.Вставить("МуниципальныйРайонСокращение",   "munDistrictType");
	СоответствиеПолей.Вставить("Поселение",                      "settlement");
	СоответствиеПолей.Вставить("ПоселениеСокращение",            "settlementType");
	СоответствиеПолей.Вставить("ВнутригородскойРайон",           "cityDistrict");
	СоответствиеПолей.Вставить("ВнутригородскойРайонСокращение", "cityDistrictType");
	СоответствиеПолей.Вставить("Территория",                     "territory");
	СоответствиеПолей.Вставить("ТерриторияСокращение",           "territoryType");
	СоответствиеПолей.Вставить("ИдентификаторАдресногоОбъекта",  "id");
	СоответствиеПолей.Вставить("ИдентификаторДома",              "houseId");
	СоответствиеПолей.Вставить("Дом",                            "houseNumber");
	СоответствиеПолей.Вставить("ТипДома",                        "houseType");
	
	Для каждого ПолеКонтактнойИнформации Из КонтактнаяИнформация Цикл
		ИмяПоля = СоответствиеПолей.Получить(ПолеКонтактнойИнформации.Ключ);
		Если ИмяПоля <> Неопределено Тогда
			ОписаниеКонтактнойИнформации[ИмяПоля] = ПолеКонтактнойИнформации.Значение;
		КонецЕсли;
	КонецЦикла;
	
	Если КонтактнаяИнформация.Свойство("ТипАдреса") И РаботаСАдресамиКлиентСервер.ЭтоМуниципальныйАдрес(КонтактнаяИнформация.ТипАдреса) Тогда
		ОписаниеКонтактнойИнформации.AddressType = РаботаСАдресамиКлиентСервер.МуниципальныйАдрес();
		Если КонтактнаяИнформация.Свойство("МуниципальноеПредставление") И ЗначениеЗаполнено(КонтактнаяИнформация.МуниципальноеПредставление) Тогда
			ОписаниеКонтактнойИнформации.value = КонтактнаяИнформация.МуниципальноеПредставление;
		КонецЕсли;
	Иначе
		ОписаниеКонтактнойИнформации.AddressType = РаботаСАдресамиКлиентСервер.АдминистративноТерриториальныйАдрес();
	КонецЕсли;
	
	Если КонтактнаяИнформация.Свойство("Здание")
		 И ТипЗнч(КонтактнаяИнформация.Здание) = Тип("Структура")
		 И КонтактнаяИнформация.Здание.Свойство("Номер") Тогда
		
			ОписаниеКонтактнойИнформации.HouseNumber = ?(КонтактнаяИнформация.Здание.Свойство("Номер"), КонтактнаяИнформация.Здание.Номер, "");
			ОписаниеКонтактнойИнформации.HouseType = ?(КонтактнаяИнформация.Здание.Свойство("ТипЗдания"), КонтактнаяИнформация.Здание.ТипЗдания, "Дом"); // Тип владения не локализуется
		
	КонецЕсли;
	
	Если КонтактнаяИнформация.Свойство("Корпус")И ЗначениеЗаполнено(КонтактнаяИнформация.Корпус) Тогда
		
		ТипКорпуса = ?(КонтактнаяИнформация.Свойство("ТипКорпуса"), КонтактнаяИнформация.ТипКорпуса, "Корпус"); // Тип владения не локализуется
		ОписаниеКонтактнойИнформации.buildings.Добавить(УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения(ТипКорпуса, КонтактнаяИнформация.Корпус));
		
	ИначеЕсли КонтактнаяИнформация.Свойство("Корпуса")И ТипЗнч(КонтактнаяИнформация.Корпуса) = Тип("Массив") Тогда
		Для каждого Корпус Из КонтактнаяИнформация.Корпуса Цикл
			
			ТипКорпуса = ?(Корпус.Свойство("ТипКорпуса"), Корпус.ТипКорпуса, Корпус.Тип);
			ОписаниеКонтактнойИнформации.buildings.Добавить(
				УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения(ТипКорпуса, Корпус.Номер));
				
		КонецЦикла;
		
	КонецЕсли;
	
	Если КонтактнаяИнформация.Свойство("Квартира") И ЗначениеЗаполнено(КонтактнаяИнформация.Квартира) Тогда
		
		ТипКвартиры = ?(КонтактнаяИнформация.Свойство("ТипКвартиры"), КонтактнаяИнформация.ТипКвартиры, "Квартира"); // Тип помещения не локализуется
		ОписаниеКонтактнойИнформации.apartments.Добавить(УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения(ТипКвартиры, КонтактнаяИнформация.Квартира));
		
	ИначеЕсли КонтактнаяИнформация.Свойство("Помещения")И ТипЗнч(КонтактнаяИнформация.Помещения) = Тип("Массив") Тогда
		
		Для каждого Помещение Из КонтактнаяИнформация.Помещения Цикл
			
			ТипПомещения = ?(Помещение.Свойство("ТипПомещения"), Помещение.ТипПомещения, Помещение.Тип);
			ОписаниеКонтактнойИнформации.apartments.Добавить(
				УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения(ТипПомещения, Помещение.Номер));
		КонецЦикла;
		
	КонецЕсли;
	
	Если ПустаяСтрока(ОписаниеКонтактнойИнформации.value) Тогда
		ОписаниеКонтактнойИнформации.value = РаботаСАдресамиКлиентСервер.ПредставлениеАдреса(ОписаниеКонтактнойИнформации, Ложь,
			ОписаниеКонтактнойИнформации.AddressType);
	КонецЕсли;
	
	Возврат ОписаниеКонтактнойИнформации;
	
КонецФункции

// Возвращает код региона по его полному наименованию.
//
//  Параметры:
//      НаименованиеРегиона - Строка - полное наименование региона с сокращением.
//
// Возвращаемое значение:
//      Строка - код региона из двух цифр. Пустая строка, если наименование определить не удалось.
//      Неопределено - если нет ни одной подсистемы адресного классификатора.
// 
Функция КодРегиона(Знач ПолноеНаименование) Экспорт
	
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.АдресныйКлассификатор") Тогда
		МодульАдресныйКлассификатор = ОбщегоНазначения.ОбщийМодуль("АдресныйКлассификатор");
		Код = МодульАдресныйКлассификатор.КодРегионаПоНаименованию(ПолноеНаименование);
		Возврат Формат(Код, "ЧЦ=2; ЧН=; ЧВН=");
	КонецЕсли;
	
	Возврат Неопределено;
	
КонецФункции

// Заполняет коды по структуре адреса.
//
Процедура ЗаполнитьКодыАдреса(Результат, Адрес)
	
	ДополнительныеКоды = Новый Структура();
	ДополнительныеКоды.Вставить("ОКТМО", "");
	ДополнительныеКоды.Вставить("ОКАТО", "");
	ДополнительныеКоды.Вставить("КодИФНСФЛ", "");
	ДополнительныеКоды.Вставить("КодИФНСЮЛ", "");
	ДополнительныеКоды.Вставить("КодУчасткаИФНСФЛ", "");
	ДополнительныеКоды.Вставить("КодУчасткаИФНСЮЛ", "");
	ДополнительныеКоды.Вставить("ИдентификаторДома", "");
	ДополнительныеКоды.Вставить("КодУчасткаИФНСЮЛ", "");
	
	Результат.Вставить("ДополнительныеКоды", ДополнительныеКоды);

	УстановитьЗначенияПоля(Результат, Адрес, "ОКТМО", "oktmo");
	УстановитьЗначенияПоля(Результат, Адрес, "ОКТМОБюджетополучателя", "oktmoBudget");
	УстановитьЗначенияПоля(Результат, Адрес, "ОКАТО", "okato");
	УстановитьЗначенияПоля(Результат, Адрес, "КодИФНСФЛ", "IFNSFLCode");
	УстановитьЗначенияПоля(Результат, Адрес, "КодИФНСЮЛ", "IFNSULCode");
	УстановитьЗначенияПоля(Результат, Адрес, "КодУчасткаИФНСФЛ", "IFNSFLAreaCode");
	УстановитьЗначенияПоля(Результат, Адрес, "КодУчасткаИФНСЮЛ", "IFNSULAreaCode");
	УстановитьЗначенияПоля(Результат, Адрес, "ИдентификаторДома", "HouseId");
	
	КодКЛАДР = "";
	Если Адрес.Свойство("CodeKLADR") И ЗначениеЗаполнено(Адрес.CodeKLADR) Тогда
		КодКЛАДР = Адрес.CodeKLADR;
	КонецЕсли;
	Результат.Вставить("КодыКЛАДР", ОпределитьКодыКодыКЛАДР(Адрес, КодКЛАДР));
	
КонецПроцедуры

Процедура УстановитьЗначенияПоля(Приемник, Источник, ИмяПоляПриемник, ИмяПоляИсточник)
	Если Источник.Свойство(ИмяПоляИсточник) Тогда
		Значение = ?(ЗначениеЗаполнено(Источник), Источник[ИмяПоляИсточник], ""); // Неопределено, Null и др. в пустую строку
	КонецЕсли;
	Приемник[ИмяПоляПриемник] = Значение;
КонецПроцедуры

// Заполняет коды по структуре адреса.
//
Функция ОпределитьКодыКодыКЛАДР(Адрес, Знач КодКЛАДР)
	
	КодыКЛАДР = Новый Структура();
	КодыКЛАДР.Вставить("Регион",               "");
	КодыКЛАДР.Вставить("Округ",                "");
	КодыКЛАДР.Вставить("Город",                "");
	КодыКЛАДР.Вставить("ВнутригородскойРайон", "");
	КодыКЛАДР.Вставить("НаселенныйПункт",      "");
	КодыКЛАДР.Вставить("Улица",                "");
	
	// Заполнить коды КЛАДР.
	Если ЗначениеЗаполнено(КодКЛАДР) Тогда
		КодКЛАДР = Формат(КодКЛАДР, "ЧРГ=''; ЧГ=0");
		
		Если СтрДлина(КодКЛАДР) = 17 Тогда
			КодыКЛАДР.Улица = КодКЛАДР;
		КонецЕсли;
		КодКЛАДР = Лев(КодКЛАДР, 13);
		
		Если СтрДлина(КодКЛАДР) = 12 Тогда
			КодКЛАДР = "0" + КодКЛАДР;
		КонецЕсли;
		
		Если СтрДлина(КодКЛАДР) = 13 Тогда
			Если ЗначениеЗаполнено(Адрес.area) Тогда
				КодыКЛАДР.Регион = Лев(КодКЛАДР, 2) + "00000000000";
			КонецЕсли;
			Если ЗначениеЗаполнено(Адрес.District) Тогда
				КодыКЛАДР.Район = Лев(КодКЛАДР, 5) + "00000000";
			КонецЕсли;
			Если ЗначениеЗаполнено(Адрес.City) Тогда
				КодыКЛАДР.Город = Лев(КодКЛАДР, 8) + "00000";
			КонецЕсли;
			Если ЗначениеЗаполнено(Адрес.Settlement) Тогда
				КодыКЛАДР.НаселенныйПункт = Лев(КодКЛАДР, 11) + "00";
			КонецЕсли;
			
		КонецЕсли;
	КонецЕсли;
	
	Возврат КодыКЛАДР;
	
КонецФункции

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

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

//  Возвращает строку списка полей.
//
//  Параметры:
//    СтруктураЗначенийПолей - Структура
//    БезПустыхПолей         - Булево - флаг сохранения полей с пустыми значениями.
//
//  Возвращаемое значение:
//     Строка - результат преобразования из структуры.
//
Функция СтрокаПолей(СтруктураЗначенийПолей, БезПустыхПолей = Истина) Экспорт
	
	Результат = "";
	Для Каждого ЗначениеПоля Из СтруктураЗначенийПолей Цикл
		Если БезПустыхПолей И ПустаяСтрока(ЗначениеПоля.Значение) Тогда
			Продолжить;
		КонецЕсли;
		
		Результат = Результат + ?(Результат = "", "", Символы.ПС)
		            + ЗначениеПоля.Ключ + "=" + СтрЗаменить(ЗначениеПоля.Значение, Символы.ПС, Символы.ПС + Символы.Таб);
	КонецЦикла;
	
	Возврат Результат;
КонецФункции

Функция НаборБуквВНижнемРегистре() Экспорт

	Возврат "абвгдеёжзийклмнопрстуфхцчшщыъьэюяabcdefghijklmnopqrstuvwxyz"; // АПК:163, АПК:216 Адреса могут содержать латиницу и все буквы русского алфавита.

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

Функция НаборБуквВВерхнемРегистре() Экспорт

	Возврат "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЫЪЬЭЮЯABCDEFGHIJKLMNOPQRSTUVWXYZ"; // АПК:163, АПК:216 Адреса могут содержать латиницу и все буквы русского алфавита.

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

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

Функция ЭтоГородФедеральногоЗначения(Город) Экспорт
	
	НазванияГородовФедеральногоЗначения = НазванияГородовФедеральногоЗначения();
	Возврат НазванияГородовФедеральногоЗначения.Получить(ВРег(Город)) = Истина;
	
КонецФункции

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

// Общероссийский классификатор стран мира

// Возвращает полные данные ОКСМ классификатора.
// Таблица значений в макете проиндексирована по полям "Код", "Наименование".
//
// Возвращаемое значение:
//     ТаблицаЗначений - данные классификатора с колонками:
//         * Код                - Строка - данные страны.
//         * Наименование       - Строка - данные страны.
//         * НаименованиеПолное - Строка - данные страны.
//         * КодАльфа2          - Строка - данные страны.
//         * КодАльфа3          - Строка - данные страны.
//
Функция ТаблицаКлассификатора() Экспорт
	
	Результат = РаботаСАдресамиПовтИсп.СтраныМира();
	СтраныМира = Результат.СтраныМира.Скопировать();
	Возврат СтраныМира;
	
КонецФункции

Функция ЗаполнитьДанныеВыбораАвтоподбораПоСтранам(Знач Параметры) Экспорт
	
	ДанныеВыбора = Новый СписокЗначений;
	
	// Будем имитировать поведение платформы - поиск по всем доступным полям поиска с формированием подобного списка.
	// Подразумеваем, что поля справочника и классификатора совпадают, за исключением отсутствующего в классификаторе поля "Ссылка".
	Запрос = Новый Запрос;
	
	ПрефиксПараметраОтбора = "ПараметрыОтбора";
	
	ПоляОтбора = Новый Массив;
	ПоляОтбора.Добавить("Код");
	ПоляОтбора.Добавить("Наименование");
	
	// Общий отбор по параметрам
	Отборы = Новый Массив;
	Для Каждого КлючЗначение Из Параметры.Отбор Цикл
		ЗначениеПоля = КлючЗначение.Значение;
		ИмяПоля      = КлючЗначение.Ключ;
		ИмяПараметра = ПрефиксПараметраОтбора + ИмяПоля;
		
		Если ТипЗнч(ЗначениеПоля) = Тип("Массив") Или ТипЗнч(ЗначениеПоля) = Тип("ФиксированныйМассив") Тогда
			Отборы.Добавить(" %1." + ИмяПоля + " В (&" + ИмяПараметра + ")");
		Иначе
			Отборы.Добавить(" %1." + ИмяПоля + " = &" + ИмяПараметра);
		КонецЕсли;
		
		ПоляОтбора.Добавить(ИмяПоля);
		Запрос.УстановитьПараметр(ИмяПараметра, КлючЗначение.Значение);
	КонецЦикла;
	
	// Дополнительные отборы
	Если Параметры.Свойство("ВыборГруппИЭлементов") Тогда
		Если Параметры.ВыборГруппИЭлементов = ИспользованиеГруппИЭлементов.Группы Тогда
			
			Отборы.Добавить(" %1.ЭтоГруппа");
			
		ИначеЕсли Параметры.ВыборГруппИЭлементов = ИспользованиеГруппИЭлементов.Элементы Тогда
			
			Отборы.Добавить(" (НЕ %1.ЭтоГруппа)");
			
		КонецЕсли;
	КонецЕсли;
	ШаблонОтбора = СтрСоединить(Отборы, " И ");
	
	// Источники данных
	Если (Параметры.Свойство("ТолькоДанныеКлассификатора") И Параметры.ТолькоДанныеКлассификатора) Тогда
		// Запрос только по классификатору.
		ШаблонЗапроса = "
		|ВЫБРАТЬ ПЕРВЫЕ 50
		|	NULL                       КАК Ссылка,
		|	Классификатор.Код          КАК Код,
		|	Классификатор.Наименование КАК Наименование,
		|	ЛОЖЬ                       КАК ПометкаУдаления,
		|	&Представление             КАК Представление
		|ИЗ
		|	Классификатор КАК Классификатор
		|ГДЕ
		|	Классификатор.ПолеПоиска ПОДОБНО &СтрокаПоиска СПЕЦСИМВОЛ ""~""";
		
		Если ЗначениеЗаполнено(ШаблонОтбора) Тогда
			ШаблонЗапроса = ШаблонЗапроса + "
			|И (
			|	" + СтрЗаменить(ШаблонОтбора, "%1", "Классификатор") + "
			|	)
			|";
		КонецЕсли;
	Иначе
		// Запрос и по справочнику и по классификатору.
		ШаблонЗапроса = "
		|ВЫБРАТЬ ПЕРВЫЕ 50 
		|	СтраныМира.Ссылка                                             КАК Ссылка,
		|	ЕСТЬNULL(СтраныМира.Код, Классификатор.Код)                   КАК Код,
		|	ЕСТЬNULL(СтраныМира.Наименование, Классификатор.Наименование) КАК Наименование,
		|	ЕСТЬNULL(СтраныМира.ПометкаУдаления, ЛОЖЬ)                    КАК ПометкаУдаления,
		|
		|	ВЫБОР КОГДА СтраныМира.Ссылка ЕСТЬ NULL ТОГДА 
		|		&Представление
		|	ИНАЧЕ 
		|		&ДругоеПредставление
		|	КОНЕЦ КАК Представление
		|
		|ИЗ
		|	Справочник.СтраныМира КАК СтраныМира
		|ПОЛНОЕ СОЕДИНЕНИЕ
		|	Классификатор
		|ПО
		|	Классификатор.Код = СтраныМира.Код
		|	И Классификатор.Наименование = СтраныМира.Наименование
		|ГДЕ 
		|	(СтраныМира.ПолеПоиска ПОДОБНО &СтрокаПоиска СПЕЦСИМВОЛ ""~"" 
		|		ИЛИ Классификатор.ПолеПоиска ПОДОБНО &СтрокаПоиска СПЕЦСИМВОЛ ""~"")";
		
		Если ЗначениеЗаполнено(ШаблонОтбора) Тогда
			ШаблонЗапроса = ШаблонЗапроса  + "
			|	И ((" + СтрЗаменить(ШаблонОтбора, "%1", "Классификатор") + ")
			|	ИЛИ (" + СтрЗаменить(ШаблонОтбора, "%1", "СтраныМира") + "))
			|
			|";
		КонецЕсли;
		
	КонецЕсли;
	
	ИменаПолей = ПоляПоиска(ПоляОтбора);
	ИменаПолейСтрокой = СтрСоединить(ИменаПолей.ИменаПолейДляОтбораВКлассификаторе, ", ");
	
	ТекстЗапросаКлассификатор = "ВЫБРАТЬ
	|	&ИменаПолейСтрокой
	|ПОМЕСТИТЬ
	|	Классификатор
	|ИЗ
	|	&Классификатор КАК Классификатор
	|ИНДЕКСИРОВАТЬ ПО
	|	&ИменаПолейСтрокой
	|";
	
	ТекстЗапросаКлассификатор = СтрЗаменить(ТекстЗапросаКлассификатор, "&ИменаПолейСтрокой", ИменаПолейСтрокой);
	
	НаборЗапросов = Новый Массив;
	Для Каждого ДанныеПоля Из ИменаПолей.СписокПолей Цикл
		ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "СтраныМира.ПолеПоиска", "СтраныМира." + ДанныеПоля.Имя);
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "Классификатор.ПолеПоиска",  "Классификатор." + ДанныеПоля.Имя);
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&Представление", СтрЗаменить(ДанныеПоля.ШаблонПредставления, "%1", "Классификатор"));
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ДругоеПредставление", СтрЗаменить(ДанныеПоля.ШаблонПредставления, "%1", "СтраныМира"));
		
		НаборЗапросов.Добавить(ТекстЗапроса);
	КонецЦикла;
	
	Запрос.Текст = ТекстЗапросаКлассификатор + "
	|;
	|" + СтрСоединить(НаборЗапросов, " ОБЪЕДИНИТЬ ВСЕ ") + "
	|УПОРЯДОЧИТЬ ПО Представление";
	
	Запрос.УстановитьПараметр("Классификатор", ТаблицаКлассификатора());
	Запрос.УстановитьПараметр("СтрокаПоиска", 
		ОбщегоНазначения.СформироватьСтрокуДляПоискаВЗапросе(Параметры.СтрокаПоиска) + "%");
	
	РезультатЗапроса = Запрос.Выполнить();
	
	Если РезультатЗапроса.Пустой() Тогда
		Возврат ДанныеВыбора;
	КонецЕсли;
	
	ДлинаСтрокиПоиска = СтрДлина(Параметры.СтрокаПоиска);
	
	Выборка = РезультатЗапроса.Выбрать();
	Пока Выборка.Следующий() Цикл
		
		Если ЗначениеЗаполнено(Выборка.Ссылка) Тогда
			// Данные справочника
			ЭлементВыбора = Выборка.Ссылка;
		Иначе
			// Данные классификатора
			РезультатВыбора = Новый Структура("Код, Наименование",
				Выборка.Код, Выборка.Наименование);
			
			ЭлементВыбора = Новый Структура("Значение, ПометкаУдаления, Предупреждение",
				РезультатВыбора, Выборка.ПометкаУдаления, Неопределено);
		КонецЕсли;
		
		ВыделенныйТекст = Новый ФорматированнаяСтрока(Лев(Выборка.Представление, ДлинаСтрокиПоиска), ШрифтыСтиля.ВажнаяНадписьШрифт, ЦветаСтиля.РезультатУспехЦвет);
		Представление = Новый ФорматированнаяСтрока(ВыделенныйТекст, Сред(Выборка.Представление, ДлинаСтрокиПоиска + 1));
		
		ДанныеВыбора.Добавить(ЭлементВыбора, Представление);
	КонецЦикла;
	
	Возврат ДанныеВыбора;
	
КонецФункции

// Возвращает поля поиска в порядке предпочтения для справочника стран мира.
//
// Возвращаемое значение:
//  Структура:
//    * СписокПолей - Массив из Структура:
//       ** Имя                 - Строка - имя реквизита поиска;
//       ** ШаблонПредставления - Строка - шаблон для формирования значения представления по именам реквизитов, 
//                                       например: "%1.Наименование (%1.Код)". Здесь "Наименование" и "Код" - имена
//                                       реквизитов, "%1" - заполнитель для передачи псевдонима таблицы.
//    * ИменаПолейДляОтбораВКлассификаторе - Массив
//
Функция ПоляПоиска(ПоляОтбора)
	
	Результат = Новый Массив;
	
	СписокПолей = Справочники.СтраныМира.ПустаяСсылка().Метаданные().ВводПоСтроке;
	ГраницаПолей = СписокПолей.Количество() - 1;
	
	Для Индекс = 0 По ГраницаПолей Цикл
		ИмяПоля = СписокПолей[Индекс].Имя;
		
		Если ПоляОтбора.Найти(ИмяПоля) = Неопределено Тогда
			ПоляОтбора.Добавить(ИмяПоля);
		КонецЕсли;
		
		ШаблонПредставления = "%1." + ИмяПоля;
		
		ОстальныеПоля = Новый Массив;
		Для Позиция = 0 По ГраницаПолей Цикл
			Если Позиция <> Индекс Тогда
				ОстальныеПоля.Добавить("%1." + СписокПолей[Позиция].Имя);
			КонецЕсли;
		КонецЦикла;
		
		Если ОстальныеПоля.Количество() > 0 Тогда
			ШаблонПредставления = ШаблонПредставления
				+ " + "" ("" + " + СтрСоединить(ОстальныеПоля, " + "", "" + ") + " + "")""";
		КонецЕсли;
		
		Результат.Добавить(
			Новый Структура("Имя, ШаблонПредставления", ИмяПоля, ШаблонПредставления));
	КонецЦикла;
	
	ПоляПоиска = Новый Структура;
	ПоляПоиска.Вставить("СписокПолей", Результат);
	ПоляПоиска.Вставить("ИменаПолейДляОтбораВКлассификаторе", ПоляОтбора);
	
	Возврат ПоляПоиска;
	
КонецФункции

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

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

Функция ОписаниеРезультатаПроверкиАдреса()
	
	ОписаниеРезультатаПроверки = Новый Структура;
	ОписаниеРезультатаПроверки.Вставить("АдресПроверен",   Ложь);
	ОписаниеРезультатаПроверки.Вставить("АдресКорректный", Ложь);
	
	Ошибки = Новый Массив;
	ОписаниеРезультатаПроверки.Вставить("Ошибки", Ошибки);
	
	АктуальныеАдреса = Новый Массив;
	ОписаниеРезультатаПроверки.Вставить("АктуальныеАдреса", АктуальныеАдреса);
	
	Возврат ОписаниеРезультатаПроверки;
	
КонецФункции

////////////////////////////////////////////////////////
// Контроль ведения учета

// Тип здания ЛИТЕРА 

// Выполняет замену в адресах типа здания Литер на Литера
//
// Параметры:
//   Проверка            - СправочникСсылка.ПравилаПроверкиУчета - исполняемая проверка.
//   ПараметрыПроверки   - см. КонтрольВеденияУчета.ОписаниеПроблемы.ПараметрыПроверки
//
Процедура ПроверитьАдресаНаТипЗданияЛитер(Проверка, ПараметрыПроверки) Экспорт
	
	Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.КонтрольВеденияУчета") Тогда
		Возврат;
	КонецЕсли;
	
	МодульКонтрольВеденияУчета = ОбщегоНазначения.ОбщийМодуль("КонтрольВеденияУчета");
	
	ПроверяемыеОбъекты = Новый Массив;
	
	ОбъектыМетаданных  = УправлениеКонтактнойИнформациейСлужебный.ОбъектыСодержащиеКонтактнуюИнформацию();
	НаборТекстаЗапроса = Новый Массив;
	
	Запрос = Новый Запрос;
	ШаблонЗапроса = 
		"ВЫБРАТЬ
		|	КонтактнаяИнформация.Ссылка КАК Ссылка,
		|	КонтактнаяИнформация.ЗначенияПолей КАК ЗначенияПолей,
		|	КонтактнаяИнформация.Вид КАК Вид,
		|	КонтактнаяИнформация.Представление КАК Представление,
		|	""&ИмяОбъекта"" КАК ИмяОбъекта
		|ИЗ
		|	&ПолноеИмяОбъектаСКонтактнойИнформацией КАК КонтактнаяИнформация
		|ГДЕ
		|	КонтактнаяИнформация.Тип = &Тип
		|	И КонтактнаяИнформация.Представление ПОДОБНО &ТипЗдания СПЕЦСИМВОЛ ""~""";
	
	Для каждого Объект Из ОбъектыМетаданных Цикл
		ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "&ПолноеИмяОбъектаСКонтактнойИнформацией", 
			Объект.Метаданные().ПолноеИмя() + ".КонтактнаяИнформация");
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяОбъекта", Объект.Метаданные().Представление());
		НаборТекстаЗапроса.Добавить(ТекстЗапроса);
	КонецЦикла;

	Запрос.Текст = СтрСоединить(НаборТекстаЗапроса, " ОБЪЕДИНИТЬ ВСЕ ");
		
	Запрос.УстановитьПараметр("Тип", Перечисления.ТипыКонтактнойИнформации.Адрес);
	Запрос.УстановитьПараметр("ТипЗдания", "%Литер %");
	РезультатЗапроса = Запрос.Выполнить().Выбрать();
	
	Проверки = Новый Соответствие;

	Пока РезультатЗапроса.Следующий() Цикл
		
		Если Проверки[РезультатЗапроса.Вид] = Неопределено Тогда
		
			ПараметрыВыполненияПроверки = МодульКонтрольВеденияУчета.ПараметрыВыполненияПроверки(НСтр("ru='Устаревший тип здания в адресах контактной информации'", ОбщегоНазначения.КодОсновногоЯзыка()), РезультатЗапроса.Вид);
			МодульКонтрольВеденияУчета.ОчиститьРезультатыПредыдущихПроверок(Проверка, ПараметрыВыполненияПроверки);
			ВидПроверки = МодульКонтрольВеденияУчета.ВидПроверки(ПараметрыВыполненияПроверки);
			
			Проверки.Вставить(РезультатЗапроса.Вид, ВидПроверки);
		
		КонецЕсли;
		
		Проблема = МодульКонтрольВеденияУчета.ОписаниеПроблемы(РезультатЗапроса.Ссылка, ПараметрыПроверки);
		Проблема.ВидПроверки = Проверки[РезультатЗапроса.Вид];
		Проблема.УточнениеПроблемы = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'В адресе ""%1"" используется устаревший тип здания Литер.'"), РезультатЗапроса.Представление);
		ПроверяемыеОбъекты.Добавить(РезультатЗапроса.Ссылка);
		
		МодульКонтрольВеденияУчета.ЗаписатьПроблему(Проблема, ПараметрыПроверки);
		
	КонецЦикла;
	
	ПараметрыПроверки.ПроверяемыеОбъекты = ПроверяемыеОбъекты;
	
КонецПроцедуры

// Выполняет замену в адресах типа здания Литер на Литера
//
// Параметры:
//   Проверка            - СправочникСсылка.ПравилаПроверкиУчета - исполняемая проверка.
//   ПараметрыПроверки   - см. КонтрольВеденияУчета.ОписаниеПроблемы.ПараметрыПроверки
//
Процедура ИсправитьТипЗданияЛитерВАдресахВФоне(Знач ПараметрыПроверки, АдресХранилища = Неопределено) Экспорт
	
	Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.КонтрольВеденияУчета") Тогда
		Возврат;
	КонецЕсли;
	
	МодульКонтрольВеденияУчета = ОбщегоНазначения.ОбщийМодуль("КонтрольВеденияУчета");
	Проверка = МодульКонтрольВеденияУчета.ПроверкаПоИдентификатору(ПараметрыПроверки.ИдентификаторПроверки);
	
	ВидПроверки = ПараметрыПроверки.ВидПроверки;
	Если Не ЗначениеЗаполнено(Проверка) Тогда
		Возврат;
	КонецЕсли;
		ВидКонтактнойИнформации = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ВидПроверки, "Свойство2"); // СправочникСсылка.ВидыКонтактнойИнформации
	ВключатьСтрануВПредставление = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ВидКонтактнойИнформации, "ВключатьСтрануВПредставление");
	
	ПроблемныеОбъекты = МодульКонтрольВеденияУчета.ПроблемныеОбъектыПоВидуПроверки(ВидПроверки);
	ВсегоЭлементов      = 0;
	ИсправленоЭлементов = 0;
	
	Пока ПроблемныеОбъекты.Количество() > 0 Цикл
		ПоследнийПроблемныйОбъект = ПроблемныеОбъекты.Получить(ПроблемныеОбъекты.Количество() - 1).ПроблемныйОбъект;
		ВсегоЭлементов = ВсегоЭлементов + ПроблемныеОбъекты.Количество();
		
		Для каждого ОписаниеОбъекта Из ПроблемныеОбъекты Цикл
			Если ИсправитьТипЗданияЛитерВАдресахОбъекта(ОписаниеОбъекта, ВидКонтактнойИнформации, ВключатьСтрануВПредставление) Тогда
				ИсправленоЭлементов = ИсправленоЭлементов + 1;
				
				Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.КонтрольВеденияУчета") Тогда
					МодульКонтрольВеденияУчета = ОбщегоНазначения.ОбщийМодуль("КонтрольВеденияУчета");
					МодульКонтрольВеденияУчета.ОчиститьРезультатПоВидуПроверки(ОписаниеОбъекта.ПроблемныйОбъект, ВидПроверки);
				КонецЕсли;
				
			КонецЕсли;
		КонецЦикла;
		
		ПроблемныеОбъекты = МодульКонтрольВеденияУчета.ПроблемныеОбъектыПоВидуПроверки(ВидПроверки, ПоследнийПроблемныйОбъект);
		
	КонецЦикла;
	Результат = Новый Структура;
	Результат.Вставить("ВсегоЭлементов", ВсегоЭлементов);
	Результат.Вставить("ИсправленоЭлементов", ИсправленоЭлементов);
	
	ПоместитьВоВременноеХранилище(Результат, АдресХранилища);
	
КонецПроцедуры

Функция ИсправитьТипЗданияЛитерВАдресахОбъекта(ОписаниеОбъекта, Знач ВидКонтактнойИнформации, Знач ВключатьСтрануВПредставление)
	
	ОбъектБылИсправлен = Ложь;
	
	СвойстваВида = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ВидКонтактнойИнформации, "ВключатьСтрануВПредставление, ХранитьИсториюИзменений, Ссылка");
	СсылкаНаОбъект = ОписаниеОбъекта.ПроблемныйОбъект;
	ЕстьДействуетС = СсылкаНаОбъект.Метаданные().ТабличныеЧасти.КонтактнаяИнформация.Реквизиты.Найти("ДействуетС") <> Неопределено;
	
	НачатьТранзакцию();
	Попытка
		
		БлокировкаДанных = Новый БлокировкаДанных;
		ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(СсылкаНаОбъект.Метаданные().ПолноеИмя());
		ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", СсылкаНаОбъект);
		БлокировкаДанных.Заблокировать();
		
		ОбъектКИ = СсылкаНаОбъект.ПолучитьОбъект(); // СправочникОбъект, ДокументОбъект
		Если ОбъектКИ = Неопределено Тогда 
			ЗафиксироватьТранзакцию();
			Возврат ОбъектБылИсправлен;
		КонецЕсли;
		ЗаблокироватьДанныеДляРедактирования(СсылкаНаОбъект);
		
		Отбор = Новый Структура("Вид", ВидКонтактнойИнформации); 
		НайденныеСтроки = ОбъектКИ.КонтактнаяИнформация.НайтиСтроки(Отбор);
		
		Если НайденныеСтроки.Количество() > 0 Тогда
			
			ЗаписыватьОбъект = Ложь;
			
			Для каждого СтрокаКонтактнойИнформации Из НайденныеСтроки Цикл
				АдресБылИзменен = Ложь;
					
					Если ПустаяСтрока(СтрокаКонтактнойИнформации.Значение) Тогда
						Если ПустаяСтрока(СтрокаКонтактнойИнформации.ЗначенияПолей) Тогда
							Продолжить;
						Иначе
							АдресВJSON = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияВJSON(СтрокаКонтактнойИнформации.ЗначенияПолей, ВидКонтактнойИнформации);
						КонецЕсли;
					Иначе 
						АдресВJSON =  СтрокаКонтактнойИнформации.Значение;
					КонецЕсли;
					
					АдресПоПолям = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(АдресВJSON, Перечисления.ТипыКонтактнойИнформации.Адрес);
					Для каждого ПоляСтроений Из АдресПоПолям.buildings Цикл
						Если СтрСравнить(ПоляСтроений.type, "Литер") = 0 Тогда
							ПоляСтроений.type             = "Литера";
							АдресБылИзменен               = Истина;
							
						КонецЕсли;
					КонецЦикла;
					
					Если АдресБылИзменен Тогда
						
						ЗаменитьАдресНаАктуальный(ОбъектКИ, СтрокаКонтактнойИнформации, АдресПоПолям, СвойстваВида, ЕстьДействуетС);
						ЗаписыватьОбъект = Истина;
						
					КонецЕсли;
				
			КонецЦикла;
			
			Если ЗаписыватьОбъект Тогда
				ОбъектКИ.Записать();
				ОбъектБылИсправлен = Истина;
			КонецЕсли;
			
		КонецЕсли;
		
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ЗаписьЖурналаРегистрации(УправлениеКонтактнойИнформациейСлужебный.СобытиеЖурналаРегистрации(),
		УровеньЖурналаРегистрации.Ошибка,,, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		ВызватьИсключение;
	КонецПопытки;
	
	Возврат ОбъектБылИсправлен;
	
КонецФункции

// Исправление некорректных адреса

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

Функция ИсправитьПорциюНекорректныхАдресовКонтактнойИнформации(Знач ПроблемныеОбъекты, Проверка, ВидПроверки)
	
	РезультатыИсправления = Новый Структура();
	РезультатыИсправления.Вставить("ИсправленоАдресов",   0);
	РезультатыИсправления.Вставить("ИсправленоЭлементов", 0);
	
	Если ПроблемныеОбъекты.Количество() = 0 Тогда
		Возврат РезультатыИсправления;
	КонецЕсли;
	
	ПолноеИмяОбъектаСКонтактнойИнформацией = ПроблемныеОбъекты[0].ПроблемныйОбъект.Метаданные().ПолноеИмя();
	
	ТекстЗапроса = "ВЫБРАТЬ
	|	ПроблемныеОбъекты.ПроблемныйОбъект КАК Ссылка
	|ПОМЕСТИТЬ ПроблемныеОбъекты
	|ИЗ
	|	&ПроблемныеОбъекты КАК ПроблемныеОбъекты
	|
	|ИНДЕКСИРОВАТЬ ПО
	|	ПроблемныеОбъекты.ПроблемныйОбъект
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ПроблемныеОбъекты.Ссылка КАК Ссылка,
	|	КонтактнаяИнформация.ЗначенияПолей КАК ЗначенияПолей,
	|	КонтактнаяИнформация.Вид КАК Вид,
	|	КонтактнаяИнформация.Значение КАК Значение,
	|	КонтактнаяИнформация.Представление КАК Представление,
	|	КонтактнаяИнформация.НомерСтроки КАК НомерСтроки
	|ИЗ
	|	ПроблемныеОбъекты КАК ПроблемныеОбъекты
	|		ЛЕВОЕ СОЕДИНЕНИЕ #ПолноеИмяОбъектаСКонтактнойИнформацией КАК КонтактнаяИнформация
	|		ПО ПроблемныеОбъекты.Ссылка = КонтактнаяИнформация.Ссылка
	|ГДЕ
	|	КонтактнаяИнформация.Тип = &Тип
	|	
	|	УПОРЯДОЧИТЬ ПО Ссылка";
	
	Запрос = Новый Запрос;
	Запрос.Текст = СтрЗаменить(ТекстЗапроса, "#ПолноеИмяОбъектаСКонтактнойИнформацией",
		ПолноеИмяОбъектаСКонтактнойИнформацией + ".КонтактнаяИнформация");
		
	ПроблемныеОбъекты.Свернуть("ПроблемныйОбъект");
	
	Запрос.Параметры.Вставить("ПроблемныеОбъекты", ПроблемныеОбъекты);
	Запрос.Параметры.Вставить("Тип", Перечисления.ТипыКонтактнойИнформации.Адрес);
	
	РезультатЗапроса = Запрос.Выполнить();
	
	Если РезультатЗапроса.Пустой() Тогда
		Возврат РезультатыИсправления;
	КонецЕсли;
	
	ТаблицаАдресов = Новый ТаблицаЗначений;
	ТаблицаАдресов.Колонки.Добавить("Ссылка");
	ТаблицаАдресов.Колонки.Добавить("Представление", ОбщегоНазначения.ОписаниеТипаСтрока(1000));
	ТаблицаАдресов.Колонки.Добавить("Результат");
	ТаблицаАдресов.Колонки.Добавить("УникальныйНомер",     ОбщегоНазначения.ОписаниеТипаЧисло(10));
	ТаблицаАдресов.Колонки.Добавить("НомерСтроки", ОбщегоНазначения.ОписаниеТипаЧисло(10));

	ТаблицаАдресов.Индексы.Добавить("Ссылка");
	
	УникальныйНомер = 1;
	АдресаДляПроверки = Новый Соответствие;
	ГруппировкаПоОбъекту = Новый Соответствие;
	ВидыКонтактнойИнформации = Новый Массив;
	
	СтрокаЗапроса = РезультатЗапроса.Выбрать();
	
	Пока СтрокаЗапроса.Следующий() Цикл
		
		АдресВJSON = СтрокаЗапроса.Значение;
		Если ПустаяСтрока(АдресВJSON) Тогда
			АдресВJSON = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияВJSON(СтрокаЗапроса.ЗначенияПолей, СтрокаЗапроса.Вид);
		КонецЕсли;
		
		РезультатИсправления = ИсправитьНекорректныеПоляАдресаКонтактнойИнформации(АдресВJSON, СтрокаЗапроса.Вид);
		
		НоваяСтрока = ТаблицаАдресов.Добавить();
		ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаЗапроса, "Ссылка, Представление, НомерСтроки");
		НоваяСтрока.Результат       = РезультатИсправления;
		НоваяСтрока.УникальныйНомер = УникальныйНомер;
		АдресаДляПроверки.Вставить(УникальныйНомер, РезультатИсправления.Адрес);
		
		ГруппировкаПоОбъекту.Вставить(СтрокаЗапроса.Ссылка, Истина); 
		
		Если ВидыКонтактнойИнформации.Найти(СтрокаЗапроса.Вид) = Неопределено Тогда
			ВидыКонтактнойИнформации.Добавить(СтрокаЗапроса.Вид);
		КонецЕсли;
		
		УникальныйНомер = УникальныйНомер + 1;
		
	КонецЦикла;
	
	РезультатАнализа = Новый Соответствие;
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.АдресныйКлассификатор") Тогда
		
		МодульАдресныйКлассификаторСлужебный = ОбщегоНазначения.ОбщийМодуль("АдресныйКлассификаторСлужебный");
		РезультатАнализа = МодульАдресныйКлассификаторСлужебный.АнализАдресовПоКлассификатору(АдресаДляПроверки, Истина);
		
	КонецЕсли;
	
	СвойстваВидовКИ = ОбщегоНазначения.ЗначенияРеквизитовОбъектов(ВидыКонтактнойИнформации, "ВключатьСтрануВПредставление, ХранитьИсториюИзменений, Ссылка");
	
	Для каждого ДанныеОбъекта Из ГруппировкаПоОбъекту Цикл 
		
		СсылкаНаОбъект = ДанныеОбъекта.Ключ;
		
		ТребуетсяЗаписьОбъекта = Ложь;
		ЕстьДействуетС = СсылкаНаОбъект.Метаданные().ТабличныеЧасти.КонтактнаяИнформация.Реквизиты.Найти("ДействуетС") <> Неопределено;
		
		НачатьТранзакцию();
		
		Попытка
			
			БлокировкаДанных = Новый БлокировкаДанных;
			ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(ПолноеИмяОбъектаСКонтактнойИнформацией);
			ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", СсылкаНаОбъект);
			БлокировкаДанных.Заблокировать();
			
			ОбъектКИ = СсылкаНаОбъект.ПолучитьОбъект();
			Если ОбъектКИ = Неопределено Тогда
				ЗафиксироватьТранзакцию();
				Продолжить;
			КонецЕсли;
			
			АдресаОбъекта = ТаблицаАдресов.НайтиСтроки(Новый Структура("Ссылка", СсылкаНаОбъект));
			Для Каждого АдресОбъекта Из АдресаОбъекта Цикл
				
				СтрокиВидаКИ = ОбъектКИ.КонтактнаяИнформация.Найти(АдресОбъекта.НомерСтроки, "НомерСтроки");
				СвойстваВидаКИ = СвойстваВидовКИ[СтрокиВидаКИ.Вид];
				
				Если СтрокиВидаКИ <> Неопределено Тогда
					
					АдресПоПолям = Неопределено;
					
					РезультатПроверки = РезультатАнализа[АдресОбъекта.УникальныйНомер];
					
					ЗаменаУстаревшего = Ложь;
					
					Если РезультатПроверки <> Неопределено И Не РезультатПроверки.АдресКорректный Тогда
						
						Если РезультатПроверки.Варианты.Количество() > 0 Тогда
							АдресПоПолям = РезультатПроверки.Варианты[0];
						КонецЕсли;
						
						ЗаменаУстаревшего = РезультатПроверки.АдресУстарел;
						
					ИначеЕсли АдресОбъекта.Результат.Изменен Тогда
						
						АдресПоПолям = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(
							АдресОбъекта.Результат.Адрес, Перечисления.ТипыКонтактнойИнформации.Адрес);
						
					КонецЕсли;
					
					Если АдресПоПолям <> Неопределено Тогда
						ЗаменитьАдресНаАктуальный(ОбъектКИ, СтрокиВидаКИ, АдресПоПолям, СвойстваВидаКИ, ЕстьДействуетС, ЗаменаУстаревшего);
						РезультатыИсправления.ИсправленоАдресов = РезультатыИсправления.ИсправленоАдресов + 1;
						ТребуетсяЗаписьОбъекта = Истина;
					КонецЕсли;
				КонецЕсли;
			КонецЦикла;
			
			Если ТребуетсяЗаписьОбъекта Тогда
				ОбновлениеИнформационнойБазы.ЗаписатьДанные(ОбъектКИ);
				РезультатыИсправления.ИсправленоЭлементов = РезультатыИсправления.ИсправленоЭлементов + 1;
				Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.КонтрольВеденияУчета") Тогда
					МодульКонтрольВеденияУчета = ОбщегоНазначения.ОбщийМодуль("КонтрольВеденияУчета");
					МодульКонтрольВеденияУчета.ОчиститьРезультатПоВидуПроверки(СсылкаНаОбъект, ВидПроверки);
				КонецЕсли;

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

// Параметры:
//  АдресВJSON - Строка
//  Вид - СправочникСсылка.ВидыКонтактнойИнформации
// 
// Возвращаемое значение:
//  Структура:
//   * Адрес      - Строка
//   * Изменен    - Булево
//   * Корректный - Булево
//
Функция ИсправитьНекорректныеПоляАдресаКонтактнойИнформации(АдресВJSON, Вид)
	
	Результат = Новый Структура;
	Результат.Вставить("Адрес", АдресВJSON);
	Результат.Вставить("Изменен", Ложь);
	Результат.Вставить("Корректный", Истина); 
	
	Адрес = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(АдресВJSON, Перечисления.ТипыКонтактнойИнформации.Адрес);
	
	Если Не Адрес.Свойство("Area") Или ПустаяСтрока(Адрес.Area) Тогда
		Результат.Корректный = Ложь;
		Возврат Результат;
	КонецЕсли;
	
	Регион = СокрЛП(Адрес.area);
	ВключатьСтрануВПредставление = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Вид, "ВключатьСтрануВПредставление");
	
	Если ЗначениеЗаполнено(Адрес.areaType) Тогда
		Если СтрСравнить(Адрес.areaType, "обл.") = 0 
			Или СтрСравнить(Адрес.areaType, "г.") = 0  Тогда
			Адрес.areaType = СтрЗаменить(Адрес.areaType, ".", "");
			ОбновитьПредставлениеАдреса(Адрес, ВключатьСтрануВПредставление);
			Результат.Изменен = Истина;
		ИначеЕсли СтрСравнить(Регион, "Чувашская Республика") = 0 Тогда
			// АПК: 1297-выкл Данные адресного классификатора, не локализуются
			Адрес.area = "Чувашская Республика -";
			// АПК: 1297-вкл
			Адрес.areaType = "Чувашия";
			ОбновитьПредставлениеАдреса(Адрес, ВключатьСтрануВПредставление);
			Результат.Изменен = Истина; 
		ИначеЕсли СтрСравнить(СокрЛП(Адрес.areaType), "ОБЛАСТЬ") = 0 Тогда
			Адрес.areaType = "обл";
			ОбновитьПредставлениеАдреса(Адрес, ВключатьСтрануВПредставление);
			Результат.Изменен = Истина;
		КонецЕсли;
		
	Иначе
		
		Если СтрНачинаетсяС(ВРег(Регион), "Г.") Тогда
			Адрес.Вставить("areaType", "г");
			Адрес.area = Сред(Регион, 3);
			ОбновитьПредставлениеАдреса(Адрес, ВключатьСтрануВПредставление);
			Результат.Изменен = Истина;
		ИначеЕсли СтрЗаканчиваетсяНа(ВРег(Регион), "ОБЛАСТЬ") Тогда
			Адрес.Вставить("areaType", "обл");
			Адрес.area = СокрЛП(Сред(Регион, 1, СтрДлина(Регион) - СтрДлина("ОБЛАСТЬ")));
			ОбновитьПредставлениеАдреса(Адрес, ВключатьСтрануВПредставление);
			Результат.Изменен = Истина;
		ИначеЕсли СтрНачинаетсяС(ВРег(Регион), "РЕСПУБЛИКА") Тогда
			Адрес.area = СокрЛП(Сред(Регион, СтрДлина("РЕСПУБЛИКА")));
			Адрес.Вставить("areaType", "Респ");
			ОбновитьПредставлениеАдреса(Адрес, ВключатьСтрануВПредставление);
			Результат.Изменен = Истина;
		КонецЕсли;
	КонецЕсли;
	
	Результат.Адрес = УправлениеКонтактнойИнформациейСлужебный.СтруктураВСтрокуJSON(Адрес);
	
	Возврат Результат;
	
КонецФункции

// Устаревшие адреса

// Исправление устаревших адресов на актуальные
//
// Параметры:
//   Проверка            - СправочникСсылка.ПравилаПроверкиУчета - исполняемая проверка.
//   ПараметрыПроверки   - см. КонтрольВеденияУчета.ОписаниеПроблемы.ПараметрыПроверки
//
Процедура ИсправитьУстаревшиеАдресаВФоне(Знач ПараметрыПроверки, АдресХранилища = Неопределено) Экспорт
	
	Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.КонтрольВеденияУчета") Тогда
		Возврат;
	КонецЕсли;
	
	МодульКонтрольВеденияУчета = ОбщегоНазначения.ОбщийМодуль("КонтрольВеденияУчета");
	Проверка = МодульКонтрольВеденияУчета.ПроверкаПоИдентификатору(ПараметрыПроверки.ИдентификаторПроверки);
	
	ВидПроверки = ПараметрыПроверки.ВидПроверки;
	Если Не ЗначениеЗаполнено(Проверка) Тогда
		Возврат;
	КонецЕсли;
	
	ПроблемныеОбъекты = МодульКонтрольВеденияУчета.ПроблемныеОбъектыПоВидуПроверки(ВидПроверки);
	ВсегоОбъектов      = 0;
	ИсправленоОбъектов = 0;

	Пока ПроблемныеОбъекты.Количество() > 0 Цикл
		
		ПоследнийПроблемныйОбъект = ПроблемныеОбъекты.Получить(ПроблемныеОбъекты.Количество() - 1).ПроблемныйОбъект;
		ВсегоОбъектов = ВсегоОбъектов + ПроблемныеОбъекты.Количество();
		//@skip-check query-in-loop - Порционное исправление некорректны адресов (контроль ведения учета).
		ИсправленоОбъектов = ИсправленоОбъектов + ИсправитьПорциюУстаревшихАдресовКонтактнойИнформации(ПроблемныеОбъекты, Проверка, ВидПроверки);
		ПроблемныеОбъекты = МодульКонтрольВеденияУчета.ПроблемныеОбъектыПоВидуПроверки(ВидПроверки, ПоследнийПроблемныйОбъект);
		
	КонецЦикла;
	Результат = Новый Структура;
	Результат.Вставить("ВсегоЭлементов", ВсегоОбъектов);
	Результат.Вставить("ИсправленоЭлементов", ИсправленоОбъектов);
	
	ПоместитьВоВременноеХранилище(Результат, АдресХранилища);
	
КонецПроцедуры

Процедура ВыявитьУстаревшиеАдреса(Проверка, ПараметрыПроверки) Экспорт
	
	Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.АдресныйКлассификатор") Тогда
		Возврат;
	КонецЕсли;
	
	Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.КонтрольВеденияУчета") Тогда
		Возврат;
	КонецЕсли;
	
	МодульКонтрольВеденияУчета = ОбщегоНазначения.ОбщийМодуль("КонтрольВеденияУчета");
	МодульАдресныйКлассификаторСлужебный = ОбщегоНазначения.ОбщийМодуль("АдресныйКлассификаторСлужебный");
	
	РезультатЗапросаСАдресами = АдресаКонтактнойИнформации();
	
	Если РезультатЗапросаСАдресами.Пустой() Тогда
		Возврат;
	КонецЕсли;
	
	СтрокаСАдресом = РезультатЗапросаСАдресами.Выбрать();
	
	ПорцияАдресов             = Новый Соответствие;
	Проверки                  = Новый Соответствие;
	СоответствиеАдресаИСсылки = Новый Соответствие;
	Счетчик                   = 1;
	
	Пока СтрокаСАдресом.Следующий() Цикл
		
		Если Проверки[СтрокаСАдресом.Вид] = Неопределено Тогда
		
			ПараметрыВыполненияПроверки = МодульКонтрольВеденияУчета.ПараметрыВыполненияПроверки(НСтр("ru='Адреса контактной информации'", ОбщегоНазначения.КодОсновногоЯзыка()), СтрокаСАдресом.Вид);
			МодульКонтрольВеденияУчета.ОчиститьРезультатыПредыдущихПроверок(Проверка, ПараметрыВыполненияПроверки);
			ВидПроверки = МодульКонтрольВеденияУчета.ВидПроверки(ПараметрыВыполненияПроверки);
			
			Проверки.Вставить(СтрокаСАдресом.Вид, ВидПроверки);
		
		КонецЕсли;
		
		АдресВJSON = СтрокаСАдресом.Значение;
		Если ПустаяСтрока(АдресВJSON) Тогда
			АдресВJSON = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияВJSON(СтрокаСАдресом.ЗначенияПолей, СтрокаСАдресом.Вид);
		КонецЕсли;
		
		ПорцияАдресов.Вставить(Счетчик, АдресВJSON);
		ОписаниеОбъекта = ОписаниеОбъекта();
		ЗаполнитьЗначенияСвойств(ОписаниеОбъекта, СтрокаСАдресом);
		
		СоответствиеАдресаИСсылки.Вставить(Счетчик, ОписаниеОбъекта);
		Если Счетчик = 100 Тогда
			Результат = МодульАдресныйКлассификаторСлужебный.АнализАдресовПоКлассификатору(ПорцияАдресов, Истина);
			ОбработкаУстаревшегоАдресаПослеПроверки(Результат, СоответствиеАдресаИСсылки, ПараметрыПроверки, Проверки);
			ПорцияАдресов             = Новый Соответствие;
			СоответствиеАдресаИСсылки = Новый Соответствие;
			Счетчик = 1;
		Иначе
			Счетчик = Счетчик + 1;
		КонецЕсли;
	КонецЦикла;
	
	// последняя порция
	Если ПорцияАдресов.Количество() > 0 Тогда
		Результат = МодульАдресныйКлассификаторСлужебный.АнализАдресовПоКлассификатору(ПорцияАдресов, Истина);
	КонецЕсли;
	
	Если Результат <> Неопределено Тогда
		ОбработкаУстаревшегоАдресаПослеПроверки(Результат, СоответствиеАдресаИСсылки, ПараметрыПроверки, Проверки);
	КонецЕсли;
	
КонецПроцедуры

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

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

Процедура ЗаменитьАдресНаАктуальный(ОбъектКИ, СтрокаВидаКИ, АдресПоПолям, СвойстваВида, ЕстьДействуетС, ЗаменаУстаревшего = Истина)
	
	НовоеПредставление = РаботаСАдресамиКлиентСервер.ПредставлениеАдреса(АдресПоПолям, СвойстваВида.ВключатьСтрануВПредставление);
	АдресПоПолям.value = НовоеПредставление;
	НовыйАдресВJSON = УправлениеКонтактнойИнформациейСлужебный.СтруктураВСтрокуJSON(АдресПоПолям);
	
	Если ЗаменаУстаревшего Тогда
		ТекстКомментария = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru='Адрес ""%1"" устарел и был переименован в ""%2""'"),
			СтрокаВидаКИ.Представление, НовоеПредставление);
	Иначе
		ТекстКомментария = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru='Адрес ""%1"" был изменен автоматически на ""%2""'"),
			СтрокаВидаКИ.Представление, НовоеПредставление);
	КонецЕсли;
		
	Если ЗначениеЗаполнено(АдресПоПолям.comment) Тогда
		ТекстКомментария = АдресПоПолям.comment + Символы.ПС + ТекстКомментария;
	КонецЕсли;
	
	УправлениеКонтактнойИнформацией.УстановитьКомментарийКонтактнойИнформации(НовыйАдресВJSON, ТекстКомментария);
	
	Если СвойстваВида.ХранитьИсториюИзменений И ЕстьДействуетС Тогда
		УправлениеКонтактнойИнформацией.ДобавитьКонтактнуюИнформацию(ОбъектКИ, НовыйАдресВJSON, СвойстваВида.Ссылка, ТекущаяДатаСеанса(), Ложь);
	Иначе
		
		СтрокаВидаКИ.Значение      = НовыйАдресВJSON;
		СтрокаВидаКИ.Представление = НовоеПредставление;
		СтрокаВидаКИ.ЗначенияПолей = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияВXML(НовыйАдресВJSON);
		
		УправлениеКонтактнойИнформациейСлужебный.ЗаполнитьТехническиеПоляКонтактнойИнформации(СтрокаВидаКИ,
			АдресПоПолям, Перечисления.ТипыКонтактнойИнформации.Адрес);
		
	КонецЕсли;

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

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

// Проверка адресов на соответствие адресному классификатору.
//
// Параметры:
//   Проверка            - СправочникСсылка.ПравилаПроверкиУчета - исполняемая проверка;
//   ПараметрыПроверки   - см. КонтрольВеденияУчета.ОписаниеПроблемы.ПараметрыПроверки
//
Процедура ПроверитьАдресаНаСоответствиеАдресномуКлассификатору(Проверка, ПараметрыПроверки) Экспорт

	Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.АдресныйКлассификатор") Тогда
		Возврат;
	КонецЕсли;
	
	Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.КонтрольВеденияУчета") Тогда
		Возврат;
	КонецЕсли;
	
	МодульАдресныйКлассификаторСлужебный = ОбщегоНазначения.ОбщийМодуль("АдресныйКлассификаторСлужебный");
	МодульКонтрольВеденияУчета = ОбщегоНазначения.ОбщийМодуль("КонтрольВеденияУчета");
	
	РезультатЗапросаСАдресами = АдресаКонтактнойИнформации();
	
	Если РезультатЗапросаСАдресами.Пустой() Тогда
		Возврат;
	КонецЕсли;
	
	СтрокаСАдресом = РезультатЗапросаСАдресами.Выбрать();
	
	ПорцияАдресов             = Новый Соответствие;
	Проверки                  = Новый Соответствие;
	СоответствиеАдресаИСсылки = Новый Соответствие;
	УникальныйНомер                   = 1;
	
	ОписаниеОбъекта = ОписаниеОбъекта();
	
	Пока СтрокаСАдресом.Следующий() Цикл
		
		Если Проверки[СтрокаСАдресом.ИмяОбъекта] = Неопределено Тогда
		
			ПараметрыВыполненияПроверки = МодульКонтрольВеденияУчета.ПараметрыВыполненияПроверки(НСтр("ru = 'Адреса контактной информации'", ОбщегоНазначения.КодОсновногоЯзыка()), СтрокаСАдресом.ИмяОбъекта);
			МодульКонтрольВеденияУчета.ОчиститьРезультатыПредыдущихПроверок(Проверка, ПараметрыВыполненияПроверки);
			ВидПроверки = МодульКонтрольВеденияУчета.ВидПроверки(ПараметрыВыполненияПроверки);
			
			Проверки.Вставить(СтрокаСАдресом.ИмяОбъекта, ВидПроверки);
		
		КонецЕсли;
		
		АдресВJSON = СтрокаСАдресом.Значение;
		Если ПустаяСтрока(АдресВJSON) Тогда
			АдресВJSON = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияВJSON(СтрокаСАдресом.ЗначенияПолей, СтрокаСАдресом.Вид);
		КонецЕсли;
		
		ПорцияАдресов.Вставить(УникальныйНомер, АдресВJSON);
		ОписаниеОбъекта = ОписаниеОбъекта();
		ЗаполнитьЗначенияСвойств(ОписаниеОбъекта, СтрокаСАдресом);
		
		СоответствиеАдресаИСсылки.Вставить(УникальныйНомер, ОписаниеОбъекта);
		Если УникальныйНомер = 100 Тогда
			Результат = МодульАдресныйКлассификаторСлужебный.АнализАдресовПоКлассификатору(ПорцияАдресов, Истина);
			ОбработкаАдресаПослеПроверки(Результат, СоответствиеАдресаИСсылки, Проверка, ПараметрыПроверки, Проверки);
			ПорцияАдресов = Новый Соответствие;
			СоответствиеАдресаИСсылки = Новый Соответствие;
			УникальныйНомер = 1;
		Иначе
			УникальныйНомер = УникальныйНомер + 1;
		КонецЕсли;
	КонецЦикла;
	
	// последняя порция
	Если ПорцияАдресов.Количество() > 0 Тогда
		Результат = МодульАдресныйКлассификаторСлужебный.АнализАдресовПоКлассификатору(ПорцияАдресов, Истина);
	КонецЕсли;
	
	Если Результат <> Неопределено Тогда
		ОбработкаАдресаПослеПроверки(Результат, СоответствиеАдресаИСсылки, Проверка, ПараметрыПроверки, Проверки);
	КонецЕсли;
	
КонецПроцедуры

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

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

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

	Для каждого КлючЗначение  Из ПроверенныеАдреса Цикл
		ПроверенныйАдрес  = КлючЗначение.Значение;
		Если ПроверенныйАдрес.АдресКорректный Тогда
			Продолжить;
		КонецЕсли;
		
		ОписаниеАдреса = СоответствиеАдресаИСсылки[КлючЗначение.Ключ];
		ВидПроверки = Проверки[ОписаниеАдреса.ИмяОбъекта];
			
		Если ПроверенныйАдрес.Ошибки.Количество() > 0 Тогда
			
			Если ЗначениеЗаполнено(ОписаниеАдреса.Представление) Тогда
				УточнениеПроблемы = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = '%1 ""%2"" не соответствует адресному классификатору, по причине: %3'"), 
					Строка(ОписаниеАдреса.Вид), ОписаниеАдреса.Представление, ПроверенныйАдрес.Ошибки[0].Текст);
			Иначе
				УточнениеПроблемы = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = '%1 не соответствует адресному классификатору, по причине: %2'"), 
					Строка(ОписаниеАдреса.Вид), ПроверенныйАдрес.Ошибки[0].Текст);
			КонецЕсли;
	
		Иначе
			УточнениеПроблемы = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = '%1 ""%2"" не соответствует адресному классификатору'"), Строка(ОписаниеАдреса.Вид), ОписаниеАдреса.Представление);
		КонецЕсли;
		
		Проблема = МодульКонтрольВеденияУчета.ОписаниеПроблемы(ОписаниеАдреса.Ссылка, ПараметрыПроверки);
		Проблема.ВидПроверки = ВидПроверки;
		Проблема.УточнениеПроблемы = УточнениеПроблемы; 
		
		МодульКонтрольВеденияУчета.ЗаписатьПроблему(Проблема, ПараметрыПроверки);
		
	КонецЦикла;
	
КонецПроцедуры

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

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

// Автоматическая замена адресов.

Процедура УстановитьСостояниеРегламентногоЗадания(Знач Статус) Экспорт
	
	Если Статус = Неопределено Тогда
		
		Запрос = Новый Запрос;
		Запрос.Текст = 
			"ВЫБРАТЬ ПЕРВЫЕ 1
			|	ВидыКонтактнойИнформации.Ссылка КАК Ссылка
			|ИЗ
			|	Справочник.ВидыКонтактнойИнформации КАК ВидыКонтактнойИнформации
			|ГДЕ
			|	ВидыКонтактнойИнформации.ИсправлятьУстаревшиеАдреса = ИСТИНА";
		
		РезультатЗапроса = Запрос.Выполнить();
		Статус = Не РезультатЗапроса.Пустой();
		
	КонецЕсли;
	
	УстановитьПривилегированныйРежим(Истина);
	
	ПараметрыПоиска = Новый Структура;
	ПараметрыПоиска.Вставить("Метаданные", Метаданные.РегламентныеЗадания.ИсправлениеУстаревшихАдресов);
	СписокЗаданий = РегламентныеЗаданияСервер.НайтиЗадания(ПараметрыПоиска);
	
	ПараметрыЗадания = Новый Структура("Использование", Статус);
	Для Каждого Задание Из СписокЗаданий Цикл
		РегламентныеЗаданияСервер.ИзменитьЗадание(Задание, ПараметрыЗадания);
	КонецЦикла;
	
КонецПроцедуры

Процедура ВыявитьИИсправитьУстаревшиеАдреса() Экспорт
	
	Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.АдресныйКлассификатор") Тогда
		Возврат;
	КонецЕсли;
	
	МодульАдресныйКлассификаторСлужебный = ОбщегоНазначения.ОбщийМодуль("АдресныйКлассификаторСлужебный");
	
	ОбъектыДляПроверки = ОбъектыСАвтоматическимИсправлениемАдресов();
	Запрос = Новый Запрос;
	ШаблонЗапроса = "ВЫБРАТЬ ПЕРВЫЕ 1000
	|	КонтактнаяИнформация.Ссылка КАК Ссылка,
	|	КонтактнаяИнформация.ЗначенияПолей КАК ЗначенияПолей,
	|	КонтактнаяИнформация.Значение КАК Значение,
	|	КонтактнаяИнформация.Вид КАК Вид,
	|	КонтактнаяИнформация.Представление КАК Представление
	|ПОМЕСТИТЬ Адреса
	|ИЗ
	|	&ПолноеИмяОбъектаСКонтактнойИнформацией КАК КонтактнаяИнформация
	|ГДЕ
	|	КонтактнаяИнформация.Ссылка > &Ссылка
	|	И КонтактнаяИнформация.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Адрес)
	|
	|УПОРЯДОЧИТЬ ПО
	|	Ссылка
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	Адреса.Ссылка КАК Ссылка,
	|	Адреса.ЗначенияПолей КАК ЗначенияПолей,
	|	Адреса.Значение КАК Значение,
	|	Адреса.Вид КАК Вид,
	|	Адреса.Представление КАК Представление
	|ИЗ
	|	Адреса КАК Адреса
	|ГДЕ
	|	Адреса.Вид В (&Виды)";
	
	ПорцияАдресов             = Новый Соответствие;
	СоответствиеАдресаИСсылки = Новый Соответствие;
	УникальныйКлючАдреса      = 1;
	
	Для каждого ОбъектДляПроверки Из ОбъектыДляПроверки Цикл
		ОбъектыМетаданных = ОбъектДляПроверки.Ключ.Метаданные();
		ПоследнийОбъект = Неопределено;
		
		ПереборОбъектов  = Истина;
		Пока ПереборОбъектов Цикл
			ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "&ПолноеИмяОбъектаСКонтактнойИнформацией", 
			ОбъектыМетаданных.ПолноеИмя() + ".КонтактнаяИнформация");
			Запрос.Текст = ТекстЗапроса;
			
			Запрос.УстановитьПараметр("Виды", ОбъектДляПроверки.Значение);
			Запрос.УстановитьПараметр("Ссылка", ПоследнийОбъект);
			//@skip-check query-in-loop - Порционное исправление некорректны адресов (контроль ведения учета).
			РезультатЗапроса = Запрос.Выполнить();
			
			Если РезультатЗапроса.Пустой() Тогда
				ПереборОбъектов = Ложь;
				Прервать;
			КонецЕсли;
			
			СтрокаСАдресом = РезультатЗапроса.Выбрать();
			
			Пока СтрокаСАдресом.Следующий() Цикл
				
				ПоследнийОбъект = СтрокаСАдресом.Ссылка;
				
				АдресВJSON = СтрокаСАдресом.Значение;
				Если ПустаяСтрока(АдресВJSON) Тогда
					АдресВJSON = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияВJSON(СтрокаСАдресом.ЗначенияПолей, СтрокаСАдресом.Вид);
				КонецЕсли;
				
				ПорцияАдресов.Вставить(УникальныйКлючАдреса, АдресВJSON);
				ОписаниеОбъекта = ОписаниеОбъекта();
				ЗаполнитьЗначенияСвойств(ОписаниеОбъекта, СтрокаСАдресом);
				
				СоответствиеАдресаИСсылки.Вставить(УникальныйКлючАдреса, ОписаниеОбъекта);
				
				Если УникальныйКлючАдреса = 100 Тогда
					Адреса = МодульАдресныйКлассификаторСлужебный.АнализАдресовПоКлассификатору(ПорцияАдресов, Истина);
					ИсправитьУстаревшиеАдресаПослеПроверкиАвто(Адреса, СоответствиеАдресаИСсылки);
					ПорцияАдресов             = Новый Соответствие;
					СоответствиеАдресаИСсылки = Новый Соответствие;
					УникальныйКлючАдреса = 1;
				Иначе
					УникальныйКлючАдреса = УникальныйКлючАдреса + 1;
				КонецЕсли;
				
			КонецЦикла;
			
		КонецЦикла;
		
	КонецЦикла;
	
	Адреса = МодульАдресныйКлассификаторСлужебный.АнализАдресовПоКлассификатору(ПорцияАдресов, Истина);
	ИсправитьУстаревшиеАдресаПослеПроверкиАвто(Адреса, СоответствиеАдресаИСсылки);
	
КонецПроцедуры

Процедура ИсправитьУстаревшиеАдресаПослеПроверкиАвто(Адреса, СоответствиеАдресаИСсылки)
	
	ГруппировкаПоОбъекту = Новый Соответствие;
	Для каждого Адрес Из Адреса Цикл
		
		РезультатПроверки = Адрес.Значение; // см. АдресныйКлассификаторСлужебный.РезультатПроверкиАдреса
		Если РезультатПроверки.Варианты.Количество() > 0 Тогда
			НовыйАдрес = СоответствиеАдресаИСсылки[Адрес.Ключ];
			
			ДанныеНовогоАдреса = Новый Структура("Варианты", РезультатПроверки.Варианты);
			ДанныеНовогоАдреса.Вставить("Представление", НовыйАдрес.Представление);
			ДанныеНовогоАдреса.Вставить("Вид", НовыйАдрес.Вид);
			
			Если ГруппировкаПоОбъекту[НовыйАдрес.Ссылка] = Неопределено Тогда
				ГруппировкаПоОбъекту.Вставить(НовыйАдрес.Ссылка, ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(ДанныеНовогоАдреса));
			Иначе
				ОбъектыГруппировки = ГруппировкаПоОбъекту[НовыйАдрес.Ссылка]; // Массив
				ОбъектыГруппировки.Добавить(ДанныеНовогоАдреса);
			КонецЕсли;
		КонецЕсли;
		
	КонецЦикла;
	
	Если ГруппировкаПоОбъекту.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	
	Для каждого СтрокаТаблицы Из ГруппировкаПоОбъекту Цикл
		
		СсылкаНаОбъект = СтрокаТаблицы.Ключ;
		
		ТребуетсяЗаписьОбъекта = Ложь;
		ПолноеИмяОбъектаСКонтактнойИнформацией = СсылкаНаОбъект.Метаданные().ПолноеИмя();
		
		НачатьТранзакцию();
		
		Попытка
			
			БлокировкаДанных = Новый БлокировкаДанных;
			ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(ПолноеИмяОбъектаСКонтактнойИнформацией);
			ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", СсылкаНаОбъект);
			БлокировкаДанных.Заблокировать();
			
			ЕстьДействуетС = СсылкаНаОбъект.Метаданные().ТабличныеЧасти.КонтактнаяИнформация.Реквизиты.Найти("ДействуетС") <> Неопределено;
			
			ОбъектКИ = СсылкаНаОбъект.ПолучитьОбъект();
			Если ОбъектКИ = Неопределено Тогда
				ЗафиксироватьТранзакцию();
				Продолжить;
			КонецЕсли;
			
			Для каждого СтрокаВидаКИ Из СтрокаТаблицы.Значение Цикл // СправочникСсылка.ВидыКонтактнойИнформации
		
				СвойстваВида = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(СтрокаВидаКИ.Вид, "ВключатьСтрануВПредставление, ХранитьИсториюИзменений, Ссылка");
				
				Отбор = Новый Структура("Вид", СтрокаВидаКИ.Вид);
				АдресаОбъекта = ОбъектКИ.КонтактнаяИнформация.НайтиСтроки(Отбор);
				Для каждого АдресОбъекта Из АдресаОбъекта Цикл
					Если СтрСравнить(АдресОбъекта.Представление, СтрокаВидаКИ.Представление) = 0 Тогда
						
						ЗаменитьАдресНаАктуальный(ОбъектКИ, АдресОбъекта, СтрокаВидаКИ.Варианты[0], СвойстваВида, ЕстьДействуетС);
						ТребуетсяЗаписьОбъекта = Истина;
						
					КонецЕсли;
					
				КонецЦикла;
				
			КонецЦикла;
			
			Если ТребуетсяЗаписьОбъекта Тогда
				ОбновлениеИнформационнойБазы.ЗаписатьДанные(ОбъектКИ);
			КонецЕсли;
			ЗафиксироватьТранзакцию();
		Исключение
			
			ОтменитьТранзакцию();
			ЗаписьЖурналаРегистрации(УправлениеКонтактнойИнформациейСлужебный.СобытиеЖурналаРегистрации(), 
			УровеньЖурналаРегистрации.Ошибка,,, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
			ВызватьИсключение;
		КонецПопытки;
		
	КонецЦикла;
	
КонецПроцедуры

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

// Проверить корректность кода города и номера телефона кодов страны.
// 
// Параметры:
//  ПоляТелефона - см. УправлениеКонтактнойИнформациейКлиентСервер.СтруктураПолейТелефона
//  СписокОшибок - СписокЗначений
// 
Процедура ПроверитьКорректностьКодовСтраныИГорода(ПоляТелефона, СписокОшибок) Экспорт
	
	РаботаСАдресамиКлиентСервер.ПроверитьКорректностьКодовСтраныИГорода(ПоляТелефона, СписокОшибок);
	
КонецПроцедуры

Функция РазложитьПредставлениеАдресаПоПолям(Представление, ТекущийАдрес = Неопределено) Экспорт
	
	Адрес = РаботаСАдресамиКлиентСервер.ОписаниеНовойКонтактнойИнформации(Перечисления.ТипыКонтактнойИнформации.Адрес);
		
	ДанныеАнализа = УправлениеКонтактнойИнформациейСлужебный.ЧастиАдресаТаблицей(Представление);
	
	РазборНаОсновеТекущегоАдреса = Ложь;
	Если ТекущийАдрес <> Неопределено И ПустаяСтрока(ТекущийАдрес.city) И ПустаяСтрока(ТекущийАдрес.area) Тогда
		РазборНаОсновеТекущегоАдреса = Истина
	КонецЕсли;
		
	УправлениеКонтактнойИнформациейСлужебный.ОпределитьСтрануИИндекс(ДанныеАнализа);
	СтрокаСтраны = ДанныеАнализа.Найти(-2, "Уровень");
		
	Если СтрокаСтраны <> Неопределено Тогда
		Адрес.Country = СокрЛП(ВРег(СтрокаСтраны.Значение));
		ДанныеАнализа.Удалить(СтрокаСтраны);
	КонецЕсли;
	
	СтрокаИндекс = ДанныеАнализа.Найти(-1, "Уровень");
	Если СтрокаИндекс <> Неопределено Тогда
		Адрес.ZipCode = СокрЛП(СтрокаИндекс.Значение);
		ДанныеАнализа.Удалить(СтрокаИндекс);
	КонецЕсли;	
		
	Если РазборНаОсновеТекущегоАдреса Тогда
		НераспределенныеДанные = Новый Массив;
		РазложитьЧастиАдресаПоПолямНаОсновеТекущегоАдреса(ДанныеАнализа, Адрес, ТекущийАдрес, НераспределенныеДанные)
	Иначе
		НераспределенныеДанные = ДанныеАнализа;
	КонецЕсли;
	
	АдресныеЕдиницы = СписокАдресныхЕдиницССокращениями();
	
	ИменаУровнейАдресаПоКоду = ИменаУровнейАдресаПоКоду();
	ВариантыДанныхДом = РаботаСАдресамиПовтИсп.ВариантыДанныхДом().ВариантыТипа;
	ВариантыДанныхСтроение = РаботаСАдресамиПовтИсп.ВариантыДанныхСтроение().ВариантыТипа;
	
	РазборНаОсновеТекущегоАдреса = НераспределенныеДанные.Количество() <> ДанныеАнализа.Количество();
	
	Для Каждого ЧастьАдрес Из НераспределенныеДанные Цикл
		
		Если Не ЗначениеЗаполнено(Адрес.ZipCode) И СтрДлина(ЧастьАдрес.Значение) = 6
			И СтроковыеФункцииКлиентСервер.ТолькоЦифрыВСтроке(ЧастьАдрес.Значение) Тогда
			Адрес.ZipCode = ЧастьАдрес.Значение;
			Продолжить;
		КонецЕсли;
		
		ЗаполненУровеньУлицы = ЗначениеЗаполнено(Адрес.street);
		ПоискПоАдреснымЕдиницам = Не ЗаполненУровеньУлицы Или РазборНаОсновеТекущегоАдреса;
		
		Если ЗначениеЗаполнено(ЧастьАдрес.ТипОбъекта) Тогда
			
			ЗначениеУстановлено = Ложь;
			Если ПоискПоАдреснымЕдиницам И Не СтроковыеФункцииКлиентСервер.ТолькоЦифрыВСтроке(ЧастьАдрес.Наименование) Тогда
				Для Каждого АдреснаяЕдиница Из АдресныеЕдиницы Цикл
					Если СтрСравнить(ЧастьАдрес.ТипОбъекта, АдреснаяЕдиница.Сокращение) = 0 
						Или СтрСравнить(ЧастьАдрес.ТипОбъекта, АдреснаяЕдиница.Значение) = 0 Тогда
						
						НомерУровня = АдреснаяЕдиница.НомерУровня;
						Если АдреснаяЕдиница.Значение = "Улица" Тогда
							НомерУровня = 8;
						КонецЕсли;
						
						ИмяУровня = ИменаУровнейАдресаПоКоду.Получить(НомерУровня);
						Если ИмяУровня <> Неопределено Тогда
							Если Адрес.Свойство(ИмяУровня) И ПустаяСтрока(Адрес[ИмяУровня])Тогда
								Адрес[ИмяУровня] = ЧастьАдрес.Наименование;
								Если НомерУровня = 8 Тогда
									ЗаполненУровеньУлицы = Истина;
								КонецЕсли;
								Если Адрес.Свойство(ИмяУровня + "Type") Тогда
									Адрес[ИмяУровня + "Type"] = ЧастьАдрес.ТипОбъекта;
								КонецЕсли;
								ЗначениеУстановлено = Истина;
								Прервать;
							Иначе
								Продолжить;
							КонецЕсли;
						КонецЕсли;
					КонецЕсли;
				КонецЦикла;
			КонецЕсли;
			Если ЗначениеУстановлено Тогда
				Продолжить;
			КонецЕсли;
			
			Если ВариантыДанныхДом.Найти(ТРег(ЧастьАдрес.ТипОбъекта)) <> Неопределено Тогда
				Если ПустаяСтрока(Адрес.HouseNumber) И ПустаяСтрока(Адрес.stead) Тогда
					Адрес.HouseType = ЧастьАдрес.ТипОбъекта;
					Адрес.HouseNumber = ЧастьАдрес.Наименование;
				ИначеЕсли ВариантыДанныхСтроение.Найти(ТРег(ЧастьАдрес.ТипОбъекта)) <> Неопределено Тогда
					Адрес.buildings.Добавить(УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения(
						ЧастьАдрес.ТипОбъекта, ЧастьАдрес.Наименование));
				Иначе
					Помещение = УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения(
						ЧастьАдрес.ТипОбъекта, ЧастьАдрес.Наименование);
					Адрес.Apartments.Добавить(Помещение);
				КонецЕсли;
				Продолжить;
			ИначеЕсли СтрНайти(ЧастьАдрес.Значение, РаботаСАдресамиКлиентСервер.НаименованиеЗемельногоУчастка()) <> 0 Тогда
				ЗемельныйУчасток = СокрЛП(СтрЗаменить(ЧастьАдрес.Значение, РаботаСАдресамиКлиентСервер.НаименованиеЗемельногоУчастка(), ""));
				Если ПустаяСтрока(Адрес.stead) И ПустаяСтрока(Адрес.HouseNumber) Тогда 
					Адрес.stead = ЗемельныйУчасток;
				Иначе
					Помещение = УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения(
						РаботаСАдресамиКлиентСервер.НаименованиеЗемельногоУчастка(), ЗемельныйУчасток);
					Адрес.Apartments.Добавить(Помещение);
				КонецЕсли;
				Продолжить;
			ИначеЕсли ВариантыДанныхСтроение.Найти(ТРег(ЧастьАдрес.ТипОбъекта)) <> Неопределено Тогда
				Адрес.buildings.Добавить(УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения(
					ЧастьАдрес.ТипОбъекта, ЧастьАдрес.Наименование));
				Продолжить;
			КонецЕсли;
			
		КонецЕсли;
			
		Если ПоискПоАдреснымЕдиницам И (ПустаяСтрока(ЧастьАдрес.Наименование) 
		   Или Не СтроковыеФункцииКлиентСервер.ТолькоЦифрыВСтроке(ЧастьАдрес.Наименование)) Тогда
			Если ЗаполнитьПоляГорода(Адрес, ЧастьАдрес, ЗаполненУровеньУлицы) Тогда
				Продолжить;
			КонецЕсли;
		КонецЕсли;
		
		Если ЗначениеЗаполнено(ЧастьАдрес.ТипОбъекта) Тогда
			Помещение = УправлениеКонтактнойИнформациейКлиентСервер.ЗначениеСтроенияИлиПомещения(
				ЧастьАдрес.ТипОбъекта, ЧастьАдрес.Наименование);
			Адрес.Apartments.Добавить(Помещение);
			Продолжить;
		КонецЕсли;
		
		Адрес.street = ?(ЗначениеЗаполнено(Адрес.street), Адрес.street + " " + ЧастьАдрес.Значение, ЧастьАдрес.Значение);
		
	КонецЦикла;
	
	Возврат Адрес;
	
КонецФункции

Процедура РазложитьЧастиАдресаПоПолямНаОсновеТекущегоАдреса(ДанныеАнализа, Адрес, ТекущийАдрес, НераспределенныеДанные)
	
	Для Каждого ЧастьАдрес Из ДанныеАнализа Цикл
		ЗначениеУстановлено = Ложь;

		Если ЗначениеЗаполнено(ЧастьАдрес.ТипОбъекта) Тогда
			Если СтрНайти(ЧастьАдрес.Значение, РаботаСАдресамиКлиентСервер.НаименованиеЗемельногоУчастка()) <> 0 Тогда
				Адрес.stead = СокрЛП(СтрЗаменить(ЧастьАдрес.Значение,
					РаботаСАдресамиКлиентСервер.НаименованиеЗемельногоУчастка(), ""));
				Продолжить;
			КонецЕсли;
			Если СтрСравнить(ТекущийАдрес.HouseType, ЧастьАдрес.ТипОбъекта) = 0 Тогда
				Адрес.HouseType = ЧастьАдрес.ТипОбъекта;
				Адрес.HouseNumber = ЧастьАдрес.Наименование;
				Продолжить;
			КонецЕсли;

			Для Каждого ЭлементАдреса Из ТекущийАдрес Цикл
				Если СтрСравнить(ЭлементАдреса.Значение, ЧастьАдрес.ТипОбъекта) = 0 И СтрНайти(ЭлементАдреса.Ключ,
					"Type") <> 0 Тогда
					Адрес[ЭлементАдреса.Ключ] = ЧастьАдрес.ТипОбъекта;
					ИмяПоля = СтрЗаменить(ЭлементАдреса.Ключ, "Type", "");
					Если Адрес.Свойство(ИмяПоля) Тогда
						Адрес[ИмяПоля] = ЧастьАдрес.Наименование;
						ЗначениеУстановлено = Истина;
						Прервать;
					КонецЕсли;
				КонецЕсли;
			КонецЦикла;
			Если ЗначениеУстановлено Тогда
				Продолжить;
			КонецЕсли;

			Если ТипЗнч(ТекущийАдрес.buildings) = Тип("Массив") Тогда
				Для Каждого Строение Из ТекущийАдрес.buildings Цикл
					Если СтрСравнить(Строение.Type, ЧастьАдрес.ТипОбъекта) = 0 Тогда
						Строение.number = ЧастьАдрес.Наименование;
						ЗначениеУстановлено = Истина;
						Адрес.buildings.Добавить(Строение);
						Прервать;
					КонецЕсли;
				КонецЦикла;
				Если ЗначениеУстановлено Тогда
					Продолжить;
				КонецЕсли;
			КонецЕсли;

			Если ТипЗнч(ТекущийАдрес.Apartments) = Тип("Массив") Тогда
				Для Каждого Помещение Из ТекущийАдрес.Apartments Цикл
					Если СтрСравнить(Помещение.Type, ЧастьАдрес.ТипОбъекта) = 0 Тогда
						Помещение.number = ЧастьАдрес.Наименование;
						ЗначениеУстановлено = Истина;
						Адрес.Apartments.Добавить(Помещение);
						Прервать;
					КонецЕсли;
				КонецЦикла;
			КонецЕсли;
			Если ЗначениеУстановлено Тогда
				Продолжить;
			КонецЕсли;
		Иначе
			Для Каждого ЭлементАдреса Из ТекущийАдрес Цикл
				Если ЗначениеЗаполнено(ЧастьАдрес.Наименование) Тогда
					Если СтрСравнить(ЭлементАдреса.Значение, ЧастьАдрес.Наименование) = 0 Тогда
						Адрес[ЭлементАдреса.Ключ] = ЧастьАдрес.Наименование;
						ЗначениеУстановлено = Истина;
						Прервать;
					КонецЕсли;
				Иначе
					Если СтрСравнить(ЭлементАдреса.Значение, ЧастьАдрес.Значение) = 0 Тогда
						Адрес[ЭлементАдреса.Ключ] = ЧастьАдрес.Значение;
						ЗначениеУстановлено = Истина;
						Прервать;
					КонецЕсли;
				КонецЕсли;
			КонецЦикла;
			Если ЗначениеУстановлено Тогда
				Продолжить;
			КонецЕсли;
		КонецЕсли;
		НераспределенныеДанные.Добавить(ЧастьАдрес);
	КонецЦикла;
	
КонецПроцедуры

Функция ЗаполнитьПоляГорода(Адрес, ЧастьАдрес, ЗаполненУровеньУлицы)
	
	Если ПустаяСтрока(Адрес.area) Тогда
		Адрес.area = ЧастьАдрес.Значение;
		Возврат Истина;
	ИначеЕсли ПустаяСтрока(Адрес.district) Тогда
		Адрес.district = ЧастьАдрес.Значение;
		Возврат Истина;
	ИначеЕсли ПустаяСтрока(Адрес.city) Тогда
		Адрес.city = ЧастьАдрес.Значение;
		Возврат Истина;
	ИначеЕсли ПустаяСтрока(Адрес.locality) Тогда
		Адрес.locality = ЧастьАдрес.Значение;
		Возврат Истина;
	ИначеЕсли ПустаяСтрока(Адрес.street) Тогда
		Адрес.street = ЧастьАдрес.Значение;
		ЗаполненУровеньУлицы = Истина;
		Возврат Истина;
	КонецЕсли;
	
	Возврат Ложь;
	
КонецФункции

Функция ИменаУровнейАдресаПоКоду()
	
	Уровни = Новый Соответствие;
	
	Уровни.Вставить(1, "area");
	Уровни.Вставить(2, "district");
	Уровни.Вставить(3, "munDistrict");
	Уровни.Вставить(4, "settlement");
	Уровни.Вставить(5, "city");
	Уровни.Вставить(6, "locality");
	Уровни.Вставить(7, "territory");
	Уровни.Вставить(8, "street");

	Возврат Уровни;

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

Процедура ОбновитьПредставлениеАдреса(Адрес, ВключатьСтрануВПредставление) Экспорт
	
	Представление = РаботаСАдресамиКлиентСервер.ПредставлениеАдреса(Адрес, ВключатьСтрануВПредставление);
	Адрес.Value = Представление;
	
КонецПроцедуры

Процедура ДобавитьУровеньУлицыДляАдреса(Адрес) Экспорт
	
	Если ЗначениеЗаполнено(Адрес.street) Тогда
		Если ТипЗнч(Адрес.munLevels) = Тип("Массив") 
		   И Адрес.munLevels.Найти("street") = Неопределено Тогда
			Адрес.munLevels.Добавить("street");
		КонецЕсли;
		
		Если ТипЗнч(Адрес.admLevels) = Тип("Массив") 
		   И Адрес.admLevels.Найти("street") = Неопределено Тогда
			Адрес.admLevels.Добавить("street");
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

Функция СписокАдресныхЕдиницССокращениями()
	
	СписокАдресныхЕдиниц = Новый ТаблицаЗначений;
	СписокАдресныхЕдиниц.Колонки.Добавить("Сокращение", ОбщегоНазначения.ОписаниеТипаСтрока(20));
	СписокАдресныхЕдиниц.Колонки.Добавить("НомерУровня", ОбщегоНазначения.ОписаниеТипаЧисло(1));
	СписокАдресныхЕдиниц.Колонки.Добавить("Значение", ОбщегоНазначения.ОписаниеТипаСтрока(50));
	
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.АдресныйКлассификатор") Тогда
		МодульАдресныйКлассификаторПовтИсп = ОбщегоНазначения.ОбщийМодуль("АдресныйКлассификаторПовтИсп");
		СписокСокращений = МодульАдресныйКлассификаторПовтИсп.СписокСокращений();
	Иначе
		Возврат СписокАдресныхЕдиниц;
	КонецЕсли;
	
	Для Каждого АдреснаяЕдиница Из СписокСокращений Цикл
		НомерУровня = Лев(АдреснаяЕдиница.Ключ, 1);
		НомерУровня = СтроковыеФункцииКлиентСервер.СтрокаВЧисло(НомерУровня);
		Если НомерУровня = Неопределено Тогда
			Продолжить;
		КонецЕсли;
		Сокращение = СтрЗаменить(АдреснаяЕдиница.Ключ, НомерУровня, "");
		
		ЕдиницаАдреса = СписокАдресныхЕдиниц.Добавить();
		ЕдиницаАдреса.Значение = АдреснаяЕдиница.Значение;
		ЕдиницаАдреса.Сокращение = Сокращение;
		ЕдиницаАдреса.НомерУровня = НомерУровня;
	КонецЦикла;
	
	СписокАдресныхЕдиниц.Сортировать("НомерУровня");
	
	Возврат СписокАдресныхЕдиниц;
	
КонецФункции

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