PRD: Inventory locations
| Module | Inventory (CORE-06) | PRD ID | PRD-LOC-001 |
| Status | Shipped | Owner | Inventory squad |
| Date | 2026-05-21 | Version | v1.0 |
| Packages | @nx/core · apps/bo · apps/admin-ui-kit | URD | LOC |
TL;DR
Gives merchants a back-office surface to see and manage their inventory locations - list every warehouse, create new ones, edit them, and choose which is the default - instead of being stuck with the single auto-created location. A reusable warehouse picker lets other back-office screens select or create a location inline. The outcome: a merchant can finally organize stock across multiple warehouses through the UI, not just in the data model.
1. Context & Problem
The inventory data model already supports locations: a default location is auto-created per merchant on commerce init, each location carries an i18n name, a default flag, address/GPS data, and a system identifier (LOC_YYYYMMDD_id). The create/list/update endpoints exist. What is missing is a back-office surface to use them: a merchant cannot see its locations, create additional ones, or change which one is the default through the UI.
Until that surface exists, multi-warehouse organization is invisible to merchants even though the backend supports it - a blocker for larger merchants who need more than one storage area, and for any back-office screen that needs to pick or create a location inline.
2. Goals & Non-Goals
Goals
- Add a Locations management area to the back-office (sidebar entry + routes).
- List inventory locations for the active merchant, filterable by status.
- Create a location via a form: i18n name, default toggle, address/GPS fields.
- Edit an existing location, including switching which one is the default.
- Provide a reusable warehouse picker (base input + inline create dialog) for other back-office screens, shipped in both
apps/boandapps/admin-ui-kit.
Non-Goals
- Backend changes to the location model or aggregate - the create/list/update endpoints already exist; this is a UI increment.
- Location-hierarchy management UX beyond what the form exposes (URD-LOC-004).
- Inventory items, stock, or tracking screens - separate features (ITM · STK · TRK).
- Sale-channel ↔ location wiring (owned by the commerce allocation work).
3. Success Metrics
| Metric | Target / signal |
|---|---|
| Self-service | Merchants can create and edit locations without backend/support intervention |
| Default integrity | Exactly one default location per merchant after any edit; setting a new default clears the previous |
| Reuse | The warehouse picker is adopted by other back-office screens that need to select/create a location |
| Coverage | All existing locations (including the auto-created default) are visible and editable in the list |
4. Personas & Use Cases
| Persona | Goal in this feature |
|---|---|
| Owner / Manager | See all warehouses, add new ones, set the default, keep address/GPS accurate |
| Back-office user (other screens) | Pick an existing location - or create one inline - without leaving the current screen |
Core scenarios: open the Locations area → see the list for the active merchant → create a new location with an i18n name and default toggle → edit a location and switch the default → from another screen, use the warehouse picker to select or inline-create a location.
5. User Stories
- As an owner, I want to see all my inventory locations in one list, so that I know which warehouses exist and which is the default.
- As an owner, I want to create a location with an i18n name and address/GPS data, so that I can organize stock across multiple warehouses.
- As an owner, I want to edit a location and switch the default, so that the right warehouse is used by default everywhere.
- As an owner, I want to filter locations by status, so that I can focus on active warehouses.
- As a back-office user, I want to pick or inline-create a location from within another screen, so that I don't have to break my flow to set one up.
6. Functional Requirements
| # | Requirement | URD ref |
|---|---|---|
| FR-1 | Locations management area in the back-office (sidebar entry + list/create/edit routes) | URD-LOC-009 |
| FR-2 | List inventory locations for the active merchant, filterable by status | URD-LOC-009 · URD-LOC-010 |
| FR-3 | Create a location with an i18n name | URD-LOC-001 |
| FR-4 | Create/edit captures address and geographic (GPS) data | URD-LOC-005 |
| FR-5 | Default toggle: exactly one default per merchant; setting a new default clears the previous | URD-LOC-003 |
| FR-6 | Edit an existing location, including switching the default | URD-LOC-001 · URD-LOC-003 |
| FR-7 | All screens operate within the active merchant (per-merchant isolation) | URD-LOC-010 |
| FR-8 | Reusable warehouse picker (base input + inline create dialog) for other back-office screens | URD-LOC-001 |
| FR-9 | Surface backend-enforced fields read-only: system identifier, lifecycle, soft-delete | URD-LOC-006..008 |
Full requirement text and acceptance criteria live in the Inventory URD. This PRD references them rather than restating them.
7. Non-Functional Requirements
| Area | Requirement |
|---|---|
| Tenancy & authz | All location screens operate within the active merchant (x-merchant-id); gated by inventory permissions |
| Data integrity | The default toggle is mutually exclusive per merchant - the UI never leaves zero or two defaults |
| Reuse | The warehouse picker ships once and is consumed by both apps/bo and apps/admin-ui-kit |
| Consistency | Read-only system fields (identifier, lifecycle, soft-delete) are surfaced but not editable in the UI |
| i18n | Location name is bilingual ({ en, vi }); all UI labels are localized |
8. UX & Flows
Key screens (in apps/bo): Locations list, create, and edit, built on a shared location form and a default-location toggle. The reusable warehouse picker (base input + inline create dialog) ships in both apps/bo and apps/admin-ui-kit so other screens can select or create a location inline.
9. Data & Domain
| Entity | Role |
|---|---|
InventoryLocation | The warehouse/storage record - i18n name, default flag, address/GPS, system identifier, lifecycle, soft-delete |
| Default flag | At most one location flagged default per merchant; the form re-points it on toggle |
Conceptual only - full schema and invariants in the inventory domain model.
10. Dependencies & Assumptions
Depends on
- Location API (URD-LOC-001..010) - the create/list/update endpoints this UI drives already exist in the backend.
- Commerce / Merchant - locations belong to a merchant; the active merchant scopes every screen.
@nx/core- back-office locale strings and shared app wiring.
Assumptions
- Each merchant already has its auto-created default location (URD-LOC-002) visible in the list.
- Lifecycle, system identifier, and soft-delete are enforced by the backend; the UI only surfaces them.
11. Risks & Open Questions
| Risk / question | Mitigation / status |
|---|---|
| Default toggle could momentarily leave zero or two defaults | Backend enforces exactly one default; setting a new default clears the previous |
| Hierarchy UX is not exposed beyond the form | Out of scope this increment; URD-LOC-004 tracked separately |
| Warehouse picker duplicated across surfaces | Shipped once, reused in both apps/bo and apps/admin-ui-kit |
| Editing a soft-deleted / archived location | Read-only lifecycle is surfaced; terminal states are not editable |
12. Release Plan & Launch Criteria
| Aspect | Plan |
|---|---|
| Phase | P1 (foundation) - see URD feature catalog |
| Rollout | All merchants; no feature flag; single-phase back-office front-end delivery |
| Migration | None - UI increment over an existing location API; no backend/model changes |
| Launch criteria | List/create/edit verified end-to-end; default toggle re-points correctly; warehouse picker works in both apps |
| Monitoring | Location create/edit volume per merchant; default-integrity checks (one default per merchant) |
13. FAQ
Does this change the location backend? No - the create/list/update endpoints already exist. This increment adds only the back-office UI over that API.
How is the default location handled? Exactly one default per merchant; setting a new default through the edit form clears the previous one. The backend enforces this invariant.
Can I build a location hierarchy here? Only what the form exposes. Full hierarchy-management UX (URD-LOC-004) is out of scope for this increment.
Where can the warehouse picker be used? Any back-office screen that needs to select or inline-create a location - it ships in both apps/bo and apps/admin-ui-kit.
Can I edit the system identifier or lifecycle? No - the identifier (LOC_YYYYMMDD_id), lifecycle, and soft-delete are backend-enforced and surfaced read-only.
References
- URD: Inventory - Locations (LOC)
- Related: Inventory Items · Stock Levels · Movement Audit Trail
- Module: Inventory - overview + traceability
- Developer: @nx/inventory · domain model