/** * 採購單表單管理 Hook */ import { useState, useEffect } from "react"; import type { PurchaseOrder, PurchaseOrderItem, Supplier, PurchaseOrderStatus } from "@/types/purchase-order"; import { calculateSubtotal } from "@/utils/purchase-order"; interface UsePurchaseOrderFormProps { order?: PurchaseOrder; suppliers: Supplier[]; } export function usePurchaseOrderForm({ order, suppliers }: UsePurchaseOrderFormProps) { const [supplierId, setSupplierId] = useState(order?.supplierId || ""); const [expectedDate, setExpectedDate] = useState(order?.expectedDate || ""); const [items, setItems] = useState(order?.items || []); const [notes, setNotes] = useState(order?.remark || ""); const [status, setStatus] = useState(order?.status || "draft"); const [warehouseId, setWarehouseId] = useState(order?.warehouse_id || ""); const [invoiceNumber, setInvoiceNumber] = useState(order?.invoiceNumber || ""); const [invoiceDate, setInvoiceDate] = useState(order?.invoiceDate || ""); const [invoiceAmount, setInvoiceAmount] = useState(order?.invoiceAmount ? String(order.invoiceAmount) : ""); const [taxAmount, setTaxAmount] = useState( order?.taxAmount !== undefined && order.taxAmount !== null ? order.taxAmount : (order?.tax_amount !== undefined && order.tax_amount !== null ? order.tax_amount : "") ); const [isTaxManual, setIsTaxManual] = useState(!!(order?.taxAmount !== undefined || order?.tax_amount !== undefined)); // 同步外部傳入的 order 更新 (例如重新執行 edit 路由) useEffect(() => { if (order) { setSupplierId(order.supplierId); setExpectedDate(order.expectedDate); setItems(order.items || []); setNotes(order.remark || ""); setStatus(order.status); setWarehouseId(order.warehouse_id || ""); setInvoiceNumber(order.invoiceNumber || ""); setInvoiceDate(order.invoiceDate || ""); setInvoiceAmount(order.invoiceAmount ? String(order.invoiceAmount) : ""); const val = order.taxAmount !== undefined && order.taxAmount !== null ? order.taxAmount : (order.tax_amount !== undefined && order.tax_amount !== null ? order.tax_amount : ""); setTaxAmount(val); if (val !== "") { setIsTaxManual(true); } } }, [order]); const resetForm = () => { setSupplierId(""); setExpectedDate(""); setItems([]); setNotes(""); setStatus("draft"); setWarehouseId(""); setInvoiceNumber(""); setInvoiceDate(""); setInvoiceAmount(""); setTaxAmount(""); setIsTaxManual(false); }; const selectedSupplier = suppliers.find((s) => String(s.id) === String(supplierId)); const isOrderSent = order && order.status !== "draft"; // 新增商品項目 const addItem = () => { if (!selectedSupplier) return; setItems([ ...items, { productId: "", productName: "", quantity: 1, unitPrice: 0, subtotal: 0, selectedUnit: "base", }, ]); }; // 移除商品項目 const removeItem = (index: number) => { setItems(items.filter((_, i) => i !== index)); }; // 更新商品項目 const updateItem = (index: number, field: keyof PurchaseOrderItem, value: any) => { const newItems = [...items]; const item = { ...newItems[index] }; if (field === "productId" && selectedSupplier) { // value is productId string const product = selectedSupplier.commonProducts.find((p) => p.productId === value); if (product) { // @ts-ignore item.productId = value; item.productName = product.productName; item.base_unit_id = product.base_unit_id; item.base_unit_name = product.base_unit_name; item.large_unit_id = product.large_unit_id; item.large_unit_name = product.large_unit_name; item.purchase_unit_id = product.purchase_unit_id; item.conversion_rate = product.conversion_rate; item.unitPrice = product.lastPrice; item.previousPrice = product.lastPrice; // 決定預設單位 const isPurchaseUnitLarge = product.purchase_unit_id && product.large_unit_id && product.purchase_unit_id === product.large_unit_id; if (isPurchaseUnitLarge) { item.selectedUnit = 'large'; item.unitId = product.large_unit_id; } else { item.selectedUnit = 'base'; item.unitId = product.base_unit_id; } // 初始小計 = 數量 * 單價 item.subtotal = calculateSubtotal(Number(item.quantity), Number(item.unitPrice)); } } else if (field === "selectedUnit") { // @ts-ignore item.selectedUnit = value; if (value === 'large') { item.unitId = item.large_unit_id; } else { item.unitId = item.base_unit_id; } // Switch unit doesn't change Total Amount (Subtotal), but implies Unit Price changes? // Actually if I switch unit, the Quantity is usually for that unit. // If I have 1 Box ($100), and switch to Pc. Quantity is still 1. // Total is $100. So Unit Price (per Pc) becomes $100. // This seems safely consistent with "Total Amount" anchor. } else { // @ts-ignore item[field] = value; } // 重新計算 (Always derive UnitPrice from Subtotal and Quantity) // 除了剛剛已經算過 subtotal 的 productId case if (field !== "productId") { if (item.quantity > 0) { item.unitPrice = Number(item.subtotal) / Number(item.quantity); } else { item.unitPrice = 0; } } newItems[index] = item; setItems(newItems); }; return { // State supplierId, expectedDate, items, notes, status, selectedSupplier, isOrderSent, warehouseId, invoiceNumber, invoiceDate, invoiceAmount, taxAmount, isTaxManual, // Setters setSupplierId, setExpectedDate, setNotes, setStatus, setWarehouseId, setInvoiceNumber, setInvoiceDate, setInvoiceAmount, setTaxAmount, setIsTaxManual, // Methods addItem, removeItem, updateItem, resetForm, }; }