В процессе разработки интеграций через веб-сервисы программисты часто сталкиваются с необходимостью выполнить программный код, который уже написан и отлажен внутри формы документа (например, процедуру отправки почты или специфического расчета). Однако прямая попытка вызвать процедуру из МодульФормы в контексте выполнения веб-сервиса приводит к ошибкам. Давайте детально разберем, почему это происходит и как правильно организовать архитектуру кода, чтобы избежать подобных проблем.
Разберем ситуацию: веб-сервис 1С работает в рамках отдельного сеанса. Этот сеанс является фоновым и серверным по своей сути. В нем отсутствует клиентское приложение, а значит, графический интерфейс (GUI) не инициализируется. Когда мы пытаемся использовать метод ПолучитьФорму() внутри кода веб-сервиса, мы сталкиваемся с несколькими критическими ограничениями:
Сообщить(), Предупреждение() или ОткрытьФорму(). В сеансе веб-сервиса любые интерактивные действия запрещены и вызывают аварийное завершение работы (Runtime Error).Наиболее правильным и архитектурно верным решением является вынос общей бизнес-логики в Общий модуль. Это позволяет переиспользовать один и тот же код и в форме документа, и в веб-сервисе, и в регламентных заданиях.
Рассмотрим по шагам, как это реализовать:
1. Создадим (или используем существующий) общий модуль, например, РаботаСРассылкамиСервер. Установим у него свойства «Сервер» и «Вызов сервера».
2. Перенесем процедуру ВыслатьПочту из модуля формы в этот общий модуль и сделаем её экспортной:
// В общем модуле РаботаСРассылкамиСервер
Процедура ОтправитьПочтуПоДокументу(СсылкаНаДокумент, ПараметрыСообщения) Экспорт
// Логика формирования и отправки письма
// Используем СсылкаНаДокумент вместо Объект.Ссылка
ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
// Выполняем действия по отправке
// ...
КонецПроцедуры
3. Теперь и в модуле формы, и в веб-сервисе мы будем просто обращаться к этой процедуре:
// В модуле формы документа
&НаСервере
Процедура КомандаОтправитьПисьмо(Команда)
ПараметрыСообщения = Новый Структура("Тема, Текст", "Уведомление", "Текст сообщения");
РаботаСРассылкамиСервер.ОтправитьПочтуПоДокументу(Объект.Ссылка, ПараметрыСообщения);
КонецПроцедуры
// В модуле веб-сервиса
Функция ВызватьОтправку(ИдентификаторДокумента)
СсылкаДок = Документы.ЗаказПокупателя.ПолучитьСсылку(Новый УникальныйИдентификатор(ИдентификаторДокумента));
РаботаСРассылкамиСервер.ОтправитьПочтуПоДокументу(СсылкаДок, Неопределено);
Возврат "Успешно";
КонецФункции
Если логика тесно связана с данными конкретного документа, её можно разместить в модуле менеджера или модуле объекта. Разберем разницу:
Модуль менеджера: Идеален для методов, которым не нужно состояние конкретного экземпляра объекта (например, печать по ссылке или массовая обработка данных). Обращение к нему происходит быстро, так как не требует загрузки всего объекта из базы.
// В модуле менеджера документа
Процедура ВыслатьПочтуМенеджер(СсылкаНаДокумент) Экспорт
// Реализация логики
КонецПроцедуры
// Вызов из веб-сервиса
Документы.ВажныйДокумент.ВыслатьПочтуМенеджер(НужнаяСсылка);
Модуль объекта: Подходит, если процедура должна оперировать данными, которые могут быть еще не записаны в базу, или требует сложной проверки состояния объекта. Однако для вызова в веб-сервисе вам придется сначала получить объект через ПолучитьОбъект() или СоздатьДокумент().
// В модуле объекта
Процедура ВыслатьПочтуОбъект() Экспорт
// Работаем напрямую с реквизитами: ЭтотОбъект.Сумма, ЭтотОбъект.Дата
КонецПроцедуры
// Вызов из веб-сервиса
ДокОбъект = НужнаяСсылка.ПолучитьОбъект();
ДокОбъект.ВыслатьПочтуОбъект();
Проанализируем ситуацию, когда веб-сервис не просто должен выполнить действие, а должен заставить уже открытую у пользователя форму как-то отреагировать. Как мы выяснили, напрямую вызвать процедуру в чужом сеансе нельзя. В этом случае используем механизм «флагов» в базе данных:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ПодключитьОбработчикОжидания("ПроверитьОбновленияФормы", 10); // Проверка каждые 10 секунд
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьОбновленияФормы()
// Вызываем серверный метод для проверки изменений в базе
Если НужноОбновитьДанныеНаСервере(Объект.Ссылка) Тогда
// Выполняем процедуру модуля формы
ВыслатьПочту();
КонецЕсли;
КонецПроцедуры
Для более современных конфигураций (платформа 8.3.18+) рекомендуется использовать Систему взаимодействия. Веб-сервис может отправить сообщение в конкретный канал или пользователю, а клиентское приложение при получении этого сообщения мгновенно выполнит нужный код в форме без использования цикличных обработчиков ожидания.
Подведем итог нашему анализу. Попытка получить фрмДок = обДок.ПолучитьФорму(); фрмДок.ВыслатьПочту(); в веб-сервисе — это путь, ведущий к нестабильной работе системы.
Правильный алгоритм действий:
Ссылка на объект или Структура с данными, чтобы не зависеть от контекста формы.Такой подход соответствует стандартам разработки фирмы «1С» и обеспечивает высокую производительность и надежность вашей системы при интеграции с внешними сервисами.