課金履歴機能(Billing Record)

組織ごと・月別の課金情報(契約プランに基づく自動計算値と、手動上書き値)を 履歴レコードとして残し、システム管理画面から確認・再計算・編集できるようにする機能。

システム管理画面 権限: システム管理者のみ 自動生成バッチ(API Route)は別セッション

概要

課金履歴は、組織1つ・年月1つにつき1レコードを持つ課金記録である。これまで「定義」のみだった 契約プランと、生成数の SoT である 生成ログを突き合わせ、 実際の請求額を算出・保存する最初の機能である。

各レコードは、計算時点のプラン内容のスナップショット(プラン名・月額・上限・超過課金)と、 計算対象となった画像生成数を保持する。プランが後から変更・削除されても、レコードは凍結された値を持ち続ける(履歴性)。 さらに、初月の日割りなど例外的な調整に備え、すべての計算量に手動入力用フィールドを持ち、 値が入っていれば自動計算値より優先される(NULL のときは自動計算値を使用)。

後払い(超過分は前月実績)モデル

(Y年 M月) のレコードは、 M月分の基本月額と、M-1月の生成実績に対する超過課金を合算する。 したがって「計算対象画像生成数」は前月(M-1)の生成数を指す。 詳しくは 用語: 課金履歴

データモデル

BillingRecordprisma/schema/billing-record.prisma / テーブル billing_records)。 論理削除(deletedAt)運用のため DB のユニーク制約は設けない(削除済み行とのタプル衝突を避けるため)。組織×年月の一意性はアプリ側で担保する。

フィールド 区分 説明
idStringcuid(2)
organizationIdString組織
contractPlanIdString?スナップショット計算時のプランID(未割当なら null)
contractPlanNameString?スナップショットプラン名
yearInt対象年(基本月額の月)
monthInt対象月 1-12(基本月額の月)
amountInt永続化課金合計額(実効値ベース。生成・再計算・編集の各経路で更新)
monthlyChargeInt自動(プラン)課金額/月
monthlyGenerationQuota1〜3Int自動(プラン)月間生成数上限(区分1〜3)
extraGenerationCharge1〜3Int自動(プラン)超過生成分課金額(区分1〜3)
targetGenerationCount1〜3Int自動(実測)計算対象画像生成数(前月実績・区分1〜3)
manualMonthlyChargeInt?手動課金額/月(NULL=自動値)
manualMonthlyGenerationQuota1〜3Int?手動月間生成数上限(NULL=自動値)
manualExtraGenerationCharge1〜3Int?手動超過生成分課金額(NULL=自動値)
manualTargetGenerationCount1〜3Int?手動計算対象画像生成数(NULL=実測値)
noteString?備考(手動入力で更新する場合は必須)
createdAt / updatedAt / deletedAtDateTime既存規約に倣う(deletedAt でソフトデリート)

凡例:緑=自動計算値 橙=手動上書き(NULL のとき自動値を使用)。 実効値はすべて 手動 ?? 自動 で解決する。

計算ロジック

レコード (Y年 M月) の課金合計額:

計算対象画像生成数k = 区分k の生成ログ件数(createdAt が 前月 M-1 に入るもの)

超過生成数k = max(0, 実効(計算対象生成数k) − 実効(上限k))

区分k 超過課金額 = 超過生成数k × 実効(超過課金k)

課金合計額 = 実効(月額) + Σ(区分1〜3 超過課金額)  (k = 1, 2, 3)

関連する画面(システム管理画面)

/billing-records — 一覧画面

  • 絞り込み(URLクエリ):年月(複数選択 YYYYMM)・組織(複数選択 組織ID)
  • 並べ替え:年月降順(UI不要)
  • リスト項目:年月 / 組織名 / 課金額(=課金合計額。基本+超過、実効値ベース)

/billing-records/[billingRecordId] — 詳細画面

  • 課金合計金額の内訳:基本月額(M月分)+ 区分1〜3 の超過課金(M-1月分 = 超過生成数 × 超過課金額)
  • 再計算ボタン:組織の現在の contractPlanId から自動値を取り直し、実測生成数を再集計。 手動入力フィールドはすべて破棄(NULL リセット)される(実行前に確認ダイアログ)。
  • 編集ボタン:手動入力用フィールド(計10個)を上書き。初月の日割りなどの例外調整に使う。

/billing-records/[billingRecordId]/edit — 編集画面

手動入力用フィールド(課金額・上限1〜3・超過課金1〜3・計算対象生成数1〜3)を編集。空欄=自動値を使用。

スコープと未実装

項目本機能(初回セッション)
DBスキーマ(BillingRecord)
一覧/詳細/編集画面
課金計算ロジック(共有関数)・再計算アクション
レコードの一括生成 API Route(POST /api/billing-records/generate✅ 追加(対象月の未生成組織にレコードを一括作成)
登録カードへの実際の課金(請求)実行❌ 未実装(決済機能参照)

※ 一括生成 API Route(POST /api/billing-records/generate):リクエストボディで year/month(省略時は現在の Asia/Tokyo の年月)・organizationIds(省略時は対象組織全件)を受け取り、 対象月のレコードが未生成の組織に対してのみレコードを作成する。プラン未割当の組織はスキップ。外部スケジューラからの定期実行を想定。

対象組織の条件organizationIds 省略時): ① activatedAt < 対象月初日(対象月開始前に有効化済み)、かつ ② deactivatedAt IS NULL または deactivatedAt > 対象月初日(対象月初日時点で解約済みでない)。 対象月中に解約した組織(deactivatedAt が対象月内)は含まれる。

関連

開発セッション履歴