Inventory Ticket
1. Overview
| Property | Value |
|---|---|
| ID | FEAT-INV-TICKET |
| Status | Beta (P2 phase) |
| Owner | inventory-team |
| Depends on | InventoryStock, InventoryLocation, Vendor (partner type), Customer (partner type), Material / ProductVariant (line items) |
InventoryTicket is a workflow document for stock operations that need approval before execution: transfer between locations, manual adjustment, cycle count reconciliation, returns, and scrap. The ticket has lines (InventoryTicketItem) and a multi-stage lifecycle. No stock effect until the ticket reaches COMPLETED — at that point the lines drive adjustStock calls.
2. Entity Model
InventoryTicket fields
| Field | Type | Required | Description |
|---|---|---|---|
merchantId | text | ✓ | Owner |
type | text | ✓ | See §3 |
status | text | ✓ | See §4 |
partnerType | text | VENDOR / CUSTOMER / NULL | |
partnerId | text | FK target | |
sourceLocationId | text | For TRANSFER | |
destinationLocationId | text | For TRANSFER | |
submittedAt / approvedAt / startedAt / completedAt / cancelledAt | timestamptz | Per-status timestamps | |
note | text | Free-form |
InventoryTicketItem fields
| Field | Type | Required | Description |
|---|---|---|---|
inventoryTicketId | text | ✓ | FK |
inventoryStockId | text | Target bucket (resolved at submit) | |
itemType | text | ✓ | MATERIAL / PRODUCT_VARIANT |
itemId | text | ✓ | FK target id |
plannedQuantity | decimal(15,4) | ✓ | What was requested |
actualQuantity | decimal(15,4) | What was applied (for cycle count vs adjustment) | |
uomId | text | Soft ref | |
multiplier | decimal(15,4) | UoM-to-base |
3. Ticket Types
Source:
InventoryTicketTypes.
| Type | Stock effect on COMPLETE | Notes |
|---|---|---|
PURCHASE_REQUEST | None (informational) | Triggers PO creation downstream (manual today) |
STOCK_IN | +plannedQuantity per line | Manual receipt without a PO |
TRANSFER | − source + + destination per line | Atomic per pair; emits MATERIAL_TRANSFERRED if material |
INTERNAL_USE | −plannedQuantity per line | Internal kitchen / office use |
ADJUSTMENT | ± actualQuantity per line | Operator-driven correction |
CYCLE_COUNT | ± actualQuantity−counted | Reconciliation with physical count |
RETURN_TO_VENDOR | −plannedQuantity per line | Linked to Vendor partner |
RETURN_FROM_CUSTOMER | +plannedQuantity per line | Linked to Customer partner |
SCRAP_DISPOSAL | −plannedQuantity per line | Marked with reason (DAMAGED / EXPIRED) |
4. Lifecycle
| From | Event | To | Effect |
|---|---|---|---|
DRAFT | submit | SUBMITTED | Lock items |
SUBMITTED | approve | APPROVED | Authorization gate |
APPROVED | start | IN_PROGRESS | Picker begins work |
IN_PROGRESS | complete | COMPLETED | Apply stock effects per line |
| any non-terminal | cancel | CANCELLED | Terminal — no stock effect |
| Status code | Display |
|---|---|
001_DRAFT | DRAFT |
200_SUBMITTED | SUBMITTED |
250_APPROVED | APPROVED |
300_IN_PROGRESS | IN_PROGRESS |
303_COMPLETED | COMPLETED |
505_CANCELLED | CANCELLED |
5. Operations
InventoryTicketService (inventory-ticket.service.ts — 40 lines)
Inherits CRUD from MerchantScopedService<TInventoryTicketSchema, ...>. Lifecycle transitions wire up via update endpoints + service-level guards (TBD — currently lifecycle methods minimal).
InventoryTicketItemService (inventory-ticket-item.service.ts — 89 lines)
| Method | Purpose |
|---|---|
| CRUD (inherited) | Manage lines |
| Stock-effect on parent COMPLETE | Iterates lines and calls InventoryStockRepository.adjustStock per line |
6. REST Endpoints
| Verb | Path | Auth | Permission |
|---|---|---|---|
| 6× CRUD | /inventory-tickets | JWT/BASIC | InventoryTicket.<crud> |
| 6× CRUD | /inventory-ticket-items | JWT/BASIC | InventoryTicketItem.<crud> |
| Lifecycle | TBD (submit / approve / start / complete / cancel) | JWT/BASIC | InventoryTicket.<action> |
7. Events
Outbound:
| Topic | When |
|---|---|
material.transferred | After TRANSFER ticket completes for a material line |
WebSocket observation/inventory/inventory-stock | After per-line adjustStock |
8. Idempotency on COMPLETE
Each line writes one tracking row keyed (INVENTORY_TICKET, ticketId, inventoryStockId). Re-running complete (e.g. from a retry) hits the idempotency lookup and skips already-applied lines.
9. Related Pages
- Inventory Stock —
adjustStocksemantics - Inventory Tracking —
INVENTORY_TICKETreference type - Inventory Location — source/destination for TRANSFER
- Domain Model