feat: 修正庫存與撥補單邏輯並整合文件
All checks were successful
Koori-ERP-Deploy-System / deploy-demo (push) Successful in 53s
Koori-ERP-Deploy-System / deploy-production (push) Has been skipped

1. 修復倉庫統計數據加總與樣式。
2. 修正可用庫存計算邏輯(排除不可銷售倉庫)。
3. 撥補單商品列表加入批號與效期顯示。
4. 修正撥補單儲存邏輯以支援精確批號轉移。
5. 整合 FEATURES.md 至 README.md。
This commit is contained in:
2026-01-26 14:59:24 +08:00
parent b0848a6bb8
commit 106de4e945
81 changed files with 4118 additions and 1023 deletions

View File

@@ -26,7 +26,7 @@ interface LogTableProps {
sortOrder?: 'asc' | 'desc';
onSort?: (field: string) => void;
onViewDetail: (activity: Activity) => void;
from?: number; // Starting index number (paginator.from)
from?: number; // 起始索引編號 (paginator.from)
}
export default function LogTable({
@@ -61,12 +61,12 @@ export default function LogTable({
const old = props.old || {};
const snapshot = props.snapshot || {};
// Try to find a name in snapshot, attributes or old values
// Priority: snapshot > specific name fields > generic name > code > ID
// 嘗試在快照、屬性或舊值中尋找名稱
// 優先順序:快照 > 特定名稱欄位 > 通用名稱 > 代碼 > ID
const nameParams = ['po_number', 'name', 'code', 'product_name', 'warehouse_name', 'category_name', 'base_unit_name', 'title', 'category'];
let subjectName = '';
// Special handling for Inventory: show "Warehouse - Product"
// 庫存的特殊處理:顯示 "倉庫 - 商品"
if ((snapshot.warehouse_name || attrs.warehouse_name) && (snapshot.product_name || attrs.product_name)) {
const wName = snapshot.warehouse_name || attrs.warehouse_name;
const pName = snapshot.product_name || attrs.product_name;
@@ -74,7 +74,7 @@ export default function LogTable({
} else if (old.warehouse_name && old.product_name) {
subjectName = `${old.warehouse_name} - ${old.product_name}`;
} else {
// Default fallback
// 預設備案
for (const param of nameParams) {
if (snapshot[param]) {
subjectName = snapshot[param];
@@ -91,12 +91,12 @@ export default function LogTable({
}
}
// If no name found, try ID but format it nicely if possible, or just don't show it if it's redundant with subject_type
// 如果找不到名稱,嘗試使用 ID如果可能則格式化顯示或者如果與主題類型重複則不顯示
if (!subjectName && (attrs.id || old.id)) {
subjectName = `#${attrs.id || old.id}`;
}
// Combine parts: [Causer] [Action] [Name] [Subject]
// 組合部分:[操作者] [動作] [名稱] [主題]
// Example: Admin 新增 可樂 商品
// Example: Admin 更新 台北倉 - 可樂 庫存
return (
@@ -114,7 +114,7 @@ export default function LogTable({
<span className="text-gray-700">{activity.subject_type}</span>
)}
{/* Display reason/source if available (e.g., from Replenishment) */}
{/* 如果有原因/來源則顯示(例如:來自補貨) */}
{(attrs._reason || old._reason) && (
<span className="text-gray-500 text-xs">
( {attrs._reason || old._reason})