0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

フリーランス向け「会員登録不要・ローカル完結」の請求書自動計算ツールをVanilla JSで作った話

0
Last updated at Posted at 2026-09-05

個人開発やフリーランスとして活動していると、月末の請求書作成が意外と手間で「サクッとブラウザ上で作ってPDF保存できるだけのツール」が欲しくなります。

しかし、既存のクラウドサービスは高機能な反面、会員登録が必要だったり、不要な機能が多かったりします。
そこで今回、「Vanilla JS + LocalStorage」のみで完結する、サーバーレスな請求書自動計算ツールをサクッと作成しました。

本記事では、その際に実装した「消費税(インボイス制度対応)の端数処理ロジック」と、「ブラウザの印刷機能で綺麗にA4出力するためのCSSテクニック」を共有します。

作成したツールのデモ

実際に動くツールはこちらです。サーバーへのデータ送信は一切なく、すべてブラウザのローカルで完結します。
👉 無料請求書作成ツール(ローカル保存対応)


1. インボイス制度を見据えた消費税計算ロジック

請求書の金額計算において注意が必要なのが「消費税の端数処理」です。インボイス制度(適格請求書等保存方式)では、**「1つのインボイスにつき、税率(10%・軽減8%)ごとにそれぞれ1回のみ端数処理を行う」**と定められています。

明細行ごとに消費税を計算して端数処理するのではなく、税抜合計額を税率ごとに集計してから、消費税を計算する必要があります。

// 誤った実装(行ごとに計算・端数処理してしまう)
// const totalTax = items.reduce((sum, item) => sum + Math.floor(item.price * taxRate), 0);

// 正しい実装例(税率ごとに合計額を算出し、1回だけ端数処理)
function calculateInvoiceTotal(items) {
    // 税率ごとに税抜金額を集計
    const subTotal10 = items.filter(i => i.taxRate === 0.10).reduce((sum, i) => sum + (i.price * i.quantity), 0);
    const subTotal8 = items.filter(i => i.taxRate === 0.08).reduce((sum, i) => sum + (i.price * i.quantity), 0);
    
    // インボイス制度に則り、税率ごとの合計額に対して1回だけ端数処理
    // この実装例では端数処理方法として切捨て(Math.floor)を採用
    const taxAmount10 = Math.floor(subTotal10 * 0.10); 
    const taxAmount8 = Math.floor(subTotal8 * 0.08); 

    
    return {
        subTotal: subTotal10 + subTotal8,
        taxTotal: taxAmount10 + taxAmount8,
        totalAmount: subTotal10 + subTotal8 + taxAmount10 + taxAmount8
    };
}

※端数処理の方法は、切捨て・四捨五入・切上げなどから事業者が選択できます。このサンプルでは実装例として切捨て(Math.floor())を採用しています。

このように、明細の合計を税率別に算出し、最後に端数処理で税額を確定させるのが実務上安全です。

2. @media print でブラウザからA4PDFを綺麗に出力する

今回のツールは「ブラウザの印刷機能(Ctrl+P / Cmd+P)を使ってPDF保存する」ことを前提としています。
そのため、画面表示用のUI(ボタンや入力フィールドの枠線)を印刷時には非表示にし、A4サイズに最適化するCSSが必要です。

/* 画面表示時のスタイル(入力しやすいように枠線を出す) */
input, textarea {
    border: 1px solid #ccc;
    background-color: #f9f9f9;
}

/* 印刷時のみ適用されるスタイル */
@media print {
    /* 印刷不要なヘッダーやボタンを隠す */
    .no-print, header, footer, button {
        display: none !important;
    }

    /* A4サイズを意識した余白設定 */
    @page {
        size: A4;
        margin: 15mm;
    }

    /* 印刷時は入力枠や背景色を消してプレーンなテキストのように見せる */
    input, textarea {
        border: none !important;
        background: transparent !important;
        resize: none;
    }

    /* 改ページを制御して見栄えを良くする */
    .invoice-container {
        page-break-inside: avoid;
    }
}

このような印刷用CSSを用意することで、ブラウザの印刷機能を利用したA4帳票として出力しやすくなります。

3. LocalStorage によるデータ永続化

「会員登録不要」を実現するため、入力された自社情報や顧客情報はすべてブラウザの localStorage に保存しています。

// 入力内容の保存
function saveToLocal(data) {
    localStorage.setItem('invoice_data', JSON.stringify(data));
}

// 初回ロード時の復元
function loadFromLocal() {
    const stored = localStorage.getItem('invoice_data');
    if (stored) {
        const data = JSON.parse(stored);
        // DOMに値をセットする処理...
    }
}

機密情報を扱うバックエンドやDBを持たないため、サーバー側の運用負担を小さく抑えることができます。


請求書発行後の入金待ちについて

請求書を発行しても、取引条件によっては実際の入金まで一定の期間が空くことがあります。

事業の資金繰りを考える際には、銀行融資などとともに、売掛債権を利用するファクタリングも選択肢の一つとして存在します。

※以下には広告リンクを含みます。

QuQuMo(ククモ)公式サイト

おわりに

ちょっとしたツールでも、実務のドメイン知識(消費税計算)やCSSの印刷制御(@media print)を組み合わせることで、実用的なものが作れます。

自分用に作ったものですが、フリーランスや個人事業主の方で「会員登録なしですぐにPDFを作りたい」という方はぜひ使ってみてください。

👉 無料請求書作成ツール(ローカル保存対応)

最後まで読んでいただきありがとうございました!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?