kintoneのWebhookの限界を超える、更新/削除前のレコード情報が取れない問題を解決

kintone

こんにちは、SEタケです。

Webhookで更新前と削除前のレコード情報を使いたい、そういうことはありませんか。

 

kintoneはシンプルで気軽に使えるツールですが、kintone本体だけでできることは限られています。

追加の機能がほしいときは、主に3つの選択肢があります。

  1. プラグインを使う
  2. JavaScriptで実装する
  3. Webhookでシステム連携

基本的には、プラグインを利用するケースが多いかと思いますが・・

目的に適したプラグインが見つからなかったり、利用料が見合わない場合は、

JavaScriptかWebhookを利用することになりますね。

 

簡単な処理や画面制御はJavaScriptでもできますが、

複雑な処理や、外部サービスへの連携が必要だったりする場合は、Webhookが便利です。

 

例えば、集計処理や引き当て処理、メール/SNS/カレンダー/Web会議への連携処理、などが考えられます。

これらは、WebhookでAzureやPower Automateなどのサービスを呼ぶことで、比較的簡単に実現できますし、ほとんどのケースでプラグインよりも安価になります。

 

なのですが、kintoneのWebhook機能には、とても残念だと感じる点が1点あります。

それは、削除時/更新時に、削除前/更新前のレコード情報が取得できない、という点です。

 

この制限を乗り越えるために、少し工夫が必要になります。

今回は、その方法について、解説します。

 

Webhookを自由に活用するために、とても参考になる内容ですので、ぜひ最後までお読みください。

 

スポンサーリンク

案件の利益計算を例に考える

まず、説明のための例として、案件の利益計算を考えます。

 

工事やイベントなど、案件を受託して、計画を立て、いろいろなところに発注したりして目的を達成して、納品する、そういうビジネスがあるとします。

案件の売上から、発注した費用を集計して差し引き、案件ごとの利益を算出する、という流れで考えます。

(実際は、人件費や経費なども集計したいところですが、今回は単純化のため、発注だけにします。)

 

データの構成としては、案件情報に対して、複数の発注情報が紐づく構成とします。

kintoneアプリの構成としては、下記のようになります。

  • 「案件情報アプリ」と「発注情報アプリ」を作成
  • 「発注情報アプリ」に「案件情報アプリ」へのルックアップフィールドを設置
  • 「発注情報アプリ」には「発注額」、「案件情報アプリ」には「売上」と「発注額の合計」フィールドを設置
  • 「案件情報アプリ」に「利益」(売上ー発注額の合計)の計算フィールドを設置

 

発注情報を追加/編集すると、案件情報に発注額の合計が自動で集計され、案件ごとの利益が算出される、という仕組みが目標です。

 

kintone本体だけの機能では、これは実現できません。

このようなケースでよく使われるプラグインの一つに、krewDataがありますが、今回これは使わないこととします。

また、APIや関連レコード一覧を使ってスクリプトで発注額を合計する、という方法も考えられますが、一覧や詳細など画面ごとに処理を作成する必要があるなど、複雑になってしまいます。

 

ということで今回は、Azureに集計処理を作成し、Webhookを使ってそれを実行する、という方法をとることにします。

 

Azureで集計処理を実装

Azureでの集計処理は、まずは下記のような処理にします。

  1. 「発注情報アプリ」のレコード追加/更新時に実行(Webhookで呼び出し)
  2. 追加/更新された発注情報と同じ案件に紐づく発注情報を、kintoneのAPIで取得し、発注額を合計
  3. 発注額の合計(2で計算したもの)を、「案件情報アプリ」の「発注額の合計」フィールドにAPIで更新

 

これで、「発注情報アプリ」のレコード追加/更新時の仕組みは、できました。

下記のパターンでは、発注額の合計が計算されるようになりました。

  • 発注情報の追加
  • 発注情報の発注額を変更

 

ですが、これだけでは充分ではありません。

下記のケースの考慮がもれていますね。

  • 発注情報を削除したとき、削除された発注情報に紐づく案件の、発注額合計を計算しなおす
  • 発注情報の案件を付け替えたとき、変更前の発注情報に紐づく案件の、発注額合計を計算しなおす

 

ここで、問題が出てきます。

kintoneのWebhookは、レコードが追加/更新/削除された後に実行されるのですが、

「削除/更新前のレコード情報が渡されない」のです。

 

困りました。

削除/更新前の発注情報に紐づく案件がわからなかったら、どうやって案件の発注額を集計しなおせばいいのか。。

 

これを実現するためには、少し小細工が必要になります。

小細工は、削除と更新(案件の付け替え)で異なりますので、それぞれ説明します。

 

小細工の前準備(共通)

結局のところ、発注情報の削除/更新時に、削除/更新前の案件が、Webhookに渡せればいいわけですよね。

ということは、予めそれ用のフィールドを用意して、Webhookで渡すようにすればよくないですか。

 

ということで、共通の前準備として「発注情報アプリ」に「更新前の案件」フィールドを追加します。

発注情報の更新/削除前に紐づいていた案件を、このフィールドを使ってWebhookに渡す、という考えです。(方法は後述します)

 

また、Azureでの集計処理に下記の処理を追加します。

  1. 「更新前の案件」フィールドに値が入っていて、「案件」の値と違う(変更された)ときは、追加の処理(下記2)を行う
  2. 更新前の案件に紐づく発注情報(「案件」=更新された発注情報の「更新前の案件」)についても、発注額の集計を行う。

 

「更新前の案件」フィールドは手で変更はしてほしくないので、スクリプトで非表示にしておくと、よりいいですね。

 

発注情報を削除したときの小細工

削除時のWebhookでは、削除前のレコード情報どころか、レコード情報自体が渡されません。

ですので、削除時はWebhookを呼ばず、更新時のWebhookを利用します。

 

どういうことかというと、

スクリプトで、発注情報の削除直前に、APIでレコードを更新して、強制的に更新時のWebhookを実行させるようにします。

 

その際、APIで更新するレコードの値は、下記を指定します。

  • 「更新前の案件」=「案件」 (削除前に紐づいていた案件の発注額合計を再計算するため)
  • 「案件」=空 (発注額の集計に、削除レコードを含めないため)

スクリプトの処理を実行するイベントとしては、下記になります。

  • app.record.detail.delete.submit(詳細画面でのレコード削除)
  • app.record.index.delete.submit(一覧画面でのレコード削除)

 

これによって、下記の流れになります。

  1. 削除前にスクリプトでレコードを更新
  2. 更新時のWebhookが呼ばれ、削除レコードを除いた発注額の合計が再計算される
  3. レコード削除

 

削除については、これで解決ですね。

 

発注情報を更新(案件付け替え)したときの小細工

次は、更新時の小細工です。

 

削除時の小細工と同様でいいのでは?

と思われた方もいるかもしれません。

  1. 削除前にスクリプトでレコードを更新
  2. 更新時のWebhookが呼ばれ、更新前レコードを除いた発注額の合計が再計算される
  3. レコード更新
  4. 更新時のWebhookが呼ばれ、更新後レコードを含む発注額の合計が計算される

で、オッケー!

・・実は私もそう思いました。

 

ですが、更新のときは、誰かが先に更新しているときは、エラーになるんです。

先ほどの手順1で更新されているので、3でエラーになって更新できない、ということになります。

 

ということで、同じ手は使えません。

 

ではどうするかというと・・

 

更新画面を開いたときと、一覧で更新アイコンをクリックしたときに、

スクリプトで「更新前の案件」フィールドに「案件」フィールドの値を予めコピーしておきます。

 

スクリプトの処理を実行するイベントとしては、下記になります。

  • app.record.edit.show
  • app.record.index.edit.show

 

これによって、下記の流れになります。

  1. 更新の入力前に、更新前の案件を退避
  2. 更新時にWebhookが呼ばれ、更新前レコードを除いた発注額の合計と、更新後レコードを含む発注額の合計が計算される

 

更新(案件付け替え)についても、これで解決ですね。

 

まとめ

具体的なスクリプトソースやAzureのロジックなどは、今回は提供しませんでしたが、

大まかな方法としては、ご理解いただけたのではないかと思います。

 

この方法を応用して、kintoneをどんどん便利にしていきましょう。

 

スクリプトソースやAzureロジックのサンプルは、また公開したいと思います。

 

以上、最後までお読みいただき、ありがとうございました。

コメント