Как известно, на вкладке "История" записываются действия, выполненные пользователями (в том числе и системными) при работе с сущностью, однако, конкретика изменения тех или иных реквизитов остается "за кадром". Чтобы конкретизировать, какой реквизит был изменен, и записать в историю значения до и после изменения - нужно немного дописать событие "До сохранения истории".
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);
}
}
}
Таким образом в карточке сущности появится подробная детализация изменения данных сущности, что позволит отслеживать изменения более тщательно.
Добрый день. Есть 2 вопроса по представленному решению:
Александр, добрый день
1. В данном примере никак. Заказчику предложен вариант с информацией, что свойство-коллекция просто изменилось, без новых и прежних значений. И к каждому такому свойству приходится обращаться персонально
2. Спасибо за вопрос. В данном примере значение самого свойства. Не отображаемое имя, а само имя значения. Например для InternalApprovalState будет указано OnApproval, а не On approval или На согласовании.
Может кто подскажет как обратиться к типу свойства и в случае с перечислением к методу GetLocalizedValue. Или к свойоствам коллекции.
Александр, Денис.
Если автор не против, то я могу накидать статью с ответами на вопросы про Enumeration типы и коллекции, со ссылкой на Вашу статью.
Сергей, автор не будет против)
Подскажите, где конкретно и что надо создать чтобы вместо пустоты действия появился текст?
по комментарию так и не понял где искать это перечисление действий истории.
Станислав, Для операции SDChange необходимо создать ресурс в вашей карточке с префиксом Enum_Operation_
Авторизуйтесь, чтобы написать комментарий