feat: 實作出貨單模組並暫時導向通用製作中頁面,同步優化盤點與調撥功能的活動日誌顯示
This commit is contained in:
@@ -106,6 +106,16 @@ interface InventoryServiceInterface
|
||||
*/
|
||||
public function decreaseInventoryQuantity(int $inventoryId, float $quantity, ?string $reason = null, ?string $referenceType = null, $referenceId = null);
|
||||
|
||||
/**
|
||||
* Find a specific inventory record by warehouse, product and batch.
|
||||
*
|
||||
* @param int $warehouseId
|
||||
* @param int $productId
|
||||
* @param string|null $batchNumber
|
||||
* @return object|null
|
||||
*/
|
||||
public function findInventoryByBatch(int $warehouseId, int $productId, ?string $batchNumber);
|
||||
|
||||
/**
|
||||
* Get statistics for the dashboard.
|
||||
*
|
||||
|
||||
@@ -127,7 +127,7 @@ class TransferOrderController extends Controller
|
||||
'batch_number' => $item->batch_number,
|
||||
'unit' => $item->product->baseUnit?->name,
|
||||
'quantity' => (float) $item->quantity,
|
||||
'max_quantity' => $stock ? (float) $stock->quantity : 0.0,
|
||||
'max_quantity' => $item->snapshot_quantity ? (float) $item->snapshot_quantity : ($stock ? (float) $stock->quantity : 0.0),
|
||||
'notes' => $item->notes,
|
||||
];
|
||||
}),
|
||||
@@ -154,14 +154,22 @@ class TransferOrderController extends Controller
|
||||
]);
|
||||
|
||||
// 1. 先更新資料
|
||||
$itemsChanged = false;
|
||||
if ($request->has('items')) {
|
||||
$this->transferService->updateItems($order, $validated['items']);
|
||||
$itemsChanged = $this->transferService->updateItems($order, $validated['items']);
|
||||
}
|
||||
|
||||
$order->fill($request->only(['remarks']));
|
||||
$remarksChanged = $order->remarks !== ($validated['remarks'] ?? null);
|
||||
|
||||
// [IMPORTANT] 使用 touch() 確保即便只有品項異動,也會因為 updated_at 變更而觸發自動日誌
|
||||
$order->touch();
|
||||
if ($itemsChanged || $remarksChanged) {
|
||||
$order->remarks = $validated['remarks'] ?? null;
|
||||
// [IMPORTANT] 使用 touch() 確保即便只有品項異動,也會因為 updated_at 變更而觸發自動日誌
|
||||
$order->touch();
|
||||
$message = '儲存成功';
|
||||
} else {
|
||||
$message = '資料未變更';
|
||||
// 如果沒變更,就不執行 touch(),也不會產生 Activity Log
|
||||
}
|
||||
|
||||
// 2. 判斷是否需要過帳
|
||||
if ($request->input('action') === 'post') {
|
||||
@@ -174,7 +182,7 @@ class TransferOrderController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->back()->with('success', '儲存成功');
|
||||
return redirect()->back()->with('success', $message);
|
||||
}
|
||||
|
||||
public function destroy(InventoryTransferOrder $order)
|
||||
|
||||
@@ -15,6 +15,7 @@ class InventoryTransferItem extends Model
|
||||
'product_id',
|
||||
'batch_number',
|
||||
'quantity',
|
||||
'snapshot_quantity',
|
||||
'notes',
|
||||
];
|
||||
|
||||
|
||||
@@ -188,6 +188,14 @@ class InventoryService implements InventoryServiceInterface
|
||||
});
|
||||
}
|
||||
|
||||
public function findInventoryByBatch(int $warehouseId, int $productId, ?string $batchNumber)
|
||||
{
|
||||
return Inventory::where('warehouse_id', $warehouseId)
|
||||
->where('product_id', $productId)
|
||||
->where('batch_number', $batchNumber)
|
||||
->first();
|
||||
}
|
||||
|
||||
public function getDashboardStats(): array
|
||||
{
|
||||
// 庫存總表 join 安全庫存表,計算低庫存
|
||||
|
||||
@@ -31,9 +31,9 @@ class TransferService
|
||||
/**
|
||||
* 更新調撥單明細 (支援精確 Diff 與自動日誌整合)
|
||||
*/
|
||||
public function updateItems(InventoryTransferOrder $order, array $itemsData): void
|
||||
public function updateItems(InventoryTransferOrder $order, array $itemsData): bool
|
||||
{
|
||||
DB::transaction(function () use ($order, $itemsData) {
|
||||
return 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 ?? '');
|
||||
@@ -88,9 +88,13 @@ class TransferService
|
||||
];
|
||||
}
|
||||
} else {
|
||||
// 新增
|
||||
$diff['added'][] = [
|
||||
// 新增 (使用者需求:顯示為更新,從 0 -> X)
|
||||
$diff['updated'][] = [
|
||||
'product_name' => $item->product->name,
|
||||
'old' => [
|
||||
'quantity' => 0,
|
||||
'notes' => null,
|
||||
],
|
||||
'new' => [
|
||||
'quantity' => (float)$item->quantity,
|
||||
'notes' => $item->notes,
|
||||
@@ -113,10 +117,12 @@ class TransferService
|
||||
}
|
||||
|
||||
// 4. 將 Diff 注入到 Model 的暫存屬性中
|
||||
// 如果 Diff 有內容,才注入
|
||||
if (!empty($diff['added']) || !empty($diff['removed']) || !empty($diff['updated'])) {
|
||||
$hasChanged = !empty($diff['added']) || !empty($diff['removed']) || !empty($diff['updated']);
|
||||
if ($hasChanged) {
|
||||
$order->activityProperties['items_diff'] = $diff;
|
||||
}
|
||||
|
||||
return $hasChanged;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -149,6 +155,9 @@ class TransferService
|
||||
|
||||
$oldSourceQty = $sourceInventory->quantity;
|
||||
$newSourceQty = $oldSourceQty - $item->quantity;
|
||||
|
||||
// 儲存庫存快照
|
||||
$item->update(['snapshot_quantity' => $oldSourceQty]);
|
||||
|
||||
$sourceInventory->quantity = $newSourceQty;
|
||||
// 更新總值 (假設成本不變)
|
||||
|
||||
Reference in New Issue
Block a user