При построении сложных корпоративных ландшафтов разработчики часто сталкиваются с необходимостью связать устаревающую, но критически важную систему «1С:Управление производственным предприятием» (УПП) с новыми вспомогательными базами. В качестве технологической основы для новых систем часто выступает самописная конфигурация на базе «Библиотеки стандартных подсистем» (БСП).
Естественным желанием бизнеса является обеспечение так называемой «бесшовной интеграции», когда пользователь работает в интерфейсе одной системы, но мгновенно видит и изменяет данные во второй системе без видимого перехода или длительного ожидания синхронизации. Разберем по шагам, почему типовых механизмов для этого нет, и как спроектировать такое решение своими силами с нуля.
Проанализируем терминологию фирмы «1С». В официальной документации вендора понятие «бесшовная интеграция» жестко закреплено за конкретной технологией — интеграцией с конфигурацией «1С:Документооборот» (1С:ДО) через специальный веб-сервис DMService и встроенную «Библиотеку интеграции с 1С:Документооборотом» (БИД).
Для связки «УПП — Самописная база на БСП» готового аналога БИД не существует по следующим причинам:
Для решения этой задачи нам придется разработать собственную архитектуру интерактивного взаимодействия систем. Ниже мы детально рассмотрим два основных практических метода реализации бесшовного взаимодействия.
Это самый современный, производительный и надежный способ организации «бесшовности». Идея заключается в том, что принимающая база (на БСП) выступает в роли поставщика данных (API), а база-клиент (УПП) делает быстрые синхронные запросы к этому API в момент работы пользователя с формой.
Рассмотрим подробнее процесс создания HTTP-сервиса на стороне самописной базы на БСП. Нам необходимо создать HTTP-сервис, например, с именем IntegrationService и шаблоном URL /get_partner_status/{PartnerCode}.
Посмотрим на пример реализации серверного метода GET, который возвращает статус контрагента и баланс взаиморасчетов из базы БСП в формате JSON:
Функция ПолучитьСтатусКонтрагента(Запрос)
// Получаем параметры из URL запроса
КодКонтрагента = Запрос.ПараметрыШаблона.Получить("PartnerCode");
УстановитьПривилегированныйРежим(Истина);
СсылкаКонтрагент = Справочники.Контрагенты.НайтиПоКоду(КодКонтрагента);
Если СсылкаКонтрагент.Пустая() Тогда
Ответ = Новый HTTPСервисОтвет(404);
Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Ответ.УстановитьТелоИзСтроки("Контрагент с указанным кодом не найден", КодировкаТекста.UTF8);
Возврат Ответ;
КонецЕсли;
// Формируем структуру с данными для ответа
Данные = Новый Структура;
Данные.Вставить("Код", СсылкаКонтрагент.Код);
Данные.Вставить("Наименование", СсылкаКонтрагент.Наименование);
Данные.Вставить("Заблокирован", СсылкаКонтрагент.Заблокирован);
// Получаем баланс из регистра накопления взаиморасчетов
ЗапросВзаиморасчеты = Новый Запрос;
ЗапросВзаиморасчеты.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| ВзаиморасчетыОстатки.СуммаОстаток КАК Баланс
|ИЗ
| РегистрНакопления.Взаиморасчеты.Остатки(, Контрагент = &Контрагент) КАК ВзаиморасчетыОстатки";
ЗапросВзаиморасчеты.УстановитьПараметр("Контрагент", СсылкаКонтрагент);
Выборка = ЗапросВзаиморасчеты.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Данные.Вставить("Баланс", Выборка.Баланс);
Иначе
Данные.Вставить("Баланс", 0);
КонецЕсли;
// Сериализуем данные в JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Данные);
СтрокаJSON = ЗаписьJSON.Закрыть();
// Формируем успешный HTTP-ответ
Ответ = Новый HTTPСервисОтвет(200);
Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Ответ.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8);
Возврат Ответ;
КонецФункции
Теперь проанализируем, как реализовать вызов этого сервиса на стороне УПП в обычной форме карточки контрагента. Мы хотим выводить актуальный баланс и статус блокировки прямо на форму при ее открытии, не дублируя эти данные в физических реквизитах УПП.
В модуле обычной формы контрагента в УПП пропишем обработчик события ПриОткрытии:
Процедура ПриОткрытии()
// Инициализируем переменные соединения
СерверИмя = "bsp-server.local";
Порт = 8080;
ПользовательAPI = "IntegrationUser";
ПарольAPI = "SecurePass123";
КодКонтрагента = ЭтотОбъект.Код;
ПутьКРесурсу = "/bsp_base/hs/IntegrationService/get_partner_status/" + СокрЛП(КодКонтрагента);
// Создаем HTTP-соединение
// В реальной базе рекомендуется выносить параметры авторизации в константы
HTTPСоединение = Новый HTTPСоединение(СерверИмя, Порт, ПользовательAPI, ПарольAPI, , 5); // Таймаут 5 секунд
HTTPЗапрос = Новый HTTPЗапрос(ПутьКРесурсу);
Попытка
HTTPОтвет = HTTPСоединение.Получить(HTTPЗапрос);
Если HTTPОтвет.КодСостояния = 200 Тогда
СтрокаJSON = HTTPОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
// Читаем полученный JSON
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
ДанныеИзБСП = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
// Динамически выводим данные на форму УПП
Если ДанныеИзБСП.Заблокирован Тогда
ЭлементыФормы.НадписьСтатусБСП.Заголовок = "ВНИМАНИЕ: Клиент заблокирован в базе БСП!";
ЭлементыФормы.НадписьСтатусБСП.ЦветТекста = ЦветаСтиля.ПревышениеЛимита;
Иначе
ЭлементыФормы.НадписьСтатусБСП.Заголовок = "Активен в БСП. Баланс: " + Формат(ДанныеИзБСП.Баланс, "ЧДЦ=2");
ЭлементыФормы.НадписьСтатусБСП.ЦветТекста = ЦветаСтиля.ПоясняющийТекст;
EndIf;
ИначеЕсли HTTPОтвет.КодСостояния = 404 Тогда
ЭлементыФормы.НадписьСтатусБСП.Заголовок = "Контрагент отсутствует в базе БСП.";
Иначе
ВызватьИсключение "Код ответа сервера: " + HTTPОтвет.КодСостояния;
КонецЕсли;
Исключение
// Обрабатываем ошибки связи, чтобы форма УПП открывалась даже при падении второй базы
ЭлементыФормы.НадписьСтатусБСП.Заголовок = "Нет связи с базой БСП (просмотр заблокирован)";
ЗаписьЖурналаРегистрации("Интеграция.ОшибкаСвязи",
УровеньЖурналаРегистрации.Предупреждение, , ,
"Не удалось получить данные из БСП: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Если обе базы расположены в рамках одного локального сервера или быстрой локальной сети под управлением ОС Windows, можно прибегнуть к технологии COM-соединения с помощью V83.COMConnector.
Этот метод проще в реализации, поскольку не требует развертывания веб-серверов (Apache/IIS) и написания обработчиков HTTP. Он позволяет выполнять запросы и искать объекты во второй базе напрямую через встроенный язык 1С.
Рассмотрим пример функции на стороне УПП, выполняющей подключение к базе БСП и считывающей информацию в режиме реального времени:
Функция ПолучитьДанныеКонтрагентаЧерезCOM(КодКонтрагента) Экспорт
// Параметры подключения к серверной базе БСП
СтрокаПодключения = "Srvr=""MyServer"";Ref=""bsp_prod"";Usr=""ComUser"";Pwd=""ComPassword"";";
Попытка
COMСоединитель = Новый COMОбъект("V83.COMConnector");
// Выполняем подключение к базе БСП
БазаБСП = COMСоединитель.Connect(СтрокаПодключения);
Исключение
ЗаписьЖурналаРегистрации("Интеграция.COM", УровеньЖурналаРегистрации.Ошибка, , ,
"Ошибка создания COM-подключения: " + ОписаниеОшибки());
Возврат Неопределено;
КонецПопытки;
// Работаем с объектами базы БСП через полученную ссылку
СсылкаНаКонтрагента = БазаБСП.Справочники.Контрагенты.НайтиПоКоду(КодКонтрагента);
Если БазаБСП.ЗначениеЗаполнено(СсылкаНаКонтрагента) Тогда
Данные = Новый Структура;
Данные.Вставить("Наименование", СсылкаНаКонтрагента.Наименование);
Данные.Вставить("ИНН", СсылкаНаКонтрагента.ИНН);
Данные.Вставить("КПП", СсылкаНаКонтрагента.КПП);
Возврат Данные;
КонецЕсли;
Возврат Неопределено;
КонецФункции
Важное предупреждение: Несмотря на простоту, использование COM-соединения имеет ряд критических ограничений:
Если бесшовная интеграция подразумевает не просто передачу реквизитов, а полноценную интерактивную работу пользователя с формами из самописной базы (например, создание сложных документов), то можно воспользоваться технологией смешанного интерфейса платформы 1С.
Платформа 1С:Предприятие 8.3 позволяет запускать сеанс УПП в режиме обычного приложения, но при этом открывать внутри него управляемые формы. Для этого выполняются следующие действия:
ИспользоватьУправляемыеФормыВОбычномПриложении.ОткрытьФорму() с указанием пути к управляемой форме.В этом случае управляемая форма может осуществлять асинхронное взаимодействие со второй базой через упомянутые выше HTTP-сервисы, предоставляя пользователю современный и действительно «бесшовный» UX прямо внутри интерфейса УПП 1.3.
Выяснив все технические детали, можно сделать однозначный вывод: если вам требуется объединить 1С:УПП и самописную базу на БСП без использования тяжеловесных промежуточных шин данных, делайте выбор в пользу HTTP-сервисов на стороне БСП.
Этот подход гарантирует высокую скорость отклика интерфейса УПП, минимизирует риски зависаний при отсутствии сети и обеспечивает полную масштабируемость вашего решения на будущее, в том числе при возможном последующем переходе с УПП на современные конфигурации линейки 1С:ERP.