Как исправить ошибку "Попытка передачи мутабельного значения" при интеграции ЗУП и Документооборота через COM?

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

При интеграции различных конфигураций 1С, например, при попытке создать и записать документ из "Зарплата и Управление Персоналом" в "Документообороте" через COM-соединение, можно столкнуться с ошибкой "Попытка передачи мутабельного значения". Эта ошибка возникает в момент записи объекта и часто ставит в тупик, особенно если не был проведен предварительный анализ конфигурации на наличие ошибок в вызовах общих модулей или нет возможности изменять код в принимающей базе.

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

Анализ проблемы: почему платформа запрещает передачу мутабельных значений

Для начала проанализируем ситуацию. У нас есть код в ЗУП, который подключается к Документообороту, создает объект справочника ВнутренниеДокументы, заполняет его и пытается записать.

Пример кода в системе-источнике (ЗУП):


&НаСервере
Процедура СоздатьСЗ_СЗ_ЭДО()	 
	
	БазаДО = ПодключитьсяКБазе(); // COM-соединение
	
	// ... Проверки ...
	
	ДокументОбъект  = БазаДО.Справочники.ВнутренниеДокументы.СоздатьЭлемент();
	
	// ... Заполнение реквизитов ...
	БазаДО.ШаблоныДокументов.ЗаполнитьРеквизитыДокументаПоШаблону(ШаблонДокумента, ДокументОбъект);
	ЗаполнитьВнутреннийДокумент(БазаДО, ДокументОбъект, Структура);
	
	// ...
	
	// В этот момент происходит ошибка
	ДокументОбъект.Записать();
КонецПроцедуры

Ошибка возникает не в этом коде, а в коде, который выполняется в Документообороте в обработчике события ПриЗаписи для этого документа. В нашем случае это вызов нетиповой процедуры ПолучитьПредварительныРегистрационныйНомер, где могут быть реализованы различные настраиваемые действия и условия проверки при записи.

Пример кода в системе-приемнике (Документооборот):


Процедура ПолучитьПредварительныРегистрационныйНомер(ОбъектЗаписи) Экспорт 
	
	Если ОбъектЗаписи.Порт_НеРегистрируется Или ЗначениеЗаполнено(ОбъектЗаписи.Порт_РегистрационныйНомер) Тогда
		Возврат;
	КонецЕсли;
	
	// ... Логика ...

	// Попытка ИЗМЕНИТЬ переданный объект
	ОбъектЗаписи.ДатаРегистрации = ТекущаяДатаСеанса();
	// ...
	ОбъектЗаписи.Порт_РегистрационныйНомер = ОбъектЗаписи.РегистрационныйНомер;
	ОбъектЗаписи.РегистрационныйНомер = "";
	ОбъектЗаписи.ДатаРегистрации = Дата('00010101');
		
КонецПроцедуры

Выясним причину ошибки, разобрав ключевые понятия:

  1. Что такое мутабельное значение? В контексте 1С это изменяемый объект, например, ДокументОбъект.ВнутреннийДокумент или СправочникОбъект.Номенклатура. В отличие от примитивных, неизменяемых типов (число, строка, дата) или ссылок (ДокументСсылка), объект содержит полную совокупность своих данных и методов и может быть изменен.
  2. Почему возникает ошибка? Платформа "1С:Предприятие" имеет строгое разделение контекстов выполнения кода: клиент и сервер. COM-соединение с точки зрения удаленной базы является "клиентом". Когда из ЗУП (клиент) вызывается метод ДокументОбъект.Записать(), управление передается на сервер Документооборота. Серверный код в ДО (процедура ПолучитьПредварительныРегистрационныйНомер) получает этот самый ДокументОбъект и пытается его модифицировать. Платформа блокирует это действие, так как запрещено изменять на сервере объект, который был создан и "принадлежит" клиенту (в данном случае — COM-клиенту). Это механизм защиты целостности данных.

Таким образом, ошибка является не багом, а следствием архитектурно неверного подхода к интеграции. Код в Документообороте (особенно нетиповой) не рассчитан на то, что его будут вызывать из внешнего соединения, передавая ему "живой" объект для модификации.

Обходные пути при COM-соединении (и почему они не сработают)

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

Создать в Документообороте специальную "обертку" — экспортную процедуру в общем модуле с флагами "Сервер" и "Внешнее соединение". Эта процедура должна принимать не объект, а структуру с примитивными данными (строки, числа, ссылки).

Правильный код в Документообороте (гипотетический):


// Процедура в общем модуле Документооборота
Процедура СоздатьВнутреннийДокументИзВнешнейСистемы(ПараметрыДокумента) Экспорт

    // 1. Создаем объект ВНУТРИ своей базы
    НовыйДокумент = Справочники.ВнутренниеДокументы.СоздатьЭлемент();
    
    // 2. Заполняем его из структуры примитивных данных
    ЗаполнитьЗначенияСвойств(НовыйДокумент, ПараметрыДокумента);
    
    // 3. Выполняем запись. Все серверные события отработают корректно,
    // так как объект "родной" для этого сервера.
    НовыйДокумент.Записать();

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

Однако в рассматриваемой ситуации изменять код в Документообороте нельзя. Это означает, что обойти вызов серверного события, которое пытается изменить наш объект, невозможно. Следовательно, решить проблему в рамках текущего COM-подхода не получится.

Рекомендованное решение: "Бесшовная интеграция" через БИД

Вместо устаревшего и хрупкого COM-взаимодействия для интеграции типовых конфигураций 1С следует использовать штатный механизм — "Библиотеку интеграции с Документооборотом" (БИД).

БИД — это специальная подсистема, которая встроена в большинство современных конфигураций (включая ЗУП) и предназначена для организации так называемой "бесшовной интеграции". Она позволяет реализовать даже такие сложные задачи, как добавление состояния согласования из 1С: Документооборот непосредственно в интерфейс системы-источника.

Преимущества использования БИД

Что делать на практике?

Поскольку подсистема БИД уже встроена в вашу конфигурацию ЗУП, необходимо выполнить ее настройку.

  1. Опубликовать веб-сервисы. На стороне 1С:Документооборот необходимо опубликовать на веб-сервере (IIS или Apache) стандартные веб-сервисы, которые используются для интеграции.
  2. Настроить интеграцию в ЗУП. В разделе администрирования ЗУП найти настройки интеграции с 1С:Документооборотом, указать адрес опубликованных веб-сервисов и данные для аутентификации.
  3. Настроить правила интеграции. Определить, какие объекты ЗУП будут связаны с какими видами документов в Документообороте, учитывая при необходимости множественные дополнительные реквизиты, если используется версия 3.0.
  4. Переписать код. Отказаться от COM-соединения и использовать функции и процедуры БИД для создания документов. Это будет выглядеть не как прямое создание объекта, а как вызов функции, которая отправит данные в Документооборот, а тот уже сам создаст документ.

Итог: Ошибка "Попытка передачи мутабельного значения" — это верный признак того, что выбранный метод интеграции (прямой COM) является архитектурно неверным для данной задачи. Не стоит пытаться "победить" платформу. Вместо этого необходимо перейти на современный, поддерживаемый и надежный способ интеграции, которым является "Бесшовная интеграция" с использованием БИД.

← На главную