Подписка на события, преобразование объекта в JSONAPI, отправка в RabbitMQ

26.02.18

Интеграция - Внешние источники данных

Обработка содержит функции: - сериализация объекта 1с в JSONAPI - отправка в RabbitMQ по HTTP

Скачать исходный код

Наименование Файл Версия Размер
Преобразование объекта в JSONAPI
.epf 11,77Kb
26
.epf 11,77Kb 26 Скачать

JSONAPI - соглашение об обмене данными о ресурсах в формате JSON.

RabbitMQ - брокер сообщений реализующий протокол AMQP, который имеет менеджмент плагин, позволяющий отправлять сообщения по протоколу HTTP.

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

// Создает exchange имя которого равно строке соединения с базой 1с
Функция PutExchange(Соединение, Заголовки, обработкаJSONAPI, VirtualHost = "")
	exchange= СтрокаСоединенияИнформационнойБазы();
	vhost= ?(VirtualHost="", "%2f", VirtualHost);
	Запрос = Новый HTTPЗапрос("/api/exchanges/"+vhost+"/"+exchange, Заголовки);
	телоСтрока = обработкаJSONAPI.JSON(new Структура("type", "topic"));
	Запрос.УстановитьТелоИзСтроки(телоСтрока, "CESU-8");
	Соединение.Записать(Запрос, "c:\shared\rmq1c-http-response.txt");
	возврат Запрос.АдресРесурса + Символы.ВК + телоСтрока;
КонецФункции

//отправляет ссылку в формате JSONAPI в exchange имя которого равно строке соединения с базой 1с
//routing key равен полному имени типа ссылки
Функция ОтправитьJSONAPIвRMQ(ссылка, обработкаJSONAPI, VirtualHost = "")
	Попытка
		Соединение = Новый HTTPСоединение("rmq.local", 15672);
	Исключение
		//Сообщить("Не удалось установить соединение с сервером онлайн-проверки:" 
		//+ Символы.ПС + ИнформацияОбОшибке().Описание, СтатусСообщения.Важное);
		Возврат ИнформацияОбОшибке().Описание;
	КонецПопытки;
	Заголовки = Новый Map();
	Заголовки.Вставить("authorization", "Basic Ym90MWM6Ym90MWM=");  
	Заголовки.Вставить("Content-Type", "application/json");
	PutExchange(Соединение, Заголовки, обработкаJSONAPI, VirtualHost);
	exchange= СтрокаСоединенияИнформационнойБазы();
	vhost= ?(VirtualHost="", "%2f", VirtualHost);
	Запрос = Новый HTTPЗапрос("/api/exchanges/"+vhost+"/"+exchange+"/publish", Заголовки);
	payloadJSON = обработкаJSONAPI.j_Экранировать(обработкаJSONAPI.JSONAPI(ссылка));
	телоСтруктура = new Структура();
	телоСтруктура.Вставить("properties",new Структура());
	телоСтруктура.Вставить("routing_key", ссылка.Метаданные().ПолноеИмя());
	телоСтруктура.Вставить("payload",payloadJSON);
	телоСтруктура.Вставить("payload_encoding","string");
	телоСтрока = обработкаJSONAPI.JSON(телоСтруктура);
	Запрос.УстановитьТелоИзСтроки(телоСтрока, "CESU-8");
	Соединение.ОтправитьДляОбработки(Запрос, "c:\shared\rmq1c-http-response.txt");
	возврат Запрос.АдресРесурса + Символы.ВК + телоСтрока;
КонецФункции

//отправка ссылки, с указанием обработки JSONAPI, в которой находится функция сериализации в JSONAPI
Процедура ОтправитьВОчередь(Ссылка) Экспорт
	ОтправитьJSONAPIвRMQ(Ссылка, Обработки.JSONAPI.Создать());
КонецПроцедуры

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

В веб интерфейсе RabbitMQ указываем в какой очереди и по каким routing key (типы объектов) мы хотим получать сообщения с данными.

Недостаток: событие "при записи" происходит перед транзакцией БД, а не после, поэтому если транзакция не пройдет, то событие "запись" отправленное куда либо, будет фальшивым.

протестировано на 1С:Предприятие 8.2 (8.2.19.130)

Перем j_СоответствиеТиповИИмен;
Перем j_Сч;

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

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

// Экранирует спецсимвоы в строке
Функция j_Экранировать(Знач Строка) Экспорт
	Строка = СтрЗаменить(Строка, "\", "\\");
    Строка = СтрЗаменить(Строка,Символы.ПС,"\n");
    Строка = СтрЗаменить(Строка,Символы.ВК,"\r"); 
	Строка = СтрЗаменить(Строка,Символы.Таб,"\t");
	Строка = СтрЗаменить(Строка,"""","\""");
	//Строка = СтрЗаменить(Строка,"'","\'");
	//Строка = СтрЗаменить(Строка, "\", "\\");
    Возврат Строка
КонецФункции

Функция JSON(Значение, Форматировать = Истина, Отступ  = "") Экспорт
	
	JSONРазделСтрок = Символы.ВК + Символы.ПС; 
	Разделитель	= "";
    ТипЗн = ТипЗнч(Значение);
	Отступ = ?(Форматировать, Отступ, "");
	
	// Строка
	Если ТипЗн = Тип("Строка") Тогда
        Стр = """" + j_Экранировать(Значение) + """"

	// Число или Булево
    ИначеЕсли ТипЗн = Тип("Число") ИЛИ ТипЗнч(Значение) = Тип("Булево") Тогда
        Стр = XMLСтрока(Значение)

	// Дата	
    ИначеЕсли ТипЗн = Тип("Дата") Тогда
        Стр = """" + ?(ЗначениеЗаполнено(Значение),XMLСтрока(Значение),"") + """"

	// Структура Данных Рекурсивно	
	ИначеЕсли ТипЗн = Тип("Структура") Тогда
        Стр = JSONРазделСтрок + Отступ + "{";
        Для Каждого Параметр Из Значение Цикл
            Стр = Стр + Разделитель + JSONРазделСтрок + Отступ + """" + Параметр.Ключ + """:" + JSON(Параметр.Значение, Форматировать, Отступ + Символы.Таб);
			Разделитель = ","
        КонецЦикла;
        Стр = Стр + JSONРазделСтрок + Отступ + "}";
		
	// Массив Рекурсивно
    ИначеЕсли ТипЗн = Тип("Массив") Тогда
        Стр = Отступ + "[";
		Для Каждого Элемент Из Значение Цикл
            Стр = Стр + Разделитель + JSONРазделСтрок + Отступ + JSON(Элемент, Форматировать, Отступ + Символы.Таб);
            Разделитель = ","
        КонецЦикла;
        Стр = Стр + JSONРазделСтрок + Отступ + "]";

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

	// Ссылка на объект
	ИначеЕсли Найти(Строка(ТипЗн), "ссылка") >0 Тогда
		Структура = Новый Структура;
		
		ИмяТипа = j_ОпределитьПоСсылкеИмяТипа(Значение);                
		
		Если Не Значение.Пустая()  Тогда
			Если ИмяТипа = "СправочникСсылка" Тогда
				Структура.Вставить("UUID",XMLСтрока(Значение));
			ИначеЕсли ИмяТипа = "ДокументСсылка" Тогда
				Структура.Вставить("UUID",XMLСтрока(Значение));
				Структура.Вставить("НомерДокумента",Значение.Номер);
				Структура.Вставить("ДатаДокумента",Значение.Дата);
			КонецЕсли;
			Структура.Вставить("ТипОбъекта",j_ОпределитьПоСсылкеПредставление(Значение));
			Структура.Вставить("Представление",j_Экранировать(Значение));
		Иначе
			Структура.Вставить("ТипОбъекта",j_ОпределитьПоСсылкеПредставление(Значение));
			Структура.Вставить("Представление",Неопределено);
		КонецЕсли;
		Стр = Отступ + JSON(Структура, Форматировать, Отступ + Символы.Таб);
		
	// Коллекция Объектов - Не сериализуется
	ИначеЕсли Найти(Строка(ТипЗн), "менеджер") >0 Тогда
		Структура = Новый Структура;
		Структура.Вставить("ТипОбъекта",j_Экранировать(Значение));
		Стр = Отступ + JSON(Структура, Форматировать, Отступ + Символы.Таб);		
		
	// Неопределенка
    ИначеЕсли не значениеЗаполнено(Значение) Тогда
        Стр = "null"
		
	// Все остальное не сериализуется
	Иначе
		//Стр = "null" + j_Экранировать(Значение);
		data = Новый Структура;
		data.Вставить("type", Значение.Метаданные().ПолноеИмя());
		попытка
			data.Вставить("id",строка(Значение.ссылка.УникальныйИдентификатор()));
		исключение
			data.Вставить("id",j_Экранировать(Значение));
		конецпопытки;
		Структура = Новый Структура;
		Структура.Вставить("data", data);
		Стр = Отступ + JSON(Структура, Форматировать, Отступ + Символы.Таб);		
    КонецЕсли;

    Возврат Стр
КонецФункции

Процедура ДобавитьВСтруктуру(Имя, Значение, attributes, relationships)
	ТипЗн = ТипЗнч(Значение);
	Если не значениеЗаполнено(Значение)Тогда
	ИначеЕсли ТипЗн = Тип("Строка") или ТипЗн = Тип("Число") ИЛИ ТипЗнч(Значение) = Тип("Булево") или ТипЗн = Тип("Дата")
		или ТипЗн = Тип("Структура") 
		//или ТипЗн = Тип("Массив") или ТипЗн = Тип("ТаблицаЗначений")
		Тогда
		attributes.Вставить(Имя, Значение);
	иначе
		relationships.Вставить(Имя, Значение);
	Конецесли;
КонецПроцедуры

Функция JSONAPI(Ссылка)Экспорт
	Ссылка = Ссылка.ссылка;
	data = Новый Структура();  
	//Объект = справочники.Контрагенты.найтипокоду("000000001").ПолучитьОбъект();
	//Объект.Метаданные().ПолноеИмя()
	МД = ссылка.Метаданные();
	ПолноеИмяТипа = МД.ПолноеИмя();
	data.Вставить("type", ПолноеИмяТипа);
	data.Вставить("id", Строка(Ссылка.УникальныйИдентификатор()));
	attributes = Новый Структура;
	relationships = Новый Структура;
	included = Новый Массив;
	Для каждого Реквизит из МД.СтандартныеРеквизиты Цикл
		ДобавитьВСтруктуру(Реквизит.Имя, Ссылка[Реквизит.Имя], attributes, relationships);
	КонецЦикла;     
	Для каждого Реквизит из МД.Реквизиты Цикл
		ДобавитьВСтруктуру(Реквизит.Имя, Ссылка[Реквизит.Имя], attributes, relationships);
	КонецЦикла;     
	Для каждого ТабличнаяЧасть из МД.ТабличныеЧасти Цикл
		Значение = Ссылка[ТабличнаяЧасть.Имя].Выгрузить();
		Колонки = Значение.Колонки;
		Массив = Новый Массив;
		Для Каждого СтрокаТЗ Из Значение Цикл
			attributes1 = Новый Структура();
			relationships1 = Новый Структура();
			Для Каждого Колонка Из Колонки Цикл
				ДобавитьВСтруктуру(Колонка.Имя, СтрокаТЗ[Колонка.Имя], attributes1, relationships1);
			КонецЦикла;
			type = ПолноеИмяТипа + "." + ТабличнаяЧасть.Имя;
			id = Строка(Ссылка.УникальныйИдентификатор()) + "-" + СтрокаТЗ.НомерСтроки;
			item1 = Новый Структура("type,id", type, id);
			Массив.Добавить(item1);
			item = Новый Структура("type,id", type, id);
			item.Вставить("attributes", attributes1);
			item.Вставить("relationships", relationships1);
			included.Добавить(item);
		КонецЦикла;
		relationships.Вставить(ТабличнаяЧасть.Имя, Новый Структура("data", Массив));
	КонецЦикла;
	Если attributes.Количество()>0 тогда 
		data.Вставить("attributes", attributes);
	КонецЕсли;
	Если relationships.Количество()>0 тогда 
		data.Вставить("relationships", relationships);
	КонецЕсли;
	Если included.Количество()>0 тогда 
		data.Вставить("included", included);
	КонецЕсли;
	Структура = Новый Структура("data", data);
	возврат JSON(Структура);
КонецФункции

 

JSON JSONAPI RabbitMQ MQ AMQP подписка на события событийно-ориентированная архитектура EDA SOA

См. также

Перенос данных из Парус 8 в ЗГУ 3

Зарплата Внешние источники данных Бюджетный учет Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бухгалтерский учет Бюджетный учет Платные (руб)

Обработка позволяет перенести кадровую информацию и данные по заработной плате, фактических удержаниях, НДФЛ, вычетах, страховых взносах из базы Парус 8 учреждений в конфигурацию 1С:Зарплата и кадры государственного учреждения ред. 3 (ЗГУ) и начать с ней работать с любого месяца года.

84000 руб.

19.08.2020    22647    19    1    

22

Экстрактор данных 1С в BI - выгрузка данных из 1С в BI-аналитику

Внешние источники данных Платформа 1С v8.3 Управляемые формы Анализ и прогнозирование Конфигурации 1cv8 Узбекистан Беларусь Кыргызстан Молдова Россия Казахстан Платные (руб)

Готовое решение для автоматической выгрузки данных из 1С 8.3 в базу данных ClickHouse, PostgreSQL или Microsoft SQL для работы с данными 1С в BI-системах. «Экстрактор данных 1С в BI» работает со всеми типовыми и нестандартными конфигурациями 1С 8.3 и упрощает работу бизнес-аналитиков. Благодаря этому решению, специалистам не требуется быть программистами, чтобы легко получать данные из 1С в вашей BI-системе.

15.11.2022    13737    12    SQV0    47    

29

Перенос данных из Парус 10 в ЗГУ ред.3

Внешние источники данных Кадровый учет Файловый обмен (TXT, XML, DBF), FTP Обмен между базами 1C Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бухгалтерский учет Бюджетный учет Платные (руб)

Обработка позволяет перенести кадровую информацию и данные по заработной плате, фактических удержаниях, НДФЛ, вычетах, страховых взносах из базы Парус 10 учреждений в конфигурацию 1С:Зарплата и кадры государственного учреждения ред. 3 (ЗГУ) и начать с ней работать с любого месяца года.

60000 руб.

05.10.2022    9318    9    8    

11

Перенос данных из Парус 7.хх в ЗГУ ред.3

Внешние источники данных Зарплата Бюджетный учет Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бухгалтерский учет Бюджетный учет Платные (руб)

Обработка позволяет перенести кадровую информацию и данные по заработной плате, фактических удержаниях, НДФЛ, вычетах, страховых взносах из базы Парус 7.хх учреждений в конфигурацию 1С:Зарплата и кадры государственного учреждения ред. 3 (ЗГУ) и начать с ней работать с любого месяца года.

24000 руб.

24.04.2017    48874    97    163    

86

Перенос данных из Парус 10 (Торнадо) в ЗГУ ред.3 через Excel

Внешние источники данных Загрузка и выгрузка в Excel Зарплата Бюджетный учет Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бухгалтерский учет Бюджетный учет Платные (руб)

Обработка позволяет перенести кадровую информацию и данные по заработной плате из Парус 10(Торнадо) учреждений через файлы Excel в конфигурацию 1С:Зарплата и кадры государственного учреждения ред. 3 (ЗГУ). В принципе, обработка может быть использована для загрузки из файлов Excel, полученных из любых информационных систем.

24000 руб.

16.11.2018    30092    20    31    

21

Загрузка в БГУ из УРМ "Криста"

Внешние источники данных Банковские операции Платформа 1С v8.3 Бухгалтерский учет 1С:Бухгалтерия государственного учреждения Россия Бухгалтерский учет Платные (руб)

Обработки для загрузки данных из УРМ "Криста" в бухгалтерию государственного учреждения редакция 2.0. Есть Демо доступ на вкладке Бесплатные файлы на 1 месяц со дня получения демонстрационного ключа регистрации. Поддерживает ПО "Web-исполнение" от НПО "Криста".

4800 руб.

19.06.2013    38533    136    90    

30
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. nomadon 367 07.05.18 19:35 Сейчас в теме
Спасибо за возможность копипаста)
HAMAZ; vsozansky; VVi3ard; maxopik2; Irwin; +5 Ответить
2. vis_tmp 32 25.04.20 14:07 Сейчас в теме
Никак не могу найти, есть ли возможность для 7.7 использовать Rabbit MQ ?
3. user1383227 18.05.20 22:00 Сейчас в теме
4. akR00b 22 26.10.20 13:30 Сейчас в теме
Добрый день, а как реализован процесс оповещения получателя? т.е н-ое количество раз опрашиваем кролика на сообщения на стороне базы приемника?
5. yaxinr 57 07.12.20 23:32 Сейчас в теме
(4)получатель должен создать сам очередь и связать еще с exchange, и забирать из этой очереди сообщения подписавшись на эту очередь.
6. CrazyHands 37 06.07.21 19:20 Сейчас в теме
(5) А что означает "подписавшись"? Это ведь по сути рег. задание, которое опрашивает кролика?
7. yaxinr 57 09.07.21 14:38 Сейчас в теме
(6)в данной статье описан способ отправки в Раббит, как забирать из Раббита решать вам. Можно периодически опрашивать, можно постоянную службу-сервис держать работе.
Оставьте свое сообщение