Skip to content

Inventory Service

@nx/inventory owns physical stock for a merchant: locations, items, stock buckets (on-hand / available / reserved), an immutable audit trail, vendor catalog, purchase orders, materials with bill-of-materials recipes, and inventory workflow tickets. It deducts stock when sale payments succeed (Kafka), explodes recipes when kitchen items change status, and emits events to finance on goods receipt.

1. Quick Reference

PropertyValue
Package@nx/inventory
CodeSVC-00050-INVENTORY
TypeMicroservice
RuntimeBun
Base ClassVerifierApplication
Locationpackages/inventory
Base Path/v1/api/inventory
Dev Port31050
Container Port3000 (external 31050)
Snowflake ID5
DB Schemainventory (17 tables — see Domain Model)
Binding Namespace@nx/inventory

2. Purpose & Scope

IncludedExcluded
Inventory locations (warehouses) with hierarchy + default-per-merchantSale quotation / quota-based reservation (P3)
Polymorphic InventoryItem (Material / ProductVariant)Multi-currency stock valuation
Stock buckets (on-hand, available, reserved) per (item, location, lot, serial)Full barcode-scanning integration (only data model)
Immutable InventoryTracking audit logStock-count audits with locking
19 fixed tracking types + customizable reasonsExpiry / FEFO / batch tracking enforcement (data only)
Vendor + VendorItem M:N catalog with snapshotsMulti-level BOM yield/scrap enforcement
Purchase Orders: aggregate API, lifecycle, receive modesStock transfer between merchants
Materials catalog + recipes (BOM) + runtime explosionInventory valuation reports
Production ordersDirect mutation of quantityReserved from outside this service
Inventory tickets (transfer, adjust, count, return, scrap)
Unit-of-measure 3-level catalog

3. Tech Stack

External:

LibraryPurpose
@venizia/ignisIoC container, DI, BaseService, BaseController, ControllerFactory
@venizia/ignis-helpersLogger, KafkaProducerHelper, KafkaConsumerHelper, Redis helper
@platformatic/kafkaKafka client (idempotent producer, lz4 compression, ALL acks)
honoHTTP server (via IGNIS)
@hono/zod-openapiOpenAPI generator from Zod schemas
@scalar/hono-api-referenceOpenAPI explorer at /doc
drizzle-ormDB access via PostgresCoreDataSource
pgPostgreSQL driver
lodashUtilities

Internal:

PackagePurpose
@nx/coreAll schemas, repositories (re-exported), VerifierApplication, KafkaTopics, CDCKafkaTopics, PurchaseOrderStatuses, MaterialRecipeStatuses, MerchantScopedService

4. Project Structure

packages/inventory/
├── src/
│   ├── application.ts                    # VerifierApplication subclass
│   ├── index.ts                          # bootstrapApplication()
│   ├── migrate.ts                        # bootstrapMigration()
│   ├── common/
│   │   ├── constants.ts                  # InventoryTrackingNotes, ReceivePurchaseOrderItemModes
│   │   ├── keys.ts                       # BindingKeys (extends @nx/core)
│   │   ├── rest-paths.ts                 # 15 RestPaths
│   │   ├── types.ts                      # local type aliases
│   │   └── websocket.ts                  # InventoryWebSocketTopics, Rooms
│   ├── components/
│   │   ├── kafka/                        # ApplicationKafkaComponent (5 inbound topics)
│   │   └── websocket/                    # ApplicationWebSocketComponent
│   ├── controllers/                      # 15 controllers (one folder each)
│   ├── datasources/                      # PostgresCoreDataSource
│   ├── migrations/processes/             # 5 seed/backfill processes
│   ├── models/                           # zod request/response schemas
│   ├── repositories/                     # re-exports from @nx/core
│   └── services/                         # 19 services
├── package.json
└── tsconfig.json

5. Architecture

Detail: see Architecture.

6. Domain Snapshot

Full ERD + per-entity tables: see Domain Model.

7. Surface Summary

REST controllers — full reference rendered live from /v1/api/inventory/doc/openapi.json (live spec — Scalar viewer at /doc, gateway portal):

ControllerBase pathLifecycle/aggregate routes
InventoryItemController/inventory-itemsmerchant-scoped CRUD
InventoryLocationController/inventory-locations+ set-default, activate, deactivate, archive
InventoryStockController/inventory-stocksCRUD
InventoryTrackingController/inventory-trackingsread-only CRUD (audit)
InventoryIdentifierController/inventory-identifiersCRUD
InventoryTicketController/inventory-ticketsCRUD + lifecycle
InventoryTicketItemController/inventory-ticket-itemsCRUD
PurchaseOrderController/purchase-orders+ aggregate, items, confirm, revert, receive, cancel, complete, close
MaterialController/materials+ aggregate
MaterialIdentifierController/material-identifiersCRUD
MaterialRecipeController/material-recipes+ aggregate, flatten
ProductionOrderController/production-ordersCRUD
VendorController/vendors+ aggregate
VendorItemController/vendor-items+ set-preferred, activate, deactivate
UnitOfMeasureController/unit-of-measuresCRUD (system + merchant-scoped)

Async surface — full reference in API Events:

DirectionChannelCount
InboundKafka5 (PAYMENT_SUCCESS, KITCHEN_TICKET_ITEM_STATUS_CHANGED, MATERIAL_TRANSFERRED, MERCHANT CDC, PRODUCT_VARIANT CDC)
OutboundKafka3 (PURCHASE_ORDER_RECEIVED, MATERIAL_STOCK_CHANGED, MATERIAL_TRANSFERRED)
OutboundWebSocket1 topic (observation/inventory/inventory-stock) × 3 room types (merchant / location / item)

8. Components

ComponentFilePurpose
ApplicationKafkaComponentsrc/components/kafka/component.tsIdempotent producer + consumer (autocommit=false); subscribes to 5 topics; dispatches via _dispatchMessage switch
ApplicationWebSocketComponentsrc/components/websocket/component.tsRedis-backed WS emitter for stock change broadcasts
Redis cache (optional)bound at BindingKeys.APPLICATION_REDIS_CACHEAuthorization permission cache (lookup by Casbin)

9. Services

ServiceFileOne-liner
InventoryServiceinventory.service.tsPolymorphic principal refs + multi-location seeding + PO receive write
InventoryWorkerServiceinventory-worker.service.tsKafka handlers: payment success, material transferred, merchant CDC, product variant CDC
InventoryStockServiceinventory-stock.service.tsMerchant-scoped CRUD on stock buckets
InventoryTrackingServiceinventory-tracking.service.tsMerchant-scoped CRUD on audit trail
InventoryItemServiceinventory-item.service.tsMerchant-scoped CRUD on polymorphic items
InventoryIdentifierServiceinventory-identifier.service.tsMerchant-scoped CRUD on SKU/barcode/serial identifiers
InventoryLocationServiceinventory-location.service.tsLocations + setDefault/activate/deactivate/archive lifecycle
InventoryTicketServiceinventory-ticket.service.tsMerchant-scoped CRUD on workflow tickets
InventoryTicketItemServiceinventory-ticket-item.service.tsTicket lines + linked stock adjust
PurchaseOrderServicepurchase-order.service.tsFull PO lifecycle, aggregate API, receive (OVERRIDE/ACCUMULATIVE)
PurchaseOrderItemServicepurchase-order-item.service.tsLine item updates + summary recalc
VendorServicevendor.service.tsVendor + aggregate (Vendor + VendorItem batch)
VendorItemServicevendor-item.service.tsM:N catalog: setPreferred, activate, deactivate, recordPurchase, batch upsert/omit
MaterialServicematerial.service.tsMaterial catalog + aggregate (with optional VendorItem batch)
MaterialIdentifierServicematerial-identifier.service.tsSYSTEM/SLUG identifier CRUD
MaterialRecipeServicematerial-recipe.service.tsRecipe (BOM) aggregate + multi-level flatten
MaterialWorkerServicematerial-worker.service.tsKitchen ticket consume, sale-order material reserve, recipe explosion
ProductionOrderServiceproduction-order.service.tsProduction order CRUD
UnitOfMeasureServiceunit-of-measure.service.tsSystem + merchant UoM catalog

10. Repositories

RepositorySourceNotable Custom Methods
InventoryStockRepository@nx/coreadjustStock — atomic UPDATE with forceNonNegative guard
InventoryLocationRepository@nx/coreensureDefaultLocation, setDefaultAtomic, findParentChain
InventoryTrackingRepository@nx/core(CRUD only — immutable audit, no custom mutators)
InventoryItemRepository@nx/coreensureInventoryItem (idempotent by (merchantId, itemType, itemId))
VendorItemRepository@nx/coresetPreferredAtomic
PurchaseOrderRepository@nx/coreupdateSummaryFromItems
InventoryIdentifierRepository@nx/core
InventoryTicketRepository@nx/core
InventoryTicketItemRepository@nx/core
MaterialRepository@nx/core
MaterialIdentifierRepository@nx/core
MaterialRecipeRepository@nx/core
MaterialRecipeItemRepository@nx/core
ProductionOrderRepository@nx/core
PurchaseOrderItemRepository@nx/core
VendorRepository@nx/core
UnitOfMeasureRepository@nx/core
ProductRepository, ProductVariantRepository, CategoryRepository, DiscriminationTypeRepository, PermissionRepository, PolicyDefinitionRepository@nx/coreCross-package read access

11. Entry Points

FilePurpose
src/index.tsService entry → bootstrapApplication()
src/migrate.tsMigration entry → bootstrapMigration()
src/application.tsApplication extends VerifierApplication

12. Configuration

Env vars + feature flags + seeded data: see Configuration.

13. Operations

Deployment + observability + security + runbook: see Operations.

Concepts — why/how the system is shaped:

Reference — lookup tables:

Features — deep dives:

Decisions:

Product module (what this powers):

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.