4.0 KiB
4.0 KiB
Tasks: enterprise-api-plugin-inventory
Change ID: enterprise-api-plugin-inventory
Package: @suaveplan/api-plugin-inventory
Target path: api/logistics/api-plugin-inventory
Prerequisite packages on Verdaccio: @suaveplan/api, @suaveplan/api-shared, @suaveplan/api-plugin-auth, @suaveplan/api-plugin-database, @suaveplan/events, @suaveplan/idempotency, @suaveplan/audit-logging, @suaveplan/rate-limiter, @suaveplan/error
0. Pre-flight (non-negotiable)
- 0.1 Confirm clean working tree (
git statusreports nothing) and no in-flight worktrees with uncommitted work (git worktree listthengit statusin each) - 0.2 If any worktrees exist under
.claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - 0.3 Confirm the package set in
MANIFEST.mdmatchesfind packages -maxdepth 3 -name package.jsoncount. Drift here means a prior change archived without regenerating the manifest.
1. Scaffold + types + errors + events
- Create
api/logistics/api-plugin-inventory/;package.jsonv0.0.0; standard tooling. Includedecimal.jsin deps (Bun catalog). - Types:
InventoryItem,CreateItemInput,UpdateItemInput,StockMovement,Warehouse,StockLevel,LotInfo,CostingMethodenum,AdjustmentRecord,InventoryConfig(Zod; expanded with basePath, defaultCostingMethod, lowStockThreshold). - Errors: 6-code union + registration. Test + doc.
- Events:
InventoryEventMap(inventory:stock:received, inventory:stock:issued, inventory:stock:low, inventory:adjustment:created). Module augmentation — noas never.
2. SurrealQL
inventory_item.surql,warehouse.surql,stock_level.surql,stock_movement.surql,lot.surql,adjustment.surql. All with tenantId indexes.
3. Services (all .test.ts + .md)
- ItemService:
createItem,updateItem,deleteItem,getItem,listItems(paginated, filterable). - WarehouseService:
createWarehouse,updateWarehouse,deleteWarehouse,getWarehouse,listWarehouses. - StockService:
getStockLevel(itemId, warehouseId),listStockLevels(itemId),isLowStock(itemId). - MovementService:
receive,issue,transfer. All idempotent; emitinventory:stock:received/:issued. - CostingService:
calculateCost(itemId, quantity, method)— FIFO/LIFO/average/specific-ID. Usedecimal.jsfor all arithmetic. Fully tested edge cases. - AdjustmentService:
createAdjustment(physical-count discrepancy); audit-logged; emit event. - ReportService:
getLowStockReport(),getExpiringStockReport(),getValuationReport().
4. procurement:grn:completed subscription
- In
onReady: subscribe toprocurement:grn:completedevent on bus; for each GRN line item, callMovementService.receive()to create stock movement. Properly typed — noas nevercast. onClose: detach bus subscription.- Integration test: emit
procurement:grn:completed→ verify stock movement created.
5. Routes
- Full CRUD for items, warehouses; stock queries; movement creation; adjustments; reports.
- All write routes:
requireAuth+ permission gates + idempotency + audit where applicable. - Route
.test.ts+.md.
6. Plugin factory + integration tests + publish
createInventoryPlugin:definePlugin,dependencies: ["database", "auth"],migrationsPath: "./surql".- Integration: receive stock → issue stock → FIFO costing → low stock alert → adjustment (real SurrealDB).
bunx turbo lint typecheck test --filter=@suaveplan/api-plugin-inventory— green; 100% coverage.bun scripts/publish.ts --package @suaveplan/api-plugin-inventory.- Archive →
openspec/archive/2026-04-24-enterprise-api-plugin-inventory/.