IEE BPM | Расширение базовой платформы

Модуль расширяет базовый функционал платформы ELMA, включающее дополнительные библиотеки, функции и методы: • Режим тестирования/обучения (вход под любым пользователем при наличии соответствующих прав) • Собственный логотип и название системы на странице авторизации • Баннер работы в тестовом режиме • Оповещение пользователей об профилактических работах • Автосохранение проектных задач • Перезапуск сервера по расписанию (устранение утечек памяти) • Много разных хелперов • Счетчики для объектов системы • Входящая почта для пользователей • Кворум сервисы

Настройки

Администрирование компонента и тонкие настройки системы

Настройки

Автоматическое удаление логов системы

Для автоматического удаления старых логов системы необходимо включить данную опцию в настройках:

1. Выбрать меню Администрирование - Тюнинг системы.

image-1625481256235.png

2. Установить Х дней, старше которых логи системы будут удалены, либо 0 для отключения автоматической очистки.

image-1625481374337.png

Если было установлено количество дней больше 0, то в планировщике появится задание Удаление старых логов системы, которое ежедневно будет проверять старые логи и при необходимости удалять их:

image-1625481558939.png

В результате успешной очистки будет сформирован лог обработки:

image-1625481641118.png

Хелперы

namespace ITino.ELMA.Common.Helpers

Хелперы

ModelHelper

/// <summary>
/// Прописано ли свойство в конфигурации
/// </summary>
/// <param name="pm">Метаданные свойства</param>
/// <returns></returns>
public static bool IsConfigProperty(PropertyMetadata pm)
/// <summary>
/// Получить Uid значения перечисления
/// </summary>
/// <param name="value">Значение перечисления</param>
/// <returns></returns>
public static Guid GetEnumUid(object value)
/// <summary>
/// Получить отображаемое описание значения перечисления
/// </summary>
/// <param name="value">Значение перечисления</param>
/// <returns></returns>
public static string GetEnumDescription(object value)
/// <summary>
/// Название типа сущности
/// </summary>
/// <param name="entity">Сущность</param>
/// <returns></returns>
public static string GetEntityDisplayName(IEntity entity)
/// <summary>
/// Описание типа сущности
/// </summary>
/// <param name="entity">Сущность</param>
/// <returns></returns>
public static string GetEntityDescription(IEntity entity)
/// <summary>
/// Проверить наличие элемента справочника и создать при необходимости
/// </summary>
/// <param name="uid">Uid элемента справочника</param>
/// <param name="values">Значения свойств</param>
/// <typeparam name="T">Тип сущности</typeparam>
public static void CheckEntityPresent<T>(Guid uid, object values) where T : IEntity
Хелперы

ListenerHelper

/// <summary>Получить старое значение</summary>
/// <typeparam name="T">Тип</typeparam>
/// <param name="event">Событие</param>
/// <param name="propertyName">Название свойства</param>
/// <returns>Старое значение</returns>
public static T GetOldValue<T>(PostUpdateEvent @event, string propertyName)
/// <summary>Получить старое значение</summary>
/// <typeparam name="T">Тип</typeparam>
/// <param name="event">Событие</param>
/// <param name="propertyName">Название свойства</param>
/// <returns>Старое значение</returns>
public static T GetOldValue<T>(PreUpdateEvent @event, string propertyName)
/// <summary>Получить значение свойства</summary>
/// <typeparam name="T">Тип</typeparam>
/// <param name="event">Событие</param>
/// <param name="propertyName">Название свойства</param>
/// <returns>Значение</returns>
public static T GetValue<T>(PostUpdateEvent @event, string propertyName)
/// <summary>Присвоить значение свойству</summary>
/// <param name="event">Событие</param>
/// <param name="propertyName">Название свойства</param>
/// <param name="value">Значение</param>
public static void SetValue(PreUpdateEvent @event, string propertyName, object value)
/// <summary>Получить значение свойства</summary>
/// <typeparam name="T">Тип</typeparam>
/// <param name="event">Событие</param>
/// <param name="propertyName">Название свойства</param>
/// <returns>Значение</returns>
public static T GetValue<T>(PostInsertEvent @event, string propertyName)
/// <summary>Присвоить значение свойству</summary>
/// <param name="event">Событие</param>
/// <param name="propertyName">Название свойства</param>
/// <param name="value">Значение</param>
public static void SetValue(PreInsertEvent @event, string propertyName, object value)
Хелперы

ServerHelper

/// <summary>
/// Получить среднее время запуска сервера
/// </summary>
public static string AverageStartTime
/// <summary>
/// Версия компонентов IEE
/// </summary>
public static string IEEVersion
/// <summary>
/// Возвращает признак что система в режиме тестирования
/// </summary>
public static bool IsTesting
/// <summary>
/// Перезапустить сервер
/// </summary>
public static void RestartServer()
/// <summary>
/// Логгер импорта
/// </summary>
public static ILog ImportLogger
/// <summary>
/// Запись в протокол импорта данных в справочник
/// </summary>
/// <param name="name">Имя справочника</param>
/// <param name="total">Всего записей</param>
/// <param name="new">Новых записей</param>
/// <param name="update">Обновлений</param>
/// <param name="delete">Удалений</param>
public static void ImportLogCatalog(string name, int total, int @new = 0, int update = 0, int delete = 0)
/// <summary>
/// Запись в протокол импорта что данные для справочника отсутствуют
/// </summary>
/// <param name="name">Имя справочника</param>
public static void ImportLogCatalogNone(string name)
/// <summary>
/// Время работы сервера
/// </summary>
/// <returns></returns>
public static TimeSpan UpTime
Хелперы

UserHelper

/// <summary>
/// Системный пользователь
/// </summary>
public static IUser SystemUser
/// <summary>
/// Пользователь подсистемы обмена
/// </summary>
public static IUser ExchangeUser
/// <summary>
/// Получить непосредственного руководителя для пользователя
/// </summary>
/// <param name="user">Пользователь</param>
/// <returns>Руководитель (если есть, иначе null)</returns>
public static IUser GetImmediateChiefByUser(IUser user)
/// <summary>
/// Получить всех активных пользователей группы
/// </summary>
/// <param name="gUidStr">Строковый Uid группы</param>
/// <returns>Список пользователей</returns>
public static IEnumerable<IUser> GetUsersInGroup(string gUidStr)
/// <summary>
/// Получить всех активных пользователей группы
/// </summary>
/// <param name="gUid">Uid группы</param>
/// <returns>Список пользователей</returns>
public static IEnumerable<IUser> GetUsersInGroup(Guid gUid)
/// <summary>
/// Преобразовать полные инициалы в сокращенные
/// </summary>
/// <param name="fullName">Полные инициалы</param>
/// <param name="lastNameOrder">Фамилия в начале</param>
/// <returns>Сокращенные инициалы</returns>
public static string ConvertToShortName(string fullName, bool lastNameOrder = true)
/// <summary>
/// Входит ли пользователь в группу Администраторы
/// </summary>
/// <returns></returns>
public static bool IsAdmin
Хелперы

WorkflowHelper

/// <summary>
/// Получить запускаемые процессы по входному типу сущности
/// </summary>
/// <param name="typeUid">UID типа сущности</param>
/// <returns>Список процессов Workflow</returns>
public static IEnumerable<IWorkflowProcess> GetStartableProcessesByInputEntity(Guid typeUid)
/// <summary>
/// Комментарий для процессной задачи
/// </summary>
/// <param name="element">Uid элемента задачи на схеме</param>
/// <param name="task">Задача</param>
/// <param name="author">Автор комментария</param>
/// <param name="date">Дата комментария</param>
/// <param name="comment">Комментарий</param>
/// <param name="type">Тип комментария</param>
public static void CommentForTask(Guid element, ITaskBase task, IUser author, DateTime date, string comment, EOWorkflowTaskCommentType type = EOWorkflowTaskCommentType.Info)
/// <summary>
/// Сохранить уведомление для последующего показа
/// </summary>
/// <param name="message">Текст сообщения</param>
/// <param name="type">Тип сообщения</param>
public static void Notify(string message, NotifyType type = NotifyType.Info)
/// <summary>
/// Убрать замещение у задачи процесса
/// </summary>
/// <param name="task">Задача процесса</param>
/// <param name="uid">Uid задачи на схеме</param>
/// <param name="ignoreUsers">Список игнорируемых пользователей</param>
public static void RemoveReplacement([NotNull] this ITaskBase task, Guid uid, IEnumerable<IUser> ignoreUsers = null)
/// <summary>
/// Завершить процесс с выводом ошибки пользователю
/// </summary>
/// <param name="context"></param>
/// <param name="error"></param>
public static void CompleteWithError(object context, string error)
/// <summary>
/// Выполнить длительное действие в отдельном потоке при создании задачи
/// </summary>
/// <param name="element">Id задачи на диаграмме</param>
/// <param name="task">Созданная задача в OnTaskCreate</param>
/// <param name="action">Действие</param>
public static void ProcessLongAction(Guid element, ITaskBase task, Action<LongActionModel, ISession> action)

Модели

Модели

LongActionModel

public class LongActionModel
{
	/// <summary>
  	/// Логгер
  	/// </summary>
  	public ILog Logger { get; }

  	/// <summary>
  	/// Контекст процесса
  	/// </summary>
  	public WorkflowInstanceContext Context { get; }

  	/// <summary>
  	/// Начало обработки
  	/// </summary>
  	public DateTime StartDate { get; }

  	/// <summary>
  	/// Окончание обработки
  	/// </summary>
  	public DateTime? EndDate { get; set; }

  	/// <summary>
  	/// Название действия
  	/// </summary>
  	public string Name { get; set; }

  	/// <summary>
  	/// Задача бизнес процесса
  	/// </summary>
	public IWorkflowTaskBase Task { get; set; }

  	/// <summary>
  	/// Кнопки переходов
  	/// </summary>
  	public IEnumerable<string> Buttons { get; set; }

  	/// <summary>
  	/// Ошибка выполнения
  	/// </summary>
  	public string Error { get; set; }

  	/// <summary>
  	/// Обновить задачу в браузере после завершения длительной операции
  	/// </summary>
  	public bool RefreshOnCompleted { get; set; }
}

Пример HTML брэнд шаблона

<div style="font-family: Arial, Helvetica, sans-serif; font-weight: 100;">
	<table style="border-spacing: 0px; border: 0; width: 100%; border-collapse: collapse;">
		<tr style="background: #ffdddd; text-align: right;">
			<td style="width: 1%; padding: 10px;">
				<img src="https://www.elmastore.ru/img/emaillogo.png" width="128"/>
			</td>
			<td style="width: 99%; padding: 15px;  vertical-align: top;">
				<span style="font-size: 2.0em;">Название Вашей системы</span>
			</td>
		</tr>
		<tr>
			<td colspan="2" style="background: #6495ed; font-size: 1.2em; padding: 10px;">
				{$Body}
			</td>
		</tr>
		<tr>
			<td colspan="2" style="color: gray; font-size: 0.7em; padding-top: 10px;">
				УВЕДОМЛЕНИЕ О КОНФИДЕНЦИАЛЬНОСТИ: Это электронное сообщение и любые документы, приложенные к нему, содержат конфиденциальную информацию. Настоящим уведомляем Вас о том, что если это сообщение не предназначено Вам, использование, копирование, распространение информации, содержащейся в настоящем сообщении, а также осуществление любых действий на основе этой информации, строго запрещено. Если Вы получили это сообщение по ошибке, пожалуйста, сообщите об этом отправителю по электронной почте и удалите это сообщение.
			</td>
		</tr>
	</table>
</div>

Результатом будет:

image-1627196011610.png

Примеры

Полезные примеры использования элементов компонента

Примеры

Реализация обработки длительной операции в задаче

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

Внутри обработчика нельзя использовать context. Вместо этого использовать model.Context.

public override void OnTaskCreate(ITaskBase task, P_IA_AandP context)
{
	// 4f55dd98-5242-4633-88e8-4c745551b52c - Id задачи на диаграмме 
	WorkflowHelper.ProcessLongAction(new Guid("4f55dd98-5242-4633-88e8-4c745551b52c"), task, (model, session) =>
	{
		model.Name = "Сбор данных по активным задачам"; // Название операции, отображаемое в задаче
      
		// Здесь любой код для длительных операций
      	var instanceContext = model.Context as P_IA_AandP;
    });
}

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

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

image-1630422165056.png

После завершения длительно операции кнопки переходов вновь появятся и будет выдано сообщение со временем завершения выполнения указанной операции:

image-1630423575147.png

Если в исполняемом коде будет вызвано исключение, то появится соответствующее сообщение, кнопки переходов так же появятся:

image-1630427822285.png

Кворум сервисы

Распределенные отказоустойчивые сервисы в кластере Корпоративной редакции системы

Кворум сервисы

Мониторинг

Доступно только в Корпоративной редакции

Статус установленных кворум сервисов кластера отображается по ссылке Администрирование - Система - Кворум сервисы:

image-1635059448252.png

Информация о текущих пакетах на обработку кворум сервисами находиться по ссылке Справочники - Элемент очереди кворумного сервиса.