--- name: sp-api-plugin-asset-register description: Fixed-asset lifecycle plugin for the Fetch-native @suaveplan/api platform. Authored with @suaveplan/api-plugin-kit definePlugin, contributes 15 typed RouteDescriptors under /assets, persisting to its own SurrealDB tables via four SurrealDB-backed repositories from one injected SurrealAdapter (plugin OWNS its persistence). Computes depreciation (straight-line, reducing-balance, units-of-activity), renders asset-tag QR labels with @suaveplan/qrcode, manages maintenance records and cost-centre assignments. Server-tier. --- # @suaveplan/api-plugin-asset-register ## Purpose Fixed-asset lifecycle plugin for the Fetch-native `@suaveplan/api` platform. Authored with `@suaveplan/api-plugin-kit` `definePlugin`, it contributes 15 typed `RouteDescriptor`s under `/assets`, persisting to its own SurrealDB tables (`asset`, `depreciation_schedule`, `maintenance_record`, `asset_assignment`) via four SurrealDB-backed repositories constructed from one injected `SurrealAdapter` — the plugin OWNS its persistence. It computes depreciation (straight-line, reducing-balance, units-of-activity) with `@suaveplan/datetime` date math, renders asset-tag QR labels with `@suaveplan/qrcode`, and manages maintenance records and cost-centre assignments. ## Architecture | Component | Source | Role | |---|---|---| | `createAssetRegisterPlugin` | `src/plugin/plugin.ts` | Plugin factory | | `createAssetRegister` | `src/plugin/plugin.ts` | Returns `{ plugin, repositories }` for live access | | `calculateDepreciation` | `src/depreciation/depreciation.ts` | Pure depreciation engine | | `SurrealAssetRepository` | `src/repositories/asset/asset.ts` | Asset CRUD persistence | | `SurrealDepreciationRepository` | `src/repositories/depreciation/depreciation.ts` | Depreciation schedule persistence | | `SurrealMaintenanceRepository` | `src/repositories/maintenance/maintenance.ts` | Maintenance record persistence | | `SurrealAssignmentRepository` | `src/repositories/assignment/assignment.ts` | Cost-centre assignment persistence | | `ASSET_REGISTER_API_CODES` | `src/error-codes/error-codes.ts` | Error-code registry | ## File Structure ``` src/ index.ts # Barrel: plugin factories, repositories, routes, depreciation, codes, types plugin/ plugin.ts # createAssetRegisterPlugin, createAssetRegister depreciation/ depreciation.ts # calculateDepreciation (pure) repositories/ asset/ # SurrealAssetRepository + InMemoryAssetStore depreciation/ # SurrealDepreciationRepository + InMemoryDepreciationStore maintenance/ # SurrealMaintenanceRepository + InMemoryMaintenanceStore assignment/ # SurrealAssignmentRepository + InMemoryAssignmentStore shared/ # Row mappers, query helpers routes/ all-routes/ # buildAllAssetRegisterRoutes assets/ # CRUD, depreciation, maintenance, assignment, label routes schema/ schema.ts # SurrealQL DDL + applyAssetRegisterSchema error-codes/ error-codes.ts # ASSET_REGISTER_API_CODES + AssetRegisterApiError otel/ instruments.ts # asset_register_api.* OTel bundle ``` ## Entry Points | Import | Exports | |---|---| | `@suaveplan/api-plugin-asset-register` | `createAssetRegisterPlugin`, `createAssetRegister`, repositories, routes, depreciation, codes, types | | `@suaveplan/api-plugin-asset-register/plugin` | `createAssetRegisterPlugin`, `createAssetRegister`, `AssetRegisterWiring` | | `@suaveplan/api-plugin-asset-register/depreciation` | `calculateDepreciation`, `DepreciationContext`, `DepreciationResult` | | `@suaveplan/api-plugin-asset-register/routes` | `buildAllAssetRegisterRoutes`, `buildAssetRoutes`, `RouteDeps` | | `@suaveplan/api-plugin-asset-register/repositories/asset` | `SurrealAssetRepository`, `InMemoryAssetStore`, types | | `@suaveplan/api-plugin-asset-register/error-codes` | `ASSET_REGISTER_API_CODES`, `AssetRegisterApiError` | | `@suaveplan/api-plugin-asset-register/otel` | OTel instruments | | `@suaveplan/api-plugin-asset-register/schemas` | `AssetRegisterPluginOptionsSchema` | | `@suaveplan/api-plugin-asset-register/types` | Public types | ## Patterns ### Basic usage ```ts import { createApi } from "@suaveplan/api"; import { createAuth } from "@suaveplan/api-plugin-auth"; import { createAssetRegister } from "@suaveplan/api-plugin-asset-register"; import { SurrealAdapter } from "@suaveplan/surrealdb"; const db = new SurrealAdapter({ url: "ws://localhost:8000" }); await db.connect(); const { plugin: authPlugin, sessionResolver } = createAuth({ betterAuth }); const { plugin } = createAssetRegister({ db }); const runtime = createApi({ plugins: [authPlugin, plugin], sessionResolver, tenantResolver, }); await runtime.start("auth"); await runtime.start("asset-register"); ``` ## Routes All routes are auth-gated and tenant-scoped. Default mount prefix `/`. | Method | Path | Operation | |---|---|---| | GET | `/assets` | list assets | | POST | `/assets` | create asset | | GET | `/assets/:id` | read one asset | | PATCH | `/assets/:id` | update asset | | POST | `/assets/:id/dispose` | dispose asset | | GET | `/assets/:id/label` | QR SVG label | | GET | `/assets/:id/depreciation` | compute depreciation snapshot | | GET | `/assets/:id/depreciation/history` | depreciation audit trail | | GET | `/assets/:id/maintenance` | list maintenance records | | POST | `/assets/:id/maintenance` | schedule maintenance | | PATCH | `/assets/:id/maintenance/:maintenanceId` | complete maintenance | | DELETE | `/assets/:id/maintenance/:maintenanceId` | cancel maintenance | | GET | `/assets/:id/assignments` | list assignments | | POST | `/assets/:id/assignments` | assign to cost centre | | POST | `/assets/:id/assignments/:assignmentId/return` | return assignment | ## Constraints - **Server-tier** — consumes `@suaveplan/surrealdb`. - **Owns its persistence** — four SurrealDB tables: `asset`, `depreciation_schedule`, `maintenance_record`, `asset_assignment`. - **Depreciation methods** — straight-line, reducing-balance, units-of-activity. - **Lifecycle enforcement** — disposed assets reject further updates (409); invalid maintenance transitions raise `MAINTENANCE_CONFLICT` (409); at most one active assignment per asset. - **In-memory variants** — each repository has an `InMemory*Store` for testing. - **Dependencies**: `@suaveplan/api`, `@suaveplan/api-plugin-auth`, `@suaveplan/api-plugin-kit`, `@suaveplan/api-types`, `@suaveplan/datetime`, `@suaveplan/error`, `@suaveplan/qrcode`, `@suaveplan/surrealdb`, `@suaveplan/types`, `@opentelemetry/api`, `tslib`, `zod`. ## Checklist - [ ] Read `src/depreciation/depreciation.ts` before modifying depreciation logic - [ ] Read `src/plugin/plugin.ts` before changing plugin wiring - [ ] Preserve lifecycle state-machine constraints - [ ] Ensure disposed assets remain immutable