今回は、以前紹介した「bulkRequestを使った複数アプリの一括処理(在庫管理や予約申請など)」を、kintoneアプリに実装する方法を紹介します。
具体的には、在庫アプリと出庫アプリの2つを使って、「出庫アプリでXX個の出庫を登録すると、在庫アプリの在庫がXX個減る」というしくみを作ります。
また、kintone JavaScript Client(@kintone/rest-api-client)を使用して、REST APIのコードを簡潔にしています。非常に便利なツールなので、これからコードを書く方はぜひ参考にしてみてください。
デモ環境
で実際に動作を確認できます。
ログイン情報は
cybozu developer networkデモ環境
で確認してください。
まずは、完成イメージから見ていきましょう。
在庫アプリはこのような状態です。
出庫アプリに出庫数を登録します。
すると、出庫アプリには出庫数が登録されます。
また、在庫アプリからは在庫数が減りました!
在庫が足りない場合は、このようなエラーを表示します。
①「在庫数の確認時」と②「在庫数の変更時」のリビジョンが異なる場合(①と②の間に在庫のデータが更新された場合)はこのようなエラーを表示します。
これで安全に在庫管理ができますね。
kintoneの設定
固定リンクがコピーされました
「在庫」アプリの作成
固定リンクがコピーされました
フィールド名 |
フィールドタイプ |
フィールドコード |
備考 |
商品コード |
文字列(1行) |
itemCode |
必須項目にする 値の重複を禁止する
|
商品名 |
文字列(1行) |
itemName |
必須項目にする
|
在庫数 |
数値 |
stockNum |
必須項目にする
|
「出庫」アプリの作成
固定リンクがコピーされました
フィールド名 |
フィールドタイプ |
フィールドコード |
備考 |
出庫先 |
文字列(1行) |
destination |
|
商品コード |
ルックアップ |
itemCode |
必須項目にする 関連付けるアプリ:在庫アプリ コピー元のフィールド:商品コード ほかのフィールドのコピー:「商品名」に「在庫アプリの商品名」
|
商品名 |
文字列(1行) |
itemName |
|
出庫数 |
数値 |
pickNum |
必須項目にする
|
「出庫」アプリのJS/CSS設定
固定リンクがコピーされました
「アプリの設定 > JavaScript / CSSでカスタマイズ」の「PC用のJavaScriptファイル」に以下のURL/ファイルを設定します。
- kintone JavaScript Client(@kintone/rest-api-client)
以下のURLを指定します。
https://js.cybozu.com/kintone-rest-api-client/5.5.2/KintoneRestAPIClient.min.js
- 以下のサンプルコードをエディタにコピーして、ファイル名を「sample.js」、文字コードを「UTF-8N」で保存、アップロードします。
ファイル名は任意ですが、ファイルの拡張子は「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
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
96
97
98
99
100
101
102
103
104
105
106
107
|
/*
* kintoneで安全に在庫を行うサンプルプログラム
* Copyright (c) 2024 Cybozu
*
* Licensed under the MIT License
* https://opensource.org/license/mit/
*/
(() => {
'use strict';
kintone.events.on('app.record.create.submit', async (event) => {
// 保存するレコードの情報を取得
const outBoundRecord = event.record;
// 在庫管理アプリのアプリIDを取得
const stockAppId = kintone.app.getLookupTargetAppId('itemCode');
// 出庫管理アプリのアプリIDを取得
const outBoundAppId = kintone.app.getId();
// 出庫数を取得
const pickNum = Number(outBoundRecord.pickNum.value);
// 出庫先を取得
const destination = outBoundRecord.destination.value;
// 商品コードを取得
const itemCode = outBoundRecord.itemCode.value;
try {
// KintoneRestAPIClientのインスタンスを作成
const client = new KintoneRestAPIClient();
// 在庫管理アプリから該当商品のレコードを取得
const {records: stockRecords} = await client.record.getRecords({
app: stockAppId,
query: 'itemCode = "' + itemCode + '"',
fields: ['$id', '$revision', 'stockNum']
});
// 商品レコードが1件取得できなかった場合はエラーを返す
if (stockRecords.length !== 1) {
event.error = '商品が特定できません。';
return event;
}
// 現在の在庫数を取得
const stockNum = Number(stockRecords[0].stockNum.value);
// 出庫後の在庫数を計算
const newStockNum = stockNum - pickNum;
// 在庫が足りない場合はエラーメッセージを表示して終了
if (newStockNum < 0) {
event.error = `在庫が足りません。今の在庫数は ${stockNum} です。`;
return event;
}
// 在庫管理アプリのレコード更新と出庫管理アプリのレコード登録のリクエストを設定
const params = {
requests: [
// 在庫管理アプリの在庫数更新
{
method: 'PUT',
api: '/k/v1/record.json',
payload: {
app: stockAppId,
id: stockRecords[0].$id.value,
record: {
stockNum: {value: newStockNum}
},
revision: stockRecords[0].$revision.value
}
},
// 出庫管理アプリの出庫情報登録
{
method: 'POST',
api: '/k/v1/record.json',
payload: {
app: outBoundAppId,
record: {
destination: {value: destination},
itemCode: {value: itemCode},
pickNum: {value: pickNum}
}
}
}
]
};
try {
// 在庫更新と出庫登録をbulkRequestで同時に実行
const bulkResp = await client.bulkRequest(params);
// 登録した出庫情報の詳細ページにリダイレクト
location.href = '/k/' + outBoundAppId + '/show#record=' + bulkResp.results[1].id;
// レコードの保存はbulkRequest内で実行済みなので、
// 保存イベントの動作はキャンセルする
return false;
} catch (err) {
// bulkRequestに失敗した場合のエラーハンドリング
console.log(err);
event.error = '出庫に失敗しました。';
return event;
}
} catch (err) {
// 在庫管理アプリから商品のレコード取得に失敗した場合のエラーハンドリング
console.log(err);
event.error = '商品を取得できませんでした。';
return event;
}
});
})();
|
ポイントは以下の3つです!
- bulkRequest(kintoneBulkRequest)を使って、2つのアプリ(在庫、出庫)を同時に操作します。
- bulkRequestによる在庫アプリの更新時にはリビジョンを指定します。
- bulkRequestが成功した場合は「return false」として、レコードの登録自体はキャンセルします。(94行目)
kintoneでは、各レコードの更新履歴をリビジョン(revision
)で管理しています。
レコード作成時にはリビジョンが1
に設定され、その後、レコードを保存するたびにリビジョン番号が1
ずつ増加します。
sample.js
では、出庫時にまず在庫管理アプリから在庫情報を取得します。
この際に取得したリビジョン値は、その時点での最新の状態を表す値となります。
その後、出庫後の在庫数を計算し、レコードを更新する際に、取得したリビジョン値を指定します。
更新処理では、指定されたリビジョンと現在のレコードのリビジョンが比較されます。
両方のリビジョンが一致している場合のみ、更新処理が実行されます。
一致しない場合は、取得から更新までの間に他のプロセスでレコードが変更されたことを意味し、衝突を防ぐために更新処理は中止されます。
詳細は次のAPIドキュメントを参考ください。
1件レコード更新時のパラメータ
更新時にリビジョンを指定しない場合
固定リンクがコピーされました
レコード更新時にリビジョンを指定しない場合、リビジョン番号は検証されません。
意図せず他の変更を上書きしてしまうリスクがありますが、複数のデータを一括で更新する場合や、競合リスクが低いケースでは便利に活用できることもあります。
リビジョンの使い方わかりましたでしょうか。
サンプルコードはレコードの登録、出庫にしか対応していません。
ぜひレコードの編集や入庫にも対応させてみてください。
- 2019/06/10
- 利用ライブラリをkintone Utility Library for JavaScriptからkintone JS SDKに変更
- 2024/07/25
- 利用ライブラリをkintone JS SDKからkintone JavaScript Clientに変更