FE: module shipment — vận đơn, thu hộ (COD) #
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.
Một đơn (module order) có tối đa 50 vận đơn. Vận đơn ghi hãng giao (carrier:
mã tự do ghn, ghtk, self…), mã theo dõi, tiền thu hộ (codAmount, tiền tệ
của đơn; null = không thu hộ).
Hai trục trạng thái #
Từ status | Sang được |
|---|---|
pending | in_transit, cancelled |
in_transit | out_for_delivery, delivered, failed, returned |
out_for_delivery | delivered, failed, returned |
failed | in_transit (giao lại), returned |
delivered / returned / cancelled | — (kết thúc) |
codStatus (trục tiền thu hộ, server đổi): none (không thu hộ) | pending →
collected (giao xong, hãng đã thu) → remitted (hãng đã nộp tiền cho store).
Vận đơn returned / cancelled khi còn pending → none.
pending→in_transitcần đơn đãfulfilled(hàng đã xuất kho, moduleorder) — không thì 409shipment_order_not_fulfilled.failedkèmreason(lưu thànhfailReason, lần hỏng gần nhất); từfailedgiao lại (in_transit) hoặc trả về (returned).- Đơn
fulfilledkhông còn vận đơn nào đang mở và có ít nhất một vận đơndelivered→ đơn tựcompleted. - Mốc thời gian:
shippedAt,deliveredAt,failedAt,returnedAt,cancelledAt,codCollectedAt,codRemittedAt.
CMS / admin (XforgeClient) #
Menu: key shipment.shipments (quyền shipment.read).
| Việc | Method | Quyền |
|---|---|---|
| Danh sách | listShipments({ query }) | shipment.read |
| Chi tiết | getShipment({ params: { id } }) | shipment.read |
| Tạo cho một đơn | createShipment({ body: { orderId, carrier, trackingNumber?, codAmount?, note? } }) | shipment.manage |
| Sửa thông tin hãng | updateShipment({ params: { id }, body }) (chỉ khoá gửi lên) | shipment.manage |
| Chuyển trạng thái | setShipmentStatus({ params: { id }, body: { status, reason? } }) | shipment.manage |
| Ghi nhận hãng nộp COD | remitShipmentCod({ params: { id }, body: { reference } }) | shipment.reconcile |
| Tiền COD hãng đang giữ | getShipmentCodSummary({ query: { carrier? } }) | shipment.read |
- Tạo vận đơn khi đơn
confirmedhoặcfulfilled(409shipment_order_not_shippable); số tự sinhSH-YYYYMMDD-0001. - Danh sách: lọc
status,order_id,cod_status,carrier;qtìm số vận đơn và mã theo dõi. Màn chi tiết đơn:listShipments({ query: { order_id } }). Mỗi vận đơn 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; giá trị lạ thì bỏ qua:update→updateShipment(shipment.manage, chưa kết thúc);- các bước kế tiếp, đúng giá trị gửi lên
setShipmentStatus:in_transit,out_for_delivery,delivered,failed,returned,cancelled(shipment.manage, theo sơ đồ trên); cod_remit→remitShipmentCod(shipment.reconcile,codStatuslàcollected).
actionschỉ xét vận đơn:in_transitvẫn hiện khi đơn chưa xuất kho và trả 409shipment_order_not_fulfilled. Bước đã lỗi thời (mở từ trước) → 409shipment_invalid_transition/shipment_closed: tải lại.shipment.manageđủ để giao xong → đơn hoàn tất: nhân viên giao hàng đóng đơn được (cố ý).- Đối soát COD:
getShipmentCodSummary= tiền thu hộ hãng còn giữ (vận đơncollected), theo hãng + tiền tệ; danh sách chi tiếtlistShipments({ query: { cod_status: "collected", carrier } }). Hãng chuyển tiền →remitShipmentCodtừng vận đơn kèm mã chuyển khoản. Khi tiền đã nộp của MỌI vận đơn của đơn đủ tổng đơn mà đơn cònunpaid→ đơn thànhpaid(modulepayments, nhà cung cấpcod); nộp một phần chỉ đánh dấu vận đơn.
- SMS báo khách (ADR-0104 của Core):
shipment.sms_notify(onInTransit— kèm hãng + mã vận đơn,onOutForDelivery,onDelivered; mặc định tắt) quaPUT /api/v1/core/configs/shipment.sms_notify. Người nhận = số của đơn.
Báo cáo shipment.cod_outstanding #
Công nợ thu hộ, quyền shipment.read, chạy qua runReport / exportReport
(docs/fe/cms.md §9). Tham số bắt buộc from, to (YYYY-MM-DD, lọc theo
NGÀY TẠO vận đơn, giờ store). Mỗi dòng là một tổ hợp hãng + trạng thái thu hộ +
tiền tệ: carrier, codStatus, currency, shipments, amount (chuỗi),
oldestCollectedAt (null khi chưa thu).
Chỉ gồm tiền CHƯA nộp về store: pending (vận đơn còn đi, chưa thu) và
collected (hãng đang giữ); bỏ none, remitted, vận đơn returned /
cancelled. summary là dòng tổng, null khi có nhiều tiền tệ. Khác
getShipmentCodSummary: route đó chỉ tính collected, không lọc ngày.
Mẫu in shipment.delivery_note #
Phiếu giao hàng, quyền riêng shipment.print, xem qua printDocument
(docs/fe/cms.md §11); không gửi email (canEmail: false). Gồm hãng, mã vận
đơn, tên + số điện thoại + địa chỉ người nhận, tiền thu hộ, chỗ ký; KHÔNG có ghi
chú nội bộ. Vận đơn chưa có dòng hàng riêng: phiếu liệt kê mọi dòng của đơn, kể
cả khi đơn tách nhiều vận đơn. Có shipment.read mà không có shipment.print
thì không in được, vì bản in lộ thông tin người nhận mà API vận đơn không trả.
Webhook gửi đi shipment.status_changed #
Đăng ký ở màn "Tích hợp" (docs/fe/cms.md §8), người đăng ký cần
shipment.read. Phát cho từng vận đơn khi đổi trạng thái qua
setShipmentStatus và khi huỷ đơn kéo vận đơn chờ sang cancelled. data là
hợp đồng (thêm field được):
{ shipmentId, number, orderId, orderNumber, carrier, from, to, currency, codAmount, codStatus }
Không có ghi chú, lý do, mã theo dõi hay dữ liệu người nhận.
Storefront (StorefrontClient) #
listMyShipments({ query: { order_id } })— theo dõi giao hàng của MỘT đơn của khách đang đăng nhập (đơn của người khác → danh sách rỗng), cũ trước, tối đa 50: số vận đơn, hãng, mã theo dõi, trạng thái, tiền thu hộ, mốc gửi / giao. Hiện ở trang chi tiết đơn (getMyOrder, moduleorder).
Lỗi cần xử lý #
code | Status | FE nên |
|---|---|---|
shipment_order_not_shippable | 409 | đơn chưa xác nhận / đã huỷ — chưa tạo vận đơn được |
shipment_order_not_fulfilled | 409 | giao (xuất kho) đơn trước khi chuyển in_transit |
shipment_invalid_transition | 409 | trạng thái đã đổi → tải lại vận đơn |
shipment_closed | 409 | vận đơn đã kết thúc, không sửa được |
shipment_limit_reached | 409 | đơn đã đủ 50 vận đơn |
shipment_on_the_way | 409 | (ở cancelOrder) vận đơn đang đi — xử lý vận đơn trước |
shipment_cod_not_collected | 409 | chưa thu được tiền (chưa giao xong) → chưa ghi nộp được |
payment_intent_not_payable / payment_currency_mismatch / payment_intent_not_found | 409 / 404 | ý định thanh toán của đơn không nhận được tiền nộp — báo nhân viên đối soát ở module payments |