Customers & accounts
Customer Profiles
Generated from docs/plan/core/customer-profiles/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.
Customer Profiles show merchants a comprehensive view of each customer — purchase history, total spent, last order date, customer lifetime value, and communication preferences.
The problem
Merchants can’t see a customer’s purchase history; VIP customers are treated like one-time buyers.
What it does
- Customer detail: email, name, phone, address(es), VIP flag
- Purchase history: order list, total spent, status, payment method
- Lifetime value (LTV): total amount spent, AOV, purchase frequency
- Repeat customer indicator
- Notes integration: show customer-notes
- Tags/segments: show segments customer belongs to
- Communication preferences: email opt-in, SMS
- Account creation date, first/last purchase date
- Contact history (if email module enabled)
- Search by email, phone, name
- Bulk actions: export to CSV, apply segment to multiple
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.
- Customer credit/store credit balance — payment-terms paid pack
- Predictive churn score — paid analytics pack
- Automatic VIP assignment (LTV > 1000 EUR) — manual flag only
- Customer merge/deduplication — separate scope
- Loyalty points display — loyalty-program paid pack
- Graph of spending over time — analytics separate
Data model
Customer: id, store_id, email, name, phone, addresses (JSON or FK), is_vip, created_at, last_purchase_at. Address: id, customer_id, type, street, city, postal_code, country. LTV calculated (SUM orders), not stored. Migration: add/update Customer table.
API
- GET /admin/customers
- GET /admin/customers/{id}
- PATCH /admin/customers/{id}
- GET /admin/customers/{id}/orders
- GET /admin/customers/{id}/notes
- GET /admin/customers/{id}/segments
- DELETE /admin/customers/{id} (anonymize)
- POST /admin/customers/export
Every route added here must also appear in src/pages/openapi.json.ts — a test
fails the build if it does not.
Admin
Customer list: table of email, name, LTV, order count, last purchase, VIP, segment tags. Detail page: contact info, addresses, VIP toggle, order history, LTV stat card, notes, segments. Search, filters (VIP, repeat, first-time, by segment, by date). Bulk export: CSV.
The seam — why this is core
Core owns: Customer table, order history query, LTV calculation, profile UI. Paid module owns: nothing; core infrastructure.
Core owns the interface + honest customer viewer; customer insight is infrastructure, not a support commitment or credential.
Dependencies
- customer-notes (optional)
- behavioral-segmentation (optional)
- email-marketing-automation-segmentation (optional)
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.
- Profile shows email, name, phone, addresses from Order billing/shipping
- LTV displays 1234.56 EUR across 5 orders (SUM of Order.total)
- Repeat badge if purchase_count > 1
- Search ‘john@example.com’ returns match
- Export 10k customers to CSV: email, name, phone, LTV, order count, last purchase, VIP
- Filter ‘segment:gold_members’ returns segment members
- GDPR delete: name to [deleted], email to null, addresses to null; orders remain
- Detail loads < 1s even with 100+ orders (indexed)
Risks
LTV slow on large order history (no index). Export 1M customers causes memory exhaustion. Hard-delete cascades to orders. Search case-sensitive. Phone format varies. VIP flag has no undo.
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.