Files
star-erp/resources/js/utils/inventory.ts

165 lines
4.7 KiB
TypeScript
Raw Normal View History

2025-12-30 15:03:19 +08:00
/**
*
*/
import { WarehouseInventory, WarehouseStats, SafetyStockSetting, SafetyStockStatus } from "../types/warehouse";
/**
*
*/
export const calculateTotalQuantity = (
inventories: WarehouseInventory[],
warehouseId: string
): number => {
return inventories
.filter((inv) => inv.warehouseId === warehouseId)
.reduce((sum, inv) => sum + inv.quantity, 0);
};
/**
*
*/
export const calculateProductTotalStock = (
inventories: WarehouseInventory[],
productId: string
): number => {
return inventories
.filter((inv) => inv.productId === productId)
.reduce((sum, inv) => sum + inv.quantity, 0);
};
/**
*
*/
export const getSafetyStockStatus = (
currentStock: number,
safetyStock: number | null | undefined
): SafetyStockStatus => {
if (!safetyStock || safetyStock === 0) return "正常";
const ratio = currentStock / safetyStock;
if (ratio >= 1.2) return "正常";
if (ratio >= 1.0) return "接近";
return "低於";
};
/**
*
*/
export const isProductLowStock = (
inventories: WarehouseInventory[],
productId: string,
safetyStockSettings: SafetyStockSetting[]
): boolean => {
const setting = safetyStockSettings.find((s) => s.productId === productId);
if (!setting) return false;
const totalStock = calculateProductTotalStock(inventories, productId);
return totalStock < setting.safetyStock;
};
/**
*
*/
export const calculateLowStockCount = (
inventories: WarehouseInventory[],
warehouseId: string,
safetyStockSettings: SafetyStockSetting[]
): number => {
// 取得該倉庫的所有庫存
const warehouseInventories = inventories.filter(
(inv) => String(inv.warehouseId) === String(warehouseId)
);
// 取得該倉庫的安全庫存設定
const warehouseSettings = safetyStockSettings.filter(
(s) => String(s.warehouseId) === String(warehouseId)
);
// 計算有多少商品低於安全庫存
let lowStockCount = 0;
warehouseSettings.forEach((setting) => {
// 找出該設定對應的商品庫存
// 注意:這裡假設一個商品在同一個倉庫只有一種庫存紀錄 (warehouse_inventory table)
// 如果有批號區分,則需要加總所有該商品的數量
const productTotalStock = warehouseInventories
.filter(inv => String(inv.productId) === String(setting.productId))
.reduce((sum, inv) => sum + inv.quantity, 0);
// 只有當安全庫存設定存在時才進行判斷 (後端已過濾掉 null)
// 若設定為 0則表示允許庫存為 0不會觸發警告 (除非庫存為負)
if (productTotalStock < setting.safetyStock) {
lowStockCount++;
}
});
return lowStockCount;
};
/**
*
*/
export const calculateReplenishmentNeeded = (
inventories: WarehouseInventory[],
warehouseId: string,
safetyStockSettings: SafetyStockSetting[]
): number => {
// 取得該倉庫的所有庫存
const warehouseInventories = inventories.filter(
(inv) => inv.warehouseId === warehouseId
);
// 取得該倉庫的安全庫存設定
const warehouseSettings = safetyStockSettings.filter(
(s) => s.warehouseId === warehouseId
);
// 計算需要撥補的總量
let replenishmentNeeded = 0;
warehouseSettings.forEach((setting) => {
const productTotalStock = calculateProductTotalStock(
warehouseInventories,
setting.productId
);
if (productTotalStock < setting.safetyStock) {
replenishmentNeeded += setting.safetyStock - productTotalStock;
}
});
return replenishmentNeeded;
};
/**
*
*/
export const calculateWarehouseStats = (
inventories: WarehouseInventory[],
warehouseId: string,
safetyStockSettings: SafetyStockSetting[]
): WarehouseStats => {
return {
totalQuantity: calculateTotalQuantity(inventories, warehouseId),
lowStockCount: calculateLowStockCount(inventories, warehouseId, safetyStockSettings),
replenishmentNeeded: calculateReplenishmentNeeded(inventories, warehouseId, safetyStockSettings),
};
};
/**
*
*/
export const hasWarehouseWarning = (
inventories: WarehouseInventory[],
warehouseId: string,
safetyStockSettings: SafetyStockSetting[]
): boolean => {
return calculateLowStockCount(inventories, warehouseId, safetyStockSettings) > 0;
};
/**
*
*/
export const filterWarehouseInventories = (
inventories: WarehouseInventory[],
warehouseId: string
): WarehouseInventory[] => {
return inventories.filter((inv) => inv.warehouseId === warehouseId);
};