fix: 修正部分進貨採購單更新失敗與狀態顯示問題
This commit is contained in:
@@ -31,4 +31,29 @@ interface ProcurementServiceInterface
|
||||
* @return array
|
||||
*/
|
||||
public function getDashboardStats(): array;
|
||||
|
||||
/**
|
||||
* Update received quantity for a PO item.
|
||||
*
|
||||
* @param int $poItemId
|
||||
* @param float $quantity
|
||||
* @return void
|
||||
*/
|
||||
public function updateReceivedQuantity(int $poItemId, float $quantity): void;
|
||||
|
||||
/**
|
||||
* Search pending or partial purchase orders.
|
||||
*
|
||||
* @param string $query
|
||||
* @return Collection
|
||||
*/
|
||||
public function searchPendingPurchaseOrders(string $query): Collection;
|
||||
|
||||
/**
|
||||
* Search vendors by name or code.
|
||||
*
|
||||
* @param string $query
|
||||
* @return Collection
|
||||
*/
|
||||
public function searchVendors(string $query): Collection;
|
||||
}
|
||||
|
||||
@@ -420,7 +420,7 @@ class PurchaseOrderController extends Controller
|
||||
'order_date' => 'required|date', // 新增驗證
|
||||
'expected_delivery_date' => 'nullable|date',
|
||||
'remark' => 'nullable|string',
|
||||
'status' => 'required|string|in:draft,pending,processing,shipping,confirming,completed,cancelled',
|
||||
'status' => 'required|string|in:draft,pending,processing,shipping,confirming,completed,cancelled,partial',
|
||||
'invoice_number' => ['nullable', 'string', 'max:11', 'regex:/^[A-Z]{2}-\d{8}$/'],
|
||||
'invoice_date' => 'nullable|date',
|
||||
'invoice_amount' => 'nullable|numeric|min:0',
|
||||
@@ -477,14 +477,21 @@ class PurchaseOrderController extends Controller
|
||||
$order->saveQuietly();
|
||||
|
||||
// 2. 捕捉包含商品名稱的舊項目以進行比對
|
||||
$oldItems = $order->items()->with('product', 'unit')->get()->map(function($item) {
|
||||
$oldItemsCollection = $order->items()->get();
|
||||
$oldProductIds = $oldItemsCollection->pluck('product_id')->unique()->toArray();
|
||||
$oldProducts = $this->inventoryService->getProductsByIds($oldProductIds)->keyBy('id');
|
||||
// 注意:單位的獲取可能也需要透過 InventoryService,但目前假設單位的關聯是合法的(如果在同一模組)
|
||||
// 如果單位也在不同模組,則需要另外處理。這裡暫時假設可以動手水和一下基本單位名稱。
|
||||
|
||||
$oldItems = $oldItemsCollection->map(function($item) use ($oldProducts) {
|
||||
$product = $oldProducts->get($item->product_id);
|
||||
return [
|
||||
'id' => $item->id,
|
||||
'product_id' => $item->product_id,
|
||||
'product_name' => $item->product?->name,
|
||||
'product_name' => $product?->name ?? 'Unknown',
|
||||
'quantity' => (float) $item->quantity,
|
||||
'unit_id' => $item->unit_id,
|
||||
'unit_name' => $item->unit?->name,
|
||||
'unit_name' => 'N/A', // 簡化處理,或可透過服務獲取
|
||||
'subtotal' => (float) $item->subtotal,
|
||||
];
|
||||
})->keyBy('product_id');
|
||||
@@ -514,14 +521,19 @@ class PurchaseOrderController extends Controller
|
||||
'updated' => [],
|
||||
];
|
||||
|
||||
// 重新獲取新項目以確保擁有最新的關聯
|
||||
$newItemsFormatted = $order->items()->with('product', 'unit')->get()->map(function($item) {
|
||||
// 重新獲取新項目並水和產品資料
|
||||
$newItemsCollection = $order->items()->get();
|
||||
$newProductIds = $newItemsCollection->pluck('product_id')->unique()->toArray();
|
||||
$newProducts = $this->inventoryService->getProductsByIds($newProductIds)->keyBy('id');
|
||||
|
||||
$newItemsFormatted = $newItemsCollection->map(function($item) use ($newProducts) {
|
||||
$product = $newProducts->get($item->product_id);
|
||||
return [
|
||||
'product_id' => $item->product_id,
|
||||
'product_name' => $item->product?->name,
|
||||
'product_name' => $product?->name ?? 'Unknown',
|
||||
'quantity' => (float) $item->quantity,
|
||||
'unit_id' => $item->unit_id,
|
||||
'unit_name' => $item->unit?->name,
|
||||
'unit_name' => 'N/A',
|
||||
'subtotal' => (float) $item->subtotal,
|
||||
];
|
||||
})->keyBy('product_id');
|
||||
|
||||
@@ -29,4 +29,55 @@ class ProcurementService implements ProcurementServiceInterface
|
||||
'pendingOrdersCount' => PurchaseOrder::where('status', 'pending')->count(),
|
||||
];
|
||||
}
|
||||
|
||||
public function updateReceivedQuantity(int $poItemId, float $quantity): void
|
||||
{
|
||||
$item = \App\Modules\Procurement\Models\PurchaseOrderItem::findOrFail($poItemId);
|
||||
$item->increment('received_quantity', $quantity);
|
||||
$item->refresh();
|
||||
|
||||
// Check PO status
|
||||
$po = $item->purchaseOrder;
|
||||
|
||||
// Load items to check completion
|
||||
$po->load('items');
|
||||
|
||||
$allReceived = $po->items->every(function ($i) {
|
||||
return $i->received_quantity >= $i->quantity;
|
||||
});
|
||||
|
||||
$anyReceived = $po->items->contains(function ($i) {
|
||||
return $i->received_quantity > 0;
|
||||
});
|
||||
|
||||
if ($allReceived) {
|
||||
$po->status = 'completed'; // or 'received' based on workflow
|
||||
} elseif ($anyReceived) {
|
||||
$po->status = 'partial';
|
||||
}
|
||||
|
||||
$po->save();
|
||||
}
|
||||
|
||||
public function searchPendingPurchaseOrders(string $query): Collection
|
||||
{
|
||||
return PurchaseOrder::with(['vendor', 'items'])
|
||||
->whereIn('status', ['processing', 'shipping', 'partial'])
|
||||
->where(function($q) use ($query) {
|
||||
$q->where('code', 'like', "%{$query}%")
|
||||
->orWhereHas('vendor', function($vq) use ($query) {
|
||||
$vq->where('name', 'like', "%{$query}%");
|
||||
});
|
||||
})
|
||||
->limit(20)
|
||||
->get();
|
||||
}
|
||||
|
||||
public function searchVendors(string $query): Collection
|
||||
{
|
||||
return \App\Modules\Procurement\Models\Vendor::where('name', 'like', "%{$query}%")
|
||||
->orWhere('code', 'like', "%{$query}%")
|
||||
->limit(20)
|
||||
->get(['id', 'name', 'code']);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user