feat: laundry-list polish pass
CI / Lint · Typecheck · Test · Build (push) Successful in 44s
CI / Playwright (smoke) (push) Has been skipped
CI / Build & push images (push) Successful in 59s

Seven bundled improvements:
- PartModel combobox on Add Part + Log Repair (known MPN auto-fills;
  unknown reveals manufacturer picker for catalog upsert).
- Host lifecycle: state (DEPLOYED/DEGRADED/TESTING) and stack
  (PRODUCTION/VETTING) fields, driven by external clients via the API.
- Locations page redesigned as a 2-pane tree + bin grid with breadcrumb.
- PENDING_REPAIR custody state: tech takes a SPARE into custody for a
  future swap; resolves to DEPLOYED via Repair or back to SPARE via a
  bin-required drop-off.
- Move Category from Part to PartModel; seed common categories
  (GPU/RAM/SSD/HDD/NIC/CPU/PSU/MOBO). Parts table gets a Category
  column and filter sourced from the model.
- Fix Deployed Value 100x bug on the Dashboard (price is stored as
  dollars, not cents).
- PartModels table shows "No" instead of "--" when destroyOnFail=false.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-17 13:36:11 -04:00
parent 3d77f2846d
commit 60255f20bb
39 changed files with 1731 additions and 630 deletions
+13 -8
View File
@@ -62,6 +62,8 @@ model PartModel {
eolDate DateTime?
destroyOnFail Boolean @default(false)
notes String?
categoryId String?
category Category? @relation(fields: [categoryId], references: [id], onDelete: SetNull)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
parts Part[]
@@ -69,6 +71,7 @@ model PartModel {
@@unique([manufacturerId, mpn])
@@index([manufacturerId])
@@index([eolDate])
@@index([categoryId])
}
model Site {
@@ -106,12 +109,12 @@ model Bin {
}
model Category {
id String @id @default(uuid())
name String @unique
id String @id @default(uuid())
name String @unique
description String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
parts Part[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
partModels PartModel[]
}
model Part {
@@ -125,8 +128,6 @@ model Part {
state String @default("SPARE")
binId String?
bin Bin? @relation(fields: [binId], references: [id], onDelete: SetNull)
categoryId String?
category Category? @relation(fields: [categoryId], references: [id], onDelete: SetNull)
hostId String?
host Host? @relation(fields: [hostId], references: [id], onDelete: SetNull)
custodianId String?
@@ -144,7 +145,6 @@ model Part {
@@index([binId])
@@index([manufacturerId])
@@index([partModelId])
@@index([categoryId])
@@index([hostId])
@@index([custodianId])
}
@@ -191,11 +191,16 @@ model Host {
name String @unique
location String?
notes String?
state String @default("DEPLOYED")
stack String @default("PRODUCTION")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
parts Part[]
fms Fm[]
repairs Repair[]
@@index([state])
@@index([stack])
}
model Fm {