feat: 優化庫存調撥單操作紀錄與 UI 佈局
This commit is contained in:
@@ -28,18 +28,94 @@ class TransferService
|
||||
/**
|
||||
* 更新調撥單明細
|
||||
*/
|
||||
/**
|
||||
* 更新調撥單明細 (支援精確 Diff 與自動日誌整合)
|
||||
*/
|
||||
public function updateItems(InventoryTransferOrder $order, array $itemsData): void
|
||||
{
|
||||
DB::transaction(function () use ($order, $itemsData) {
|
||||
// 1. 準備舊資料索引 (Key: product_id . '_' . batch_number)
|
||||
$oldItemsMap = $order->items->mapWithKeys(function ($item) {
|
||||
$key = $item->product_id . '_' . ($item->batch_number ?? '');
|
||||
return [$key => $item];
|
||||
});
|
||||
|
||||
$diff = [
|
||||
'added' => [],
|
||||
'removed' => [],
|
||||
'updated' => [],
|
||||
];
|
||||
|
||||
// 2. 處理新資料 (Deleted and Re-inserted currently for simplicity, but logic simulates update)
|
||||
// 為了保持 ID 當作外鍵的穩定性,最佳做法是 update 存在的,create 新的,delete 舊的。
|
||||
// 但考量現有邏輯是 delete all -> create all,我們維持原策略但優化 Diff 計算。
|
||||
|
||||
// 由於採用全刪重建,我們必須手動計算 Diff
|
||||
$order->items()->delete();
|
||||
|
||||
$newItemsKeys = [];
|
||||
|
||||
foreach ($itemsData as $data) {
|
||||
$order->items()->create([
|
||||
$key = $data['product_id'] . '_' . ($data['batch_number'] ?? '');
|
||||
$newItemsKeys[] = $key;
|
||||
|
||||
$item = $order->items()->create([
|
||||
'product_id' => $data['product_id'],
|
||||
'batch_number' => $data['batch_number'] ?? null,
|
||||
'quantity' => $data['quantity'],
|
||||
'notes' => $data['notes'] ?? null,
|
||||
]);
|
||||
// Eager load product for name
|
||||
$item->load('product');
|
||||
|
||||
// 比對邏輯
|
||||
if ($oldItemsMap->has($key)) {
|
||||
$oldItem = $oldItemsMap->get($key);
|
||||
// 檢查數值是否有變動
|
||||
if ((float)$oldItem->quantity !== (float)$data['quantity'] ||
|
||||
$oldItem->notes !== ($data['notes'] ?? null)) {
|
||||
|
||||
$diff['updated'][] = [
|
||||
'product_name' => $item->product->name,
|
||||
'old' => [
|
||||
'quantity' => (float)$oldItem->quantity,
|
||||
'notes' => $oldItem->notes,
|
||||
],
|
||||
'new' => [
|
||||
'quantity' => (float)$data['quantity'],
|
||||
'notes' => $item->notes,
|
||||
]
|
||||
];
|
||||
}
|
||||
} else {
|
||||
// 新增
|
||||
$diff['added'][] = [
|
||||
'product_name' => $item->product->name,
|
||||
'new' => [
|
||||
'quantity' => (float)$item->quantity,
|
||||
'notes' => $item->notes,
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 處理被移除的項目
|
||||
foreach ($oldItemsMap as $key => $oldItem) {
|
||||
if (!in_array($key, $newItemsKeys)) {
|
||||
$diff['removed'][] = [
|
||||
'product_name' => $oldItem->product->name,
|
||||
'old' => [
|
||||
'quantity' => (float)$oldItem->quantity,
|
||||
'notes' => $oldItem->notes,
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 將 Diff 注入到 Model 的暫存屬性中
|
||||
// 如果 Diff 有內容,才注入
|
||||
if (!empty($diff['added']) || !empty($diff['removed']) || !empty($diff['updated'])) {
|
||||
$order->activityProperties['items_diff'] = $diff;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -49,6 +125,9 @@ class TransferService
|
||||
*/
|
||||
public function post(InventoryTransferOrder $order, int $userId): void
|
||||
{
|
||||
// [IMPORTANT] 強制重新載入品項,因為在 Controller 中可能剛執行過 updateItems,導致記憶體中快取的 items 是舊的或空的
|
||||
$order->load('items.product');
|
||||
|
||||
DB::transaction(function () use ($order, $userId) {
|
||||
$fromWarehouse = $order->fromWarehouse;
|
||||
$toWarehouse = $order->toWarehouse;
|
||||
@@ -131,11 +210,25 @@ class TransferService
|
||||
]);
|
||||
}
|
||||
|
||||
$order->update([
|
||||
'status' => 'completed',
|
||||
'posted_at' => now(),
|
||||
'posted_by' => $userId,
|
||||
]);
|
||||
// 準備品項快照供日誌使用
|
||||
$itemsSnapshot = $order->items->map(function($item) {
|
||||
return [
|
||||
'product_name' => $item->product->name,
|
||||
'old' => [
|
||||
'quantity' => (float)$item->quantity,
|
||||
'notes' => $item->notes,
|
||||
],
|
||||
'new' => [
|
||||
'quantity' => (float)$item->quantity,
|
||||
'notes' => $item->notes,
|
||||
]
|
||||
];
|
||||
})->toArray();
|
||||
|
||||
$order->status = 'completed';
|
||||
$order->posted_at = now();
|
||||
$order->posted_by = $userId;
|
||||
$order->save(); // 觸發自動日誌
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user