Help us understand the problem. What is going on with this article?

kintone Google Directions API を用いた2地点間距離の自動入力

目的

住所が保存してあるフィールドA,B地点間の距離を自動で算出して経理が交通費を処理する
という要望があり、自動化を図る。
ここでは、A,B地点間の距離を算出するまでを紹介します。
(ただGoogle先生にお願いするだけです)

Google Directions APIトークンの発行

発行できているものとします。
調べたら他にも記事が出てきますので、そちらを参考に。
使用環境が大型の場合、リクエスト数が有料枠に届ことが考えられますので、
そちらは自己責任でよろしくお願いします。

フィールドを用意

image.png

フィールド フィールドコード フィールドタイプ
距離 距離 数値
A地点 A地点 文字列一行
B地点 B地点 文字列一行

とします

ソースコード

route.js
(function() {
  'use strict';
  kintone.events.on('app.record.create.submit', function(event) {
      const record = event.record;

      const api_key = 'XXXXXXXX'; //API key

      const origin = record['A地点'].value ? record['A地点'].value : 0; //A地点
      const destination = record['B地点'].value ? record['B地点'].value : 0; //B地点

      if(origin === 0 | destination === 0){//何も入力されていなければリターン
         event.error = 'エラー';
         return;
      }

      const param = 'origin=' + origin + '&destination=' + destination + '&avoid=highways';

      return kintone.proxy('https://maps.googleapis.com/maps/api/directions/json?' + param + '&key=' + api_key , 'GET', {}, {}).then(function(resp) {

        const response = JSON.parse(resp[0]);
        const routes = response.routes[0];

        //距離、分数
        const distance = routes.legs[0].distance.value;
        const duration = routes.legs[0].duration.text;

        //小数第一の位で切り上げ
        const cul = Math.round((distance / 1000)*10)/10;

        record['距離'].value = String(cul); 

        return event;

      }, function(error) {
          // error
      });


    });
})();

解説

保存時イベント

イベントのタイミングはA,B地点両方入力された後と想定し、保存時イベントに設定。
外部のWebAPIを使用するのでPromiseを使用した同期的な処理が必要となる。
(Google Directions APIの結果を待って処理をするということ)

両地点の宣言とエラー設定

三項演算子を使用

const origin = record['A地点'].value ? record['A地点'].value : 0; //A地点
const destination = record['B地点'].value ? record['B地点'].value : 0; //B地点

レコードに値があればその値を宣言し、なければ0を代入する。

if(origin === 0 | destination === 0){//何も入力されていなければリターン
    event.error = 'エラー';
    return;
}

どちらかで0が代入されていた場合、エラー処理を入れてイベントを返す。
例えばエラー詳細としてフィールド下部にエラー文字を表示させる場合は、

record['A地点'].error = '必須';

これでフィールドにエラーを表示させることができます。

リクエストヘッダ

'https://maps.googleapis.com/maps/api/directions/json?' + param + '&key=' + api_key

公式ドキュメントを参照。

パラメータ

リクエストURLに動的に変化する値(ここではフィールドからの値)を代入したいので、
origin,destinationは事前に宣言して文字列としてparamに代入します。
注意:origin,destinationの文字列は空白を挟むとエラーを返します。

const param = 'origin=' + origin + '&destination=' + destination + '&avoid=highways';

最後の &avoid=highways は高速道路を使わないルート。

外部APIの実行

return kintone.proxy('https://maps.googleapis.com/maps/api/directions/json?' + param + '&key=' + api_key , 'GET', {}, {}).then(function(resp) {

        const response = JSON.parse(resp[0]);
        const routes = response.routes[0];

        //距離、分数
        const distance = routes.legs[0].distance.value;
        const duration = routes.legs[0].duration.text;

        //小数第一の位で切り上げ
        const cul = Math.round((distance / 1000)*10)/10;

        record['距離'].value = String(cul); 

        return event;

      }, function(error) {
          // error
      });

JSON形式で値が返ってくるため、パースをして、欲しいオブジェクトを参照。
distanceは距離、durationは予測分数(デフォルトで車)。

必要に応じてその他処理をイベントを返す前に記述すると交通費までを算出できるかと思います。

距離フィールドにグレーアウトをかけたい場合は、
app.record.create.show
app.record.edit.show
の二つのイベントで下記のコードを記述すると入力時にユーザーは触れないフィールドになります。

const record = event.record;
record['任意のフィールドコード'].disabled = true;
return event;

最終的なコード

コピペしていじれば使えるよってやつです。

サンプル
route.js
(function() {
  'use strict';
  kintone.events.on('app.record.create.submit', function(event) {
      let record = event.record;

      let api_key = 'XXXXXX'; //API key

      let origin = record['A地点'].value ? record['A地点'].value : 0; //A地点
      let destination = record['B地点'].value ? record['B地点'].value : 0; //B地点

      if(origin === 0 | destination === 0){//何も入力されていなければリターン
        return;  
      }

      let param = 'origin=' + origin + '&destination=' + destination + '&avoid=highways';

      return kintone.proxy('https://maps.googleapis.com/maps/api/directions/json?' + param + '&key=' + api_key , 'GET', {}, {}).then(function(resp) {

        const response = JSON.parse(resp[0]);
        let routes = response.routes[0];

        //距離、分数
        let distance = routes.legs[0].distance.value;
        let duration = routes.legs[0].duration.text;

        window.alert(duration);

        //小数第一の位で切り上げ
        let cul = Math.round((distance / 1000)*10)/10;

        record['距離'].value = String(cul); 

        return event;

      }, function(error) {
          // error
      });


    });

    const ev_input = [
      'app.record.create.show',
      'app.record.edit.show'
      ];

    kintone.events.on(ev_input, function(event) {

      const record = event.record;

      record['距離'].disabled = true;

      return event;

    });

})();



後述

Qiitaで初投稿はおろか、自分のコードを世に公開することが初めてで、下手な日本語で説明させていただきました。
kintone,jsを触り始めて一年経ち、いろいろな経験をさせていただいています。

活発に活動をしていきたいと思っていますのでコードの訂正、語句の訂正などご教授よろしくお願いします。
反応があれば、もっとこのAPIで遊んでみようかと思います。

zackey_
kintoneユーザー kintone hive 2020 福岡 登壇者 思いついたときに投稿してます。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした