Как перехватить момент перед записью...?

Автор Злоп, 05 сентября 2025, 13:38

« назад - далее »

Злоп

Обычная задача ведения лога изменений документа. Если нормально написано - то вкорячиапешь в ПриЗаписи() и норм. Но конфига самопальная, извращенная, запросто в коде формы документа встречается Записать(), ПриЗаписи() не отрабатывает. И прочие заморочки.
.
Поэтому куда можно вклиниться чтобы получить состояние контекста формы документа (изменений, но не записанный), самого документа через ТекущийДокумент() (без изменений еще), при этом чтобы после отработки моего кода пошла запись измененного документа.

И как вообще аннулировать запись в базу об изменениях если по какой-то причине запись измененного документа не прошла?

Мысли есть, но как-то некрасиво, извращенно получается.

Или может какой другой вариант/метод записи изменений документа по всем его реквизитам шапки и тч по типу "было-стало"

Злоп

Изменения фиксируются в базе документом "Протокол". Где в свободном виде в строку неограниченной длины пишется было-стало

Djelf

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

Теоретически было бы довольно просто так сделать - ПриНачалеИзменения забираем первичный документ в ит или sqlite, затем ПослеОкончанияИзменения опять забираем, сравниваем, загоняем в json и его пишем в базу sqlite, что важно, иначе кирдык твой таблице длинных строк.

Но первоначальное состояние точно и надежно никак не получить.

P.S. АльФ! С какой частотой тебя гугл сниферит? Я даже не нажал кнопку отправить, а он уже этот пост засниферил  :o

Злоп

Или сделать тупо просто
В Приоткрытии() запоминаем содержимое документа, а формексом Послезакрытия() сравниваем с уже текущим состоянием документа.
...
?

Djelf

Цитата: Злоп от 05 сентября 2025, 14:54Или сделать тупо просто
В Приоткрытии() запоминаем содержимое документа, а формексом Послезакрытия() сравниваем с уже текущим состоянием документа.
...
?
Так должно сработать. Попробуй. А ограничения я уже написал выше.
Ну и лучше в json в таблику sqlite писать, или сериализировать туда тз или итз, а вот в длинные строки этот так себе вариант. Плохой вариант...

Злоп

Цитата: Djelf от 05 сентября 2025, 14:52ПриОткрытии не сработает при программной записи.
ПриЗаписи не перехватывается, на 1с++ это неоднократно обсуждали.
ПриПроведении работает стабильно, но надо получить данные до  момента измения, а получить ты их не можешь.

Теоретически было бы довольно просто так сделать - ПриНачалеИзменения забираем первичный документ в ит или sqlite, затем ПослеОкончанияИзменения опять забираем, сравниваем, загоняем в json и его пишем в базу sqlite, что важно, иначе кирдык твой таблице длинных строк.

Но первоначальное состояние точно и надежно никак не получить.

P.S. АльФ! С какой частотой тебя гугл сниферит? Я даже не нажал кнопку отправить, а он уже этот пост засниферил  :o

Программную запись извне не рассматриваем.

Злоп

Цитата: Djelf от 05 сентября 2025, 15:02
Цитата: Злоп от 05 сентября 2025, 14:54Или сделать тупо просто
В Приоткрытии() запоминаем содержимое документа, а формексом Послезакрытия() сравниваем с уже текущим состоянием документа.
...
?
Так должно сработать. Попробуй. А ограничения я уже написал выше.
Ну и лучше в json в таблику sqlite писать, или сериализировать туда тз или итз, а вот в длинные строки этот так себе вариант. Плохой вариант...
Знаю что плохой вариант.
Костыли все это.
Можно тупо в файло писать, но как его закрыть что 1с может писать, а интерактивно ось пользователь ручками - не может. Хз.

Злоп

Цитата: Djelf от 05 сентября 2025, 15:02
Цитата: Злоп от 05 сентября 2025, 14:54Или сделать тупо просто
В Приоткрытии() запоминаем содержимое документа, а формексом Послезакрытия() сравниваем с уже текущим состоянием документа.
...
?
Так должно сработать. Попробуй. А ограничения я уже написал выше.
Ну и лучше в json в таблику sqlite писать, или сериализировать туда тз или итз, а вот в длинные строки этот так себе вариант. Плохой вариант...

Но тут засада
Во например ЗБ
Открыл - поправил - провел (тут выполняется запись) - поправил назад - провел (тут запись) - закрыл.

При записи зарегистрируется бы два факта изменения, а при выходе - ищменений нет...

Djelf

Ну и хорошо что при выходе изменений нет, зачем логгировать?

Djelf

Давай каждый клик логгировать, sqlite то справится, но нафейхоа?

Злоп

Цитата: Djelf от 05 сентября 2025, 15:17Ну и хорошо что при выходе изменений нет, зачем логгировать?
поправили - напечатали - поправили, вышли. Печатное и в базе - разное...
.
Приправильнрй конструкции документов/процессов все это можно обойти, но рефакторить туеву хучу всего не вариант

Djelf

Цитата: Злоп от 05 сентября 2025, 15:51
Цитата: Djelf от 05 сентября 2025, 15:17Ну и хорошо что при выходе изменений нет, зачем логгировать?
поправили - напечатали - поправили, вышли. Печатное и в базе - разное...
.
Приправильнрй конструкции документов/процессов все это можно обойти, но рефакторить туеву хучу всего не вариант

Товарищь Берия с таким бы справился...

Злоп

Я тоже согласен но персоналом рулю не я

Djelf

А как они смогли напечатать не измененный документ без записи а базу?
Можно тогда еще ПриПечатиТаблицы сниферить...

Но это реально глупость, прощать таки штучки и одновременно их мониторить. 

Ветер в поле

У меня это решено так. ПриОткрытии запоминаем текущее состояние документа. ПриЗакрытии сравниваем и записываем в базу.
С одной стороны тут есть бонус - промежуточные сохранения не забивают базу. С другой - если из документа не вышли, то информация об изменении не отразится в базе. Также в шапке документа есть счетчик перепроведений. В большинстве документов стоит запрет печати незаписанного документа. Точнее при нажатии на кнопку печати, документ записывается и проводится.
Данные изменений хранятся иерархически. Справочник ДокументыИзменения содержит все документы, для которых отслеживается история. Подчиненный ему справочник ИзмененияВДокументе содержит факты изменения, когда, где, кто изменил, тип изменения (провел, пометил на удаление, записал и т.д). Уже этому справочнику подчинен ИзмененияРеквизитовДокумента - тут содержатся измененные реквизиты шапки. Также для каждого документа с табличной частью сделаны справочники типа ИзмененныеСтрокиПоступлениеМатериала, которые содержат изменения в строках.
Такое хранение позволяет очень точно находить всякие специфические ситуации, потому что позволяет запросом поднять нужные данные. С помощью специального класса все манипуляции по поддержанию истории делается просто.
Были идеи по созданию отдельной базы, в которую будут периодически переноситься данные истории, но не понадобилось. Просто создал архивную базу, в которую раз в год переносились все данные за прошедший год. Поэтому есть архив за 14 лет и рабочая база за 1-2 года.

В каждом документе есть примерно такие строки:
Перем ОбъектФормаДокумента;

//*****************************************************************************
Процедура ПриОткрытии() //предопределенная
	
	Если ОбъектФормаДокумента.ПриОткрытии("кнХПредставитель", 1, 1, 1) = 0 Тогда //тут запоминается начальное состояние
		Возврат;
	КонецЕсли;
	
	Если Форма.ТолькоПросмотр() = 0 Тогда
		Если глПолучитьПолномочие("РазрешитьИзменятьДатуДокумента") = 0 Тогда
			глДоступностьРеквизитов(Контекст, "ДатаДок", 0);
		КонецЕсли;
	КонецЕсли;
	
	глАктивизироватьРеквизит(Контекст, "Статус", "ДатаДок", 1);
	
КонецПроцедуры //ПриОткрытии

//*****************************************************************************
Процедура ПриЗаписи() //предопределенная
	
	Если ОбъектФормаДокумента.ПриЗаписи_ВНачале("") = 0 Тогда //тут стандартные проверки на заполненность реквизитов и возможность записи
		Возврат;
	КонецЕсли;
	
	Если ОбъектФормаДокумента.ПриЗаписи() = 0 Тогда //тут взводится флаг записи документа
		Возврат;
	КонецЕсли;
	
КонецПроцедуры //ПриЗаписи

//*****************************************************************************
Процедура ПриЗакрытии() //предопределенная
	
	Если ОбъектФормаДокумента.ПриЗакрытии() = 0 Тогда //здесь анализируем изменения и записываем в базу
		Возврат;
	КонецЕсли;
	
КонецПроцедуры //ПриЗакрытии

////////////////////////////////////////////////////////////////////////////////
// ОПЕРАТОРЫ ОСНОВНОЙ ПРОГРАММЫ

ОбъектФормаДокумента = СоздатьОбъект("Форма.Документ");
ОбъектФормаДокумента.Инит(Контекст, 1);
//ОбъектФормаДокумента.ДобавитьПечФорму("Печатная форма", "Печать");