feat: add AssetItem.purchaseOrderId (nullable FK)
This commit is contained in:
@@ -22,12 +22,14 @@ export async function POST(request: Request): Promise<NextResponse> {
|
||||
return NextResponse.json({ error: "Request body must be a JSON object" }, { status: 400 });
|
||||
}
|
||||
|
||||
const { serialNumber, model, purchaseDate, warrantyEndDate } = body as Record<string, unknown>;
|
||||
const { serialNumber, model, purchaseDate, warrantyEndDate, purchaseOrderId } =
|
||||
body as Record<string, unknown>;
|
||||
const validation = validateCreateAssetItemInput({
|
||||
serialNumber,
|
||||
model,
|
||||
purchaseDate,
|
||||
warrantyEndDate,
|
||||
purchaseOrderId,
|
||||
});
|
||||
|
||||
if (!validation.ok) {
|
||||
|
||||
+25
-1
@@ -11,6 +11,7 @@ export interface AssetItemRecord {
|
||||
purchase_date: string;
|
||||
warranty_end_date: string | null;
|
||||
status: AssetItemStatus;
|
||||
purchase_order_id: string | null;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
@@ -19,6 +20,7 @@ export interface CreateAssetItemInput {
|
||||
model: string;
|
||||
purchaseDate: Date;
|
||||
warrantyEndDate?: Date;
|
||||
purchaseOrderId?: string | null;
|
||||
}
|
||||
|
||||
export type ValidationResult =
|
||||
@@ -48,12 +50,24 @@ const createAssetItemSchema = z.object({
|
||||
model: nonEmptyString("model is required and must be a non-empty string"),
|
||||
purchaseDate: dateString("purchaseDate is required and must be a valid date string"),
|
||||
warrantyEndDate: dateString("warrantyEndDate must be a valid date string").optional(),
|
||||
// FK to PurchaseOrder — nullable/optional, supply-side traceability (not
|
||||
// every AssetItem goes through a formal PO). Only a UUID *format* check
|
||||
// here, whether it references a real PurchaseOrder is left to Prisma's
|
||||
// own FK constraint at insert time (see createAssetItem()'s P2003
|
||||
// handling below). Mirrors src/lib/purchase-orders.ts's receivedById
|
||||
// optional().nullable() pattern.
|
||||
purchaseOrderId: z
|
||||
.string({ invalid_type_error: "purchaseOrderId must be a valid UUID string" })
|
||||
.uuid("purchaseOrderId must be a valid UUID string")
|
||||
.optional()
|
||||
.nullable(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Validates raw (untyped) asset-item-creation input. serialNumber/model
|
||||
* must be non-empty strings, purchaseDate must be a valid date string,
|
||||
* warrantyEndDate is optional but must be a valid date string if present.
|
||||
* purchaseOrderId is optional/nullable but must be a valid UUID if present.
|
||||
* status is not accepted here — new assets always start "in_stock" (same
|
||||
* pattern as Request always starting "Draft"), later states are set via
|
||||
* other operations, not at creation.
|
||||
@@ -63,6 +77,7 @@ export function validateCreateAssetItemInput(input: {
|
||||
model?: unknown;
|
||||
purchaseDate?: unknown;
|
||||
warrantyEndDate?: unknown;
|
||||
purchaseOrderId?: unknown;
|
||||
}): ValidationResult {
|
||||
const result = createAssetItemSchema.safeParse(input);
|
||||
if (!result.success) {
|
||||
@@ -79,6 +94,7 @@ function toRecord(row: {
|
||||
purchaseDate: Date;
|
||||
warrantyEndDate: Date | null;
|
||||
status: AssetItemStatus;
|
||||
purchaseOrderId: string | null;
|
||||
createdAt: Date;
|
||||
}): AssetItemRecord {
|
||||
return {
|
||||
@@ -88,6 +104,7 @@ function toRecord(row: {
|
||||
purchase_date: row.purchaseDate.toISOString(),
|
||||
warranty_end_date: row.warrantyEndDate ? row.warrantyEndDate.toISOString() : null,
|
||||
status: row.status,
|
||||
purchase_order_id: row.purchaseOrderId,
|
||||
created_at: row.createdAt.toISOString(),
|
||||
};
|
||||
}
|
||||
@@ -102,7 +119,10 @@ export type CreateAssetItemResult =
|
||||
* caught here and translated into the same `{ok:false,error}` shape as
|
||||
* input validation failures, rather than letting a raw Prisma error leak
|
||||
* to the API layer. Mirrors createEmployee()/createRequest()'s P2003
|
||||
* handling for FK violations.
|
||||
* handling for FK violations. If purchaseOrderId doesn't reference an
|
||||
* existing PurchaseOrder, Prisma raises P2003 (FK constraint violation) —
|
||||
* caught the same way, mirrors src/lib/purchase-orders.ts's
|
||||
* createPurchaseOrder() P2003 handling.
|
||||
*/
|
||||
export async function createAssetItem(
|
||||
input: CreateAssetItemInput
|
||||
@@ -114,6 +134,7 @@ export async function createAssetItem(
|
||||
model: input.model,
|
||||
purchaseDate: input.purchaseDate,
|
||||
warrantyEndDate: input.warrantyEndDate ?? null,
|
||||
purchaseOrderId: input.purchaseOrderId ?? null,
|
||||
},
|
||||
});
|
||||
return { ok: true, value: toRecord(created) };
|
||||
@@ -121,6 +142,9 @@ export async function createAssetItem(
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2002") {
|
||||
return { ok: false, error: "serialNumber already exists" };
|
||||
}
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2003") {
|
||||
return { ok: false, error: "purchaseOrderId does not reference an existing purchase order" };
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user