first commit
This commit is contained in:
73
source-code/ERP(B-aa)-管理採購單/src/hooks/useInspection.ts
Normal file
73
source-code/ERP(B-aa)-管理採購單/src/hooks/useInspection.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* 驗收流程管理 Hook
|
||||
*/
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import type { PurchaseOrder, InspectionItem } from "../types/purchase-order";
|
||||
|
||||
interface UseInspectionProps {
|
||||
order?: PurchaseOrder;
|
||||
}
|
||||
|
||||
export function useInspection({ order }: UseInspectionProps) {
|
||||
const [inspectionItems, setInspectionItems] = useState<InspectionItem[]>([]);
|
||||
|
||||
// 極速驗收模式:預設所有實際到貨數量 = 應到貨數量
|
||||
useEffect(() => {
|
||||
if (order) {
|
||||
setInspectionItems(
|
||||
order.items.map((item) => ({
|
||||
...item,
|
||||
receivedQuantity: item.quantity,
|
||||
damagedQuantity: 0,
|
||||
shortageQuantity: 0,
|
||||
issueType: "none",
|
||||
}))
|
||||
);
|
||||
}
|
||||
}, [order]);
|
||||
|
||||
// 更新實際收貨數量
|
||||
const updateReceivedQuantity = (index: number, value: number) => {
|
||||
const newItems = [...inspectionItems];
|
||||
const item = newItems[index];
|
||||
const expectedQty = item.quantity;
|
||||
|
||||
item.receivedQuantity = value;
|
||||
|
||||
// 自動計算短缺數量
|
||||
item.shortageQuantity = expectedQty - value;
|
||||
|
||||
// 判斷是否有異常(實際收貨 < 應到貨)
|
||||
item.issueType = value < expectedQty ? "shortage" : "none";
|
||||
|
||||
setInspectionItems(newItems);
|
||||
};
|
||||
|
||||
// 更新異常說明
|
||||
const updateIssueNote = (index: number, note: string) => {
|
||||
const newItems = [...inspectionItems];
|
||||
newItems[index].issueNote = note;
|
||||
setInspectionItems(newItems);
|
||||
};
|
||||
|
||||
// 計算統計資訊
|
||||
const statistics = {
|
||||
hasIssues: inspectionItems.some((item) => item.issueType !== "none"),
|
||||
issueItems: inspectionItems.filter((item) => item.issueType !== "none"),
|
||||
damagedItems: 0, // 不再追蹤損壞數量
|
||||
shortageItems: inspectionItems.filter((item) => item.shortageQuantity > 0).length,
|
||||
totalExpectedAmount: order?.totalAmount || 0,
|
||||
totalReceivedAmount: inspectionItems.reduce(
|
||||
(sum, item) => sum + item.receivedQuantity * item.unitPrice,
|
||||
0
|
||||
),
|
||||
};
|
||||
|
||||
return {
|
||||
inspectionItems,
|
||||
statistics,
|
||||
updateReceivedQuantity,
|
||||
updateIssueNote,
|
||||
};
|
||||
}
|
||||
Binary file not shown.
126
source-code/ERP(B-aa)-管理採購單/src/hooks/usePurchaseOrderForm.ts
Normal file
126
source-code/ERP(B-aa)-管理採購單/src/hooks/usePurchaseOrderForm.ts
Normal file
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* 採購單表單管理 Hook
|
||||
*/
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import type { PurchaseOrder, PurchaseOrderItem, Supplier, PurchaseOrderStatus, RequesterType } 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("");
|
||||
const [expectedDate, setExpectedDate] = useState("");
|
||||
const [items, setItems] = useState<PurchaseOrderItem[]>([]);
|
||||
const [notes, setNotes] = useState("");
|
||||
const [status, setStatus] = useState<PurchaseOrderStatus>("draft");
|
||||
const [requesterType, setRequesterType] = useState<RequesterType>("store");
|
||||
const [requesterId, setRequesterId] = useState("");
|
||||
|
||||
// 載入編輯訂單資料
|
||||
useEffect(() => {
|
||||
if (order) {
|
||||
setSupplierId(order.supplierId);
|
||||
setExpectedDate(order.expectedDate);
|
||||
setItems(order.items);
|
||||
setNotes(order.notes || "");
|
||||
setStatus(order.status);
|
||||
setRequesterType(order.requesterType || "store");
|
||||
setRequesterId(order.requesterId || "");
|
||||
} else {
|
||||
resetForm();
|
||||
}
|
||||
}, [order]);
|
||||
|
||||
const resetForm = () => {
|
||||
setSupplierId("");
|
||||
setExpectedDate("");
|
||||
setItems([]);
|
||||
setNotes("");
|
||||
setStatus("draft");
|
||||
setRequesterType("store");
|
||||
setRequesterId("");
|
||||
};
|
||||
|
||||
const selectedSupplier = suppliers.find((s) => s.id === supplierId);
|
||||
const isOrderSent = order && order.status !== "draft";
|
||||
|
||||
// 新增商品項目
|
||||
const addItem = () => {
|
||||
if (!selectedSupplier) return;
|
||||
|
||||
setItems([
|
||||
...items,
|
||||
{
|
||||
productId: "",
|
||||
productName: "",
|
||||
quantity: 0,
|
||||
unit: "",
|
||||
unitPrice: 0,
|
||||
subtotal: 0,
|
||||
},
|
||||
]);
|
||||
};
|
||||
|
||||
// 移除商品項目
|
||||
const removeItem = (index: number) => {
|
||||
setItems(items.filter((_, i) => i !== index));
|
||||
};
|
||||
|
||||
// 更新商品項目
|
||||
const updateItem = (index: number, field: keyof PurchaseOrderItem, value: string | number) => {
|
||||
const newItems = [...items];
|
||||
newItems[index] = { ...newItems[index], [field]: value };
|
||||
|
||||
// 當選擇商品時,自動填入商品資訊
|
||||
if (field === "productId" && selectedSupplier) {
|
||||
const product = selectedSupplier.commonProducts.find((p) => p.productId === value);
|
||||
if (product) {
|
||||
newItems[index].productName = product.productName;
|
||||
newItems[index].unit = product.unit;
|
||||
newItems[index].unitPrice = product.lastPrice;
|
||||
newItems[index].previousPrice = product.lastPrice;
|
||||
}
|
||||
}
|
||||
|
||||
// 計算小計
|
||||
if (field === "quantity" || field === "unitPrice") {
|
||||
newItems[index].subtotal = calculateSubtotal(
|
||||
newItems[index].quantity,
|
||||
newItems[index].unitPrice
|
||||
);
|
||||
}
|
||||
|
||||
setItems(newItems);
|
||||
};
|
||||
|
||||
return {
|
||||
// State
|
||||
supplierId,
|
||||
expectedDate,
|
||||
items,
|
||||
notes,
|
||||
status,
|
||||
selectedSupplier,
|
||||
isOrderSent,
|
||||
requesterType,
|
||||
requesterId,
|
||||
|
||||
// Setters
|
||||
setSupplierId,
|
||||
setExpectedDate,
|
||||
setNotes,
|
||||
setStatus,
|
||||
setRequesterType,
|
||||
setRequesterId,
|
||||
|
||||
// Methods
|
||||
addItem,
|
||||
removeItem,
|
||||
updateItem,
|
||||
resetForm,
|
||||
};
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user