未送付のfreee請求書一覧を定期通知する


はじめに

バックオフィス業務として、請求書をお客様に送付するタイミングがあると思います。
freee上で請求書を作成したけど、送付し忘れてた!なんてことを予防するために、未送付の請求書一覧を定期的にslack通知できると便利ではないでしょうか。

というわけで本項では上記の仕組みについて説明したいと思います。
こちらC#を利用して実装しているので、一部C#も含めた説明になります。

未送付のfreee請求書一覧を取得する

freee APIのうち、GET /api/1/invoices を用いることで取得することが出来ます。
https://developer.freee.co.jp/docs/accounting/reference#/Invoices/get_invoices

invoice_status(請求書のステータス)に"unsubmitted"を指定することで、送付待ちの請求書一覧を取得することが可能です。

https://developer.freee.co.jp/release-note/2948
詳細は上記、2-5 請求書ステータスの変更(C10)参照ですが、2020/12のAPI仕様変更に伴い送付待ちの請求書一覧が取得可能になります。
API切り替えまでの間に新API仕様でコールする場合は上記を元にリクエストヘッダを指定する必要がありますのでご注意ください。

// freee-accounting-sdk-csharpを利用した場合の取得
int myCompanyId = 12345678;

string invoiceStatus = "unsubmitted";
string description = null;
string paymentStatus = null;

var invoiceApi = new InvoicesApi(config);

var invoices = await invoiceApi.GetInvoicesAsync(myCompanyId, null, null, null, null, null, null, null, description, invoiceStatus, paymentStatus, null);

freee-accounting-sdk-csharpを用いる場合は上記のような呼び出し方になります。
(2020/07/03時点では、先述した新API仕様に対応していないので、利用の際はSDKに手を加えましょう)

未送付の請求書一覧の中で、一定日数経過した請求書を取得する(絞り込む)

GET /api/1/invoicesのstart_issue_date/end_issue_dateを指定すれば取れそうですが、自分の指定の仕方がまずいのか意図したとおり取れなかったので、自前でチェックします。
start_issue_dateには請求日がyyyy-MM-ddのフォーマットで入っています。

こちらの日付と現在日付を比較することによって、経過日数を取得することが可能です。

// JSTの現在日付の取得
TimeZoneInfo jstZone = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");
DateTime jstDate = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, jstZone).Date;
// 時間差分の算出
DateTime issueJstDate = DateTime.ParseExact(invoice.IssueDate, "yyyy-MM-dd", null);
TimeSpan elapsedTime = jstDate - issueJstDate;

このあと、例えばelapsedTime.TotalDays >= 1のようにすれば1日以上経過した請求書であることが判定できます。

通知の仕組み

弊社ではslackを通常利用していることもあり、通知はslackに行うことにします。

Incoming Webhookを利用します。

通知先のテキストに、https://secure.freee.co.jp/docs_v2/invoice/{invoice.Id}を含めることによって、slackからすぐに請求書へ飛べるので便利かなーと思います。

定期的に実行するための仕組み

上記で用意した処理を定期的に呼ぶための仕掛けが必要になります。
ここは何でもよいですが、Azure Functionsのタイマ関数を利用しています。

[FunctionName("invoiceNotification")]
public async void Run([TimerTrigger("0 30 12 * * 1-5")] TimerInfo myTimer, ILogger log)
{
  (上記で説明した処理を呼び出す)
}

この例では、0 30 12 * * 1-5とトリガが設定されていますが、月-金12:30に処理が呼び出されます。
なので、午後に未送付の請求書を送ってしまおう!という感じの運用ですね。

こんな感じで毎日(月-金)通知されます

その他

特定の請求書に絞り込みたい場合は、請求書の概要(description)に値を入れておいて、請求書検索時はdescriptionを指定すると絞り込むことが可能です。
複数の業務の請求書を扱っている場合は、そちらを用いて請求書を分類することで、その請求書に関係するメンバーのみjoinしているslack chに通知するといったことも出来るので、そちらが望ましいでしょう。