feat(inventory): 實作盤點、盤調與調撥操作紀錄,並支援前端本地化顯示

This commit is contained in:
2026-02-04 13:24:33 +08:00
parent 95fdec8a06
commit a8b88b3375
4 changed files with 122 additions and 12 deletions

View File

@@ -76,6 +76,22 @@ class AdjustDocController extends Controller
} }
$doc = $this->adjustService->createFromCountDoc($countDoc, auth()->id()); $doc = $this->adjustService->createFromCountDoc($countDoc, auth()->id());
// 記錄活動
activity()
->performedOn($doc)
->causedBy(auth()->user())
->event('created')
->withProperties([
'attributes' => $doc->toArray(),
'snapshot' => [
'doc_no' => $doc->doc_no,
'warehouse_name' => $doc->warehouse?->name,
'count_doc_no' => $countDoc->doc_no,
]
])
->log('created_from_count');
return redirect()->route('inventory.adjust.show', [$doc->id]) return redirect()->route('inventory.adjust.show', [$doc->id])
->with('success', '已從盤點單生成盤調單'); ->with('success', '已從盤點單生成盤調單');
} }
@@ -172,6 +188,22 @@ class AdjustDocController extends Controller
// 提交 (items 更新 或 過帳) // 提交 (items 更新 或 過帳)
if ($request->input('action') === 'post') { if ($request->input('action') === 'post') {
$this->adjustService->post($doc, auth()->id()); $this->adjustService->post($doc, auth()->id());
// 記錄活動
activity()
->performedOn($doc)
->causedBy(auth()->user())
->event('posted')
->withProperties([
'attributes' => ['status' => 'posted'],
'old' => ['status' => 'draft'],
'snapshot' => [
'doc_no' => $doc->doc_no,
'warehouse_name' => $doc->warehouse?->name,
]
])
->log('posted');
return redirect()->route('inventory.adjust.index') return redirect()->route('inventory.adjust.index')
->with('success', '盤調單已過帳生效'); ->with('success', '盤調單已過帳生效');
} }
@@ -195,12 +227,19 @@ class AdjustDocController extends Controller
return redirect()->back()->with('success', '儲存成功'); return redirect()->back()->with('success', '儲存成功');
} }
public function destroy(InventoryAdjustDoc $doc) // 記錄活動
{ activity()
if ($doc->status !== 'draft') { ->performedOn($doc)
return redirect()->back()->with('error', '只能刪除草稿狀態的單據'); ->causedBy(auth()->user())
} ->event('deleted')
->withProperties([
'snapshot' => [
'doc_no' => $doc->doc_no,
'warehouse_name' => $doc->warehouse?->name,
]
])
->log('deleted');
$doc->items()->delete(); $doc->items()->delete();
$doc->delete(); $doc->delete();

View File

@@ -200,12 +200,19 @@ class CountDocController extends Controller
->with('success', '已取消核准,單據回復為盤點中狀態'); ->with('success', '已取消核准,單據回復為盤點中狀態');
} }
public function destroy(InventoryCountDoc $doc) // 記錄活動
{ activity()
if ($doc->status === 'completed') { ->performedOn($doc)
return redirect()->back()->with('error', '已完成的盤點單無法刪除'); ->causedBy(auth()->user())
} ->event('deleted')
->withProperties([
'snapshot' => [
'doc_no' => $doc->doc_no,
'warehouse_name' => $doc->warehouse?->name,
]
])
->log('deleted');
$doc->items()->delete(); $doc->items()->delete();
$doc->delete(); $doc->delete();

View File

@@ -81,6 +81,21 @@ class TransferOrderController extends Controller
$remarks, $remarks,
auth()->id() auth()->id()
); );
// 記錄活動
activity()
->performedOn($order)
->causedBy(auth()->user())
->event('created')
->withProperties([
'attributes' => $order->toArray(),
'snapshot' => [
'doc_no' => $order->doc_no,
'from_warehouse_name' => $order->fromWarehouse?->name,
'to_warehouse_name' => $order->toWarehouse?->name,
]
])
->log('created');
// 如果請求包含單筆商品資訊 // 如果請求包含單筆商品資訊
if ($request->has('product_id')) { if ($request->has('product_id')) {
@@ -95,6 +110,23 @@ class TransferOrderController extends Controller
if ($request->input('instant_post') === true) { if ($request->input('instant_post') === true) {
try { try {
$this->transferService->post($order, auth()->id()); $this->transferService->post($order, auth()->id());
// 記錄過帳活動
activity()
->performedOn($order)
->causedBy(auth()->user())
->event('posted')
->withProperties([
'attributes' => ['status' => 'posted'],
'old' => ['status' => 'draft'],
'snapshot' => [
'doc_no' => $order->doc_no,
'from_warehouse_name' => $order->fromWarehouse?->name,
'to_warehouse_name' => $order->toWarehouse?->name,
]
])
->log('posted');
return redirect()->back()->with('success', '撥補成功,庫存已更新'); return redirect()->back()->with('success', '撥補成功,庫存已更新');
} catch (\Exception $e) { } catch (\Exception $e) {
// 如果過帳失敗,雖然單據已建立,但應回報錯誤 // 如果過帳失敗,雖然單據已建立,但應回報錯誤
@@ -156,6 +188,23 @@ class TransferOrderController extends Controller
if ($request->input('action') === 'post') { if ($request->input('action') === 'post') {
try { try {
$this->transferService->post($order, auth()->id()); $this->transferService->post($order, auth()->id());
// 記錄活動
activity()
->performedOn($order)
->causedBy(auth()->user())
->event('posted')
->withProperties([
'attributes' => ['status' => 'posted'],
'old' => ['status' => 'draft'],
'snapshot' => [
'doc_no' => $order->doc_no,
'from_warehouse_name' => $order->fromWarehouse?->name,
'to_warehouse_name' => $order->toWarehouse?->name,
]
])
->log('posted');
return redirect()->route('inventory.transfer.index') return redirect()->route('inventory.transfer.index')
->with('success', '調撥單已過帳完成'); ->with('success', '調撥單已過帳完成');
} catch (\Exception $e) { } catch (\Exception $e) {

View File

@@ -131,6 +131,18 @@ const fieldLabels: Record<string, string> = {
recipe_id: '生產配方', recipe_id: '生產配方',
recipe_name: '配方名稱', recipe_name: '配方名稱',
yield_quantity: '預期產量', yield_quantity: '預期產量',
// 庫存單據通用欄位
doc_no: '單據編號',
snapshot_date: '快照日期',
completed_at: '完成日期',
posted_at: '過帳日期',
from_warehouse_id: '來源倉庫',
from_warehouse_name: '來源倉庫名稱',
to_warehouse_id: '目的地倉庫',
to_warehouse_name: '目的地倉庫名稱',
reason: '原因',
count_doc_id: '盤點單 ID',
count_doc_no: '盤點單號',
}; };
// 狀態翻譯對照表 // 狀態翻譯對照表
@@ -145,6 +157,9 @@ const statusMap: Record<string, string> = {
completed: '已完成', completed: '已完成',
closed: '已結案', closed: '已結案',
partial: '部分收貨', partial: '部分收貨',
// 庫存單據狀態
counting: '盤點中',
posted: '已過帳',
// 生產工單狀態 // 生產工單狀態
planned: '已計畫', planned: '已計畫',
in_progress: '生產中', in_progress: '生產中',