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