AstroBaaS

Orders & fulfilment

Shipment Management & Tracking

Free — GPL coresize Mplanned, not built

Generated from docs/plan/core/shipment-management-tracking/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.

Merged from duplicate proposals: “Shipment Tracking”, “Shipment Management & Tracking”

Merchants cannot tell customers where their orders are because there is no shipment entity, tracking numbers, or partial shipment state. This feature introduces shipments as a first-class order fulfillment primitive.

The problem

I have no way to track shipments separately from orders. An order is ‘completed’ or it isn’t — I can’t ship partially, add tracking numbers, or tell a customer their package is in transit. Competitors track shipments; I track orders only.

What it does

  • Add shipments collection: {id, order_id, tracking_number, carrier (UPS|FedEx|USPS|custom), status (pending|shipped|in_transit|delivered|failed), shipped_at, expected_delivery, delivered_at}
  • Support partial shipments: one order can have multiple shipments (e.g., 3-item order ships in 2 boxes)
  • Add shipment_items table to link order line items to shipments (many-to-many)
  • Record carrier tracking URL so customer/staff can click through to carrier tracking page
  • Display shipment list in order detail: table showing tracking number, carrier, status, shipped/delivered dates
  • Update shipment status based on carrier webhook data (if shipping-labels-carrier-sync is implemented)
  • Calculate fulfillment percentage: show % of order items shipped vs total
  • Support manual shipment creation (staff enters tracking number + carrier, no carrier webhook)

What it deliberately does NOT do

Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.

  • Automatic status updates from carriers without webhook infrastructure — defer to shipping-labels-carrier-sync (paid module) for carrier integrations
  • Return shipments or reverse logistics tracking — that is separate returns-exchanges feature
  • Multi-location warehouse management (e.g., ‘ship item X from warehouse A, item Y from warehouse B’) — that is inventory system, separate feature

Data model

shipments collection: {id, order_id, tracking_number, carrier, status, shipped_at, expected_delivery, delivered_at, notes}. shipment_items collection: {shipment_id, order_item_id, quantity}. Migration: introduces new entities and order.fulfillment_status field.

API

  • POST /api/admin/orders/:orderId/shipments — create shipment
  • GET /api/admin/orders/:orderId/shipments — list shipments for order
  • PATCH /api/admin/shipments/:shipmentId — update shipment status or tracking
  • GET /api/admin/shipments/:shipmentId — fetch shipment details with items
  • POST /api/admin/orders/:orderId/shipments/:shipmentId/items — add items to shipment

Every route added here must also appear in src/pages/openapi.json.ts — a test fails the build if it does not.

Admin

Order detail page includes ‘Shipments’ section. Button ‘Create Shipment’ opens modal: select items (checkboxes), enter tracking number, select carrier, set expected delivery. Shipment list shows: tracking number (linked to carrier), carrier, status badge (pending/shipped/in_transit/delivered), shipped date, expected delivery, delivered date. Fulfillment progress bar shows % of order items shipped.

The seam — why this is core

Core owns shipment entity, partial shipment logic, and status tracking. Paid module (shipping-labels-carrier-sync) owns carrier integration and automatic status updates via webhooks. Core ensures shipment state is accurate; paid modules just keep it fresh.

Operational interface seam. No merchant can operate without shipment tracking. This is foundational infrastructure.

Dependencies

  • Existing orders, order_items collections
  • audit_log (to log shipment state changes)

Acceptance checks

Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.

  • Create shipment with 2 of 5 order items and confirm shipment_items stores both items and fulfillment % shows 40%
  • Add tracking number ‘ABC123’ with carrier ‘UPS’ and confirm carrier field is stored correctly
  • Update shipment status from ‘pending’ to ‘shipped’ and confirm shipped_at timestamp is recorded
  • Create 2 shipments for same order and confirm shipment list shows both with different tracking numbers
  • Verify fulfillment progress bar updates as shipments are added (2/5 items shipped = 40%)
  • Verify tracking number and carrier are exposed via API for customer-facing tracking pages

Risks

Partial shipments add complexity: reconciliation logic must ensure no item is shipped twice, and fulfillment status must account for partial states. Implement validation: sum of shipment quantities <= order quantity per line item. Carrier tracking URLs can change format per carrier; store normalized tracking_url for each carrier or use third-party tracking aggregator.

Commercial context

Suggested priceFree
Rival anchorMagento ships shipment entities, tracking numbers, and partial shipment reconciliation free.

The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.


Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full catalogue and ../../AI-GUIDE.md for how to work on this repository.