Files
vmall/openspec/changes/add-freight-templates/tasks.md
T

30 lines
4.6 KiB
Markdown

## 1. Migration and shared contract
- [ ] 1.1 Add migration `0017_freight_templates.sql`: `freight_templates` (shop FK, name, default flag with a partial unique index per shop, always-free toggle, `by_piece`/`by_weight` pricing method, first/additional unit fees as i64 minor units, integer first/additional unit sizes in pieces or grams, optional free-shipping threshold in i64 minor units), `freight_region_rules` (template FK, region code set, overriding fees and unit sizes), `shipping_companies` (code, `{en, zh}` JSONB name), `orders.shipping_fee_minor`, `order_items` pricing-method and template-id snapshot columns, and `shipments.shipping_company_code`, with shop/template indexes and cascading deletes.
- [ ] 1.2 Add shared freight template, region rule, shipping company, and checkout shipping-quote types plus `@vmall/shared` API methods for merchant template CRUD, region-rule editing, company listing, and checkout fee quoting; all money in i64 minor units and weights in integer grams, no floats.
- [ ] 1.3 Implement `apps/api/src/modules/freight/` repository, service, DTO, handlers, and module registration with shop routes scoped through `own_shop` and services returning `ApiResult<Dto>`; add a product-to-template link on the product edit contract, rejecting templates of another shop.
## 2. Calculation service and tests
- [ ] 2.1 Implement the pure shipping calculation service: per-shop grouping by resolved template (product template first, shop default second, zero fee fallback), quantity or integer-weight merging within a group, first-unit fee plus per-additional-unit fees with part units rounding up, always-free and free-shipping-threshold checks before fees, and region-rule fee overrides for matching destinations.
- [ ] 2.2 Wire checkout to the calculation service in the order-creation transaction: require the destination address, compute each shop order's fee server-side ignoring client amounts, add it to the order total, and persist `shipping_fee_minor` plus per-item pricing-method and template snapshots.
- [ ] 2.3 Add focused calculation tests at the boundaries: free-shipping threshold met and unmet, region rule overriding default fees, mixed templates in one shop order, partial additional-unit rounding, by-weight versus by-piece merging, and the no-template zero-fee fallback.
## 3. Shop-admin pages
- [ ] 3.1 Build the shop-admin freight template management page (list, create/edit, default toggle, always-free and threshold fields, pricing method and unit sizes, region-rule editor, delete) reading and writing through `@vmall/shared`, styled with `@vmall/ui` primitives and shared tokens, with a navigation entry beside existing shop operations.
- [ ] 3.2 Extend the shop-admin fulfillment flow with a shipping-company selector populated from the shared dictionary, required before marking an order shipped, showing the recorded company afterwards.
## 4. Mall checkout and mock
- [ ] 4.1 Implement the shared shipping-quote and company client methods in `apps/mall/mock/api.ts` with deterministic fixture templates (per-shop by-piece and by-weight cases plus one region override), and register the shipping surface in Mall API selection with exact shared-client method picks, enabling it in the default live configuration alongside `LIVE_PICKS`.
- [ ] 4.2 Update Mall checkout to select the shipping address before quoting, render each shop group's server-computed delivery fee and the combined shipping total in the selected currency, and show the persisted `shipping_fee` on payment and order detail.
- [ ] 4.3 Add bilingual en/zh checkout shipping strings through the existing Mall locale source without per-page hard-coded copy.
## 5. Verification and tracker cleanup
- [ ] 5.1 Add isolated API integration tests in `apps/api/tests/`, reusing the `tests/common/mod.rs` fixtures, covering freight template CRUD with `own_shop` isolation and single-default enforcement, checkout fee persistence and totals for multi-shop carts, region-rule and free-shipping-threshold edges, snapshot stability after template edits, and shipping-company selection and rejection of unknown companies.
- [ ] 5.2 Build the affected frontends because the shared contract changes: `pnpm --filter @vmall/shop-admin build`, `pnpm --filter @vmall/mall build`, and `pnpm --filter @vmall/admin build`.
- [ ] 5.3 Browser-smoke the running stack: create a template with a region rule in shop-admin, run a two-shop Mall checkout showing per-shop fees and totals, change the address to see fees update, pay, and ship with a selected company.
- [ ] 5.4 Run `openspec change validate add-freight-templates --strict` and `openspec validate --all --strict`, and check every OpenSpec task.