PRD: Organization & merchant
| Module | Commerce (CORE-03) | PRD ID | PRD-ORG-001 |
| Status | Shipped | Owner | Commerce squad |
| Date | 2026-06-01 (v1.1: 2026-06-12 · v1.2: 2026-06-15) | Version | v1.2 |
| Packages | @nx/commerce · @nx/core | URD | ORG · MER · ACC |
Changelog — v1.2 (2026-06-15): Documents the onboarding internals the earlier versions skipped: the two onboarding paths (self-service vs administrative aggregate), the aggregate two-phase saga with compensation, idempotency, license issuance against the new owner, the hardcoded defaults (headquarter merchant, sale channels, F&B category templates), the six onboarding steps, the three owner-grant rows, merchant enum defaults, the read-path scoping note, and the no-maximum-merchants rule. All v1.1 and earlier content is unchanged.
TL;DR
Lets a business owner stand up their whole structure in one step: an organization (the brand) and its merchants (the legal selling units), each with sale channels and categories. Afterwards a merchant is saved together with its channels and categories in a single step, so the structure is never half-built. A pre-submit slug check guards uniqueness, and role-filtered launchpads show each user only the organizations and merchants they are allowed to see.
1. Context & Problem
Everything in KICKO hangs off a merchant - products, orders, inventory, finance. The first thing a new owner needs is a business structure: one organization for the brand and at least one merchant for the legal selling unit, each with its sale channels and categories. Building that piece by piece is slow, error-prone, and leaves half-built businesses when a step fails midway; slug clashes surface late; and there is no consistent rule for which organizations and merchants a user may see. This feature stands the whole structure up in one step, lets a merchant be saved together with its channels and categories, checks slugs before submit, and filters every list by the user's role.
2. Goals & Non-Goals
Goals
- One-step onboarding that creates the organization, a default merchant, its sale channels, and owner access together - all of it or none of it.
- Save a merchant together with its categories and sale channels in one step. Within that save, an item sent with its details is updated, a new item is added, and an item marked for removal is removed.
- A pre-submit slug check confirming uniqueness - global for organizations, per-organization for merchants.
- Role-filtered launchpads (summaries and overviews, including how many users hold each role) so each user sees only the organizations and merchants their role permits.
- A reworked organizer back-office (create/edit pages, role visibility).
- Organization vs merchant principles - the organization stays a virtual brand; every legal and financial attribute belongs to a merchant, never to the organization.
Non-Goals
- Cross-organization access or sharing merchants between organizations.
- Ownership transfer (Planned).
- Managing sale channels or categories on their own, outside the combined merchant save (Planned).
- Permanent deletion - everything is deactivated or archived and can be restored.
3. Success Metrics
| Metric | Target / signal |
|---|---|
| Onboarding success | Every completed onboarding yields an organization, default merchant, channels, and owner access - or leaves nothing behind |
| Slug integrity | No duplicate organization slugs globally; no duplicate merchant slugs within an organization |
| Save integrity | No partially-saved merchant updates (no leftover channels or categories) |
| Isolation between businesses | No data of one business visible to another through role-filtered lists |
| Onboarding time | Median time from sign-up to a usable merchant trends down |
4. Personas & Use Cases
| Persona | Goal |
|---|---|
| Business Owner | Onboard a business, manage the organization and its merchants, control channels and categories |
| Manager | Manage the merchants in scope and their channels and categories |
| Employee | View only the merchants they are assigned to |
| Super Admin | See all organizations and merchants (no role filtering) |
Core scenario: a new owner onboards (organization + default merchant + channels + access in one step) → adds more merchants one at a time, several at once, or together with their categories and channels → edits a merchant and its channels and categories in a single save → each user opens a launchpad showing exactly the organizations and merchants their role permits.
5. User Stories
- As a business owner, I want onboarding to create my organization, a default merchant, its sale channels, and my owner access in one step, so I can start selling without setting up each piece by hand.
- As a business owner, I want to add, change, or remove a merchant's categories and sale channels in a single save, so the whole merchant is reconciled at once and never left half-applied.
- As a business owner, I want slug uniqueness checked before I submit, so I never lose a form to a late clash.
- As an employee, I want my launchpad to show only the merchants I am assigned to, so I never see another business's data.
- As a super admin, I want to see every organization and merchant, so I can support and audit across businesses.
6. Functional Requirements
| # | Requirement | URD ref |
|---|---|---|
| FR-1 | Onboarding creates organization + default merchant + sale channels + owner access together, all-or-nothing; the creating user becomes Owner | URD-ORG-001..003 · URD-MER-001 · URD-SC-001 |
| FR-2 | Organization requires a multilingual name and a slug; a non-editable identifier is assigned on creation | URD-ORG-004..005 |
| FR-3 | Organization and merchant can be found by identifier, falling back to slug; owner can update the organization profile | URD-ORG-006..007 · URD-MER-009 |
| FR-4 | The combined save supports file attachments on the organization | URD-ORG-008 |
| FR-5 | Owner can create a merchant one at a time, several at once, or together with its categories and sale channels | URD-MER-002..004 |
| FR-6 | Merchant slug is unique within its organization; a slug check confirms organization/merchant uniqueness before submit | URD-MER-005 · URD-ORG-004 |
| FR-7 | A merchant can be viewed with its channels and categories; owner can update merchant information | URD-MER-006..007 |
| FR-8 | In the combined save, an item with its details is updated, a new item is added, and an item marked for removal is removed - with removal kept distinct from "leave unchanged" | URD-MER-008 · URD-MER-015 |
| FR-9 | Organization and merchant lists, and their totals, are role-filtered (Admin sees all) | URD-ORG-009 · URD-MER-010..011 · URD-ACC-004..005 |
| FR-10 | Owner sees only their own organization and merchants; owner can create, view, and update them; an unrecognized role is denied, never shown an empty list | URD-ACC-006..007 · URD-ACC-012 |
| FR-11 | Launchpads return role-filtered summaries and overviews, including how many users hold each role | URD-ORG-009 · URD-MER-010 |
| FR-12 | Organization/merchant can be deactivated (reversible), designate a headquarter merchant, or be archived (read-only) | URD-ORG-010..012 |
| FR-13 | All legal and financial attributes belong to the merchant - business type, tax identity, e-invoice details, finance accounts and wallets, currency - and never to the organization | URD-MER-016 |
| FR-14 | Every organization has exactly one headquarter merchant - created at onboarding and recorded on the organization in the same step | URD-MER-017 |
| FR-15 | A merchant's sectors must be valid business sectors; onboarding sets up the default sale channels and category templates for those sectors | URD-MER-018 |
| FR-16 | The merchant is where tax identity is entered; the e-invoice profile then reuses it automatically, with no re-entry | URD-MER-019 |
| FR-17 | Two onboarding paths exist: self-service onboarding runs in one local transaction and grants the calling user Owner with no license; administrative (aggregate) onboarding provisions a new owner user plus a license | URD-ORG-014..015 |
| FR-18 | Administrative onboarding is a two-phase operation - phase 1 creates the organization, headquarter merchant, and defaults locally; phase 2 provisions the owner user, owner grant, and license - and fully compensates in reverse on a phase-2 failure | URD-ORG-015 |
| FR-19 | Administrative onboarding is idempotent: an Idempotency-Key (request header or payload) replays a completed result and rejects a concurrent retry as in-progress | URD-ORG-016 |
| FR-20 | The license is issued against the new owner user; its activation / contract code is echoed back to the caller, never stored | URD-ACC-013 |
| FR-21 | Onboarding auto-creates a fixed default set - exactly one headquarter merchant (derived slug, "Headquarter" name, headquarter flag, direct tax method), two sale channels (Offline, Take away), and F&B category templates (F&B industry only; retail / ticket / other receive none) | URD-ORG-017 · URD-MER-020 |
| FR-22 | The owner grant is recorded as three access rows - join-domain to the organization, join-domain to the merchant, and assign-role Owner | URD-ACC-014 |
| FR-23 | Merchant enum defaults: business type (Household default / Business), industry (Retail / F&B default / Ticket / Other), currency (default VND) | URD-MER-021 |
| FR-24 | Onboarding progress is six ordered steps on the merchant (merchant info → sale channel → finance account → tax info → product → employee), surfaced in the launchpad as completed / total | URD-MER-022 |
| FR-25 | Slug uniqueness is soft-delete-aware (a removed slug is freed for reuse); administrative onboarding auto-suffixes a unique token on slug collision; there is no maximum number of merchants per organization | URD-MER-023 |
| FR-26 | Organization / merchant list, count, and find reads are scoped at the handler from the caller's access grants (the central policy engine does not currently gate these reads) | URD-ACC-016 |
| FR-27 | Administrative merchant aggregate-create branches on caller - a back-office admin scopes Owner to the new merchant; an organization owner links themselves | URD-ACC-015 |
| FR-28 | Changing the headquarter merchant emits an organization-HQ-changed event to downstream consumers | URD-ORG-018 |
Full requirement text and acceptance criteria live in the Commerce URD. This PRD references them rather than restating them.
6.1 Two onboarding paths
Onboarding has two distinct entry points with different ownership, transactional, and provisioning models. Earlier PRD versions described only the self-service path.
| Aspect | Self-service onboarding | Administrative (aggregate) onboarding |
|---|---|---|
| Driven by | The signing-up user (no organization yet) | A back-office operator provisioning a client |
| Owner | The calling user becomes Owner | A new owner user is created |
| Transaction | Single local transaction (all-or-nothing) | Two-phase saga: local phase 1 + remote phase 2, with compensation |
| License | None | A license is issued against the new owner user |
| Idempotency | None | Idempotency-Key (header or payload) - replay completed, reject in-progress |
| Request shape | { organization: { name, slug }, merchant: { industry, sectors? } } | Organization + merchant + a new owner's details + license intent |
Both paths produce the same default structure (§6.2) and the same three-row owner grant (FR-22).
6.2 Auto-created defaults
Every onboarding (either path) provisions a fixed, non-configurable default set:
| Default | Rule |
|---|---|
| Headquarter merchant | Exactly one, slug derived from the organization slug, name "Headquarter", headquarter flag set, direct tax method; recorded on the organization as its headquarter |
| Sale channels | Exactly two - Offline and Take away - with slugs derived from the merchant slug |
| Category templates | F&B industry only - default categories from the system category templates; retail, ticket, and other industries receive none |
| Owner grant | Three access rows - join-domain to the organization, join-domain to the merchant, assign-role Owner (FR-22) |
6.3 Onboarding progress steps
After the structure exists, the merchant tracks six ordered onboarding steps, surfaced in the merchant launchpad as a completed / total count:
merchant info → sale channel → finance account → tax info → product → employee
The launchpad reports how many of the six are complete so an owner can see what remains before the merchant is fully set up.
7. Non-Functional Requirements
| Area | Requirement |
|---|---|
| All-or-nothing | Onboarding and every combined save complete fully or leave nothing behind - a partial failure saves nothing |
| Data integrity | Slug uniqueness is enforced (global for organizations, per-organization for merchants, per-merchant for channels); nothing is permanently deleted - items are deactivated or archived and can be restored |
| Isolation & access | Every list, total, and change is role-filtered; owners see only their own organization and merchants, employees only assigned merchants; Admin sees all; an unrecognized role is denied |
| Identity | Identifiers are assigned on creation and never change |
| Languages | Organization/merchant names and user-facing labels are shown in multiple languages |
| Source of truth | Commerce is the source of truth; merchant changes flow automatically to dependent areas such as invoicing |
8. UX & Flows
Administrative aggregate onboarding - saga & compensation
The administrative path spans three services and compensates fully if the remote phase fails, so a half-provisioned client is never left behind.
Key screens in the back-office and POS client: organizer create/edit pages, the merchant create/edit form with its slug check, role-filtered organizer and merchant launchpads, and the merchant settings sections (languages, e-invoice, payment, finance wallet).
9. Data & Domain
| Concept | Role |
|---|---|
| Organization | The virtual brand - multilingual name, globally-unique slug, status, place in a hierarchy |
| Merchant | The legal selling unit under an organization - slug (unique per organization), business type, currency, status |
| Sale channel | A selling channel within a merchant (dine-in, takeaway, delivery); slug unique per merchant |
| Category | A product grouping within a merchant, optionally an add-on group |
| Access | A role-scoped grant of an organization or merchant to a user; drives every role-filtered list |
Conceptual only - full data details and rules in the commerce domain model.
9.1 Organization vs merchant - the principles
| Principle | Rule |
|---|---|
| Org is virtual | The organization is a brand: name, slug, hierarchy, branding. It has no legal existence - no tax code, no e-invoice account, no wallet, no business type. |
| Merchant is legal | Every legal and financial attribute belongs to a merchant: business type (household or enterprise, which drives invoice rules), tax identity (tax code + registered address), e-invoice details, finance accounts and wallets, currency, industry, and physical location. |
| One headquarter per org | Onboarding creates the organization and its headquarter merchant together; an organization never exists without at least this merchant. |
| Identity & slugs | A merchant's identifier is assigned on creation and never changes. Its slug is unique within the organization among active merchants - removing a merchant frees its slug for reuse. |
| Sector-driven defaults | A merchant's sectors must be valid business sectors; onboarding sets up the default sale channels and the category templates for those sectors. |
| Ownership | The person who onboards becomes the Owner of the new organization and its merchant. One user may own several organizations; a merchant never moves between organizations. |
| Hierarchy | Merchants may form a parent-child hierarchy within their organization - branches under a flagship, never across organizations. |
| Tax identity flows down | The tax code is entered once on the merchant and the e-invoice profile reuses it automatically - editing it on the merchant is the only supported path. |
10. Dependencies & Assumptions
Depends on
- User Management (CORE-01) - the owner and employees belong to the organization and its merchants.
- Permissions (CORE-02) - roles are scoped to an organization or merchant; onboarding grants the owner access.
Assumptions
- An authenticated user with no organization drives onboarding.
- A set of roles exists so launchpads and lists can be filtered by role (with an Admin who sees all).
- Slug input is normalized to a URL-friendly form before the uniqueness check.
11. Risks & Open Questions
| Risk / question | Mitigation / status |
|---|---|
| Partial failure mid-onboarding leaves a half-built business | Onboarding is all-or-nothing; nothing is saved on failure |
| The combined save removes the wrong item and drops data | Removal is an explicit marker, kept distinct from "leave unchanged"; the save is all-or-nothing |
| A slug clash surfaces only at submit | A dedicated slug check validates before submit |
| An unrecognized role silently returns empty data | An unrecognized role is explicitly denied, never shown an empty list |
| No ownership transfer | Out of scope (Planned); documented as a constraint |
12. Release Plan & Launch Criteria
| Aspect | Plan |
|---|---|
| Phase | P1 for ORG / MER / ACC (per the URD feature catalog) |
| Rollout | All merchants; no feature flag |
| Migration | None - works on existing data; nothing is permanently deleted |
| Launch criteria | Onboarding creates organization + merchant + channels + access all-or-nothing; the combined merchant save adds, updates, and removes correctly; the slug check rejects duplicates; launchpads are role-filtered with no leakage between businesses |
| Monitoring | Onboarding success and failure rate, partial-save failures, slug-clash rejections, role-filter coverage |
13. FAQ
Does onboarding create everything in one shot? Yes - organization, default merchant, sale channels, and owner access are created all-or-nothing. If any step fails, nothing is saved.
How does the combined merchant save decide add vs. update vs. remove? An item with its details is updated, a new item is added, and an item marked for removal is removed - see the combined-save rule in §6.
Why check the slug before submit? So a form is never lost to a clash discovered late.
Why do two users see different launchpads? Every list is role-filtered - an owner sees only their own organization and merchants, an employee only assigned merchants. Super Admin sees all.
Can a merchant be moved to another organization? No - cross-organization sharing and ownership transfer are out of scope (Planned).
Why doesn't the organization carry a tax code? Because the organization is a brand, not a legal seller. Tax identity, e-invoice accounts, wallets, and business type all belong to the merchant. One brand can cover several merchants with different tax registrations.
Can one user own several organizations? Yes. What is fixed is the other direction: a merchant belongs to exactly one organization, forever.
Why are there two onboarding endpoints? Self-service onboarding sets the calling user up as Owner in one local transaction with no license. Administrative onboarding (from the back office) provisions a brand-new owner user and a license, so it runs as a two-phase saga that compensates fully if the remote phase fails. See §6.1.
What does the Idempotency-Key do? It makes administrative onboarding safe to retry - a completed request replays its stored result, and a concurrent retry of the same key is rejected as still in-progress, so a client is never provisioned twice. See FR-19.
Is there a cap on merchants per organization? No - an organization can hold any number of merchants (FR-25).
References
- URD: Commerce - Organization · Merchant · Access
- Builds on: Sale Channels · Categories
- Module: Commerce - overview + traceability
- Developer: @nx/commerce · domain model