refactor(assignments): move workflows into use cases
This commit is contained in:
@@ -1,298 +0,0 @@
|
||||
"use server"
|
||||
|
||||
import { revalidatePath } from "next/cache"
|
||||
|
||||
import prisma from "@/lib/prisma"
|
||||
import { AssetService } from "@/services/asset.service"
|
||||
import { AssignmentService } from "@/services/assignment.service"
|
||||
import { getAuthenticatedUserId } from "@/services/auth.service"
|
||||
import { ItemService } from "@/services/item.service"
|
||||
import { MovementService } from "@/services/movement.service"
|
||||
|
||||
import {
|
||||
assignmentSchema,
|
||||
type CreateAssignmentFormType,
|
||||
type ReturnAssignmentFormType,
|
||||
type UpdateAssignmentFormType,
|
||||
updateAssignmentSchema,
|
||||
} from "../schemas/assignment.schemas"
|
||||
|
||||
export async function getAssignments() {
|
||||
return await AssignmentService.findAllWithRecipient()
|
||||
}
|
||||
|
||||
export async function getAssignmentById(id: string) {
|
||||
return await AssignmentService.findById(id)
|
||||
}
|
||||
|
||||
export async function createAssignment(formData: CreateAssignmentFormType) {
|
||||
const createdBy = await getAuthenticatedUserId()
|
||||
|
||||
const validatedFields = assignmentSchema.safeParse({
|
||||
...formData,
|
||||
createdBy,
|
||||
})
|
||||
|
||||
if (!validatedFields.success) {
|
||||
return {
|
||||
success: false,
|
||||
errors: validatedFields.error.flatten().fieldErrors,
|
||||
}
|
||||
}
|
||||
|
||||
const { itemId, assetId, quantity, recipientId } = validatedFields.data
|
||||
|
||||
if (!itemId || !recipientId || quantity <= 0) return
|
||||
|
||||
try {
|
||||
const item = await ItemService.findById(itemId)
|
||||
|
||||
if (!item) {
|
||||
return {
|
||||
success: false,
|
||||
errors: { itemId: ["Item not found"] },
|
||||
}
|
||||
}
|
||||
|
||||
if (item.stock < quantity) {
|
||||
return {
|
||||
success: false,
|
||||
errors: { quantity: ["Item does not have enough stock"] },
|
||||
}
|
||||
}
|
||||
|
||||
if (assetId) {
|
||||
const asset = await AssetService.findById(assetId)
|
||||
|
||||
if (!asset) {
|
||||
return {
|
||||
success: false,
|
||||
errors: { assetId: ["Asset not found"] },
|
||||
}
|
||||
}
|
||||
|
||||
if (asset.itemId !== item.id) {
|
||||
return {
|
||||
success: false,
|
||||
errors: { assetId: ["Asset does not belong to item"] },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await ItemService.updateStock(itemId, -quantity)
|
||||
|
||||
if (assetId && recipientId) {
|
||||
await AssetService.update(assetId, {
|
||||
status: "ASSIGNED",
|
||||
})
|
||||
}
|
||||
|
||||
const createdAssignment = await AssignmentService.create({
|
||||
itemId,
|
||||
assetId: assetId || undefined,
|
||||
quantity,
|
||||
recipientId,
|
||||
})
|
||||
|
||||
await MovementService.create({
|
||||
itemId,
|
||||
assetId: assetId || undefined,
|
||||
quantity,
|
||||
type: "ASSIGNMENT",
|
||||
recipientId,
|
||||
assignmentId: createdAssignment.id,
|
||||
})
|
||||
|
||||
revalidatePath("/assignments")
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "Assignment created successfully",
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Database error:", error)
|
||||
return {
|
||||
success: false,
|
||||
errors: { error: ["Error creating assignment"] },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateAssignment(formData: UpdateAssignmentFormType) {
|
||||
const validatedFields = updateAssignmentSchema.safeParse(formData)
|
||||
|
||||
if (!validatedFields.success) {
|
||||
return {
|
||||
success: false,
|
||||
errors: validatedFields.error.flatten().fieldErrors,
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const { id, recipientId, itemId, assetId, quantity } = validatedFields.data
|
||||
|
||||
const assignment = await prisma.assignment.findUnique({
|
||||
where: { id },
|
||||
})
|
||||
|
||||
if (!assignment) {
|
||||
return {
|
||||
success: false,
|
||||
errors: { id: ["Assignment not found"] },
|
||||
}
|
||||
}
|
||||
|
||||
if (itemId) {
|
||||
const item = await prisma.item.findUnique({
|
||||
where: { id: itemId },
|
||||
})
|
||||
|
||||
if (!item) {
|
||||
return {
|
||||
success: false,
|
||||
errors: { itemId: ["Item not found"] },
|
||||
}
|
||||
}
|
||||
|
||||
// if (item.stock < quantity) {
|
||||
// return {
|
||||
// success: false,
|
||||
// errors: { quantity: ["Item does not have enough stock"] },
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
if (assetId) {
|
||||
const asset = await prisma.asset.findUnique({
|
||||
where: { id: assetId },
|
||||
})
|
||||
|
||||
if (!asset) {
|
||||
return {
|
||||
success: false,
|
||||
errors: { assetId: ["Asset not found"] },
|
||||
}
|
||||
}
|
||||
|
||||
if (asset.itemId !== itemId) {
|
||||
await prisma.asset.update({
|
||||
where: { id: assetId },
|
||||
data: { itemId },
|
||||
})
|
||||
|
||||
return {
|
||||
success: false,
|
||||
errors: { assetId: ["Asset does not belong to item"] },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const createdBy = await getAuthenticatedUserId()
|
||||
|
||||
if (assignment.recipientId !== recipientId) {
|
||||
await MovementService.create({
|
||||
type: "RETURN",
|
||||
quantity: assignment.quantity || 1,
|
||||
itemId: assignment.itemId || undefined,
|
||||
assetId: assignment.assetId || undefined,
|
||||
recipientId: assignment.recipientId || undefined,
|
||||
assignmentId: id,
|
||||
})
|
||||
|
||||
await MovementService.create({
|
||||
type: "ASSIGNMENT",
|
||||
quantity,
|
||||
itemId,
|
||||
assetId: assetId || undefined,
|
||||
recipientId,
|
||||
assignmentId: id,
|
||||
})
|
||||
|
||||
await prisma.assignment.update({
|
||||
data: {
|
||||
...validatedFields.data,
|
||||
createdBy,
|
||||
recipientId,
|
||||
itemId,
|
||||
assetId,
|
||||
quantity,
|
||||
returnDate: null,
|
||||
},
|
||||
where: { id },
|
||||
})
|
||||
} else {
|
||||
await prisma.assignment.update({
|
||||
where: { id },
|
||||
data: {
|
||||
...validatedFields.data,
|
||||
itemId,
|
||||
assetId,
|
||||
quantity,
|
||||
returnDate: new Date(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
revalidatePath("/assignments")
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "Assignment updated successfully",
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Database error:", error)
|
||||
return {
|
||||
success: false,
|
||||
errors: { error: ["Error creating assignment"] },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function returnAssignment(formData: ReturnAssignmentFormType) {
|
||||
const { id } = formData
|
||||
|
||||
const assignment = await AssignmentService.findById(id)
|
||||
|
||||
if (!assignment) {
|
||||
return {
|
||||
success: false,
|
||||
errors: { id: ["Assignment not found"] },
|
||||
}
|
||||
}
|
||||
|
||||
if (assignment.returnDate) {
|
||||
return {
|
||||
success: false,
|
||||
errors: { id: ["Assignment already returned"] },
|
||||
}
|
||||
}
|
||||
|
||||
if (assignment.itemId && assignment.quantity) {
|
||||
await ItemService.update(assignment.itemId, {
|
||||
stock: { increment: assignment.quantity || 1 },
|
||||
})
|
||||
}
|
||||
|
||||
if (assignment.assetId) {
|
||||
await AssetService.update(assignment.assetId, {
|
||||
status: "AVAILABLE",
|
||||
})
|
||||
}
|
||||
|
||||
await AssignmentService.delete(id)
|
||||
|
||||
await MovementService.create({
|
||||
type: "RETURN",
|
||||
quantity: assignment.quantity || 1,
|
||||
itemId: assignment.itemId || undefined,
|
||||
assetId: assignment.assetId || undefined,
|
||||
assignmentId: id,
|
||||
})
|
||||
|
||||
revalidatePath("/assignments")
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "Assignment returned successfully",
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
import { z } from "zod"
|
||||
|
||||
export const assignmentSchema = z.object({
|
||||
id: z.string().optional(),
|
||||
quantity: z.coerce
|
||||
.number()
|
||||
.int()
|
||||
.nonnegative()
|
||||
.min(1, {
|
||||
error: "Quantity is required"
|
||||
}),
|
||||
notes: z.string().optional(),
|
||||
itemId: z.string().min(1, {
|
||||
error: "Item is required"
|
||||
}).optional(),
|
||||
assetId: z.string().optional(),
|
||||
recipientId: z.string().min(1, {
|
||||
error: "Recipient is required"
|
||||
}),
|
||||
assignmentDate: z.date().optional(),
|
||||
returnDate: z.date().optional(),
|
||||
})
|
||||
|
||||
export const createAssignmentSchema = assignmentSchema.omit({
|
||||
id: true,
|
||||
returnDate: true,
|
||||
})
|
||||
export type CreateAssignmentFormType = z.input<typeof createAssignmentSchema>
|
||||
export type CreateAssignmentData = z.output<typeof createAssignmentSchema>
|
||||
|
||||
export const updateAssignmentSchema = assignmentSchema
|
||||
.omit({
|
||||
returnDate: true,
|
||||
})
|
||||
.superRefine((data, ctx) => {
|
||||
if (data.itemId && !data.assetId) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: "Asset ID is required when item ID is provided",
|
||||
path: ["assetId"],
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
export type UpdateAssignmentFormType = z.input<typeof updateAssignmentSchema>
|
||||
|
||||
export const returnAssignmentSchema = z.object({
|
||||
id: z.string().min(1, {
|
||||
error: "Assignment ID is required"
|
||||
}),
|
||||
})
|
||||
export type ReturnAssignmentFormType = z.infer<typeof returnAssignmentSchema>
|
||||
Reference in New Issue
Block a user