119 lines
4.3 KiB
PHP
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;
|
|
});
|
|
}
|
|
}
|