Расширение Бром для интеграции с 1С

Публикация № 1084522

Разработка - Системная интеграция - Внешние источники данных

интеграция обмен расширение загрузка выгрузка RPC web-сервис .Net C# PHP Python

13
Из этой статьи вы узнаете, как можно быстро и просто синтегрироваться с любой конфигурацией 1С при помощи расширения Бром.

Предисловие

Если вы когда-либо пробовали реализовывать интеграцию с 1С:Предприятие, то вы, вероятно, уже знаете, что разумных способов это сделать не так много. Вот список механизмов, с которыми вы могли столкнуться:

  • механизмы взаимодействия через COM-соединение;
  • механизмы web/http - сервисов;
  • механизмы обмена XML-пакетами (конвертация данных, EnterpriseData и пр..);
  • стандартизированный протокол OData.

Указанные механизмы не являются в общем случае взаимозаменяемыми, каждый из них имеет как преимущества так и недостатки, но независимо от выбора, их использование оказывается достаточно трудоемкой задачей.

Мы решили упростить процесс интеграции с 1С и создали расширение, которое и хотим вам представить.

 

Возможности расширения

Расширение Бром может быть установлено на любую конфигурацию 1С, которая поддерживает работу с расширениями (версия совместимости 8.3.10 или выше). Расширение не требует наличия стандартных библиотек, поэтому будет работать даже на самописных конфигурациях. Расширение позволяет:

  • получать и редактировать данные объектов 1С (ссылочные объекты, константы, параметры сеанса);
  • получать выборки из коллекций с учетом сложных условий отбора и сортировки;
  • исполнять произвольные запросы на языке 1С, в том числе пакетные запросы и запросы с разметкой для построителя;
  • вызывать процедуры и функции 1С с возможностью передачи параметров и получения результата в естественном виде (без необходимости преобразования типов);
  • получать данные о метаданных конфигурации с возможностью их частичной (постраничной) загрузки;
  • передавать в обоих направлениях данные как примитивных данных, так и сложные структурированные данные (ссылки, массивы, структуры, соответствия, таблицы значений, деревья, системные перечисления и многое другое).

Функциональность позволяет создать в клиентском приложении свою ORM. Вообще-то, мы уже сделали это за вас, но об этом далее.

 

Принцип работы

Принцип интеграции с 1С следующий:

  1. Подготавливаем инфраструктуру на стороне 1С:
    1. В конфигурацию 1С устанавливаем расширение Бром. Расширение содержит веб-сервис, который будет отвечает на клиентские запросы. Также расширение содержит собственный сериализатор, который преобразует данные 1С в XDTO-объекты и обратно.
    2. Создаем одного или нескольких пользователей, которым доступны роли основной конфигурации и роли расширения (или выдаем эти роли существующим пользователям);
    3. Публикуем конфигурацию на веб-сервере, чтобы она откликалась по HTTP;
  2. В клиентском приложении подключаем готовую библиотеку, создаем клиентский объект-коннектор и пользуемся им.

На момент написания данной статьи реализованы клиентские библиотеки для .Net Core, PHP и Python.

Если ваш проект работает на другой платформе, то свою клиентскую библиотеку вы можете реализовать самостоятельно. Это возможно сделать на любом современном языке программирования.

 

Примеры использования

Теперь давайте посмотрим как выглядит клиентский код. В этой статья я буду использовать C#. Код на PHP и Python полностью аналогичен.

В качестве удаленной конфигурации будет выступать УТ 11, вы можете проводить эксперименты на любой другой.

 

Подключение и инициализация

Подключаемую библиотеку можно скачать с сайта проекта или репозитория (библиотеки для .Net Core и Python лучше ставить из репозитория, т.к. они имеют зависимости). После подключения библиотеки к проекту нам необходимо создать объект "БромКлиент". Сделать это можно одной командой:

dynamic клиент = new БромКлиент(@"
	Публикация = http://domainname.ru/publication_name;
	Пользователь = username;
	Пароль = userpassword
");

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

Наш бром-клиент готов к использованию. Поехали дальше!

 

Вызов процедур и функций 1С

Давайте теперь вызовем простейшую функцию 1С, например "ЧислоПрописью". В качестве кода локализации укажем французский язык:

var числоПрописью = клиент.ЧислоПрописью(2547, "Л = fr_FR");

// -> "Cent vingt-trois mille cent vingt-trois 00"

Данная функция принимает и возвращает значения примитивных типов. Давайте вызовем функцию, которая вернет нам массив:

var цвета = клиент.СтрРазделить("Красный,Синий,Зеленый", ",");

// -> Массив ["Красный", "Синий", "Зеленый"]

Теперь давайте вызовем функцию "НайтиПоКоду" модуля менеджера справочника "Валюты":

var доллар = клиент.Справочники.Валюты.НайтиПоКоду(840);

//-> СправочникСсылка (Доллар)

Функция вернула нам ссылку на элемент справочника. Со ссылками можно делать много полезных вещей, но пока что мы просто передадим эту ссылку в качестве параметра в другую функцию.

var данные = клиент.РаботаСКурсамиВалют.ПолучитьКурсВалюты(доллар, DateTime.Today);

//-> Структура

var курс = данные.Курс;
var кратность = данные.Кратность;

В этом примере мы обратились к функции общего модуля, передали в нее ссылку на элемент справочника и дату. Функция вернула нам объект типа "Структура". Обращаться с этим объектом мы можем так же как и в 1С.

Доступность тех или иных методов можно ограничивать с помощью настроек областей видимости в расширении. Так, например, если указать область «Справочники.*.НайтиПоКоду», то будет доступен только метод «НайтиПоКоду» во всех справочниках конфигурации.

Работа со ссылками

Мы уже умеем находить ссылки на объекты коллекций в 1С. Давайте теперь получим данные этих объектов:

var заказ = клиент.Документы.ЗаказКлиента.НайтиПоНомеру("ТД00-000018", new Date(2017, 1, 1));

var датаЗаказа		= заказ.Дата;
var контрагент		= заказ.Контрагент;
var иннКонтрагента	= заказ.Контрагент.ИНН;

foreach (var стр in заказ.Товары) {
	Console.WriteLine((стр.Номенклатура, стр.Количество));
}

В этом примере мы получили ссылку на документ, а далее через нее уже получили значения реквизитов и табличной части. При обращении к любому атрибуту ссылки из 1С загружаются все данные объекта, поэтому дальнейшее обращение к реквизитам происходит только на стороне клиента.

Если вам известен уникальный идентификатор объекта, то вы можете получить ссылку на стороне клиента без обращений к серверу:

var текСсылка = клиент.Документы.ЗаказКлиента.ПолучитьСсылку(new Guid("5a32b6ab-4661-11e9-912a-38d547755ef7"));

Если вам нужна ссылка на предопределенный элемент, то получить ее предельно просто:

var ставкаНДС = клиент.Перечисления.СтавкиНДС.НДС18_118;

var рольИсполнителя = клиент.Справочники.РолиИсполнителей.ОтветственныйЗаКонтрольИсполнения;

 

Редактирование объектов

Читать данные объектов мы теперь умеем. Давайте попробуем их отредактировать:

var заказ = клиент.Документы.ЗаказКлиента.НайтиПоНомеру("ТД00-000018", new Date(2017, 1, 1));

var заказОбъект = заказ.ПолучитьОбъект();

заказОбъект.Дата = DateTime.Today;
заказОбъект.Номер = "ТД00-000055";

заказОбъект.Товары.Очистить();

var стр = заказОбъект.Товары.Добавить()

стр.Номенклатура = клиент.Справочники.Номенклатура.НайтиПоКоду("000000104");
стр.Количество = 3;

заказОбъект.Записать(РежимЗаписиДокумента.Проведение);

В данном примере мы получили объект документа из ссылки, изменили реквизиты и табличную часть. Теперь попробуем создать номенклатуру и поместить ее в группу, которую тоже предварительно создадим:

// Создаем контекст группы справочника
var группаОбъект = клиент.Справочники.Номенклатура.СоздатьГруппу();
группаОбъект.Наименование = "Новая группа";
группаОбъект.Записать();

// Создаем контекст элемента справочника
var товарОбъект = клиент.Справочники.Номенклатура.СоздатьЭлемент();
товарОбъект.Родитель = группаОбъект.Ссылка;
товарОбъект.Наименование = "Новый товар";
товарОбъект.Артикул = "T-00012321";

// Записываем объект справочника
товарОбъект.Записать();

// Получаем ссылку на созданный объект
var товарСсылка = товарОбъект.Ссылка;

Теперь редактировать объекты мы тоже умеем! Двигаемся дальше!

 

Формирование выборок

Зачастую в клиентском приложении требуется получить список элементов справочника, документов и прочих коллекций. Для этого в библиотеке предусмотрен класс "Селектор". Селектор позволяет формировать выборку ссылок из указанной коллекции с учетом сложных отборов и сортировок. Вместе со ссылками могут быть запрошены и контекстные данные объектов.

var группаМебель = клиент.Справочники.Номенклатура.НайтиПоНаименованию("Мебель");

var текСелектор = клиент.Справочники.Номенклатура.СоздатьСелектор();

текСелектор.
	Выбрать("Наименование, Код, Производитель, Производитель.ИНН").
	Где("ЭтоГруппа", false).
	Где("Ссылка", группаМебель, ВидСравнения.ВИерархии).
	Упорядочить("Производитель").
	Упорядочить("Наименование", НаправлениеСортирвки.Убывание);

foreach (var текСсылка in текСелектор) {
	Console.WriteLine("Наименование: {0}; Код: {1}, Производитель: {2}; ИНН: {3}",
		текСсылка.Наименование,
		текСсылка.Код,
		текСсылка.Производитель,
		текСсылка.Производитель.ИНН
	);
}

// Сохраняем результат выборки в массив для последующего использования
var результат = текСелектор.ВыгрузитьРезультат();

Мы только что выбрали всю номенклатуру, которая находится иерархически в группе "Мебель", и упорядочили ее по двум полям. Вместе с выборкой загрузились данные перечисленных выше полей. Теперь эти данные сохранены на стороне клиента и обращение к ним не будет приводить к серверным вызовам.

Полагаю, принцип работы селектора понятен! Продолжим!

 

Выполнение запросов

Иногда возможностей селектора становится недостаточно, и нам нужно получить данные с помощью произвольного запроса. Давайте создадим и выполним простейший запрос:

var запрос = клиент.СоздатьЗапрос(@"
	ВЫБРАТЬ
		Номенклатура.Ссылка КАК Ссылка,
		Номенклатура.Код КАК Код,
		Номенклатура.Наименование КАК Наименование
	ИЗ
		Справочник.Номенклатура КАК Номенклатура
	ГДЕ
		Номенклатура.Артикул = &Артикул			
");
запрос.УстановитьПараметр("Артикул", "Т-0001");

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

foreach (var стр in результат) {
	Console.WriteLine((стр.Код, стр.Наименование));
}

Мы только что выполнили простой запрос с одним параметром. Давайте теперь выполним шаблонизированный запрос:

var текЗапрос = клиент.СоздатьЗапрос(@"
	ВЫБРАТЬ ПЕРВЫЕ 5
		ЦеныНоменклатурыСрезПоследних.Номенклатура КАК Номенклатура,
		ЦеныНоменклатурыСрезПоследних.Характеристика КАК Характеристика,
		ЦеныНоменклатурыСрезПоследних.Цена КАК Цена
	{ВЫБРАТЬ
		Номенклатура.*}
	ИЗ
		РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
			{(&Период)}, 
			{ (Номенклатура).*, (Характеристика).*}
		) КАК ЦеныНоменклатурыСрезПоследних
	{ГДЕ
		ЦеныНоменклатурыСрезПоследних.Цена}
	{УПОРЯДОЧИТЬ ПО
		Номенклатура.*,
		Характеристика.*}
");

// Добавляем дополнительное поле запроса с указанием синонима поля
текЗапрос.ДобавитьПоле("Номенклатура.Производитель.Наименование", "Бренд");

// Добавляем дополнительный отбор по цене
текЗапрос.ДобавитьУсловиеОтбора("Цена", 100, ВидСравнения.БольшеИлиРавно);

// Указываем дополнительное упорядочение по двум полям
текЗапрос.ДобавитьУпорядочение("Номенклатура.Производитель");
текЗапрос.ДобавитьУпорядочение("Характеристика", НаправлениеСортировки.Убывание);

var результат = текЗапрос.Выполнить(ОбходРезультатаЗапроса.Прямой);

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

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

Если вам нужно выполнить пакетный запрос, то вместо функции "Выполнить" достаточно вызвать "ВыполнитьПакет". Результатом будет массив таблиц или массив деревьев, в зависимости от указанного типа обхода.

 

Обучающие материалы

Мы записали обучающие видеоролики, которые демонстрируют работу расширения:

 

Заключение

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

На текущий момент расширение и клиентские модули находятся в стадии beta-тестирования и распространяются по свободной лицензии.

13

Скачать файлы

Наименование Файл Версия Размер
Расширение Бром для интеграции с 1С
.zip 39,22Kb
06.08.19
3
.zip 1.0.0.4-beta 39,22Kb 3 Скачать

См. также

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. capitan 1247 07.08.19 14:02 Сейчас в теме
Вспоминается...
А Степанида Матвеевна большая дыра ... в компьютерой безопасности нашей фирмы
Старые знакомые. На этот раз без знойных женщин обошлось.
А зря.
Это расширение уже на Хабре мне помнится заклевали.
Безопасность его не нулевая, а отрицательная
В добром здравии и своем разуме редкий человек его поставит на свою конфигурацию

Но на Хабре то люди не курсе стандартов разработки 1С, поэтому они к разыменованию через точку отнеслись спокойно.
А так то в программировании 1С рекомендуют запросами пользоваться
2. itworks 29 07.08.19 18:52 Сейчас в теме
На хабре люди в курсе. Такие особенности работы с объектами есть во многих ORM, 1С в этом плане не особенная. Работа с запросами в расширении предусмотрена, можно получать данные и так и так, и даже третьим способом через выборки с явным указанием полей.

Единственная дыра в безопасности - это закрытый код. Такую проблему можно решить в индивидуальном порядке.
3. capitan 1247 08.08.19 11:15 Сейчас в теме
(2)
Единственная дыра в безопасности - это закрытый код

Я так не смеялся со времен выпускных экзаменов )))

Закрытый код - это реально шедевр, это вам не полуголые женщины в роликах ютюба
За это люблю программистов 1С

// Функция для страпонации декомпилятора, не содержит смысла
Функция СтрапонаторДекомпилятора()
ПеременнаяСтрапонации = "";
МассивСтрапонации = Новый Массив();

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

Пока СтруктураСтрапонации.ХуитологическаяКонстанта <> Неопределено Цикл
ЕщеПеременная = 1 / (2 + 5) + СтруктураСтрапонации.ХуитологическаяКонстанта;

Если ЕщеПеременная <> "ПарметрАдекватности" Тогда
СтруктураСтрапонации.Очистить();
Иначе
Если ЕщеПеременная <> "ФакторБыдлокода" Тогда
СтруктураСтрапонации.Вставить("ПоПолной", "Полнее не бывает");
Иначе
Для к = 69 По 69 * 69 Цикл
п = к - (к / 2);
к = к + п;
Переменная_С_Палками = "| | | | | |";
Если к > п Или п = "Страпонированное состояние почти достигнуто" Тогда
Для о = 69 По 69 * (69 - 68) Цикл
п = о - (к / 2);

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

Попытка
Для Каждого БесполезныйПараметр Из СтруктураСтрапонации Цикл
Сообщить(БесполезныйПараметр.Значение);
КонецЦикла;
Исключение
Сообщить("Не фортануло!");
Попытка
Для Каждого БесполезныйПараметр Из СтруктураСтрапонации.ПоПолной Цикл
Если БесполезныйПараметр > 0 Тогда
ПеременнаяОтсутствияСмыслаЖизни = "НеопределеноКакСтрока";
Иначе
Сообщить("Иполнение кода достиго критической безысходности.");
КонецЕсли;
КонецЦикла;
Исключение
Сообщить("Опять не фортануло!");
КонецПопытки;
КонецПопытки;
КонецЦикла;
МассивСтрапонации[0] = ПеременнаяСтрапонации;
МассивСтрапонации[к + 0] = СтруктураСтрапонации.ПоПолной;
КонецЕсли;

МассивСтрапонации[1] = 5 + ПеременнаяСтрапонации + "Этот код обречен быть непонятым...";
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЦикла;

Возврат "Смысл не найден!";
КонецЕсли;
КонецЦикла;

Возврат "Декомпилятор успешно страпонирован. Возрадуемся!";
КонецФункции

Функция ИнформацияОбАвторе() Экспорт
Возврат "Модуль разработан ООО ""ИТВОРКС"". Автор исходного кода - Шаганов Антон Павлович (ООО ""ИТВОРКС"").";
КонецФункции
Показать
4. itworks 29 08.08.19 11:47 Сейчас в теме
12. itworks 29 08.08.19 14:45 Сейчас в теме
(10) Спасибо, что предупредили.
6. itworks 29 08.08.19 12:54 Сейчас в теме
(3) Раз уж страпонатор не помогает, выложил с исходниками.
Perfolenta; +1 Ответить
9. aspirator23 400 08.08.19 14:10 Сейчас в теме
(6)Чтоб все были такими же щедрыми. :)
8. aspirator23 400 08.08.19 14:08 Сейчас в теме
Оставьте свое сообщение