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

26.02.18

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

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

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование По подписке [?] Купить один файл
Преобразование объекта в JSONAPI
.epf 11,77Kb
26
26 Скачать (1 SM) Купить за 1 850 руб.

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

См. также

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

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

120000 руб.

19.08.2020    26469    26    1    

28

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

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

28500 руб.

15.11.2022    22964    24    49    

39

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

Готовая интеграция для управляемых форм. Встраивается в вашу 1С как расширение. Реализует автоматический обмен данными между 1С (1С:Фитнес клуб и аналогов) и СКУД RusGuard, автоматизирует бизнес-процессы по созданию и учету сотрудников в СКУД. Значительно упрощает работу специалистов отдела кадров и отдела безопасности: избавляет от двойного ввода информации в 1С и СКУД.

94999 руб.

11.07.2024    1307    1    0    

3

Розничная торговля Внешние источники данных Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист Бухгалтерский учет 1С:Бухгалтерия 3.0 Фармацевтика, аптеки Россия Бухгалтерский учет Платные (руб)

Внешняя обработка загрузки данных из файла-выгрузки, сформированного в программе F3 TAIL версии 3.4 (и выше) или еФарма версии 2.1, в базу конфигурации 1С: Бухгалтерия предприятия 8, ред. 3.0 (базовая, ПРОФ, КОРП, ФРЕШ).

13200 руб.

19.12.2016    48669    98    106    

70

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

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

84000 руб.

24.04.2017    52680    104    165    

91
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. nomadon 369 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 24 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)в данной статье описан способ отправки в Раббит, как забирать из Раббита решать вам. Можно периодически опрашивать, можно постоянную службу-сервис держать работе.
Оставьте свое сообщение