Ledger:Javaから台帳を壊さない
既存Ledger教材を統合せず、Javaサービスから見た台帳境界を学びます。Payment Serviceは仕訳を直接作らず、既存RPCを通じて業務処理と台帳を同じ原子操作へ保ちます。
Java / Spring Bootを入口に、金融システムのService・Repository・Transaction設計を読む。
先に学ぶ内容 — Prerequisite: ソフトウェア工学 / 銀行システム学ぶこと — LEARNING GOALS
このページで学ぶこと
- 業務APIとLedgerの責任分担
- 直接更新を避ける理由
- Javaモデルと会計記録を混同しない方法
体験17 · JAVA LEDGER(台帳を壊さない)
Javaの応答と、会計上の記帳は同時に起きるか確かめよう
まずは予想をひと言。本文を読んだ後、教材内の参照元で実際のJavaコードを確認します。
- 01まず予想する — PREDICT
まずここだけ:思ったことをひと言書く
Javaのプログラムが「振込完了」と応答したら、その時点で会計上の記録(仕訳)も必ず作られていると言えるでしょうか?
正解でなくて大丈夫です。「〜だと思う」から始めてみましょう。
ヒント1を見る
受付控えが発行されたことと、正式な帳簿に記帳されたことは、同じ意味でしょうか?
ヒント2を見る
JavaのMoney型は、金額を安全に扱えますが、それだけで会計の帳尻(借方=貸方)まで保証するでしょうか?
もっと詳しく:この問いで使う専門用語
- 業務状態は、依頼が受付・確認待ち・完了のどこにあるかを表します。
- Ledger境界は、正式な仕訳を作れる処理経路です。
- 会計不変条件は、どの処理でも破ってはいけない帳簿の規則です。
日常語で理解する — PLAIN LANGUAGE
まず、ここだけつかむ
JavaのPendingPaymentはOTP待ちの依頼であり、台帳への記帳完了を意味しません。
Payment ServiceはLedgerテーブルを直接更新せず、既存RPCの中で業務状態・残高・仕訳・監査を一緒に確定させます。
Moneyは金額の表現を守りますが、借貸一致やappend-onlyなどの会計不変条件はDB Ledger側が守ります。
順番に理解する — DIFFICULT PARTS, STEP BY STEP
難しいポイントを、順番にほどく
専門用語を覚えることより、「なぜ必要か」「このシステムのどこで使うか」を理解することが目標です。
業務状態
依頼が受付・確認待ち・完了のどこにあるかです。
会計記録が作られる前後を正しく区別するためです。
PendingPaymentはOTP確認待ちを表します。
Ledger境界
正式な仕訳を作れる処理経路です。
業務記録だけ、仕訳だけという片側確定を防ぐためです。
confirm_transfer_otp RPC内部で記帳します。
会計不変条件
どの処理でも破ってはいけない帳簿の規則です。
資金の根拠を完全に説明可能にするためです。
借貸一致やappend-onlyはDB側が守ります。
発展 — ADVANCEDもっと詳しく確認する最初の学習では読まなくても問題ありません。仕組みをもっと深く理解したい場合に開いてください。
PendingPaymentはLedgerではない
PendingPaymentはOTP確認待ちの振込依頼を表します。まだ資金移動の仕訳が確定したことを意味しません。
PaymentOtpConfirmationのoutcomeがcompletedになりtransferIdが返った時に、既存RPC内で業務記録とLedger記帳が完了したと理解します。APIの状態と会計事実を区別することが重要です。
| Javaモデル | 表す事実 | 表さないもの |
|---|---|---|
| PendingPayment | 振込依頼とOTP期限 | 完了した仕訳 |
| PaymentOtpConfirmation | OTP処理結果とtransfer状態 | 仕訳明細そのもの |
| Money | 正の整数円 | 借方・貸方の方向 |
仕訳をJavaから直接INSERTしない
振込の業務状態だけ更新して仕訳に失敗する、または仕訳だけ作って振込状態が残らない、という片側確定を避ける必要があります。
Payment Serviceはconfirm_transfer_otp()を1回呼び、PostgreSQL側で状態検査、資金移動、Ledger、監査を同じtransactionへまとめます。
JavaのMoneyが守る範囲
- float/doubleを使わず金額を正確に表す
- JPYの小数を拒否する
- 0以下と既存システム上限超過を拒否する
- 借貸一致、勘定科目、append-onlyはDB Ledger側が守る
- 残高不足と同時実行は更新地点のDB側が判断する
台帳を読むAPIを将来追加するなら
JavaのDTOへ仕訳を写すだけでは安全なLedger APIになりません。認可、勘定の意味、ページング、監査、情報公開範囲まで設計します。
- 01利用目的と閲覧権限を定義
- 02正式な台帳と表示用projectionを区別
- 03顧客へ公開してよい列を限定
- 04cursor paginationと安定した並び順を設計
- 05業務記録・残高cacheとの照合を継続
体験学習の続き · LEARNING LOOP
ここまで読めましたか?続けて確認してみましょう
Javaから見た台帳の境界を読んだところで、教材内の参照元で実際のJavaコードを確認し、自分の言葉で説明してみます。
- 02仕組みを確かめる — CONCEPT CHECK
画面操作なしで、仕組みを確かめる
この仕組みは、Mini Bankの画面には現れません。次のEvidenceとCode Trail、教材本文だけで理解を進めます。
- 03証拠を確認する — EVIDENCE
何を見たか、1つずつ確かめる
Evidence(判断の根拠となる記録)を確認したらチェックします。各項目の「何を見るか」を手がかりにしてください。
画面を開けない項目は、Source Trail(教材の参照元)と教材の説明で確認できます。失敗を実際に起こす必要はありません。
- 04コードの処理経路を追う — CODE TRAIL
コードを書く必要はありません
ここでは「説明されている仕組みが、実際のMini Bankのどこに実装されているか」を確認します。まずは日本語の役割説明を読み、入力した依頼がどこへ渡るかをつかみましょう。コードの全文を読む必要はありません。
まず依頼を表すモデルを見て、次にLedgerへの書き込み経路を見ます。会計記録がどこで作られるかを確かめましょう。
教材の参照元を確認する — Source Trail ↓OTP確認待ちの振込依頼を表すモデル。仕訳情報を持たないことを探します。
services/payment-service/src/main/java/com/minibank/payment/domain/PendingPayment.javaLedgerを直接操作せず、既存RPCを呼び出すだけの境界を探します。
services/payment-service/src/main/java/com/minibank/payment/repository/PaymentRpcGateway.java - 05自分の言葉で説明する — EXPLAIN
LEVEL 1 — やさしい説明(まずここだけ)
なぜJavaのモデル(PendingPaymentなど)は、それ自体が正式な会計記録にならないのでしょうか? 短い2文を目安に説明してください。
日常語だけで完了できます。専門用語の数や正誤を自動採点するものではありません。
ヒント1を見る
「業務状態」と「会計記録」という2つの言葉を使って書いてみましょう。
ヒント2を見る
PendingPaymentが表すものと、表さないものを分けて考えてみましょう。
もっと詳しく:LEVEL 2 — 専門用語を使った説明(任意)
業務状態、Ledger境界、会計不変条件の3つを使って、Javaが台帳を壊さないためにしていることを説明してみましょう。
挑戦する場合は、上の説明欄に追記できます。追加しなくても完了できます。
説明の確認ポイント — Checkpoint- 業務上の受付と会計上の記帳が別の事実だと説明できる
- 仕訳を作れる経路が既存RPCに限られていると説明できる
理解を確かめる — CHECK YOUR UNDERSTANDING
3問で理解チェック
答えを頭の中で考えてから、各項目を開いて確認してください。
Q1PendingPaymentが返れば仕訳も完成していますか?
いいえ。まだOTP確認待ちで、資金移動は確定していません。
Q2Moneyがあれば借貸一致も保証されますか?
いいえ。Moneyは金額値を守り、借貸一致はLedger側の別の制約です。
Q3Javaからjournal_linesへ直接保存してよいですか?
既存RPCの原子性や権限を迂回するため、現在の設計では行いません。
完全に暗記する必要はありません。大切な考え方を説明できそうなら押してください。
教材の参照元 — SOURCE TRAIL
根拠と関連教材
CURRENT IMPLEMENTATIONは確認したrepository内の実装です。HISTORICAL IMPLEMENTATIONは導入・修正の履歴で、後続migrationによる再定義があり得ます。RELATED LESSONは教材への案内で、実装の一次Sourceではありません。ASSUMPTIONは仮定、UNKNOWNは未確認を表します。
確認基点: d02eae8914f39cbf06bfe422dc39c71886f82b3e / 2026-09-11。稼働環境への適用確認: UNKNOWN。パス実在の自動検査と、記述した技術的事実の確認は別です。
- 現在の実装 — CURRENT IMPLEMENTATION
services/payment-service/src/main/java/com/minibank/payment/domain/PendingPayment.java記帳前の振込依頼を表すモデル - 現在の実装 — CURRENT IMPLEMENTATION
services/payment-service/src/main/java/com/minibank/payment/domain/PaymentOtpConfirmation.java振込実行結果を表すモデル - 現在の実装 — CURRENT IMPLEMENTATION
services/payment-service/src/main/java/com/minibank/payment/repository/PaymentRpcGateway.javaLedgerを直接操作しないRPC境界 - 過去の実装 — HISTORICAL IMPLEMENTATION
supabase/migrations/Ledger・残高・監査の正式実装