Почему возникает ошибка глобальных функций в модуле объекта при вызове из веб-сервиса 1С и как её исправить?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции сторонних систем с 1С через SOAP/HTTP веб-сервисы разработчики нередко сталкиваются с ситуацией, когда попытка вызвать метод объекта документа или справочника (например, функцию печати или заполнения) приводит к критической ошибке: «Ошибка инициализации модуля» или сообщению о том, что глобальные переменные и функции не определены. Проанализируем причины этой ошибки и разберем по шагам правильные архитектурные способы её устранения.

Причины возникновения ошибки контекста и компиляции

Для понимания проблемы выясним, в каком именно окружении исполняется код веб-сервиса в платформе «1С:Предприятие»:

  1. Контекст веб-сервиса: вызовы методов веб-сервиса всегда происходят исключительно на стороне сервера в неинтерактивном сеансе (контекст Сервер). Сеанс веб-сервиса не является внешним соединением (COM-соединением), поэтому директива препроцессора #Если ВнешнееСоединение для него не срабатывает.
  2. Принцип полной компиляции модуля объекта: при создании объекта или получении ссылки на сервере модуль объекта компилируется целиком. Если в модуле объекта присутствуют вызовы клиентских процедур (например, Предупреждение(), Вопрос(), вызовы методов форм) или обращения к общим модулям, у которых выключен флажок «Сервер», компилятор 1С выдает ошибку инициализации модуля, даже если вызываемый метод не использует эти проблемные участки.
  3. Устаревший код обычного приложения: в конфигурациях, созданных для толстого клиента, модули объектов часто содержат смешанный интерактивный и серверный код, не разделенный директивами препроцессора.

Способ 1. Корректная изоляция клиентского кода директивами препроцессора

Рассмотрим первый вариант решения, когда требуется быстро адаптировать существующий модуль объекта без масштабного рефакторинга. Для этого изолируем все клиентские и интерактивные вызовы с помощью директив препроцессора.

Разберем пример: если в модуле объекта содержатся функции отображения диалогов или работы с интерфейсом, заключим их в соответствующие блоки:


#Если Клиент Тогда
Процедура ПоказатьДиалогПользователю()
    Предупреждение("Операция завершена успешно!");
КонецПроцедуры
#КонецЕсли

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


#Если ТолстыйКлиентОбычноеПриложениеКлиент Тогда
Процедура ИнтерактивнаяПроверка()
    // Клиентский код, недоступный в веб-сервисе
    Предупреждение("Проверьте заполнение реквизитов");
КонецПроцедуры
#КонецЕсли

Важно: проверку синтаксиса в конфигураторе необходимо выполнять с включенным флажком «Сервер» (меню Сервис — Параметры — Модули — Проверка), а не только в режиме «Внешнее соединение».

Способ 2. Перенос логики формирования печатных форм в модуль менеджера

Посмотрим на более правильный с точки зрения стандартов разработки «1С:Предприятия 8» подход. Модули объектов предназначены для обеспечения целостности данных самого объекта (обработчики событий ПередЗаписью, ПриЗаписи, ОбработкаПроведения). Процедуры печати, отчетов и формирования табличных документов рекомендуется размещать в модуле менеджера объекта.

Преимущества модуля менеджера:

  1. Модуль менеджера компилируется исключительно на сервере и не содержит клиентского интерфейсного контекста.
  2. Для вызова процедуры печати из модуля менеджера не требуется создавать экземпляр объекта через Ссылка.ПолучитьОбъект(), что снижает нагрузку на серверную память и исключает блокировки.

Разберем пример переноса функции печати в модуль менеджера документа:


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

Способ 3. Вынос логики в серверный общий модуль и передача результата через веб-сервис

Проанализируем процесс вызова метода и передачи сформированного табличного документа через веб-сервис клиенту. Создадим или используем серверный общий модуль (с установленными свойствами «Сервер» и «Вызов сервера»).

В методе веб-сервиса формируем ТабличныйДокумент, сохраняем его в двоичные данные (например, в формате PDF) и возвращаем клиенту:


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

Проверка свойств общих модулей конфигурации

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

  1. Найдем общий модуль в дереве метаданных.
  2. Откроем палитру свойств модуля.
  3. Убедимся, что для глобального модуля (установлен флаг Глобальный) установлен флажок «Сервер». Если флажок снят и стоит только «Клиент (управляемое приложение)», в сеансе веб-сервиса данный модуль и его процедуры будут недоступны.
← На главную