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