| 04-inventory-expenses-and-financial-reports |
02 |
inventory |
| asset-management |
| serialized-tracking |
| disposal |
| write-off |
| journal-entry |
| location-history |
|
| phase |
provides |
| 04-01 |
InventoryService.recordMovement, InventoryItem/StockMovement models, COA accounts 1200/2010 |
|
| phase |
provides |
| 02-02 |
JournalEntryService.createEntry for disposal write-off JE |
|
|
| AssetService with assignToSubscriber, assignToTechnician, returnAsset, disposeAsset, getAssetHistory |
| API routes for assign, return, dispose, and history |
| Admin-only disposal with write-off JE (DR 5030, CR 1200) |
| Chronological location history with resolved names |
|
|
| added |
patterns |
|
|
| Asset lifecycle builds on immutable movement ledger (no new models) |
| Role-based authorization at service layer (userRoles parameter) |
| Location name resolution via batch query + map lookup |
|
|
| created |
modified |
| src/lib/services/asset-service.ts |
| src/lib/__tests__/asset-service.test.ts |
| src/app/api/inventory/items/[id]/assign/route.ts |
| src/app/api/inventory/items/[id]/return/route.ts |
| src/app/api/inventory/items/[id]/dispose/route.ts |
| src/app/api/inventory/items/[id]/history/route.ts |
|
|
|
| AssetService delegates all movement recording to InventoryService.recordMovement — no direct StockMovement writes |
| Disposal JE created separately before movement record — InventoryService only auto-creates JEs for RECEIVED |
| getCurrentLocation derives from latest movement's to-fields (null for DISPOSED) |
| returnAsset always returns to main-warehouse — single warehouse model sufficient for ISP scale |
| History name resolution uses batch queries (subscribers + users) then Map lookup — avoids N+1 |
|
| Service-layer role check via userRoles array parameter (not CASL) for admin-only operations |
|
8min |
2026-03-05 |