star-cloud/app/Models/Transaction/PickupCode.php
sky121113 0c29cdae97 [FEAT] 取貨碼改綁「商品」而非「貨道」
1. 新增 migration 為 pickup_codes 增加 product_id 欄位(nullable + index),既有綁貨道碼向後相容。
2. PickupCode Model 補上 product_id fillable 與 product() 關聯。
3. 產碼 storePickupCode 改收 product_id(與 slot_no 二擇一,required_without),並驗證商品屬於機台所屬公司;機台未上架仍可產碼。
4. 新增 pickupCompanyProducts AJAX 端點與路由,回傳公司商品清單與機台已上架 product_id,供前端標示「此機台未上架」提示。
5. B660 刷碼驗證新增綁商品擋關:機台無此商品貨道時回 409 並寫 PickupCodeLog;回傳資料補上 product_id 供 App 自挑貨道。
6. 產碼介面(pickup-codes/index)由「選擇貨道」改為「選擇商品」,加入未上架警告提示。
7. 多語系同步新增 4 組詞彙(zh_TW/en/ja 對齊排序)。
2026-06-26 17:31:22 +08:00

113 lines
2.5 KiB
PHP

<?php
namespace App\Models\Transaction;
use App\Models\Machine\Machine;
use App\Models\System\User;
use App\Traits\TenantScoped;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class PickupCode extends Model
{
use TenantScoped;
protected $fillable = [
'company_id',
'machine_id',
'product_id',
'slot_no',
'code',
'slug',
'status',
'expires_at',
'used_at',
'usage_limit',
'usage_count',
'created_by',
'order_id',
];
/**
* 獲取公開取貨連結
*/
public function getTicketUrlAttribute()
{
return $this->slug ? route('pickup.ticket', $this->slug) : route('pickup.ticket', $this->code);
}
/**
* Boot the model.
*/
protected static function booted()
{
static::creating(function ($pickupCode) {
$pickupCode->slug = \Illuminate\Support\Str::random(16);
});
}
protected $casts = [
'expires_at' => 'datetime',
'used_at' => 'datetime',
];
/**
* 關聯機台
*/
public function machine(): BelongsTo
{
return $this->belongsTo(Machine::class);
}
/**
* 關聯商品(取貨碼改綁商品時使用)
*/
public function product(): BelongsTo
{
return $this->belongsTo(\App\Models\Product\Product::class);
}
/**
* 關聯建立者
*/
public function creator(): BelongsTo
{
return $this->belongsTo(User::class, 'created_by');
}
/**
* 關聯訂單
*/
public function order(): BelongsTo
{
return $this->belongsTo(Order::class);
}
/**
* 判斷是否可用
*/
public function isValid(): bool
{
return $this->status === 'active'
&& ($this->usage_count < $this->usage_limit)
&& ($this->expires_at?->isFuture() ?? true); // null expires_at = 無到期限制
}
/**
* 產生唯一的取貨碼 (8位)
*/
public static function generateUniqueCode(int $machineId): string
{
do {
$code = str_pad(rand(0, 99999999), 8, '0', STR_PAD_LEFT);
$exists = self::where('machine_id', $machineId)
->where('code', $code)
->where('status', 'active')
->where('expires_at', '>', now())
->exists();
} while ($exists);
return $code;
}
}