Initial commit
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
"use server";
|
||||
|
||||
import { auth } from "@/auth";
|
||||
import { db } from "@/lib/db";
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { z } from "zod";
|
||||
import { ApprovalStatus } from "@prisma/client";
|
||||
import { recalcShotStatus } from "@/lib/shot-status";
|
||||
import { notifyApprovalChange } from "@/lib/notifications";
|
||||
import { slackNotifyApproval } from "@/lib/slack";
|
||||
import { versionLabel } from "@/lib/utils";
|
||||
|
||||
const approvalSchema = z.object({
|
||||
versionId: z.string().cuid(),
|
||||
status: z.nativeEnum(ApprovalStatus),
|
||||
notes: z.string().optional(),
|
||||
});
|
||||
|
||||
export async function submitApproval(data: z.infer<typeof approvalSchema>) {
|
||||
const session = await auth();
|
||||
if (!session?.user) throw new Error("Unauthorized");
|
||||
|
||||
const parsed = approvalSchema.parse(data);
|
||||
|
||||
// Only supervisors, producers, admins, and clients can approve
|
||||
const allowedRoles = ["ADMIN", "PRODUCER", "SUPERVISOR", "CLIENT"];
|
||||
if (!allowedRoles.includes(session.user.role)) {
|
||||
throw new Error("Insufficient permissions to review versions");
|
||||
}
|
||||
|
||||
// Create the approval record
|
||||
const approval = await db.approval.create({
|
||||
data: {
|
||||
versionId: parsed.versionId,
|
||||
userId: session.user.id,
|
||||
status: parsed.status,
|
||||
notes: parsed.notes,
|
||||
},
|
||||
});
|
||||
|
||||
// Update version approval status
|
||||
await db.version.update({
|
||||
where: { id: parsed.versionId },
|
||||
data: { approvalStatus: parsed.status },
|
||||
});
|
||||
|
||||
// Load version + task + shot + project for downstream effects
|
||||
const version = await db.version.findUnique({
|
||||
where: { id: parsed.versionId },
|
||||
include: {
|
||||
task: {
|
||||
include: {
|
||||
shot: true,
|
||||
project: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!version) throw new Error("Version not found");
|
||||
|
||||
// Update task status based on approval result
|
||||
if (version.task && parsed.status !== "PENDING_REVIEW") {
|
||||
if (parsed.status === "APPROVED") {
|
||||
await db.task.update({
|
||||
where: { id: version.task.id },
|
||||
data: { status: "DONE" },
|
||||
});
|
||||
} else if (parsed.status === "REJECTED" || parsed.status === "NEEDS_CHANGES") {
|
||||
await db.task.update({
|
||||
where: { id: version.task.id },
|
||||
data: { status: "CHANGES" },
|
||||
});
|
||||
}
|
||||
|
||||
// Recalculate shot status from updated task states
|
||||
if (version.task.shot) {
|
||||
await recalcShotStatus(version.task.shot.id).catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
// Notifications
|
||||
const reviewer = await db.user.findUnique({ where: { id: session.user.id } });
|
||||
const reviewerName = reviewer?.name ?? "Reviewer";
|
||||
|
||||
if (version.task && parsed.status !== "PENDING_REVIEW") {
|
||||
const contextCode = version.task.shot?.shotCode ?? null;
|
||||
await notifyApprovalChange({
|
||||
artistId: version.task.assignedArtistId ?? version.artistId,
|
||||
shotCode: contextCode ?? version.task.title,
|
||||
versionId: parsed.versionId,
|
||||
status: parsed.status as "APPROVED" | "REJECTED" | "NEEDS_CHANGES",
|
||||
reviewerName,
|
||||
});
|
||||
|
||||
// Slack
|
||||
if (version.task.project.slackWebhook) {
|
||||
const appUrl = process.env.NEXT_PUBLIC_APP_URL ?? "http://localhost:3000";
|
||||
await slackNotifyApproval(version.task.project.slackWebhook, {
|
||||
shotCode: contextCode ?? version.task.title,
|
||||
versionLabel: versionLabel(version.versionNumber),
|
||||
status: parsed.status as "APPROVED" | "REJECTED" | "NEEDS_CHANGES",
|
||||
reviewerName,
|
||||
projectName: version.task.project.name,
|
||||
reviewUrl: `${appUrl}/review/${parsed.versionId}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
revalidatePath(`/review/${parsed.versionId}`);
|
||||
if (version.task) {
|
||||
revalidatePath(`/tasks/${version.task.id}`);
|
||||
revalidatePath(`/projects/${version.task.projectId}`);
|
||||
}
|
||||
|
||||
return { success: true, approval };
|
||||
}
|
||||
|
||||
export async function getApprovalHistory(versionId: string) {
|
||||
const session = await auth();
|
||||
if (!session?.user) throw new Error("Unauthorized");
|
||||
|
||||
return db.approval.findMany({
|
||||
where: { versionId },
|
||||
include: {
|
||||
user: { select: { id: true, name: true, email: true, image: true, role: true } },
|
||||
},
|
||||
orderBy: { createdAt: "desc" },
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user