Appearance
Type Deep Dive — Payment Withdraw And Wallet Boundary
1. Hai khái niệm khác nhau cần tách ngay
| Khái niệm UI | Source-of-truth thật |
|---|---|
| Affiliate payment | invoice_affiliate trong domain ecommerce |
| Affiliate withdraw / payout | transaction_request và transaction trong domain wallet |
Rất nhiều nhầm lẫn xảy ra vì cả hai đều được gọi là "thanh toán".
2. Withdraw Form Runtime
WithdrawAffiliateForm nằm trong affiliate UI nhưng thực tế:
- query
wallet_balancevớiwallet_type_id = COMMISSION, - query
affiliate_usertheoaccount_idđể render info CTV, - submit mutation
refundRequestCreate, - tạo
transaction_requestvới:type = W,status = R,behavior_id = refund_collaborator,payment_method_id = wallet | cash,reference_amount = amount.
Kết luận: withdraw không mutate invoice_affiliate hay order_affiliate.
3. Withdraw History Queries
GetWithdrawHistory lọc:
customer_id = user_id,payment_method_id in ["wallet", "cash"],type = W,behavior_id = refund_collaborator.
Cards summary lại đọc ba nguồn:
transaction_aggregatevớitransaction_request.behavior_id = transaction_commissionđể tính tổng commission đã nhận,transaction_request_aggregatevớirefund_collaboratorđể tính tổng đã rút,wallet_statsđể tính số dư còn lại.
Điều này xác nhận affiliate payout dashboard là một màn hình reconciliation xuyên domain, không phải query một bảng duy nhất.
4. Customer Workspace Embed
Trong customer detail:
OrderCustomerListvàPaymentCustomerListembed order/payment views,- action
Withdrawmở route withdraw form, - affiliate user id được resolve lại qua
account_id -> affiliate_user.
Vì vậy user module chỉ là shell host; runtime thật vẫn nằm ở affiliate + wallet.
5. Approval Boundary vs Payout Boundary
Sequence đúng nên hiểu là:
affiliate_useractive,order_affiliateapproved,invoice_affiliateapproved,transaction_request(transaction_commission)success,- user tạo
transaction_request(refund_collaborator)để rút, - wallet flow xử lý payout thực.
Nếu bỏ qua bước 4 và 5, rất dễ lẫn "đã duyệt payment" với "đã trả tiền cho CTV".
6. Findings kỹ thuật
| ID | Mức | Finding |
|---|---|---|
| W-01 | P0 | Withdraw flow nằm hoàn toàn ở wallet boundary; affiliate module chỉ là UI shell tạo request và hiển thị reconciliation cards. |
| W-02 | P0 | Số dư commission không suy trực tiếp từ invoice_affiliate; nó đến từ wallet projections (wallet_balance, wallet_stats, transaction). |
| W-03 | P1 | GetWithdrawHistoryCards dùng transaction_request.behavior_id = transaction_commission để tính tổng đã nhận, còn withdraw dùng refund_collaborator; đây là hai behavior families khác nhau nhưng cùng xuất hiện trong một màn hình. |
| W-04 | P1 | WithdrawAffiliateForm chỉ clamp amount theo wallet balance ở FE; validation/quy tắc cuối cùng vẫn cần dựa vào wallet layer. |
| W-05 | P2 | Chỉ wallet và cash đang được tính là withdraw methods trong history query, nên nếu thêm payment method mới mà không sửa filter này thì dashboard sẽ drift. |