メインコンテンツにスキップ

ArtinTech Solution

WordPress invoice plugin by ArtinTech Solution

🌐 他の言語で読む: English · Español · Deutsch · Français · العربية · Bahasa Melayu · 简体中文 · 日本語

小規模な制作会社やフリーランスの請求書作成は、たいてい二つの方法のどちらかです。一つは、スプレッドシートと Word のテンプレートを使い、誰かが手作業で PDF に書き出す方法。もう一つは、ユーザー単位・月額で課金され続けるクラウド型の請求書サービスです。前者は二人が同時に触った瞬間に破綻します。後者は、メンバーが一人増える、二つ目の通貨を扱う、あるいは製品が想定していない要件を持つ顧客が現れるまでは問題なく使えます。

私たちはその両方の問題に直面したため、独自の WordPress 請求書プラグイン「ArtinTech Invoice Manager」を開発しました。WordPress サイト上でフルスクリーンのアプリとして動作し、ワンクリックで PDF 出力できる本格的な請求書の作成、残高付きの顧客台帳、複数通貨での入金管理、利用者を管理する管理パネルを備えています。このプラグインは当サイトで実際に稼働しており、私たち自身も現在これで顧客に請求書を発行しています。

本記事はその開発の全記録です。プラグインの機能、設計の内容と理由、セキュリティモデル、お客様より先に私たちが見つけた不具合、そしてコードを WordPress.org のプラグインディレクトリの基準に合わせるために行った作業を解説します。請求書ツールを個別開発するか既製品を使うかで迷っている方は、最後のセクションが参考になるはずです。

請求額・入金額・未収金・期限超過の合計を表示する WordPress 請求書プラグインのダッシュボード
請求書ダッシュボード:通貨ごとの合計、最近の請求書、全件リスト。本記事のスクリーンショットはすべてデモデータを使用しており、顧客名は架空のものです。

独自の WordPress 請求書プラグインを開発した理由

借りて済むソフトウェアをわざわざ自作するのは、たいていの場合は失敗です。だからこそ、今回そうではなかった理由をきちんと説明しておきます。決め手になったのは理念ではなく、実務上の理由でした。

  • データは自社で保有すべきだから。 請求書、顧客の住所、入金履歴は会社の財務記録そのものです。すでにバックアップと管理を行っている WordPress のデータベースに保存するほうが、いざという日に外部サービスのエクスポート機能に頼るよりも確実です。
  • ユーザー単位の課金は、規模が大きくなるほど不利だから。 一人で使うなら安いクラウドツールも、小さなチームや外部の協力者がそれぞれアカウントを必要とするようになると、無視できないコストになります。プラグインなら、一人で使っても二十人で使っても費用は同じです。
  • 一つのサイトで、独立した複数のアカウントを運用したかったから。 一人ひとりが自分の請求書、顧客、ロゴ、口座情報、採番ルールを持ち、同じサイト上で他の人と完全に分離されている必要がありました。
  • 請求が国際的だから。 私たちは海外の顧客に、複数の通貨で請求しています。勝手に換算されない通貨別の合計と、海外送金用の口座情報を記載できる請求書が必要でした。
  • 自分たちで改修したかったから。「支払済みにする」ボタンや、顧客ロゴを非表示にするスイッチが必要になったとき、ベンダーのロードマップを待つのではなく、その日の午後には実装したかったのです。

クラウド型の請求書ソフトが悪いというわけではありません。トレードオフが異なるだけです。両者を並べて比較すると分かりやすくなります。

クラウド型請求書サービスセルフホスト型 WordPress 請求書プラグイン
データの保存場所ベンダーのサーバー自社の WordPress データベース
チーム拡大時のコスト通常はユーザー数に応じて増加ユーザー数にかかわらず一定
導入の手間数分インストール、有効化、アプリページの作成
カスタマイズ性設定画面で可能な範囲コードで実現できることすべて
保守ベンダーが対応他のプラグインと同様に自社の責任
外部連携既製のコネクタが豊富なことが多い自社のシステム構成に合わせて必要に応じて開発

右の列が面倒な作業のリストに見えるなら、クラウド型ツールのほうがおそらく適しています。すでにサイト運営で日常的に行っていることのリストに見えるなら、プラグインが現実的な選択肢になります。

使い方:インストールから請求書の入金確認まで

詳細に入る前に、全体の流れを最初から最後まで紹介します。管理者が一度だけ行う作業と、アカウント利用者が請求のたびに行う作業です。全9ステップを、実際の画面とともにご覧ください。

ステップ1:プラグインをインストールしてアプリページを作成する

  1. Plugins → Add New → Upload Plugin からプラグインをアップロードし、有効化します。
  2. wp-admin に追加された Invoice Manager メニューを開きます。
  3. Create app page をクリックします。

これで /invoice-manager/ にページが公開され、そのページがアプリになります。サイトのほかの部分には一切影響がなく、管理者はすぐにアプリを使い始められます。

ステップ2:ログインする、または利用者に登録してもらう

ログインしていない人がアプリページを開くと、専用のログイン画面が表示されます。通常の WordPress のユーザー名またはメールアドレスでログインでき、「Remember me」と「Forgot password」のリンクも用意されています。

Invoice Manager のログイン画面
フロントエンドのログイン画面。アカウント利用者が wp-admin を目にすることはありません。

一般登録を有効にすると、ログインフォームの下に Create one リンクが表示され、登録画面が開きます。管理者承認を有効にしている場合、新しいアカウントは管理者が承認するまで保留状態になります。

Invoice Manager の登録画面
任意で有効化できる登録画面。新規アカウントは利用前に審査される旨が表示されます。

ステップ3:事業者情報を一度だけ登録する

アカウント利用者はまず My settings から始めます。

  • ロゴをアップロードし、個人か法人かを選択します。
  • 住所、連絡先、税番号を入力します。
  • 既定の通貨と支払期限を選びます。
  • 振込先口座情報を貼り付けます。
  • 請求書番号の接頭辞と開始番号を設定し、独自の税率を追加します。

ここで入力した内容は新しい請求書に自動で反映されるので、入力は一度だけで済みます。

ロゴ、事業所住所、通貨、口座情報、請求書番号を設定するアカウント設定画面
My settings:ブランディング、事業者情報、通貨、口座情報、請求書の採番。

ステップ4:顧客を登録する

Clients → Add Client から、各顧客を一度だけ登録します。ロゴ、会社名と担当者名、メールアドレス、電話番号、住所、税番号です。顧客台帳は検索でき、各カードにはその顧客の請求書数と未収金額が表示されます。

ロゴと未収残高を表示する顧客台帳
顧客台帳。ロゴと未収残高がひと目で分かります。

ステップ5:請求書を作成する

New invoice をクリックします。番号、日付、通貨、支払条件、自社情報はすでに入力されています。

  1. 顧客を選びます。
  2. 数量・単価・税率を指定して明細行を追加します。
  3. 必要に応じて値引きを適用し、発注番号などのカスタム項目を追加します。
  4. この請求書に自社ロゴと顧客ロゴを表示するかどうかを選びます。
  5. Save をクリックします。

合計金額は入力に合わせてその場で再計算されます。

明細行、値引き、顧客情報、ロゴ切り替えスイッチを備えた請求書エディター
請求書エディター:左が請求書本体、右が操作ボタンとロゴ切り替えスイッチです。

ステップ6:プレビューして PDF をダウンロードする

Preview では、顧客が受け取るのとまったく同じ見た目で請求書を確認できます。Download PDF で A4 サイズのファイルを保存し、メール送付、顧客ポータルへのアップロード、印刷に利用できます。

テンプレートは3種類あり、エディターのテンプレートメニューから請求書ごとに選べます。

  • Blank: すっきりとしたミニマルなレイアウト。
  • Modern: カラーのヘッダー帯付き。
  • Classic: 明朝系のセリフ書体と罫線。
差出人と顧客のロゴ、口座情報、支払条件を含む PDF 請求書のプレビュー
PDF プレビュー。両方のロゴ、値引き、口座情報、支払条件が表示されます。

ステップ7:入金を記録する

入金があったら、請求書の行にある Mark paid をクリックします。一部入金の場合は $ アイコンから、日付・支払方法・参照番号を添えて記録します。ステータスは自動で切り替わります。

  • 分割入金後は Partially paid(一部入金)。
  • 残高がゼロになると Paid(支払済み)。
  • 全額入金前に支払期限を過ぎると Overdue(期限超過)。
金額、日付、支払方法を入力する入金記録ダイアログ
入金の記録。金額には未収残高があらかじめ入力されています。

ステップ8:未収金を把握する

ダッシュボードの合計はすぐに更新されます。特定の顧客については、顧客台帳からその顧客のページを開くと、次の内容を確認できます。

  • 通貨ごとの請求額、入金額、未収金。
  • その顧客に発行したすべての請求書。

督促の電話をかける前に開くべき画面です。

請求額・入金額・未収金の合計と請求履歴を表示する顧客ページ
顧客ページ:通貨ごとの残高と全請求履歴。

ステップ9:利用者を管理する

管理者と Invoice Manager Admin ロールを付与された人は、Admin panel → Users を開きます。ここでは次の操作ができます。

  • 保留中の登録を承認する。承認されたユーザーには自動でメールが届きます。
  • アカウントを停止、または再開する。
  • ユーザーを直接追加する。新しいユーザーにはパスワード設定用のメールが届きます。
  • ロールを変更し、アカウントを削除する。
承認・停止・ロール変更の操作ができる管理パネルのユーザー管理画面
ユーザー管理:承認、停止、ロール、各アカウントの請求書数と顧客数。

プラグインの機能紹介

上記の流れがメインの使い方です。ここでは、それ以外にできることを紹介します。すべての機能がサイト内の1ページで動作し、WordPress の管理画面ではなく独立したアプリのように感じられるインターフェースになっています。

請求書ダッシュボード

トップ画面は、経営者が請求書ツールを開くときに真っ先に知りたいこと、つまり「誰がいくら未払いなのか」に答えます。上部には請求額、入金額、未収金、期限超過の4つの数値が並びます。いずれも通貨ごとに個別に計算され、複数の通貨で請求している場合は切り替えることができます。その下に最新の請求書4件がカードで表示され、続いて全請求書のリストが表示されます。

リストは請求書番号や顧客名で検索でき、顧客、ステータス、書類種別、期間で絞り込み、任意の列で並べ替えられます。各行から、請求書を開かずに入金の記録、支払済みへの変更、PDF のダウンロード、複製、削除が行えます。

請求書エディター

エディターは完成した請求書と同じレイアウトになっており、入力した内容がそのまま実際の位置に表示されます。操作ボタンは右側のパネルにまとまっています。

  • 4種類の書類: Invoice(請求書)、Quote(見積書)、Proforma(プロフォーマインボイス)、Credit Note(貸方票)。
  • 自動採番: ユーザーごとの接頭辞付き(例:AT2623)。番号は編集でき、重複は受け付けません。
  • 発行日と支払期限: 支払期限は各ユーザーの既定の支払条件から自動入力されます。
  • 明細行: 数量、単価、説明、ユーザー独自の税率リストから選ぶ税率。
  • 請求書単位の値引き、発注番号などのカスタム項目、追加の会社情報、自由記述の説明。
  • 顧客情報: 顧客台帳から選ぶか、一度限りの入力も可能。その場で新規顧客として保存することもできます。
  • 通貨の選択(請求書ごと)と、設定から自動入力される支払条件のテキスト。

合計は入力に合わせて更新されます。未保存の変更があるまま画面を離れようとすると、破棄してよいか確認されます。この小さな配慮は、請求書ツールでは特に重要です。

入金、ステータス、「支払済みにする」

請求書のステータスを手作業で設定する人はいません。ステータスは記録された入金から導き出されるため、実際のお金の動きと食い違うことがありません。

記録された入金表示されるステータス
なしUnpaid(未入金)
合計より少ないPartially paid(一部入金)
合計と同額以上Paid(支払済み)
全額未入金のまま支払期限を超過Overdue(期限超過)
書類種別が見積書Quote(売上には計上されません)

各入金には日付、金額、支払方法、任意のメモがあり、分割払いや振込手数料による不足額も正確に記録できます。最もよくあるケース、つまり顧客が全額を支払った場合には、ワンクリックの Mark as paid ボタンがあります。残高と同額の入金を、本日の日付で1件記録します。

PDF 出力とテンプレート

すべての請求書は、3種類のテンプレートのいずれかでプレビューし、A4 の PDF としてダウンロードできます。シンプルな Blank、カラーのヘッダー帯が入った Modern、セリフ書体と罫線の Classic です。

PDF には次の内容が含まれます。

  • 差出人のロゴと顧客のロゴ。それぞれ請求書ごとに非表示にできます。
  • 双方の住所。
  • 明細行、値引き、税額、合計。
  • 受領済みの入金、請求残高、口座情報、支払条件。

顧客台帳

顧客は一度登録すれば繰り返し使えます。各顧客にはロゴ、会社名と担当者名、住所、税番号、メモがあります。

顧客リストには各顧客の未収金額が表示され、顧客ページでは次の内容を確認できます。

  • 通貨ごとの請求額、入金額、未収金の合計。
  • 請求書の全履歴。
  • その顧客の情報が入力済みの状態で新しい請求書を作成するボタン。

アカウント利用者ごとの個別設定

各ユーザーは次の項目をそれぞれ持っています。

  • ロゴと、個人・法人の区別。
  • 住所と国際電話番号。
  • 税務登録番号とウェブサイト。
  • 既定の通貨と、日数で指定する支払期限。
  • 口座情報、請求書番号の接頭辞、次の番号。
  • 既定の支払条件テキストと、名前付きの税率リスト。

そのため、同じサイト上の二人が、まるで別々の会社から発行されたような請求書を発行できます。実際にそうだからです。

登録、承認、管理パネル

アプリにはフロントエンド専用のログイン画面と登録画面があり、アカウント利用者が wp-admin を目にすることはありません。一般登録は任意です。有効にした場合、新規アカウントの利用開始前に管理者の承認を必須にでき、登録があるたびに管理者へメールが届きます。

アプリ内では、管理者は4つのセクションからなる Admin panel を利用できます。

  • Overview: 全ユーザーのアカウント数と請求件数。
  • Users: アカウントの承認、停止、再開、追加、削除、ロールの変更。
  • Sign-up settings: 登録に関する設定。
  • Messages: アプリ内の「Contact us」フォームから届いたメッセージ。
アカウント数、登録設定、通貨別の請求件数を表示する管理パネルの概要画面
管理パネルの概要:承認待ちのアカウント、登録設定、全アカウントの請求件数。

自社の業務にぴったり合う社内ツールをお探しですか?

請求、承認、見積、顧客ポータル。業務の流れをお聞かせください。既存のプラグインで十分か、個別開発に見合う価値があるかを率直にお伝えします。

設計:WordPress 請求書プラグインはデータをどう保存すべきか

プラグインの長期的な品質は、その大部分がデータモデルで決まります。実際の請求書が存在するようになると、データモデルは最も変更しにくい部分になるからです。私たちは早い段階で4つの判断を下し、そのすべてが正しかったと実証されました。

独自テーブルではなくカスタム投稿タイプを採用

請求書、顧客、問い合わせメッセージは、非公開のカスタム投稿タイプとして保存しています。各レコードは作成した WordPress ユーザーが所有し、構造化データは1件の投稿メタ(post meta)に格納しています。個人設定はユーザーメタ(user meta)に、プラグイン全体の設定は Options API に保存しています。

独自のデータベーステーブルにすれば、非常に大量のデータではわずかに高速だったかもしれません。その代わり、投稿タイプを使うことで多くのメリットが得られます。

  • WordPress の標準的なバックアップや移行で、データが自動的に含まれます。
  • エクスポートツールがそのまま扱えます。
  • 追加のコードなしでオブジェクトキャッシュが機能します。
  • ユーザーを削除すると、後処理のコードを一行も書かずにそのユーザーのレコードも削除できます。

企業向けの請求書ツールで、一人あたりの請求書が数千件を超えることはまずありません。その規模であれば、WordPress 標準の方法が最適です。

これらの投稿タイプは完全な非公開として登録しています。公開されず、クエリの対象にならず、検索から除外され、REST API やサイトマップにも表示されません。請求書がテーマの検索結果や SEO プラグインのサイトマップに誤って紛れ込むことはありません。

スナップショット:請求書が差出人と顧客の情報を複製する理由

請求書は、ある時点を記録した法的な書類です。来年オフィスを移転しても、昨年の請求書には昨年の住所が表示されていなければなりません。そのため、請求書を作成する時点で、プラグインは差出人情報を請求書内に複製し、顧客情報も同様に複製します。

設定や顧客の住所を変更しても、過去の請求書が書き換わることはありません。古い下書きに新しい情報を反映させたい場合は、黙って置き換えるのではなく、エディターの「Use my latest settings」という明示的な操作で行います。

請求書は顧客レコードへのリンクも保持しており、顧客ごとの残高はこのリンクに基づいて計算されます。顧客を削除するとリンクは解除されますが、スナップショットは残ります。請求書は正しく表示され続け、存在しなくなった顧客の集計に含まれなくなるだけです。

ステータスは保存せず、計算する

「期限超過」は今日の日付によって決まるため、保存してしまうと翌日には誤った値になりかねません。プラグインが保存するのは事実、つまり明細、値引き、入金、支払期限です。ステータスは請求書を読み込むたびに計算します。ステータスを保存するフィールドは、業務ソフトウェアでよくある「ダッシュボードでは支払済みなのに、銀行では未入金」という問題の最大の原因の一つです。

経理担当者も納得する金額計算

  • 値引きは税計算の前に適用します。 10% の値引きは小計とそれにかかる税額の両方を減らします。これは多くの税制が想定している方法です。
  • 税は明細行ごとに計算します。 各行が独自の税率を持つため、一枚の請求書に課税項目と非課税項目を混在させられます。
  • 貸方票はすべての合計でマイナスとして扱い、見積書は一切計上しません。
  • 通貨は換算しません。 合計は通貨ごとに保持します。任意の為替レートで勝手に換算すると、請求書とも銀行明細とも一致しない数字になってしまいます。
  • 合計は保存時にサーバー側で明細行から再計算します。 ブラウザでの計算は表示のためだけのものであり、改ざんされたリクエストで辻褄の合わない合計を保存することはできません。

すべてのリクエストで所有者を確認する REST API

フロントエンドは、専用の REST 名前空間を通じて WordPress と通信します。すべてのルートで同じ権限チェックが行われます。リクエストは、プラグイン独自の権限と有効なアカウント状態を持つログイン済みユーザーからのものでなければならず、有効な WordPress の nonce を含んでいる必要があります。

さらに、請求書や顧客を指定するすべてのリクエストで、そのレコードが現在のユーザーのものかを確認します。そうでない場合、API は forbidden(アクセス拒否)ではなく not found(見つかりません)を返します。この区別は意図的なものです。「アクセス拒否」はその ID のレコードが存在することを認めてしまいますが、「見つかりません」は何も明かしません。あるアカウントでログインした状態で別のアカウントの請求書を要求するテストを行い、実際に確認しています。

受け付けるすべての項目は、無害化と文字数制限を行っています。

  • 日付は厳密な形式に一致する必要があります。
  • 通貨は3文字である必要があります。
  • 書類種別とテンプレートは、決められたリストの中から選ばれる必要があります。
  • ロゴは、サイト自身のメディアライブラリにアップロード済みの画像のみ受け付けます。

アップロードされた画像は、メディアライブラリに保存される前にデコードされ、本物の PNG、JPEG、GIF、WebP ファイルかどうかが確認されます。SVG ファイルはスクリプトを含む可能性があるため受け付けません。

ある実務的な工夫が、将来のサポート対応を減らしてくれました。共有サーバーやファイアウォールの設定によっては、HTTP の PUT や DELETE リクエストが完全にブロックされることがあります。そこでアプリでは、すべての書き込みを POST として送信し、WordPress 標準のメソッドオーバーライドヘッダーを付けています。これは REST API が標準でサポートしている仕組みです。ルートは RESTful なまま、制限の厳しいサーバーでもリクエストが通ります。

アカウント、ロール、承認

プラグインは2つのロールと1つの権限モデルを追加します。WordPress 標準のロールについては、管理者にアクセス権を付与する以外には一切変更しません。

ロールアプリの利用アカウント利用者の管理請求書管理者とロールの管理
Administrator(管理者)可可可
Invoice Manager Admin可可不可
Invoice Account Holder可不可不可

中間のロールは、たとえば事務所の責任者が、サイト全体の権限を持たずに利用者の承認やサポートを行えるようにするためのものです。アプリ内から管理者を停止・削除することはできず、自分自身のアカウントを削除することもできません。こうした操作ミスこそが、自分のサイトから締め出される原因になるからです。

一般登録は、管理者が有効にするまで無効になっています。有効にした場合、登録フォームは次の4つの方法で保護されます。

  • nonce。
  • ボットは入力し、人間は入力しない隠しフィールド(ハニーポット)。
  • ネットワークアドレスごとに1時間あたり5件までの登録制限。
  • パスワードの最小文字数。

承認を有効にしている場合、新しいアカウントはログインできても、管理者が承認するまでは「承認待ち」の画面しか表示されません。承認された時点でユーザーにメールが届きます。ユーザーを停止すると、Cookie の有効期限切れを待たず、WordPress のセッションを破棄することで、すべての端末から即座にログアウトさせます。

テーマに崩されないフルスクリーンアプリ

請求書アプリは、どのサイトにインストールされても同じ見た目と動作である必要があります。テーマのボタンスタイル、ページビルダーのリセット CSS、キャッシュプラグインのスクリプト最適化機能は、いずれもアプリ型のインターフェースを気づきにくい形で崩してしまう可能性があります。そのため、プラグインは自分のページの表示を完全に自前で行います。

訪問者がアプリページを開くと、プラグインはテーマの代わりに独自の最小限のテンプレートを返します。このテンプレートは、WordPress 標準のスタイル・スクリプト関数を通じてプラグイン自身のスタイルシートとスクリプトだけを出力し、テーマや他のプラグインのものは一切含みません。また、このページはコンテンツではなくアプリであるため、キャッシュには保存しないよう、検索エンジンにはインデックスしないよう指示しています。

インターフェース自体は、フレームワークを使わない素の JavaScript モジュールで書かれ、読みやすい1つのファイルにまとめられています。ナビゲーションにはハッシュベースのルーティングを使っているため、請求書、顧客、設定を切り替えてもページは再読み込みされず、ブラウザの「戻る」ボタンもそのまま使えます。書体の DM Sans はフォント配信サービスから読み込むのではなくプラグインに同梱しているため、アプリが外部のサーバーにリクエストを送ることはありません。

レイアウトは最初からスマートフォンを前提に設計しています。小さな画面では、次のように表示が変わります。

  • サイドバーはスライド式のメニューになります。
  • データの表は、各値にラベルが付いた縦並びのカードになります。
  • 請求書エディターは1列に並び替えられます。

顧客から「支払いました」と連絡があったとき、請求書はスマートフォンで確認されることがよくあります。

スマートフォンで表示した請求書ダッシュボード
スマートフォンで見たダッシュボード。
スマートフォンで縦並びのカードとして表示された請求書リスト
請求書リストは縦並びのカードになり、Mark paid もワンタップで押せます。

PDF 請求書をブラウザ内で生成する

PHP によるサーバー側での PDF 生成は、重いライブラリ、サーバーへのフォント導入、メモリ制限、そしてサーバーごとに大きく異なる出力結果を意味しがちです。そこで私たちは、PDF をユーザーのブラウザ内で生成しています。

  1. 請求書を A4 サイズの HTML ドキュメントとして描画します。
  2. そのドキュメントを画像に変換します。
  3. オープンソースのライブラリ html2pdf.js を使って、画像を PDF ファイルに配置します。

この方式には3つの利点があります。

  • 画面上のプレビューそのものなので、PDF はプレビューとまったく同じ見た目になります。
  • どのサーバーでも動作します。
  • 変換のために請求書データがどこかへ送信されることはありません。

トレードオフとして、PDF 内の文字は選択可能なテキストではなく画像になります。読んで、印刷して、保管する請求書であれば、どこでも同じ出力が得られることの代償として十分に許容できると考えています。

お客様より先に見つけた不具合

以下はいずれも実際の画面で発生した不具合です。どれも他のプロジェクトでも起こりうる類の問題なので、詳しく紹介します。

0.5ピクセルが原因の空白の2ページ目

1ページの請求書をダウンロードすると2ページの PDF になり、2ページ目が空白になっていました。原因は次のとおりです。プレビューを1枚の用紙らしく見せるため、画面上のドキュメントに1123ピクセルの最小の高さを設定していましたが、96 DPI での A4 の高さは1122.5ピクセルです。このわずか0.5ピクセルのはみ出しで、PDF ライブラリが新しいページを作成していました。

修正では、書き出し時にだけ最小の高さを解除するようにしました。プレビューは引き続き用紙のように見えます。生成された PDF のページ数を数えて確認したところ、修正前は2ページ、修正後は1ページでした。45行の明細がある請求書は、引き続き内容のある2ページ目に正しく続きます。

自分自身をエスケープしてしまったログアウトリンク

WordPress のログアウト URL を生成する関数は、HTML 用にエスケープ済みの URL を返し、アンパサンドは & と表記されます。これは HTML の属性内では正しいのですが、JavaScript 内では誤りです。エスケープされた記号がセキュリティトークンを壊し、ログアウトできなくなっていました。修正では、アプリに渡す前に URL を一度デコードしています。小さな不具合ですが、PHP テンプレートと JavaScript の境界で起こりがちな典型例です。

請求書に反映されなかった顧客ロゴ

顧客のロゴはアップロードでき、正しく保存もされていましたが、請求書には一度も表示されませんでした。各請求書に複製されるスナップショットに、ロゴが含まれていなかったのが原因です。修正は2段階で行いました。

  • 新しい請求書では、スナップショットにロゴを含めるようにしました。
  • 以前に保存された請求書は、読み込み時にリンクされた顧客の現在のロゴを使います。保存済みのデータは書き換えません。

表示の問題を修正するときに保存済みのデータに手を付けないことは、身につけておく価値のある習慣です。

表と食い違うダッシュボードのカード

リストから請求書を支払済みにすると、表の行は緑色に変わるのに、その上の「最近の請求書」カードはページを再読み込みするまで Unpaid のままでした。同じデータを表示する二つの画面の同期がずれていたのです。現在は、請求書を変更する操作を行うたびに最新のデータで画面全体を再描画するため、ページ上のすべての数値が常に一致します。

ロゴ追加後のレイアウトのずれ

顧客のロゴを住所の上に配置すると、「To」ブロックが「From」ブロックより下から始まり、請求書のバランスが崩れて見えました。ロゴを住所の右側に移すことで解決し、両方のブロックが同じ行から始まり、ロゴは上の請求書番号と揃うようになりました。さらに、スイスの一般的な住所が1行に収まるよう、顧客欄の幅を少し広げました。教訓は、請求書のレイアウトは実際の顧客データでテストすることです。サンプルの名前は、いつも都合よく短いものだからです。

WordPress.org プラグインディレクトリへの公開準備

自社サイトで動くコードと、WordPress.org の審査に通るコードは同じではありません。プラグインディレクトリには独自のルールがあり、申請前にいくつもの点を見直して対応しました。

  • 外部サーバーへの通信をなくしました。 当初はフォントを外部のフォント配信サービスから読み込んでおり、訪問者全員の IP アドレスが第三者に送られていました。現在は、オープンフォントライセンスに基づいてフォントをプラグインに同梱しています。
  • スクリプトとスタイルは WordPress 自身の関数で読み込みます。 直接書いていた script タグや link タグは、登録済みでバージョン付きのアセットに置き換えました。実行時の設定は、標準のインラインスクリプトの仕組みで渡しています。
  • 読めるソースコードにしました。 ディレクトリでは、ソースのない圧縮済みコードは認められません。アプリのバンドルは圧縮せずに配布し、元のモジュールも同梱して、再ビルドの方法を readme に記載しました。
  • サードパーティのライセンスを明記しました。 PDF ライブラリとフォントは、ライセンスとソースへのリンクとともに readme に記載し、ライセンスファイルもプラグインに同梱しています。
  • プラグインからコアのフックを発火させません。 初期のバージョンでは、登録後に WordPress 自身のログインアクションを呼び出していましたが、現在はプラグイン独自のコードでログインを記録しています。
  • アンインストール時のデータ削除は任意です。 管理者が明示的に削除を求めない限り、プラグインを削除してもデータは一切消えません。請求書は業務上の記録であり、誤クリックで失われることがあってはならないからです。
  • readme を完備しました。 概要、インストール手順、よくある質問、プライバシーに関する項目、変更履歴を記載しています。また、公式の Plugin Check ツールで問題なく審査できるようにコードを構成しています。

こうしたルールのせいでプラグインが悪くなったものは一つもなく、むしろいくつかは改善につながりました。たとえばフォントを同梱したことで、プライバシー上の懸念そのものがなくなりました。

データ設計からしっかり作り込んだ WordPress プラグインが必要ですか?

ツールに求める機能をお知らせください。1営業日以内に、明確な開発範囲、検討すべき選択肢、固定のお見積りをご提示します。

WordPress 請求書プラグインは個別開発すべきか、既製品を使うべきか

率直に言えば、ほとんどの企業は請求書ツールを個別開発する必要はありません。一人が月に数件の請求書を一つの通貨で発行する程度なら、既製品で十分に用が足り、どんな個別開発よりも安く済みます。次の項目のうち複数が当てはまる場合に、個別開発がより良い選択肢になります。

  • 複数の人が一つのシステムで、互いに分離された請求業務を行う必要があり、ユーザー単位の課金が負担になり始めている。
  • 予約システム、プロジェクト管理ツール、ERP、顧客ポータルなど、自社に固有のシステムと請求業務を連携させる必要がある。
  • 複数の通貨で請求しており、勝手に換算されない合計が必要である。
  • 独自の承認手順、書類種別、採番ルールなど、既製のツールでは対応できないルールが請求書に必要である。
  • 財務データを、自社で所有し、バックアップし、管理しているインフラに置いておきたい。

当てはまるのが一つだけなら、まずは既製品をもっと詳しく検討しましょう。三つ以上当てはまるなら、このような目的特化型のプラグインは、2〜3年で見れば、置き換える月額サービスや回避策の合計より安く済むことがほとんどです。しかも、必要なことをぴったり実現できます。

どちらを選ぶにしても、本記事で取り上げた次の観点で請求書ツールを評価してください。

  • 請求書ごとに確定した記録を残し、後から自社や顧客の情報を変更しても過去の請求書が書き換わらないか。
  • ステータスを保存するのではなく、入金から計算しているか。
  • 通貨ごとに分けて管理しているか。
  • ユーザー同士のデータを分離しているか。
  • 自社のデータを取り出せるか。

よくある質問

WordPress 請求書プラグインで複数のユーザーを扱えますか?

はい、そのように設計されていれば可能です。ArtinTech Invoice Manager では、すべての請求書と顧客は作成したアカウント利用者の所有となり、API はリクエストのたびに所有者を確認します。各ユーザーは自分専用の設定、ロゴ、採番ルール、口座情報を持ち、他の人のデータを見ることはできません。

請求書データを外部のサービスに送信しますか?

いいえ。すべてのデータはサイト自身の WordPress データベースに保存されます。PDF はユーザーのブラウザ内で生成され、フォントはプラグインに同梱されています。外部に送られるのは、登録や承認の通知など、通常の WordPress のメールだけです。

異なる通貨で請求できますか?

はい。請求書ごとに通貨を設定でき、ダッシュボードと顧客ページでは通貨ごとに合計を表示します。換算は一切行わないため、数値は実際に発行した請求書と常に一致します。

使用中のテーマやページビルダーでも動作しますか?

はい。アプリページはプラグイン独自のテンプレートとアセットで表示されるため、テーマや Elementor などのページビルダーが見た目や動作を変えることはありません。サイトのほかの部分にも一切影響しません。

プラグインは WordPress.org で入手できますか?

WordPress.org のプラグインディレクトリへの公開準備を完了しており、審査に通過し次第、掲載される予定です。それまでの間に利用をご希望の場合や、業務に合わせたカスタマイズ版をご希望の場合は、お気軽にお問い合わせください。

自社向けにカスタマイズ版を開発してもらえますか?

はい。独自の請求書レイアウト、書類種別の追加、予約システムやプロジェクト管理システムとの連携、顧客ポータル、承認ワークフローなどは、いずれも同じ基盤の自然な拡張です。開発範囲の決め方については、当社の WordPress プラグイン開発サービスをご覧ください。

このような WordPress ツールの開発は、私たちの業務の中核です。nonce の有効期限が原因だと突き止めたキャッシュ由来の 403 エラーのような小さな修正もあれば、今回のような本格的なアプリケーションもあり、WordPress 開発や独自 CMS・ERP 開発として提供しています。請求書ツールの導入を検討中の方、あるいは業務がソフトウェアに振り回されていると感じている方は、ぜひご相談ください。既製品で十分という結論であっても、率直に評価をお伝えします。

Share this article

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です