Skip to content

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 ecommerce module,
  • 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 qua wallet.transaction_request,
  • negative payment đi qua hrm.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 effects

3. Frontend Surface

3.1 Refund / Withdraw routes

SurfaceRoute familyGuard thực tếPage stack
POSROUTE_WITHDRAW_REQUEST*moduleId = refund_request_management, BranchPOSlist, create/update, detail
Admin / request managementROUTE_REQUEST_MANAGEMENT_WITHDRAW*moduleId = fund_request_management, ITLeader/ITStaff/AccountantLeaderlist, create/update, detail

Nguồn chính:

  • diva-admin/src/modules/ecommerce/module.ts:742
  • diva-admin/src/modules/ecommerce/module.ts:848
  • diva-admin/src/modules/ecommerce/module.ts:2203
  • diva-admin/src/modules/ecommerce/module.ts:2219

3.2 Negative payment routes

SurfaceRoute familyGuard thực tếPage stack
Approval flowROUTE_REQUEST_MANAGEMENT_NEGATIVE_PAYMENT*moduleId = negative_payment_request_management_submenulist, detail

Nguồn chính:

  • diva-admin/src/modules/ecommerce/module.ts:713
  • diva-admin/src/modules/ecommerce/module.ts:2371

3.3 FE pages quan trọng

FileVai trò
pages/WithdrawRequest.tsxList shell + approver preload
pages/WithdrawRequestCreate.tsxUpsert request thủ công
pages/WithdrawRequestDetail.tsxDetail, approve/reject/cancel, child refund commission
components/withdraw-request/WithdrawRequestTable.tsxFilter/where builder cho list
components/withdraw-request/WithdrawRequestSelectStatus.tsxRuntime action gate cho status
components/withdraw-request/CommissionRefundConfirmForm.tsxSinh child request refund_commission
pages/NegativePaymentRequests.tsxList approval cho negative payment
pages/NegativePaymentRequestDetail.tsxDetail + approve/reject

4. GraphQL / Action Map

4.1 Refund / withdraw family

OperationLoạiMục đích
GetTransactionRequestByPkqueryĐọc detail request
GetTransactionRequestRefundsqueryĐọc child refund requests
RefundRequestCreatemutationTạo / update transaction_request
ChangeStatusTransactionRefundmutationGọi action changeStatusTransaction
UploadFileRefundmutationUpload wallet_reference_file
GetOrderCommissionRefundqueryLấy nguồn commission để tạo child refund

Nguồn: diva-admin/src/modules/ecommerce/graphql/withdraw_request.graphql

4.2 Negative payment family

OperationLoạiMục đích
GetNegativeRequest*queryList/detail request_working_schedule
ChangeApprovalStatusmutation/actionApprove/reject request âm
createNegativePaymentactionTạo request âm + negative invoice

Nguồn:

  • diva-admin/src/modules/ecommerce/graphql/negative_payment_request.graphql
  • diva-admin/src/modules/ecommerce/graphql/prepaid_order.graphql

5. Backend Flow Map

5.1 Refund / withdraw

LớpFile chínhVai trò
Actionwallet-api/action/change_status_transaction_refund.goGate transition + dispatch theo behavior_id
Eventwallet-api/event/transaction_request_insert.goEarly sync / set flags / commission setup
Eventwallet-api/event/transaction_request_update.goRevenue rollback, wallet credit, refund log, notification
Event helperwallet-api/event/refund_log_sync.goĐồng bộ transaction_refund_log

5.2 Negative payment

LớpFile chínhVai trò
Actionecommerce-api/action/negative_payment.goTạo request_working_schedule + negative invoice
Actionecommerce-api/action/change_status_request_working_schedule.goApprove/reject request âm
Eventecommerce-api/event/request_working_schedule_update.goSide effect vào invoice / approval downstream

6. Data Model Cốt Lõi

DBObjectVai trò
wallettransaction_requestRequest engine trung tâm cho refund/withdraw
wallettransaction_request_userCác leg sender/receiver theo ví
wallettransaction_request_logAudit trail approve/reject/cancel
wallettransactionLedger sau khi request thành công
walletorder_commission_refundView aggregate commission vs refund_commission
walletwallet_reference_fileChứng từ / file đính kèm
ecommercetransaction_refund_logAudit/read-model refund phía ecommerce
ecommerceorderis_refunded_order, refund_amount, refunded_at, debt_amount
ecommerceinvoiceParent invoice, negative invoice, request_negative_id
hrmrequest_working_scheduleApproval container cho negative payment

7. Semantic Rules Cần Nhớ

  1. transaction_request.reference_id không canonical.
  2. transaction_request.order_idorder.id <- reference_id cùng tồn tại, nên phải nói rõ flow nào dùng khóa nào.
  3. negative payment không phải “một dạng refund”; nó là approval flow riêng.
  4. commission refund là child request của refund cha, không phải route độc lập.
  5. is_refunded_order có 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

IDMứcFinding
F-01P1FE đang có drift moduleId giữa refund_request_management, fund_request_management, và guard exclude *_submenu.
F-02P1canApprove ở cả refund và negative payment có dấu hiệu check sai actor vì so với created_by của request.
F-03P1Side effects refund lớn nằm ở event transaction_request_update, không chỉ ở action approve.
F-04P1reference_id bị overload giữa invoice/order/project_task nên rất dễ làm sai downstream query hoặc doc.
F-05P1request_working_schedule_update đang có dấu hiệu chạm invoice quá sớm cho negative payment.
F-06P2Nhánh cosmetic refund tạo TransactionCommission thay vì TransactionRefundCommission, cho thấy semantics chưa nhất quán.