П ервая статья принесла один отклик, однако он оказался настолько концептуальным, что пришлось сесть за написание второй части. У новой технологии нет ни одного из недостатков, упомянутых в первой статье. Кроме того, описанную идею можно использовать и в других целях. Например, для организации детального журналирования изменений БД, совершенных пользователем.
автор статьи: Фёдор Езеев
fe@alterplast.ru
опубликовано:
апрель 2003
Первая мысль анализировать документ в момент записи, и в зависимости от того, что было изменено, принимать решение: перепроводить насильно, или без этого можно обойтись.
Первое решение, пришедшее в голову было таким: нужно отлавливать момент изменения
реквизита, и в зависимости от того, какой реквизит изменять (или не изменять)
некую переменную формы документа. В процедуре
Однако, уважаемый Mx@mail.ru и здесь проявил
могучий разум, он предложил еще одну здравую мысль (просто результат он знал заранее
Теория кончилась берем в руки клавиатуру и пишем код. Начнем с анализа реквизитов шапки.
//Берем документ из БД Д=СоздатьОбъект("Документ"); Д.НайтиДокумент(ТекущийДокумент()); МетаД=Метаданные.Документ(Вид()); //Определим, изменился реквизит, или нет Для С=1 По МетаД.РеквизитШапки() Цикл РеквИД=МетаД.РеквизитШапки(С).Идентификатор; СтароеЗначение=Д.ПолучитьАтрибут(РеквИД); НовоеЗначение=ПолучитьАтрибут(РеквИД); Если СтароеЗначение<>НовоеЗначение Тогда Сообщить("Изменился реквизит шапки "+РеквИД); Сообщить("Старое значение: "+СтароеЗначение); Сообщить("Новое значение: "+НовоеЗначение); Сообщить("==============================="); КонецЕсли; КонецЦикла; |
Теперь я хочу понять, насколько критичны сделанные изменения. И сообщить только о критичных.
// В список значений занесем идентификаторы тех реквизитов, // изменение которых нас не волнует Косметика=СоздатьОбъект("СписокЗначений"); Косметика.ДобавитьЗначение("Комментарий"); Косметика.ДобавитьЗначение("Автор"); Д=СоздатьОбъект("Документ"); Д.НайтиДокумент(ТекущийДокумент()); МетаД=Метаданные.Документ(Вид()); Для С=1 По МетаД.РеквизитШапки() Цикл РеквИД=МетаД.РеквизитШапки(С).Идентификатор; Если Косметика.НайтиЗначение(РеквИД)>0 Тогда Продолжить; КонецЕсли; СтароеЗначение=Д.ПолучитьАтрибут(РеквИД); НовоеЗначение=ПолучитьАтрибут(РеквИД); Если СтароеЗначениеНовоеЗначение Тогда Сообщить("Изменился реквизит шапки "+РеквИД); Сообщить("Старое значение: "+СтароеЗначение); Сообщить("Новое значение: "+НовоеЗначение); Сообщить("==============================="); КонецЕсли; КонецЦикла; |
Ну и в заключение на основании сделанного анализа примем нужное нам решение.
Процедура ПриЗаписи() Если Выбран()=0 Тогда Возврат; КонецЕсли; Косметика=СоздатьОбъект("СписокЗначений"); Косметика.ДобавитьЗначение("Комментарий"); Косметика.ДобавитьЗначение("Автор"); ИзменениеКритично=0; Д=СоздатьОбъект("Документ"); Д.НайтиДокумент(ТекущийДокумент()); МетаД=Метаданные.Документ(Вид()); Для С=1 По МетаД.РеквизитШапки() Цикл РеквИД=МетаД.РеквизитШапки(С).Идентификатор; Если Косметика.НайтиЗначение(РеквИД)>0 Тогда Продолжить; КонецЕсли; СтароеЗначение=Д.ПолучитьАтрибут(РеквИД); НовоеЗначение=ПолучитьАтрибут(РеквИД); Если СтароеЗначение<>НовоеЗначение Тогда ИзменениеКритично=1; //Одного критичного изменения вполне достаточно Возврат; КонецЕсли; КонецЦикла; Если ИзменениеКритично=0 Тогда ПриЗаписиПерепроводить(0); Записать(); ПриЗаписиПерепроводить(1); СтатусВозврата(0);Возврат; КонецЕсли; КонецПроцедуры |
Общая картина ясна. Осталось только дописать анализ общих реквизитов и табличной части документа. Проблема может возникнуть разве что со сравнением табличной части. Тут главное не забыть о том, что кроме изменения строк бывает еще и удаление и добавление.
Кусочек, сравнивающий строки, будет выглядеть примерно так (предполагаем, что любое изменение табличной части требует перепроведения):
Если КоличествоСтрок()<>Д.КоличествоСтрок() Тогда ИзменениеКритично=1; Возврат; Иначе ВыбратьСтроки(); Пока ПолучитьСтроку()=1 Цикл Д.ПолучитьСтрокуПоНомеру(НомерСтроки); Для С=1 По МетаД.РеквизитТабличнойЧасти() Цикл РеквИД=МетаД.РеквизитТабличнойЧасти(С).Идентификатор; СтароеЗначение=Д.ПолучитьАтрибут(РеквИД); НовоеЗначение=ПолучитьАтрибут(РеквИД); Если СтароеЗначение<>НовоеЗначение Тогда ИзменениеКритично=1; Возврат; КонецЕсли; КонецЦикла; КонецЦикла; КонецЕсли; |
Преимуществами этого метода можно признать:
- Прозрачность для пользователя.
- Размещение кода, ответственного за одну задачу в одном месте.
- Отсутствие "каскада записей" при изменении сразу нескольких "неважных" реквизитов.
Начать дискуссию