Как создать задачу пользователю в 1С при отмене проведения документа?

Программист Торговля и дистрибуция
← На главную

В процессе разработки часто возникает необходимость программно создавать задачи для пользователей. Обычно это простая операция, но иногда разработчики сталкиваются с ситуацией, когда код создания задачи выполняется без ошибок, но сама задача в базе данных не появляется. Особенно часто это происходит при попытке создать задачу в обработчиках проведения или отмены проведения документов.

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

Выясняем причину: магия транзакций в 1С

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

Что это значит на практике? Платформа 1С "запоминает" все изменения, которые вы делаете в базе данных в рамках этой операции. Если в конце процедуры проведения выставляется флаг Отказ = Истина или происходит какая-либо ошибка, платформа отменяет абсолютно все изменения, сделанные с момента начала транзакции. Она как бы "откатывает" базу данных к состоянию, в котором та была до начала операции.

Именно в эту ловушку и попадает создание нашей задачи. Посмотрим на типичный код:


// Этот код находится, например, в модуле документа
// в процедуре ОбработкаОтменыПроведения(Отказ)

// ... какая-то логика ...
Отказ = Истина; // Симулируем отмену операции

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

// После выхода из процедуры, из-за "Отказ = Истина",
// вся транзакция будет отменена, включая запись новой задачи.

В результате код отрабатывает, но так как вся транзакция отменяется, запись о новой задаче тоже стирается из базы данных. Вы не видите ни ошибок, ни результата.

Решение: как создать задачу вне основной транзакции

Чтобы задача гарантированно сохранилась, ее создание и запись нужно вынести за пределы "проблемной" транзакции. Самый надежный и правильный способ сделать это — использовать фоновые задания.

Фоновое задание запускается в отдельном сеансе и, соответственно, в своей собственной, независимой транзакции. Если основная транзакция документа откатится, это никак не повлияет на выполнение фонового задания.

Разберем по шагам, как это реализовать:

  1. Создаем процедуру для фонового задания.
    В общем серверном модуле (убедитесь, что у него стоят флаги "Сервер", "Вызов сервера" и "Внешнее соединение") создайте экспортную процедуру, которая будет непосредственно создавать задачу.
    
    // Общий модуль, например, "РаботаСЗадачамиСервер"
    
    Процедура СоздатьЗадачуНапоминаниеВФоне(Знач ПараметрыЗадачи) Экспорт
    
        НоваяЗадача = Задачи.ЗадачиПользователя.СоздатьЗадачу();
        НоваяЗадача.Наименование = ПараметрыЗадачи.Наименование;
        НоваяЗадача.Исполнитель = ПараметрыЗадачи.Исполнитель;
        НоваяЗадача.Объект = ПараметрыЗадачи.Объект;
        НоваяЗадача.Описание = ПараметрыЗадачи.Описание;
        НоваяЗадача.Дата = ТекущаяДата();
        НоваяЗадача.СрокИсполнения = КонецДня(ТекущаяДата());
        
        НоваяЗадача.Записать();
    
    КонецПроцедуры
    
  2. Вызываем фоновое задание из модуля документа.
    Теперь в месте, где нужно создать задачу (например, в ОбработкаОтменыПроведения), мы не создаем ее напрямую, а инициируем запуск нашей процедуры в фоновом режиме.
    
    // Модуль объекта документа, процедура ОбработкаОтменыПроведения(Отказ)
    
    // ... какая-то логика ...
    Если НужноСоздатьЗадачу Тогда
    
        // 1. Готовим параметры для передачи в фоновое задание
        ПараметрыЗадачи = Новый Структура;
        ПараметрыЗадачи.Вставить("Наименование", "Документ " + ЭтотОбъект.Ссылка + " не проведен");
        ПараметрыЗадачи.Вставить("Исполнитель", ЭтотОбъект.Ответственный);
        ПараметрыЗадачи.Вставить("Объект", ЭтотОбъект.Ссылка);
        ПараметрыЗадачи.Вставить("Описание", "Необходимо проверить причину отмены проведения документа.");
    
        // 2. Формируем массив параметров для метода Выполнить()
        ПараметрыВыполнения = Новый Массив;
        ПараметрыВыполнения.Добавить(ПараметрыЗадачи);
    
        // 3. Запускаем фоновое задание
        ФоновыеЗадания.Выполнить("РаботаСЗадачамиСервер.СоздатьЗадачуНапоминаниеВФоне", ПараметрыВыполнения);
    
    КонецЕсли;
    
    Отказ = Истина;
    // Теперь откат транзакции не повлияет на создание задачи,
    // так как она будет создана в другом сеансе.
    

Этот подход является наиболее универсальным и надежным для выполнения любых действий, которые должны произойти независимо от исхода основной транзакции.

Задачи и Бизнес-процессы: разбираемся в терминах

В ходе обсуждения подобных проблем часто возникает путаница между объектами конфигурации Задача и Бизнес-процесс. Давайте проясним этот момент.

Вариант 1: Простая задача-напоминание (без бизнес-процесса)

В 1С можно создать объект метаданных Задача, который не будет привязан ни к одному бизнес-процессу. Это идеальный вариант для создания простых напоминаний или поручений. Именно такой подход мы и использовали в примерах выше.

Важный момент: если вы создали задачу, а она не видна пользователю, проверьте, куда он смотрит. Возможно, он использует какой-то специфический отчет или форму списка, настроенную на отображение задач только из конкретного бизнес-процесса. Прежде чем утверждать, что задача не создалась, проверьте ее наличие через консоль запросов.

Вариант 2: Задача как часть бизнес-процесса

Если задача является шагом в какой-то сложной логике (согласование, обработка заказа и т.д.), то она, скорее всего, привязана к бизнес-процессу. В этом случае создавать объект задачи вручную — неправильно.

Вместо этого нужно создавать и запускать сам бизнес-процесс. Платформа 1С, двигаясь по карте маршрута, сама создаст все необходимые задачи в нужные моменты времени.

Посмотрим на пример создания задачи через запуск бизнес-процесса "Задание":


// Создаем не задачу, а сам бизнес-процесс
НовыйБП = БизнесПроцессы.Задание.СоздатьБизнесПроцесс();

// Заполняем реквизиты бизнес-процесса
НовыйБП.Автор = ТекущийПользователь;
НовыйБП.Важность = Перечисления.ВариантыВажностиЗадачи.Высокая;
НовыйБП.Дата = ТекущаяДата();
НовыйБП.СрокИсполнения = КонецДня(ТекущаяДата());
НовыйБП.Исполнитель = НужныйПользователь;
НовыйБП.Наименование = "Обработать запрос клиента";
НовыйБП.Предмет = СсылкаНаДокумент;

// Записываем бизнес-процесс
НовыйБП.Записать();

// Стартуем его! Именно в этот момент создастся первая задача по маршруту
НовыйБП.Старт();

// После этого пользователю "НужныйПользователь" будет назначена новая задача

Главное правило: если вам нужно простое напоминание — создавайте независимую задачу. Если нужна часть сложного процесса — создавайте и запускайте бизнес-процесс.

← На главную