import { ShotStatus, ShotApprovalStatus, TaskStatus } from "@prisma/client"; import { db } from "@/lib/db"; import type { PrismaClient } from "@prisma/client"; type TxClient = Omit< PrismaClient, "$connect" | "$disconnect" | "$on" | "$transaction" | "$use" | "$extends" >; /** * Derive shot status from tasks + shot-level approval fields. * * Priority order (highest → lowest): * 1. REVISIONS — any task is CHANGES * 2. COMPLETE — shotApprovalStatus === CLIENT_APPROVED * 3. CLIENT_REVIEW — shotApprovalStatus === INTERNALLY_APPROVED && sharedWithClient * 4. READY_FOR_CLIENT — shotApprovalStatus === INTERNALLY_APPROVED && !sharedWithClient * 5. IN_PROGRESS — any task is TODO or IN_PROGRESS * 6. INTERNAL_REVIEW — tasks exist but none blocking, approval still PENDING * 7. WAITING — no tasks */ export function deriveShotStatus( tasks: { status: TaskStatus }[], shotApprovalStatus: ShotApprovalStatus, sharedWithClient: boolean ): ShotStatus { // 1. Changes requested — highest priority if (tasks.some((t) => t.status === "CHANGES")) return "REVISIONS"; // 2. Client approved — terminal completion state if (shotApprovalStatus === "CLIENT_APPROVED") return "COMPLETE"; // 3 & 4. Internally approved — client-facing states if (shotApprovalStatus === "INTERNALLY_APPROVED") { return sharedWithClient ? "CLIENT_REVIEW" : "READY_FOR_CLIENT"; } // 5. Active work in progress (approval still PENDING) if (tasks.some((t) => t.status === "TODO" || t.status === "IN_PROGRESS")) { return "IN_PROGRESS"; } // 6. All work done, awaiting internal approval if (tasks.length > 0) return "INTERNAL_REVIEW"; // 7. No tasks yet return "WAITING"; } /** * Query all tasks + approval fields for a shot, derive the correct ShotStatus, * and persist it. Accepts an optional Prisma transaction client (tx). */ export async function recalcShotStatus( shotId: string, tx?: TxClient ): Promise { const client = tx ?? db; const [tasks, shot] = await Promise.all([ client.task.findMany({ where: { shotId }, select: { status: true }, }), client.shot.findUnique({ where: { id: shotId }, select: { shotApprovalStatus: true, sharedWithClient: true }, }), ]); if (!shot) return; const newStatus = deriveShotStatus(tasks, shot.shotApprovalStatus, shot.sharedWithClient); await client.shot.update({ where: { id: shotId }, data: { status: newStatus }, }); }