Skip to main content

Tasks — Player → Shop/Cashier (Phase 3)

Spec: player-to-shop-cashier · Mockup: Redemptions tab

Dependencies: Phase 2 deposit (schema + shop cash-transactions API foundation); Cashier redeem + approval (Cashier spec).


Business summary

When Shop redeems Player credits, Shop pays Player cash at the counter.

Player requests credit withdrawal
→ Shop/Cashier confirms
→ Debits Player credits, credits Shop (CDN wallet)
→ Shop pays cash to Player
→ Cash ledger (Cash Out) + reporting

Two required values when operating:

FieldMeaningExample
Credits to redeemCredits debited from Player wallet30 credits
Cash paid to PlayerCash Shop pays directly to Player$30.00

V1: usually 1:1 (30 credits → $30.00), but Shop enters both so the system clearly records credits recovered and cash paid. Ledger and reporting use cash paid to Player for Cash Out — not inferred from credits.

V1 scope: Redemption only. Auto-settled when completed; pending approval does not create cash tx.


Who does what

RoleAction
PlayerRequests withdrawal; present at counter
Shop ManagerEnters credits to redeem + cash paid to Player; confirms redeem from Shop portal
CashierEnters credits to redeem + cash paid to Player; pays cash after completed (or after Manager approval)
SystemDebits player wallet, credits shop wallet, writes cash_transactions, updates shift Cash Out

Two execution channels

ChannelAPINotes
Shop portalPOST /shop/players/:id/credits (action: deduct)Shift not required
Cashier portalPOST /cashier/players/:id/redeemActive shift; cash only

Both channels must collect credits to redeem and cash paid; after successful wallet transfer → create cash_transactions flow shop_player_redemption.


Phase 1 — Schema

#TaskNotes
1.1Flow shop_player_redemptionIf not shipped with Phase 2 migration
1.2Optional metadata.approvalIdLink approval record (Cashier path)
1.3Doc schema-cash-transactionscredit_amountcash_received when needed

Phase 2 — Backend biz (redemption only)

#TaskNotes
2.1createCounterRedemptionCashTransactionseller=player, buyer=shop
2.2Payload: credit_amount + cash_paid (cash_received)Both required, > 0
2.3expected_cash = cash_paidCash Shop pays out
2.4Hook after _adjustCreditsDeductOnly when wallet transfer completed
2.5Do not hook from pending_approvalOnly after approve + transfer
2.6Shop portal action: deductValidate + pass cash_paid to ledger
2.7Cashier redeemCreditsBody adds cash_paid; cashDelta = −cash_paid
2.8Wire after cashierRedemptionApprovalBizService approveApproval uses saved cash_paid
2.9Idempotency by reqIdAvoid duplicate cash tx
2.10Unit testsHappy path; insufficient balance; pending→approve; cash ≠ credit (if allowed)

Main files: cashTransactionBizService.js, shopPlayerBizService.js, cashierTransactionBizService.js, cashierRedemptionApprovalBizService.js

Ledger (cash_transactions):

FieldValue
flowshop_player_redemption
sellerplayer / player uuid
buyershop / shop uuid
credit_amountCredits to redeem
expected_cash / cash_receivedCash paid to Player
statuspaid_full (auto on completed)

Links: payment_transaction_id, wallet txs, cashier_transaction_id, shift_id, metadata.approvalId.


Phase 3 — Shop portal API (redemption filter)

#TaskNotes
3.1GET /api/shop/cash-transactions?flow=shop_player_redemptionList redemptions
3.2Detail shows credit + cash paid + approval context
3.3Summary: Cash Out (SUM cash_received), pending approval countAggregate full filter, not page only
3.4Export CSVColumns credit redeem + cash paid

Extend shopCashSettlementController — currently only filters shop_player_deposit.


Phase 4 — Shop portal UI

#TaskNotes
4.1Tab Payable — RedemptionsMockup phase2 redeem tab
4.2Player redeem modal: 2 input fields — credits to redeem + cash paid to PlayerPre-fill cash = credit (1:1); Shop may edit
4.3Review step shows both credit and cash before confirm
4.4Summary card Cash Out (today / filter)From ledger cash_received
4.5Table: player, credits redeemed, cash paid, cashier/actor, statusSettled / Pending approval
4.6Badge Pending approval vs Settled
4.7Combined dashboard: Cash In (P2) + Cash Out (P3) = NetOptional after both tabs

Phase 5 — Cashier / Shift

#TaskNotes
5.1Cashier redeem form: credit + cash paidSame as Shop portal
5.2Redemption completed → shift Cash Out = cash_paidDo not use credit amount for cashDelta
5.3Pending approval: cashDelta = 0Cash not yet paid
5.4Cashier tx list shows CTX-* after settleRead-only; show cash paid
5.5Integration test Expected Closing CashCash Out matches total redemptions

Phase 6 — Reporting

#TaskNotes
6.1Shop portal Redemptions tab summaryCash Out aggregate
6.2Export CSV redemptioncredit_amount, cash_received, player, date
6.3Shift reconciliation reportCash Out from redemption uses cash_paid
6.4Admin / Shop cash-transaction detailView-only; link payment + wallet txs

Phase 7 — QA (redemption)

#ScenarioExpected
7.1Shop redeem 30 credits, pay $30 cashcash tx: credit=30, cash_received=30; wallet −30/+30
7.2Shop redeem 30 credits, pay $28 cash (if allowed)cash tx cash_received=28; shift cashDelta −28
7.3Cashier redeem pending approvalNo cash tx; cashDelta = 0
7.4Approve → completecash tx created once with saved cash_paid
7.5Insufficient player balance400; no cash tx
7.6Shop manual deduct missing cash_paid400 validation
7.7Idempotent retry same reqIdSingle cash tx only

Implementation order

Phase 2 deposit done
→ Schema redemption (1)
→ Biz hook + cash_paid payload (2)
→ Shop API redemption filter (3)
→ UI: 2-field modal + Redemptions tab (4)
→ Cashier cash_paid + shift (5)
→ Reporting (6)
→ QA (7)

Current status (baseline)

ComponentStatus
Wallet transfer player → shop
Cashier redeem + approval + cashDelta (1 field)✅ — needs cash_paid added
Shop portal manual deduct (1 field)✅ — needs cash_paid added
cash_transactions flow shop_player_redemption
Shop portal redemption ledger + Cash Out reporting