next slice

This commit is contained in:
2026-03-15 09:22:39 -05:00
parent 18e4044124
commit ce21ad4a4c
13 changed files with 708 additions and 24 deletions

View File

@@ -6,6 +6,42 @@ import { prisma } from "../../lib/prisma.js";
const purchaseOrderModel = prisma.purchaseOrder;
export interface PurchaseOrderPdfData {
documentNumber: string;
status: PurchaseOrderStatus;
issueDate: string;
vendor: {
name: string;
email: string;
phone: string;
addressLine1: string;
addressLine2: string;
city: string;
state: string;
postalCode: string;
country: string;
paymentTerms: string | null;
currencyCode: string | null;
};
notes: string;
subtotal: number;
taxPercent: number;
taxAmount: number;
freightAmount: number;
total: number;
lines: Array<{
itemSku: string;
itemName: string;
description: string;
quantity: number;
receivedQuantity: number;
remainingQuantity: number;
unitOfMeasure: string;
unitCost: number;
lineTotal: number;
}>;
}
type PurchaseLineRecord = {
id: string;
description: string;
@@ -642,3 +678,80 @@ export async function createPurchaseReceipt(orderId: string, payload: PurchaseRe
const detail = await getPurchaseOrderById(orderId);
return detail ? { ok: true as const, document: detail } : { ok: false as const, reason: "Unable to load updated purchase order." };
}
export async function getPurchaseOrderPdfData(orderId: string): Promise<PurchaseOrderPdfData | null> {
const order = await prisma.purchaseOrder.findUnique({
where: { id: orderId },
include: {
vendor: {
select: {
name: true,
email: true,
phone: true,
addressLine1: true,
addressLine2: true,
city: true,
state: true,
postalCode: true,
country: true,
paymentTerms: true,
currencyCode: true,
},
},
lines: {
include: {
item: {
select: {
sku: true,
name: true,
},
},
receiptLines: {
select: {
quantity: true,
},
},
},
orderBy: [{ position: "asc" }, { createdAt: "asc" }],
},
},
});
if (!order) {
return null;
}
const lines = order.lines.map((line) => {
const receivedQuantity = line.receiptLines.reduce((sum, receiptLine) => sum + receiptLine.quantity, 0);
return {
itemSku: line.item.sku,
itemName: line.item.name,
description: line.description,
quantity: line.quantity,
receivedQuantity,
remainingQuantity: Math.max(0, line.quantity - receivedQuantity),
unitOfMeasure: line.unitOfMeasure,
unitCost: line.unitCost,
lineTotal: line.quantity * line.unitCost,
};
});
const totals = calculateTotals(
lines.reduce((sum, line) => sum + line.lineTotal, 0),
order.taxPercent,
order.freightAmount
);
return {
documentNumber: order.documentNumber,
status: order.status as PurchaseOrderStatus,
issueDate: order.issueDate.toISOString(),
vendor: order.vendor,
notes: order.notes,
subtotal: totals.subtotal,
taxPercent: totals.taxPercent,
taxAmount: totals.taxAmount,
freightAmount: totals.freightAmount,
total: totals.total,
lines,
};
}