Skip to content

Module Overview — Affiliate Approval And Payout

1. Scope

Flow này không nằm gọn trong một page hay một bảng. Nó cắt qua:

  • frontend affiliate routes cho approval, list, order, payment, customer detail subpages,
  • backend ecommerce-api actions cho affiliateUserRegistration, affiliateUserChangeStatus, changeCustomerCommissionPercent, changeAffiliateWalletType,
  • Hasura metadata của domain ecommerce,
  • wallet queries cho wallet_balance, transaction_request, transaction,
  • report và user drill-down dùng lại cùng data surfaces.

Mental model nên giữ từ đầu:

  • affiliate_user là hồ sơ và quyền CTV,
  • order_affiliate là ledger cấp order, chưa phải payout,
  • invoice_affiliate là ledger cấp payment/invoice,
  • transaction_request mới là runtime boundary để commission vào ví hoặc rút tiền ra khỏi ví.

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

text
Affiliate registration
  -> affiliate_user insert
  -> by customer/anonymous: pending inactive
  -> by staff/user: auto-activate ngay nếu đủ tag

Affiliate approval
  -> affiliateUserChangeStatus(type=user)
  -> create/find customer account
  -> activate/revoke affiliate_user
  -> write affiliate_action_log

Order commission
  -> order insert / referral handling tạo order_affiliate + invoice_affiliate + transaction_request draft/pending
  -> staff approve/reject order_affiliate
  -> staff approve/reject invoice_affiliate
  -> approve invoice => flip transaction_request status success + credit commission

Affiliate payout
  -> customer detail withdraw form
  -> refundRequestCreate on wallet transaction_request
  -> history cards đọc transaction + transaction_request + wallet_stats

3. Frontend Surface

3.1 Route families

FamilyRoute groupBoundary
Approval shell/affiliate/approvalQueue các CTV chưa active
Affiliate list/affiliate/listDanh sách CTV active, edit, referral detail
Order shell/affiliate/orderCommission cấp order, approve/reject, detail
Payment shell/affiliate/paymentCommission cấp invoice/payment, approve/reject, detail
Customer embedded viewsuser/customer-detail/collaborators/*Reuse order/payment/withdraw flows trong customer workspace

3.2 Runtime map thực tế

BoundaryGhi chú
Root redirectPOS branch có thể vào thẳng list, admin flow mặc định vào approval queue
Create/edit reuseListCreate được mount cho cả approval edit, create mới và edit affiliate
Action popup reuseCả user/order/invoice đều dùng chung mutation ChangeAffiliateUserStatus, chỉ khác typenew_status
Payment vs withdrawPaymentList chỉ là invoice commission; withdraw history lại đọc transaction_request riêng

4. Backend Boundary Map

LớpFile chínhVai trò
Actionaffiliate_user_registration.goĐăng ký CTV theo role caller, create account nếu cần
Actionaffiliate_user_change_status.goState machine cho user, order, invoice; ghi action log
Actionchange_customer_commission_percent.goSửa commission percent trên order/invoice chưa approve
Actionchange_affiliate_wallet_type.goĐổi ví nhận commission và recalc order/invoice chưa approve
Eventorder_insert.goTạo order_affiliate khi order đủ điều kiện referral/affiliate
Wallet boundaryrefundRequestCreate + wallet queriesTạo withdraw request và đọc lịch sử rút tiền

5. Data Layer Map

LayerObject chínhVai trò
Affiliate profileaffiliate_userHồ sơ CTV, KYC, bank info, active/tag state
Referral linkageaffiliate_user_logAi được affiliate bởi ai, thời điểm nào
Approval/action auditaffiliate_action_logHistory approve/revoke/reject/update percent
Order commissionorder_affiliatePending/approved/rejected commission cấp order
Invoice commissioninvoice_affiliatePending/approved/rejected commission cấp payment
Configaffiliate_configEnable matrix theo order_kindpayment_method_id
Wallet runtimetransaction_request, transaction, wallet_balance, wallet_statsCommission materialization và payout/withdraw

6. Semantic Rules Cần Nhớ

  1. affiliateUserRegistration có hai semantics khác nhau: user/admin path auto-activate, còn customer/anonymous path chỉ insert pending record.
  2. affiliateUserChangeStatus là state engine chung nhưng không đối xứng hoàn toàn:
    • user hỗ trợ approverevoke,
    • order hỗ trợ approve, cancel, reject, unreject,
    • invoice hỗ trợ approve, reject, unreject, còn cancel bị chặn.
  3. Approve invoice_affiliate mới là điểm commission đi vào wallet, vì handler gọi AddAffiliateCommission và set transaction_request.status = success.
  4. Withdraw history của affiliate không đọc invoice_affiliate; FE lọc transaction_request theo type = Wbehavior_id = refund_collaborator.
  5. Các list order/payment cố ý vẫn hiển thị hồ sơ inactive nếu commission đã được approve, để giữ historical visibility.

7. Rủi ro / Findings

IDMứcFinding
F-01P0affiliateUserRegistration cho role user/admin auto-activate ngay (is_active = true, approved_at = now), nên approval queue không phải là cửa duy nhất để một CTV đi vào trạng thái active.
F-02P0Approve invoice phụ thuộc invoice_affiliate.transaction_id đã tồn tại sẵn; nếu transaction request thiếu hoặc lệch state, flow commission materialization sẽ fail ở AddAffiliateCommission.
F-03P1Cùng một output code như ALREADY_APPROVED được reuse cho user/order/invoice, nên nếu chỉ nhìn response code từ FE sẽ thiếu ngữ cảnh reference type.
F-04P1PaymentListOrderList cố tình include affiliate đã inactive nếu record commission đã approved; đây là semantics lịch sử đúng, nhưng rất dễ bị hiểu nhầm là bug filter.
F-05P1Withdraw/payout chạy ở wallet boundary với refund_collaborator, nên reconciliation nếu chỉ test trên affiliate payment pages sẽ thiếu một nửa runtime thật.
F-06P2CreateCustomer set một số default cứng như gender = malewallet_receive_commission = commission, cho thấy affiliate approval còn gánh side effects account bootstrap ngoài phạm vi affiliate thuần.