В процессе разработки учетных систем нередко возникает задача контроля действий пользователей. Типичный сценарий: оператор открыл новый документ, заполнил реквизиты или табличную часть, но в момент закрытия окна на штатный вопрос программы «Сохранить изменения?» ответил «Нет». Руководству или службе безопасности часто требуется фиксировать подобные факты — например, для предотвращения злоупотреблений или анализа причин незавершенных операций.
Разберем, с какими системными ограничениями платформы 1С мы сталкиваемся при решении этой задачи и как корректно реализовать перехват отказа от записи в обычном приложении.
Когда пользователь закрывает форму документа с признаком модифицированности, платформа 1С автоматически отображает модальный диалог с вопросом о сохранении данных. Проанализируем, почему нельзя использовать этот штатный механизм для фиксации события:
Следовательно, единственный способ зарегистрировать отказ — полностью отключить штатный диалог и подставить вместо него собственный обработчик.
Для реализации задуманного обратимся к событию формы документа ПередЗакрытием. Разберем логику по шагам:
ЭтоНовый() и были ли в него внесены изменения через свойство Модифицированность.СтандартнаяОбработка = Ложь.Вопрос() с кнопками «Да», «Нет» и «Отмена».ЗаписатьВФорме(). Если запись не удалась, прерываем закрытие установкой Отказ = Истина.Отказ = Истина), позволяя пользователю продолжить работу.Модифицированность = Ложь, чтобы форма закрылась без повторных запросов.Посмотрим на пример кода процедуры, размещаемой в модуле обычной формы документа:
Процедура ПередЗакрытием(Отказ, СтандартнаяОбработка)
// Проверяем, что документ еще ни разу не сохранялся в базе и данные были изменены
Если ЭтоНовый() И Модифицированность Тогда
// Отключаем типовой вопрос платформы "Сохранить изменения?"
СтандартнаяОбработка = Ложь;
ТекстВопроса = "Данные документа не сохранены. Сохранить изменения?";
Ответ = Вопрос(ТекстВопроса, РежимДиалогаВопрос.ДаНетОтмена);
Если Ответ = КодВозвратаДиалога.Да Тогда
// Пытаемся записать документ стандартным методом формы
Если Не ЗаписатьВФорме() Тогда
Отказ = Истина;
КонецЕсли;
ИначеЕсли Ответ = КодВозвратаДиалога.Нет Тогда
// Фиксируем факт отказа от сохранения документа
ЗарегистрироватьОтказОтСохранения();
// Сбрасываем модифицированность, чтобы платформа не задала вопрос повторно
Модифицированность = Ложь;
ИначеЕсли Ответ = КодВозвратаДиалога.Отмена Тогда
// Пользователь передумал закрывать форму
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Вспомогательная процедура ЗарегистрироватьОтказОтСохранения() может выполнять запись события в журнал регистрации через метод ЗаписьЖурналаРегистрации() либо производить запись реквизитов несохраненного документа в специально созданный независимый регистр сведений.
Рассмотрим ситуации, при которых описанный выше программный перехват может не сработать или повести себя некорректно:
ПередЗавершениемРаботыСистемы.1cv8.exe через системный диспетчер задач Windows или происходит сбой питания, код в обработчиках форм вообще не вызывается. Соответственно, факт набора и отмены документа зафиксирован не будет.Если задача аудита критически важна для бизнес-процесса предприятия, полагаться исключительно на событие закрытия формы рискованно. Разберем более надежные архитектурные подходы:
ПриОкончанииРедактированияСтроки) данные сбрасываются в независимый непериодический регистр сведений. Это позволяет сохранять историю ввода даже в том случае, если пользователь намеренно завершит сеанс через диспетчер задач.