目指せ!JavaScript カスタマイズ中級者(4)〜kintone REST API Client 編〜

目次

はじめに

目指せ!JavaScriptカスタマイズ中級者(1)〜webpack 編〜 では複数のアプリカスタマイズを扱うための webpack の導入をしていました。
今回は同じ webpack の環境で、kintone REST API を扱うのに便利な kintone REST API Client をインストールして利用できるようにし、簡単に使い方をお伝えします。

目指せ中級者シリーズの記事一覧は以下を参照してください。
目指せ中級者シリーズ

kintone REST API Client とは

kintone REST API Client は、kintone REST API を利用するためのライブラリです。
たとえば次のようなレコードやアプリの操作が簡単にできます。

  • レコード全件取得
  • アップサート(既存のデータがあったらアップデートし、なかったらインサートする)

もともと、同じ用途のライブラリーとして kintone JS SDK (External link) というものもありますが、そちらは利用非推奨となっています。
今まで kintone JS SDK を使っていた方も今回紹介する kintone REST API Client をぜひ利用いただければと思います。

使うための準備

目指せ!JavaScriptカスタマイズ中級者(1) 〜webpack編〜 で説明したように JavaScript ファイルを build できるようになっているのが前提です。

下記をコマンドラインから入力し実行します。

1
npm install @kintone/rest-api-client

これでインストールが始まり、kintone REST API Client を利用できます。
初めて利用する方は以下の記事の QuickStart をやってみるとよいでしょう。
kintone JavaScript Client (@kintone/rest-api-client)

使い方

GitHubのkintone-rest-api-client (External link) のページに利用方法などが書かれていますが、英語ですのでリファレンスのどこを参照すればよいかを説明します。

リファレンス

Record (External link)

レコードの取得や作成などレコードの操作に関することが記載されています。
通常、このリファレンスが基本になると思います。

App (External link)

アプリの設定変更の操作に関することが記載されています。
アプリの設定を自動で変更したいなどがあれば使いますが、見る頻度は基本的に低いはずです。

File (External link)

ファイルのアップロード、ダウンロードに関することが記載されています。
レコードにファイルを添付したい場合などもこちらを利用することになります。

BulkRequest (External link)

複数アプリへのレコード一括処理に関することが記載されています。

リファレンスの読み方

リファレンスの各項目には、その関数の説明と、Parameters(関数の引数)と Returns(関数の戻り値)があります。
英語で読み取れないところは Google 翻訳などを利用すれば理解の一助になるかと思います。

  1. 関数名
  2. 関数の説明
  3. 関数の戻り値
  4. 関数の引数

使用例

リファレンスに記載されているものから一部、使用例を次に示します。
async/await 形式で記述します。
参考にしてください。

レコードを取得

アプリ ID が「1」でレコード番号が「10」のレコードを取得したい場合の例です。

1
const res = await client.record.getRecord({app: '1', id: '10'});

レコードを一括取得

2020 年 7 月定期メンテナンスで、それ以降に作られるアプリは offset 上限が 1 万件となってしまったため、レコードを全件取得する場合は カーソル API を使う必要があります。

ですが、kintone REST API Client ではカーソル API を意識せずとも次のように全件取得できます。

アプリ ID が「1」でフィールドコードが「price」、「price が 1000 以上のもの」を取得したい場合の例です。

1
const res = await client.record.getAllRecords({app: '1', condition: 'price >= 1000'});

レコードの作成

アプリ ID が「1」でフィールドコードが「fiel-cod-1」のフィールドに「サンプルテキスト」と入力されたレコードを作成したい場合の例です。

1
const res = await client.record.addRecord({app: '1', record: {field_code_1: {value: 'サンプルテキスト1'}}});

レコードの更新

アプリ ID が「1」でレコード ID が「10」、フィールドコードが「fiel-cod-1」のフィールドに「サンプルテキスト 2」と入力された状態にレコードを更新したい場合の例です。

1
const res = await client.record.updateRecord({app: '1', id: '10', record: {field_code_1: {value: 'サンプルテキスト2'}}});

レコードの複数更新

次のように、アプリ ID が「1」のアプリに対し、次のレコードを一括で更新したい場合の例です。

  • レコード ID が「11」、フィールドコードが「fiel-cod-1」のフィールドに「サンプルテキスト 1」と入力
  • レコード ID が「12」、フィールドコードが「fiel-cod-2」のフィールドに「サンプルテキスト 2」と入力
  • レコード ID が「13」、フィールドコードが「fiel-cod-3」のフィールドに「サンプルテキスト 3」と入力
1
2
3
4
5
6
7
8
9
const res = await client.record.updateAllRecords({
  app: 1,
  // レコードは、オブジェクトの配列で指定します。
  records: [
    {id: '11', record: {field_code_1: {value: 'サンプルテキスト1'}}},
    {id: '12', record: {field_code_2: {value: 'サンプルテキスト2'}}},
    {id: '13', record: {field_code_3: {value: 'サンプルテキスト3'}}},
  ]
});

レコードのアップサート

アップサートとは、該当するレコードがなければインサート(挿入・新規作成)、該当するレコードがあればアップデート(更新)をするための機能です。

次の内容でアップサートする例です。

  • アプリ ID が「1」
  • 更新対象のレコード:更新のキーに利用するフィールドのフィールドコードが「fiel-key」で値が「apple」のレコード
  • 更新内容:フィールドコードが「fiel-cod-1」のフィールドに「サンプルテキスト 1」と入力
1
2
3
const res = await client.record.upsertRecord({
  app: '1', updateKey: {field: 'field_key', value: 'apple'}, record: {field_code_1: {value: 'サンプルテキスト1'}}
});

サンプル

アプリ間のデータのやりとりで kintone REST API Client を中心に使ったサンプルを示します。

シナリオ

kintone アプリストアに、見積書アプリと商品リストアプリの 2 つのアプリがパックになっている「商品見積書パック」というものがあります。
見積書アプリで見積作成時に、ルックアップフィールドを用いて商品リストアプリにある商品を選べるものです。

それを利用して、次の仕様を満たすようアプリのカスタマイズと JavaScript カスタマイズを行います。

  1. 見積作成時(見積アプリでレコード保存時)に、選択されている商品の在庫数を減らす。
  2. 見積作成時(見積アプリでレコード保存時)に、選択されている商品の在庫がない場合はエラーを表示する。

保存時のイメージ

レコードを保存したときの動作イメージは次のとおりです。

  • 保存時に、数量分の、在庫数がなければ保存させない。
  • 在庫がある場合は、在庫引当処理を行う(商品リストアプリの在庫数をへらす)

なお「在庫数」フィールドは今回のサンプルで追加します。

アプリの用意と設定

アプリの用意

kintone アプリストアにある 商品見積書パック (External link) を選び「このアプリパックを追加」を押して追加してください。

アプリの設定

商品リストアプリに、フィールド名とフィールドコードが「在庫数」のフィールドを追加してください。
また、見積書アプリからルックアップするためのレコードを 1 つ以上登録してください。

JavaScript カスタマイズ

コードを書き、ビルドしたものを見積書アプリにアップロードしてください。

コードは、以下のリポジトリにも公開しています。
https://github.com/cybozudevnet/sample-kintone-webpack-for-intermediate/tree/master/src/apps/quote (External link)

ビルドやアップロード方法については 目指せ!JavaScript カスタマイズ中級者(2)〜自動で一括ファイルアップロード編〜 などの記事を参照ください。

4 行目のアプリ ID については、環境に合わせて書き換えてください。

 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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import {KintoneRestAPIClient} from '@kintone/rest-api-client';

// 商品リストのアプリIDを入力してください
const productsAppId = 122;

const events = ['app.record.create.submit', 'app.record.edit.submit'];

kintone.events.on(events, async (event) => {
  const {record} = event;

  // kintoneへ接続するためのインスタンスを作成
  const client = new KintoneRestAPIClient();

  // 今回はコード簡略化のために、テーブルの商品は重複禁止とします。
  // ただの簡易的な重複チェックなので意味は理解しなくてOKです。
  const hasDuplicatedRow = record.見積明細.value.some((rowA, indexA, arr) => {
    return arr.find((rowB, indexB) => indexA !== indexB && rowA.value.型番.value === rowB.value.型番.value);
  });
  if (hasDuplicatedRow) {
    event.error = '重複した商品は登録できません。';
    return event;
  }

  // テーブルに入っている商品レコードを取得
  let products;
  try {
    products = await client.record.getRecords({
      app: productsAppId,
      query: `型番 in (${record.見積明細.value
        .map((row) => `"${row.value.型番.value}"`)
        .join(', ')})`,
    });
  } catch (error) {
    event.error = 'レコードの取得に失敗しました';
    return event;
  }

  // 商品リストの在庫数を差し引いたデータを作成
  const deductedProductRecords = products.records.map((productRecord) => {
    const tableRow = record.見積明細.value.find(
      (row) => productRecord.型番.value === row.value.型番.value
    );

    // アップデートのキーとなる型番と, 差し引いた在庫数を格納する。
    return {
      型番: {
        value: productRecord.型番.value,
      },
      在庫数: {
        value: Number(productRecord.在庫数.value) - Number(tableRow.value.数量.value),
      },
    };
  });

  // 在庫数を差し引いたあと在庫数が0未満になるようなレコードがないか確認
  const noStockRecords = deductedProductRecords.filter(
    (productRecord) => Number(productRecord.在庫数.value) < 0
  );

  // 差し引き1未満のレコードがでた場合はエラーとみなしレコードの作成をストップさせる
  if (noStockRecords.length > 0) {
    // event.errorにデータをいれたあとeventを返すとレコードの作成をストップできる
    // どの商品が問題か示すために在庫が足りない商品の型番を列挙する
    event.error = `在庫がない商品があります。型番 ${noStockRecords
      .map((productRecord) => productRecord.型番.value)
      .join(', ')}`;

    return event;
  }

  // 問題なければアップデート
  try {
    await client.record.updateRecords({
      app: productsAppId,
      records: deductedProductRecords.map((productRecord) => {
        return {
          updateKey: {
            field: '型番',
            value: productRecord.型番.value,
          },
          record: {
            在庫数: {
              value: productRecord.在庫数.value,
            },
          },
        };
      }),
    });
  } catch (error) {
    event.error = `アップデートに失敗しました。${error.message}`;
    return event;
  }

  return event;
});

アップロードしたら、シナリオが実現できるか動作確認してください。

おわりに

kintone の JavaScript API をそのまま使い続けてももちろん問題ないですが、kintone REST API Client を使うとより簡単に REST でデータを扱えるようになるので、ぜひ利用してみてください。

information

この Tips は、2020 年 10 月版 kintone と @kintone/rest-api-client@1.7.0 で動作を確認しています。