銀行エンジニアリング 37:グループと entity(別々の元帳・別々の権限)
銀行がいくつかの法人に分かれているとき、法人ごとに帳簿と権限を分ける理由と、MiniBankが既存の銀行の元帳を変えずにそれを実現した設計を学びます。
v8以降に実装した台帳・記帳エンジンなどを実際に動かし、正常時と異常時の両方から銀行システムの構造を学ぶ。
Prerequisite: BANKING SYSTEMLEARNING GOALS
このページで学ぶこと
- entity(法人)ごとに元帳を分ける理由
- 既存の表に entity_id を足さなかった判断
- entity の役割と越境の拒否
PLAIN LANGUAGE
まず、ここだけつかむ
法人(entity)ごとに、別々の元帳と別々の役割を持たせます。
既存の銀行の表には entity_id を足さず、追加の entity は独立した元帳を持ちます。既存の数字を守るための選択です。
役割のない管理者は何もできず、別の entity は見えません(GR002)。
DIFFICULT PARTS, STEP BY STEP
難しいポイントを、順番にほどく
専門用語を覚えることより、「なぜ必要か」「このシステムのどこで使うか」を理解することが目標です。
entity
グループを構成する、1つの法人です。
法人ごとに帳簿と責任を分けるためです。
bankgroup.entities。MINIBANK(基準)、WEST、TRUST。
基準 entity
既存の銀行そのものです。
既存の元帳を変えずに、グループへ参加させるためです。
Posting Engine と GL がそのまま元帳。
越境の拒否
役割のない entity を扱えないことです。
法人間の情報と権限を分けるためです。
GR002。取消しは次の呼び出しから効く。
Level 1 基礎:法人が違えば、帳簿も責任者も違う
銀行グループでは、銀行・信託・証券などが別々の法人です。法人ごとに帳簿を持ち、それぞれの責任者が確定します。1つの帳簿に全部を混ぜると、どの法人がいくら持っているのかが分からなくなります。
MiniBankの架空のグループには、既存の銀行そのものである MINIBANK(基準)と、追加の WEST・TRUST があります。
Level 2 銀行業務:権限は entity ごと
- 役割の取消しは、次の呼び出しから効く
- 移動を受け取れるのは受け手の責任者だけで、送り手の役割では受け取れない
| 役割 | できること |
|---|---|
| グループ管理者(admin_manager) | entity の登録・停止・再開、役割の付与、連結、未確定の移動の解消。全 entity を扱える |
| ENTITY_MANAGER(責任者) | 自分の entity の参照・移動の送信、手仕訳・資本金・仕訳の取消し・受取り・スナップショットの確定 |
| ENTITY_OPERATOR(担当者) | 自分の entity の参照・移動の送信だけ(手仕訳はできない) |
| 役割のない operator | 何もできない(別の entity は GR002) |
Level 3 システム:MiniBankでの実装
- 既存の金融表(ledger.*、bank_accounts など)には entity_id を追加していない。追加すると、試算表・整合性チェック・締め・復旧の検証など、元帳全体を集計する関数のすべてが、黙って別 entity の残高を混ぜる恐れがあるため
- 基準 entity(MINIBANK)は既存の Posting Engine と GL がそのまま元帳。追加の entity は bankgroup スキーマの独立した元帳(仕訳・明細・勘定表)を持つ
- 仕訳は追記専用で、借方合計=貸方合計。1つの仕訳は1つの entity の科目だけを使い、訂正は逆仕訳(元の仕訳は残る)
- bankgroup の表と関数は全ロールに非公開で、入口は public.admin_group だけ。入口で役割を確認する(bankgroup.require_entity)
異常時:ある担当者が別の entity の数字を見ようとした
| 段階 | 内容 |
|---|---|
| 症状 | GR002 が返る |
| 確認1 | その管理者に、その entity の役割が付与されているか(取消し済みではないか) |
| 確認2 | entity が停止中ではないか(GR003) |
| 確認3 | admin_manager でなく operator の場合、役割がなければ何もできないのが仕様 |
Level 4 アーキテクチャ:列を足さない選択
『全部の表に entity_id を足す』のが一見自然ですが、それは全集計関数を書き換える大工事で、1つ漏れると資金の数字が狂います。MiniBankは既存の数字を守ることを優先し、別の元帳を並べる形にしました。代わりに、基準 entity の試算表を bankgroup 側の読取り口で読み、gl.trial_balance() と完全に一致することをテストで固定しています。
この選択の限界(追加の entity は集計レベルの元帳で、顧客口座や契約は持たないこと)は契約書に明記しています。
どこを確認すればよいか
- 管理画面『グループ・連結』:entity 一覧、あなたの役割、試算表と仕訳
- テスト:scripts/banking/v19-group.test.mjs(越境・役割の取消し・停止)
CHECK YOUR UNDERSTANDING
3問で理解チェック
答えを頭の中で考えてから、各項目を開いて確認してください。
Q1既存の表に entity_id を足さなかったのはなぜですか?
元帳全体を集計する関数が、黙って別 entity の残高を混ぜる恐れがあるからです。
Q2役割のない operator は何ができますか?
グループ内の操作は何もできません。
Q3基準 entity を bankgroup に手仕訳できますか?
できません。既存の Posting Engine が唯一の入口です。
完全に暗記する必要はありません。大切な考え方を説明できそうなら押してください。
SOURCE TRAIL
根拠と関連教材
CURRENT IMPLEMENTATIONは確認したrepository内の実装です。HISTORICAL IMPLEMENTATIONは導入・修正の履歴で、後続migrationによる再定義があり得ます。RELATED LESSONは教材への案内で、実装の一次Sourceではありません。ASSUMPTIONは仮定、UNKNOWNは未確認を表します。
確認基点: d02eae8914f39cbf06bfe422dc39c71886f82b3e / 2026-09-11。稼働環境への適用確認: UNKNOWN。パス実在の自動検査と、記述した技術的事実の確認は別です。
Implementation Status: IMPLEMENTED IN MINIBANK(この教材が扱うコードの範囲)
- RELATED LESSON/docs/be-ledger-foundation台帳と複式簿記
- CURRENT IMPLEMENTATION
supabase/migrations/20260930150000_v19_group.sqlbankgroup.require_entityentity ごとの役割の確認。越境は GR002、停止中の entity は GR003。役割の取消しは次の呼び出しから効く - CURRENT IMPLEMENTATION
supabase/migrations/20260930150000_v19_group.sqlbankgroup.postentity の元帳の仕訳。1つの仕訳は1つの entity の科目だけ、借方合計=貸方合計、訂正は逆仕訳 - CURRENT IMPLEMENTATION
scripts/banking/v19-group.test.mjs権限の分離・2段階の移動・片側だけ確定した場合・停止・照合・連結と元帳の不変のDBテスト