PRD: Customer management
| Module | User Management (CORE-01) | PRD ID | PRD-CUS-001 |
| Status | In-progress | Owner | Identity squad |
| Date | 2026-03-15 | Version | v0.1 |
| Packages | @nx/identity · @nx/sale · @nx/core | URD | CUS |
TL;DR
Gives merchants a first-class Customer that a sale order can attach to, and a path to promote a sale-captured customer into a full user account carrying the Customer role. The result: orders record who they were for, and the people behind them can become authenticated, organization-linked users without duplicate identities.
1. Context & Problem
Sale orders need a real customer to attach to. Before this increment there is no Customer entity owned by an organization, so an order cannot record who it was for, and a customer captured at the point of sale can never become an authenticated user. Merchants lose the link between an order and the person behind it, and the same customer can be re-keyed across sales with no shared identity.
This increment introduces a Customer entity centralized in @nx/core, wires customer management into the sale package for sale orders, and adds a registration path in identity that promotes an existing sale-level customer into a full user account with the Customer role - guarded by identifier-conflict checks so the same email/phone/username is never claimed twice. It delivers the CUS feature area defined in the User Management URD.
2. Goals & Non-Goals
Goals
- A
Customerentity (model + schema + repository) for organization-linked customers, reused acrosssaleandidentity. - Customer CRUD scoped to sale orders in the
salepackage, with customer attachment to aSaleOrder. - Promotion of a sale-level customer into a full user account carrying the Customer role, via a dedicated
CustomerRegistrationServiceinidentity. - Identifier-conflict checks (username / email / phone) before promotion creates the user.
Non-Goals
- Custom role creation or dynamic permission management → Permissions.
- Customer self-service sign-up / OAuth login.
- Multi-organization customer access for a single user.
- Loyalty / point accrual and customer engagement (owned later, outside this increment).
3. Success Metrics
| Metric | Target / signal |
|---|---|
| Order attribution | Sale orders carry a Customer reference where a customer is known |
| Identity de-duplication | Promotion never creates a duplicate identifier; conflicts blocked, not silently merged |
| Promotion success | A promoted customer signs in (post-credential) and resolves the Customer role + organization scope |
| Reuse | One Customer model serves both sale and identity - no parallel customer tables |
4. Personas & Use Cases
| Persona | Goal |
|---|---|
| Owner | Create and maintain customers under their organization; promote a known buyer into a full account |
| Cashier / Employee | Attach a customer to a sale order at the point of sale |
| Customer | Be linked to an organization and (after promotion) hold a Customer-role account |
Core scenarios: create a customer under an organization → attach the customer to a sale order → later, promote that sale-level customer into a full Customer-role user, with identifier-conflict checks blocking duplicates.
5. User Stories
- As an owner, I want to create customer accounts under my organization, so orders can be attributed to a known buyer.
- As an owner, I want a created customer to receive the Customer role automatically and be linked to my organization, so scope is correct without extra steps.
- As a cashier, I want to attach a customer to a sale order, so the order records who it was for.
- As an owner, I want to update or soft-delete customer information, so records stay accurate and nothing is lost permanently.
- As an owner, I want to promote a sale-level customer into a full user account, so a recurring buyer becomes an authenticated user.
- As an owner, I want promotion to check for identifier conflicts first, so the same email / phone / username is never claimed twice.
6. Functional Requirements
| # | Requirement | URD ref |
|---|---|---|
| FR-1 | Owner can create customer accounts scoped to an organization | URD-CUS-001 |
| FR-2 | A customer is linked to an organization and receives the Customer role automatically | URD-CUS-002 |
| FR-3 | Customer profile holds name and contact details | URD-CUS-003 |
| FR-4 | Customer information can be updated and soft-deleted | URD-CUS-004 |
| FR-5 | A customer can be attached to a SaleOrder (customer CRUD lives in the sale package) | URD-CUS-001..004 |
| FR-6 | A sale-level customer can be promoted to a full user account via CustomerRegistrationService | URD-CUS-005 |
| FR-7 | Promotion checks for identifier conflicts (username / email / phone) before creating the user | URD-CUS-006 |
Full requirement text and acceptance criteria live in the User Management URD. This PRD references them rather than restating them.
7. Non-Functional Requirements
| Area | Requirement |
|---|---|
| Data integrity | Customer create/promote is atomic - a partial promotion never leaves a half-created user |
| Identity uniqueness | Each identifier type is globally unique; promotion enforces conflict checks before write |
| Reuse | A single Customer model in @nx/core is shared by sale and identity - no duplicate schema |
| Tenancy & authz | Customers are scoped to an organization; operations are permission-gated |
| Soft-delete | Customer records use soft-delete; data is never physically removed |
| i18n | User-facing labels are bilingual ({ en, vi }) |
8. UX & Flows
Key screens (in apps/client): customer management on sale orders, customer create/edit, and the attach-to-order control.
9. Data & Domain
| Entity | Role |
|---|---|
Customer | Organization-linked customer (model + schema + repository) in @nx/core, reused by sale and identity |
SaleOrder | Carries a customer reference; customer attachment lives in the sale aggregate |
User + Customer role | The promoted full account created by CustomerRegistrationService |
Identifier | Username / email / phone checked for conflicts before promotion |
Conceptual only - full schema and invariants in the identity domain model.
10. Dependencies & Assumptions
Depends on
- User Account & Roles (URD-USR · URD-ROLE) - promotion creates a user and assigns the Customer role.
- Organization (
@nx/core/ Commerce) - a customer is linked to an organization. - Sale orders (
@nx/sale) - customer CRUD is scoped to sale orders, and a customer attaches to aSaleOrder.
Assumptions
- The merchant operates under an organization that owns the customer.
- The eight fixed roles (incl. Customer) are pre-seeded and available for assignment.
11. Risks & Open Questions
| Risk / question | Mitigation / status |
|---|---|
| Promotion could create a duplicate identity | Identifier-conflict checks block before user creation |
| Promoted customers have no credential yet | Known gap - customer accounts are created without credentials, so sign-in is not yet possible |
| Partial promotion on failure | Create/promote is atomic; no half-written user |
| Multi-organization customers | Out of scope; one customer is linked to one organization |
12. Release Plan & Launch Criteria
| Aspect | Plan |
|---|---|
| Phase | P2 - see URD feature catalog (CUS is In-progress; partial delivery of the area) |
| Rollout | All merchants; no feature flag |
| Migration | New entities (Customer); no data migration |
| Launch criteria | Create customer → attach to sale order verified; promotion creates a Customer-role user with conflict checks; one shared Customer model across sale + identity |
| Monitoring | Customer create/promote error rate, identifier-conflict rejections, orders-with-customer coverage |
13. FAQ
Where does the Customer entity live? In @nx/core (models/schemas/sale/customer), so both sale and identity reuse one model - there is no parallel customer table.
Does creating a customer create a login? No - a created customer is an organization-linked record. Promotion turns a sale-level customer into a full user with the Customer role; credentials (and sign-in) are a separate, later concern.
What happens if the email or phone is already taken? Promotion is blocked with a conflict error. Identifiers are globally unique per type and are checked before the user is created.
Can one customer belong to multiple organizations? No - multi-organization access for a single customer is out of scope.
Is loyalty / points part of this? No - customer engagement and loyalty are handled later, outside this increment.
References
- URD: User Management - Customer Management - requirements (
CUSarea) - Related: URD - User Account · Roles & Scoping
- Module: User Management - overview + traceability
- Developer: @nx/identity · @nx/sale