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