KintoneとOutlookカレンダーを連携して工数を集計する #2

## この記事の続き
- [KintoneとOutlookカレンダーを連携して工数を集計する](https://qiita.com/iNaoki04/items/844c66db6538082606f0)

Outlookカレンダーと連携してキントーンにスケジュールを一覧化しています。
公式にサンプルがあるので改造して実装しています。

## サンプルのままではまだ微妙なので改修する
### graphは1度に10件しか取得できない問題
graphは一度のリクエストで10件分しか返さず、超過した分を取得するにはページングして再度リクエストする必要がある。
ページング用のリンクは`@odata.nextLink`に格納されているので、JSONに格納されているかを判断する。

```kintone-connect-outlook-schedule.js
// outlook予定表取得
getEvent: function(eventGetUrl) {
~
  // Outlookの予定表取得
  kintone.proxy(eventGetUrl, 'GET', header, {}).then(function(res) {
  ~
    // 10件以上ある場合、次を抽出
    if (JSON.parse(res[0])["@odata.nextLink"]) {
      outlookAPI.getEvent(JSON.parse(res[0])["@odata.nextLink"]);
    }
```

リロードするタイミングを変更する。

```kintone-connect-outlook-schedule.js
// 取得した予定をkintoneへ登録
putScheduleToKintoneApp: function(index, data, accessToken) {
  var self = this;
  // キントーンに登録済みのデータかをチェックする
  return this.getScheduleIDIndexIsNotRetrived(index, data).then(function(indexSchedule) {
    ~
    });
  });
  //.then(function(resp) {         ← 10件処理するとリロードしてしまうので、
  //    window.location.reload();　　ここでのreload()を行わないようにする。
  //    KC.ui.loading.hide();
  //  });
},
```

### スケジュールの内容がHTMLな問題
HTMLのタグがそのままテキストとして保存されてしまうのでテキスト形式で取得するようにします。
リクエストヘッダーにコンテンツ形式を追加して指定します。

```kintone-connect-outlook-schedule.js
// タイムゾーンを日本設定とテキスト形式で取得に設定
header = {
  'Authorization': 'Bearer ' + accessToken,
  'Content-Type': 'application/json',
  'Prefer': "outlook.timezone=\"Tokyo Standard Time\", outlook.body-content-type=\"text\""
};
```

### 指定した時間外のデータを取得してしまう問題
リクエストの指定の仕方が悪いのかgraphの仕様なのかバグなのかわからないですが、開始日（StartDate）～終了日（EndDate）から外れたデータも取得してしまうので除外します。

```kintone-connect-outlook-schedule.js
// Outlookの予定表取得
kintone.proxy(eventGetUrl, 'GET', header, {}).then(function(res) {
~
  // 取得範囲外のデータを削除する
  var isDate = new Date(kintoneScheduleService.data.ui.inputFromDate.getValue());
  var ieDate = new Date(kintoneScheduleService.data.ui.inputToDate.getValue());
  isDate.setHours(0,0,0);
  ieDate.setDate(ieDate.getDate()+1);
  ieDate.setHours(0,0,0);
  for (var i=0; i<data.length; i++) {
    var dsDate = new Date(data[i].start.dateTime);
    var deDate = new Date(data[i].end.dateTime);
    if (!(isDate.getTime() <= dsDate.getTime() && deDate.getTime() <= ieDate.getTime())) {
      delete data[i];
    }
  }
~
// 取得した予定をkintoneへ登録
putScheduleToKintoneApp: function(index, data, accessToken) {
  var self = this;
  // キントーンに登録済みのデータかをチェックする
  return this.getScheduleIDIndexIsNotRetrived(index, data).then(function(indexSchedule) {
    // ※除外されたデータは処理しないように条件を追加
    // 更新処理
    if (data[index] && indexSchedule === null) {
      return self.updateScheduleIntoKintone(data[index], accessToken).then(function(result) {
~
    // ※除外されたデータは処理しないように条件を追加
    // 登録処理
    if (data[indexSchedule]) {
        return self.addScheduleIntoKintone(data[indexSchedule], accessToken).then(function(result) {
~
// 除外データを処理しないようにする
getScheduleIDIndexIsNotRetrived: function(index, data) {
  var self = this;
  // データが削除されている場合は存在チェックでヒットしないようにする
  var dataindex = data[index] ? data[index].id.substr(data[index].id.length-64) : -1;
~
```

### 終日の予定を設定できない問題
キントーンからOutlookカレンダーへ新規登録と更新をする際に終日設定が動作しないので改修。
サンプルでは開始日と終了日が同じの場合に開始日の0時0分と終了日の24時0分を設定しているが、この指定ではリクエストのフォーマットエラーになるので、開始日の0時0分と開始日の翌日の0時0分に設定する。
また、timezoneもUTCなので日本に設定する。
サンプルの開始日と終了日で判定する方法の他に、終日チェックボックスの入力内容での判定も追加しておきましょう。

```kintone-connect-outlook-schedule.js
setDataForRegistration: function(kintoneData, isAllDay) {
~
  // 終日だった場合の処理
  if (isAllDay) {
    var sDate = new Date(kintoneData[START_DATE_FIELD_CODE].value);
    var eDate = sDate.setDate(sDate.getDate() + 1);
    startDate = kintoneScheduleService.convertDateForAllDay(
      kintoneData[START_DATE_FIELD_CODE].value) + 'T00:00:00.000Z';
    endDate = kintoneScheduleService.convertDateForAllDay(
      dateFormat.format(eDate)) + 'T00:00:00.000Z';
  } else {
    startDate = kintoneData[START_DATE_FIELD_CODE].value;
    endDate = kintoneData[END_DATE_FIELD_CODE].value;
  }

  sendParam.start = {
    'dateTime': startDate,
    'timeZone': 'Tokyo Standard Time'
  };

  sendParam.end = {
    'dateTime': endDate,
    'timeZone': 'Tokyo Standard Time'
  };
~
};
~
setDataForUpdate: function(kintoneData, isAllDay) {
~
// 更新も↑（登録）と同じ対応をする。
~
};
```

チェックボックスでの判定を追加する

```kintone-connect-outlook-schedule.js
checkDateTime: function(record) {
  return new kintone.Promise(function(resolve, reject){
~
    if ("終日" === record[ALLDAY_FIELD_CODE].value[0]) {
      resolve(false);
    }  
```

### 一覧画面からの編集はOutlook連携できていない問題
各処理に一覧のエディット（編集、削除）イベントを追加する。

```kintone-connect-outlook-schedule.js
// 編集処理
kintone.events.on(['app.record.edit.submit.success', 'app.record.index.edit.submit.success'], function(event) {
~
// 削除処理
kintone.events.on(['app.record.detail.delete.submit', 'app.record.index.delete.submit'], function(event) {
```