Shop/Cashier → Player (Counter Deposit)
Phase 2 in the Cash Settlement chain — after Phase 1 hierarchy (Admin → SA → Agent → Shop).
Player pays cash at the counter → Shop/Cashier confirms → credits added to player wallet, shop CDN wallet debited accordingly.
Player pays cash → Cashier/Shop confirms → credits to Player → reconciliation ledger (Cash In)
Redemption flow (Player exchanges credits for cash) is a separate Phase 3: Player → Shop/Cashier.
Mockup: Phase 2 — Deposits tab · Cashier spec: Cashier Management spec
Position in the system
flowchart LR
subgraph P1["Phase 1"]
AG[Agent] --> SH[Shop CDN wallet]
end
subgraph P2["Phase 2"]
SH --> P[Player wallet]
end
subgraph P3["Phase 3"]
P --> SH2[Shop — redemption]
end
P1 --> P2
P2 -.-> P3
Shop must have sufficient credit in CDN wallet (from Phase 1 Agent→Shop) before issuing credits to Player.
Unlike Phase 1 hierarchy: counter deposit is auto-settled on complete — cash and credits move simultaneously; V1 has no temporary receivables.
Who does what
| Role | Action |
|---|---|
| Player | Pays cash at counter; receives credits after Cashier/Shop confirms |
| Cashier | Find player, enter amount/credits, confirm deposit (cash only, within active shift) |
| Shop Manager | May manually add credit from Shop portal (cash / card / bank transfer) |
| System | Debits shop CDN wallet, credits player wallet, writes audit, updates shift Cash In |
Two execution channels
| Channel | Role | Conditions | API |
|---|---|---|---|
| Cashier portal | Counter cashier | Active shift required; cash only | POST /cashier/players/:id/deposit |
| Shop portal | Shop Manager | Shift not required | POST /shop/players/:id/credits (action: add) |
Cashier path writes cashier_transactions (shift reconciliation). Shop Manager path writes shop_action_logs. Both do not yet write cash_transactions ledger (Phase 2 target).
Required information
Cashier portal (V1)
| Field | Required | Description |
|---|---|---|
| Player | ✅ | Player belonging to shop |
| Credits / amount | ✅ | V1: 1:1 — 50 credits = $50 cash |
| Method | ✅ (fixed) | cash |
| Shift / Cashier / Device | ✅ (system) | Auto-attached from session + active shift |
Shop portal (manual add)
| Field | Required | Description |
|---|---|---|
| Player | ✅ | Player belonging to shop |
| Credits | ✅ | Positive number, > 0 |
| payment_method | ✅ | cash | card | bank transfer |
| action | ✅ | add |
Amount & margin formulas
V1 counter deposit: 1 credit = $1 USD (face value for Player).
| Metric | Formula |
|---|---|
| Cash received (expected) | credit_amount |
| Shop CDN cost | credit_amount × shop.costRate (snapshot) |
| Shop gross margin | credit_amount × (1 − shop.costRate) — reporting metadata |
Example: cost rate 0.80, deposit 50 credits:
| Item | Value |
|---|---|
| Cash received | $50.00 |
| Shop CDN cost | $40.00 |
| Gross margin | $10.00 |
| Shop CDN wallet | −50 |
| Player wallet | +50 |
Counter deposit always debits the current shop wallet —
effectiveLevelis reporting snapshot only.
Business rules
- Player belongs to shop, not banned.
- Shop has sufficient credit in CDN wallet.
- Cashier: active shift required; no OTP.
- After complete: no edit / cancel / reverse.
cashDelta = +amount(cash) → Cash In in shift.
Proposed ledger (cash_transactions)
| Field | Value |
|---|---|
| flow | shop_player_deposit |
| seller | shop / shop uuid |
| buyer | player / player uuid |
| expected_cash | = credit_amount (1:1 V1) |
| status | paid_full (auto) |
Links: payment_transaction_id, wallet txs, cashier_transaction_id (cashier path), shift_id.
Current backend
Cashier: cashierTransactionBizService.depositCredits
→ playerCreditPort.transferCreditsAtCounter (deposit)
→ shopPlayerBizService._adjustCreditsAdd
→ walletTransferService (shop → player)
→ PaymentTransaction (provider: shop_player_cash)
→ CashierTransaction (type: deposit_credits)
Shop: shopPlayerBizService.adjustPlayerCredits (action: add)
→ same _adjustCreditsAdd (not via shift)
API
Existing
| Method | Endpoint | Body |
|---|---|---|
POST | /api/cashier/players/:id/deposit | { "amount": number } |
POST | /api/shop/players/:id/credits | { "action": "add", "amount": N, "payment_method": "cash" } |
Phase 2 target
| Method | Endpoint | Description |
|---|---|---|
GET | /api/shop/cash-transactions?flow=shop_player_deposit | List deposits |
GET | /api/shop/cash-transactions/:id | Detail |
GET | /api/shop/cash-transactions/export | CSV |
Proposed UI (Shop portal)
Tab Receivable — Deposits on mockup phase2-counter:
- Summary: Counter Cash In, Gross margin (today)
- Table: player, cashier, credits, cash received, margin, receipt
- Detail view-only
Cashier portal: transactions live in Active Shift — no separate ledger needed for V1.
Current status
| Component | Status |
|---|---|
| Wallet transfer shop → player | ✅ |
payment_transactions + cashier_transactions | ✅ |
cash_transactions flow shop_player_deposit | ❌ |
| Shop portal deposit ledger | ❌ |
Tasks: tasks-shop-cashier-to-player
Related
- Phase 1: Agent → Shop
- Phase 3: Player → Shop/Cashier (Redemption)
- Schema: schema-cash-transactions