При интеграции различных систем с конфигурациями на базе 1С:Предприятие 8.3 часто используется механизм COM-соединения. Однако разработчики нередко сталкиваются со специфической ошибкой при попытке пометить на удаление именно проведенный документ. В то время как обычные (черновики) документы обрабатываются корректно, проведенные вызывают исключение: "Попытка передачи с клиента на сервер мутабельного значения 1-го параметра метода УдалитьДвиженияРегистратора". Разберем подробно, почему это происходит и как правильно решить данную задачу.
Для начала проанализируем ситуацию: почему код успешно отрабатывает для непроведенных документов, но спотыкается на проведенных? Причина кроется в архитектуре платформы и особенностях работы внешнего соединения. Когда мы вызываем метод УстановитьПометкуУдаления(Истина) для проведенного документа, платформа автоматически инициирует процесс отмены проведения. В этот момент управление передается в модуль объекта документа, а именно в обработчик ОбработкаУдаленияПроведения.
В типовых конфигурациях, таких как "Бухгалтерия предприятия 3.0", внутри этого обработчика часто вызываются методы общих модулей для очистки движений по регистрам (например, ОбщегоНазначенияБПВызовСервера.УдалитьДвиженияРегистратора). Проблема заключается в следующем:
ДокументОбъект.Рассмотрим типовой код, который обычно приводит к этой ошибке при выполнении через COM:
// Код на стороне вызывающей системы
Пока РезультатЗапроса.Следующий() Цикл
НайденныйДокумент = РезультатЗапроса.Ссылка.ПолучитьОбъект();
// Ошибка возникнет здесь, если документ проведен
НайденныйДокумент.УстановитьПометкуУдаления(Истина);
КонецЦикла;
Самый простой, но не всегда рекомендуемый метод — это изменение свойств метаданных в конфигурации-приемнике. Как было замечено в ходе обсуждения проблемы, включение флага "Внешнее соединение" у проблемного общего модуля решает вопрос. В случае с БП 3.0 это модуль ОбщегоНазначенияБПВызовСервера.
После установки этой галочки платформа перестает считать вызов метода "переходом границы", требующим сложной сериализации мутабельного объекта, и выполнение кода продолжается в рамках того же процесса.
Минус этого подхода: Вам придется снять типовой общий модуль с поддержки, что усложнит дальнейшие обновления конфигурации. Рассмотрим более профессиональные методы.
Если ваша задача — просто пометить документ на удаление, игнорируя сложные проверки и не вызывая стандартные обработчики, можно воспользоваться свойством ОбменДанными.Загрузка. Этот флаг сообщает системе, что запись объекта производится в режиме обмена, и большинство проверок в модуле объекта (включая очистку движений через проблемные модули) будут пропущены.
Разберем, как это реализовать программно:
НайденныйДокумент = РезультатЗапроса.Ссылка.ПолучитьОбъект();
НайденныйДокумент.ОбменДанными.Загрузка = Истина;
НайденныйДокумент.ПометкаУдаления = Истина;
// Важно: нужно вручную отменить проведение, если это необходимо
НайденныйДокумент.Записать(РежимЗаписиДокумента.Запись);
Важный нюанс: При установке ОбменДанными.Загрузка = Истина стандартная очистка регистров не произойдет автоматически. Если документ был проведен, его движения "зависнут" в регистрах, хотя сам документ будет помечен на удаление. Поэтому этот способ требует дополнительной очистки движений программным путем, если целостность данных критична.
Наиболее правильным с точки зрения архитектуры 1С является перенос всей логики работы с объектом на сторону сервера конфигурации-приемника. Вместо того чтобы манипулировать объектом через COM напрямую, мы создаем специальную процедуру-обертку в своем собственном (не типовом) общем модуле.
Выполним следующие шаги:
КастомныйМодульCOM.Пример кода в новом модуле:
Процедура ПометитьДокументНаУдалениеНаСервере(СсылкаНаДокумент) Экспорт
// Весь код выполняется на сервере, передачи мутабельных значений через COM нет
ОбъектДокумента = СсылкаНаДокумент.ПолучитьОбъект();
Если ОбъектДокумента <> Неопределено Тогда
ОбъектДокумента.УстановитьПометкуУдаления(Истина);
КонецЕсли;
КонецПроцедуры
Теперь из внешней системы через COM-соединение мы вызываем не стандартный метод объекта, а нашу новую процедуру:
// Код во внешней системе
COMСоединение.КастомныйМодульCOM.ПометитьДокументНаУдалениеНаСервере(СсылкаНаДокумент);
В этом случае передается только Ссылка (которая не является мутабельным значением и легко сериализуется), а создание объекта и вызов всех обработчиков (включая очистку движений) происходит внутри одного серверного вызова. Это исключает возникновение ошибки контекста.
Выясним причину еще раз: ошибка "мутабельного значения" — это защитный механизм платформы 1С, предотвращающий некорректную передачу тяжелых объектов между клиентом/COM и сервером. При работе с проведенными документами эта проблема проявляется наиболее остро из-за срабатывания триггеров отмены проведения.
Подводя итог, при работе через COM-соединение старайтесь:
ДокументОбъект.ДокументСсылка) в серверные модули-обертки.Использование серверного "моста" является самым стабильным и безопасным решением, которое сохранит поддержку вашей конфигурации и обеспечит корректную работу бизнес-логики 1С.