В практике разработки на платформе 1С:Предприятие 8.3 часто возникает задача: необходимо предотвратить случайную отмену проведения документа, если на его основании созданы другие документы. Сложность заключается в том, что сама проверка (поиск связей) должна выполняться на сервере, а интерактивный вопрос пользователю («У данного документа есть связанные записи. Вы уверены, что хотите отменить проведение?») можно задать только на клиенте. Рассмотрим подробнее, как реализовать этот механизм в формах документов и списках.
Для начала разберем ситуацию, когда пользователь открыл форму документа и нажал кнопку «Отмена проведения». Основным местом перехвата этого действия является клиентское событие ПередЗаписью. Проанализируем стандартный алгоритм работы:
В обработчике ПередЗаписью на клиенте нам доступен параметр ПараметрыЗаписи. Именно в нем платформа передает информацию о том, какое именно действие инициировал пользователь. Если ПараметрыЗаписи.РежимЗаписи равен РежимЗаписиДокумента.ОтменаПроведения, значит, пора запускать нашу проверку.
Рассмотрим пример кода для формы документа, который можно быстро подготовить, используя консоль кода с ИИ-помощником:
&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
// Проверяем, что это именно отмена проведения
Если ПараметрыЗаписи.РежимЗаписи = РежимЗаписиДокумента.ОтменаПроведения Тогда
// Если мы уже задавали вопрос и пользователь согласился, в параметрах будет наш флаг
Если ПараметрыЗаписи.Свойство("ПодтвержденнаяОтмена") И ПараметрыЗаписи.ПодтвержденнаяОтмена Тогда
Возврат;
КонецЕсли;
// Останавливаем стандартную запись, чтобы выполнить асинхронную проверку
Отказ = Истина;
// Переходим на сервер для поиска связанных документов
Если ИмеютсяСвязанныеДокументыНаСервере(Объект.Ссылка) Тогда
// Задаем вопрос пользователю (асинхронно для управляемых форм)
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВопросаОбОтмене", ЭтотОбъект, ПараметрыЗаписи);
ТекстВопроса = "У документа есть связанные цепочки. При отмене проведения они также могут стать неактуальными. Продолжить?";
ПоказатьВопрос(ОписаниеОповещения, ТекстВопроса, РежимДиалогаВопрос.ДаНет);
Иначе
// Связей нет, можем спокойно отменять проведение
ПараметрыЗаписи.Вставить("ПодтвержденнаяОтмена", Истина);
ЭтотОбъект.Записать(ПараметрыЗаписи);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Проанализируем процедуру обратного вызова. После того как пользователь нажмет «Да», нам нужно снова вызвать метод Записать(), но уже передав признак того, что проверка пройдена.
&НаКлиенте
Процедура ПослеВопросаОбОтмене(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
// Добавляем флаг подтверждения в структуру параметров записи
ДополнительныеПараметры.Вставить("ПодтвержденнаяОтмена", Истина);
ЭтотОбъект.Записать(ДополнительныеПараметры);
КонецЕсли;
КонецПроцедуры
Ситуация усложняется, когда пользователь пытается отменить проведение или пометить документ на удаление прямо из списка документов (например, нажав клавишу Del). В этом случае событие формы документа не срабатывает. Выясним, как бороться с этой проблемой, применяя различные методы доработки динамических списков.
У элемента формы Таблица, отображающей динамический список, есть специфические события. Рассмотрим два эффективных пути:
Del или команда меню). Здесь также можно вызвать серверную проверку, установить Отказ = Истина и вывести ПоказатьВопрос.УстановитьПометкуУдаления() или Записать() для объекта.Для реализации серверной части проверки (функция ИмеютсяСвязанныеДокументыНаСервере) не стоит писать тяжелые запросы ко всем таблицам базы данных. Проанализируем использование метаданных. В 1С существует объект КритерииОтбора. Обычно в типовых и многих самописных конфигурациях уже есть критерий СвязанныеДокументы.
Посмотрим на пример эффективного поиска:
&НаСервереБезКонтекста
Функция ИмеютсяСвязанныеДокументыНаСервере(ДокументСсылка)
// Используем критерий отбора для быстрого получения списка ссылок
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| СвязанныеДокументы.Ссылка КАК Ссылка
|ИЗ
| КритерийОтбора.СвязанныеДокументы(&ДокументСсылка) КАК СвязанныеДокументы";
Запрос.УстановитьПараметр("ДокументСсылка", ДокументСсылка);
Результат = Запрос.Выполнить();
Возврат НЕ Результат.Пустой();
КонецФункции
Разберем ситуацию, упомянутую опытными разработчиками: если менеджер отменяет «Заказ клиента», за которым тянется цепочка из «Перемещения», «Ордеров» и «Реализаций», простая отмена проведения одного документа может привести к нарушению логики учета.
Рекомендации по реализации:
Таким образом, комбинируя перехват событий в форме (ПередЗаписью) и в списке (ПередУстановкойПометкиУдаления), а также используя асинхронные вызовы и критерии отбора, мы создаем надежный механизм защиты целостности данных, который предупреждает пользователя о последствиях его действий.