ルックアップの更新を自動で行う

目次

はじめに

ルックアップ機能は、他のアプリから値を取得して、自動で情報をフィールドに入力する機能です。
たとえば、注文管理アプリを顧客管理アプリとルックアップ連携した場合、注文管理アプリでは顧客IDを入力するだけで顧客の名前や住所が自動的に入力されるようになります。
しかしながら、顧客管理アプリ側のデータを更新しても、注文管理アプリ側の顧客の名前や住所は自動では更新されません。
こういった問題の場合は、kintone REST APIを使うことで、注文管理アプリ側も自動で更新できます。
では、さっそく解説していきます。

動作イメージ

今回は、顧客マスターアプリと見積もり管理アプリを使います。
見積管理アプリから顧客マスターアプリをルックアップしています。
顧客マスターアプリの情報が更新されたとき、見積もり管理アプリに登録されたデータも自動で更新します。

デモ環境

デモ環境で実際に動作を確認できます。

ログイン情報は cybozu developer network デモ環境 で確認してください。

カスタマイズを適用するアプリ

顧客マスターアプリ

次のような顧客マスターアプリを用意します。

フィールド名 フィールドタイプ フィールドコード 備考
会社 文字列(1行) company 必須項目
部署 文字列(1行) post
電話番号 リンク tel 入力値の種類:電話番号

この顧客マスターアプリにJavaScriptを登録することで、ルックアップの自動更新を実現します。

見積もり管理アプリ

次のような見積もり管理アプリを用意します。
このアプリは、レコード番号で顧客マスターアプリからルックアップし、「会社」「部署」「電話番号」をコピーします。

フィールド名 フィールドタイプ フィールドコード 備考
ルックアップ ルックアップ lookup 関連付けるアプリ:顧客マスター
コピー元のフィールド:レコード番号
ほかのフィールドのコピー:
  • 会社⇐[顧客マスター]会社
  • 部署⇐[顧客マスター]部署
  • 電話番号⇐[顧客マスター]電話番号
コピー元のレコード選択時に表示するフィールド:会社、部署
会社 文字列(1行) company 必須項目
部署 文字列(1行) post
電話番号 リンク tel 入力値の種類:電話番号
テーブル テーブル Table
テーブル[製品] 文字列(1行) product
テーブル[個数] 数値 quantity 最小値:0以上
テーブル[単価] 数値 unit_price 最小値:0以上
単位:¥
テーブル[価格] 計算 price 計算式:unit_price*quantity
計算式を表示しない
単位:¥
小計 計算 subtotal 計算式:SUM(price)
計算式を表示しない
単位:¥
消費税 計算 tax 計算式:subtotal*0.08
計算式を表示しない
単位:¥
合計 計算 total 計算式:subtotal+tax
計算式を表示しない
単位:¥

作成できたら、アプリIDは後で使うので控えておいてください。

実装する処理を整理

今回カスタマイズする内容と、実装する処理の流れをまとめます。

カスタマイズする内容

顧客マスターアプリで特定のレコードが更新されたとき、そのレコードをルックアップしている見積もり管理アプリのレコードを検索し、フィールドの内容を最新のものに更新する。

実装する処理

顧客マスターアプリで、レコードが更新されたときに以下の処理を行います。

  1. 見積もり管理アプリの対象レコードを一括取得
  2. レコード更新用のデータを準備し、1の対象レコードを一括更新
  3. 処理の成功、失敗を知らせるメッセージを表示

別アプリのデータを更新するので、更新処理がうまくいったかどうかを実行後にメッセージでお知らせします。
1~3は処理の順番を守る必要がある、ということが重要なポイントです。

サンプルコード

見積もり管理のアプリのアプリIDは環境によって変えてください。

lookupAutoUpdate.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/*
 * ルックアップ更新のサンプルプログラム
 * Copyright (c) 2024 Cybozu
 *
 * Licensed under the MIT License
 * https://opensource.org/license/mit/
 */
(() => {
  'use strict';
  // 見積もり管理アプリのアプリID
  const updateAppId = 21;
  // 保存成功後イベント
  kintone.events.on([
    'app.record.edit.submit.success',
    'app.record.index.edit.submit.success'
  ], async (event) => {
    // 検索する条件をまとめたオブジェクトを作成する
    const paramGet = {
      app: updateAppId,
      query: 'lookup = ' + event.record.$id.value
    };

    try {
      // レコードを一括で取得する(100件まで)
      const resp = await kintone.api(
        kintone.api.url('/k/v1/records.json', true), 'GET', paramGet
      );
      // レコードの更新データを用意する
      const estimationAppRecords = resp.records.map((record) => {
        return {
          id: record.$id.value,
          record: {
            lookup: {
              value: record.lookup.value
            }
          }
        };
      });
      // appにアプリid, recordsに更新データを入れたオブジェクトを作成する
      const paramPut = {
        app: updateAppId,
        records: estimationAppRecords
      };
      // ルックアップの更新を行う
      await kintone.api(
        kintone.api.url('/k/v1/records.json', true), 'PUT', paramPut
      );
      // 処理成功のメッセージを表示する
      window.alert('ルックアップの更新が完了しました!');

    } catch (error) {
      // エラーを表示する
      window.alert('ルックアップの更新でエラーが発生しました。\n' + error.message);
    }
  });
})();

サンプルコードの解説

保存成功時イベント

今回の処理は、顧客マスターアプリのレコード編集の保存成功後に行います。
レコードの編集は、レコード編集画面とレコード一覧画面の2ヵ所で行うことができるため、以下の2つのイベントを使います。

また、今回はasync/awaitを使った非同期処理でレコードを更新します。
そのためイベントハンドラーの関数の先頭にasyncを宣言します。

1
2
3
4
5
6
7
// 保存成功後イベント
kintone.events.on([
  'app.record.edit.submit.success',
  'app.record.index.edit.submit.success'
], async (event) => {
  // ここに処理の内容を記述する
});

更新が必要なレコードの一括取得

見積もり管理アプリから、顧客マスターアプリで更新したレコードをルックアップ参照しているものを一括取得します。
レコードを取得するkintone.api()を非同期で実行します。
非同期処理を同期的に扱うため、先頭にawaitを指定します。

1
2
3
4
// レコードを一括で取得する(100件まで)
const resp = await kintone.api(
  kintone.api.url('/k/v1/records.json', true), 'GET',
);

今回は、レコードを一括で取得する処理とルックアップの更新処理を非同期で行います。
try〜catchを使うことで、非同期の処理中にエラーが発生した場合、それを補足できます。
ここまでをまとめると、プログラムは以下のようになります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// 検索する条件をまとめたオブジェクトを作成する
const paramGet = {
  app: updateAppId,
  query: 'lookup = ' + event.record.$id.value
};

try {
  // レコードを一括で取得する(100件まで)
  const resp = await kintone.api(
    kintone.api.url('/k/v1/records.json', true), 'GET',
  );
  // レコード取得後の処理の内容を記述する


} catch (error) {
  // エラー時の処理を記述する

}

「レコード取得後の処理の内容を記述する」というコメントのところに、次の処理を足していきます。

  1. 見積管理アプリのレコードを更新するためのデータを準備
  2. 1のデータを使って、見積もり管理アプリの対象レコードを一括更新
  3. 処理の成功を知らせるメッセージを表示

2と3の処理は、必ず前の処理が終わってから行いますが、async/awaitを使うことでそれが実現できます。
async/awaitについては、以下の記事で解説させていただいていますので、参考にしてください。

また、複数のレコードを取得するAPIでは、limitオプションで一度に取得できるレコード件数を設定できます。

  • 「query」パラメーターの「limit」オプションを使用することで、最大500件まで取得できます。
  • limitに指定がない場合は一度に100件まで取得できます。

500件以上のレコードのルックアップを自動更新したい場合は、更新データの元になるレコードを一括で取得する処理が必要です。
レコードを一括で取得する方法は、「offsetの制限値を考慮したレコード一括取得について」を参考にしてください。

今回は100件までの場合で、説明します。

ルックアップの更新

更新したいレコードIDと更新内容のレコード情報をセットにしたオブジェクトを作成します。
レコード情報は、レコード取得によって得られたrespを使ってオブジェクト配列を作成します。
ルックアップのコピー先のフィールド更新は、ルックアップフィールドの値を指定するだけで実現できます。
そのため、更新内容のレコードのルックアップフィールド(lookup)に、取得した顧客マスターアプリのレコード番号をそのまま代入します。
そうすることで、更新処理が走るときに、最新の顧客管理アプリの情報がルックアップされるようになります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// レコードの更新データを用意する
const estimationAppRecords = resp.records.map((record) => {
  return {
    id: record.$id.value,
    record: {
      lookup: {
        value: record.lookup.value
      }
    }
  };
});
// appにアプリid, recordsに更新データを入れたオブジェクトを作成する
const paramPut = {
  app: updateAppId,
  records: estimationAppRecords
};

レコードを更新するAPIを使って非同期処理で更新します。

1
2
3
4
// ルックアップの更新を行う
await kintone.api(
  kintone.api.url('/k/v1/records.json', true), 'PUT', paramPut
);

動作確認

では、実際にこのJavaScriptを顧客マスターアプリに適用して、レコードを更新してみましょう。
今回は電話番号を変更します。

レコードを保存するとアラートが表示されました。

では、見積もり管理アプリのルックアップしているレコードに更新内容が反映されているか確認してみましょう。

ルックアップでコピーしているフィールドの値が最新の状態になりました。
これで、ルックアップが自動で更新されていることが確認できました。

おわりに

今回は、kintone REST APIを使ってルックアップを自動更新する方法を紹介しました。

今回のサンプルだと100件までしかルックアップの自動更新ができません。
それ以上のレコードを一括更新する場合は、以下の記事を参考に実装してみてください。
offset の制限値を考慮した kintone のレコード一括取得について

information

このTipsは、2024年5月版kintoneで動作を確認しています。