FE: module return_request — trả hàng #
Phần chung (khởi tạo client, lỗi, danh sách, ngôn ngữ) ở tài liệu FE của Core:
docs/fe/common.md (bản đọc: xforge-documentation, ADR-0102 của xforge-core).
Sửa file này CÙNG PR khi đổi hành vi FE thấy được của module.
Vòng đời #
requested → approved → received → refunded | closed. Từ requested:
rejected (kèm rejectionReason). requested / approved → cancelled. Mỗi
Mỗi phiếu có actions: thao tác người gọi làm được lúc này — bật / tắt nút theo
đó, đừng tự suy từ status. status, actions, items[].condition là chuỗi
và tập giá trị sẽ còn thêm (đổi hàng…): giá trị lạ thì hiện nguyên, đừng coi là
lỗi.
Phiếu rejected / cancelled nhả phần trả: khách tạo phiếu mới cho chính các
dòng đó được.
Storefront (StorefrontClient) #
Khách đã đăng nhập, chỉ phiếu và đơn của chính mình (khách là của cả hệ thống
nhưng phiếu tính theo store: đăng nhập store khác không thấy). Response không có
storeId, customerId, người tạo / sửa; createdAt là lúc gửi yêu cầu.
createMyReturnRequest({ body: { orderId, reason, items: [{ orderItemId, qty }] } })— đơn phải đã giao (fulfilled/completed; không thì 409return_request_order_not_returnable,details.status).orderItemIdlàitems[].idcủa đơn,qtytheo đơn vị bán của dòng đó. Vượt phần còn trả → 409return_request_qty_exceeded(details.availabletheo đơn vị của dòng,error.at = items.<i>). Dòng không thuộc đơn → 404return_request_item_not_found; số lượng không quy đổi đúng sang đơn vị gốc → 400return_request_qty_not_exact(cả hai mangerror.at). Đơn không phải của khách → 404return_request_order_not_found.listMyReturnRequests(lọcstatus,order_id),getMyReturnRequest.cancelMyReturnRequest— khi cònrequested/approved.
total là số tiền hoàn GỢI Ý (tổng khách đã trả cho dòng × phần trả). Tiền về
khi cửa hàng hoàn tất phiếu hoàn (refundInfo.status: pending → completed).
CMS / admin (XforgeClient) #
Menu: key return_request.return_requests (quyền return_request.read).
| Thao tác | Quyền | Ghi chú |
|---|---|---|
createReturnRequest | return_request.create | Tạo thay khách, cùng luật như storefront |
approveReturnRequest | return_request.manage | |
rejectReturnRequest | return_request.manage | body: { reason } — khách thấy |
receiveReturnRequest | return_request.receive | Nhận hàng, xem dưới |
refundReturnRequest | return_request.refund | body: { method, amount?, shippingAmount?, reason? } → phiếu hoàn pending |
closeReturnRequest | return_request.manage | Kết thúc không hoàn tiền qua hệ thống (đổi hàng, hoàn ngoài) |
cancelReturnRequest | return_request.manage |
Thông báo + realtime. Khách gửi yêu cầu từ storefront → thông báo
return_request.requested (kèm Web Push) cho người có return_request.manage:
link.key = return_request.return_requests, link.id = id phiếu, mở thẳng
màn duyệt. Nhân viên tạo thay thì không có thông báo này. Thông báo đến trễ vài
giây (Core giải người nhận sau commit).
Topic return_request.changed (người có return_request.read, docs/fe/cms.md
§6): phiếu vừa tạo / đổi trạng thái, data: { returnRequestId }. Màn danh sách
/ chi tiết đang mở đọc lại qua API, đừng dùng data làm dữ liệu.
Nhận hàng. Mặc định mọi dòng resellable: hàng về kho của đơn, đúng lô /
serial đã xuất (theo thứ tự xuất). items chỉ gửi dòng khác mặc định, id là
id DÒNG PHIẾU TRẢ (items[].id của phiếu, không phải orderItemId), mỗi dòng
một lần; error.at = items.<chỉ số trong body gửi lên>:
condition: "damaged"— ghi nhận, không về kho (không gửi kèm lô / serial).batches: [{ id, qty }](biến thể theo lô, số lượng theo đơn vị gốc) hoặcserialIds: [...](theo serial) — chọn trong phần đã xuất của dòng đơn chưa trả. Sai → 409return_request_detail_invalid(details.reason:qty_mismatch,batch_not_returnable,serial_not_returnable…),error.at = items.<i>.
Sau khi nhận, items[].detail là lô / serial đã về, restocked cho biết dòng
có về kho không.
Hoàn tiền. refundReturnRequest tạo phiếu hoàn pending của module
refund; amount vắng = total của phiếu trả. Tiền HÀNG
(amount −
shippingAmount) không quá total, amount > 0 → không thì 409
return_request_refund_invalid (details.reason: over_total,
nothing_to_refund, shipping_over_amount; details.max). Trần của cả đơn là
luật của refund (không hoàn quá số khách đã trả). Hoàn tất / thất bại phiếu
hoàn bằng route của refund; refundInfo.status cho biết trạng thái
(pending, processing, completed, failed). Phiếu hoàn failed thì phiếu
trả vẫn refunded: tạo phiếu hoàn mới cho đơn ở màn hoàn tiền (refund).