Orders & fulfilment
Bulk Order Actions
Generated from docs/plan/core/bulk-order-actions/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.
Merchants can’t update 50 orders at once; they manually change status one-by-one, which is time-consuming. This feature allows batch operations on multiple orders.
The problem
When I need to update 50 orders (mark as fulfilled, add tag, cancel), I click 50 times. One bulk-action interface would save hours per week.
What it does
- Add ‘Select All’ checkbox to order list to select multiple orders
- Show selection count badge: ‘X orders selected’
- Bulk-action dropdown: ‘Change Status’, ‘Add Tag’, ‘Cancel Orders’, ‘Mark Fulfilled’, ‘Add Note’
- Confirm dialog before bulk action (e.g., ‘Mark 50 orders as fulfilled?’)
- Log each action to order_events with user_id so individual orders retain history
- Show progress bar for long-running bulk actions (e.g., cancelling 500 orders)
- Support filtering + bulk action: filter orders (e.g., fulfillment_status=unfulfilled), then ‘Select All Filtered’ to apply action
- Undo bulk action (within 1 hour): revert all orders to previous state
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.
- Scheduled bulk actions (e.g., ‘mark unfulfilled orders as cancelled at 11:59 PM tomorrow’) — that is scheduling/automation, separate feature
- Conditional bulk actions (e.g., ‘if order total > $100, add VIP tag’) — that is automation/rules engine, separate feature
- Bulk export/import of orders — that is data migration, separate feature
Data model
No new schema; bulk actions are UI wrapper around individual order updates. Audit trail stored in order_events (user_id shows who triggered bulk action, and each order event is logged individually).
API
- POST /api/admin/orders/bulk-action — apply action to multiple orders
- GET /api/admin/orders/bulk-action/:jobId — check status of long-running bulk action
- POST /api/admin/orders/bulk-action/:jobId/undo — undo a bulk action
Every route added here must also appear in src/pages/openapi.json.ts — a test
fails the build if it does not.
Admin
Order list view. Checkbox column with ‘Select All’ in header. Bulk-action toolbar appears when ≥1 order selected: ‘X orders selected’ counter, dropdown with actions (Change Status, Add Tag, Cancel, Mark Fulfilled, Add Note), and ‘Undo’ button if recent bulk actions exist. Clicking action opens modal: select target value (e.g., new status), confirm button, cancel button. Progress bar shown during execution.
The seam — why this is core
Core owns bulk-action UI and batch processing. No paid seam — batch operations are infrastructure.
Core owns the interface + honest batch editor; order operations are infrastructure, not a per-country obligation or credential.
Dependencies
- Existing orders collection
- order-tags (for ‘Add Tag’ action)
- order-notes (for ‘Add Note’ action)
- scheduler (for async bulk processing)
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.
- Select 10 orders and apply ‘Mark Fulfilled’; confirm fulfillment_status updates for all 10 orders
- Verify order_events logs 10 individual events (one per order) with same bulk-action-id linking them
- Apply bulk action to 100 orders and verify progress bar updates during processing
- Undo bulk action and confirm all 100 orders revert to pre-action state within 1 minute
- Filter orders (e.g., status=processing), select all filtered, and apply bulk action; confirm only filtered orders are updated
Risks
Bulk actions on 10,000+ orders can timeout or consume too much memory. Implement chunked processing (1000 orders at a time) and run async in background job. Undo feature requires storing previous state; implement snapshot-on-bulk-action or transaction log.
Commercial context
| Suggested price | free (core) |
| Rival anchor | Shopify: included; Magento: included |
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.