FE: module price — báo giá #
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.
Không có màn hình riêng (không có menu), không có bảng riêng: giá nằm ở
product, thuế ở tax, ưu đãi ở module mở rộng. price là MỘT phép tính dùng
chung cho giỏ, chốt đơn, đơn hàng, POS. Mọi màn hình nhận cùng hình dạng dòng +
tổng tiền dưới đây.
Cách tính #
Giá catalog theo đơn vị bán → ưu đãi đơn giá (bảng giá, giá theo nhóm khách…:
THẤP NHẤT thắng, cao hơn catalog không được dùng) → giảm giá + bù trừ của module
mở rộng theo pha (unit_promo, order_promo, code, shipping, offset) →
thuế của sản phẩm vào ngày hiện tại của store → làm tròn từng dòng theo loại
tiền. FE KHÔNG tự tính lại: hiện đúng số server trả (tiền là chuỗi).
CMS: quotePrices #
quotePrices({ body }) — quyền price.quote. Chỉ đọc, không giữ mã / suất,
không tạo gì. Dùng để xem trước giá trên form tạo đơn thay khách, POS, hoặc kiểm
tra cấu hình bảng giá / thuế. Kênh luôn là admin: bảng giá chỉ áp web /
pos không vào kết quả.
| Field body | Ghi chú |
|---|---|
lines[] (1–200) | variantId, qty (chuỗi > 0, ≤ 4 chữ số lẻ), uomId (null = đơn vị gốc) |
customerId | khách để tính ưu đãi theo khách; null = khách lẻ |
codes[] (≤ 10) | mã khách nhập (giảm giá, thẻ quà…) |
shipping | phí giao trước giảm, chuỗi tiền ≥ 0 |
Response data:
currency,day(ngày của store dùng để chọn thuế suất).lines[]:variantId+variantInfo,uomId+uomInfo,factor,qty,baseQty(theo đơn vị gốc),listPrice(giá catalog),unitPrice(giá áp),priceSource,taxRate,taxInclusive,gross(giá × số lượng),discount,net,tax,total.adjustments[]:source(module),phase,scope(line/order/shipping/offset),amount(dương = giảm cho khách),lineIndex,code,referenceId,label. Mã bí mật (thẻ quà) trả về đã che (****ABCD).totals:subtotal,discountTotal,taxTotal,shippingTotal,offsetTotal,grandTotal.
priceSource: base / explicit / converted = giá catalog (giá biến thể
/ đặt tay cho đơn vị đó / quy đổi); giá trị khác = ưu đãi của module
(price_list, customer_type…). Tập giá trị còn thêm: giá trị lạ thì hiện "giá
ưu đãi", đừng coi là lỗi. Muốn hiện giá gạch: listPrice > unitPrice.
Mã: mỗi mã khác nhau trong codes tính là một lần đoán, theo nhân viên + IP
trong store; hết lượt → 429 too_many_attempts, chờ details.retryAfter giây
(header retry-after). Đừng gọi lại mỗi lần gõ phím: chỉ báo giá khi người dùng
bấm áp mã.
Module khác dùng thế nào #
Không gọi quotePrices; đọc kết quả trên màn hình của module đó, cùng hình dạng
dòng / tổng tiền ở trên:
- Giỏ / chốt đơn (
cart,checkout, storefront):lines[],totals,adjustmentscó sẵn trong response; xem trước không giữ mã, chốt đơn mới giữ. - Đơn hàng (
order): dòng + tổng tiền là BẢN CHỤP lúc đặt, đổi giá / thuế sau đó không ảnh hưởng. - Nguồn giá / giảm: cấu hình ở
price_list,customer_type_price_rule(đơn giá),coupon,gift_card(mã),tax(thuế suất),product(giá + đơn vị).
Lỗi cần xử lý #
Lỗi của một dòng có error.at = "lines.<i>": tô đúng dòng.
code | Status | FE nên |
|---|---|---|
price_variant_unavailable | 409 | details.variantId: hàng ngừng bán / sản phẩm chưa active: bỏ khỏi dòng |
price_uom_invalid | 400 | details.uomId không phải đơn vị bán của sản phẩm: tải lại đơn vị |
price_qty_not_exact | 400 | số lượng × hệ số lẻ quá 4 chữ số ở đơn vị gốc: sửa số lượng |
price_currency_mismatch | 409 | các biến thể khác loại tiền: tách đơn |
price_code_not_recognized | 400 | details.code: mã không dùng được, hiện ở ô mã |
too_many_attempts | 429 | thử sai quá nhiều: khoá ô mã details.retryAfter giây |