В практике разработки на платформе 1С:Предприятие часто возникает потребность внедрить простой механизм выдачи поручений, контроля сроков и перенаправления задач между сотрудниками. Типовые механизмы на базе бизнес-процессов нередко избыточны для линейных сценариев, а интеграция с внешними системами класса 1С:Документооборот требует дополнительных затрат. Рассмотрим подробно, как организовать учет задач в конфигурациях на обычных формах (например, 1С:Управление производственным предприятием 1.3) исключительно с помощью стандартного объекта метаданных Задача.
Платформа 1С позволяет использовать объект Задача автономно. Стандартный реквизит БизнесПроцесс может оставаться незаполненным, при этом сохраняется весь встроенный функционал объекта: состояние выполнения, адресация и события жизненного цикла.
Разберем основные особенности автономной работы с задачами:
Выполнена (тип Булево) управляется платформенным методом ВыполнитьЗадачу(). Вызов этого метода переводит реквизит в значение Истина и автоматически вызывает обработчики событий модуля задачи ПередВыполнением и ПриВыполнении.Задача не поддерживает иерархическую структуру на уровне платформы. Для связывания перенаправленных поручений в единую цепочку необходимо добавить собственный реквизит ЗадачаОснование или РодительскаяЗадача с типом ссылки на текущую задачу.Исполнитель (ссылка на справочник Пользователи). Если требуется распределение по ролям или подразделениям, задействуется механизм адресации через связанный регистр сведений.Проанализируем задачу передачи поручения: когда сотрудник перенаправляет задачу коллеге, она должна оставаться видимой для участников цепочки до момента ее фактического закрытия финальным исполнителем.
Для решения этой задачи рассмотрим два практических варианта реализации:
Задача, в реквизите ЗадачаОснование которого указывается родительская задача. При выполнении подчиненной задачи в событии ПриВыполнении программно и в транзакции вызывается метод ВыполнитьЗадачу() для всей цепочки родителей.Задача добавляется табличная часть Участники (колонки Пользователь, Роль). При перенаправлении текущий исполнитель меняется в шапке, а предыдущий исполнитель записывается в историю. В списке задач отбор настраивается так, чтобы пользователь видел записи, где он указан либо исполнителем, либо участником цепочки, пока задача не выполнена.Посмотрим на пример программного создания подчиненной задачи при перенаправлении:
НоваяЗадача = Задачи.ЗадачиПользователя.СоздатьЗадачу();
НоваяЗадача.Дата = ТекущаяДата();
НоваяЗадача.Наименование = "Перенаправлено: " + ИсходнаяЗадача.Наименование;
НоваяЗадача.Исполнитель = НовыйИсполнитель;
НоваяЗадача.ЗадачаОснование = ИсходнаяЗадача.Ссылка;
НоваяЗадача.СрокИсполнения = ИсходнаяЗадача.СрокИсполнения;
НоваяЗадача.Описание = ИсходнаяЗадача.Описание;
НоваяЗадача.Записать();
Для наглядности работы пользователей просроченные задачи должны выделяться красным цветом, а текущие выполняемые — стандартным черным цветом. В интерфейсе обычного приложения (толстый клиент) отсутствует механизм условного оформления динамического списка, поэтому оформление реализуется программно в свойствах табличного поля формы списка.
Выясним причину возможных проблем с производительностью: использование события ПриВыводСтроки выполняет код для каждой строки по отдельности, что приводит к зависанию интерфейса при скроллинге. Для пакетной обработки строк следует использовать событие ПриПолученииДанных.
Разберем по шагам обработку строк в табличном поле списка:
Процедура СписокЗадачПриПолученииДанных(Элемент, ОформленияСтрок)
ТекущийМомент = ТекущаяДата();
Для Каждого Оформление Из ОформленияСтрок Цикл
СтрокаДанных = Оформление.ДанныеСтроки;
Если СтрокаДанных = Неопределено Тогда
Продолжить;
КонецЕсли;
// Проверяем просрочку выполнения задачи
Если Не СтрокаДанных.Выполнена И СтрокаДанных.СрокИсполнения < ТекущийМомент Тогда
Оформление.ЦветТекста = Новый Цвет(255, 0, 0); // Красный цвет для просроченных
Иначе
Оформление.ЦветТекста = Новый Цвет(0, 0, 0); // Черный цвет для обычных
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Важное правило производительности: внутри обработчика ПриПолученииДанных категорически запрещено выполнять запросы к базе данных или обращаться к свойствам объектов через точку, вызывающим неявные обращения к СУБД. Все необходимые поля (Выполнена, СрокИсполнения) должны присутствовать в колонках табличного поля.
Поскольку в толстом клиенте отсутствуют push-уведомления сервера, появление новых задач в реальном времени требует периодического обновления формы списка.
Для этого в событии формы ПриОткрытии настраивается обработчик ожидания:
Процедура ПриОткрытии()
// Подключаем автоматическое обновление списка каждые 60 секунд
ПодключитьОбработчикОжидания("ОбновитьСписокЗадач", 60);
КонецПроцедуры
Процедура ОбновитьСписокЗадач() Экспорт
ЭлементыФормы.СписокЗадач.Обновить();
КонецПроцедуры
Процедура ПриЗакрытии()
ОтключитьОбработчикОжидания("ОбновитьСписокЗадач");
КонецПроцедуры
Период обновления рекомендуется устанавливать в интервале от 60 до 180 секунд. Слишком частый вызов метода Обновить() создает избыточную нагрузку на сервер баз данных.
Для построения отчета по исполнительской дисциплине используется система компоновки данных (СКД). Источником данных выступает виртуальная таблица или реальная таблица объекта Задача. В схеме компоновки рассчитываются ключевые метрики:
Таким образом, архитектура автономного объекта Задача позволяет быстро развернуть гибкую систему поручений на базе типовой конфигурации УПП 1.3 без утяжеления конфигурации избыточными бизнес-процессами.