jonnify·codemojex /codemojex/commerce

Codemojex · chapter C6

The revenue ledger and the KeyShop.

Where C5 moves the players’ money, this chapter books the house’s. The RVL revenue ledger (cm.6) is the platform’s own account — a dedicated table of signed deltas with no non-negative CHECK — and the KeyShop (cm.7) is the multi-rail pay-in that feeds it. The law is conservation: every keys-unit a player is debited is a house credit or a pool conversion, and every rail’s external event lands exactly once.

Grounding — echo/…/codemojex/wallet.ex (house_post/5, house_balance/1, revenue_breakdown/1) · key_shop.ex · rails.ex · the revenue_ledger/package/order/order_transaction/webhook schemas · the revenue-ledger + keyshop stories.

One ledger, two sources — select a movement
Wallet.house_post mints RVL · touches no balance revenue_ledger RVL · signed delta no non-negative CHECK the buy-in cm.6 · currency = keys the purchase cm.7 · currency = the rail house_balance/1 Σ delta GROUP BY currency
the buy-in → a Golden-Room buy-in books its five house movements — the negative deposit_seed, the deposit_recovery and revenue credits, and the deposit_reclaim on a void — in keys, paired inside the same transaction as the player debit and the pool increment.
§1

The house’s own book

wallet.ex · house_post/5

The revenue_ledger is the deliberate inverse of players: a signed delta with no non-negative guard (the house legitimately swings negative on the seed debit), no exactly-once index (each post is a distinct accrual), and its uniqueness is the RVL primary key alone. Every platform movement funnels through one primitive — house_post/5 mints one RVL row and touches no balance column, so it never hits players_non_negative and needs no player lock. The balance is the sum of these rows.

echo/…/codemojex/wallet.ex · house_post/5 source
def house_post(account, currency, delta, reason, ref) do
  rid = EchoData.BrandedId.generate!("RVL")

  {:ok, _} =
    %RevenueLedger{}
    |> RevenueLedger.changeset(%{
      id: rid,
      account: account,        # "platform" — the sole account this rung
      currency: to_string(currency),
      delta: delta,            # SIGNED — negative on the deposit_seed debit
      reason: reason,
      ref: ref
    })
    |> Repo.insert()

  rid
end

The reconciliation reads never re-derive: house_balance/1 is a SUM(delta) GROUP BY currency over a table holding only platform movements — no player rows to exclude, the dedicated-table payoff — and revenue_breakdown/1 groups one game’s rows by reason. The conservation identity holds over three observable columns, explicitly not by a zero row-sum.

§2

The three dives

C6.1 · C6.2 · C6.3

The order is the money’s: first the house’s own book (C6.1), then the pay-in that feeds it (C6.2), then the outward rail the design points at but has not built (C6.3). Scoring stays linear throughout; this chapter is money, not points.

§3

The doors

out of this chapter
§4

References

sources · related

Sources

Related