PRD: Vendors
| Module | Inventory (CORE-06) | PRD ID | PRD-VEN-001 |
| Status | Shipped | Owner | Inventory squad |
| Date | 2026-05-27 | Version | v1.0 |
| Packages | @nx/inventory · apps/client | URD | VEN |
TL;DR
Gives a merchant a place to keep its suppliers - a vendor directory with contacts, address, tax registration, and material associations - created and edited in one aggregate operation from both the client app and the back office. Every purchase order references a vendor here, so each stock-in traces back to a named supplier, and soft-delete preserves that link even after a vendor is removed.
1. Context & Problem
Purchase orders need a supplier to reference, and merchants need a single place to keep their suppliers' contact and tax details. Without a vendor directory, a stock-in cannot be tied back to a named supplier, and there is no merchant-isolated record of who a business buys from, how to reach them, or their tax registration - making purchasing, vendor reconciliation, and tax reporting unreliable.
The @nx/inventory package already carries a Vendor entity, service, and API (the result of an earlier supplier → vendor rename), but there is no user-facing surface to create, edit, or browse vendors. This increment delivers that surface - client and back-office screens plus an aggregate create/update path - turning the backend Vendor into a working directory of suppliers that purchase orders can reference.
2. Goals & Non-Goals
Goals
- A vendor directory scoped per merchant, capturing name, contact info (emails, phones), address, and tax registration.
- Create/edit screens with a structured contacts form and a payment-terms field.
- A vendor listing/table for browsing existing suppliers.
- Aggregate create/update so a vendor and its related fields (including material associations via a material multi-input) save in one operation.
- The same surface delivered in both the client app and the back office.
Non-Goals
- Purchase-order receipt and stock movement - owned by Purchase Orders / Purchase Order Items.
- Vendor-side material catalog ownership beyond the multi-select association surfaced in the form.
- Multi-currency vendor pricing or vendor valuation (out of module scope per the URD Non-Goals).
3. Success Metrics
| Metric | Target / signal |
|---|---|
| Traceability | 100% of purchase orders reference an existing vendor (no orphan stock-ins) |
| Adoption | Merchants maintain a vendor directory rather than ad-hoc supplier notes |
| Data completeness | Vendors carry contact + tax details usable for PO and tax reporting |
| History integrity | Removing a vendor never breaks an existing PO reference (soft-delete preserves it) |
4. Personas & Use Cases
| Persona | Goal in this feature |
|---|---|
| Owner | Maintain a directory of suppliers with contact and tax details |
| Inventory staff | Look up and select a vendor when raising a purchase order |
Core scenarios: create a vendor (name, contacts, address, tax) → edit it later with an aggregate update including material associations → browse the vendor list → reference the vendor from a purchase order → soft-delete a vendor while preserving historical PO links.
5. User Stories
- As an owner, I want to create a vendor with name, contacts, address, and tax registration, so my suppliers live in one merchant-isolated directory.
- As an owner, I want to edit a vendor and its material associations in a single save, so the vendor and its related fields stay consistent.
- As inventory staff, I want to browse and search the vendor list, so I can pick the right supplier when raising a PO.
- As an owner, I want a removed vendor to keep its historical PO references intact, so past purchases remain auditable.
6. Functional Requirements
| # | Requirement | URD ref |
|---|---|---|
| FR-1 | Owner can create vendors within a merchant; vendors are isolated per merchant | URD-VEN-001 · URD-VEN-005 |
| FR-2 | Vendor captures name, contact info (emails, phones), address, and a system identifier (VEN_YYYYMMDD_id) | URD-VEN-002 |
| FR-3 | Vendor can store a tax registration number | URD-VEN-003 |
| FR-4 | Aggregate create/update saves the vendor and its related fields (contacts, payment terms, material associations) in one operation | URD-VEN-001..002 |
| FR-5 | Vendor uses soft-delete; historical PO references are preserved | URD-VEN-004 |
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 |
|---|---|
| Data integrity | Soft-delete preserves vendors referenced by purchase orders - a removed vendor never orphans a PO line |
| Tenancy & authz | All operations scoped per merchant (x-merchant-id); gated by inventory permissions |
| Consistency | Aggregate create/update is transactional - a vendor and its related fields commit together or not at all |
| i18n | User-facing labels are bilingual ({ en, vi }) |
8. UX & Flows
Key screens (in apps/client and the back office): vendor list/table, vendor create, vendor edit - with a structured contacts form, a payment-terms field, and a material multi-input.
9. Data & Domain
| Entity | Role |
|---|---|
Vendor | The supplier record - name, contacts (emails/phones), address, tax registration, system identifier, soft-delete |
| Material association | Links a vendor to materials it supplies, captured via the form's material multi-input |
Conceptual only - full schema and invariants in the inventory domain model.
10. Dependencies & Assumptions
Depends on
@nx/inventoryVendor entity/service/API - the existing backend contract this surface consumes (from the priorsupplier → vendorrefactor).- Materials (URD-MAT) - for the material multi-input associations on the vendor form.
Assumptions
- The merchant context (
x-merchant-id) is established so vendors are isolated correctly. - Purchase orders will reference vendors from this directory rather than free-text suppliers.
11. Risks & Open Questions
| Risk / question | Mitigation / status |
|---|---|
| Deleting a vendor could orphan historical PO references | Soft-delete preserves the link; vendors are never hard-deleted |
| Aggregate update partial failure | Update is transactional - vendor and related fields commit together |
| Material association scope creep (vendor-owned catalog) | Out of scope; only the multi-select association on the form is supported |
| Multi-currency vendor pricing | Out of scope per URD Non-Goals; document as a constraint for cross-border vendors |
12. Release Plan & Launch Criteria
| Aspect | Plan |
|---|---|
| Phase | P1 (foundation) - see URD feature catalog |
| Rollout | All merchants; no feature flag; client app + back office |
| Migration | None (backend Vendor entity already in place from the supplier → vendor refactor) |
| Launch criteria | Create→edit→list verified end-to-end; aggregate update (incl. material associations) saves atomically; soft-delete preserves PO references |
| Monitoring | Vendor count per merchant, create/update error rate, PO-to-vendor reference integrity |
13. FAQ
Where does a purchase order get its vendor? From this directory - a PO requires an existing vendor, so the supplier, contacts, and tax details are reused rather than re-entered.
What happens to POs when I remove a vendor? Nothing breaks - vendors use soft-delete, so historical PO references are preserved.
Can I save a vendor and its materials in one step? Yes - aggregate create/update commits the vendor and its related fields (contacts, payment terms, material associations) in a single transactional operation.
Is the vendor directory shared across merchants? No - vendors are isolated per merchant.
Does this own the material catalog? No - only the material multi-select association on the vendor form; the material catalog itself is the Materials feature.
References
- URD: Inventory - Vendors
- Used by: Purchase Orders · Purchase Order Items
- Related: Materials
- Module: Inventory - overview + traceability
- Developer: @nx/inventory · domain model