feat(assets): add asset metadata views and enforce assignment transitions

This commit is contained in:
2026-06-19 17:14:22 +02:00
parent c1763ed007
commit f32d55a7b0
17 changed files with 1573 additions and 70 deletions
+44 -10
View File
@@ -1,12 +1,6 @@
import {
type AssetStatus,
Prisma,
} from "@/generated/prisma/client"
import { type AssetStatus, Prisma } from "@/generated/prisma/client"
import prisma from "@/lib/prisma"
import type {
CreateAssetFormType,
UpdateAssetFormType,
} from "@/schemas/asset.schema"
import type { CreateAssetData, UpdateAssetData } from "@/schemas/asset.schema"
import { AssetService } from "@/services/asset.service"
import { AssignmentService } from "@/services/assignment.service"
import { ItemService } from "@/services/item.service"
@@ -15,11 +9,11 @@ import type { Assignment } from "@/types"
type FieldErrors = Record<string, string[]>
type CreateAssetUseCaseInput = CreateAssetFormType & {
type CreateAssetUseCaseInput = CreateAssetData & {
actorId: string
}
type UpdateAssetUseCaseInput = UpdateAssetFormType & {
type UpdateAssetUseCaseInput = UpdateAssetData & {
actorId: string
}
@@ -56,6 +50,12 @@ function updateAssetError(errors: FieldErrors): UpdateAssetUseCaseResult {
}
}
function validateAssignedPerson(status: AssetStatus, personId?: string) {
return status === "ASSIGNED" && !personId
? { personId: ["Person is required"] }
: null
}
class AssetTransitionError extends Error {
constructor(readonly errors: FieldErrors) {
super("Asset transition failed")
@@ -104,12 +104,23 @@ export async function createAssetUseCase(
actorId,
itemId,
serialNumber,
assetTag,
manufacturer,
model,
purchaseDate,
purchasePrice,
warrantyEndsAt,
deliveryNote,
status,
notes,
personId,
} = input
const assignedPersonError = validateAssignedPerson(status, personId)
if (assignedPersonError) {
return createAssetError(assignedPersonError)
}
try {
return await prisma.$transaction(async (tx) => {
const item = await ItemService.findByIdWithCategory(itemId, tx)
@@ -133,6 +144,12 @@ export async function createAssetUseCase(
{
item: { connect: { id: itemId } },
serialNumber,
assetTag,
manufacturer,
model,
purchaseDate,
purchasePrice,
warrantyEndsAt,
deliveryNote,
status,
notes,
@@ -200,12 +217,23 @@ export async function updateAssetUseCase(
id,
itemId,
serialNumber,
assetTag,
manufacturer,
model,
purchaseDate,
purchasePrice,
warrantyEndsAt,
deliveryNote,
status,
notes,
personId,
} = input
const assignedPersonError = validateAssignedPerson(status, personId)
if (assignedPersonError) {
return updateAssetError(assignedPersonError)
}
try {
return await prisma.$transaction(async (tx) => {
const item = await ItemService.findByIdWithCategory(itemId, tx)
@@ -249,6 +277,12 @@ export async function updateAssetUseCase(
{
item: { connect: { id: itemId } },
serialNumber,
assetTag,
manufacturer,
model,
purchaseDate,
purchasePrice,
warrantyEndsAt,
deliveryNote,
status,
notes,