feat(procurement): 實作採購退回單模組並修復商品選單報錯
All checks were successful
ERP-Deploy-Demo / deploy-demo (push) Successful in 58s

This commit is contained in:
2026-02-25 13:49:02 +08:00
parent deef3baacc
commit c4908533a8
21 changed files with 2409 additions and 1 deletions

View File

@@ -0,0 +1,123 @@
import { useState, useEffect } from "react";
import type { PurchaseReturn, PurchaseReturnItem, PurchaseReturnStatus } from "@/types/purchase-return";
import type { Supplier } from "@/types/purchase-order";
interface UsePurchaseReturnFormProps {
purchaseReturn?: PurchaseReturn;
suppliers: Supplier[];
}
export function usePurchaseReturnForm({ purchaseReturn, suppliers }: UsePurchaseReturnFormProps) {
const [vendorId, setVendorId] = useState<string | number>(purchaseReturn?.vendor_id || "");
const [warehouseId, setWarehouseId] = useState<string | number>(purchaseReturn?.warehouse_id || "");
const [returnDate, setReturnDate] = useState(purchaseReturn?.return_date || new Date().toISOString().split('T')[0]);
const [items, setItems] = useState<PurchaseReturnItem[]>(purchaseReturn?.items || []);
const [remarks, setRemarks] = useState(purchaseReturn?.remarks || "");
const [status, setStatus] = useState<PurchaseReturnStatus>(purchaseReturn?.status || "draft");
const [taxAmount, setTaxAmount] = useState<string | number>(purchaseReturn?.tax_amount || 0);
// 同步外部傳入的 order 更新 (例如重新執行 edit 路由)
useEffect(() => {
if (purchaseReturn) {
setVendorId(purchaseReturn.vendor_id);
setWarehouseId(purchaseReturn.warehouse_id);
setReturnDate(purchaseReturn.return_date);
setItems(purchaseReturn.items || []);
setRemarks(purchaseReturn.remarks || "");
setStatus(purchaseReturn.status);
setTaxAmount(purchaseReturn.tax_amount || 0);
}
}, [purchaseReturn]);
const resetForm = () => {
setVendorId("");
setWarehouseId("");
setReturnDate(new Date().toISOString().split('T')[0]);
setItems([]);
setRemarks("");
setStatus("draft");
setTaxAmount(0);
};
const selectedVendor = suppliers.find((s) => String(s.id) === String(vendorId));
// 新增商品項目
const addItem = () => {
if (!selectedVendor) return;
setItems([
...items,
{
product_id: 0,
quantity_returned: 1,
unit_price: 0,
total_amount: 0,
batch_number: "",
},
]);
};
// 移除商品項目
const removeItem = (index: number) => {
setItems(items.filter((_, i) => i !== index));
};
// 更新商品項目
const updateItem = (index: number, field: keyof PurchaseReturnItem, value: any) => {
const newItems = [...items];
const item = { ...newItems[index] };
if (field === "product_id" && selectedVendor) {
const product = selectedVendor.commonProducts.find((p) => String(p.productId) === String(value));
if (product) {
// @ts-ignore
item.product_id = Number(value);
item.product_name = product.productName;
item.unit_price = product.lastPrice || 0;
item.total_amount = Number(item.quantity_returned) * Number(item.unit_price);
}
} else if (field === "total_amount") {
item.total_amount = Number(value);
if (item.quantity_returned > 0) {
item.unit_price = Number(item.total_amount) / Number(item.quantity_returned);
}
} else if (field === "quantity_returned" || field === "unit_price") {
// @ts-ignore
item[field] = Number(value);
if (field === "quantity_returned" && item.unit_price > 0) {
item.total_amount = Number(value) * item.unit_price;
} else if (field === "unit_price" && item.quantity_returned > 0) {
item.total_amount = item.quantity_returned * Number(value);
}
} else {
// @ts-ignore
item[field] = value;
}
newItems[index] = item;
setItems(newItems);
};
return {
vendorId,
warehouseId,
returnDate,
items,
remarks,
status,
selectedVendor,
taxAmount,
setVendorId,
setWarehouseId,
setReturnDate,
setRemarks,
setStatus,
setTaxAmount,
addItem,
removeItem,
updateItem,
resetForm,
};
}