2024.05.01
OnWindowTransactionで変更ログ(監査ログ)を取得してみる【FileMaker 2023】
こんにちは。木村です。
Claris FileMaker 2023の新機能として、OnWindowTransactionというスクリプトトリガが実装されました。
2023のリリースから間もなく1年というところで、今更感も漂わせつつ、ざっくりと検証してみたいと思います。
細かく知りたい方は、他の方のブログや動画で確認していただければと思います。
Claris ジャパンの公式のWebセミナー動画もありますので、そちらもご覧ください。
▼Claris FileMaker 2023の新機能 OnWindowTransactionで実現する操作ログTips
▼Claris FileMaker 2023 OnWindowTransaction イベント基本編 〜OnWindowTransactionを使用して、レコードの変更記録を取得する〜
▼Claris FileMaker 2023 OnWindowTransaction イベント応用編 〜OnWindowTransactionを使用して、レコードの変更記録を利用する〜
「OnWindowTransaction」とは何なのか?
まず、この機能自体はスクリプトトリガを指します。
詳しい部分は他サイトを見ていただければと思うのですが、簡単に言ってしまえば、このスクリプトトリガを使って、レコードの作成、変更、削除のログ情報を取得できるようになった、という認識で良いんじゃないでしょうか。(雑)
とりあえず難しいことは考えずにやってみよう
まずはサンプルファイルを用意しました
単一ファイル内にテーブルを用意し、商品番号、商品名、価格の3つのフィールドがあるだけ。
商品名や価格を更新したときに、フィールドの変更情報を取得してみたいと思います。
[手順1]
OnWindowTransactionトリガに設定する用のスクリプトを作る
以下の様にスクリプトを設定します。
スクリプトを簡単に説明すると、OnWindowTransactionトリガで実行されるとき、変更内容がスクリプト引数として渡されるので、1行目のスクリプトでそれを受け取っています。
変数を設定 [ $変更内容 ; 値: Get ( スクリプト引数 ) ]
2行目のカスタムダイアログ表示はデバッグ用です。
スクリプト自体はシンプル。
[手順2]
作ったスクリプトをOnWindowTransactionトリガに設定する
ファイルオプションのスクリプトトリガタブ(メニュー -> ファイル -> ファイルオプション -> スクリプトトリガ)で以下のように設定し、「OK」を押します。
一旦テストなので「フィールド名」には「価格」フィールドを設定します。
(ここに設定したフィールドの変更情報を取得できます。)
[手順3]
変更情報を取得できるのかテストしてみる
りんごジュースの価格を150円に変更してみます。
レイアウトの余白部分をクリックして、レコードを確定してみると、以下のようなダイアログが表示されました。
JSON形式で、変更ログが取得できています。
それぞれの要素と値の意味は以下の通り。
【取得したJSON】
{
"さんぷる" : ←ファイル名
{
"さんぷる" : ←テーブル名(TOではない)
[
[
"Modified", ←操作(Modified:編集、New:新規、Deleted:削除)
1, ←レコードID
"150" ←指定したフィールドの値
]
]
}
}
[手順4]
2つ以上のフィールドの変更情報を取得するために
複数フィールドを監視するためのフィールドを作成する
現在の設定だと「価格」フィールドのみの変更履歴しか取得できないので、複数フィールドの変更情報を取得しようとする場合、計算フィールドを追加するのがセオリーらしい。
フィールド名はなんでも良いのですが、「OnWindowTransaction」という名前にしておけば、標準で監査対象のフィールドになります。
が、今回は「_zc_変更ログ」という名前で作りました。
以下のように設定します。
・計算式に「Get ( 変更されたフィールド )」と入力します。
・計算結果を「テキスト」に。
そして、索引オプションボタンを押して、
「計算結果を保存せずに必要時に再計算する」にチェックを入れておきます。
いわゆる非保存フィールドってやつです。
ここらへんはもう少し良い手法があるりそうですが一旦これでいきましょう。
[ちょっと補足]
「Get ( 変更されたフィールド )」の注意点
「Get ( 変更されたフィールド )」は、その名の通り、変更されたフィールドを改行区切りで返してくれますが、レコードを確定してしまうと値を返してくれません。
どういうことかというと、商品名を「りんごジュース2」にして、すぐに確定すると何も表示されません。
ですが、確定せずに価格フィールドに移動すると、「_zc_変更ログ」に表示されます。
(画面の描画が遅く表示されない場合は、メニューの、レコード->ウインドウ内容の再表示、を押して下さい)
つまり、レコードが確定されるまでしか保持されていない値なのです。
デバッグ時に「どれどれ変更されたフィールドがどうなってるのかな?」とか見たいとき、これが分かっていないと「?」ってなります。
ちなみに「Get ( 変更されたフィールド )」については、イエス ウィ キャンさんのブログが非常に為になりますので、ぜひ御覧ください。
【Claris FileMaker 2023】 ~編集ログで使用する「Get ( 変更されたフィールド )」関数の動作変更について~
そこを踏まえて、スクリプトトリガの設定を変更してみます。
[手順5]
作成したフィールドをスクリプトトリガの監視フィールドとして指定する
手順2と同様の手順で、ファイルオプションのスクリプトトリガタブ(メニュー -> ファイル -> ファイルオプション -> スクリプトトリガ)を選び、フィールド名に「_zc_変更ログ」と入力してOKを押します。
では早速、商品名を「りんごジュース3」、価格を「160」にして確定してみます。
改行区切りで変更されたフィールド名が取得できました。
これでは、何の値にしたのかは取得できていないので、このフィールド名を使ってJSONを作って行きます。
[手順6]
監視フィールド(_zc_変更ログ)の計算式を使って、取得したい情報をJSON形式にする
手順5で改行区切りで変更されたフィールド名を取得できました。
これらのフィールド名を使って、変更後の値も取得していきます。
以下のように「_zc_変更ログ」の計算式を変更します。
【「_zc_変更ログ」フィールドに設定する計算式】
--------------------------------------
While (
[
//初期変数
%fls = Get ( 変更されたフィールド );
%max = ValueCount ( %fls );
%json = "[]"; // 空のJSON配列を初期化
%i = 1
] ;
//条件
%i <= %max
; [
//ロジック
%fieldName = GetValue ( %fls ; %i );
%fieldValue = GetField ( %fieldName );
%element = JSONSetElement( "{}"; ["FieldName"; %fieldName; JSONString]; ["FieldValue"; %fieldValue; JSONString] );
%json = JSONSetElement( %json; %i - 1 ; %element; JSONObject );
%i = %i + 1
] ;
%json
)
--------------------------------------
少しややこしいように見えますが、「%fls = Get ( 変更されたフィールド );」で改行区切りの変更されたフィールドのリストを受け取っています。
で、その改行区切りの値の数だけ、Whileで繰り返し処理をしながら、フィールド名とフィールドの値をセットにしてJSONにしているだけです。
では試しに、商品名を「りんごジュース4」、価格を「170」にして確定してみます。
はい、無事JSONJ化されて取得することができましたね。
よかった。
おまけ。もう少し情報を追加してみる
一応今回はここまでで終わろうと思ったんですが、今取得できた情報に加えて、「誰が」「いつ」といった情報もいれてみたいと思います。
今回はテストなので「Get ( ユーザ名 )」「Get ( タイムスタンプ )」のみでやりますが、他に取得したい場合はプラスして書いていただければOKかと思います。
これもややこしいように見えますが、変更情報のJSONと「Get ( ユーザ名 )」「Get ( タイムスタンプ )」の情報をJSONにしてくっつけているだけです。
実際にログとして保存していくには最低限この程度の情報は必要になってくるかと思います。
【「_zc_変更ログ」フィールドに設定する計算式】
--------------------------------------
Let ( [
%情報用JSON =
JSONSetElement ( "" ;
["ユーザ名" ; Get ( ユーザ名 ) ; JSONString ];
["タイムスタンプ"; Get ( タイムスタンプ ); JSONString]
) ;
%更新内容JSON =
While (
[
//初期変数
%fls = Get ( 変更されたフィールド );
%max = ValueCount ( %fls );
%json = "[]"; // 空のJSON配列を初期化
%i = 1
] ;
//条件
%i <= %max
; [
//ロジック
%fieldName = GetValue ( %fls ; %i );
%fieldValue = GetField ( %fieldName );
%element = JSONSetElement( "{}"; ["FieldName"; %fieldName; JSONString]; ["FieldValue"; %fieldValue; JSONString] );
%json = JSONSetElement( %json; %i - 1 ; %element; JSONObject );
%i = %i + 1
] ;
%json
)
] ;
JSONSetElement("{}";
["情報"; %情報用JSON; JSONObject ];
["更新情報"; %更新内容JSON ; JSONArray ]
)
)
--------------------------------------
では、商品名を「りんごジュース5」、価格を「180」にして確定してみます。
はい。取得できました。
タイムスタンプとユーザ名もバッチリです。
このあたりをワンセットで保持しておけば、どのユーザがいつ変更したのかわかります。
まとめ
利用するにあたっては割と注意点もありますが、そこさえしっかり抑えておけば大丈夫かな。
レコードの操作ログを取りたいという要件は多いと思いますので、非常に有用。
かなりいろいろな操作ログを取得できるので、ログをどの様に保持・運用するのかは要検討ですね。(手段自体は色々ありそう)