"use server"; import { auth } from "@/auth"; import { db } from "@/lib/db"; import { canPerformAction } from "@/lib/po-state-machine"; import { notify } from "@/lib/notifier"; import { revalidatePath } from "next/cache"; export async function provideVendorId({ poId, vendorId, }: { poId: string; vendorId: string; }): Promise<{ ok: true } | { error: string }> { const session = await auth(); if (!session?.user) return { error: "Unauthorized" }; if (!vendorId) return { error: "Please select a vendor with a verified ID." }; const po = await db.purchaseOrder.findUnique({ where: { id: poId }, include: { submitter: true }, }); if (!po) return { error: "PO not found" }; if (!canPerformAction(po.status, "provide_vendor_id", session.user.role)) { return { error: "You cannot provide a vendor ID for this PO in its current state." }; } const vendor = await db.vendor.findUnique({ where: { id: vendorId } }); if (!vendor?.vendorId) return { error: "The selected vendor does not have a verified ID." }; await db.purchaseOrder.update({ where: { id: poId }, data: { vendorId, status: "MGR_REVIEW", actions: { create: { actionType: "VENDOR_ID_PROVIDED", actorId: session.user.id }, }, }, }); const managers = await db.user.findMany({ where: { role: "MANAGER", isActive: true } }); await notify({ event: "VENDOR_ID_PROVIDED", po, recipients: managers }); revalidatePath(`/po/${poId}`); return { ok: true }; } export async function submitDraftPo( poId: string ): Promise<{ ok: true } | { error: string }> { const session = await auth(); if (!session?.user) return { error: "Unauthorized" }; const po = await db.purchaseOrder.findUnique({ where: { id: poId }, include: { submitter: true }, }); if (!po) return { error: "PO not found" }; if (po.status !== "DRAFT") return { error: "Only draft purchase orders can be submitted." }; if (po.submitterId !== session.user.id && session.user.role !== "SUPERUSER") { return { error: "You can only submit your own purchase orders." }; } await db.purchaseOrder.update({ where: { id: poId }, data: { status: "MGR_REVIEW", submittedAt: new Date(), actions: { create: { actionType: "SUBMITTED", actorId: session.user.id }, }, }, }); const managers = await db.user.findMany({ where: { role: "MANAGER", isActive: true } }); await notify({ event: "PO_SUBMITTED", po, recipients: managers }); revalidatePath(`/po/${poId}`); revalidatePath("/dashboard"); revalidatePath("/my-orders"); return { ok: true }; } export async function discardDraftPo( poId: string ): Promise<{ ok: true } | { error: string }> { const session = await auth(); if (!session?.user) return { error: "Unauthorized" }; const po = await db.purchaseOrder.findUnique({ where: { id: poId }, select: { id: true, status: true, submitterId: true }, }); if (!po) return { error: "PO not found" }; if (po.status !== "DRAFT") return { error: "Only DRAFT purchase orders can be discarded." }; const { role, id: userId } = session.user; const canDiscard = po.submitterId === userId || ["MANAGER", "SUPERUSER"].includes(role); if (!canDiscard) return { error: "You do not have permission to discard this PO." }; // POAction has no cascade — delete child records before the PO await db.$transaction([ db.pOAction.deleteMany({ where: { poId } }), db.notification.deleteMany({ where: { poId } }), db.purchaseOrder.delete({ where: { id: poId } }), ]); revalidatePath("/my-orders"); revalidatePath("/dashboard"); return { ok: true }; }