Опишу, в чём суть задачи, с которой столкнулся...
-- Делаю свой инструмент для переноса данных из УПП/ЗУП 2.5 в ЗУП 3.1.
-- Контактная информация - это часть переносимых данных.
-- Оказалось, что со времен "царя" никто адреса не правил. Т.к. организации 20 лет, то ровно на столько устарели введённые данные.
-- Структура хранения, мягко говоря, не совпадает
-- Необходимо преобразовать имеющуюся контактную информацию под новый формат данных и новый классификатор.
Статья будет довольно объёмная. Состоит она из двух частей:
1. Общая информация и простые приемы работы с контактной информацией.
2. Преобразование старого формата адреса в новый формат адреса. Описание ошибок в типовом релизе, в т.ч. в архитектуре.
Рассмотрим всё по порядку...
Структура хранения информации
Во всех старых конфигурациях мы привыкли к регистру сведений "Контактная информация" с такой вот структурой:
Ресурсы с названием "Поле1"-"Поле10" имеют текстовый тип значения. А вот "ТипДома", "ТипКорпуса" и "ТипКвартиры" - это перечисления.
Чтоб раскидать это в нормальную структуру, нужно написать такой код:
ЗначенияПолей.Вставить("Страна", "РОССИЯ");
ЗначенияПолей.Вставить("КодСтраны", "643");
ЗначенияПолей.Вставить("Индекс", СтрокаКонтактнойИнформации.Поле1);
ЗначенияПолей.Вставить("Регион", СтрокаКонтактнойИнформации.Поле2);
ЗначенияПолей.Вставить("КодРегиона", "");
ЗначенияПолей.Вставить("РегионСокращение", "");
ЗначенияПолей.Вставить("Район", СтрокаКонтактнойИнформации.Поле3);
ЗначенияПолей.Вставить("РайонСокращение", "");
ЗначенияПолей.Вставить("Город", СтрокаКонтактнойИнформации.Поле4);
ЗначенияПолей.Вставить("ГородСокращение", "");
ЗначенияПолей.Вставить("НаселенныйПункт", СтрокаКонтактнойИнформации.Поле5);
ЗначенияПолей.Вставить("НаселенныйПунктСокращение", "");
ЗначенияПолей.Вставить("Улица", СтрокаКонтактнойИнформации.Поле6);
ЗначенияПолей.Вставить("УлицаСокращение", "");
ЗначенияПолей.Вставить("ТипДома", ?(ЗначениеЗаполнено(СтрокаКонтактнойИнформации.ТипДома),Метаданные.Перечисления.ТипыДомов.ЗначенияПеречисления.Получить(Перечисления.ТипыДомов.Индекс(СтрокаКонтактнойИнформации.ТипДома)).Имя,""));
ЗначенияПолей.Вставить("Дом", СтрокаКонтактнойИнформации.Поле7);
ЗначенияПолей.Вставить("ТипКорпуса", ?(ЗначениеЗаполнено(СтрокаКонтактнойИнформации.ТипКорпуса),Метаданные.Перечисления.ТипыКорпусов.ЗначенияПеречисления.Получить(Перечисления.ТипыКорпусов.Индекс(СтрокаКонтактнойИнформации.ТипКорпуса)).Имя,""));
ЗначенияПолей.Вставить("Корпус", СтрокаКонтактнойИнформации.Поле8);
ЗначенияПолей.Вставить("ТипКвартиры", ?(ЗначениеЗаполнено(СтрокаКонтактнойИнформации.ТипКвартиры),Метаданные.Перечисления.ТипыКвартир.ЗначенияПеречисления.Получить(Перечисления.ТипыКвартир.Индекс(СтрокаКонтактнойИнформации.ТипКвартиры)).Имя,""));
ЗначенияПолей.Вставить("Квартира", СтрокаКонтактнойИнформации.Поле9);
ЗначенияПолей.Вставить("Комментарий", СтрокаКонтактнойИнформации.Комментарий);
Теперь посмотрим, как это сделано в новых решениях, на примере конфигурации ЗУП 3.1 релиз 3.1.23.
1. Как говорится - найди 10 отличий... Теперь контактная информация во всех справочниках лежит в табличной части. Помнится, мы уже проходили лет 10 назад такой вариант хранения информации об адресах. Всё новое - хорошо забытое старое)))
Разберем назначение реквизитов новой табличной части:
-- "Тип" и "Вид" полностью соответствуют старому решению перечисления. Лишь добавлены несколько новый значений
-- "Представление" тоже не поменялось, обычный текст
-- Из привычных нам 10 полей отдельно вынесены только 3: "Страна", "Регион" и "Город". Это также простые текстовые поля.
Следующие 2 поля и являются причиной всех проблем при работе с адресами.
-- Значение. Это поле содержит строку в формате JSON. Т.е. весь адрес разбит на поля с учетом классификатора и записан особым образом.
Почему-то номер квартиры записан в отдельный текстовый блок) Наверно, у кого-то в одном подъезде их несколько. Вот образец текста, корректно разбитого по полям:
{
"value": "445030, Самарская обл, г Тольятти, ул Тополиная, д. 100, кв. 200",
"type": "Адрес",
"country": "Россия",
"addressType": "Административно-территориальный",
"ZIPcode": "445030",
"area": "Самарская",
"areaType": "обл",
"city": "Тольятти",
"cityType": "г",
"street": "Тополиная",
"streetType": "ул",
"id": "05218b6f-7d92-4ec8-b64b-1c2e878417d3",
"areaId": "df3d7359-afa9-4aaa-8ff9-197e73906b1c",
"munDistrict": "Тольятти",
"munDistrictType": "г.о.",
"munDistrictId": "ccd78564-c43d-43b8-bf36-03152da5d6d8",
"cityId": "242e87c1-584d-4360-8c4c-aae2fe90048e",
"streetId": "05218b6f-7d92-4ec8-b64b-1c2e878417d3",
"houseType": "Дом",
"houseNumber": "100",
"houseId": "a3ef43fc-c91c-498a-9ab0-a4805e0bfc4c",
"apartments": [
{
"type": "Квартира",
"number": "200"
}
],
"oktmo": "36740000001",
"okato": "36440363000",
"ifnsFLCode": 6320,
"ifnsULCode": 6320
}
Этот адрес введен как "Административно-территориальный". Ещё есть "Муниципальный" и "ВСвободнойФорме".
На что ещё требуется обратить особое внимание:
Недостаточно просто раскидать информацию по полям! Как видно из примера, каждый элемент адресной информации имеет свой ID.
Тип значения его "УникальныйИдентификатор". Именно благодаря ему мы можем быть уверены, что адрес правильный!
Также этот ID является первым измерением регистра сведений "Адресные объекты". В этом регистре хранится загруженный классификатор. Как его загрузить описывать не буду, т.к. есть на ИТС.
-- Значение полей. Нам же мало иметь адрес записанный в одном формате! А давайте сохраним ещё в одном!? В XML.
Почему бы и ДА!? Вот как это выглядит для того же адреса:
<КонтактнаяИнформация xmlns="http://www.v8.1c.ru/ssl/contactinfo" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Представление="445030, Самарская обл, г Тольятти, ул Тополиная, д. 100, кв. 200">
<Состав xsi:type="Адрес" Страна="Россия">
<Состав xsi:type="АдресРФ">
<СубъектРФ>Самарская обл</СубъектРФ>
<Город>Тольятти г</Город>
<Улица>Тополиная ул</Улица>
<ОКТМО>36740000001</ОКТМО>
<ДопАдрЭл ТипАдрЭл="10100000" Значение="445030"/>
<ДопАдрЭл>
<Номер Тип="1010" Значение="100"/>
</ДопАдрЭл>
<ДопАдрЭл>
<Номер Тип="2010" Значение="200"/>
</ДопАдрЭл>
</Состав>
</Состав>
</КонтактнаяИнформация>
Для удобства просмотра сделал перенос строк. Хранится это одной строкой без пробелов и прочих разделителей.
Чтоб был понятен мой сарказм выше, стоит написать, что весь программный интерфейс работы с адресом заточен на формат JSON.
Формат XML формируется в самом конце в момент записи адреса в табличную часть.
Простые операции с адресом
Ввод адресов
Разберемся, как работать со строкой в формате JSON.
Сразу хочу отметить, что первая наша задача - получить правильное представление на основе разбитой по полям контактной информации.
1. Когда мы загружаем информацию откуда-нибудь, нам нужна понятная структура для записи данных. Пишем такой код:
СтруктураКонтактнойИнформации = РаботаСАдресамиКлиентСервер.СтруктураКонтактнойИнформацииПоТипу(Выборка.Тип);
Структура содержит в себе следующие поля:
В этой структуре привычные нам поля. Если их заполнить, появляется возможность сформировать правильное представление, которое позволит распознать адрес.
Для этого воспользуемся программным интерфейсом:
Представление = УправлениеКонтактнойИнформацией.ПредставлениеКонтактнойИнформации(СтруктураКонтактнойИнформации);
В результате Представление = "142700, Московская обл, р-н Ленинский, г Видное, б-р Зеленые аллеи, д. 10, кв. 200".
Далее наша вторая задача - преобразовать представление в нужный нам формат JSON.
Для этого воспользуемся ещё одним программным интерфейсом:
Значение = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияПоПредставлению(Представление, Выборка.Тип);
Получается для приведённого примера такой результат:
{
"value": "142700, Московская обл, д. 10, р-н Ленинский, г Видное, б-р зеленые аллеи, кв. 200",
"type": "Адрес",
"country": "Россия",
"addressType": "Административно-территориальный",
"ZIPcode": "142700",
"area": "Московская",
"areaType": "обл",
"id": "29251dcf-00a1-4e34-98d4-5c47484a36d4",
"areaId": "29251dcf-00a1-4e34-98d4-5c47484a36d4",
"houseType": "Дом",
"houseNumber": "10",
"apartments": [
{
"type": "Р-Н",
"number": "Ленинский"
},
{
"type": "Г",
"number": "Видное"
},
{
"type": "Б-Р Зеленые",
"number": "аллеи"
},
{
"type": "Квартира",
"number": "200"
}
],
"oktmo": "46000000",
"okato": "46000000000",
"ifnsFLCode": 5000,
"ifnsULCode": 5000
}
Как видно, в результате получился адрес в старом административно-территориальном виде. Сейчас никаких районов не существует, есть городские округа.
Этим займёмся немного позднее. Сейчас необходимо полученный адрес записать правильно в табличную часть "Контактная информация". Опять же для этого не нужно городить велосипед, достаточно воспользоваться программным интерфейсом:
УправлениеКонтактнойИнформацией.ЗаписатьКонтактнуюИнформацию(ФизическоеЛицоОбъект,
ЗначенияПолей, Выборка.Вид, Выборка.Тип);
Если смотреть отладчиком, получился вот такой результат:
Нужные поля заполнились самостоятельно.
Ввод телефонов
Теперь рассмотрим что происходит с телефонами. Там всё гораздо проще... Программный интерфейс от вида контактной информации практически не меняется! Разница вот в чём:
1. Получение структуры контактной информации нужно делать с помощью вот такого программного интерфейса:
СтруктураКонтактнойИнформации = УправлениеКонтактнойИнформациейКлиентСервер.СтруктураПолейТелефона();
Результат будет такой:
2. Теперь отличие только в результате заполнения. Представление = "+7 (495) 111-22-33"
3. Переменная "Значение" в формате JSON выглядит так:
{
"value": "+7 (495) 111-22-33",
"type": "Телефон",
"countryCode": "7",
"areaCode": "495",
"number": "111-22-33"
}
Ввод адресов электронной почты
Ещё одна особенность есть при вводе адреса электронной почты.
Переменная "Представление" равна адресу электронной почты.
Переменная "Значение" в формате JSON выглядит так:
{
"value": "pochta@yandex.ru",
"type": "АдресЭлектроннойПочты"
}
Казалось бы... У нас всё получилось! УРА! Но не тут то было! Открываем пользовательский режим и видим такую картину:
Оказывается, чего-то в адресе не хватает, хотя всё везде разбилось по полям и пользовались мы только программным интерфейсом ЗУП КОРП!
Телефон и адрес электронной почты записались правильно.
Если Ваша цель была поверхностно узнать что-то про контактную информацию и не заниматься "магией" преобразования адресов - дальше можно не читать)
Во второй части будет описан процесс трансформации адреса из формата "Административно-территориальный" в формат "Муниципальный".
Другие технические публикации:
Отладка временных таблиц и типа ТаблицаЗначений
Особенности работы с COM-соединением
Пример работы с файлами odt в клиент-серверной модели работы
Статьи про ЗУП:
Ни в ЗУП ногой!? А мне нравится! Главные сложности решения, что отталкивает