Pricing & promotions
Draft Orders & Approval Workflow
Indicative price, not an offer: €12–20/month
Generated from docs/plan/paid/draft-orders-approval-workflow/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.
A paid module that enables B2B sales workflows: sales staff create draft orders (items, quantities, customer, negotiated price), save as draft (no payment charged), and submit for manager approval. Manager reviews draft, approves (sends to customer for payment), rejects, or requests changes. Draft order stays in limbo until approved; payment is collected only after approval and customer confirms.
The problem
High-value B2B customers negotiate prices and payment terms before orders are placed. Currently, sales staff create an order in the system, but merchant has no way to require approval before payment or delivery. Draft orders are a standard B2B CMS feature, missing from AstroBaaS.
What it does
- Draft order creation: sales staff fills in customer, items, quantities, negotiated prices (override standard prices), discount reason, notes for manager
- Draft state: order is NOT sent to customer, payment is NOT charged, inventory is NOT decremented
- Approval workflow: draft order appears in manager dashboard with ‘Approve’, ‘Reject’, ‘Request Changes’ buttons
- Approval conditions: manager can add conditions (e.g., ‘approve only if total < €10k’)
- Change requests: manager clicks ‘Request Changes’ → form to describe what to adjust; draft bounces back to sales staff
- Send to customer: manager approves → draft converts to order, customer receives payment link via email, order enters ‘pending_payment’ state
- Audit trail: log all draft edits, approvals, rejections, comments from sales staff and manager
- Notifications: email alerts for drafts awaiting approval, approvals/rejections
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.
- Purchase order (PO) file upload and matching (too specific; out of scope)
- Invoice generation (separate module owns this)
Data model
Add draft_orders table: { id, shop_id, customer_id, items (JSON), total_minor_units, discount_reason, created_by_user_id, created_at, status (‘draft’, ‘pending_approval’, ‘changes_requested’, ‘approved’, ‘rejected’) }. Add draft_order_approvals table: { id, draft_id, approved_by_user_id, approval_at, approval_decision, conditions (JSON), comments }. Schema migration: new tables.
API
- POST /admin/draft-orders — create draft order
- GET /admin/draft-orders?status=pending_approval — list drafts awaiting approval
- PUT /admin/draft-orders/:id — edit draft (sales staff)
- POST /admin/draft-orders/:id/submit-for-approval — submit draft to manager review
- PUT /admin/draft-orders/:id/approve — manager approves (converts to order, sends payment link)
- PUT /admin/draft-orders/:id/reject — manager rejects
- PUT /admin/draft-orders/:id/request-changes — manager asks for edits
Every route added here must also appear in src/pages/openapi.json.ts — a test
fails the build if it does not.
Admin
Add ‘Draft Orders’ in Commerce > Orders. Tab: ‘Pending Approval’ lists drafts with customer, total, created date, and ‘Approve/Reject/Request Changes’ buttons. Click draft to view full order detail: items, prices, discount reason, sales staff notes. Approval form: conditions (optional), comments, action (approve/reject/request changes). History tab: shows all edits and approvals.
The seam — why this is paid
Paid module owns the draft order workflow (creation, approval, state transitions). Core order system owns the final order model; draft orders are a wrapper around it.
B2B and high-volume sales feature. Most retail shops don’t need this; sales-driven shops do. Specialized workflow justifies paid tier.
Dependencies
- Order system (draft orders must convert to orders)
- User/permissions system (sales staff and manager roles must exist)
- Email system (to notify manager of awaiting approval, send payment link)
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.
- Sales staff creates draft order: customer=‘Retailer XYZ’, items=[shoe-001 x 10], total=€500 with 20% discount
- Draft is NOT visible to customer, payment is NOT charged, inventory is NOT decremented
- Manager reviews draft in ‘Pending Approval’ tab, sees discount reason ‘negotiated by sales’
- Manager clicks ‘Approve’ → draft converts to order #12345, customer receives email ‘Your order is ready, pay here’
- If manager clicks ‘Request Changes’, sales staff receives notification, draft returns to pending_approval when resubmitted
- Audit log shows: ‘draft created by sales@, submitted for approval, rejected by manager@ with reason: total too high’
Risks
If draft orders can be converted to paid orders without explicit approval, workflow is bypassed (always check approval status before charging). If customer can see draft orders in their account, they may be confused (drafts are internal only; customers see only approved orders).
Commercial context
| Suggested price | €12–20/month |
| Rival anchor | Magento Open Source (not included); Adobe Commerce (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.