Как передать переменную из формы в модуль объекта при пометке на удаление в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Рассмотрим частую задачу, с которой сталкиваются разработчики в 1С: необходимость запретить или разрешить пометку на удаление объекта (например, документа или справочника) в зависимости от значения определенного реквизита, который заполняется или вычисляется непосредственно на управляемой форме. Проанализируем ситуацию по шагам и выясним причину, почему стандартные подходы не всегда работают.

Почему не отрабатывают события формы при пометке на удаление?

Разберем механику работы платформы. В 1С стандартная команда «Пометить на удаление» (которая вызывается из меню «Еще») обращается напрямую к объекту базы данных. Если пользователь открыл форму, но ничего в ней не менял, системный флаг Модифицированность имеет значение Ложь. Платформа анализирует это состояние и «понимает», что сохранять данные с формы не требуется.

Именно поэтому платформа пропускает события ПередЗаписьюНаСервере и ПриЗаписи в модуле формы, вызывая напрямую события в модуле объекта. Из-за этого мы не можем просто так перехватить действие и передать наши переменные с формы в модуль. Посмотрим на доступные варианты решения этой проблемы.

Решение 1: Замена стандартной кнопки на пользовательскую

Один из самых надежных способов перехватить логику — это забрать у пользователя права на интерактивную пометку удаления и добавить свою собственную кнопку. Разберем по шагам:

  1. В ролях убираем право на интерактивную пометку на удаление для нужных пользователей.
  2. Добавляем на форму собственную команду и кнопку «Пометить на удаление».
  3. В обработчике команды реализуем нужную бизнес-логику проверок.

В современных конфигурациях на платформе 8.3 правильнее использовать механизм расширений. Вы можете программно скрыть стандартную кнопку пометки в расширении формы и добавить свою. В коде вашей команды можно сразу выполнить проверку и вызвать метод платформы:


&НаКлиенте
Процедура Расш1_ПометитьНаУдаление(Команда)
    Если Объект.ЗапретитьУдаление Тогда
        Сообщить("Удаление запрещено согласно настройкам формы!");
        Возврат;
    КонецЕсли;
    
    УстановитьПометкуУдаленияНаСервере();
КонецПроцедуры

&НаСервере
Процедура УстановитьПометкуУдаленияНаСервере()
    ОбъектДок = РеквизитФормыВЗначение("Объект");
    ОбъектДок.УстановитьПометкуУдаления(Истина);
КонецПроцедуры

Решение 2: Использование Дополнительных свойств и принудительная модификация

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

Рассмотрим подробнее, как это обойти. В момент, когда пользователь на форме выбирает или меняет значение реквизита (от которого зависит разрешение на удаление), программно установим флаг модифицированности:


&НаКлиенте
Процедура МойРеквизитПриИзменении(Элемент)
    Модифицированность = Истина;
КонецПроцедуры

Теперь при нажатии на стандартную пометку удаления платформа будет вынуждена сначала выполнить полную запись формы. События формы отработают штатно, и мы сможем передать переменную в модуль объекта в событии ПередЗаписьюНаСервере:


&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    // Передаем значение нашего реквизита
    ТекущийОбъект.ДополнительныеСвойства.Вставить("МожноУдалять", Объект.МойРеквизитДляУдаления);
КонецПроцедуры

Правильное определение момента пометки в модуле объекта

Важный нюанс заключается в обработке переданных данных в самом модуле объекта. В событии ПередЗаписью недостаточно просто проверить флаг ПометкаУдаления. Объект может просто перезаписываться (например, пользователь нажал «Записать»), будучи уже помеченным на удаление ранее. Чтобы перехватить именно момент изменения статуса пометки, нужно сравнивать новое состояние объекта с тем, которое сохранено в базе.

Посмотрим на пример правильной проверки:


Процедура ПередЗаписью(Отказ)
    
    // Проверяем, что происходит ИМЕННО установка пометки на удаление
    Если ПометкаУдаления И НЕ Ссылка.ПометкаУдаления Тогда
        
        // Проверяем наличие нашего свойства, переданного с формы
        Если ДополнительныеСвойства.Свойство("МожноУдалять") Тогда
            
            Если НЕ ДополнительныеСвойства.МожноУдалять Тогда
                Отказ = Истина;
                Сообщить("Удаление данного объекта запрещено настройками формы!");
            КонецЕсли;
            
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Если вам нужно отследить снятие пометки на удаление, условие будет обратным: Если НЕ ПометкаУдаления И Ссылка.ПометкаУдаления Тогда.

Решение 3: Использование параметров сеанса

Проанализируем еще один альтернативный подход. Если передача через коллекцию свойств не подходит, значение с формы можно записать в специально созданный параметр сеанса. При любом интерактивном действии на форме (изменении реквизита) значение пишется в объект ПараметрыСеанса. Модуль объекта в событии ПередЗаписью или специальная подписка на событие просто считывают его глобально и принимают решение об отказе в записи.

Какой метод выбрать — зависит от архитектуры вашей конфигурации. Метод с расширением и собственной кнопкой является наиболее предсказуемым с точки зрения пользовательского интерфейса. Метод с принудительной модификацией и использованием ДополнительныеСвойства позволяет оставить типовой интерфейс нетронутым, решая задачу на уровне событий формы и объекта.

← На главную