HubSpotで見積書を作ったら、freee上で見積書/請求書を作成する

# はじめに
[HubSpot](https://www.hubspot.jp/)はマーケティング、セールス、カスタマーサービスを繋ぐ総合的なプラットフォーム。

[クラウド会計ソフト freee](https://www.freee.co.jp/)は法人向け会計ソフトで、帳簿や決算書作成・請求業務などに対応しています。

HubSpotはフロントオフィス、freeeはバックオフィスに相当します。
フロントオフィスとバックオフィスで人員は異なる場合が多いと思いますが、この間を繋ぐ部分のデータがシームレスに流れることが重要になります。
HubSpot上で契約は成立したけど、そのあとfreee上で見積/請求処理をし忘れていた...なんてケースはなくしたいと思います。
そのためにこの部分のデータ連携を極力自動化することが大事になります。

というわけで、今回はHubSpot上で契約が成立した取引に対して、freee側にて見積書・請求書を自動的で作成する方法について説明したいと思います。

# HubSpot と freeeの連携

実はこの辺の課題を解決する仕組みとして[freee for HubSpot](https://support.freee.co.jp/hc/ja/articles/900000747946-freee-for-HubSpot-%E3%81%AE%E6%A6%82%E8%A6%81)というサービスが存在します。(ちなみに私はfreee社/HubSpot社とは無関係な人なので、回し者ではありませんｗ）

こちらを利用するとHubSpotの取引からfreeeの請求書を作ったり、取引先を連携できたりするようです。

同じ内容を説明してもそれなら[freee for HubSpot](https://support.freee.co.jp/hc/ja/articles/900000747946-freee-for-HubSpot-%E3%81%AE%E6%A6%82%E8%A6%81)を使えばええやんってなるので、少し違うシチュエーションを紹介します。

# 今回説明する連携
1. HubSpot上で見積書を作成したら、freee見積書を作成する
1. 作成されたfreee見積書を元にfreee請求書を作成する

# 1. HubSpot上で見積書を作成したら、freee見積書を作成する

## 「HubSpotで見積書を作成したら」などの条件の検知
HubSpotの[ワークフロー登録トリガ](https://knowledge.hubspot.com/jp/workflows/set-your-workflow-enrollment-triggers)を利用することで可能です。
Professional/Enterpriseいずれかの利用が必要になります。
今回は説明を割愛しますが、HubSpotのいろいろな操作をトリガにし、処理の呼び出しを行うことが出来る機能になります。

## リクエスト内容からfreee見積書を作成するためのパラメータを取得
見積書作成時のトリガを設定した場合は、リクエスト内容のobjectidにそのHubSpotの見積りID(quoteid)の値が入っています。
まずこちらを元に、HubSpot APIにて見積もり情報を取得します。

```
https://api.hubapi.com/crm/v3/objects/quotes/{quoteid}?associations=deals,companies,line_items,contacts&hapikey={_apiKey}
```
associationsを指定することで、見積もりに紐づいているdeals(取引)、companies(会社)、line_items(製品)、contacts(担当者)のidを取得できます。
freeeの見積書を作成するためには、社名、製品名/価格/個数、担当者名などの情報が必要になりますが、これらのidを用いてそれぞれ必要な情報を取得します。

## freee見積書を作成する
[POST /api/1/quotations](https://developer.freee.co.jp/docs/accounting/reference#/Quotations/create_quotation) を利用することで見積書を作成可能です。

### パラメータの指定に関して
例えば品目の指定(item_id)はID指定になります。
HubSpot上の製品のIDとは当然値が異なるため、どのように渡すか考える必要があります。

例えば「リクエスト内容から取得したHubSpot製品名と同じ名前のものがfreee上の品目に登録されているか確認し、登録されていなければ登録する」というやり方があります。
この際は、[GET /api/1/items](https://developer.freee.co.jp/docs/accounting/reference#/Items/get_items)で品目を取得し、同一の名称の品目が存在するか確認し、なければ、[POST /api/1/items](https://developer.freee.co.jp/docs/accounting/reference#/Items/create_item)で登録する、といった流れになるかと思います。

freeeの取引先名なども同様に考える必要があります。

# 2. 作成されたfreee見積書を元にfreee請求書を作成する

[POST /api/1/invoice](https://developer.freee.co.jp/docs/accounting/reference#/Invoices/create_invoice)を用いて、請求書を作成することが出来ます。
請求書作成に必要なパラメータの大半は見積書と同じになるため、必要な情報を見積書から取得します。

[GET /api/1/quotations/{id}](https://developer.freee.co.jp/docs/accounting/reference#/Quotations/get_quotation)を用いて先ほど作成した見積書をすることが出来るので、こちらから情報を取得し、そちらを元に請求書作成を行います。

# HubSpotワークフロートリガーでシームレスに処理を流すには

freeeの請求書作成時に、freeeの見積書作成で作られたIDが必要になりますが、ワークフロートリガを用いた場合に渡す方法としては例えば以下の方法があります。

- HubSpotの取引にfreee見積書のIDを格納するカスタムプロパティを用意しておく
- freee見積書作成後、見積書のIDを上記のカスタムプロパティに格納する
- freee請求書作成時に、カスタムプロパティを読み込み、見積書IDを取得し請求書作成処理を行う

このようにすることで、請求書作成時に見積書情報を読み取ることが出来ます。（あくまで一例です）
また、HubSpotの取引上にfreeeの見積書ID情報が含まれるので、取引を見ただけでどのfreee見積書と紐づくかも確認することが出来ます。

# こんな感じで処理した結果をslack通知しても面白そう

この仕組みを使えば、HubSpotの見積書作成を行った際に、HubSpotの取引、見積書、freee見積書、freee請求書までのデータが
シームレスに連携されます。

![notif.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153845/86ccbece-260e-1019-b461-c191c323869b.png)

こんな風にslack通知することも出来ますね。
バックオフィス担当の方は上記の通知がきたら、下部のリンクをクリックしてfreeeの請求書を送付するという流れを実現できると思います。

請求書の送付忘れを防止するための定期通知の仕組みは[別記事](https://qiita.com/ShojiTaira/items/519114e234267d64e80a)で紹介しているので、そちらも組み合わせると良いかなーと思います。

# 最後に

HubSpotとfreeeのAPIを利用することで、このような業務の効率化を行うことが出来ます。
実用に関して少し考慮が必要かなと思う点としては、freeeのAPIはOAuth認証でのコールになる点です。
機械的に毎回同じユーザで処理を行いたい場合においては、シンプルな対応は、以下かなと思います。

- アクセストークンをあらかじめ発行しておき、アクセストークン/アクセストークン作成日時/リフレッシュトークンをDB等に保持しておく
- freeeAPIを実行する前のアクセストークン取得時に、24時間以上経過していたら、リフレッシュトークンを用いてアクセストークンを再発行するような仕掛けを入れておく(freeeのアクセストークンの有効期限は24時間)

Azure上で開発する場合は、KeyVaultを使うと良いかなーと思います。
https://azure.microsoft.com/ja-jp/services/key-vault/

また実用にあたってはセキュリティ面を考慮した実装もきちんと入れ込みましょう。
例えば、[HubSpotのwebhookリクエストのバリデーション](https://developers.hubspot.com/docs/api/webhooks/validating-requests)なども行えたりしますのでこういったものなどもしっかり取り込みましょう。