1. 於 DispenseRecord、OrderItem 及 MachineStockMovement 模型之 product 關聯中加入 withTrashed(),確保被軟刪除商品的歷史快照仍可正常讀取。
2. 將 tab-dispense.blade.php、order-detail-panel.blade.php 及 SalesController 報表導出中的 product->name 統一修改為 product->localized_name ?? __('Unknown Product'),支援多語系切換與翻譯並替換 'Unknown' 為 '未知商品'。
3. 在銷售明細的商品圖片區塊整合 Alpine.js x-on:error 動態破圖防呆機制,一旦偵測到破圖或刪除實體圖,自動無縫退回精緻的 3D 箱子預設占位 SVG,消除破圖小圖標以維護全站極簡奢華風的視覺美感。
120 lines
2.9 KiB
PHP
120 lines
2.9 KiB
PHP
<?php
|
|
|
|
namespace App\Models\Machine;
|
|
|
|
use App\Traits\TenantScoped;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
|
use App\Models\Product\Product;
|
|
use App\Models\System\User;
|
|
|
|
class MachineStockMovement extends Model
|
|
{
|
|
use TenantScoped;
|
|
|
|
protected $fillable = [
|
|
'company_id',
|
|
'machine_id',
|
|
'product_id',
|
|
'slot_no',
|
|
'type',
|
|
'quantity',
|
|
'before_qty',
|
|
'after_qty',
|
|
'reference_type',
|
|
'reference_id',
|
|
'note',
|
|
'context',
|
|
'created_by',
|
|
];
|
|
protected $appends = [
|
|
'translated_note',
|
|
'translated_type',
|
|
];
|
|
|
|
public function getTranslatedNoteAttribute(): ?string
|
|
{
|
|
if (empty($this->note)) {
|
|
return null;
|
|
}
|
|
|
|
return __($this->note, $this->context ?? []);
|
|
}
|
|
|
|
/**
|
|
* 動態翻譯類型
|
|
*/
|
|
public function getTranslatedTypeAttribute(): string
|
|
{
|
|
return __("movement.type.{$this->type}");
|
|
}
|
|
|
|
protected $casts = [
|
|
'quantity' => 'integer',
|
|
'before_qty' => 'integer',
|
|
'after_qty' => 'integer',
|
|
'context' => 'array',
|
|
];
|
|
|
|
// ─── 異動類型常數 ───
|
|
|
|
const TYPE_REPLENISHMENT = 'replenishment'; // 補貨單完成
|
|
const TYPE_PICKUP = 'pickup'; // 取貨碼核銷
|
|
const TYPE_REMOTE_DISPENSE = 'remote_dispense'; // 遠端出貨 (B055 樂觀扣除)
|
|
const TYPE_SALE = 'sale'; // 一般訂單銷售
|
|
const TYPE_ADJUSTMENT = 'adjustment'; // B009 回報 / 後台手動修改
|
|
const TYPE_ROLLBACK = 'rollback'; // B055 出貨失敗回退
|
|
const TYPE_DECOMMISSION = 'decommission'; // B009 全量同步時移除不在清單的貨道
|
|
|
|
// ─── 關聯 ───
|
|
|
|
public function machine(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Machine::class);
|
|
}
|
|
|
|
public function product(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Product::class)->withTrashed();
|
|
}
|
|
|
|
public function creator(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class, 'created_by');
|
|
}
|
|
|
|
/**
|
|
* 多型關聯:補貨單、取貨碼操作記錄、遠端指令等
|
|
*/
|
|
public function reference(): MorphTo
|
|
{
|
|
return $this->morphTo();
|
|
}
|
|
|
|
// ─── 輔助方法 ───
|
|
|
|
/**
|
|
* 是否為增加庫存的類型
|
|
*/
|
|
public function isInbound(): bool
|
|
{
|
|
return in_array($this->type, [
|
|
self::TYPE_REPLENISHMENT,
|
|
self::TYPE_ROLLBACK,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 是否為減少庫存的類型
|
|
*/
|
|
public function isOutbound(): bool
|
|
{
|
|
return in_array($this->type, [
|
|
self::TYPE_PICKUP,
|
|
self::TYPE_REMOTE_DISPENSE,
|
|
self::TYPE_SALE,
|
|
]);
|
|
}
|
|
}
|