FE: module tax — thuế #
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.
Chỉ có ở CMS (XforgeClient). Storefront không gọi gì: thuế hiện thẳng trong
giỏ / chốt đơn (lines[].taxRate, taxInclusive, tax; totals.taxTotal).
Mô hình #
nhóm thuế (code, name, isDefault) vd STANDARD, REDUCED, EXEMPT
└─ thuế suất rates[]: rate (%), inclusive, [effectiveFrom, effectiveTo)
sản phẩm → một nhóm (không gán = nhóm mặc định của store)
Thuế của một dòng vào một ngày: nhóm gán riêng → nhóm mặc định → không thuế. Không có thuế suất hiệu lực vào ngày đó = 0%. "Ngày" là ngày theo giờ store. Đơn đã đặt giữ bản chụp: sửa thuế suất không đổi đơn cũ.
CMS / admin #
Menu: key tax.classes (quyền tax.read).
| Việc | Method | Quyền |
|---|---|---|
| Danh sách nhóm | listTaxClasses({ query }) | tax.read |
| Picker | listTaxClassOptions({ query }) → { id, code, name, active } | tax.read |
| Chi tiết | getTaxClass({ params: { id } }) | tax.read |
| Tạo | createTaxClass({ body }) | tax.create |
| Sửa một phần / thay hết | updateTaxClass / replaceTaxClass | tax.update |
| Xoá (vào thùng rác) | deleteTaxClass({ params: { id } }) | tax.delete |
| Thùng rác / khôi phục | listTaxClassTrash / restoreTaxClass | tax.restore |
| Xoá vĩnh viễn | deleteTaxClass({ params: { id }, query: { force: "true" } }) | tax.delete + tax.hard_delete |
| Thuế suất của nhóm | listTaxRates({ params: { id } }) | tax.read |
| Thêm / thay / xoá thuế suất | createTaxRate / replaceTaxRate / deleteTaxRate | tax.update |
| Nhóm của một sản phẩm | getProductTaxClass({ params: { productId } }) | tax.read |
| Gán nhóm cho sản phẩm | setProductTaxClass({ params: { productId }, body: { taxClassId } }) | tax.update |
- Nhóm:
codeduy nhất trong store. Mỗi store tối đa MỘT nhómisDefault: true: muốn đổi, tắt nhóm cũ trước rồi bật nhóm mới (không thì 409tax_default_exists). Danh sách lọcactive,qtìm mã + tên. active: falsechỉ để lọc / ẩn ở picker, KHÔNG làm ngừng áp thuế: sản phẩm đang gán nhóm (hoặc nhóm đang mặc định) vẫn tính theo nó. Muốn ngừng: gán nhóm khác, bỏisDefault, hoặc cho thuế suất hết hạn.- Thuế suất:
ratelà CHUỖI phần trăm 0–100, ≤ 4 chữ số lẻ ("10"= 10%; response có dạng"10.0000").effectiveFrom/effectiveTolàYYYY-MM-DDtheo giờ store,effectiveFromtính,effectiveToKHÔNG tính;effectiveTo: null= không hết hạn. Các khoảng của một nhóm không được chồng nhau: đổi thuế suất từ một ngày = đặteffectiveTocủa dòng cũ (replaceTaxRategửi đủ field) rồi tạo dòng mới từ đúng ngày đó.listTaxRateskhông phân trang, mới nhất trước. inclusive: true= giá bán của sản phẩm trong nhóm ĐÃ gồm thuế (giá bán không đổi khi đổi thuế suất, tiền thuế tách ra từ giá);false= cộng thuế lên giá.- Form sản phẩm:
getProductTaxClasstrảtaxClassId(null = chưa gán riêng) +effectiveTaxClassId/effectiveTaxClassInfo(nhóm áp thật; null = không thuế). Hiện "Mặc định (<tên nhóm>)" khitaxClassIdnull. GửitaxClassId: nullđể bỏ gán. Nhóm thuế không nằm trongupdateProduct: lưu riêng qua route này. - Xoá nhóm: sản phẩm gán nhóm đó quay về nhóm mặc định; module phụ thuộc có thể
chặn (409 mã của module đó, hiện
error.message). - Xem thử số thuế của một đơn:
quotePrices(FE củaprice).
Lỗi cần xử lý #
code | Status | FE nên |
|---|---|---|
tax_not_found | 404 | nhóm không có / đã vào thùng rác: tải lại picker |
tax_code_exists | 409 | báo ở ô code |
tax_default_exists | 409 | store đã có nhóm mặc định: bỏ isDefault của nhóm đó trước |
tax_rate_not_found | 404 | tải lại danh sách thuế suất |
tax_rate_period_invalid | 400 | effectiveTo phải sau effectiveFrom |
tax_rate_overlaps | 409 | details.rateId = dòng bị chồng: tô dòng đó, sửa khoảng ngày |
tax_product_invalid | 400 | sản phẩm không có trong store / đã vào thùng rác |