/** * 建立/編輯採購單頁面 */ import { ArrowLeft, Plus, Info, ShoppingCart } from "lucide-react"; import { useEffect } from "react"; import { Button } from "@/Components/ui/button"; import { Input } from "@/Components/ui/input"; import { Textarea } from "@/Components/ui/textarea"; import { Alert, AlertDescription } from "@/Components/ui/alert"; import { SearchableSelect } from "@/Components/ui/searchable-select"; import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout"; import { Head, Link, router } from "@inertiajs/react"; import { PurchaseOrderItemsTable } from "@/Components/PurchaseOrder/PurchaseOrderItemsTable"; import type { PurchaseOrder, Supplier } from "@/types/purchase-order"; import type { Warehouse } from "@/types/requester"; import { usePurchaseOrderForm } from "@/hooks/usePurchaseOrderForm"; import { filterValidItems, calculateTotalAmount, getTodayDate, formatCurrency, } from "@/utils/purchase-order"; import { STATUS_OPTIONS } from "@/constants/purchase-order"; import { toast } from "sonner"; import { getCreateBreadcrumbs, getEditBreadcrumbs } from "@/utils/breadcrumb"; interface Props { order?: PurchaseOrder; suppliers: Supplier[]; warehouses: Warehouse[]; } export default function CreatePurchaseOrder({ order, suppliers, warehouses, }: Props) { const { supplierId, expectedDate, orderDate, items, notes, selectedSupplier, isOrderSent, warehouseId, setSupplierId, setExpectedDate, setOrderDate, setNotes, setWarehouseId, addItem, removeItem, updateItem, status, setStatus, invoiceNumber, invoiceDate, invoiceAmount, setInvoiceNumber, setInvoiceDate, setInvoiceAmount, taxAmount, setTaxAmount, isTaxManual, setIsTaxManual, } = usePurchaseOrderForm({ order, suppliers }); const totalAmount = calculateTotalAmount(items); // Auto-calculate tax if not manual useEffect(() => { if (!isTaxManual) { const calculatedTax = Math.round(totalAmount * 0.05); setTaxAmount(calculatedTax); } }, [totalAmount, isTaxManual]); const handleSave = () => { if (!warehouseId) { toast.error("請選擇入庫倉庫"); return; } if (!supplierId) { toast.error("請選擇供應商"); return; } if (!orderDate) { toast.error("請選擇採購日期"); return; } if (!expectedDate) { toast.error("請選擇預計到貨日期"); return; } if (items.length === 0) { toast.error("請至少新增一項採購商品"); return; } // 檢查是否有數量大於 0 的項目 const itemsWithQuantity = items.filter(item => item.quantity > 0); if (itemsWithQuantity.length === 0) { toast.error("請填寫有效的採購數量(必須大於 0)"); return; } // 檢查有數量的項目是否都有填寫單價 const itemsWithoutPrice = itemsWithQuantity.filter(item => !item.unitPrice || item.unitPrice <= 0); if (itemsWithoutPrice.length > 0) { toast.error("請填寫所有商品的預估單價(必須大於 0)"); return; } const validItems = filterValidItems(items); if (validItems.length === 0) { toast.error("請確保所有商品都有填寫數量和單價"); return; } const data = { vendor_id: supplierId, warehouse_id: warehouseId, order_date: orderDate, expected_delivery_date: expectedDate, remark: notes, status: status, invoice_number: invoiceNumber || null, invoice_date: invoiceDate || null, invoice_amount: invoiceAmount ? parseFloat(invoiceAmount) : null, tax_amount: Number(taxAmount) || 0, items: validItems.map(item => ({ productId: item.productId, quantity: item.quantity, unitPrice: item.unitPrice, unitId: item.unitId, subtotal: item.subtotal, })), }; if (order) { router.put(`/purchase-orders/${order.id}`, data, { onSuccess: () => { },//toast.success("採購單已更新"), onError: (errors) => { // 顯示更詳細的錯誤訊息 if (errors.items) { toast.error("商品資料有誤,請檢查數量和單價是否正確填寫"); } else if (errors.error) { toast.error(errors.error); } else { toast.error("更新失敗,請檢查輸入內容"); } console.error(errors); } }); } else { router.post("/purchase-orders", data, { onSuccess: () => { },//toast.success("採購單已成功建立"), onError: (errors) => { if (errors.items) { toast.error("商品資料有誤,請檢查數量和單價是否正確填寫"); } else if (errors.error) { toast.error(errors.error); } else { toast.error("建立失敗,請檢查輸入內容"); } console.error(errors); } }); } }; const hasSupplier = !!supplierId; return (
{/* Header */}

{order ? "編輯採購單" : "建立採購單"}

{order ? `修改採購單 ${order.poNumber} 的詳細資訊` : "填寫新採購單的資訊以開始流程"}

{/* 步驟一:基本資訊 */}
1

基本資訊

({ label: w.name, value: String(w.id) }))} placeholder="請選擇倉庫" searchPlaceholder="搜尋倉庫..." />
({ label: s.name, value: String(s.id) }))} placeholder="選擇供應商" searchPlaceholder="搜尋供應商..." />
setOrderDate(e.target.value)} className="block w-full" />
setExpectedDate(e.target.value)} min={getTodayDate()} className="block w-full" />
{order && (
setStatus(v as any)} options={STATUS_OPTIONS.map((opt) => ({ label: opt.label, value: opt.value }))} placeholder="選擇狀態" />
)}