PRD: Merchant Management (Back Office)
| Module | Commerce | PRD ID | PRD-MER-001 |
| Status | Ready to dev | FEAT | MER · BANA-1437 |
| Epic | BANA-1337 | Plane | BANA-1735 |
| Date | 2026-06-30 | Version | v1.0 |
| Packages | @nx/commerce | URD | MER |
| Surface | BO · Ops | ||
| Owner | Phát Nguyễn | ||
What Merchant Management (Back Office) is
Onboarding creates an organizer together with a headquarters merchant and a set of defaults (PRD-ORG-001). After that, the operations team needs a place to manage merchants as records: add another merchant for an organizer, fix a profile, change the lifecycle status, and - most importantly - turn on how a merchant accepts payment. The Merchant Management screen in the Back Office is that place: find merchants across every organizer, create new ones, edit each merchant's profile and lifecycle, and configure payment providers, payment settings, and print templates.
Organizer and merchant
This screen rests on a principle set by PRD-ORG-001: the organizer stays a virtual brand; every legal and financial attribute belongs to a merchant, never to the organizer. Tax identity, currency, and payment-acceptance configuration all live on the merchant as a result - which is exactly what this screen edits, on the merchant's behalf, from the Back Office.
Why this screen exists
Before this screen, adding or fixing a merchant meant raw data edits. The operations team had no managed place for the whole merchant lifecycle and its payment configuration, scoped to their role. It is the operations counterpart to the owner-facing merchant setup.
One scenario, start to finish
An operator searches the merchant table, opens a merchant, corrects its profile on the General tab, then switches to the Payment provider tab to enter VNPAY QR credentials, and to the Payment settings tab to register merchant/terminal details. Once both steps are done, the merchant can accept payment. To add a new merchant, the operator creates one under the right organizer. When a merchant is no longer needed, the operator tries to delete it; if it still holds content or is the headquarters, the screen refuses and points to Archive, or to reassigning the headquarters first.
The easiest thing to get wrong
Payment provider configuration is not Payment settings
The two tabs sound alike but do different things. Payment provider configuration enters a provider's raw technical credentials (VNPAY QR, VNPAY Phone POS). Payment settings registers merchant and terminal details, per sale channel, with the payment party. Two separate tabs, saved separately - miss either one and the merchant cannot fully accept payment.
1. Goals & Non-Goals
Goals
- Find merchants across organizers - a table with search and filters by name, status, business type, industry, and organizer.
- Create a merchant with its core profile and a predefined set of defaults.
- Edit a merchant's profile and lifecycle (5 statuses, see FR-004).
- Configure payment providers - enter each provider's credentials (exactly 2 supported today: VNPAY QR and VNPAY Phone POS).
- Payment settings - register merchant and per-sale-channel terminal details with the payment party.
- Set the merchant's receipt print templates, multiple per language, with one default.
- View and edit a merchant's deletion policy on the merchant's behalf, and delete a merchant under the server's real conditions.
- Reassign a merchant's headquarters designation for an organizer, with guardrails protecting the current headquarters.
Non-Goals
- The guided onboarding wizard that first creates an organizer + merchant - its own flow (Backoffice Portal).
- A merchant owner's self-service setup in the client app (same capability, different surface).
- Organizer-level legal/financial data - by design these belong to the merchant, not the organizer.
- Categories, sale channels, and receipt-template authoring as standalone features (own areas:
CAT,SC,RCP).
2. Success Metrics
| Metric | Target / signal |
|---|---|
| Operator self-service | An operator creates or edits a merchant, and turns on its payment acceptance, without a database change |
| Findability | An operator locates any merchant by search/filter within their role's scope |
| Slug integrity | A new merchant's slug is unique within its organizer; collisions are prevented |
| Payment readiness | After configuration, a merchant accepts payment via its configured providers |
| Safe deletion | A merchant with child merchants, remaining content, or the headquarters designation is never deleted by mistake |
3. Personas & Scenarios
| Persona | Goal in this feature |
|---|---|
| Operations team | Maintain merchants on behalf of organizers - profile, lifecycle, deletion policy, and payment setup |
| Onboarding / support staff | Add a merchant for an existing organizer and get it ready to transact |
Core scenario: an operator searches the merchant table, opens a merchant, corrects its profile on the General tab, then switches to the Payment provider tab to enter VNPAY QR credentials and to the Payment settings tab to register merchant/terminal details; the merchant can now accept payment. To add a merchant, the operator creates a new merchant under the right organizer. When a merchant is no longer needed, the operator tries to delete it; if it still holds content or is the headquarters, the screen refuses and points to Archive, or to reassigning the headquarters first.
4. User Stories
| # | As a | I want | So that |
|---|---|---|---|
| 01 | operator | a searchable, filterable merchant table with the headquarters clearly marked | I find the right merchant by name, status, business type, industry, or organizer |
| 02 | operator | to create a merchant with predefined defaults (Active, VND, Household business) | a new merchant doesn't require re-picking everything; Industry is the one field I always pick myself |
| 03 | operator | a merchant's slug to be unique within its organizer | links and lookups never clash |
| 04 | operator | to edit a merchant's profile and change its lifecycle status | the record reflects the real merchant |
| 05 | operator | to enter payment-provider credentials and register merchant/terminal details | the merchant can accept payment |
| 06 | operator | to author the merchant's print templates per language | receipts print in the approved format |
| 07 | operator | to view and edit a merchant's two deletion-policy flags on its behalf | I can support a merchant that needs a change it can't yet make itself |
| 08 | operator | to delete a merchant only when it's genuinely empty | I never wipe out data still in use |
| 09 | operator | to reassign which merchant is an organizer's headquarters, and never be able to delete the current headquarters by mistake | the organizer always has exactly one valid headquarters |
5. Functional Requirements
| # | Requirement | Status | URD ref |
|---|---|---|---|
FR-001 | Merchant table with 8 columns, search and filters, scoped to the operator's role. • Columns: Merchant name (search by name; shows a Headquarters badge when the merchant is the organizer's headquarters) · Tax code (display only) · Status (filterable, see FR-004) · Business type (filterable, see FR-002) · Industry (filterable, see FR-002) · Categories (display only, up to 3 badges shown, the rest collapse into "+N", hover to see all) · Address (display only) · Organizer (filterable, merchants list across organizers within the role's scope). • Row actions: open merchant (into the editor) and delete (per the deletion conditions in FR-010, with a confirmation dialog naming the merchant); the list only shows merchants within the operator's role scope. | ✅ | URD-MER-006 · URD-MER-010 · URD-MER-017 |
FR-002 | Create a merchant via an 11-field profile form, with predefined defaults. Slug unique within the organizer. • Required: Merchant name (bilingual VI/EN) · Organizer (picked from existing organizers) · Business type (only Household business today; Enterprise is not among the choices when creating a merchant in the BO (🚧)) · Industry (F&B · Retail · Other; Ticketing is not among the choices when creating a merchant in the BO) · Slug (auto-generated from the Vietnamese name; manually editable via a dialog - a manual edit stops auto-generation, clearing it resumes; unique within the organizer - duplicates are rejected, and a soft-deleted merchant's slug is freed for reuse) · Status (5 values, see FR-004) · Currency (VND · USD · EUR · GBP · JPY). • Optional: Merchant code (free-form, entered by the operator) · Start date · End date (must not be before Start date - violations error on the field) · Address (free text). • Defaults on create: Status = Active, Currency = VND, Business type = Household business; Industry is required but has no preset value - the operator always picks it. • The create screen shows only the profile form (the payment / print-template tabs appear only when editing). On success the operator lands in the new merchant's editor; if the tax data sync raises a warning, it is shown alongside the success message. | ✅ | URD-MER-002 · URD-MER-005 · URD-MER-021 |
FR-003 | Edit the general profile on the General tab. • The editor opens 4 tabs: General · Payment provider configuration · Payment settings · Print template. • The General tab reuses the 11-field form from FR-002; on save, only changed fields are written. • Leaving with unsaved changes triggers a warning. | ✅ | URD-MER-007 |
FR-004 | Merchant lifecycle - 5 statuses. Inactive is reversible, Archived is a read-only end-state. • Statuses: Unknown · Active · Inactive · Draft · Archived. • Inactive is reversible (set back to Active). • Archived is a deliberate end-state: an archived merchant must be read-only - this read-only constraint is a requirement and is not yet enforced on the screen (🔶). • A merchant that is currently an organizer's headquarters can never be moved to Archived - see FR-011. | 🔶 | URD-MER-012 · URD-MER-013 |
FR-005 | Registration & tax profile - tax code, business registration number, registration type, and registration date. • An area in the editor where the operator enters the tax code, business registration number, registration type (picked from the registration-type list), and registration date; all 4 fields optional. • The form has been designed but is currently not attached to any tab on the screen - it must be added to the editor as a tab or section. | 🚧 | URD-MER-016 |
FR-006 | Payment provider configuration - per-operation credentials for VNPAY QR and VNPAY Phone POS. • The tab lists providers in a left column (with logo and providing party), and the selected provider's credential form on the right. Exactly 2 providers are supported today. • VNPAY QR - 7 credentials across 4 business operations: Create payment (request + response), Verify IPN (1 credential), Check transaction (request + response), Refund (request + response). • VNPAY Phone POS - 2 credentials: Verify IPN and Create merchant MOID. • On save, only changed credentials are written: an existing credential is updated, a missing one is created. If nothing changed, the screen reports "no configuration to save" instead of writing blanks. | ✅ | URD-MER-016 |
FR-007 | Payment settings - register merchant and per-sale-channel terminal details with the payment party. • A separate tab (edit only), with 2 registration groups for the payment party. • Merchant details: merchant name, merchant code, merchant type - all 3 required. • Terminal details per sale channel: sale channel (required pick), terminal name, terminal code, terminal service code - all required. One terminal set per sale channel. • Each group saves independently with its own save button. | ✅ | URD-MER-016 |
FR-008 | Print templates - multiple templates per language (VI/EN), one default, authored in the tab. • The Print template tab opens the receipt-template editor inside the merchant editor. • Each merchant can have multiple templates per language (VI/EN - switching language loads that language's set), of which one is the default. • Saving updates the selected template, or creates a new one if the merchant has none. | ✅ | URD-RCP-001 |
FR-009 | Merchant deletion policy - the operator views and edits a merchant's two deletion-policy flags on the merchant editor. • Every merchant carries a deletion policy with two flags, stored in the merchant's own settings store. • Block-delete-category-with-children (default on) - a category that still has child categories cannot be deleted. • Cascade-delete-product-variants (default off) - deleting a product also deletes its variants. • On the merchant editor, the operator views the current value of both flags and edits them on the merchant's behalf when the merchant needs the operations team's help making the change. | 🚧 | URD-MER-024 · URD-MER-025 |
FR-010 | Delete a merchant under the server's real conditions. • Deleting (from the FR-001 table or from the editor) only succeeds when both conditions hold: the merchant has no child merchants, and the merchant has no remaining content (categories, products, sale channels, orders). • Violating either condition gets the request rejected, with a message pointing the operator to Archive (FR-004) instead of deleting. • On success, the system cleans up every outbound link and setting belonging to the merchant, then soft-deletes it. | ✅ | URD-MER-026 |
FR-011 | Headquarters merchant - reassign an organizer's headquarters. • The newly picked merchant must be in the same organizer and currently Active. Once reassigned, the system emits a headquarters-changed event to downstream consumers. • A merchant that is currently an organizer's headquarters can never be deleted or archived - the headquarters designation must be reassigned to another merchant first, then the old one can be deleted or archived. • The same headquarters-protection rule applies everywhere a merchant is managed, including the Client app. | 🚧 | URD-ORG-011 · URD-ORG-018 · URD-MER-017 |
5.1 Acceptance criteria
- The merchant table shows all 8 columns from FR-001; it filters by name, status, business type, industry, and organizer; the headquarters merchant carries a Headquarters badge.
- Merchants outside the operator's role scope never appear in the table and cannot be opened.
- Deleting a merchant requires confirmation on a dialog that names the merchant; on confirm the row disappears from the table if the FR-010 conditions are met.
- The create form is pre-filled with Active / VND / Household business; Industry is left blank and must be picked; leaving any required field empty blocks saving and errors that field.
- Typing the Vietnamese name auto-generates the slug; editing the slug manually via the dialog stops auto-generation; clearing the slug resumes it.
- Creating a merchant with a slug already used by another merchant in the same organizer is rejected with an error; reusing the slug of a soft-deleted merchant succeeds.
- Setting End date before Start date errors on the date field and blocks saving.
- In the editor, only changed fields are written on save; leaving with unsaved changes triggers a warning.
- Setting a merchant to Inactive and back to Active succeeds; an Archived merchant can no longer be edited (once the read-only constraint is built).
- The Payment provider tab shows exactly 2 providers; VNPAY QR shows all 7 credential inputs across 4 groups, Phone POS shows both of its 2; after saving and reopening, the stored configuration is visible.
- The Payment settings tab saves merchant details (3 required fields) and per-sale-channel terminal details (4 required fields) independently.
- Print template tab: switching VI ↔ EN loads that language's template set; the first save creates a template, subsequent saves update the selected one; the default template is pre-loaded when the tab opens.
- Opening the merchant editor shows both deletion-policy flags with the correct defaults (block-delete-category-with-children on, cascade-delete-product-variants off); the operator changes and saves them.
- Deleting a merchant that still has products fails, with a message suggesting Archive.
- Deleting an empty merchant succeeds, and its settings and links are cleaned up.
- Reassigning the headquarters to a merchant in the same organizer that is Active succeeds and emits the headquarters-changed event; picking a merchant from another organizer or one that isn't Active is rejected.
- Clicking delete on the merchant that is the current headquarters is rejected; reassigning the headquarters to another merchant and then deleting the old one succeeds.
6. Non-Functional Requirements
| Area | Requirement |
|---|---|
| Tenancy & authz | The list and every action are scoped to the operator's role; an operator never sees or edits merchants outside their scope |
| Slug integrity | Slug uniqueness is enforced within an organizer and is soft-delete-aware (a removed slug is freed) |
| Credential safety | Credentials are stored encrypted server-side; after saving, the screen must not display the full credential value again (masked display only). The masked display is a requirement - today the screen still loads the stored values back (🚧) |
| Reversibility | Inactive is reversible; Archived is a deliberate, read-only end-state |
| Deletion integrity | Deleting a merchant honors the two-condition guard (FR-010) and the headquarters-protection rule (FR-011); no shortcut bypasses the guard |
| i18n | Merchant name and labels are bilingual (EN/VI) |
7. UX & Flows
How an operator manages a merchant:
How an operator deletes or reassigns a headquarters merchant:
What the screen lets an operator do:
The screen lives in the Back Office "CRM & Merchant" section. Creating a merchant captures only the core profile; editing opens all 4 tabs.
8. Data & Domain
| Concept | Role in this screen |
|---|---|
| Organizer | The branding parent a merchant belongs to; merchants are listed and created under one |
| Merchant | The legal point-of-sale unit - name, slug, business type, industry, status, currency, merchant code, effective dates, address; one per organizer is the headquarters |
| Deletion policy | Two flags (block-delete-category-with-children, cascade-delete-product-variants) stored in the merchant's settings store; the operator views/edits them on the merchant's behalf |
| Payment provider configuration | Per-operation credentials for each provider (VNPAY QR, VNPAY Phone POS) |
| Payment settings | Merchant and per-sale-channel terminal details registered with the payment party |
| Print template | The merchant's receipt templates per language, one default |
Conceptual only - legal/financial attributes (tax identity, finance accounts, wallets, currency) belong to the merchant; the data model lives in the developer docs.
9. Dependencies & Assumptions
Depends on
| # | Feature | What is depended on |
|---|---|---|
| 01 | Onboarding (PRD-ORG-001) | creates the organizer + headquarters merchant this screen then manages. |
| 02 | ORG Organizer | owns the headquarters concept; reassigning it emits a headquarters-changed event to the organizer and downstream consumers. |
| 03 | CAT / SC Categories & sale channels | categories show on a merchant; sale channels are the unit of terminal registration, and are one of the content types the FR-010 deletion guard checks. |
| 04 | RCP Receipt templates | the template editor used in the Print template tab. |
| 05 | Payment | the two providers (VNPAY QR, VNPAY Phone POS) a merchant can be configured to accept (Payment). |
Assumptions
| # | Assumption | What breaks if it is wrong |
|---|---|---|
| 01 | The operator is authenticated with a role that scopes which merchants they manage. | The operator sees and acts on merchants outside their assigned scope, breaking this screen's authorization boundary. |
| 02 | Each merchant belongs to exactly one organizer; one merchant per organizer is the headquarters. | The FR-011 headquarters guard assumes exactly one headquarters per organizer; if an organizer has none or more than one, the guard can no longer tell which merchant it is meant to protect. |
10. Release Plan & Criteria
| Aspect | Plan |
|---|---|
| Phase | P1 - available to operators in the Back Office |
| Rollout | All operator users; no feature flag |
| Migration | None - it manages existing merchant records |
| Launch criteria | All §5.1 acceptance criteria pass, except items marked 🚧/🔶 (credential masking, Archived read-only, registration & tax profile, deletion policy on the editor, headquarters reassignment) which have their own build plan |
| Monitoring | Merchant create/edit volume; payment configuration save success rate; count of merchant deletions rejected by the guard |
References
- URD: Commerce -
MER(Merchant) ·ORG·RCP - Related: PRD-ORG-001 - Organizer & merchant
- Module: Commerce - URD · Roadmap: Phase 2 - By Month
- Developer: @nx/commerce
Risks & Open Questions
| # | Risk / question | Mitigation / status |
|---|---|---|
| 01 | An operator editing a merchant outside their scope | The list and actions are role-filtered; out-of-scope merchants are never shown |
| 02 | Slug collisions within an organizer | Uniqueness is enforced and soft-delete-aware |
| 03 | Sensitive credentials exposed via the screen | Masked display after save is required (🚧) - today the screen still loads values back; must be built before widening the audience |
| 04 | An Archived merchant is still editable | The read-only constraint for Archived is not yet enforced (🔶 FR-004) |
| 05 | Registration & tax profile cannot be entered | FR-005 kept as a requirement; the form must be attached to the editor |
| 06 | A merchant with remaining content is deleted by mistake | The server guard blocks deletion while child merchants, categories, products, sale channels, or orders remain; points to Archive (FR-010) |
| 07 | The current headquarters is deleted or archived by mistake | The guard blocks this outright; the headquarters must be reassigned to another merchant first (FR-011) |
| 08 | The headquarters is reassigned to the wrong merchant | The guard only accepts a merchant in the same organizer that is currently Active (FR-011) |
Frequently asked questions
| # | Question | Answer |
|---|---|---|
| 01 | Is this how a merchant first gets created? | Usually onboarding creates the first (headquarters) merchant; this screen manages merchants afterwards and adds more. |
| 02 | Why is tax / currency on the merchant, not the organizer? | Legal and financial attributes belong to the legal POS unit - the merchant - so each can transact and invoice under its own identity. |
| 03 | What payment providers can be configured? | Exactly 2 today: VNPAY QR and VNPAY Phone POS, each with its own per-operation credential set. Additional providers arrive as their own increments. |
| 04 | How does "provider configuration" differ from "payment settings"? | Provider configuration enters the provider's technical credentials; Payment settings registers merchant and terminal (per sale channel) details with the payment party. Two separate tabs, saved separately. |
| 05 | Can a merchant with products be deleted? | No. The guard blocks deletion while the merchant has child merchants or remaining content (categories, products, sale channels, orders); the screen suggests Archive instead. |
| 06 | Can the current headquarters merchant be deleted? | Never, even if it's empty. The headquarters designation must be reassigned to another merchant in the same organizer first, then the old one can be deleted or archived. |
| 07 | Can a merchant owner do this themselves? | The same capability is offered to owners in the client app; this PRD covers the operator surface in the Back Office. The headquarters-protection rule (FR-011) is the same single rule set on both surfaces. |