kintoneに登録した予定情報をGaroonにPOSTしてみた

# はじめに

サイボウズにはkintoneの他にもGaroonというグループウェア製品があります。
※ これら以外にも製品はあります。

そして、このGaroonにはREST APIが搭載されているので、
kintoneと連携（俗にこれを **ガルキン連携** といいます）することもできます！！

ってことで、この記事ではシンプルに
**kintone → Garoon**
のスケジュール連携を実装してみました。

# コーディング前

「同じ会社の製品だし簡単に連携できるっしょ！」って思っていました。
なので、コーディングする前は「わざわざ記事化する必要ないだろう」とも思っていました。

しかし、世の中そんな甘くはないなーってことがコーディング中にあったので記事化しますｗ

# 引っかかったところ

では、さっそく何があったのか。 

* エンドポイントの構成が異なる
* ユーザー(アカウント)情報の構成が異なる
* 認証がいい感じにできない
* ~~日時のフォーマットが異なる~~ <-記事作ってる間になんかできるようになった(謎)
* ドキュメントの量が異なる

## エンドポイント問題

kintoneのendpointは ```https://{subdomain}.cybozu.com/k/v1/〇〇.json``` という形で、
kintone JavaScript APIを使えば ```kintone.api.url('/k/v1/〇〇');``` と書けます。

ここは調べずにおおちゃくした自分が悪いのですが、
「Garoonの場合は ```kintone.api.url('/g/api/v1/〇〇');``` でいけるやろ！」ってことで書いて実行したところ、、、

<br/><br/>

<font color="red">**{"error":{"errorCode":"GRN_REST_API_00101","message":"入力内容が正しくありません。","cause":"指定されたURIパスが見つかりません。"}}**</font>

<br/>

なんだって！？！？

<br/>

どうやらGaroonは、
```https://{subdomain}.cybozu.com/g/api/v1/〇〇``` で最後に「.json」は必要ないらしい。
kintone.api.url();は「.json」も補完する。~~余計なお世話や！~~

## ユーザー情報問題

ここは普通にハマったのですが、
kintoneのユーザー選択フィールドのデータは

```json

{
  "value" : [{
    "code": "<ログインID>",
    "name": "<ユーザー名>"
  }]
}
```

となっています。複数人いた場合は

```json
{
  "value" : [{
    "code": "aa",
    "name": "AA"
  },
  {
    "code": "bb",
    "name": "BB"
  },
  {
    "code": "cc",
    "name": "CC"
  }]
}
```

となります。

しかし、これをそのままGaroonに突っ込もうとするとエラーがでます。

<br/><br/>

<font color="red">**"{"error":{"errorCode":"GRN_REST_API_00201","message":"パラメーターの指定が正しくありません。","cause":"attendees.typeは必須パラメーターです。"}}"**</font>

<br/>

Oh...
Garoonの場合はユーザーと施設と2種類アカウント（のようなもの）があるので、TYPEが別途必要！！

```json
{
  "value" : [{
    "code": "aa",
    "name": "AA",
    "type": "USER"
  },
  {
    "code": "bb",
    "name": "BB",
    "type": "USER"
  },
  {
    "code": "cc",
    "name": "CC",
    "type": "USER"
  }]
}
```

ってことでkintoneのユーザー選択フィールドの値を取得した後に、ちょっとごにょごにょしないといけません

## 認証問題

今回、kintoneとGaroonは同じドメインでやっているため、セッション認証を使えればいいなと思ったのですが、**Garoon→kintone** ならCSRFトークンが使えますが、**kintone→Garoon** はCSRFトークンは使えませんでした。Oh...

→ GaroonにはCSRFトークンを取得するJavaScript APIがあるんですが、kintoneにはそのAPIはありませんでした。。

ってことで、今回はログパス認証になります。（Grにトークン認証はないため）

> 参考）kintone連携用トークンを取得する
> https://developer.cybozu.io/hc/ja/articles/115005294843

## 日時問題 (なんか解決済)

記事を書き始める前はフォーマットが違ったので、Garoon側に合うように修正しないときちんと入らなかったのですが、なんか記事書いている間にもう一度試したら、普通にいけましたｗ

でもフォーマットは異なるのでそこだけご紹介。

* kintoneの日時フィールドは `2019-01-01T12:50:00Z` のような形で **UTC** <br/>
  -> [リンク](https://developer.cybozu.io/hc/ja/articles/201941754#step6)
* Garoonのスケジュールの日時は `2019-01-01T21:50:00+09:00` のような形で **JST** <br/>
-> [リンク](https://developer.cybozu.io/hc/ja/articles/115005314266#step4)

<br/>

日時フォーマットはややこしい。。。

## ドキュメント問題 (問題ってレベルでもないけど)

devnetしかり、世の中一般しかり、Garoonのカスタマイズをしているところが圧倒的に少ない！！
-> kintoneのカスタマイズはググればたくさん出てくるのに。。。つД`)ｸﾞｽﾝ
だから、参考にできるものも少なくて、1から自分で調べないといけない。辛い。。

<br/>

まぁこんな背景もあって、この記事を書こうって決心したのもあります (´･∀･`)


# コード

上記のトラップに引っかかりながらも作成したコードがこちらです。

```javascript
(function() {
  'use strict';

  // kintoneのフィールドコード
  var common = {
    text: 'Text',
    user: 'User',
    startDate: 'Start',
    endDate: 'End',
    memo: 'Memo'
  };

  // Garoonの認証
  var auth = {
    'X-Cybozu-Authorization': 'ログ:パス Base64エンコード',
    'Content-Type': 'application/json'
  };

  // editは一旦放置。Garoon予定の更新も放置。
  kintone.events.on('app.record.create.submit', function(event) {

    // kintoneのユーザー選択フィールドにはtypeがないので追加する
    event.record[common.user].value = event.record[common.user].value.map(function(element) {
      return {
        code: element.code,
        name: element.name,
        type: 'USER'
      };
    });

    // GaroonのスケジュールREST API に必要なパラメータ (施設は今回省略)
    var params = {
      'eventType': 'REGULAR',
      'subject': event.record[common.text].value,
      'start': {
        'dateTime': event.record[common.startDate].value, // UTCの変換
        'timeZone': 'Asia/Tokyo'
      },
      'end': {
        'dateTime': event.record[common.endDate].value, // UTCの変換
        'timeZone': 'Asia/Tokyo'
      },
      'attendees': event.record[common.user].value,
      'notes': event.record[common.memo].value
    };

    return kintone.proxy('https://<subdomain>.cybozu.com/g/api/v1/schedule/events', 'POST', auth, JSON.stringify(params))
      .then(function(resp) {
        if (resp[1] !== 201) {
          return Promise.reject(resp);
        }
        window.alert('登録に成功しました！');
      }).catch(function(err) {
        console.log(err);
        window.alert('登録に失敗しました！');
        return false;
      });
  });
})();

```
# 動きのイメージ

* kintoneに登録すると、
<img width="500" src="https://qiita-image-store.s3.amazonaws.com/0/153051/3c411045-c5b6-31e8-7895-ad8938138084.png">

* Garoonにも入った！以上！
<img width="600" src="https://qiita-image-store.s3.amazonaws.com/0/153051/8b119b0e-80ca-b343-406f-519b4ce52544.png">

* 複数人も登録できます
<img width="600" src="https://qiita-image-store.s3.amazonaws.com/0/153051/69485f9f-c50f-8d81-44c3-3e92daa6d4b1.png">

# おわりに

やはり一度触ってみないとわからないものですね〜
kintoneだけでなく、Garoonも便利カスタマイズがたくさんできるので、どんどん記事化していこうと思います！

まぁそもそも論、このkintone→Garoonスケジュール連携ってニーズあるのかな・・・^^;


それでは！≧(+･` ཀ･´)≦