feat: 修正庫存與撥補單邏輯並整合文件
1. 修復倉庫統計數據加總與樣式。 2. 修正可用庫存計算邏輯(排除不可銷售倉庫)。 3. 撥補單商品列表加入批號與效期顯示。 4. 修正撥補單儲存邏輯以支援精確批號轉移。 5. 整合 FEATURES.md 至 README.md。
This commit is contained in:
@@ -95,7 +95,7 @@ export default function AddSafetyStockDialog({
|
||||
// 更新商品安全庫存量
|
||||
const updateQuantity = (productId: string, value: number) => {
|
||||
const newQuantities = new Map(productQuantities);
|
||||
newQuantities.set(productId, value); // Allow 0
|
||||
newQuantities.set(productId, value); // 允許為 0
|
||||
setProductQuantities(newQuantities);
|
||||
};
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ interface TransferOrderDialogProps {
|
||||
onOpenChange: (open: boolean) => void;
|
||||
order: TransferOrder | null;
|
||||
warehouses: Warehouse[];
|
||||
// inventories: WarehouseInventory[]; // Removed as we fetch from API
|
||||
// inventories: WarehouseInventory[]; // 因從 API 獲取而移除
|
||||
onSave: (order: Omit<TransferOrder, "id" | "createdAt" | "orderNumber">) => void;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ interface AvailableProduct {
|
||||
batchNumber: string;
|
||||
availableQty: number;
|
||||
unit: string;
|
||||
expiryDate: string | null;
|
||||
}
|
||||
|
||||
export default function TransferOrderDialog({
|
||||
@@ -99,7 +100,15 @@ export default function TransferOrderDialog({
|
||||
if (formData.sourceWarehouseId) {
|
||||
axios.get(route('api.warehouses.inventories', formData.sourceWarehouseId))
|
||||
.then(response => {
|
||||
setAvailableProducts(response.data);
|
||||
const mappedData = response.data.map((item: any) => ({
|
||||
productId: item.product_id,
|
||||
productName: item.product_name,
|
||||
batchNumber: item.batch_number,
|
||||
availableQty: item.quantity,
|
||||
unit: item.unit_name,
|
||||
expiryDate: item.expiry_date
|
||||
}));
|
||||
setAvailableProducts(mappedData);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Failed to fetch inventories:", error);
|
||||
@@ -240,7 +249,7 @@ export default function TransferOrderDialog({
|
||||
onValueChange={handleProductChange}
|
||||
disabled={!formData.sourceWarehouseId || !!order}
|
||||
options={availableProducts.map((product) => ({
|
||||
label: `${product.productName} (庫存: ${product.availableQty} ${product.unit})`,
|
||||
label: `${product.productName} | 批號: ${product.batchNumber || '-'} | 效期: ${product.expiryDate || '-'} (庫存: ${product.availableQty} ${product.unit})`,
|
||||
value: `${product.productId}|||${product.batchNumber}`,
|
||||
}))}
|
||||
placeholder="選擇商品與批號"
|
||||
|
||||
@@ -78,8 +78,17 @@ export default function WarehouseCard({
|
||||
{warehouse.description || "無描述"}
|
||||
</div>
|
||||
|
||||
{/* 統計區塊 - 庫存警告 */}
|
||||
|
||||
{/* 統計區塊 - 狀態標籤 */}
|
||||
<div className="space-y-3">
|
||||
{/* 銷售狀態 */}
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-gray-500">銷售狀態</span>
|
||||
<Badge variant={warehouse.is_sellable ? "default" : "secondary"} className={warehouse.is_sellable ? "bg-green-600" : "bg-gray-400"}>
|
||||
{warehouse.is_sellable ? "可銷售" : "暫停銷售"}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
{/* 低庫存警告狀態 */}
|
||||
<div className="flex items-center justify-between p-3 rounded-lg bg-gray-50">
|
||||
<div className="flex items-center gap-2 text-gray-600">
|
||||
|
||||
@@ -51,11 +51,13 @@ export default function WarehouseDialog({
|
||||
name: string;
|
||||
address: string;
|
||||
description: string;
|
||||
is_sellable: boolean;
|
||||
}>({
|
||||
code: "",
|
||||
name: "",
|
||||
address: "",
|
||||
description: "",
|
||||
is_sellable: true,
|
||||
});
|
||||
|
||||
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
|
||||
@@ -67,6 +69,7 @@ export default function WarehouseDialog({
|
||||
name: warehouse.name,
|
||||
address: warehouse.address || "",
|
||||
description: warehouse.description || "",
|
||||
is_sellable: warehouse.is_sellable ?? true,
|
||||
});
|
||||
} else {
|
||||
setFormData({
|
||||
@@ -74,6 +77,7 @@ export default function WarehouseDialog({
|
||||
name: "",
|
||||
address: "",
|
||||
description: "",
|
||||
is_sellable: true,
|
||||
});
|
||||
}
|
||||
}, [warehouse, open]);
|
||||
@@ -148,6 +152,23 @@ export default function WarehouseDialog({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 銷售設定 */}
|
||||
<div className="space-y-4">
|
||||
<div className="border-b pb-2">
|
||||
<h4 className="text-sm text-gray-700">銷售設定</h4>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="is_sellable"
|
||||
className="h-4 w-4 rounded border-gray-300 text-primary-main focus:ring-primary-main"
|
||||
checked={formData.is_sellable}
|
||||
onChange={(e) => setFormData({ ...formData, is_sellable: e.target.checked })}
|
||||
/>
|
||||
<Label htmlFor="is_sellable">此倉庫可進行銷售扣庫</Label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 區塊 B:位置 */}
|
||||
<div className="space-y-4">
|
||||
<div className="border-b pb-2">
|
||||
@@ -210,10 +231,10 @@ export default function WarehouseDialog({
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</Dialog >
|
||||
|
||||
{/* 刪除確認對話框 */}
|
||||
<AlertDialog open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
|
||||
< AlertDialog open={showDeleteDialog} onOpenChange={setShowDeleteDialog} >
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>確認刪除倉庫</AlertDialogTitle>
|
||||
@@ -231,7 +252,7 @@ export default function WarehouseDialog({
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</AlertDialog >
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user