10
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-03-12

🔖 はじめに

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 にもチャンレンジしてみてください📣

10
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?