HandyCafe Docs
owner

セッション料金設定

HandyCafeは、インターネットカフェやゲームセンターでのセッションコストを計算するためにセグメントベースの料金エンジンを使用しています。セッション全体に対して単一の固定料金を適用する代わりに、エンジンは各セッションをセグメントに分割し、それぞれに独自の料金コンテキストを持たせます。このアプローチにより、複数の時間帯にまたがるセッションや料金変更、一時停止、切断が発生した場合でも正確な請求が可能です。

基本概念

詳細に入る前に、以下の重要な用語を確認してください。

用語 定義
基本時間料金 乗数が適用される前の1時間あたりの価格。設定 > 料金で設定します。
料金スロット 特定の乗数を持つ名前付きの時間帯。8つのスロットがあり、それぞれ色分けされています。
乗数 基本料金に適用される係数。1.0 = 標準価格、0.5 = 半額、2.0 = 倍額。
セグメント セッション内で料金コンテキスト(スロット、乗数、基本価格)が変わらない連続した期間。
精算 セッション終了時に顧客が支払うべき金額を決定する最終計算。

基本時間料金

基本時間料金は、すべての料金計算の基礎です。設定 > 料金で設定され、PC使用の標準1時間あたりの価格を表します。

すべての内部計算は小額通貨単位(例:USDのセント、TRYのクルシュ)を使用します。基本料金が1時間あたり$3.00の場合、内部値は300です。これにより浮動小数点の丸め誤差が排除されます。

二重通貨サポート

HandyCafeは、基本通貨と現地通貨を為替(FX)レートでサポートしています。国際価格が現地価格と異なる国で運営している場合:

  • 基本通貨。 内部料金計算に使用される通貨。
  • 現地通貨。 顧客に表示され、支払いに使用される通貨。
  • FXレート。 基本通貨と現地通貨間の換算係数。

両通貨が同じ場合、FXレートは1.0として扱われ、影響を与えません。

料金スロット

8つの色分けされた料金スロットがあり、それぞれ異なる料金階層を表します。

スロット 一般的な用途
Blue 標準料金
Orange オレンジ 夕方または週末の追加料金
Red ピーク時間のプレミアム
Green 非ピーク割引
Teal ティール 学生または会員料金
Gray グレー 休日または特別料金
Cyan シアン ナイト料金
Emerald エメラルド プロモーション料金

各スロットには3つのプロパティがあります。

  1. 名前。 説明的なラベル(例:「ピーク時間」または「ナイト割引」)。
  2. 乗数。 基本料金を修正する小数値。一般的な値には1.0(標準)、0.5(半額)、1.5(50%追加料金)、2.0(倍額)が含まれます。乗数はゼロまたは正でなければなりません。
  3. スケジュールデータ。 スロットが適用される曜日と時間を定義する内部表現。スケジュールグリッドを通じて自動的に管理されます。

スロットは個別に有効または無効にできます。無効なスロットは料金エンジンによって無視されます。

スケジュールグリッド

料金スケジュールは、7日間×24時間のマトリックス(合計168の1時間ブロック)です。各ブロックは1つの料金スロットに割り当てられます。スケジュールは、任意の時点でどの乗数が適用されるかを決定します。

グリッドは設定 > 料金スケジュールで設定されます。曜日は月曜日から日曜日まで、時間は00:00から23:00までです。時間ブロックにスロットを割り当てるには、グリッド内のブロックを選択し、希望のスロット色を選びます。

エンジンのスケジュール読み取り方法

内部的には、各時間ブロックがスケジュールデータ内の位置にマッピングされます。エンジンは、任意の曜日と時間にどのスロットがアクティブであるかを決定するために、各有効スロットのスケジュールデータをチェックします。

特定の時間にスロットが設定されていない場合、エンジンは基本料金に乗数1.0を適用します。

料金スケジュール機能が完全に無効にされている場合(設定 > 料金)、すべてのセッションは時間に関係なく基本料金と1.0の乗数を使用します。

料金セグメント

セグメントは、料金コンテキストが変わらないセッション内の連続した時間期間です。料金エンジンは、以下の境界イベントが発生するたびに新しいセグメントを作成します。

境界 トリガー
session_start 新しいセッションが始まる
session_stop セッションが停止される
pause キャッシャーがセッションを一時停止する
resume キャッシャーが一時停止されたセッションを再開する
tick 時計が異なる料金スロットに入る時間境界を越える
disconnect クライアントPCがネットワーク接続を失う
offline クライアントPCがオフラインになる
load_recovery サーバーが再起動し、実行中のセッションを回復する

各セグメントは以下を記録します。

フィールド 説明
session_id このセグメントが属するセッション
segment_start セグメントが開始したUnixタイムスタンプ
segment_end セグメントが終了したUnixタイムスタンプ(まだ開いている場合はnull)
pricing_slot_id アクティブな料金スロットのID(例:「blue」、「red」、または「base」)
multiplier 料金スロットからの乗数値
base_price_snapshot セグメントが開いた瞬間にキャプチャされた基本時間料金
amount このセグメントの計算されたコスト(セグメントが閉じたときに設定)
boundary_reason このセグメントが作成された理由

基本料金をスナップショットする理由

base_price_snapshotは、セグメントが開いた瞬間の基本時間料金をキャプチャします。これは、管理者がセッション中に基本料金を変更する可能性があるため重要です。スナップショットを取ることで、各セグメントは開始時に有効だった料金を使用し、公正で監査可能な請求を保証します。

コスト計算式

単一のセグメントのコストは次のように計算されます。

amount = ceil( (base_price_snapshot * multiplier * duration_seconds) / 3600 )

より正確には、エンジンは浮動小数点エラーを避けるためにスケーリングされた整数演算を使用します。

  1. 乗数は固定小数点整数にスケーリングされます(1,000,000倍)。
  2. 計算は128ビット整数で完全に行われます。
  3. 天井除算が使用されます。結果は常に次の小額単位に切り上げられます。

分単位での計算

設定 > 料金で「分単位で計算」オプションが有効になっている場合、式はわずかに変更されます。

amount = ceil( (base_price_snapshot * multiplier * used_minutes) / 60 )

ここでused_minutes = ceil(duration_seconds / 60)です。これは、部分的な分が完全な分としてカウントされることを意味します。

セッション合計計算

セッションの合計コストは3つのステップで計算されます。

ステップ1: すべてのセグメントを合計

raw_total = sum of all closed segment amounts + open segment partial amount

オープンセグメントの部分的な金額は、現在のタイムスタンプをセグメント終了として使用してリアルタイムで計算されます。

ステップ2: 丸めを適用

rounded_total = round_up(raw_total, rounding_step)

丸めは常に(天井)に行われ、収益を保護します。丸めのステップは設定 > 料金で設定可能です。例えば、丸めのステップが50(2桁の小数を持つ通貨で$0.50を表す)である場合、$3.27の生合計は$3.50に切り上げられます。

ステップ3: スタートアップ料金の最低額を適用

final_total = max(rounded_total, startup_fee)

スタートアップ料金は、セッションの長さに関係なく、任意のセッションに対する最低料金です。丸められた合計がスタートアップ料金よりも少ない場合、代わりにスタートアップ料金が請求されます。

精算

精算は、セッションの請求を最終確定するプロセスです。精算には2つの段階があります。

スタート精算(プリペイドのみ)

プリペイドセッションが始まると、「スタート」精算記録が作成されます。これには以下が含まれます。

  • 計算されたコスト。 購入した時間に対するシステム計算コスト。
  • 請求額。 顧客が実際に支払った金額(通常は計算されたコストと同じ)。

「購入時にロック」プリペイドモードでは、このロックされた金額がセッション中の料金変更に関係なくセッションのコストを決定します。

ストップ精算

任意のセッション(プリペイドまたはポストペイド)が停止されると、「ストップ」精算記録が作成されます。

フィールド 説明
計算されたコスト すべての料金セグメントからのシステム計算合計
請求額 実際に請求された金額(デフォルトは計算されたコスト)
手動調整額 キャッシャーが価格を手動で調整した場合、元の計算されたコストがここに保存されます
手数料率 支払い方法の手数料率(パーセンテージとして)
手数料 計算された手数料額
固定手数料 支払い方法の固定手数料
計算されたタイムラインスナップショット セッション内のすべての料金セグメントのJSON記録

タイムラインスナップショットは、セグメントごとにコストがどのように計算されたかを示す完全な監査証跡を提供します。

支払い方法手数料

各支払い方法には2種類の手数料があります。

手数料(ベーシスポイント)

手数料率はパーセンテージとして表されます。手数料は、この率を請求額に適用して計算されます。

例: 請求額が$10.00(1000小額単位)で、支払い方法に2.5%の手数料率がある場合、手数料は$0.25(25小額単位)です。

固定手数料

金額に関係なく、取引ごとに差し引かれる固定手数料。例えば、クレジットカード処理手数料の$0.30。

両方の手数料は情報提供用です。それらはその支払い方法を受け入れることによるビジネスのコストを表します。精算に記録されますが、顧客の請求書には追加されません。

VAT(付加価値税)

VATは、設定 > 料金でパーセンテージ(0~100%)として設定されます。計算されたセッション金額に上乗せされます。

VAT = 請求額 x (VAT率 / 100)

VAT金額は支払いダイアログに別途表示され、キャッシャーが税金の内訳を確認できます。

プリペイド料金モード

セッション管理で説明されているように、プリペイドセッションは2つの料金モードをサポートしています。

購入時にロック

プリペイドセッションが開始されると、「スタート」精算が請求額をロックします。セッションの期間中:

  • 購入した分数に基づいてセッション終了時間が固定されます。
  • 料金スケジュールが変更されても、ロックされた時間が切れるまでセッションは続行されます。
  • ストップ精算はスタート精算からのロックされた金額を使用します。

ライブスケジュール

料金スロットが変更されると、セッションの残り時間が継続的に再計算されます。

  • セッションがより安いスロットに入ると、残り時間が伸びます(顧客はお金に対してより多くの分数を得ます)。
  • セッションがより高価なスロットに入ると、残り時間が短縮されます。
  • ストップ精算は、セッション全体で適用された実際の料金を反映します。

小数桁数

通貨表示に使用される小数桁数は設定可能です(2~4桁)。これはUIでの金額表示に影響しますが、内部の小額単位計算は変更されません。

例: 小数桁数が2の場合、$3.50は「3.50」と表示されます。小数桁数が3の場合、「3.500」と表示されます。

実用例

例1: シンプルなポストペイドセッション

  • 基本料金: $3.00/時間(300小額単位)
  • スケジュール: 一日中標準スロット(乗数1.0)
  • セッション: 10:00 AMから11:30 AM(90分)
  • スタートアップ料金: $0.50

計算:

セグメント1: (300 * 1.0 * 5400) / 3600 = 450小額単位 ($4.50)
合計: max($4.50, $0.50) = $4.50

例2: 2つのスロットにまたがるセッション

  • 基本料金: $4.00/時間(400小額単位)
  • スケジュール: 10:00--12:00は標準(1.0)、12:00--14:00はハッピーアワー(0.5)
  • セッション: 11:00 AMから1:00 PM(120分)
  • スタートアップ料金: $1.00

計算:

セグメント1 (11:00-12:00, 標準): (400 * 1.0 * 3600) / 3600 = 400 ($4.00)
セグメント2 (12:00-13:00, ハッピーアワー): (400 * 0.5 * 3600) / 3600 = 200 ($2.00)
合計: $4.00 + $2.00 = $6.00
最終: max($6.00, $1.00) = $6.00

例3: 一時停止を含むセッション

  • 基本料金: $2.00/時間(200小額単位)
  • スケジュール: 一日中標準スロット(乗数1.0)
  • セッション: 開始10:00、一時停止10:30、再開11:00、停止11:45
  • スタートアップ料金: $0.50

計算:

セグメント1 (10:00-10:30, アクティブ): (200 * 1.0 * 1800) / 3600 = 100 ($1.00)
一時停止期間 (10:30-11:00): 無料
セグメント2 (11:00-11:45, アクティブ): (200 * 1.0 * 2700) / 3600 = 150 ($1.50)
合計: $1.00 + $1.50 = $2.50
最終: max($2.50, $0.50) = $2.50

次のステップ