AstroBaaS

Orders & fulfilment

Order Status History

Free — GPL coresize Mplanned, not built

Generated from docs/plan/core/order-status-history/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.

Merchants need to see when an order was placed, shipped, delivered, or refunded to understand the customer lifecycle. This feature logs and displays order state changes chronologically.

The problem

I don’t have a clear record of when an order progressed through states (placed, processing, shipped, delivered, refunded). I manually track events in notes, and I lose visibility when someone else handles the order.

What it does

  • Create order_events collection to log every state change: {order_id, timestamp, old_status, new_status, user_id (who triggered), reason}
  • Capture automatic events: order placed, payment captured, refund initiated, shipment created
  • Capture manual events: status changed by staff, notes added, tags applied, customer contacted
  • Display status history table in order detail: chronological list of all events with timestamp, old status, new status, who changed it, why
  • Show event actor: staff member name or ‘system’ if automated
  • Filter history by event type (e.g., show only payment events, or only status changes)
  • Export order history as CSV for accounting or dispute resolution

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.

  • Automated status progression based on third-party webhooks (e.g., Stripe → payment captured) — that is payment-gateway integration, separate feature; core only logs events
  • Customer-facing order history — this is storefront feature, not admin infrastructure
  • Audit trail for admin actions (who viewed the order, when) — that is general audit logging, separate feature

Data model

order_events collection: {id, order_id, timestamp, old_status, new_status, event_type (status_change|payment|note|tag|contact), user_id, reason/message}. Migration: add to schema.

API

  • GET /api/admin/orders/:orderId/events — list all events for an order
  • GET /api/admin/orders/:orderId/events?type=payment — filter events by type
  • POST /api/admin/orders/:orderId/events — manually log event (e.g., staff notes a reason for status change)

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 ‘History’ tab showing chronological timeline. Each row: timestamp, old status → new status, event type icon, actor name (staff or ‘system’), reason/message. Clickable filters: ‘All Events’, ‘Status Changes’, ‘Payments’, ‘Notes’, etc.

The seam — why this is core

Core owns event logging schema and history UI. Events are logged by core actions (status transitions) and staff actions (manual edits). No paid seam — order auditing is infrastructure.

Core owns the interface + honest status tracker; order auditing is infrastructure, not a support commitment or credential.

Dependencies

  • Existing orders collection
  • order-status-history must trigger logging on status change
  • existing admin dashboard

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.

  • Change order status from ‘processing’ to ‘shipped’ and confirm order_events logs old_status=‘processing’, new_status=‘shipped’
  • Verify timestamp is accurate (within 1 second of actual change time)
  • Confirm event_type matches the action (e.g., ‘status_change’ for status updates)
  • Verify history table shows all 10+ events for order without pagination issues
  • Confirm filter by event type shows only matching events (e.g., filter ‘payment’ shows only payment-related events)

Risks

High-volume orders (many status changes per second during batch processing) can cause order_events collection to grow rapidly. Implement retention policy (90 days) and index on (order_id, timestamp) for fast retrieval. Ensure logging is async to avoid blocking status change operations.

Commercial context

Suggested pricefree (core)
Rival anchorShopify: 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.