freee APIとGASを使って商品が購入されたら自動で仕訳登録する (中編)

## はじめに

[bocci bocci](https://boccibocci.com)を運営している@shoji-kaiです。
[前編](https://qiita.com/shoji-kai/items/14379266c9f39704dee5)ではfreee APIのセットアップと基本的な使い方を確認しました。
今回は、GAS(Google Apps Scripts)を使って商品購入メールが届いていたらfreee APIを叩くところまでをやってみたいと思います。

## GAS(Google Apps Script)とは

GASは、GmailやGoogle SpreadsheetsなどGoogle Workspaceの一連のアプリケーションを操作できるスクリプトの総称になります。
GASは下記URLより誰でも使うことができます。

https://www.google.com/script/start/

## Google Appsの承認

GASからGoogle Apps(Gmail, Google Spreadsheetsなど)にアクセスしようとすると承認が求められます。
下記のステップで承認を許可してください。

### 1. 承認ダイアログが出てきたら「権限を確認」を押す
![スクリーンショット 2021-11-16 9.14.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177074/646c0ca2-b9dd-c366-6700-2fda484f9b96.png)

### 2. アカウントを選択する
![スクリーンショット 2021-11-16 9.15.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177074/a2c6954f-47ad-6901-8aa4-6150f81d17a9.png)

### 3. 左下にある「詳細」を開く
![スクリーンショット 2021-11-16 9.15.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177074/d955f08a-8a37-5aa0-76d8-db2c7bd56af3.png)

### 4. 「無題のプロジェクト (安全ではないページ) に移動」をクリックする
![スクリーンショット 2021-11-16 9.15.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177074/8c880572-4e29-2239-c0be-3a324866ad4c.png)

### 5. アクセスリクエストを許可する
![スクリーンショット 2021-11-16 9.15.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177074/9eb8eda7-d8aa-85a5-820b-b5b0f06cd58c.png)

## GASからfreee APIを叩いてみる

それでは、早速GASからfreee APIを叩いてみたいと思います。
GASでプロジェクトを新規作成し、以下のコードを貼り付けて実行します。

```javascript:コード.gs
function postDeal() {
  const accessToken = '<ACCESS_TOKEN>'; // 自分のアクセストークンに置き換えてください
  const companyId = <COMPANY_ID>;       // 自分の事業所IDに置き換えてください
  const data = {
    "issue_date": "2020-11-01",
    "type": "expense",
    "company_id": companyId,
    "details": [
      {
        "tax_code": 136,
        "account_item_id": 538987945,
        "amount": 1100,
        "description": "ノートとボールペンをコンビニで購入"
      }
    ]
  };

  const url = 'https://api.freee.co.jp/api/1/deals';
  const options = {
    'method': 'post',
    'contentType': 'application/json',
    'payload': JSON.stringify(data),
    'headers': {
      'Authorization': 'Bearer ' + accessToken
    }
  };
  const res = UrlFetchApp.fetch(url, options);
  Logger.log(res.getResponseCode());
}
```

エラーが発生せずに正常終了していれば成功です。
![スクリーンショット 2021-11-14 14.46.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177074/a6ef6bd2-cc83-462d-cf3f-19c0b8d22755.png)

## GASからGmailに商品購入メールが届いているか確認する

まずはダミーの商品購入メールを自分のGmail宛てに送信します。

```
cat <<. | sendmail -t
Subject: 商品が購入されました。
To: <メールアドレス>

テスト
.
```

GASに以下のコードを追記します。

```javascript:コード.gs
function checkOrderMail() {
  const query = 'subject:(商品が購入されました) in:anywhere';
  const threads = GmailApp.search(query).reverse();
  for (let i = 0; i < threads.length; i++) {
    const messages = threads[i].getMessages();
    for (let j = 0; j < messages.length; j++) {
      const date = messages[j].getDate();
      const orderedAt = date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate();
      Logger.log('ordered at ' + orderedAt);
    }
  }
}
```

実行する関数を checkOrderMail に変更して実行します。
実行ログに'ordered at'のログが記録されていれば成功です。
![スクリーンショット 2021-11-14 14.20.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177074/fd8e3e51-dba4-4067-6445-0a43829581fd.png)

## メールが届いていたら仕訳登録する

続いて、メールが届いていたらpostDeal()を呼び出して仕訳登録する処理を追加します。
ここではメール受信〜仕訳登録の一連のながれをテストしたいだけなので、先ほどのサンプル取引データをそのまま流用します。
ただし、取引発生時刻はメール受信時刻とすることにします。

コードは以下のようになります。

```javascript:コード.gs
function postDeal(orderedAt) {          // <= 引数にorderedAtを受け取る
  const accessToken = '<ACCESS_TOKEN>';
  const companyId = <COMPANY_ID>;
  const data = {
    "issue_date": orderedAt,            // <= issue_dateのvalueをorderedAtに変更
  :
  (snip)
  :
}

function checkOrderMail() {
  const query = 'subject:(商品が購入されました) in:anywhere';
  const threads = GmailApp.search(query).reverse();
  for (let i = 0; i < threads.length; i++) {
    const messages = threads[i].getMessages();
    for (let j = 0; j < messages.length; j++) {
      const date = messages[j].getDate();
      const orderedAt = date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate();
      Logger.log('ordered at ' + orderedAt);

      postDeal(orderedAt);  // <= postDeal()の呼び出しを追加
    }
  }
}
```

以下のようにエラーがなく正常終了していたら成功です。
![スクリーンショット 2021-11-14 14.53.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177074/ba96b339-3bd0-0eed-8808-b76b061b78ac.png)

いちおう、freeeの画面からも確認してみます。
メール受信時刻を取引日とした仕訳が登録されていることが確認できます。
![スクリーンショット 2021-11-14 14.56.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177074/6e9b11ad-3def-1b5a-be60-08e95d17ace8.png)

## トリガーを設定する

最後にトリガーを設定して、Gmailを定期的にチェックするようにします。
トリガーは、左カラムにある時計のアイコンになります。
![スクリーンショット 2021-11-14 15.00.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177074/16ae3601-0c1f-58b0-f09d-5ed8d03589cc.png)

トリガーをクリックし、新しいトリガーを作成すると以下のようなダイアログが出てきます。
今回はテストのために分単位でチェックしますが、本番では一日単位で十分でしょう。
以下のように項目を選択してトリガーを保存します。
![スクリーンショット 2021-11-14 15.03.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177074/7340a57c-024e-d628-2583-c2fef1099942.png)

1分ほど待ってから、再度freeeを確認してみます。
取引データが追加されていることが分かります。
![スクリーンショット 2021-11-14 15.06.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177074/35b3e75c-9fcb-9ee7-2acb-f590aaee03a7.png)

トリガーの確認ができたら、忘れずにトリガーを削除しておきます。
GASは無料で使えますが、一日あたりの実行回数に制限があります。
ref. https://developers.google.com/apps-script/guides/services/quotas
![スクリーンショット 2021-11-14 15.07.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177074/2940e2c1-d75f-43e0-62ea-fd79275545ec.png)

## おわりに
以上でGASから購入メール確認〜仕訳登録までを定期的に実行するやり方を確認できました。
ですが、本番に実装するにはまだクリアしなければいけない項目があります。

- アクセストークンの更新 (freeeのアクセストークン期限は24時間なのでリフレッシュする必要があります)
- 検索するメールの範囲を指定する (一日単位でトリガーを設定した場合、一日以内のメールのみを検索する)
- 重複取引の除外 (同じデータを取り込まないようにする)
- 購入メール本文から注文番号、商品名、商品価格を抽出する

などです。
[次回](https://qiita.com/shoji-kai/items/8fa5d163471acb8ebac0)は、このあたりの項目も実装した完成版を構築していきたいと思います。