feat: 整合門市領料日誌、API 文件存取、修改庫存與併發編號問題、供應商商品內聯編輯及日誌 UI 優化
All checks were successful
ERP-Deploy-Demo / deploy-demo (push) Successful in 1m0s
All checks were successful
ERP-Deploy-Demo / deploy-demo (push) Successful in 1m0s
This commit is contained in:
@@ -189,71 +189,81 @@ class PurchaseOrderController extends Controller
|
||||
]);
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
// 使用 Cache Lock 防止併發時產生重複單號
|
||||
$lock = \Illuminate\Support\Facades\Cache::lock('po_code_generation', 10);
|
||||
|
||||
// 生成單號:PO-YYYYMMDD-01
|
||||
$today = now()->format('Ymd');
|
||||
$prefix = 'PO-' . $today . '-';
|
||||
$lastOrder = PurchaseOrder::where('code', 'like', $prefix . '%')
|
||||
->lockForUpdate() // 鎖定以避免並發衝突
|
||||
->orderBy('code', 'desc')
|
||||
->first();
|
||||
|
||||
if ($lastOrder) {
|
||||
// 取得最後 2 碼序號並加 1
|
||||
$lastSequence = intval(substr($lastOrder->code, -2));
|
||||
$sequence = str_pad($lastSequence + 1, 2, '0', STR_PAD_LEFT);
|
||||
} else {
|
||||
$sequence = '01';
|
||||
}
|
||||
$code = $prefix . $sequence;
|
||||
|
||||
$totalAmount = 0;
|
||||
foreach ($validated['items'] as $item) {
|
||||
$totalAmount += $item['subtotal'];
|
||||
if (!$lock->get()) {
|
||||
return back()->withErrors(['error' => '系統忙碌中,請稍後再試']);
|
||||
}
|
||||
|
||||
// 稅額計算
|
||||
$taxAmount = isset($validated['tax_amount']) ? $validated['tax_amount'] : round($totalAmount * 0.05, 2);
|
||||
$grandTotal = $totalAmount + $taxAmount;
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
// 確保有一個有效的使用者 ID
|
||||
$userId = auth()->id();
|
||||
if (!$userId) {
|
||||
$user = $this->coreService->ensureSystemUserExists(); $userId = $user->id;
|
||||
}
|
||||
// 生成單號:PO-YYYYMMDD-01
|
||||
$today = now()->format('Ymd');
|
||||
$prefix = 'PO-' . $today . '-';
|
||||
$lastOrder = PurchaseOrder::where('code', 'like', $prefix . '%')
|
||||
->orderBy('code', 'desc')
|
||||
->first();
|
||||
|
||||
$order = PurchaseOrder::create([
|
||||
'code' => $code,
|
||||
'vendor_id' => $validated['vendor_id'],
|
||||
'warehouse_id' => $validated['warehouse_id'],
|
||||
'user_id' => $userId,
|
||||
'status' => 'draft',
|
||||
'order_date' => $validated['order_date'], // 新增
|
||||
'expected_delivery_date' => $validated['expected_delivery_date'],
|
||||
'total_amount' => $totalAmount,
|
||||
'tax_amount' => $taxAmount,
|
||||
'grand_total' => $grandTotal,
|
||||
'remark' => $validated['remark'],
|
||||
'invoice_number' => $validated['invoice_number'] ?? null,
|
||||
'invoice_date' => $validated['invoice_date'] ?? null,
|
||||
'invoice_amount' => $validated['invoice_amount'] ?? null,
|
||||
]);
|
||||
if ($lastOrder) {
|
||||
$lastSequence = intval(substr($lastOrder->code, -2));
|
||||
$sequence = str_pad($lastSequence + 1, 2, '0', STR_PAD_LEFT);
|
||||
} else {
|
||||
$sequence = '01';
|
||||
}
|
||||
$code = $prefix . $sequence;
|
||||
|
||||
foreach ($validated['items'] as $item) {
|
||||
// 反算單價
|
||||
$unitPrice = $item['quantity'] > 0 ? $item['subtotal'] / $item['quantity'] : 0;
|
||||
$totalAmount = 0;
|
||||
foreach ($validated['items'] as $item) {
|
||||
$totalAmount += $item['subtotal'];
|
||||
}
|
||||
|
||||
$order->items()->create([
|
||||
'product_id' => $item['productId'],
|
||||
'quantity' => $item['quantity'],
|
||||
'unit_id' => $item['unitId'] ?? null,
|
||||
'unit_price' => $unitPrice,
|
||||
'subtotal' => $item['subtotal'],
|
||||
// 稅額計算
|
||||
$taxAmount = isset($validated['tax_amount']) ? $validated['tax_amount'] : round($totalAmount * 0.05, 2);
|
||||
$grandTotal = $totalAmount + $taxAmount;
|
||||
|
||||
// 確保有一個有效的使用者 ID
|
||||
$userId = auth()->id();
|
||||
if (!$userId) {
|
||||
$user = $this->coreService->ensureSystemUserExists();
|
||||
$userId = $user->id;
|
||||
}
|
||||
|
||||
$order = PurchaseOrder::create([
|
||||
'code' => $code,
|
||||
'vendor_id' => $validated['vendor_id'],
|
||||
'warehouse_id' => $validated['warehouse_id'],
|
||||
'user_id' => $userId,
|
||||
'status' => 'draft',
|
||||
'order_date' => $validated['order_date'],
|
||||
'expected_delivery_date' => $validated['expected_delivery_date'],
|
||||
'total_amount' => $totalAmount,
|
||||
'tax_amount' => $taxAmount,
|
||||
'grand_total' => $grandTotal,
|
||||
'remark' => $validated['remark'],
|
||||
'invoice_number' => $validated['invoice_number'] ?? null,
|
||||
'invoice_date' => $validated['invoice_date'] ?? null,
|
||||
'invoice_amount' => $validated['invoice_amount'] ?? null,
|
||||
]);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
foreach ($validated['items'] as $item) {
|
||||
// 反算單價
|
||||
$unitPrice = $item['quantity'] > 0 ? $item['subtotal'] / $item['quantity'] : 0;
|
||||
|
||||
$order->items()->create([
|
||||
'product_id' => $item['productId'],
|
||||
'quantity' => $item['quantity'],
|
||||
'unit_id' => $item['unitId'] ?? null,
|
||||
'unit_price' => $unitPrice,
|
||||
'subtotal' => $item['subtotal'],
|
||||
]);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
} finally {
|
||||
$lock->release();
|
||||
}
|
||||
|
||||
return redirect()->route('purchase-orders.index')->with('success', '採購單已成功建立');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user