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

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

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


#フィールドを用意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511519/4aa9006a-74e8-dfbf-0a30-3cea05d3f6bd.png)


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

とします

#ソースコード
```js: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](https://developer.cybozu.io/hc/ja/articles/360023047852-kintone%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8BPromise%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96%B9%E3%81%AE%E5%9F%BA%E6%9C%AC)を使用した**同期的な処理**が必要となる。
(Google Directions APIの結果を待って処理をするということ)

###両地点の宣言とエラー設定
[三項演算子](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Conditional_Operator)を使用

```js:
const origin = record['A地点'].value ? record['A地点'].value : 0; //A地点
const destination = record['B地点'].value ? record['B地点'].value : 0; //B地点
```
レコードに値があればその値を宣言し、なければ0を代入する。

```js:
if(origin === 0 | destination === 0){//何も入力されていなければリターン
    event.error = 'エラー';
    return;
}
```
どちらかで0が代入されていた場合、エラー処理を入れてイベントを返す。
例えばエラー詳細としてフィールド下部にエラー文字を表示させる場合は、

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

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

###リクエストヘッダ
```js:
'https://maps.googleapis.com/maps/api/directions/json?' + param + '&key=' + api_key
```
[公式ドキュメント](https://developers.google.com/maps/documentation/directions/intro?hl=ja)を参照。


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


```js:
const param = 'origin=' + origin + '&destination=' + destination + '&avoid=highways';
```

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

###外部APIの実行
```js:
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
の二つのイベントで下記のコードを記述すると入力時にユーザーは触れないフィールドになります。

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

##最終的なコード
コピペしていじれば使えるよってやつです。
<details><summary>サンプル</summary><div>

```js: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;
      
    });
    
})();



````

</div></details>

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

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