Как правильно зафиксировать дату создания документа в 1С и предотвратить ее изменение

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке систем на платформе 1С:Предприятие 8 часто возникает задача разделения оперативной даты документа (которая определяет момент отражения операции в учете) и реальной даты создания записи в базе данных. Это необходимо для контроля работы персонала, построения отчетов по KPI менеджеров или для интеграции с внешними системами. Разберем подробно, как реализовать этот механизм правильно, избежав типичных ошибок новичков.

Почему нельзя использовать только формы

Рассмотрим ситуацию: разработчик добавляет код заполнения даты в событие формы ПриСозданииНаСервере. На первый взгляд, это работает. Однако проанализируем риски. Документ может быть создан программно (например, через обмен данными, внешнюю обработку или фоновое задание). В этом случае форма документа вообще не открывается, и ваш реквизит ДатаСоздания останется пустым. Поэтому основную логику заполнения данных всегда следует выносить в модуль объекта.

Способ 1. Использование обработчика ПередЗаписью (Рекомендуемый)

Наиболее надежный метод фиксации момента появления документа в базе данных — это использование обработчика ПередЗаписью в модуле объекта. Этот метод гарантирует, что дата будет записана ровно один раз в момент самого первого сохранения документа.

Проанализируем пример кода, который необходимо разместить в модуле объекта:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
	
	// Проверяем, является ли объект новым (еще не записанным в БД)
	Если ЭтоНовый() Тогда
		// Фиксируем дату именно в момент первой записи
		ДатаСоздания = ТекущаяДатаСеанса();
	КонецЕсли;
	
КонецПроцедуры

В данном примере мы используем метод ЭтоНовый(). Он возвращает Истина, если ссылка на документ еще не была сформирована в базе данных. Как только документ будет записан, при последующих изменениях условие ЭтоНовый() станет ложным, и дата создания не перезапишется.

Способ 2. Обработка заполнения и копирования

Иногда требуется зафиксировать дату в тот момент, когда пользователь только нажал кнопку "Создать", еще до момента записи. Для этого используется процедура ОбработкаЗаполнения. Но здесь есть важный нюанс — копирование документов.

При стандартном копировании платформа копирует все реквизиты, включая вашу ДатуСоздания от старого документа. Чтобы в новом документе-копии появилась актуальная дата, необходимо использовать следующий подход в модуле объекта:


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
	// Заполняем дату при обычном создании
	ДатаСоздания = ТекущаяДатаСеанса();
КонецПроцедуры

Процедура ПриКопировании(ОбъектКопирования)
	// При копировании обязательно обновляем дату на текущую
	ДатаСоздания = ТекущаяДатаСеанса();
КонецПроцедуры

Важный момент: если вы используете и ОбработкаЗаполнения, и ПередЗаписью, следите за тем, чтобы логика не противоречила друг другу. Обычно достаточно одного из этих методов в зависимости от бизнес-задачи.

Выбор функции: ТекущаяДата() или ТекущаяДатаСеанса()

Рассмотрим разницу между этими функциями, так как это критично для распределенных систем.

  1. ТекущаяДата() — возвращает время сервера, на котором выполняется код. Если сервер находится в Москве, а пользователь во Владивостоке, в документе будет московское время.
  2. ТекущаяДатаСеанса() — возвращает время с учетом часового пояса, установленного в настройках пользователя.

Для корректного отображения времени создания документа с точки зрения пользователя всегда используйте ТекущаяДатаСеанса().

Почему не стоит извлекать дату из ссылки (GUID)

В среде разработчиков иногда обсуждается возможность получения даты создания из уникального идентификатора ссылки (GUID). Проанализируем, почему это "моветон":

Вывод: создание отдельного реквизита ДатаСоздания с включенным индексированием — самый правильный путь.

Как заполнить данные для старых документов

Если вы добавили реквизит в уже работающую базу, у старых документов он будет пустым. Выясним, как это исправить. Простое заполнение датой из реквизита Дата может быть неточным, если документы вводились "задним числом".

Рассмотрим вариант использования Журнала регистрации. С помощью программного кода можно прочитать события добавления объектов:


Фильтр = Новый Структура;
Фильтр.Вставить("Данные", СсылкаНаОбъект);
Фильтр.Вставить("Событие", "_$Data$_.New"); // Событие создания

ТаблицаСобытий = Новый ТаблицаЗначений;
ВыгрузитьЖурналРегистрации(ТаблицаСобытий, Фильтр);

Если ТаблицаСобытий.Количество() > 0 Тогда
    ДатаРеальногоСоздания = ТаблицаСобытий[0].Период;
КонецЕсли;

Этот метод позволяет ретроспективно восстановить реальную хронологию событий в базе данных и заполнить новый реквизит максимально достоверно.

Настройка интерфейса и прав доступа

Чтобы пользователь не мог изменить зафиксированную дату вручную на форме, выполните следующие действия:

  1. Вынесите реквизит на форму документа.
  2. В свойствах элемента формы установите флаг Только просмотр (или Доступность = Ложь).
  3. В идеале, на уровне прав доступа (ролей) запретите редактирование этого поля для всех, кроме администратора.

Так мы обеспечим неизменность данных и доверие к отчетности, которая будет строиться на основе этого реквизита.

← На главную