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