Последняя версия DataExpress 3 beta от 9 августа 2020 года.
Изображение Скачать | Изображение Что нового?
См. также: Энциклопедия DX | Форум на develop-soft | Расширения
ИзображениеИзображениеИзображение

Пример: Лог пользователей.

Полезное от пользователей DataExpress
Nikxdrummer
Опытный
Сообщения: 257
Зарегистрирован: 16 фев 2017, 10:56
Откуда: Новосибирск
Благодарил (а): 5 раз

Re: Пример: Лог пользователей.

Сообщение Nikxdrummer » 17 май 2017, 07:45

YurAnt писал(а):Встроенного лога наверное не будет (прямо в мониторе пользователей), но есть идея создать универсальное выражение. Может дойдут руки как-нибудь...


Если есть идея это уже что то, буду ждать)

neitri
Мастер скриптов
Сообщения: 539
Зарегистрирован: 13 фев 2017, 17:42

Re: Пример: Лог пользователей.

Сообщение neitri » 17 май 2017, 08:44

Я писал скриптами.
Для каждой формы прописывал обработчик

Код: Выделить всё

procedure Form_Create;
begin
  Self.OnBeforePost := @LastUserEdit;
end;   

Код обработчика в модуле

Код: Выделить всё

procedure LogMsg(Msg:String; doc:string;id:integer);
var
   Fm: TdxForm;
Begin
//MainWindow.OnCreateForm := @FormCreate;
   Fm := CreateForm('SYSTEMLOG');
   // Если надо добавить новую запись
   Fm.OpenRecord(0);
   Fm.Append;
   // Заполняем при необходимости поля, если это ввода на основании
   Fm['Дата'] := Date;
   Fm['Время'] := Time;
   Fm['Сообщение'] := GetCurrentUser+ ' '+ Msg;
   Fm['ТипДок']:= doc;
   fm['НомерДок']:=id;
   Fm.Post
   DestroyForm(Fm);
end;

procedure ConfirmClose(Sender:TObject; var Ok:Boolean);
Begin
  ok:=true;
  case MessageDlg('Сохранение...','Сохратить изменения?', mtConfirmation, [mbYes, mbNo, mbCancel]) of
    mrYes://Устанавливаем
      Ok:=true;
    mrNo:// закрыть без сохранения
      begin
        TdxForm(sender).Cancel;
        Ok:=true;
      end;
    mrCancel:
      Ok:=false;
  end;
end;


function VarToStrDef(const V: Variant; const ADefault: string): string;
begin
  if not VarIsNull(V) then
    Result := V
  else
    Result := ADefault;
end;
function VarToStr1(const V: Variant): string;
begin
  Result := VarToStrDef(V, '');
end;
function VarToStr(const V: Variant): string;
begin
  case VarType(V) of
    varSmallInt,
    varInteger   : Result := IntToStr(V);
    varSingle,
    varDouble,
    varCurrency  : Result := FloatToStr(V);
    varDate      : Result := FormatDateTime('dd/mm/yyyy', V);
    varBoolean   : if V then Result := 'T' else Result := 'F';
    varString    : Result := V;
    else            Result := VarToStr1(V);
  end;
end;
function VarTypeToStr(const V: Variant):string;
begin
  case VarType(V) of
//    varAny      : Result := 'varAny';
    varArray    : Result := 'varArray';
    varBoolean  : Result := 'varBoolean';
    varByRef    : Result := 'varByRef';
    varByte     : Result := 'varByte';
    varCurrency : Result := 'varCurrency';
    varDate     : Result := 'varDate';
    varDispatch : Result := 'varDispatch';
    varDouble   : Result := 'varDouble';
    varEmpty    : Result := 'varEmpty';
    varError    : Result := 'varError';
    varInt64    : Result := 'varInt64';
    varInteger  : Result := 'varInteger';
    varLongWord : Result := 'varLongWord';
    varNull     : Result := 'varNull';
    varOleStr   : Result := 'varOleStr';
    varShortInt : Result := 'varShortInt';
    varSingle   : Result := 'varSingle';
    varSmallInt : Result := 'varSmallInt';
//    varStrArg   : Result := 'varStrArg';
    varString   : Result := 'varString';
    varTypeMask : Result := 'varTypeMask';
    varUnknown  : Result := 'varUnknown';
    varVariant  : Result := 'varVariant';
    varWord     : Result := 'varWord';
    else Result := VarToStr1(V);
  end;
end;
procedure ChangeLog(Sender:TObject);
var
  i:integer;
  f:Tfield;
  fn,o,v,msg:string;
begin
//debug('ChangeLog');
  msg:='';
  for i:=0 to tdxForm(sender).Grid.Columns.count-1 do
    begin
      f:=tdxForm(sender).Grid.Columns.items[i].field;
      if f.value<>f.OldValue then
        begin
          fn:=tdxForm(sender).Grid.GetFieldName(tdxForm(sender).Grid.Columns.items[i]);
          v:=VarToStr(f.Value);
          o:=VarToStr(f.OldValue);
          msg:=msg + fn+' "'+o+'"=>"'+v+'"; ';
          debug(fn+VarTypeToStr(f.Value));
        end;
    end;
    Logmsg(msg,tdxForm(sender).formcaption,tdxForm(sender).RecId);
end;

Procedure LastUserEdit(Sender: TObject);
Begin
  //Устанавливаем
  debug('LastUserEdit');
  ChangeLog(Sender);
  TdxForm(sender).fields['Сохранил']:=GetCurrentUser;
  TdxForm(sender).fields['ДатаСохранения']:=Now;
  TdxForm(sender).fields['ВремяСохранения']:=Now;
End;         
Помогли Тебе. Помоги проекту.
Реквизиты помощи Вы можете найти в окне "О программе"

Аватара пользователя
YurAnt
Эксперт
Сообщения: 3352
Зарегистрирован: 13 апр 2017, 08:57
Поблагодарили: 6 раз
Контактная информация:

Re: Пример: Лог пользователей.

Сообщение YurAnt » 17 май 2017, 09:04

Я вообще что-то подобное пробовал делать, но хотелось замутить унифицированное быстро-развертываемое решение. И блин, пока не хватает должных знаний. Наброски чистого кода есть, но когда начинаю перетаскивать их в функцию модуля выражений - начинаются танцы с бубнами и песни с плясками. Потом вроде собрал - там работает, тут не работает. Дыщь-хрыщь, фкорзину мляха муха! Думаю пущай лежит пока меня "отпустит". Где-то упираюсь в ограничения DX, где-то что-то пересекается с ее автоматикой. Не очень люблю условности, чтобы выкладывать недобитое "решение". Наверное надо "подписывать договор совместной разработки :D ". Могу куски частично работающего кода с включенными в него идеями выкладывать на доработку и обертку в нормальные функции.
Изображение

neitri
Мастер скриптов
Сообщения: 539
Зарегистрирован: 13 фев 2017, 17:42

Re: Пример: Лог пользователей.

Сообщение neitri » 17 май 2017, 09:09

Пример выше подчиненные формы не следит. Актуально для справочников. Для документов нужно допиливать.
Помогли Тебе. Помоги проекту.
Реквизиты помощи Вы можете найти в окне "О программе"

Аватара пользователя
YurAnt
Эксперт
Сообщения: 3352
Зарегистрирован: 13 апр 2017, 08:57
Поблагодарили: 6 раз
Контактная информация:

Re: Пример: Лог пользователей.

Сообщение YurAnt » 17 май 2017, 09:16

Для подчиненных думается серьезный запил нужно делать...
Изображение

Аватара пользователя
YurAnt
Эксперт
Сообщения: 3352
Зарегистрирован: 13 апр 2017, 08:57
Поблагодарили: 6 раз
Контактная информация:

Re: Пример: Лог пользователей.

Сообщение YurAnt » 17 май 2017, 09:40

Вообще наверное для небольшого лога последних изменений, где достаточно несколько строк, может и правда проще шапковое решение...
Еще пришла такая мысль - с целью уменьшения объема записываемых данных их можно частично типизировать в коротких константах. Например:
"ВидДокумента" = 1
"Изменил запись" = 2
"Пользователь: " = 3
"Изменил поле: " = 2
...
и т.д.
Потом на ходу расшифровка строк вида (белиберда поясняющая суть):
"1,3,2,КлиентНаименование,3";
"2,4,7,КлиентНаименование,1";
"1,5,3,8,";
Реальная экономия ресурсов для "фулл-лога".
Изображение

cordek
Знаток
Сообщения: 411
Зарегистрирован: 14 май 2017, 14:53
Благодарил (а): 80 раз
Поблагодарили: 10 раз

Re: Пример: Лог пользователей.

Сообщение cordek » 18 май 2017, 14:48

А нельзя ли сделать скрипт, который при изменении каких-то полей будет записывать в другую форму, создавая новую запись?
Вопрос не только к ведению лога, но и к другим задачам.

Аватара пользователя
YurAnt
Эксперт
Сообщения: 3352
Зарегистрирован: 13 апр 2017, 08:57
Поблагодарили: 6 раз
Контактная информация:

Re: Пример: Лог пользователей.

Сообщение YurAnt » 18 май 2017, 14:49

Он чуть Выше. viewtopic.php?f=5&t=190&p=7646#p7569
Изображение

Nikxdrummer
Опытный
Сообщения: 257
Зарегистрирован: 16 фев 2017, 10:56
Откуда: Новосибирск
Благодарил (а): 5 раз

Re: Пример: Лог пользователей.

Сообщение Nikxdrummer » 19 май 2017, 05:53

neitri писал(а):Я писал скриптами.
Для каждой формы прописывал обработчик

Код: Выделить всё

procedure Form_Create;
begin
  Self.OnBeforePost := @LastUserEdit;
end;   

Код обработчика в модуле

Код: Выделить всё

procedure LogMsg(Msg:String; doc:string;id:integer);
var
   Fm: TdxForm;
Begin
//MainWindow.OnCreateForm := @FormCreate;
   Fm := CreateForm('SYSTEMLOG');
   // Если надо добавить новую запись
   Fm.OpenRecord(0);
   Fm.Append;
   // Заполняем при необходимости поля, если это ввода на основании
   Fm['Дата'] := Date;
   Fm['Время'] := Time;
   Fm['Сообщение'] := GetCurrentUser+ ' '+ Msg;
   Fm['ТипДок']:= doc;
   fm['НомерДок']:=id;
   Fm.Post
   DestroyForm(Fm);
end;

procedure ConfirmClose(Sender:TObject; var Ok:Boolean);
Begin
  ok:=true;
  case MessageDlg('Сохранение...','Сохратить изменения?', mtConfirmation, [mbYes, mbNo, mbCancel]) of
    mrYes://Устанавливаем
      Ok:=true;
    mrNo:// закрыть без сохранения
      begin
        TdxForm(sender).Cancel;
        Ok:=true;
      end;
    mrCancel:
      Ok:=false;
  end;
end;


function VarToStrDef(const V: Variant; const ADefault: string): string;
begin
  if not VarIsNull(V) then
    Result := V
  else
    Result := ADefault;
end;
function VarToStr1(const V: Variant): string;
begin
  Result := VarToStrDef(V, '');
end;
function VarToStr(const V: Variant): string;
begin
  case VarType(V) of
    varSmallInt,
    varInteger   : Result := IntToStr(V);
    varSingle,
    varDouble,
    varCurrency  : Result := FloatToStr(V);
    varDate      : Result := FormatDateTime('dd/mm/yyyy', V);
    varBoolean   : if V then Result := 'T' else Result := 'F';
    varString    : Result := V;
    else            Result := VarToStr1(V);
  end;
end;
function VarTypeToStr(const V: Variant):string;
begin
  case VarType(V) of
//    varAny      : Result := 'varAny';
    varArray    : Result := 'varArray';
    varBoolean  : Result := 'varBoolean';
    varByRef    : Result := 'varByRef';
    varByte     : Result := 'varByte';
    varCurrency : Result := 'varCurrency';
    varDate     : Result := 'varDate';
    varDispatch : Result := 'varDispatch';
    varDouble   : Result := 'varDouble';
    varEmpty    : Result := 'varEmpty';
    varError    : Result := 'varError';
    varInt64    : Result := 'varInt64';
    varInteger  : Result := 'varInteger';
    varLongWord : Result := 'varLongWord';
    varNull     : Result := 'varNull';
    varOleStr   : Result := 'varOleStr';
    varShortInt : Result := 'varShortInt';
    varSingle   : Result := 'varSingle';
    varSmallInt : Result := 'varSmallInt';
//    varStrArg   : Result := 'varStrArg';
    varString   : Result := 'varString';
    varTypeMask : Result := 'varTypeMask';
    varUnknown  : Result := 'varUnknown';
    varVariant  : Result := 'varVariant';
    varWord     : Result := 'varWord';
    else Result := VarToStr1(V);
  end;
end;
procedure ChangeLog(Sender:TObject);
var
  i:integer;
  f:Tfield;
  fn,o,v,msg:string;
begin
//debug('ChangeLog');
  msg:='';
  for i:=0 to tdxForm(sender).Grid.Columns.count-1 do
    begin
      f:=tdxForm(sender).Grid.Columns.items[i].field;
      if f.value<>f.OldValue then
        begin
          fn:=tdxForm(sender).Grid.GetFieldName(tdxForm(sender).Grid.Columns.items[i]);
          v:=VarToStr(f.Value);
          o:=VarToStr(f.OldValue);
          msg:=msg + fn+' "'+o+'"=>"'+v+'"; ';
          debug(fn+VarTypeToStr(f.Value));
        end;
    end;
    Logmsg(msg,tdxForm(sender).formcaption,tdxForm(sender).RecId);
end;

Procedure LastUserEdit(Sender: TObject);
Begin
  //Устанавливаем
  debug('LastUserEdit');
  ChangeLog(Sender);
  TdxForm(sender).fields['Сохранил']:=GetCurrentUser;
  TdxForm(sender).fields['ДатаСохранения']:=Now;
  TdxForm(sender).fields['ВремяСохранения']:=Now;
End;         


Объясните как это работает и что нужно с этим делать, а то тут не все программисты))

neitri
Мастер скриптов
Сообщения: 539
Зарегистрирован: 13 фев 2017, 17:42

Re: Пример: Лог пользователей.

Сообщение neitri » 19 май 2017, 06:54

Есть форма SYSTEMLOG с полями

Код: Выделить всё

   Fm['Дата'] := Date;
   Fm['Время'] := Time;
   Fm['Сообщение'] := GetCurrentUser+ ' '+ Msg;
   Fm['ТипДок']:= doc;
   fm['НомерДок']:=id;

процедура LogMsg(Msg:String; doc:string;id:integer); записывает в SYSTEMLOG текст сообщения Msg, Название формы doc, и идентификатор записи id.
в обработчике OnBeforePost необходимо вызвать процедуру LastUserEdit или ChangeLog.
LastUserEdit вызывает сначала ChangeLog а после сохраняет в записи кто сохранил и когда. На форме соответственно должны быть поля

Код: Выделить всё

  TdxForm(sender).fields['Сохранил']:=GetCurrentUser;
  TdxForm(sender).fields['ДатаСохранения']:=Now;
  TdxForm(sender).fields['ВремяСохранения']:=Now;

Большой листинг это код пользовательского модуля, у меня он называется Log. Его необходимо подключить к форме

Код: Выделить всё

{$i Log} 
procedure Form_Create;
begin
  Self.OnBeforePost := @LastUserEdit;
end;   
Помогли Тебе. Помоги проекту.
Реквизиты помощи Вы можете найти в окне "О программе"