Почему не вызывается функция общего модуля из Веб-сервиса и как правильно создать документ на основе полученных данных?

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

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

Анализ контекста выполнения веб-сервиса

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

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

Настройка свойств общего модуля

Выясним причину, по которой метод общего модуля может быть «не обнаружен». Основная ошибка кроется в неправильной расстановке флагов в свойствах общего модуля. Рассмотрим, какие настройки должны быть установлены для модуля, к которому обращается веб-сервис:

1. Флаг «Сервер»: Должен быть включен обязательно, так как веб-сервис — это серверная операция.

2. Флаг «Внешнее соединение»: Это критически важный момент. Поскольку сеанс веб-сервиса часто идентифицируется платформой аналогично внешнему соединению, отсутствие этого флага сделает модуль недоступным для вызова из модуля веб-сервиса.

3. Флаг «Вызов сервера»: Многие ошибочно включают этот флаг, пытаясь «достучаться» до модуля. Однако Вызов сервера нужен только для обращения из клиентского модуля (формы) к серверному общему модулю. В случае с веб-сервисом этот флаг не требуется и иногда может мешать, если комбинируется с другими клиентскими флагами.

Рассмотрим рекомендации по разделению модулей. Если ваш общий модуль предназначен для работы и в обычном интерфейсе, и через веб-сервис, лучше всего разделить логику или убедиться, что у модуля стоят только флаги «Сервер» и «Внешнее соединение».

Директивы компиляции в общем модуле

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

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

Корректное создание документа и заполнение табличной части

Разберем типичную ошибку при работе с данными. Часто разработчики пытаются обратиться к табличной части через менеджер документа, что вызывает ошибку «Поле объекта не обнаружено». Посмотрим на неправильный пример:


// ОШИБОЧНЫЙ КОД
ТЧ = Документы.ЗаказПокупателя.ТЧНоменклатура; // Это обращение к метаданным, так делать нельзя!

Для работы с данными документа необходимо сначала создать экземпляр объекта. Рассмотрим правильный алгоритм создания документа ЗаказПокупателя на основе структуры данных, полученной из мобильного приложения:


Процедура СоздатьЗаказИзМобильногоПриложения(СтруктураДанных) Экспорт
    
    // Создаем новый объект документа
    НовыйДокумент = Документы.ЗаказПокупателя.СоздатьДокумент();
    НовыйДокумент.Дата = ТекущаяДата();
    НовыйДокумент.Партнер = СтруктураДанных.Контрагент;
    // Заполняем остальные реквизиты шапки...

    // Переходим к заполнению табличной части
    // Предположим, что данные пришли в виде массивов внутри структуры
    
    Для Каждого ЭлементНоменклатуры Из СтруктураДанных.СписокНоменклатуры Цикл
        
        // Добавляем новую строку в ТЧ конкретного ОБЪЕКТА
        НоваяСтрока = НовыйДокумент.ТЧНоменклатура.Добавить();
        НоваяСтрока.Номенклатура = ЭлементНоменклатуры;
        
        // Если комментарии передаются отдельным массивом (важно соблюдать индексы!)
        // Но лучше передавать массив структур, где номенклатура и комментарий связаны
        
    КонецЦикла;

    Попытка
        НовыйДокумент.Записать(РежимЗаписиДокумента.Запись);
    Исключение
        ЗаписьЖурналаРегистрации("ОшибкаВебСервиса", УровеньЖурналаРегистрации.Ошибка, , , ОписаниеОшибки());
        ВызватьИсключение "Не удалось создать документ: " + ОписаниеОшибки();
    КонецПопытки;

КонецПроцедуры

Синхронизация данных: Массивы vs Структуры

Выясним, как лучше передавать данные табличных частей. В сообщениях форума предлагалось использовать метод ЗагрузитьКолонку(). Рассмотрим этот метод: он удобен, но опасен. Если в одном массиве данных будет больше, чем в другом, информация в строках «съедет», и комментарий от одного товара прикрепится к другому.

Рекомендация: Передавайте данные в виде единого массива структур. Каждая структура должна представлять собой законченную строку документа. Например:


// Пример структуры данных строки
СтрокаТЧ = Новый Структура;
СтрокаТЧ.Вставить("Номенклатура", СсылкаНаТовар);
СтрокаТЧ.Вставить("Количество", 10);
СтрокаТЧ.Вставить("Комментарий", "Срочная доставка");

В этом случае при обходе массива в цикле вы гарантированно получите связанные данные для каждой строки НовыйДокумент.ТЧНоменклатура.Добавить().

Дополнительные советы по отладке

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

  1. Журнал регистрации: Используйте ЗаписьЖурналаРегистрации() внутри блока Попытка...Исключение. Это позволит вам увидеть реальный текст ошибки, даже если веб-сервис вернул клиенту стандартное сообщение об ошибке SOAP.
  2. Привилегированный режим: Если веб-сервис запущен под пользователем с ограниченными правами, создание документов может блокироваться системой прав 1С. В таком случае в общем модуле стоит установить флаг «Привилегированный», чтобы запись документа производилась без проверки прав доступа (если это допустимо политикой безопасности).
  3. Проверка типов XDTO: Если вы передаете сложные объекты через параметры веб-сервиса, убедитесь, что типы в XDTO-пакете соответствуют типам в 1С. Любое несовпадение приведет к тому, что метод в модуле веб-сервиса даже не начнет выполняться, выдав ошибку десериализации.

Подводя итог, можно сказать: для успешного вызова общего модуля из веб-сервиса необходимо обеспечить его доступность через флаги «Сервер» и «Внешнее соединение», убрать лишние директивы компиляции и работать с документами через создание Объекта, а не через менеджер метаданных.

← На главную