import { auth } from "@/auth"; import { db } from "@/lib/db"; import { hasPermission } from "@/lib/permissions"; import { redirect } from "next/navigation"; import { NewPoForm } from "./new-po-form"; import { buildAccountGroups } from "@/lib/cost-centre-groups"; import { formatDeliveryLocation } from "@/lib/delivery-location"; import { getTermsCatalogue, getDefaultPoTerms } from "@/lib/terms-data"; import { buildDuplicatePrefill, type DuplicatePrefill } from "@/lib/duplicate-po"; import type { Metadata } from "next"; import type { LineItemInput } from "@/lib/validations/po"; import type { CartItem } from "@/lib/cart"; export const metadata: Metadata = { title: "New Purchase Order" }; interface Props { searchParams: Promise<{ cart?: string; vesselId?: string; duplicate?: string }>; } export default async function NewPoPage({ searchParams }: Props) { const session = await auth(); if (!session?.user) redirect("/login"); if (!hasPermission(session.user.role, "create_po")) redirect("/dashboard"); const { cart, vesselId, duplicate } = await searchParams; // Duplicate-PO prefill (issue #142): copy a source PO's editable order fields // onto a fresh draft. Nothing is written until the user saves/submits — same // shape as the cart→new-PO prefill below, just a richer field set. let dup: DuplicatePrefill | null = null; let initialLineItems: LineItemInput[] | undefined; let initialVendorId: string | undefined; let initialVesselId: string | undefined = vesselId; if (duplicate) { const source = await db.purchaseOrder.findUnique({ where: { id: duplicate }, include: { lineItems: { orderBy: { sortOrder: "asc" } } }, }); if (source) dup = buildDuplicatePrefill(source); } else if (cart) { try { const cartItems: CartItem[] = JSON.parse(decodeURIComponent(cart)); if (Array.isArray(cartItems) && cartItems.length > 0) { initialLineItems = cartItems.map((item) => ({ name: item.name, description: item.description ?? "", quantity: item.quantity, unit: item.unit, size: "", unitPrice: item.unitPrice, gstRate: 0.18, productId: item.productId, })); const vendorIds = [...new Set(cartItems.map((i) => i.vendorId).filter(Boolean))]; if (vendorIds.length === 1) initialVendorId = vendorIds[0]; } } catch { // malformed cart param — ignore } } const [vessels, leafAccounts, vendors, companies, deliveryLocations, projectCodes] = await Promise.all([ db.vessel.findMany({ where: { isActive: true }, orderBy: { name: "asc" }, select: { id: true, name: true, code: true } }), db.account.findMany({ where: { isActive: true, children: { none: {} } }, orderBy: { code: "asc" }, select: { id: true, code: true, name: true, parent: { select: { name: true, code: true, parent: { select: { name: true, code: true } } } } }, }), db.vendor.findMany({ where: { isActive: true }, orderBy: { name: "asc" } }), db.company.findMany({ where: { isActive: true }, orderBy: { name: "asc" }, select: { id: true, name: true, code: true } }), db.deliveryLocation.findMany({ where: { isActive: true }, orderBy: { createdAt: "asc" }, include: { company: { select: { name: true } } } }), db.projectCode.findMany({ where: { isActive: true }, orderBy: { code: "asc" }, select: { code: true } }), ]); const accounts = buildAccountGroups(leafAccounts); const deliveryOptions = deliveryLocations.map((l) => formatDeliveryLocation(l.company.name, l.address)); const projectCodeOptions = projectCodes.map((c) => c.code); const [termsCatalogue, defaultTerms] = await Promise.all([getTermsCatalogue(), getDefaultPoTerms()]); return (

New Purchase Order

Fill in the details below. You can save as draft or submit directly for approval.

); }