diff --git a/prisma/migrations/20260825073402_add_asset_item_status_lost/migration.sql b/prisma/migrations/20260825073402_add_asset_item_status_lost/migration.sql new file mode 100644 index 0000000..5dab1fe --- /dev/null +++ b/prisma/migrations/20260825073402_add_asset_item_status_lost/migration.sql @@ -0,0 +1,2 @@ +-- Hand-written (same deviation as other 2026-08-2x migrations -- see CLAUDE.md). +ALTER TYPE "AssetItemStatus" ADD VALUE 'lost'; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index e52e431..80a0d8f 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -84,14 +84,19 @@ model Employee { @@map("employees") } -// Fixed, closed set of 4 values tied to the domain (see docs/ +// Fixed, closed set of values tied to the domain (see docs/ // asset-license-management.md's "Data model (sơ bộ)" table) — native -// Postgres enum, same rationale as RequestType above. +// Postgres enum, same rationale as RequestType above. `lost` added +// 2026-08-25 (ALTER TYPE ... ADD VALUE, not a table -- see the +// 2026-08-24/25 discussion in CLAUDE.md on why this stays an enum: the +// values are read directly by business logic, e.g. createAssignment()'s +// `status !== "in_stock"` gate, not just display labels). enum AssetItemStatus { in_stock assigned repair retired + lost } // Hardware inventory — see docs/asset-license-management.md's "Data model diff --git a/src/app/assets/page.tsx b/src/app/assets/page.tsx index 19fd7bb..9fc4bb0 100644 --- a/src/app/assets/page.tsx +++ b/src/app/assets/page.tsx @@ -30,7 +30,7 @@ interface AssetItemRecord { model_id: string; purchase_date: string | null; warranty_end_date: string | null; - status: "in_stock" | "assigned" | "repair" | "retired"; + status: "in_stock" | "assigned" | "repair" | "retired" | "lost"; cost: number | null; cost_currency: string | null; purchase_order_id: string | null; @@ -40,13 +40,24 @@ interface AssetItemRecord { // Shape returned by GET /api/asset-models — only the fields used to populate // the modelId here. +interface AssetCategoryRecord { + id: string; + name: string; +} + // Shape returned by GET /api/purchase-orders — only the id, used to populate // the purchaseOrderId + + +
+ +
@@ -275,7 +339,7 @@ export default function AssetsPage() { All - {assetModels.map((assetModel) => ( + {modelsForCategoryFilter.map((assetModel) => ( {assetModel.manufacturer} {assetModel.name} diff --git a/src/lib/assets.ts b/src/lib/assets.ts index 92c500d..3e7cbe8 100644 --- a/src/lib/assets.ts +++ b/src/lib/assets.ts @@ -3,7 +3,7 @@ import { Prisma } from "@prisma/client"; import { prisma } from "./prisma"; import { splitCsvLine, splitCsvLines, normalizeHeader, csvField } from "./csv"; -export type AssetItemStatus = "in_stock" | "assigned" | "repair" | "retired"; +export type AssetItemStatus = "in_stock" | "assigned" | "repair" | "retired" | "lost"; export interface AssetItemRecord { id: string; @@ -455,6 +455,8 @@ const IMPORT_STATUS_MAP: Record = { "in repair": "repair", retired: "retired", disposed: "retired", + lost: "lost", + missing: "lost", }; function statusFromImportText(text: string): AssetItemStatus | null {