import type { APIRoute } from "astro"; import { db } from "../../../../db"; import { invoices, members } from "../../../../db/schema"; import { eq, and } from "drizzle-orm"; export const POST: APIRoute = async ({ request, redirect, locals, params, }) => { const user = locals.user; if (!user) { return redirect("/login"); } const { id: invoiceId } = params; if (!invoiceId) { return new Response("Invoice ID required", { status: 400 }); } const formData = await request.formData(); const status = formData.get("status") as string; const validStatuses = [ "draft", "sent", "paid", "void", "accepted", "declined", ]; if (!status || !validStatuses.includes(status)) { return new Response("Invalid status", { status: 400 }); } const invoice = await db .select() .from(invoices) .where(eq(invoices.id, invoiceId)) .get(); if (!invoice) { return new Response("Invoice not found", { status: 404 }); } const membership = await db .select() .from(members) .where( and( eq(members.userId, user.id), eq(members.organizationId, invoice.organizationId) ) ) .get(); if (!membership) { return new Response("Unauthorized", { status: 401 }); } // Destructive status changes require owner/admin const destructiveStatuses = ["void"]; const isAdminOrOwner = membership.role === "owner" || membership.role === "admin"; if (destructiveStatuses.includes(status) && !isAdminOrOwner) { return new Response("Only owners and admins can void invoices", { status: 403 }); } try { await db .update(invoices) .set({ status: status as any }) .where(eq(invoices.id, invoiceId)); return redirect(`/dashboard/invoices/${invoiceId}`); } catch (error) { console.error("Error updating invoice status:", error); return new Response("Internal Server Error", { status: 500 }); } };