Skip to content

Shared Rules — Ecommerce Refund / Withdraw

1. Thuật ngữ chuẩn

Thuật ngữNghĩa trong code hiện tạiGhi chú
Refund requesttransaction_requesttype = "W"behavior_id thuộc family refundKhông phải mọi transaction_request đều là refund
Withdraw requestUI đang dùng chung page set với refund requestTên route/page thiên về “withdraw” nhưng behavior có nhiều loại refund
Commission refundChild transaction_request với behavior_id = refund_commissionGắn parent_id về request cha
Negative paymentrequest_working_schedule type negative_payment + negative invoiceKhông đi qua transaction_request
Successstatus = S ở wallet requestKhác với approved ở HRM request

2. Behavior Matrix

BehaviorFamilyEngine chínhMô tả ngắn
refund_orderRefundwallet.transaction_requestHoàn order dịch vụ
refund_order_cosmeticRefundwallet.transaction_requestHoàn order mỹ phẩm
refund_topupRefundwallet.transaction_requestHoàn topup ví / gói liên quan
refund_collaboratorRefundwallet.transaction_requestChi / hoàn liên quan collaborator
refund_commissionChild refundwallet.transaction_requestTruy thu commission gắn theo request cha
negative_paymentApproval riênghrm.request_working_scheduleInvoice âm / điều chỉnh thanh toán

3. Status Matrix

3.1 Wallet request

StatusÝ nghĩa
RRequesting
PProcessing
SSuccess
FFailure
CCanceled
RejectRejected

Điểm đáng chú ý:

  • CReject cùng tồn tại, semantics có phần chồng nhau.
  • FE hiện chủ yếu hiển thị R / Reject / C / S.

3.2 Negative payment request

StatusÝ nghĩa
pendingChờ duyệt
approvedĐã duyệt
rejectedTừ chối
canceledHủy
recalledThu hồi
approved_step_oneDuyệt bước 1

4. Approval Rules

Refund / withdraw

  • Người tạo được cancel.
  • Reviewer hiện tại mới được approve.
  • reject yêu cầu nằm trong reviewer chain hiện tại.
  • FE tự build approver logic từ useGetApproversQuery, nhưng logic gate đang bị lặp ở nhiều page/component.

Negative payment

  • Duyệt qua changeStatusRequestWorkingSchedule.
  • Status model và reviewer chain khác family refund.
  • Không nên reuse logic approve/refuse của transaction_request.

5. Key Semantic Rules

SR-001: reference_id không phải khóa canonical

Trong metadata hiện tại, transaction_request.reference_id có thể trỏ tới:

  • ecommerce.invoice
  • ecommerce.order
  • project.project_task

Ngoài ra nhiều flow còn dùng transaction_request.order_id riêng.

Hệ quả:

  • mọi tài liệu downstream phải nói rõ đang join theo reference_id hay order_id,
  • không được viết chung chung kiểu “request gắn với order qua reference_id”.

SR-002: transaction_refund_log không phải source of truth chính

  • transaction_refund_log là audit/read-model phía ecommerce.
  • Nguồn điều khiển chính của flow vẫn là wallet.transaction_request.

SR-003: negative payment chỉ có coupling dữ liệu với refund, không cùng state machine

  • Nó đọc commission đã success từ wallet.
  • Nhưng approval container là HRM request.
  • Invoice âm lại nằm phía ecommerce.

Vì vậy:

  • không được gộp negative payment vào “refund flow” như một subtype,
  • chỉ nên xem nó là flow adjacent / related.

SR-004: Child refund_commission là phần mở rộng của refund request cha

  • FE đọc order_commission_refund,
  • mở dialog xác nhận,
  • tạo child transaction_request với parent_id,
  • side effects downstream vẫn phụ thuộc event/update của family wallet request.

SR-005: is_refunded_order không đồng nghĩa với “refund đã hoàn tất”

Backend insert event có thể set cờ này sớm, trước cả khi request đi tới S.

Hệ quả:

  • dashboard/report/doc không nên dùng cờ này như dấu hiệu duy nhất cho success,
  • cần kết hợp status, success_at, refund_amount, hoặc transaction log.

6. Boundary Checklist

Khi phân tích một bug hoặc yêu cầu mới trong vùng này, luôn hỏi 5 câu:

  1. Đây là transaction_request flow hay request_working_schedule flow?
  2. Quyết định chính nằm ở action hay nằm ở event?
  3. reference_id ở case này đang mang nghĩa order hay invoice?
  4. Có child refund_commission hay không?
  5. Side effect chính chạm order, invoice, wallet, customer_revenue, hay commission?

7. Rủi ro / Findings

IDFinding
SR-F01FE và backend đều dùng từ “withdraw” cho một family gồm nhiều loại refund, dễ làm người đọc hiểu hẹp hơn thực tế.
SR-F02Approval logic đang phân tán, không có một source FE duy nhất cho canApprove.
SR-F03Cùng một feature nhưng trạng thái wallet và trạng thái HRM dùng 2 vocabulary khác nhau, rất dễ viết test sai.