[ 初めての kintone REST API ] 旅費精算申請アプリを "ちょっとだけ" 使いやすくしよう


🔖 はじめに

kintone REST API の GET(取得)と PUT(更新)メソッドを使って、

旅費精算申請アプリを "ちょっとだけ" 使いやすくカスタマイズする記事です。

cybozu developer network(以降、愛称である devnet と記載) を見ると、順番処理のために Promise

書き方の簡略化のために jQuery がよく使われていますが、いきなりそれはきつい...ですよね。

ということで、そこら辺は一旦置いておいて、まず基本的な書き方を勉強しましょう。

REST API の使い方が分かると、ゆくゆくはアプリ間連携や他サービス連携もできるようになります٩( ᐛ )و

"kintone REST API 初めの一歩" の課題としてチャレンジしてみてください!


🔖 やること

旅費精算申請アプリを使って、以下のカスタマイズしていきます。


  • レコード一覧画面を表示した時に、ログインユーザーが申請中のレコード件数を表示する

  • レコード追加画面で保存成功後に、自動でプロセスを次に進める(申請のし忘れ防止)


🔖 完成イメージ

レコード一覧画面を開くと...

IndexScreen.png

レコード追加画面で保存ボタンを押すと...

CreateSubmitScreen.gif

こうなれば成功です!

それでは早速作り込んでいきましょう。


🔖 下準備

JavaScript カスタマイズをする前に、下準備です。


1. kintone のアプリ作成

ご自身の kintone 環境にアクセスして、アプリストアから「旅費精算申請」アプリを追加します。

後々の動作確認のために予め数件レコード追加しておきます。

(💡アプリストアからアプリを追加する

※ kintone 環境をお持ちでない方は、検証目的で1年間無償でご利用いただける「開発者ライセンス」がありますので、お申し込みください。

(💡kintone環境の取得方法

旅費精算申請アプリ.png


2. テキストエディタの用意

コーディングをするためのテキストエディタを用意します。

ノートPCに標準搭載されている メモ帳 などを使うこともできますが、

Visual Studio CodeSublime Text が書きやすくて個人的にはおすすめです。


🔖 kintone REST API とは

コーディングに入る前に、kintone REST API の基本を押さえておきましょう。

kintone JavaScript API は、ブラウザ上の情報を取得・操作できるもので、一方 kintone REST API は、kintone アプリのレコード操作やフォーム設計情報の取得、スペース操作ができるものです。

※ REST APIとは:特定の URL にパラメータを指定して、HTTP/HTTPS(通信プロトコルの種類) でアクセスすることで、データ操作(取得・登録・更新・削除など)ができる仕組みのこと。

REST API 自体は、様々な方法で実行することができますが、ここでは kintone のカスタマイズ内に記述します。


基本構文

kintone REST API の基本構文は下記のようになっています。

kintone.api(pathUrl, method, params, callback, opt_errback)

// pathUrl: 特定のURL
// method: 指定した URL に対して、何をしたいかを指定する部分
// params: API に渡すパラメータをオブジェクトで指定
// callback: APIの呼び出しが成功したら実行される関数(省略可)
// opt_errback: APIの呼び出しが失敗したら実行される関数(省略可)

ここから kintone.api メソッドの各引数を見ていきましょう。


URL/URI

pathUrl の部分。kintone の何の API を扱うかを URL で指定します。どの API を使うかは操作したいデータによって異なります。

// レコードを1件操作する

https://(サブドメイン名).cybozu.com/k/v1/record.json

// レコードを複数件操作する
https://(サブドメイン名).cybozu.com/k/v1/records.json

// レコードのステータスを操作する
https://(サブドメイン名).cybozu.com/k/v1/record/status.json

サブドメインとは、この赤枠のところです。

subdomain.png

また、kintone 上でカスタマイズする場合は、kintone.api.url() メソッド を使うことで、 URL を短縮することができます。

kintone.api('https://(サブドメイン名).cybozu.com/k/v1/records.json')

// ↓ 短縮可能
kintone.api(kintone.api.url('/k/v1/records'))


メソッド

method の部分。何をしたいかを記述します。

kintone では以下の4種類のメソッドを用意しています。

GET(取得)

POST(登録)
PUT(更新)
DELETE(削除)


パラメータ

params の部分。具体的に扱いたいデータを記述します。

例えば...

レコード1件を操作しようとした時、「どのアプリの、どのレコードか」が分からないと何もできません。

レコード複数件を操作しようとした時、「どのアプリで、どんな条件で」が分からないと何もできません。

レコード1件の場合は、以下のように扱いたいデータを指定します。

var params = {

app: 10,
record: 1
};

※ パラメータに指定できるものは、URL や メソッドによって変わるので、注意が必要です。


コールバックとエラーバック

callback と opt_errback の部分。「成功した時にどうするか」と「失敗した時にどうするか」を記述します。

例えば、以下のような感じです。

var params = {

app: 10,
record: 1
};

// 成功した時
function callback(resp) {
console.log(resp);
}

// 失敗した時
function opt_errback(error) {
console.log(error)
}

kintone.api(kintone.api.url('/k/v1/record'), 'GET', params, callback, opt_errback)


注意点

今回は、kintone アプリ内で完結するデータ操作なので、ヘッダー(認証情報)の記述は必要ありません。

外部サービスから kintone API を実行する場合は、「アクセスして情報をもらってもいいですか?」と

お伺いを立てないといけないので、そのために上記以外に認証情報の設定が必要になります。

(💡kintone REST APIの共通仕様


🔖 JavaScript カスタマイズ

ここからは、やりたいシナリオに沿って JavaScript で記述していきます。

devnet も確認しながら進めます。


『ログインユーザーが申請中のレコード件数を表示する』 の巻

まずは、「レコード一覧画面の表示」イベント内で、「ログインユーザーが申請中のレコード件数を表示する」カスタマイズ。

このカスタマイズは、細かくすると以下の3ステップに分けることができます。


  • レコード一覧画面が表示されたら、ログインユーザーが申請中のレコードを取得

  • 取得が成功したら、一覧画面のメニューの下側の空白部分の要素を取得して、件数を表示する

  • 取得が失敗したら、エラーメッセージを表示する

それでは順番に書いていきましょう。


✏️ 条件に合うレコードの取得


  • レコード一覧画面の表示時イベント「'app.record.index.show'」を指定して、getRecords 関数を渡します。

(function() {

'use strict';

function getRecords(event) {

}

kintone.events.on('app.record.index.show', getRecords);
})();


  • getRecords 関数内に kintone REST API の GETメソッドを記述します。

    ※ 同時にコールバックとエラーバックの関数も、宣言しておきましょう

// (function() {

// 'use strict';

function getRecords(event) {
var params = {
'app': event.appId,
'query': '申請者 in (LOGINUSER()) and ステータス = "申請中"'
};

function showCount(resp) {

}

function handleError(error) {

}

kintone.api(kintone.api.url('/k/v1/records'), 'GET', params, showCount, handleError);
}

// kintone.events.on('app.record.index.show', getRecords);
// })();


📝Check devnet!

今回は、自分が申請中のレコードを全て取得したいということで、

レコードの一括取得(クエリで条件を指定)」を実行します。

pathUrl

赤枠の URL を短縮したものを入力します。

getRecords.png

method

GET(取得)メソッドを指定します。

params

オブジェクト内で、app(アプリID) と query(取得するレコードの条件)を指定します。

params.png

app:レコード一覧画面の表示後の event オブジェクト appId プロパティを指定。

app: event.appId

query: クエリ記法を元に、「申請者フィールドがログインユーザー かつ ステータスが申請中」を記述。

query:  '申請者 in (LOGINUSER()) and ステータス = "申請中"'

callbackopt_errback

成功した時の操作を showCount 関数、失敗した時の操作を handleError 関数と定義します。

(詳細は後ほど)



✏️ レコード取得が成功した時


  • 取得成功時の操作を showCount 関数内に記述します。


    • countSpace 要素を作成

    • id, innerText, style.marginLeftプロパティを指定

    • レコード一覧のメニューの下側の空白部分の要素を取得して、appendChild メソッドを使って、countSpace 要素を追加



// (function() {

// 'use strict';

// function getRecords(event) {
// var params = {
// 'app': event.appId,
// 'query': '申請者 in (LOGINUSER()) and ステータス = "申請中"'
// };

function showCount(resp) {
var countSpace = document.createElement('countSpace');
countSpace.id = 'space';
countSpace.innerText = 'あなたの申請中のレコードは ' + resp.records.length + ' 件です';
countSpace.style.marginLeft = '20px';
kintone.app.getHeaderSpaceElement().appendChild(countSpace);
}

// function handleError(error) {

// }

kintone.api(kintone.api.url('/k/v1/records'), 'GET', params, showCount, handleError);
// }

// kintone.events.on('app.record.index.show', getRecords);
// })();


📝Check devnet!

新規に作成した countSpace 要素のテキストに、取得したレコード数を表示します。

kintone api()から受け取った resp オブジェクト内の records.length(レコード件数)を入れます。

countSpace.innerText = 'あなたの申請中のレコードは ' + resp.records.length + ' 件です';

レコード一覧のメニューの下側の空白部分の要素の取得をします。

kintone.app.getHeaderSpaceElement();

取得した要素に、countSpace 要素を追加します。

ここでは、以下の appendChild メソッドを使います。

// A 要素に B 要素を追加

A.appendChild(B);

kintone.app.getHeaderSpaceElement().appendChild(countSpace);



✏️ レコード取得が失敗した時


  • 取得失敗時の操作を handleError 関数内に記述します。


    • エラー内容をアラート表示



// (function() {

// 'use strict';

// function getRecords(event) {
// var params = {
// 'app': event.appId,
// 'query': '申請者 in (LOGINUSER()) and ステータス = "申請中"'
// };

// function showCount(resp) {
// var countSpace = document.createElement('countSpace');
// countSpace.id = 'space';
// countSpace.innerText = 'あなたの申請中のレコードは ' + resp.records.length + ' 件です';
// countSpace.style.marginLeft = '20px';
// kintone.app.getHeaderSpaceElement().appendChild(countSpace);
// }

function handleError(error) {
window.alert(error.message);
}

kintone.api(kintone.api.url('/k/v1/records'), 'GET', params, showCount, handleError);
// }

// kintone.events.on('app.record.index.show', getRecords);
// })();


📝Check!

error オブジェクト内の message を、エラー内容としてアラート表示します。

window.alert(error.message);



✏️ JavaScript ファイルの kintone への適用

ここまで書けたら、「arrange.js」など任意のファイル名で保存して、

kintone の「JavaScript / CSSでカスタマイズ」設定ページにアップロードして保存します。

※ メモ帳をお使いの方は、「UTF-8(BOMなし)」を指定して保存してください。

(💡JavaScriptやCSSでアプリをカスタマイズする

customizationScreen.png

レコード一覧画面を表示した時に、ログインユーザー(自分)が申請中のレコード件数が正しく表示されたら成功です。

IndexScreen.png


『自動でプロセスを次に進める』 の巻

次に、「レコード追加画面で保存成功後」イベント内で、「自動でプロセスを次に進める」カスタマイズ。

これはレコード保存はしたけれど、プロセス管理の「申請」ボタン押し忘れるというケースを防止するための小技です。

こちらも以下の3ステップに分けて考えます。


  • レコード追加画面の保存成功後に、プロセスを次(申請中)に進める

  • 更新が成功したら、実行完了のアラート表示をする

  • 更新が失敗したら、エラーメッセージを表示する


✏️ 保存後にプロセスを次に進めて更新

ここまで書いてきたプログラムの下に書き足していきます。


  • レコード追加画面の保存成功後イベント「'app.record.create.submit.success'」を指定して、putRecord 関数を渡します。

// (function() {

// 'use strict';
// ・・・
// kintone.api(kintone.api.url('/k/v1/records'), 'GET', params, showCount, handleError);
// }

function putRecord(event) {

}

kintone.events.on('app.record.create.submit.success', putRecord);
// })();


  • putRecord 関数内に kintone REST API の PUT メソッドを記述します。

// (function() {

// 'use strict';
// ・・・

function putRecord(event) {
var params = {
app: event.appId,
id: event.recordId,
action: '申請',
assignee: event.record.上長.value[0].code
};

function handleSuccess() {

}

function handleError(error) {

}

kintone.api(kintone.api.url('/k/v1/record/status'), 'PUT', params, handleSuccess, handleError);
}

// kintone.events.on('app.record.create.submit.success', putRecord);
// })();


📝Check devnet!

今回は、プロセスを次に進めたいということで、

1つのレコードのステータスの更新する」を実行します。

pathUrl

赤枠の URL を短縮したものを入れます。

putRecord.png

method

PUT(更新)メソッドを指定します。

params

オブジェクト内で、app(アプリID) と id(レコードID) と action(実行するアクションの名前) と assignee(ユーザー名)を指定します。

params_putRecord.png

app: レコード追加画面の保存成功後の event オブジェクト appId プロパティを指定。

app: event.appId

id: 上記同様に、event オブジェクト recordId プロパティを指定。

id: event.recordId

action: 実行するアクション名を指定。今回は「申請」。

action: '申請'

assignee: 申請の承認者(ユーザーのログイン名)を指定。

assignee: event.record.上長.value[0].code

callbackopt_errback

成功した時の操作を handleSuccess 関数、失敗した時の操作を handleError 関数と定義します。

(詳細は後ほど)



✏️ レコード更新が成功した時


  • 更新成功時の操作を handleSuccess 関数内に記述します。今回は特に何もしないので、空のままにしておきます。

// (function() {

// 'use strict';
// ・・・
// function putRecord(event) {
// var params = {
// app: event.appId,
// id: event.recordId,
// action: '申請',
// assignee: event.record.上長.value[0].code
// };

function handleSuccess() {

}

// function handleError(error) {

// }

kintone.api(kintone.api.url('/k/v1/record/status'), 'PUT', params, handleSuccess, handleError);
// }

// kintone.events.on('app.record.create.submit.success', putRecord);
// })();


✏️ レコード更新が失敗した時


  • 更新失敗時の操作を handleError 関数内に記述します。


    • エラー内容をアラート表示



// (function() {

// 'use strict';
// ・・・
// function putRecord(event) {
// var params = {
// app: event.appId,
// id: event.recordId,
// action: '申請',
// assignee: event.record.上長.value[0].code
// };

// function handleSuccess() {

// }

function handleError(error) {
window.alert('エラーが発生しました。手動で申請ボタンをクリックしてください。\nエラー内容:' + error.message);
}

kintone.api(kintone.api.url('/k/v1/record/status'), 'PUT', params, handleSuccess, handleError);
// }

// kintone.events.on('app.record.create.submit.success', putRecord);
// })();


✏️ JavaScript ファイルの kintone への適用

arrange.js ファイルを上書き保存して、先程と同様に設定画面よりアップロードして保存します。

(💡JavaScriptやCSSでアプリをカスタマイズする

レコード追加画面で保存ボタンを押した後に、ステータスが "申請中" に進んでいたら成功です。

※ ブラウザの挙動によって、画面の更新が必要になる場合もあります。

CreateSubmitScreen.gif


🔖 プログラム全文

上記の 1. と 2. をまとめて書いた完成形のプログラムはこちらです。


arrange.js

(function() {

'use strict';

// 一覧画面の表示時にログインユーザーの申請中のレコード件数を表示する
function getRecords(event) {
// パラメータ定義
var params = {
app: event.appId,
query: '申請者 in (LOGINUSER()) and ステータス = "申請中"'
};

// 成功時の関数
function showCount(resp) {
var countSpace = document.createElement('countSpace');
countSpace.id = 'space';
countSpace.innerText = 'あなたの申請中のレコードは ' + resp.records.length + ' 件です';
countSpace.style.marginLeft = '20px';
kintone.app.getHeaderSpaceElement().appendChild(countSpace);
}

// 失敗時の関数
function handleError(error) {
window.alert(error.message);
}

// GETメソッドの実行
kintone.api(kintone.api.url('/k/v1/records'), 'GET', params, showCount, handleError);
}

// 一覧画面の表示イベントで getRecords 関数を実行
kintone.events.on('app.record.index.show', getRecords);

// レコード追加画面の保存成功後にプロセスを次に回す
function putRecord(event) {
// パラメータ定義
var params = {
app: event.appId,
id: event.recordId,
action: '申請',
assignee: event.record.上長.value[0].code
};

// 成功時の関数
function handleSuccess() {

}

// 失敗時の関数
function handleError(error) {
window.alert('エラーが発生しました。手動で申請ボタンをクリックしてください。\nエラー内容:' + error.message);
}

// PUTメソッドの実行
kintone.api(kintone.api.url('/k/v1/record/status'), 'PUT', params, handleSuccess, handleError);
}

// レコード追加画面の保存成功後イベントで putRecord 関数を実行
kintone.events.on('app.record.create.submit.success', putRecord);
})();



🔖 備考

『自動でプロセスを次に進める』 の巻で、以下のように書きました。


※ ブラウザの挙動によって、画面の更新をする必要がある場合もあります。


裏側ではレコードの更新が成功しているのですが、ユーザー側で画面の更新作業が発生するのは親切ではありません。

これを解決するには、JavaScript の Promise という順番処理の書き方を学ぶ必要があります。

詳細については、ここでは割愛しますが、気になる方は以下の記事をご覧ください。

💡kintoneにおけるPromiseの書き方の基本

💡レコード保存後に自動でステータス更新!


🔖 おわりに

今回は、以下のメソッドやイベントを使いました。

kintone には他にも利用できるイベント、それぞれで可能な操作、

データ操作をリクエストするためのメソッドがあります。

"やりたいこと" を処理レベルに分解すると、どんなイベントやメソッドを使って、

どの順番でコーディングしていけばいいかも見えてきます。


ぜひ他の KAIZEN にもチャンレンジしてみてください📣