Skip to content

Type Deep Dive — Order Commission And Invoice

1. Order Affiliate là lớp commission trung gian

order_affiliate được tạo từ order/referral runtime ở ecommerce-api chứ không được nhập tay trong module affiliate. FE order list chủ yếu:

  • filter và summary,
  • mở detail,
  • approve / cancel approve / reject / unreject,
  • chỉnh commission percent hoặc wallet type khi record còn pending hợp lệ.

2. Order Status Engine

OrderActivePopup vẫn gọi ChangeAffiliateUserStatus, nhưng với:

  • type = order,
  • new_status thuộc approve, cancel, reject, unreject.

Rule chính

  1. approve set is_approved = true, approved_at = now.
  2. cancel chỉ hợp lệ khi chưa có bất kỳ invoice_affiliate nào approved.
  3. reject chỉ hợp lệ khi order chưa approved.
  4. unreject chỉ hợp lệ khi order đang rejected và chưa approved.

3. Invoice Affiliate là lớp materialization gate

invoice_affiliate là bước gần cuối trước khi commission vào ví. PaymentActivePopup gọi cùng action engine với:

  • type = invoice,
  • new_status thuộc approve, reject, unreject.

Approve invoice làm gì?

handleTypeInvoice thực hiện:

  1. set invoice_affiliate.is_approved = true,
  2. set approved_atcommission_paid_date,
  3. gọi AddAffiliateCommission,
  4. ghi commission_revoke_log,
  5. ghi affiliate_action_log.

Trong AddAffiliateCommission:

  • load transaction_request qua invoice_affiliate.transaction_id,
  • update transaction_request.status = success,
  • gửi notification / ZNS side effects,
  • từ đây wallet layer mới nhìn thấy commission đã thành công.

Kết luận: invoice approval là business gate cuối trước wallet success, không chỉ là cờ UI.

4. Commission Percent Mutation

Action changeCustomerCommissionPercent cho phép sửa phần trăm commission ở 4 modes:

  • order,
  • invoice,
  • order item within order,
  • order item within invoice.

Semantics chính:

  • chỉ update trên pending records,
  • recalc order_affiliate.temp_commission_amount,
  • recalc invoice_affiliate.commission_amountcurrent_sale_percent,
  • sync luôn transaction_request.amounttransaction_request_user.amount,
  • ghi affiliate_action_log cho audit.

Nói cách khác, affiliate commission ở đây không phải read-only sau khi sinh ra; pending path còn cho phép rewrite upstream financial inputs.

5. Wallet Type Mutation

Action changeAffiliateWalletType cho phép đổi ví nhận commission ở cấp order:

  • update order.wallet_receive_commission,
  • recalc order_affiliate.wallet_typetemp_commission_amount,
  • recalc toàn bộ invoice_affiliate.commission_amount chưa approve.

Nhưng nếu có bất kỳ invoice approved nào thì action bị chặn.

6. Historical Visibility Rule ở FE

OrderListPaymentList dùng filter đặc biệt:

  • record approved của affiliate inactive vẫn được show,
  • pending records thường gắn điều kiện active/current status chặt hơn.

Mục đích là giữ nhìn thấy lịch sử commission đã chốt dù CTV hiện đã bị revoke.

7. Findings kỹ thuật

IDMứcFinding
O-01P0Approve invoice phụ thuộc pre-existing transaction_request; nếu upstream order/referral runtime không tạo đúng transaction_id, approval sẽ fail ở lớp wallet bridge.
O-02P0changeCustomerCommissionPercent sync cả invoice_affiliate lẫn transaction_requesttransaction_request_user, nên đây là financial mutation thật, không phải chỉ sửa display percent.
O-03P1changeAffiliateWalletType recalc hàng loạt invoice pending theo level discount hiện tại; QA cần test lại cả amount lẫn wallet type sau khi đổi.
O-04P1Order cancel approval bị chặn nếu có invoice approved, cho thấy state machine thật đang coi invoice approval là irreversible boundary của order-level approval.
O-05P2FE gọi useRefreshSettings() ở order flows để kéo config mới, nghĩa là semantics commission phụ thuộc settings runtime hơn là constants local của affiliate module.