Orders & fulfilment
Fulfillment & Shipping Labels
Indicative price, not an offer: €199–499/month depending on order volume (e.g., €199 for <1000/mo, €399 for <5000/mo); per-label fees offset; owner sets
Generated from docs/plan/paid/fulfillment-shipping-labels/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.
Merged from duplicate proposals: “Shipping Labels & Fulfillment Network”
A fulfillment management system for warehouse teams to pick and pack orders, track progress, and print shipping labels. Supports order assignment to bins, pick-list generation, packing verification, and 3PL handoff tracking.
The problem
Warehouse teams pick orders from paper printouts with zero coordination or tracking; misshipments occur, staff can’t track progress, and 3PL handoffs are manual. As order volume grows, the operation collapses.
What it does
- Assign orders to pick bins or batches (by warehouse location, FIFO, or custom grouping)
- Generate pick lists (PDF or mobile app) with item locations and quantities
- Track pick status (not-started, in-progress, completed, error)
- Verify packed items before shipping (scan barcodes or manual checklist)
- Packing slip generation (packing list + address label on one page)
- Shipping label integration (fetch from carrier-integrations module)
- Generate batch labels for mass printing (zebra printer support)
- Track 3PL handoff: scan shipment batch, record timestamp, courier confirmation
- Mark order as shipped (auto-set order status and send customer notification)
- Reverse pick (return/exchange workflow): mark items as received, verify condition
- Warehouse location management (bin codes, SKU locations, barcode mapping)
- Audit trail: who picked, when, what was packed, discrepancies
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.
- Inventory sync on pick — picking does not auto-decrement inventory. Reason: inventory is managed by a separate subsystem.
- Route optimization — core does not suggest optimal pick order within warehouse. Reason: advanced warehouse operations planning (WMS) is separate.
- Real-time warehouse visibility (GPS tracking of pickers) — not included. Reason: requires mobile device tracking; support SLA commitment not in scope.
- Quality control/inspection — core does not enforce photographic proof or damage reporting. Reason: QC is paid add-on.
- Kitting (pre-assembled sub-bundles) — not supported. Reason: complex fulfillment logic; separate feature.
- Cross-docking (temporary holding for consolidation) — not supported. Reason: advanced fulfillment pattern; separate feature.
Data model
New tables: PickBatch {id, warehouseId, batchNumber, createdAt, status (‘open’|‘in_progress’|‘completed’), pickedBy (userId), completedAt}; PickBatchItem {id, batchId, orderId, lineItemId, quantity, location (bin code), status (‘not_started’|‘picked’|‘verified’), pickedAt}; PackingSlip {id, orderId, batchId, packingSlipPdf (artifact ID), generatedAt}; ShipmentHandoff {id, batchId, carrierId, handoffTimestamp, couriers (array of {name, signature_timestamp}), receiptConfirmed}; WarehouseLocation {id, warehouseId, binCode, productId, quantity, lastUpdatedAt}. No migration.
API
- POST /api/fulfillment/batches
- GET /api/fulfillment/batches/:batchId
- POST /api/fulfillment/batches/:batchId/pick-list
- PUT /api/fulfillment/batches/:batchId/items/:itemId
- POST /api/fulfillment/batches/:batchId/verify
- POST /api/fulfillment/batches/:batchId/packing-slip
- POST /api/fulfillment/batches/:batchId/labels
- POST /api/fulfillment/batches/:batchId/handoff
- GET /api/fulfillment/locations/:warehouseId
- PUT /api/fulfillment/locations/:locationId
Every route added here must also appear in src/pages/openapi.json.ts — a test
fails the build if it does not.
Admin
Fulfillment dashboard: pending orders, in-progress batches, completed batches. Create batch: multi-select orders, assign to warehouse, generate pick list. Pick list view: PDF or mobile HTML; show item location, quantity, barcode. Packing verification: checklist of items in batch, scan/check each, flag discrepancies. Label printing: view generated labels, queue for printer, download bulk labels (ZPL). 3PL handoff: scan batch barcode, record courier details, confirm receipt. Warehouse location map: visual or table of bin codes, SKUs, quantities. Audit trail.
The seam — why this is paid
Core owns: order status transitions (mark as shipped), basic fulfillment UI. Paid owns: warehouse management, pick-list generation, barcode scanning, 3PL integration, SLA tracking.
The paid pack owns the support commitment (fulfillment is operational software with SLA requirements, not just an API); per-warehouse configuration and compliance with regional labor/shipping regulations.
Dependencies
- Order/checkout infrastructure (orders must exist, line items must be queryable)
- carrier-integrations (to fetch shipping labels)
- Artifact storage (to store PDFs: pick lists, packing slips, labels)
- Settings system (warehouse locations, default carrier)
- Notification system (send shipping confirmation to customer)
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.
- Creating a pick batch with orderIds=[1, 2, 3] and warehouseId=‘WH-01’ creates PickBatch with 3 PickBatchItems
- Generating pick list for batch returns PDF with order ID, item SKU, location (bin code), quantity
- Marking an item as picked updates PickBatchItem.status to ‘picked’ and records timestamp
- Verifying batch when all items are marked ‘picked’ returns {verified: true}; if any item not picked, returns {verified: false, discrepancies: […]}
- Generating packing slip creates one PDF per order with items, quantities, shipping address, order notes
- Fetching labels from batch calls carrier-integrations and returns one label per order in batch
- Recording 3PL handoff sets ShipmentHandoff.handoffTimestamp and couriers array; subsequent handoff attempts return error (already handed off)
- Audit log records every pick action with userId, timestamp, item details (no customer PII)
- Warehouse location update: reducing bin quantity from 10 to 8 records oldQuantity=10, newQuantity=8 in audit log
- Batch completion: marking all items as picked and verified auto-sets order status to ‘packed’ (not ‘shipped’ yet)
Risks
Pick theft: packer marks items as picked without actually picking; product goes missing; mitigation: barcode scanning enforced. Double-shipment: same order shipped twice; mitigation: order status lock. Location collision: two batches assigned same bin; mitigation: warehouse-location-level lock. Label mismatch: wrong label printed for order; mitigation: label generation queries carrier-integrations with correct order ID.
Commercial context
| Suggested price | €199–499/month depending on order volume (e.g., €199 for <1000/mo, €399 for <5000/mo); per-label fees offset; owner sets |
| Rival anchor | Shopify Fulfillment Network (integration via Plus, €2000+/month), ShipHero (€300–800/month), SkuVault (€499–2000/month), Extensiv (€600+/month) |
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.