feat: rework EOL, repairs, and hosts for real workflow
Four domain-model changes driven by exercising the deployed 2.0 build: - EOL moves from manufacturer to MPN via new PartModel catalog table, so alerts fire on the thing that actually ages. - Repairs re-home to Host (required hostId + problem text) with an optional RepairJobPart join for affected parts; drop Part.replacementPartId. - New /repairs/:id detail page with editable problem, part list, and a RepairComment thread (REPAIR_COMMENTED events fan out to each problem part's timeline). - Host.assetId (required, unique) surfaces prominently on the repair page so techs can confirm they're touching the right box. Single destructive migration reshapes existing dev data. All 7 packages typecheck clean; 30 API tests pass (9 new covering host membership, upsertByMpn idempotency + race, assetId 409, comment userId stamping). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -89,7 +89,7 @@ export default function PartDetail() {
|
||||
);
|
||||
}
|
||||
|
||||
const eolDate = part.manufacturer.eolDate ? new Date(part.manufacturer.eolDate) : null;
|
||||
const eolDate = part.partModel.eolDate ? new Date(part.partModel.eolDate) : null;
|
||||
const pastEol = eolDate ? eolDate.getTime() < Date.now() : false;
|
||||
|
||||
return (
|
||||
@@ -102,7 +102,7 @@ export default function PartDetail() {
|
||||
<div>
|
||||
<h1 className="font-mono text-lg font-semibold tracking-tight">{part.serialNumber}</h1>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{part.manufacturer.name} · {part.mpn}
|
||||
{part.manufacturer.name} · {part.partModel.mpn}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -132,7 +132,7 @@ export default function PartDetail() {
|
||||
<AlertTriangle className="mt-0.5 h-4 w-4 text-warning" />
|
||||
<div className="text-sm">
|
||||
<span className="font-medium text-foreground">
|
||||
{part.manufacturer.name} reached EOL {eolDate.toLocaleDateString()}.
|
||||
{part.partModel.mpn} reached EOL {eolDate.toLocaleDateString()}.
|
||||
</span>{' '}
|
||||
<span className="text-muted-foreground">
|
||||
Plan a replacement for this part.
|
||||
@@ -150,7 +150,7 @@ export default function PartDetail() {
|
||||
<CardContent>
|
||||
<dl className="space-y-2">
|
||||
<DetailRow label="Serial" value={<span className="font-mono text-xs">{part.serialNumber}</span>} />
|
||||
<DetailRow label="MPN" value={part.mpn} />
|
||||
<DetailRow label="MPN" value={part.partModel.mpn} />
|
||||
<DetailRow
|
||||
label="Manufacturer"
|
||||
value={
|
||||
|
||||
Reference in New Issue
Block a user