OLTA TECH BLOG

テクノロジーと好奇心で事業を成長させる

TECH BLOG

「社会保険+税金」払いの機能追加でエンジニアがやったこと

はじめに

OLTAのINVOYでエンジニアをしている小林です. 11月に「社会保険+税金」の支払いの機能がリリースされました!!

今回の記事では、この機能追加においてエンジニアがリリースまでに何をしてきたかを書こうと思います. 実際に、現場でエンジニアがどのように仕様に関わり、技術的な意思決定を行っているかのイメージが伝われば幸いです.

対象読者

  • OLTAの開発に興味がある人

現状の支払い機能と、新しい「社会保険+税金」払い

技術的な話に入る前に、INVOYが提供している支払い機能について簡単に説明します.

1. 既存の「請求書払い」

「請求書払い」はNVOYが提供しているメインの機能の1つです. ユーザーは取引先から受け取った請求書を登録し、カードで支払うことができます.その後、INVOYがユーザーに代わって振込先口座へ銀行振込を行う仕組みです.

ユーザーは以下の情報を登録します.

  • 振込金額
  • 振込先口座(銀行/支店/口座種別/口座番号/名義)
  • 請求書ファイル、支払期限など

2. 今回リリースした「社会保険+税金」払い

今回追加したのは、上記と同じく「カード払い」のスキームを使いつつ、支払い対象をPay-easyペイジー)対応の納付書(社会保険料労働保険料・税金など)まで広げた機能です.

ユーザーは納付書をアップロードし、カード情報を入力して支払います.具体的には以下の項目を入力することで支払いが可能になります.

  • 収納機関番号
  • 納付番号
  • 確認番号
  • 納付区分(必要な収納機関のみ)

Pay-easyはこれらの番号が1桁でも異なると納付が成立しません.そのため、従来の請求書払い以上に、プロダクト側での入力補助やユーザー体験(UX)の設計が重要になりました.

エンジニアがやったこと

ここからは、この機能をリリースするにあたり、エンジニアがどのようにプロジェクトを進め、設計と向き合ったかを書いていきます. 大きく「プロジェクトの進め方」と「データベース設計」の2つのパートに分けて説明します.

1. プロジェクトの進め方

参加メンバーはPdM、デザイナー、エンジニア3名(実装は2名)でした. PdMとデザイナーはこのプロジェクト以外にも案件を抱えていたため、スケジュールの策定や仕様の細かい詰めに関しては、エンジニアの主体性が求められる環境でした. 今回は以下のようなフェーズでプロジェクトを進めていきました.

要件定義:リスクの徹底的な洗い出し

機能を設計していくにあたり、まずは懸念事項の洗い出しを行いました.エンジニア主導で「実際に審査漏れやが発生したときどうするか?」といったケースの議論を行い、そこから「漏れを即座に検知できるようにシステム化する」などの具体的な要件へ落とし込みました.

実装期間:週次の同期とフィードバック

実装期間中は週一で定例MTGを実施しました. 単なる進捗報告だけでなく、PdMからの仕様変更の相談や、デザイナー側からの実装に対するフィードバックをその場で受け、即座に修正サイクルを回すことで手戻りを防ぎました.このサイクルを回せたおかげで、結果としてエンジニア主導で策定した当初のスケジュール通りに、大きな遅延なく開発を進めることができました.

仕様詰め:実装して、触って、詰めていく

仕様策定のアプローチとして「仕様を完全に固めてから実装」するのではなく、「大枠を決めたら実装し、実際に触りながら詰めていく」スタイルをとったりしました.

例えば、今回の機能は入力項目が多いです. 全ての項目が開いた状態だと情報量が多すぎてユーザーが離脱する懸念がある一方で、閉じた状態だと入力ミスに気づきにくいという課題がありました. そこで、実装したものを触りながら以下のような挙動に調整を行いました.

  • 初期表示: エラーがある箇所は自然に目に入る状態(開いた状態+エラー表示)にする.
  • 情報の取捨選択: 「自社情報」セクションは、入力が必要になる場合のみ表示するように制御する.

こうすることで、「多すぎて圧倒される」ことと「入力ミスを見逃す」ことのバランスを取り、離脱を防ぐ設計に落とし込みました.

「自社情報」のセクションが表示 「自社情報」のセクションは必要なタイミングで表示

リリース戦略:Feature Toggleと安全な検証

リリースシミュレーションも入念に行いました. リリース当日は Feature Toggle(機能のON/OFFを切り替えるフラグ)を導入し、安全に本番反映を行いました. また、一般公開前に我々社員のアカウントのみ一時的に機能をONにし、本番環境でしか検証できない挙動を確認することを設けることで、リリースの安全性を高めました.

2. データベース設計:既存の「請求書」モデルとの親和性

今回、技術的に大きな壁になったのが「データの責務」と「既存テーブルの流用」でした.

既存テーブル AccountPayable の課題

INVOYの内部では、支払データを AccountPayable というテーブルで管理しています. このテーブルは、長らく「請求書払い」のために使われてきたため、以下のような性質を持っていました.

  • 「振込先関連」のカラムを持つ
  • 一覧表示や料金計算のロジックが、このテーブル構造に強く依存している

新機能とのギャップ

今回追加するPay-easy支払いに必要な情報は、「収納機関番号」や「納付番号」などであり、銀行口座情報とは全く異なります. しかし、決済処理やステータス管理(支払い済み、キャンセルなど)は、既存の枠組みを流用したい状況でした.

もし、AccountPayable にそのままPay-easy用のカラムを追加していくとどうなるでしょうか? 既存の支払いデータにはPay-easy用のカラムが不要(NULL)、逆にPay-easy支払いには銀行口座カラムが不要(NULL)となり、一つのテーブルに不要な情報が同居し、モデルの意味が曖昧になるという問題が発生します.最悪のケースは2重の支払いが1つのモデルで完結できてしまうことです.

解決策:「支払い方法」を軸にした分離

この相反を解くために、以下のような方針でテーブル設計を行いました.

  • AccountPayable は共通の骨格として維持する
    • 金額、ステータス、ユーザーIDなど、支払い手段に関わらず必要な情報のみを持つ.
  • 固有情報は専用テーブルに切り出す
    • 社会保険+税金に必要な情報は GovernmentPayment の専用テーブルを作成し、そちらに寄せる.銀行情報は BankAccountPaymentに寄せる.

このように設計することで、AccountPayable は決済や表示ロジックの中心としての役割を保ちつつ、中身の詳細は PaymentMethodHub に応じて適切なテーブル(今回は GovernmentPayment)を参照する形になりました.(*今回のリリースに加えると修正が広くなるので、リリース後対応となりました.2026年の年明けリリース予定)

下記にER図を書きます.一部のフィールドしか書いていませんが、大枠はこのような形です.

この方針をとったことで、今後さらに別の支払い方法が増えたとしても、AccountPayable にカラムを継ぎ足して巨大化させることなく、責務を分離したまま段階的に拡張できるようになりました. (※この方針は、CTO室とも議論を重ねて決定しました)

終わりに

いかがでしたでしょうか? 今回の「社会保険+税金」支払いは、INVOYにとって大きめの機能開発でしたが、PdMやデザイナー、CTO室とも密に会話しながら、エンジニアが仕様や設計に深く関わって進めることができました.

言われたものを作るだけでなく、ユーザー体験や将来の拡張性まで考えて開発できる環境があります.少しでも興味があれば、ぜひカジュアル面談からお話ししましょう!!

herp.careers

herp.careers