kintoneのデータをクラウド請求書に連携する

にほんブログ村 IT技術ブログへ

はじめに

Cybozu kintoneで業務システム開発をしていると、請求書データを作りたいというお客様要望が良くあります。

割と一般的な業務システムをkintoneで作ると、顧客情報、売上情報、請求情報のアプリを作って、社内業務の顧客管理と売上管理をする。そして最終的に顧客にPDF形式の請求書を作って印刷・送付する。
という使い方が多いかと思います。

そういった業務フローの中で、請求書は直接顧客の目に触れるものであるため、デザインはちょっと凝りたいと思うのは自然な要望だと思います。
もちろんkintoneだけでPDF形式の請求書は作れるのですが、凝ったデザインとかをしたいのであれば「マネーフォワード クラウド請求書」にデータ連携して、そっちで請求書を作ってしまいましょう。
クラウド請求書ならデザインテンプレートでワンタッチでデザインが変えられるし、
項目名なども変えられる。
また、別途契約すれば作った請求書を郵送するサービスまであるので、印刷物の封入作業なんてのも無くせます。超便利。ちなみに「クラウド請求書」といいつつ「請求書」の他にも「見積書」「納品書」「領収書」等も作れるのでお得感有ります。

今回はkintoneのアプリで作成した請求データをクラウド請求書に連携して、PDF形式の請求書を作ろうという記事です。

kintoneの請求情報アプリ

以下のような請求情報アプリを作りました。

上記「請求情報」アプリの他、「顧客情報」、「契約情報」、「売上情報」のアプリもありますが、今回紹介は割愛します。
本アプリは、「顧客情報」、「契約情報」はルックアップで紐づけし、「売上品目」の所で「売上情報」アプリの該当レコードを「関連レコード」項目として参照しています。
小計、消費税、請求金額合計は関連レコードをカスタマイズで計算します。今回の記事ではあまり関係無いのでそこも割愛します。

kintone API と クラウド請求書APIを駆使する

データ連携するためにはクラウド請求書側でWrite権限のアクセストークンの発行をしておく必要があります。

カスタマイズでやる事は以下の通りです。以下は、レコード詳細画面に仕掛けます。

  1. 請求書データ連携ボタンを作成する
  2. 作成したボタンにクリックイベントハンドラ設定
    1. 売上情報アプリのレコード取得(kintone REST API)
      • 顧客コードと売上計上日の範囲指定で売上情報を絞る
      • 売上計上日、売上品目、売上単価、数量の項目を取得
    2. 請求情報アプリのレコード取得(kintone JavaScrip API)
      • 件名等の項目を取得
    3. クラウド請求書に請求書データ作成( kintone JavaScrip API でクラウド請求書 APIを実行)
      1. 上記で取得した情報を元に請求書データを作成し、クラウド請求書APIを実行

以下のような形になるかと思います。

/** MF請求書 アクセストークン(Write) */
var MF_WRITE_TOKEN = 'BEARER ' + 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

/** MF請求書 API URL */
var MF_API_URL = 'https://invoice.moneyforward.com/api/v2/billings.json';

kintone.events.on(["app.record.detail.show"], function (event) {
    // ヘッダーメニュースペースにボタン作成
    $(kintone.app.record.getHeaderMenuSpaceElement())
        .append("<button id='btn-create-invoice' class='gaia-ui-actionmenu-save'>請求書データ連携</button>");

    // 【請求書データ連携ボタン】クリックイベントハンドラ
    $('#btn-create-invoice').on('click', function () {
        // 売上レコード取得条件
        var body = {
            "app": xx,
            "query": "顧客レコード番号 = 1" +
                " and 売上計上日 >= \"2019-08-01T00:00:00Z" +
                "\" and 売上計上日 <= \"2019-08-31T23:59:59Z\"" +
                " order by 売上計上日 asc",
            "fields": ["売上計上日", "売上品目", "売上単価", "数量"]
        };
        // 売上レコード取得
        kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body)
            .then((resp) => {
                console.log(resp);
                // 請求レコード取得
                var rec = kintone.app.record.get();
                var postData = {
                    'billing': {
                        'department_id': 'HNg5HRj6dhCimemflwa8_g',
                        "title": rec.record['件名'].value,
                        "billing_date": "2019-09-08",
                        "due_date": "2019-10-30",
                        "billing_number": "B01",
                        "items": [
                            {
                                "name": resp.records[0]['売上品目'].value,
                                "unit_price": resp.records[0]['売上単価'].value,
                                "quantity": resp.records[0]['数量'].value
                            },
                            {
                                "name": resp.records[1]['売上品目'].value,
                                "unit_price": resp.records[1]['売上単価'].value,
                                "quantity": resp.records[1]['数量'].value
                            }
                        ]
                    }
                };
                // マネーフォワードの請求書データ作成
                return kintone.proxy(MF_API_URL, 'POST',
                    { 'Authorization': MF_WRITE_TOKEN, 'Content-Type': 'application/json' }, postData);

            }).then((resp) => {
                console.log(JSON.parse(resp[0]));
                console.log(resp[2]);
                if (resp[1] === 201) {
                    console.log('請求書データ作成完了');
                } else {
                    return Promise.reject('HTTP ステータスコード異常');
                }

            }).catch((error) => {
                console.log(error);
            });
    });
});

ポイントは以下。

  1. アクセストークンはWrite権限のものを指定
    • MF請求書APIを実行するために必要です。読込み権限のものを指定すると不正アクセスで弾かれます。BEARERというキーワードも忘れずに。
  2. 売上情報取得の為のkintone REST API と クラウド請求書 API は 非同期で実行されるため、Promise形式にして、thenメソッドを使い、シーケンシャルに実行していく。
    • kintone.api(売上情報取得).then(請求データ作成).then(正常終了時処理).catch(異常時処理);
  3. MF請求書APIの実行は kintone.proxy() で実行する
    • クライアント側で実行されるJavaScriptで外部連携を実施するにはクロスドメイン制約の壁を突破する必要があります。とっても大事な事なので、クロスドメインについてはここを参照ください。
    • kintone.proxy()は簡単に言うとkintoneサーバに実行したいAPIを登録して、クライアントの代わりに実行してもらう機能です。kintoneサーバ側での実行なのでクロスドメイン制約は受けないのです。

以下は、kintone.proxy()実行時のHTTPリクエストの状況です。/k/api/proxy/call.jsonのPOSTリクエストが発行されてます。Request Payloadを見ると請求情報が渡されているのが分かります。

請求情報の作成が成功するとクライアント側に以下のような情報が返ってきます。
それを元にkintone側の情報に更新を加えれば請求データ作成済みか否かも管理できます。
また、画像の中ほどには作成した請求書のPDFファイルへのURLもあるので、PDFファイルをダウンロードしたい場合はそこからダウンロードします。

実際に作成したクラウド請求書上に作成した請求書です。

まとめ

今回はとりあえず売上品目については問答無用で登録してしまいましたが、クラウド請求書側でマスタ管理しておく事もできるので、利用してみると楽かもしれません。
やってみると、わりと楽に外部APIを使用してデータ連携できるので、kintoneご利用の際は、使えるAPIを探して便利に使うと幸せかもです。

wpmaster
  • wpmaster
  • フリーランスシステムエンジニアの鎌形です。
    鎌形システムエンジニアリングとして都内で活動中です。

%d人のブロガーが「いいね」をつけました。