DirectumRX. Подробная история в карточке сущности

46 6

Как известно, на вкладке "История" записываются действия, выполненные пользователями (в том числе и системными) при работе с сущностью, однако, конкретика изменения тех или иных реквизитов остается "за кадром". Чтобы конкретизировать, какой реквизит был изменен, и записать в историю значения до и после изменения - нужно немного дописать событие "До сохранения истории".

public override void BeforeSaveHistory(Sungero.Content.DocumentHistoryEventArgs e)
{
  // Вызываем базовый обработчик
  base.BeforeSaveHistory(e);

  // Нам нужно записывать историю, только если произошло обновление
  var isUpdateAction = e.Action == Sungero.CoreEntities.History.Action.Update;
  if (!isUpdateAction)
	return;
  
  // Далее мы отбираем те свойства, для которых будем записывать данные в историю, 
  // нас не интересует некоторые системные свойства, и свойства-коллекции
  var properties = _obj.State.Properties.Where(p =>
					p != _obj.State.Properties.Index &&
					p != _obj.State.Properties.Modified &&
					p != _obj.State.Properties.DocumentDate &&
					p != _obj.State.Properties.Versions &&
					p != _obj.State.Properties.Tracking);
  
  var propertiesType = Сontracts.Info.Properties.GetType();
  var objType = _obj.GetType();
  // Чтобы в истории, в колонке "Действие" отобразилось конкретное наименование - нам нужно
  // создать Enumeration этого действия и создать под него строку локализации с префиксом 
  // Enum_Operation_ (для нашего примера - Enum_Operation_SDChange, где будет прописано желаемое 
  // имя действия, например "Изменение реквизита". Если этого не сделать - в колонке "Действие" будет пусто.
  var operation = new Enumeration("SDChange");
  
  // Обходим коллекцию свойств
  foreach (var property in properties)
  {
	// Берем в работу только те свойства, которые были помечены как измененные
	var isChanged = (property as Sungero.Domain.Shared.IPropertyState).IsChanged;        
	if (isChanged)
	{
	  // Извлечение локализованного наименования реквизита.
	  var propertyName = (property as Sungero.Domain.Shared.PropertyStateBase).PropertyName;
	  var propertyInfo = propertiesType.GetProperty(propertyName).GetValue(Сontracts.Info.Properties);
	  var name = propertyInfo.GetType().GetProperty("LocalizedName").GetValue(propertyInfo);
	  
	  // Извлечение нового значения реквизита.
	  var newValue = objType.GetProperty(propertyName).GetValue(_obj);
	  
	  // Извлечение старого значения реквизита.
	  var oldValue = property.GetType().GetProperty("OriginalValue").GetValue(property);
	  
	  // Дополнительно еще раз сверяет что старое и новое значения не равны, также отбрасываем изменения строковых свойств с null на пустую строку
	  if (newValue == oldValue ||
		  newValue != null && oldValue != null && Equals(newValue.ToString(), oldValue.ToString()) ||
		  newValue != null && oldValue == null && string.IsNullOrEmpty(newValue.ToString()) ||
		  oldValue != null && newValue == null && string.IsNullOrEmpty(oldValue.ToString()))
		continue;
	  
	  // Записываем данные в историю
	  var comment = string.Format("{0}. Новое значение: {1}. Прежнее значение: {2}", name, newValue, oldValue);
	  e.Write(operation, null, comment);
	}
  }

}

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

46
Авторизуйтесь, чтобы оценить материал.
6
Александр Волошин

Добрый день. Есть 2 вопроса по представленному решению:

  1. Как Вы отслеживаете изменение в коллекциях?
  2. Что записывается в историю для свойств-перечислений: их английское название или локализованное?
Денис Зайцев

Александр, добрый день

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

2. Спасибо за вопрос. В данном примере значение самого свойства. Не отображаемое имя, а само имя значения. Например для InternalApprovalState будет указано OnApproval, а не On approval или На согласовании.

Может кто подскажет как обратиться к типу свойства и в случае с перечислением к методу GetLocalizedValue. Или к свойоствам коллекции.

Сергей Беляков

АлександрДенис.

Если автор не против, то я могу накидать статью с ответами на вопросы про Enumeration типы и коллекции, со ссылкой на Вашу статью.

Денис Зайцев

Сергей, автор не будет против)

Станислав Егоров

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

Денис Зайцев

Станислав, Для операции SDChange необходимо создать ресурс в вашей карточке с префиксом Enum_Operation_Изображение

Авторизуйтесь, чтобы написать комментарий