Integration of 1C with the mapping service Mappable

Hello! In this article I want to share my experience of integrating 1C with by Mappable service (Yandex)

The client is a local logistics company engaged in cargo transportation within the country and to neighboring and distant foreign countries. It maintains its records in 1C. This company contacted us to write a module for integration with a mapping service. The client insisted on using Yandex services. A local Yandex representative told us that the Mappable service (the same Yandex.Maps, but, as I understand it, operating outside the Russian Federation) can be used to solve this problem.

The customer wanted to have the ability to enter an address or some locality in 1C, so that the service would issue a list of found addresses. After selecting a value from the list, this address should be displayed on the map. In parallel, data would be created in a new directory “Addresses” with the preservation of coordinates and the exact address of the selected value.

To solve this problem, it was necessary to use various Mappable API products, which I will discuss in this article.

To list possible addresses I used the geosuggest product:

suggest.api.mappable.world

For this purpose, the following method was created in the general server module:


// Получить места.
//
// Параметры:
//   ТекстПоиска - Строка - Текст поиска.
//
// Возвращаемое значение:
//   Произвольный - Получить места.
Функция ПолучитьМеста(ТекстПоиска = "") Экспорт
	АдресСервера = "suggest.api.mappable.world";
	СоединениеССервером = ПолучитьСоединение(АдресСервера);//HTTPСоединение
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded");
Ресурс = "v1/suggest";

ТелоЗапроса = СтрШаблон("?apikey=%1&text=%2&lang=ru_RU&print_address=1&attrs=uri",
	Константы.MappableAPIKey.Получить(), ТекстПоиска);

HTTPЗапрос = Новый HTTPЗапрос(Ресурс + ТелоЗапроса, Заголовки);
Результат = СоединениеССервером.ВызватьHTTPМетод("GET", HTTPЗапрос);//HTTPОтвет
Ответ = Результат.ПолучитьТелоКакСтроку();

СтруктураОтвета = ПолучитьДанныеИзJSON(Ответ);

Возврат СтруктураОтвета;

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

In response, this function returns a data structure. This structure contains an array of “results” structures, which contains all the necessary data. Each element of the array is a structure containing a formatted address, as well as an address broken down into components: country, city, street, and other data. This structure also contains a very important parameter “Uri” – a kind of identifier of the proposed address. It will be needed to obtain the coordinates of the location.

When a value is selected from the drop-down list, a second query is executed on the Mappable: geocoder.api.mappable.world

For this purpose, a function was created in our module:


// Получить координаты места.
//
// Параметры:
//   uri - Строка - uri.
//
// Возвращаемое значение:
//   Произвольный - Получить координаты места.
Функция ПолучитьКоординатыМеста(uri = "") Экспорт
	АдресСервера = "geocoder.api.mappable.world";
	СоединениеССервером = ПолучитьСоединение(АдресСервера);//HTTPСоединение
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded");
Ресурс = "v1/";

ТелоЗапроса = СтрШаблон("?apikey=%1&uri=%2&lang=en_US", Константы.MappableAPIKey.Получить(), uri);

HTTPЗапрос = Новый HTTPЗапрос(Ресурс + ТелоЗапроса, Заголовки);
Результат = СоединениеССервером.ВызватьHTTPМетод("GET", HTTPЗапрос);//HTTPОтвет
Ответ = Результат.ПолучитьТелоКакСтроку();

СтруктураОтвета = ПолучитьДанныеИзJSON(Ответ);

Возврат СтруктураОтвета;

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

This method returns the coordinates of the selected location. The result can be processed as follows:


Если РезультатПоиска.Свойство("response") И РезультатПоиска.response.Свойство("GeoObjectCollection")
	И РезультатПоиска.response.GeoObjectCollection.featureMember.Количество() > 0 Тогда
Точка = РезультатПоиска.response.GeoObjectCollection.featureMember[0].GeoObject.Point.pos;

СимволРазделителя = СтрНайти(Точка, " ");

Долгота = СокрЛП(Лев(Точка, СимволРазделителя));

Широта  = СокрЛП(Сред(Точка, СимволРазделителя));

КонецЕсли;

Having received the necessary data (address and coordinates of the location), they can be displayed on the map.

It is worth noting that at the time of writing, 1C did not support working with JavaScript API versions v3 from Yandex. Therefore, version 2.1 was used.

So, we display the HTML document field on the processing form and set the text provided by Yandex. I will not display the HTML code itself, it is available in the documentation from Yandex.

To display points on the map, you need to write a few lines of JavaScript code:

First you need to initialize the map:


ymaps.ready(init);
var myMap = "";
var exchangeData = "";
function init() {
	myMap = new ymaps.Map("map", {
		center: [широта, долгота],
		zoom: 11
	});
}

As you can see from the code above, in the parameter center the coordinates of the center of the displayed map are passed, and in the parameter zoom — the value of the map scale.

To directly display a point on the map, you need to add the following code:


function setPoints(lat, lng, pointContent, changeZoom=false) {
	if(changeZoom){
		myMap.setCenter([lat, lng],19);
	}
var myPlacemark = new ymaps.Placemark([lat, lng],{
	balloonContent: pointContent
});
myMap.geoObjects.add(myPlacemark);

}

This method takes as parameters the latitude and longitude of the point to be displayed, the point's content (the text displayed when the point is clicked), and the parameter changeZoom. The map on the form is updated periodically. If you change the map scale manually, the next time you update the map, the scale will return to its original position, and this parameter allows you to save the scale when updating.

As part of the task, it was also necessary to add the ability to create an address by clicking on an arbitrary place on the map. It was necessary to obtain the coordinates of the selected place and have the ability to create an address in our “Addresses” directory.

To do this, we add the following text to our HTML text:

– this is an invisible button, when pressed, the data will be transferred to 1C.

JavaScript code:

myMap.events.add('click', function (e) {
if (!myMap.balloon.isOpen()) {
var coords = e.get('coords');
exchangeData = JSON.stringify({"lat":coords[0].toPrecision(6),
"lng":coords[1].toPrecision(6)})
myMap.balloon.open(coords, {
contentHeader:'Новый адрес',
contentBody:'
<p>Координаты: ' + [
coords[0].toPrecision(6),
coords[1].toPrecision(6)
].join(', ') + '</p>',
contentFooter:'<button id="saveNewAddress" style = type="button" onclick = "createNewAddress()">Сохранить новый адрес</button>'
});
}
else {
myMap.balloon.close();
}
});
}
function createNewAddress(){
interactionButton.click();
}

In 1C, in the processing form, in the OnClick event of our HTML field, we write:

&НаКлиенте
Процедура ПолеHTMLПриНажатии(Элемент, ДанныеСобытия, СтандартнаяОбработка)
	ЭлементНажатия = ДанныеСобытия.Element;
	Если ЭлементНажатия.id = "interactionButton" Тогда
		MyData = Элементы.ПолеHTML.Документ.defaultView.exchangeData;
		ОписаниеОповещения = Новый ОписаниеОповещения("ПолучитьОтвет", ЭтотОбъект, MyData);
		ПоказатьВопрос(ОписаниеОповещения, "Сздать адрес?", РежимДиалогаВопрос.ДаНет);
	КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПолучитьОтвет(Параметры, ДопПараметр) Экспорт
Если Параметры = КодВозвратаДиалога.Да Тогда
ДанныеМетки = МодульИнтеграцииВызовСервера.ПолучитьДанныеИзJSON(ДопПараметр);
	ФормаНовогоАдреса = ПолучитьФорму(&quot;Справочник.Адреса.ФормаОбъекта&quot;);
	ДанныеФормы = ФормаНовогоАдреса.Объект;
	Координаты = ПолучитьКоординатыТочки(Новый Структура(&quot;Долгота,Широта&quot;, ДанныеМетки.lng, ДанныеМетки.lat));
	ОбработатьДанныеНаСервере(ДанныеФормы, Координаты);

	КопироватьДанныеФормы(ДанныеФормы, ФормаНовогоАдреса.Объект);

	ФормаНовогоАдреса.Модифицированность = Истина;
	ФормаНовогоАдреса.Открыть();
КонецЕсли;

КонецПроцедуры
&НаСервереБезКонтекста
Процедура ОбработатьДанныеНаСервере(ДанныеФормы, Координаты)
НовыйАдрес = ДанныеФормыВЗначение(ДанныеФормы, Тип(&quot;СправочникОбъект.Адреса&quot;));
НовыйАдрес.Долгота = Координаты.Долгота;
НовыйАдрес.Широта = Координаты.Широта;

ЗначениеВДанныеФормы(НовыйАдрес, ДанныеФормы);

КонецПроцедуры
image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

Conclusion

Thus, the above-described integration of 1C with the Mappable mapping service allowed the customer's requirements to be successfully implemented. Thanks to the use of the Mappable API, the logistics company was able to automate the process of entering addresses and working with geographic data directly in 1C.

Basic tasks such as searching and selecting addresses, obtaining coordinates, and displaying points on a map were accomplished using the products. geosuggest And geocoder. Also, the integration provided the ability to create a new address in the 1C directory by clicking on the map.

This project demonstrated how modern APIs can be used to expand 1C functionality and improve the efficiency of processes in a logistics company. Such integration can also be adapted for other businesses that need to work with geographic data.

In conclusion, I would like to note that support for current technologies and flexibility in integration allow 1C to remain a popular tool for automating business in a wide variety of areas.

I hope this article will help readers in solving similar problems. If you have any questions or suggestions for improving this method, I will be glad to receive your feedback and comments. Good luck in your projects!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *