52 lines
1.7 KiB
TypeScript
52 lines
1.7 KiB
TypeScript
import { z } from 'zod'
|
|
import { pikkuFunc } from '#pikku/pikku-types.gen.js'
|
|
import { setAuditContext } from '../../lib/audit-context.js'
|
|
import { NotFoundError } from '../../lib/errors.js'
|
|
import { validateTransition } from '../../lib/state-machine.js'
|
|
|
|
export const ReviewInventoryRequestInput = z.object({
|
|
requestId: z.string().uuid().describe('Inventory request ID to review'),
|
|
status: z.enum(['approved', 'rejected']).describe('Review decision'),
|
|
reviewNotes: z.string().optional().describe('Notes about the review decision'),
|
|
})
|
|
|
|
export const ReviewInventoryRequestOutput = z.object({
|
|
requestId: z.string().describe('Reviewed request ID'),
|
|
status: z.string().describe('New request status'),
|
|
})
|
|
|
|
export const reviewInventoryRequest = pikkuFunc({
|
|
expose: true,
|
|
approvalRequired: true,
|
|
tags: ['inventory.manage'],
|
|
input: ReviewInventoryRequestInput,
|
|
output: ReviewInventoryRequestOutput,
|
|
func: async ({ kysely }, { requestId, status, reviewNotes }, { session }) => {
|
|
const request = await kysely
|
|
.selectFrom('inventoryRequest')
|
|
.select(['requestId', 'status'])
|
|
.where('requestId', '=', requestId)
|
|
.executeTakeFirst()
|
|
|
|
if (!request) throw new NotFoundError('Inventory request not found')
|
|
|
|
validateTransition('inventory_request', request.status, status)
|
|
|
|
await setAuditContext(kysely, session!.userId)
|
|
|
|
await kysely
|
|
.updateTable('inventoryRequest')
|
|
.set({
|
|
status,
|
|
reviewedByUserId: session!.userId,
|
|
reviewedAt: new Date(),
|
|
reviewNotes: reviewNotes ?? null,
|
|
updatedAt: new Date(),
|
|
})
|
|
.where('requestId', '=', requestId)
|
|
.execute()
|
|
|
|
return { requestId, status }
|
|
},
|
|
})
|