Работа с контактной информацией. Часть 2

05.06.23

Разработка - Механизмы типовых конфигураций

Во второй части статьи рассмотрим вопрос преобразования адреса из старого формата в новый. Рассмотрим реальные задачи, связанные с контактной информацией.

Если Вы не читали первую статью, то Вам сюда:

Работа с контактной информацией. Часть 1

 

Составим план статьи:

1. Как прочитать адрес, записанный в формате JSON?

2. Рассмотрим процесс преобразования адреса из формата КЛАДР в формат муниципального адреса.

3. Какие ошибки в тиражном решении усложняют этот процесс?

4. Сложности при решении задач, связанных с контактной информацией.

 

Как прочитать адрес, записанный в формате JSON

 

Для этого воспользуемся программным интерфейсом:

Адрес = УправлениеКонтактнойИнформациейСлужебный.JSONВКонтактнуюИнформациюПоПолям(Значение, Перечисления.ТипыКонтактнойИнформации.Адрес);

В результате получим структуру, которая инициализируется следующим программным интерфейсом:

Результат = РаботаСАдресамиКлиентСервер.ОписаниеНовойКонтактнойИнформации(ТипКонтактнойИнформации);

//Поля структуры:
Результат.Вставить("value",   "");
Результат.Вставить("comment", "");
Результат.Вставить("type",    ТипКонтактнойИнформацииВСтроку(ТипКонтактнойИнформации));
	
Результат.Вставить("country",     "");
Результат.Вставить("addressType", АдресВСвободнойФорме());
Результат.Вставить("countryCode", "");
Результат.Вставить("ZIPcode",     "");
Результат.Вставить("area",        "");
Результат.Вставить("areaType",    "");
Результат.Вставить("city",        "");
Результат.Вставить("cityType",    "");
Результат.Вставить("street",      "");
Результат.Вставить("streetType",  "");

Результат.Вставить("id",               "");
Результат.Вставить("areaCode",         "");
Результат.Вставить("areaId",           "");
Результат.Вставить("district",         "");
Результат.Вставить("districtType",     "");
Результат.Вставить("districtId",       "");
Результат.Вставить("munDistrict",      "");
Результат.Вставить("munDistrictType",  "");
Результат.Вставить("munDistrictId",    "");
Результат.Вставить("cityId",           "");
Результат.Вставить("settlement",       "");
Результат.Вставить("settlementType",   "");
Результат.Вставить("settlementId",     "");
Результат.Вставить("cityDistrict",     "");
Результат.Вставить("cityDistrictType", "");
Результат.Вставить("cityDistrictId",   "");
Результат.Вставить("territory",        "");
Результат.Вставить("territoryType",    "");
Результат.Вставить("territoryId",      "");
Результат.Вставить("locality",         "");
Результат.Вставить("localityType",     "");
Результат.Вставить("localityId",       "");
Результат.Вставить("streetId",         "");
Результат.Вставить("houseType",        "");
Результат.Вставить("houseNumber",      "");
Результат.Вставить("houseId",          "");
Результат.Вставить("buildings",        Новый Массив);
Результат.Вставить("apartments",       Новый Массив);
Результат.Вставить("codeKLADR",        "");
Результат.Вставить("oktmo",            "");
Результат.Вставить("okato",            "");
Результат.Вставить("asInDocument",     "");
Результат.Вставить("ifnsFLCode",       "");
Результат.Вставить("ifnsULCode",       "");
Результат.Вставить("ifnsFLAreaCode",   "");
Результат.Вставить("ifnsULAreaCode",   "");
Результат.Вставить("stead",            "");
Результат.Вставить("steadId",          "");

По этому коду должно стать понятно, что здания и квартиры - это массивы! Тип адреса по умолчанию - "ВСвободнойФорме". 

Если адрес записан в свободной форме, то реквизит "Значение" выглядит так:

{
"value": "142700, Московская обл, Ленинский р-н, Видное г, Зеленые аллеи б-р, дом 10, кв.200",
"type": "Адрес",
"country": "Россия",
"addressType": "ВСвободнойФорме",
"ZIPcode": "142700",
"street": "142700, Московская обл, Ленинский р-н, Видное г, Зеленые аллеи б-р, дом 10, кв.200"
}

Теперь стоит посмотреть на заполненную версию этой структуры:

Сначала для адреса в произвольной форме:

 

Свойство Значение
Адрес Структура
ZIPcode "142700"
addressType "ВСвободнойФорме"
apartments Массив
area ""
areaCode ""
areaId ""
areaType ""
asInDocument ""
buildings Массив
city ""
cityDistrict ""
cityDistrictId ""
cityDistrictType ""
cityId ""
cityType ""
codeKLADR ""
comment ""
country "Россия"
countryCode ""
district ""
districtId ""
districtType ""
houseId ""
houseNumber ""
houseType ""
id ""
ifnsFLAreaCode ""
ifnsFLCode ""
ifnsULAreaCode ""
ifnsULCode ""
locality ""
localityId ""
localityType ""
munDistrict ""
munDistrictId ""
munDistrictType ""
okato ""
oktmo ""
settlement ""
settlementId ""
settlementType ""
stead ""
steadId ""
street "142700, Московская обл, Ленинский р-н, Видное г, Зеленые аллеи б-р, дом 10, кв.200"
streetId ""
streetType ""
territory ""
territoryId ""
territoryType ""
type "Адрес"
value "142700, Московская обл, Ленинский р-н, Видное г, Зеленые аллеи б-р, дом 10, кв.200"

 

Для адреса в муниципальном формате заполненная структура будет показана ниже на шаге №3 преобразования адреса.

 

Процесс преобразования адреса в муниципальный формат

 

Поясню идею, которая мне помогла провести преобразование адреса...

Если в форме ввода адреса установить переключатель в положение "Муниципальное деление"

 

 

И начать что-то вводить в поле город, то система предлагает несколько вариантов, среди которых есть правильный! 

Аналогичный подбор есть и при вводе улицы. Н надо понимать, что вариантов очень много и надо сначала правильно определить населённый пункт.

 

 

Мне стало интересно, что происходит, как принято говорить, "под капотом"... 

В статье не буду описывать процесс изучения кода и перебор возможных вариантов... Опишу найденный путь, который помог.

Шаг №1. Формируем строку подбора. Сначала пробуем Регион + Район + Город.

Текст ниже взят из обработчика события формы на предыдущем скрине. 

//Подберем Регион/Район/Населенный пункт 
ТекстПодбора = Выборка.Регион + ", " + Выборка.Район + ", " + Выборка.Город;
		
ДополнительныеПараметры = УправлениеКонтактнойИнформациейСлужебный.ПараметрыАвтоподбораАдреса();
ДополнительныеПараметры.Уровни    = "1,3,31,4,41,5,6,65";
		
Результат = Обработки.РасширенныйВводКонтактнойИнформации.СписокАвтоподбораНаселенногоПункта(ТекстПодбора, ДополнительныеПараметры);
УправлениеКонтактнойИнформациейСлужебный.ФорматированиеРезультатовАвтоподбора(Результат.Данные, ТекстПодбора, ПустаяСтрока(Выборка.Тип));

На этом этапе результат может быть пустой. 

 

Шаг №2. Проверяем полученный результат, если он пустой, то повторяем поиск. В этот раз используем только Регин + Город.

//Попробуем подобрать адрес без района
Если Результат.Данные.Количество() = 0 Тогда
    ТекстПодбора = Выборка.Регион + ", " + Выборка.Город;

    ДополнительныеПараметры = УправлениеКонтактнойИнформациейСлужебный.ПараметрыАвтоподбораАдреса();
    ДополнительныеПараметры.Уровни    = "1,3,31,4,41,5,6,65";
			
    Результат = Обработки.РасширенныйВводКонтактнойИнформации.СписокАвтоподбораНаселенногоПункта(ТекстПодбора, ДополнительныеПараметры);
    УправлениеКонтактнойИнформациейСлужебный.ФорматированиеРезультатовАвтоподбора(Результат.Данные, ТекстПодбора, ПустаяСтрока(Выборка.Тип));
			
    Если Результат.Данные.Количество() = 0 Тогда
        Возврат ЗначенияПолей;
    КонецЕсли;
КонецЕсли;

Смотрим результат (Результат.Данные):

 

 

Получился список значений, в котором есть город в муниципальном формате. 

Как видно из результатов, проблема преобразования в том, что в административно-территориальном формате не используется почему-то район!?

Для меня осталось загадкой, почему же не используется!? На мой взгляд - это ОШИБКА!

Откроем отдельно нужный нам адрес. Это структура:

 

 

Поле "Адрес" содержит адрес города правильно записанный в JSON формат.

Поле "Идентификатор" - это уникальный идентификатор конкретного населенного пункта. Он нам понадобится дальше для поиска улицы.

Поле "Адрес" содержит такую информацию:

{
"value": "Московская обл, г.о. Ленинский, г Видное",
"comment": "",
"type": "Адрес",
"country": "Россия",
"addressType": "Муниципальный",
"countryCode": "",
"ZIPcode": "",
"area": "Московская",
"areaType": "обл",
"city": "Видное",
"cityType": "г",
"street": "",
"streetType": "",
"id": "9a72b510-9413-41d8-b076-576fbfd78404",
"areaCode": "5000000000000",
"areaId": "29251dcf-00a1-4e34-98d4-5c47484a36d4",
"district": "",
"districtType": "",
"districtId": "",
"munDistrict": "Ленинский",
"munDistrictType": "г.о.",
"munDistrictId": "c2c325fc-435f-4ab7-88fc-d632f6b33c87",
"cityId": "9a72b510-9413-41d8-b076-576fbfd78404",
"settlement": "",
"settlementType": "",
"settlementId": "",
"cityDistrict": "",
"cityDistrictType": "",
"cityDistrictId": "",
"territory": "",
"territoryType": "",
"territoryId": "",
"locality": "",
"localityType": "",
"localityId": "",
"streetId": "",
"houseType": "",
"houseNumber": "",
"houseId": "",
"stead": "",
"steadId": "",
"buildings": [],
"apartments": [],
"codeKLADR": "5000002500000",
"oktmo": "46707000001",
"okato": "46407000000",
"asInDocument": "",
"ifnsFLCode": "5003",
"ifnsULCode": "5003",
"ifnsFLAreaCode": "",
"ifnsULAreaCode": ""
}

 

Шаг №3. Преобразуем формат JSON в привычную нам структуру. Предварительно из полученных результатов выберем нужный.

Если вдруг не получилось найти такой город, то дальнейшие шаги выполнять нет смысла! 

Преобразование в структуру идёт через программный интерфейс. Поля структуры приведены в разделе "Как прочитать адрес..."

ДанныеНаселенногоПункта = Неопределено;

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

Полученная структура:

 

Ключ Значение
"value" "Московская обл, г.о. Ленинский, г Видное"
"comment" ""
"type" "Адрес"
"country" "Россия"
"addressType" "Муниципальный"
"countryCode" ""
"ZIPcode" ""
"area" "Московская"
"areaType" "обл"
"city" "Видное"
"cityType" "г"
"street" ""
"streetType" ""
"id" 9a72b510-9413-41d8-b076-576fbfd78404
"areaCode" "5000000000000"
"areaId" 29251dcf-00a1-4e34-98d4-5c47484a36d4
"district" ""
"districtType" ""
"districtId" ""
"munDistrict" "Ленинский"
"munDistrictType" "г.о."
"munDistrictId" c2c325fc-435f-4ab7-88fc-d632f6b33c87
"cityId" 9a72b510-9413-41d8-b076-576fbfd78404
"settlement" ""
"settlementType" ""
"settlementId" ""
"cityDistrict" ""
"cityDistrictType" ""
"cityDistrictId" ""
"territory" ""
"territoryType" ""
"territoryId" ""
"locality" ""
"localityType" ""
"localityId" ""
"streetId" ""
"houseType" ""
"houseNumber" ""
"houseId" ""
"buildings" Массив
"apartments" Массив
"codeKLADR" "5000002500000"
"oktmo" "46707000001"
"okato" "46407000000"
"asInDocument" ""
"ifnsFLCode" "5003"
"ifnsULCode" "5003"
"ifnsFLAreaCode" ""
"ifnsULAreaCode" ""
"stead" ""
"steadId" ""

 

Дальнейшие шаги иначе как танцы с бубном не назовёшь))) Но было очень интересно всё таки решить задачу преобразования!

 

Шаг №4. Получим представление адреса с учетом полученного населенного пункта, правильно разложенного по полям. 

Для этого выполним уже описанные в первой статье шаги и заменим в структуре полученные поля:

//Перепишем данные в структуру и получим представление типовым программным интерфейсом
СтруктураКонтактнойИнформации = РаботаСАдресамиКлиентСервер.СтруктураКонтактнойИнформацииПоТипу(Выборка.Тип);
		
ЗаполнитьЗначенияСвойств(СтруктураКонтактнойИнформации, Выборка, ,"Представление"); 
		
//Заполним полученный населённый пункт
СтруктураКонтактнойИнформации.Город = ДанныеНаселенногоПунктаСтруктура.city;
СтруктураКонтактнойИнформации.ГородСокращение = ДанныеНаселенногоПунктаСтруктура.cityType;
СтруктураКонтактнойИнформации.Район = ДанныеНаселенногоПунктаСтруктура.munDistrict;
СтруктураКонтактнойИнформации.РайонСокращение = ДанныеНаселенногоПунктаСтруктура.munDistrictType;
СтруктураКонтактнойИнформации.Регион = ДанныеНаселенногоПунктаСтруктура.area;
СтруктураКонтактнойИнформации.РегионСокращение = ДанныеНаселенногоПунктаСтруктура.areaType;
		
СтруктураКонтактнойИнформации.Вставить("ТипАдреса", "Муниципальный");
		
//Получим новое представление, которое преобразуем далее в JSON
//Чтоб из представления не убирался район/городской округ необходимо:
//В функции ИменаУровнейАдреса из модуля РаботаСАдресамиКлиентСервер для муниципального адреса добавить
//    Уровни.Добавить("District");
Представление = УправлениеКонтактнойИнформацией.ПредставлениеКонтактнойИнформации(СтруктураКонтактнойИнформации);

Как видно из комментария, типовой код содержит ошибки! Почему-то в указанной процедуре отсутствует поле Район, полученный таким трудом.

Такое ощущение, что поле район хотели убрать для другого вида адресов, а убрали для муниципального! 

Вот как функция выглядит после исправления:

Функция ИменаУровнейАдреса(ТипАдреса, ВключатьУровеньУлицы, ВключатьУровеньДома = Ложь, ИсключитьУровеньГорода = Ложь) Экспорт
	
    Уровни = Новый Массив;
	
    Если ТипАдреса = УправлениеКонтактнойИнформациейКлиентСервер.ИностранныйАдрес() Тогда
        Уровни.Добавить("Area");
    Иначе
        Уровни.Добавить("Area");
        Если ТипАдреса = УправлениеКонтактнойИнформациейКлиентСервер.АдресЕАЭС() Тогда
			
            Уровни.Добавить("District");
            Если Не ИсключитьУровеньГорода Тогда
                Уровни.Добавить("City");
            КонецЕсли;
            Уровни.Добавить("Locality");
			
        Иначе
			
            Если ТипАдреса = "Все" Тогда
                Уровни.Добавить("District");
                Уровни.Добавить("MunDistrict");
                Уровни.Добавить("Settlement");
                Уровни.Добавить("City");
            Иначе
                Если ЭтоМуниципальныйАдрес(ТипАдреса) Тогда
	                Уровни.Добавить("MunDistrict");
                    Уровни.Добавить("Settlement");
                    //Филатов +
                    Уровни.Добавить("District");
                    //Филатов -
                    Если Не ИсключитьУровеньГорода Тогда
                        Уровни.Добавить("City");
                    КонецЕсли;
                Иначе
                    Уровни.Добавить("District");
                    Уровни.Добавить("City");
                КонецЕсли;
            КонецЕсли;
			
            Уровни.Добавить("CityDistrict");
            Уровни.Добавить("Locality");
            Уровни.Добавить("Territory");
			
        КонецЕсли;
		
    КонецЕсли;
	
    Если ВключатьУровеньУлицы Тогда
        Уровни.Добавить("Street");
    КонецЕсли;
	
    Если ВключатьУровеньДома Тогда
        Уровни.Добавить("house");
    КонецЕсли;
	
    Возврат Уровни;
	
КонецФункции

Еще одна ошибка заключается в том, что программный интерфейс РаботаСАдресамиКлиентСервер.СтруктураКонтактнойИнформацииПоТипу 

не добавляет в структуру поле "ТипАдреса". Т.е. нет возможности указать, что это муниципальный адрес! Поэтому поле в структуру добавляем самостоятельно.

Из-за этого полученное представление ошибочно преобразовывается в административно-территориальный адрес.

 

В итоге поле "Представление" = "142700, Московская обл, г.о. Ленинский, г Видное, Зеленые аллеи б-р, д. 10, кв. 200"

Как говорится - то, что доктор прописал!

 

Шаг №5. Подготовка представления к тому, чтоб его распознать.

На этом шаге необходимо использовать функцию "ЧастиАдресаТаблицей" общего модуля "АдресныйКлассификаторСлужебный".

На мой взгляд здесь заложена ещё одна ошибка: эта функция почему-то не экспортная!!! 

Я её скопировал к себе в модуль обработки. Вот эта функция:

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

 

Возвращает она таблицу:

 

Уровень Позиция Значение Наименование Сокращение Начало Длина Идентификатор
0 1 "142700" "142700" "" 1 6 ""
0 2 "Московская обл" "Московская" "обл" 8 15 ""
0 3 "г.о. Ленинский" "г.о." "Ленинский" 24 15 ""
0 4 "г Видное" "г" "Видное" 40 9 ""
0 5 "Зеленые аллеи б-р" "Зеленые аллеи" "б-р" 50 18 ""
0 6 "д. 10" "д." "10" 69 5 ""
0 7 "кв. 200" "кв." "200" 75 8 ""

 

Самое плохое в этом то, что функция не способна корректно определить, где наименование, а где всё-таки сокращение! 

И это очередная ошибка! Получается, что мы программным интерфейсом получили правильное представление для муниципального адреса, т.к. получали его из структуры,

а эта функция не понимает, что сокращение может быть в начале фразы. Это также добавляет проблем в момент распознавания адреса!

 

Чтоб функция сработала, вместе с ней необходимо скопировать ещё 2 не экспортные функции:

Функция СловаТекстаТаблицей(Знач Текст, Знач Разделители = Неопределено)
	
    // Удаление из текста спец. символов "точек", "номеров".
    Текст = СтрЗаменить(Текст, "№", "");
	
    НачалоСлова = 0;
    Состояние   = 0;
	
    Результат = ТаблицаФрагментов();
	
    Для Позиция = 1 По СтрДлина(Текст) Цикл
        ТекущийСимвол = Сред(Текст, Позиция, 1);
        ЭтоРазделитель = ?(Разделители = Неопределено, ПустаяСтрока(ТекущийСимвол), СтрНайти(Разделители, ТекущийСимвол) > 0);
		
        Если Состояние = 0 И (Не ЭтоРазделитель) Тогда
            НачалоСлова = Позиция;
            Состояние   = 1;
        ИначеЕсли Состояние = 1 И ЭтоРазделитель Тогда
            Строка = Результат.Добавить();
            Строка.Начало = НачалоСлова;
            Строка.Длина  = Позиция-НачалоСлова;
            Строка.Значение = Сред(Текст, Строка.Начало, Строка.Длина);
            Состояние = 0;
        КонецЕсли;
    КонецЦикла;
	
    Если Состояние = 1 Тогда
        Строка = Результат.Добавить();
        Строка.Начало = НачалоСлова;
        Строка.Длина  = Позиция-НачалоСлова;
        Строка.Значение = Сред(Текст, Строка.Начало, Строка.Длина)
    КонецЕсли;
	
    Возврат Результат;
КонецФункции

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

 

Шаг №6. Изменение функции для распознавания адреса

Распознавание происходит с помощью функции "РаспознатьАдрес" общего модуля "АдресныйКлассификаторСлужебный"

В ней 2 варианта работы:

-- Через загруженный классификатор

-- Через веб-сервис.

 

Из-за ошибок на шаге №5, распознавание через загруженный классификатор не происходит! 

Проблема в том, что в запрос к регистру сведений города и городского округа передаются сокращения. Естественно, запрос выдаёт пустой результат!

 

Для того, чтобы решить эту проблему, необходимо в функции "РаспознатьАдрес" поменять местами условия. Получится вот так:

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

 

На мой взгляд, эта функция также содержит ошибку! Вопрос не в том, в какой последовательности пытаться распознать адрес. 

Вопрос в том, почему нельзя воспользоваться обоими способами для достижения наилучшего результата???

Т.е. посмотрели сначала через загруженный классификатор, проверили переменную "Адрес" на Неопределено. И если не получилось - смотрим через веб-сервис! 

 

ВАЖНО: Для работы веб-сервиса необходимо авторизоваться в базе под логином к сайту ИТС. Ну и подписка ИТС должна быть действующей, иначе не сработает.

Ещё важней то, что это не реклама подписки ИТС)))

 

Шаг №7. Распознавание адреса

Вызываем измененный программный интерфейс:

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

 

Полученная структура выглядит так:

 

Свойство Значение
ПравильныйАдресСтруктура Структура
ZIPcode "142703"
addressType "Муниципальный"
apartments Массив
area "Московская"
areaCode "5000000000000"
areaId 29251dcf-00a1-4e34-98d4-5c47484a36d4
areaType "обл"
asInDocument ""
buildings Массив
city "Видное"
cityDistrict ""
cityDistrictId ""
cityDistrictType ""
cityId 9a72b510-9413-41d8-b076-576fbfd78404
cityType "г"
codeKLADR ""
comment ""
country "Россия"
countryCode ""
district ""
districtId ""
districtType ""
houseId 4a08fd6b-0563-4439-9525-92b8ec03927f
houseNumber "10"
houseType "Дом"
id 4a08fd6b-0563-4439-9525-92b8ec03927f
ifnsFLAreaCode ""
ifnsFLCode "5003"
ifnsULAreaCode ""
ifnsULCode "5003"
locality ""
localityId ""
localityType ""
munDistrict "Ленинский"
munDistrictId c2c325fc-435f-4ab7-88fc-d632f6b33c87
munDistrictType "г.о."
okato "46407000000"
oktmo "46707000001"
settlement ""
settlementId ""
settlementType ""
stead ""
steadId ""
street "Зеленые аллеи"
streetId f6b2a8ba-9b06-4646-b88e-4f25c8100cec
streetType "б-р"
territory ""
territoryId ""
territoryType ""
type "Адрес"
value "142703, Московская обл, г Видное, б-р Зеленые аллеи, Дом 10, кв. 200"

 

Как Вы, наверно, помните, квартира записывается в массив, каждый элемент массива - это ещё одна структура:

type number
"Кв." "200"

 

Шаг №7. Преобразование структуры в строку JSON.

Здесь всё просто! Вызываем программный интерфейс:

Значение = УправлениеКонтактнойИнформациейСлужебный.СтруктураВСтрокуJSON(ПравильныйАдресСтруктура);

 

Наконец-то мы получаем желанный адрес разбитый как надо и в формате JSON! Можем его записывать в табличную часть.

Как записать я писал в первой статье (ссылка вверху).

 

Долгожданный результат выглядит так:

{
"value": "142703, Московская обл, г Видное, б-р Зеленые аллеи, Дом 10, кв. 200",
"type": "Адрес",
"country": "Россия",
"addressType": "Муниципальный",
"ZIPcode": "142703",
"area": "Московская",
"areaType": "обл",
"city": "Видное",
"cityType": "г",
"street": "Зеленые аллеи",
"streetType": "б-р",
"id": "4a08fd6b-0563-4439-9525-92b8ec03927f",
"areaCode": "5000000000000",
"areaId": "29251dcf-00a1-4e34-98d4-5c47484a36d4",
"munDistrict": "Ленинский",
"munDistrictType": "г.о.",
"munDistrictId": "c2c325fc-435f-4ab7-88fc-d632f6b33c87",
"cityId": "9a72b510-9413-41d8-b076-576fbfd78404",
"streetId": "f6b2a8ba-9b06-4646-b88e-4f25c8100cec",
"houseType": "Дом",
"houseNumber": "10",
"houseId": "4a08fd6b-0563-4439-9525-92b8ec03927f",
"apartments": [
{
"type": "Кв.",
"number": "200"
}
],
"oktmo": "46707000001",
"okato": "46407000000",
"ifnsFLCode": "5003",
"ifnsULCode": "5003"
}

 

ВАЖНО: Имейте в виду, что если адрес в табличной части уже есть, то программный интерфейс всё равно добавит новую строку!

Поэтому, если Вы исправляете существующие адреса, то не забывайте их удалять.

 

Процесс чтения адреса и преобразования в новый формат полностью рассмотрели. Надеюсь, коллеги разработчики БСП исправят ошибки в тиражных решениях.

Кстати, всё, что описано в этой статье, делалось на релизе ЗУП КОРП 3.1.23.63. Версия подсистемы БСП 3.1.7.110.

 

Другие технические публикации:

Отладка временных таблиц и типа ТаблицаЗначений

Особенности работы с COM-соединением

Пример работы с файлами odt в клиент-серверной модели работы

 

Статьи про ЗУП:

Ни в ЗУП ногой!? А мне нравится! Главные сложности решения, что отталкивает

Я - ЗУПер! Компетенции сотрудников.

Заполнение графиков при вахтовом методе работы

См. также

Механизмы типовых конфигураций Программист Платформа 1С v8.3 1С:Комплексная автоматизация 2.х Россия Бесплатно (free)

Эта ошибка была обнаружена мной в типовой конфигурации 1С:Комплексная автоматизация 2 (2.5.16.115), БСП версия 3.1.9.302. Возникает она после того, как вы добавляете в расширение бизнес-процесс или задачу, выполняете обновление идентификаторов метаданных расширений, но ошибка при записи любого элемента справочника "Профили групп доступа" всё равно остаётся.

01.07.2024    826    Vidz    0    

6

Механизмы типовых конфигураций Программист Платформа 1С v8.3 Конфигурации 1cv8 Россия Бесплатно (free)

Очень часто в написании кода требуется обращаться к предопределённым значениям. Если идёт обращение к типовым предопределённым значениям, то проблем не возникает.

24.06.2024    650    olja-ljaaa    0    

2

Механизмы типовых конфигураций Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Статистическая выборка сценариев и точек изменения отчетов на общей форме ФормаОтчета в типовых конфигурациях. Примеры кода.

03.06.2024    2883    Serg2000mr    29    

99

Механизмы типовых конфигураций Ценообразование, анализ цен Программист Пользователь Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 Россия Абонемент ($m)

Продолжение темы вынесения кусков повторно-используемого кода в запрос. В прошлый раз мы сделали это с вычислением пользовательских формул. Здесь замахнулись на формулы, задаваемые пользователем запросами.

1 стартмани

11.04.2024    771    tango    5    

3

Механизмы типовых конфигураций Программист Платформа 1С v8.3 1С:Управление торговлей 11 Россия Абонемент ($m)

Какому-либо элементу списка сопоставляется числовое значение, зависящее от других значений, причем эта зависимость изменяется от элемента к элементу. Так, в справочнике "Валюты" курс какой-либо валюты может быть задан формулой (или даже запросом) от значения другой валюты. А в справочнике "Виды цен" формула определяет расчет цены для товарной позиции, т.е. элементов справочника "Номенклатура", у которых в карточке указан этот вид цены. А в 1С:ERP, например, этот механизм используется в ресурсной спецификации.

10 стартмани

11.04.2024    641    tango    5    

4

Механизмы типовых конфигураций Программист Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 Россия Бесплатно (free)

В первом сезоне мы рассмотрели (с точки зрения программиста) внутренний механизм, помещающий цены в регистр "Цены". Из этого регистра цена попадает в исходящие УПД (в продажи). Но эта цена (в прайс-листе) дифференцирована (ценообразована) в разрезах свойств самой номенклатуры. Но стратегия ценообразования, ценовая власть - это в первую очередь о работе с ценами для клиента. И тут вступает в дело второй акт марлезонского, Скидки (наценки) и кешбек.

08.04.2024    957    tango    0    

2

Ценообразование, анализ цен Механизмы типовых конфигураций Программист Бизнес-аналитик Пользователь Платформа 1С v8.3 Оперативный учет 1С:Управление торговлей 11 Россия Управленческий учет Абонемент ($m)

Ценовая власть - это способность (возможность) компании изменять в некоторых пределах отпускную цену своего товара (услуг, продукции). Чем в более широких пределах вы можете играть в цену продажи, тем больше этой власти у вас. Если вы не можете управлять отпускной ценой, то это или не ваш бизнес, или не бизнес вовсе. Здесь в рубрике "База знаний аналитика и руководителя проекта" слово проект не ограничено "проектом в 1С". Посмотрим, что для этого есть в УТ 11.5.

1 стартмани

05.04.2024    950    tango    12    

2
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. fatman78 17 06.06.23 21:41 Сейчас в теме
Проделана серьезная изыскательная работа. Достойна уважения.

Помню проблемы, когда 1С: Документооборот перевели с версии БСП 2.х на 3.x. Добавилось тогда незапланированной работы.
Good_Smile; RealSurfer; NiGMa; biimmap; +4 Ответить
2. biimmap 1977 06.06.23 21:44 Сейчас в теме
3. пользователь 07.06.23 06:33
Сообщение было скрыто модератором.
...
4. NiGMa 07.06.23 11:09 Сейчас в теме
Спа-си-бо!!!
Снимаю шляпу!
5. japopov 68 28.09.23 07:56 Сейчас в теме
Спасибо, отличная работа! Использовал её, сильно переработав в конце (сделал подбор улицы и дома аналогично подбору населённого пункта).
Замечание по п.4: не обязательно дорабатывать типовой метод. Достаточно при вызове указать ТипАдреса - "Все". То есть, строку
СтруктураКонтактнойИнформации.Вставить("ТипАдреса", "Муниципальный");

заменить на
СтруктураКонтактнойИнформации.Вставить("ТипАдреса", "Все");

и все поля появляются - магия! :-)
Оставьте свое сообщение