Files
star-erp/app/Modules/Procurement/Services/ShippingService.php
sky121113 04f3891275
All checks were successful
Koori-ERP-Deploy-System / deploy-demo (push) Successful in 1m11s
Koori-ERP-Deploy-System / deploy-production (push) Has been skipped
feat: 實作出貨單模組並暫時導向通用製作中頁面,同步優化盤點與調撥功能的活動日誌顯示
2026-02-05 09:33:36 +08:00

119 lines
4.3 KiB
PHP

<?php
namespace App\Modules\Procurement\Services;
use App\Modules\Procurement\Models\ShippingOrder;
use App\Modules\Procurement\Models\ShippingOrderItem;
use App\Modules\Inventory\Contracts\InventoryServiceInterface;
use Illuminate\Support\Facades\DB;
class ShippingService
{
protected $inventoryService;
public function __construct(InventoryServiceInterface $inventoryService)
{
$this->inventoryService = $inventoryService;
}
public function createShippingOrder(array $data)
{
return DB::transaction(function () use ($data) {
$order = ShippingOrder::create([
'warehouse_id' => $data['warehouse_id'],
'customer_name' => $data['customer_name'] ?? null,
'shipping_date' => $data['shipping_date'],
'status' => 'draft',
'remarks' => $data['remarks'] ?? null,
'created_by' => auth()->id(),
'total_amount' => $data['total_amount'] ?? 0,
'tax_amount' => $data['tax_amount'] ?? 0,
'grand_total' => $data['grand_total'] ?? 0,
]);
foreach ($data['items'] as $item) {
$order->items()->create([
'product_id' => $item['product_id'],
'batch_number' => $item['batch_number'] ?? null,
'quantity' => $item['quantity'],
'unit_price' => $item['unit_price'] ?? 0,
'subtotal' => $item['subtotal'] ?? ($item['quantity'] * ($item['unit_price'] ?? 0)),
'remark' => $item['remark'] ?? null,
]);
}
return $order;
});
}
public function updateShippingOrder(ShippingOrder $order, array $data)
{
return DB::transaction(function () use ($order, $data) {
$order->update([
'warehouse_id' => $data['warehouse_id'],
'customer_name' => $data['customer_name'] ?? null,
'shipping_date' => $data['shipping_date'],
'remarks' => $data['remarks'] ?? null,
'total_amount' => $data['total_amount'] ?? 0,
'tax_amount' => $data['tax_amount'] ?? 0,
'grand_total' => $data['grand_total'] ?? 0,
]);
// 簡單處理:刪除舊項目並新增
$order->items()->delete();
foreach ($data['items'] as $item) {
$order->items()->create([
'product_id' => $item['product_id'],
'batch_number' => $item['batch_number'] ?? null,
'quantity' => $item['quantity'],
'unit_price' => $item['unit_price'] ?? 0,
'subtotal' => $item['subtotal'] ?? ($item['quantity'] * ($item['unit_price'] ?? 0)),
'remark' => $item['remark'] ?? null,
]);
}
return $order;
});
}
public function post(ShippingOrder $order)
{
if ($order->status !== 'draft') {
throw new \Exception('該單據已過帳或已取消。');
}
return DB::transaction(function () use ($order) {
foreach ($order->items as $item) {
// 尋找對應的庫存紀錄
$inventory = $this->inventoryService->findInventoryByBatch(
$order->warehouse_id,
$item->product_id,
$item->batch_number
);
if (!$inventory || $inventory->quantity < $item->quantity) {
$productName = $this->inventoryService->getProduct($item->product_id)?->name ?? 'Unknown';
throw new \Exception("商品 [{$productName}] (批號: {$item->batch_number}) 庫存不足。");
}
// 扣除庫存
$this->inventoryService->decreaseInventoryQuantity(
$inventory->id,
$item->quantity,
"出貨扣款: 單號 [{$order->doc_no}]",
'ShippingOrder',
$order->id
);
}
$order->update([
'status' => 'completed',
'posted_by' => auth()->id(),
'posted_at' => now(),
]);
return $order;
});
}
}