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