FileMaker13でのトランザクション制御について

ファイルメーカーのコミットは標準だとフィールドの外をクリックしたタイミングになります。レコード単位で関連レコードも含めた全体をこのタイミングで排他制御しているので、通常の更新では特に問題無いと私は考えています。

ですが、例えば販売管理などで新規注文を入力する場合など、必要項目が全て入力されてから他の端末からも参照出来るようにしたい場面が存在します。
このようなニーズに応える方法を実装したサンプルを現行バージョンのFileMaker13で作ってみましたので、実現方法の説明をします。

---

##概要
詳細説明の前にどのような作りにしたのかを大まかに説明します。

- トランザクション制御する編集用画面はモーダルウィンドウにする
- トランザクションが開始されているか判断するフラグ用にグローバル変数を１つ用意(今回は$$onTransaction とした）
- フラグを立てるタイミングは編集画面を開く時
- フラグを消すのは編集用画面の「確定用ボタン」か「キャンセルボタン」が押された時
- 編集用画面でフィールド外をクリックされてもコミットしないように、レイアウトトリガでトランザクション中かを判断する。（使用したトリガは**「OnRecordCommit」**と**「OnLayoutExit」**）

以上です。
現行バージョンだとトリガとモーダルウィンドウが使えるので、かなりシンプルに制御できるようになりました。

##サンプルファイルの説明
今回作成したサンプルですが、販売管理の注文入力・編集の部分だけを実装しています。
注文一覧画面から新規注文入力と既存注文の編集が出来るようにしました。
その時の入力・編集画面がトランザクション制御の対象になっています。

画面はこんな感じです。まずは一覧画面。
![注文一覧画面](https://qiita-image-store.s3.amazonaws.com/0/68589/8525fb7a-f7b4-905d-0eaa-77625349c2dd.png)

次に入力・編集画面。
![注文入力編集画面](https://qiita-image-store.s3.amazonaws.com/0/68589/522cf54d-d266-b762-0f2c-3fa21699fb4b.png)

##実装内容説明
それでは実装内容について順番に説明していきます。

###スクリプト
今回作成したスクリプトは３つです。
1. 編集用画面を開く時用（引数で新規か編集かを指定）
2. 編集用画面でボタンが押された時用（引数で確定かキャンセルかを指定）
3. 編集用画面のトリガ用

順番に見ていきましょう。

###1.編集用画面を開く時用のスクリプト
最初にスクリプトの内容全体です。

```Script:注文入力画面表示(mode)
1  変数を設定 [$mode; 値:Get ( スクリプト引数 )]
2  エラー処理 [オン]
3  新規ウインドウ [名前: "注文入力"; 高さ: 650; 横幅: 850; 上: 100; 左: 100; スタイル: ダイアログ]
4  レイアウト切り替え [「注文入力」 (注文ヘッダ)]
5  //  メニューバーの表示切り替え  [隠す]
6  ツールバーの表示切り替え [ロック; 隠す]
7  If [$mode = "new"]
8  	新規レコード/検索条件
9  End If
10 レコード/検索条件を開く
11 If [Get ( 最終エラー )]
12 	カスタムダイアログを表示 ["編集開始できません"; "現在このレコードの編集はできません。¶しばらく経ってから実行してください。"]
13 	ウインドウを閉じる [現在のウインドウ]
14 Else
15	変数を設定 [$$onTransaction; 値:1]
16 End If
```

やっていることは モーダルで画面を開いて、新規の場合はレコードを作って、トランザクションを明示的に開始（レコードを開く）して、フラグを立てています。

###2.編集用画面でボタンが押された時用のスクリプト
まずはスクリプトの内容全体。

```Script:注文登録(type)
1  #トランザクションの状態を判定しコミット(type: "commit" or "cancel")
2  エラー処理 [オン]
3  変数を設定 [$type; 値:Get ( スクリプト引数 )]
4  If [IsEmpty($type)]
5  	現在のスクリプト終了 [結果: False]
6  Else If [$type = "cancel" and not IsEmpty(Get ( 変更されたフィールド ))]
7  	カスタムダイアログを表示 ["キャンセル確認"; "現在の変更をキャンセルしますがよろしいですか？"]
8  	If [Get ( 最終メッセージ選択 ) = 2]
9  		現在のスクリプト終了 [結果: True]
10 	End If
11 	レコード/検索条件復帰 [ダイアログなし]
12 Else
13 	レコード/検索条件確定 [ダイアログなし]
14 End If
15 変数を設定 [$$onTransaction; 値:""]
16 ウインドウを閉じる [現在のウインドウ]
17 ウインドウ内容の再表示 [キャッシュ結合結果を書き込む; キャッシュ外部データを書き込む]
18 現在のスクリプト終了 [結果: True]
```

キャンセルボタンを押された場合は、レコードの復帰。
確定ボタンが押された場合は、レコードの確定。
そのあとに、フラグの値をクリアして画面を閉じて一覧に戻っています。

###3.編集用画面のトリガ用スクリプト
これは単純です。

```Script:trg_トランザクション判定
1 If [IsEmpty($$onTransaction)]
2 	現在のスクリプト終了 [結果: True]
3 Else
4 	現在のスクリプト終了 [結果: False]
5 End If
```

フラグが立っていたらFalseを返して、コミットや画面を閉じるのをやめさせています。

あとは各ボタンやトリガにスクリプト設定を埋めるだけ。

##一覧画面
###新規注文ボタンの設定
スクリプト「注文入力画面表示(mode)」に引数「new」を渡しています。

![新規注文ボタンの設定](https://qiita-image-store.s3.amazonaws.com/0/68589/87cf3ab8-03de-18c5-0fe9-504d24ef6c29.png)

###編集ボタンの設定
スクリプト「注文入力画面表示(mode)」に引数「edit」を渡しています。
![編集ボタンの設定](https://qiita-image-store.s3.amazonaws.com/0/68589/59156589-3498-7f47-64e6-3dfc7f4cbf79.png)

##編集画面
###登録ボタンの設定
スクリプト「注文登録(type)」に引数「commit」を渡しています。
![登録ボタンの設定](https://qiita-image-store.s3.amazonaws.com/0/68589/a80fbc6d-9fba-f7d2-1801-1666a218a990.png)

###キャンセルボタンの設定
スクリプト「注文登録(type)」に引数「cancel」を渡しています。
![キャンセルボタンの設定](https://qiita-image-store.s3.amazonaws.com/0/68589/6ff31e14-1fb8-3a00-6b08-134ae970e731.png)

###レイアウトトリガの設定
イベント「OnRecordCommit」と「OnLayoutExit」にスクリプト「trg_トランザクション判定」を設定しています。
![レイアウトトリガの設定](https://qiita-image-store.s3.amazonaws.com/0/68589/b1ae98fd-eafc-9a47-8ba4-87879f09e987.png)

以上です。
同様に処理を入れることで他のデータについてもトランザクション制御可能になるはずです。
サンプルファイルも置いておきますので参考にしてみて下さい。

[サンプルファイル](http://it-komons.jp/filemaker/samples/fm-transaction.zip)