Проверка изменения данных при записи объектов

В некоторых случаях при записи объектов возникает необходимость проверки, какие данные объекта были изменены и какие были значения до изменения.

Допустим, при записи документа, может возникнуть потребность проверить, не изменилась ли дата документа, и если дата изменилась, то откорректировать движения документа, которые не обновляются при его проведении (например, вводятся вручную).

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

Правильным способом реализации такой проверки является считывание значений тех реквизитов, изменения которых нужно анализировать, непосредственно из базы данных.

Например, считывание может быть выполнено обращением через ссылку:

Копировать в буфер обмена
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)

	ДатаДокумента = Ссылка.Дата; 
	Если ДатаДокумента <> Дата Тогда 
		Сообщить("Дата изменена");
	КонецЕсли; 

КонецПроцедуры 

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

Копировать в буфер обмена
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения) 

	ДатаДокумента = '00010101'; 

	Если Не ЭтоНовый() Тогда 
		Запрос = Новый Запрос; 
		Запрос.Текст = "ВЫБРАТЬ 
		| Документ1.Дата 
		|ИЗ 
		| Документ.Документ1 КАК Документ1 
		|ГДЕ 
		| Документ1.Ссылка = &Ссылка"; 

		Запрос.УстановитьПараметр("Ссылка", Ссылка); 

		Результат = Запрос.Выполнить(); 
		Выборка = Результат.Выбрать(); 
		
		Если Выборка.Следующий() Тогда 
			ДатаДокумента = Выборка.Дата; 
		КонецЕсли; 
	КонецЕсли; 

	Если ДатаДокумента <> Дата Тогда 
		Сообщить("Дата изменена"); 
	КонецЕсли; 

КонецПроцедуры 

В этом случае из базы данных будет считан ровно один реквизит, который требуется анализировать.

Заметим, что таким способом можно, например, определить, что объект помечается на удаление. Для этого достаточно проверить, изменение поля ПометкаУдаления.

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