Как изменить статус связанного объекта при принятии, отмене или выполнении задачи в бизнес-процессе 1С

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

При проектировании бизнес-процессов в среде 1С:Предприятие 8 начинающие разработчики часто сталкиваются с фундаментальным ограничением платформы при работе с задачами. Типичный сценарий: в рамках бизнес-процесса создается задача (например, проверка контрагента юристом). Требуется динамически менять статус этого контрагента в информационной базе в зависимости от действий пользователя: когда задача просто "висит" в списке, когда ее приняли к исполнению, когда отменили принятие и когда, наконец, выполнили.

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

Почему не работает "Точка выбора вариантов" при принятии задачи?

Для начала проанализируем поведение платформы 1С. Бизнес-процесс — это жестко регламентированная цепочка взаимосвязанных шагов. Продвижение по карте маршрута бизнес-процесса происходит строго в момент выполнения задачи. Технически это означает, что реквизит объекта Задача под названием Выполнена принимает значение Истина (обычно это происходит при вызове метода ВыполнитьЗадачу()).

Когда пользователь выполняет действия "Принять к исполнению" или "Отменить принятие к исполнению", карта маршрута бизнес-процесса "молчит". С точки зрения платформы, бизнес-процесс все еще находится в той же самой точке действия. Изменяются лишь реквизиты самой задачи (заполняется или очищается реквизит Исполнитель, меняются параметры адресации). Никакого перехода к следующему блоку маршрута (включая "Точку выбора вариантов" или "Условие") не происходит и происходить не должно. Пытаться выстроить маршрут БП из точек, реагирующих на принятие задачи — это грубая архитектурная ошибка, которая перегружает схему и делает систему неработоспособной.

Правильная архитектура: использование событий объекта задачи

Чтобы корректно решить задачу и своевременно менять статусы связанных объектов (в нашем примере — контрагентов), мы должны перенести логику отслеживания состояний непосредственно в модуль самой задачи. Нам не нужно менять карту маршрута бизнес-процесса. Она должна оставаться максимально простой: одна точка действия "Проверить контрагента". Все промежуточные статусы мы будем перехватывать программно.

Рассмотрим подробнее, как это сделать. Мы будем использовать предопределенный обработчик события ПередЗаписью в модуле объекта нашей задачи. Этот обработчик идеален, так как он срабатывает при любом интерактивном или программном изменении задачи.

Шаг 1. Анализ изменений реквизитов задачи

Принятие задачи к исполнению конкретным пользователем технически выражается в том, что реквизит Исполнитель заполняется ссылкой на пользователя (ранее задача могла быть адресована роли, например "Юристы", и персональный исполнитель был пуст). Отмена принятия к исполнению — это очистка реквизита Исполнитель. Выполнение задачи — это изменение флага Выполнена с Ложь на Истина.

Разберем программный код, который необходимо разместить в модуле объекта задачи (например, Задача.ЗадачаИсполнителя):


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

КонецПроцедуры

Обратите внимание на использование функции ОбщегоНазначения.ЗначенияРеквизитовОбъекта. Это стандартная функция из Библиотеки Стандартных Подсистем (БСП), которая позволяет быстро получить значения реквизитов из базы данных без явного обращения к транзакционному объекту, что существенно повышает производительность системы.

Шаг 2. Реализация процедуры изменения статуса

Для непосредственного изменения статуса контрагента напишем вспомогательную процедуру. Ее можно разместить в этом же модуле или вынести в общий серверный модуль:


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

Альтернативный вариант: Использование событий форм (Менее рекомендуемый)

Некоторые разработчики предпочитают решать подобные задачи через изменение кода форм. Например, прописывать вызов обработки изменения статусов при нажатии кнопок в форме задачи или в форме списка задач. Рассмотрим, почему этот подход имеет существенные недостатки:

Именно поэтому перехват событий на уровне модуля объекта (подписка на событие или предопределенные процедуры модуля) является единственным надежным промышленным стандартом разработки в среде 1С.

Использование механизмов БСП (Библиотеки Стандартных Подсистем)

Если ваша конфигурация разработана на основе БСП (что является стандартом для большинства современных конфигураций 1С, таких как ERP, КА, УТ, ЗУП), то в ней уже развернута подсистема "Бизнес-процессы и задачи".

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

Резюме и рекомендации по проектированию БП

Подведем итог нашему разбору. При проектировании систем с использованием бизнес-процессов придерживайтесь следующих правил:

  1. Карта маршрута БП должна отражать только крупную бизнес-логику (шаги согласования, ветвления по бизнес-условиям, циклы доработки). Не пытайтесь отобразить на карте маршрута мелкие интерактивные действия пользователей, такие как "взятие задачи в работу".
  2. Продвижение вперед происходит только при завершении задач. Все промежуточные статусы объектов фиксируйте программно в транзакции записи самой задачи.
  3. Используйте безопасное чтение старых данных. Всегда сравнивайте старое значение реквизита из базы данных с новым значением в оперативной памяти объекта, чтобы точно идентифицировать момент перехода задачи из одного состояния в другое (например, переход от пустого исполнителя к конкретному лицу).

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

← На главную