Appearance
Module Overview — Ecommerce Refund / Withdraw
1. Scope
Feature này không nằm gọn trong một service hay một route tree duy nhất. Nó cắt qua:
- frontend
ecommercemodule, - backend
wallet-api, - backend
ecommerce-api, - metadata Hasura của
wallet,ecommerce,hrm.
Phần quan trọng nhất cần nhớ:
refund / withdraw / commission refundđi quawallet.transaction_request,negative paymentđi quahrm.request_working_schedule,- nhưng 2 nhánh này lại gặp nhau ở cùng các order/invoice/commission downstream, nên rất dễ bị mô tả sai boundary nếu chỉ nhìn UI.
2. Bức tranh kiến trúc
text
Order / Product Order / Topup / Collaborator flow
-> FE tạo hoặc mở refund request
-> wallet.transaction_request
-> action changeStatusTransaction
-> wallet-api event transaction_request_update
-> update order / revenue / wallet / refund log / commission side effects
Negative payment
-> FE createNegativePayment từ payment flow
-> hrm.request_working_schedule (type = negative_payment)
-> ecommerce-api changeStatusRequestWorkingSchedule
-> ecommerce-api event request_working_schedule_update
-> invoice negative / approval side effects3. Frontend Surface
3.1 Refund / Withdraw routes
| Surface | Route family | Guard thực tế | Page stack |
|---|---|---|---|
| POS | ROUTE_WITHDRAW_REQUEST* | moduleId = refund_request_management, BranchPOS | list, create/update, detail |
| Admin / request management | ROUTE_REQUEST_MANAGEMENT_WITHDRAW* | moduleId = fund_request_management, ITLeader/ITStaff/AccountantLeader | list, create/update, detail |
Nguồn chính:
diva-admin/src/modules/ecommerce/module.ts:742diva-admin/src/modules/ecommerce/module.ts:848diva-admin/src/modules/ecommerce/module.ts:2203diva-admin/src/modules/ecommerce/module.ts:2219
3.2 Negative payment routes
| Surface | Route family | Guard thực tế | Page stack |
|---|---|---|---|
| Approval flow | ROUTE_REQUEST_MANAGEMENT_NEGATIVE_PAYMENT* | moduleId = negative_payment_request_management_submenu | list, detail |
Nguồn chính:
diva-admin/src/modules/ecommerce/module.ts:713diva-admin/src/modules/ecommerce/module.ts:2371
3.3 FE pages quan trọng
| File | Vai trò |
|---|---|
pages/WithdrawRequest.tsx | List shell + approver preload |
pages/WithdrawRequestCreate.tsx | Upsert request thủ công |
pages/WithdrawRequestDetail.tsx | Detail, approve/reject/cancel, child refund commission |
components/withdraw-request/WithdrawRequestTable.tsx | Filter/where builder cho list |
components/withdraw-request/WithdrawRequestSelectStatus.tsx | Runtime action gate cho status |
components/withdraw-request/CommissionRefundConfirmForm.tsx | Sinh child request refund_commission |
pages/NegativePaymentRequests.tsx | List approval cho negative payment |
pages/NegativePaymentRequestDetail.tsx | Detail + approve/reject |
4. GraphQL / Action Map
4.1 Refund / withdraw family
| Operation | Loại | Mục đích |
|---|---|---|
GetTransactionRequestByPk | query | Đọc detail request |
GetTransactionRequestRefunds | query | Đọc child refund requests |
RefundRequestCreate | mutation | Tạo / update transaction_request |
ChangeStatusTransactionRefund | mutation | Gọi action changeStatusTransaction |
UploadFileRefund | mutation | Upload wallet_reference_file |
GetOrderCommissionRefund | query | Lấy nguồn commission để tạo child refund |
Nguồn: diva-admin/src/modules/ecommerce/graphql/withdraw_request.graphql
4.2 Negative payment family
| Operation | Loại | Mục đích |
|---|---|---|
GetNegativeRequest* | query | List/detail request_working_schedule |
ChangeApprovalStatus | mutation/action | Approve/reject request âm |
createNegativePayment | action | Tạo request âm + negative invoice |
Nguồn:
diva-admin/src/modules/ecommerce/graphql/negative_payment_request.graphqldiva-admin/src/modules/ecommerce/graphql/prepaid_order.graphql
5. Backend Flow Map
5.1 Refund / withdraw
| Lớp | File chính | Vai trò |
|---|---|---|
| Action | wallet-api/action/change_status_transaction_refund.go | Gate transition + dispatch theo behavior_id |
| Event | wallet-api/event/transaction_request_insert.go | Early sync / set flags / commission setup |
| Event | wallet-api/event/transaction_request_update.go | Revenue rollback, wallet credit, refund log, notification |
| Event helper | wallet-api/event/refund_log_sync.go | Đồng bộ transaction_refund_log |
5.2 Negative payment
| Lớp | File chính | Vai trò |
|---|---|---|
| Action | ecommerce-api/action/negative_payment.go | Tạo request_working_schedule + negative invoice |
| Action | ecommerce-api/action/change_status_request_working_schedule.go | Approve/reject request âm |
| Event | ecommerce-api/event/request_working_schedule_update.go | Side effect vào invoice / approval downstream |
6. Data Model Cốt Lõi
| DB | Object | Vai trò |
|---|---|---|
wallet | transaction_request | Request engine trung tâm cho refund/withdraw |
wallet | transaction_request_user | Các leg sender/receiver theo ví |
wallet | transaction_request_log | Audit trail approve/reject/cancel |
wallet | transaction | Ledger sau khi request thành công |
wallet | order_commission_refund | View aggregate commission vs refund_commission |
wallet | wallet_reference_file | Chứng từ / file đính kèm |
ecommerce | transaction_refund_log | Audit/read-model refund phía ecommerce |
ecommerce | order | is_refunded_order, refund_amount, refunded_at, debt_amount |
ecommerce | invoice | Parent invoice, negative invoice, request_negative_id |
hrm | request_working_schedule | Approval container cho negative payment |
7. Semantic Rules Cần Nhớ
transaction_request.reference_idkhông canonical.transaction_request.order_idvàorder.id <- reference_idcùng tồn tại, nên phải nói rõ flow nào dùng khóa nào.negative paymentkhông phải “một dạng refund”; nó là approval flow riêng.commission refundlà child request của refund cha, không phải route độc lập.is_refunded_ordercó thể bị set sớm từ insert event, chưa đồng nghĩa với “đã hoàn tiền thành công”.
8. Rủi ro / Findings
| ID | Mức | Finding |
|---|---|---|
| F-01 | P1 | FE đang có drift moduleId giữa refund_request_management, fund_request_management, và guard exclude *_submenu. |
| F-02 | P1 | canApprove ở cả refund và negative payment có dấu hiệu check sai actor vì so với created_by của request. |
| F-03 | P1 | Side effects refund lớn nằm ở event transaction_request_update, không chỉ ở action approve. |
| F-04 | P1 | reference_id bị overload giữa invoice/order/project_task nên rất dễ làm sai downstream query hoặc doc. |
| F-05 | P1 | request_working_schedule_update đang có dấu hiệu chạm invoice quá sớm cho negative payment. |
| F-06 | P2 | Nhánh cosmetic refund tạo TransactionCommission thay vì TransactionRefundCommission, cho thấy semantics chưa nhất quán. |