Skip to content

Module Overview — Wallet Transaction Request / Commission

1. Scope

Feature này không nằm gọn trong một frontend module riêng. Nó cắt qua:

  • frontend ecommerce cho request lifecycle và withdraw approval,
  • frontend user cho wallet summary, withdraw history, employee commission ledger,
  • frontend affiliate cho payout/commission mutate,
  • frontend settings cho approver config và commission/payment config,
  • backend wallet-api cho action/event engine,
  • backend ecommerce-api cho upstream creator của commission và refund side effects,
  • Hasura metadata và migrations của DB wallet.

Điểm cốt lõi cần nhớ:

  • transaction_request là engine trung tâm,
  • transaction_request_user là các leg sender/receiver,
  • transaction chỉ được materialize khi request đi tới S,
  • commission, refund, payout và topup đều chỉ là các family behavior_id chạy trên cùng engine đó.

2. Bức tranh kiến trúc

text
FE surface (ecommerce / user / affiliate / settings)
  -> GraphQL mutation / Hasura action
  -> wallet.transaction_request + transaction_request_user
  -> wallet-api action / event
  -> DB trigger materialize transaction khi status = S
  -> wallet balance / stats / ecommerce_transaction / notification side effects

Commission create path
  -> ecommerce-api event/action
  -> commission_util.AddCommission(...)
  -> transaction_request status = S
  -> DB insert transaction
  -> wallet-api transaction_insert side effects

Refund / withdraw / payout path
  -> FE insert transaction_request status = R
  -> changeStatusTransaction
  -> wallet-api transaction_request_update
  -> success/cancel/reject side effects

3. Frontend Surface

3.1 Write surfaces

SurfaceModuleVai trò
Withdraw request list/create/detailecommerceTạo, sửa, duyệt, hủy request family refund/withdraw
Collaborator payout inlineuserTạo withdraw request cho collaborator ngay trong customer detail
Affiliate withdraw formaffiliateTạo payout request cho affiliate/collaborator
Commission percent editaffiliateThay đổi commission percent, gây side effect refund/commission
Promotion wallet / approver configsettingsChỉ cấu hình visibility/gating, không trực tiếp ghi ledger

3.2 Read surfaces

SurfaceModuleVai trò
Wallet summary customeruserĐọc wallet_stats, wallet_balance
Employee commission ledgeruserĐọc history wallet của staff
Commission reportreportĐọc aggregate/reporting model
Checkout/prepaid/product flowsecommerceĐọc wallet để quyết định payment source

3.3 Permission map thực tế

CaseGate đang dùng
POS withdrawrefund_request_management + BranchPOS
IT/accounting withdraw managementfund_request_management
Affiliate payout editaffiliate_management và không phải BranchPOS
Customer collaborator payout inlineChủ yếu check isPlatformPos() ở UI host
Commission reportmoduleId = report_management

4. GraphQL / Action Map

OperationLoạiSurface chínhMục đích
walletBalancesHasura actionuser, affiliate, ecommerceĐọc/cấp phát wallet rows theo user
wallet_balanceSQL function queryecommerce, affiliate, userĐọc balance khả dụng theo wallet type
wallet_statsSQL function queryuser, affiliate, ecommerceThống kê amount/inflow/outflow theo wallet
RefundRequestCreatemutationecommerce, user, affiliateTạo hoặc update transaction_request
changeStatusTransactionHasura actionecommerceApprove / reject / cancel request
GetOrderCommissionRefundquery/viewecommerceĐọc aggregate để tạo child refund_commission
changeCustomerCommissionPercentactionaffiliateĐiều chỉnh commission percent, kéo theo refund/clawback

5. Backend Flow Map

5.1 Request engine

LớpFile chínhVai trò
Actionwallet-api/action/wallet.gowalletBalances: đọc balance facade và auto-create wallet
Actionwallet-api/action/change_status_transaction_refund.goGate transition approve/reject/cancel
Eventwallet-api/event/transaction_request_insert.goEarly sync HRM/refund log/order flags
Eventwallet-api/event/transaction_request_update.goSync refund log, notification, wallet refund, ecommerce side effects
Eventwallet-api/event/transaction_insert.goCập nhật before/after amount, ecommerce_transaction, ZNS
DB triggermigration 1624088117982_initializationMaterialize transaction khi request thành công

5.2 Upstream creator

SourceFile chínhVai trò
Order confirmecommerce-api/action/order_confirm.goTạo transfer/withdraw path khi xác nhận order
Order item insertecommerce-api/event/order_item_insert.goNạp ví/topup từ prepaid order item
Invoice approvedecommerce-api/event/invoice_insert_update.goTạo commission chuẩn
Referral / affiliateecommerce-api/action/handle_referral_customer.goTemp commission, commission percent change, refund commission
Affiliate approvalecommerce-api/action/affiliate_user_change_status.goChốt temp commission sang success

6. Data Model Cốt Lõi

ObjectVai trò
wallet_typeĐịnh nghĩa loại ví, currency, min_balance_capacity, flags default/promotion/disabled
walletSố dư base theo (user_id, wallet_type_id)
transaction_requestRequest envelope: type, status, behavior, approver chain, reference
transaction_request_userSender/receiver legs của request
transactionLedger thực tế sau khi materialize
wallet_balance / wallet_statsRead models chính cho FE
payment_gateway, payment_gateway_wallet_type, user_payment_gateway3 lớp cấu hình payment riêng nhau
order_commission_refundRead model aggregate commission/refund, không phải source-of-truth

7. Semantic Rules Cần Nhớ

  1. transaction_request.amounttransaction_request_user.amount là requested amount; transaction.amount mới là ledger realized amount.
  2. reference_id không canonical; cùng field này đang bị dùng cho invoice, order, project task.
  3. walletBalances không chỉ đọc dữ liệu, mà còn auto-create wallet row nếu chưa có.
  4. Không phải mọi request chờ duyệt đều làm tăng hold_amount; semantics hiện phụ thuộc status.
  5. Commission create và commission clawback là hai nhánh khác nhau nhưng dùng chung transaction_request.

8. Rủi ro / Findings

IDMứcFinding
F-01P1FE không có wallet module riêng, nên permission và UX phân tán qua ecommerce, user, affiliate, settings.
F-02P1walletBalances là action đọc nhưng có side effect auto-create wallet, nên không thuần read-only.
F-03P1Request chờ duyệt R có dấu hiệu chưa được hold như business wording đang ngụ ý.
F-04P1transaction_request_user.amounttransaction.amount có thể drift nếu update request user sau khi bỏ trigger chống update.
F-05P1Commission idempotency hiện dựa trên checksum time-window, chưa phải business key ổn định.
F-06P2Nhiều FE surface đọc wallet/balance bằng query hoặc helper khác nhau, dễ dẫn tới không đồng nhất UX và validation.