'decimal:2', 'discount_amount' => 'decimal:2', 'pay_amount' => 'decimal:2', 'change_amount' => 'decimal:2', 'original_amount' => 'decimal:2', 'payment_at' => 'datetime', 'machine_time' => 'datetime', 'metadata' => 'array', 'payment_type' => 'integer', 'delivery_status' => 'integer', ]; /** * 取得所有支付類型的對照標籤 */ public static function getPaymentTypeLabels(): array { return [ 1 => __('Credit Card'), 2 => __('E-Ticket (EasyCard/iPass)'), 3 => __('QR Code Payment - E.SUN'), // 掃碼支付-玉山 4 => __('Bill Acceptor'), 5 => __('Pass Code'), // 使用者要求由「通關密碼」改為「通行碼」 6 => __('Pickup Code'), 7 => __('Welcome Gift'), 8 => __('Questionnaire'), 9 => __('Coin Acceptor'), 10 => __('Mobile Pay'), // NFC 手機感應(行動支付,信用卡軌道,依使用者按鈕分類) 11 => __('QR Code Payment - TayPay'), // 掃碼支付-TayPay 21 => __('Offline + 1'), 22 => __('Offline + 2'), 23 => __('Offline + 3'), 24 => __('Offline + 4'), 25 => __('Offline + 9'), 30 => __('LINE Pay'), 31 => __('JKO Pay'), 32 => __('Easy Wallet'), 33 => __('Pi Pay'), 34 => __('PlusPay'), 40 => __('Member Verify Pickup'), 41 => __('Staff Card'), 42 => __('Pickup Voucher'), 50 => __('Offline + LINE Pay'), 51 => __('Offline + JKO Pay'), 52 => __('Offline + Easy Wallet'), 53 => __('Offline + Pi Pay'), 54 => __('Offline + PlusPay'), 60 => __('Points/Voucher'), 61 => __('Member + 1'), 62 => __('Member + 2'), 63 => __('Member + 3'), 64 => __('Member + 4'), 65 => __('Member + 5'), 66 => __('Member + 6'), 67 => __('Member + 7'), 68 => __('Member + 8'), 69 => __('Member + 9'), 70 => __('LINE Pay (Official)'), // LINE Pay 官方直連(非 TapPay 底下的 30) 90 => __('Member + LINE Pay'), 91 => __('Member + JKO Pay'), 92 => __('Member + Easy Wallet'), 93 => __('Member + Pi Pay'), 94 => __('Member + PlusPay'), ]; } /** * 取得目前的支付類型標籤 (Accessor) */ public function getPaymentTypeLabelAttribute(): string { return self::getPaymentTypeLabels()[$this->payment_type] ?? __('Unknown'); } public function getMaskedPickupRecipientAttribute(): ?string { if (empty($this->member_barcode)) { return null; } return self::maskPickupRecipientName($this->member_barcode); } public static function maskPickupRecipientName(string $value): string { $value = trim($value); if ($value === '') { return $value; } if (preg_match('/^([^\s((]+)(.*)$/us', $value, $matches) !== 1) { return self::maskName($value); } return self::maskName($matches[1]) . ($matches[2] ?? ''); } private static function maskName(string $name): string { $length = mb_strlen($name); if ($length <= 1) { return $name; } if ($length === 2) { return mb_substr($name, 0, 1) . 'O'; } return mb_substr($name, 0, 1) . str_repeat('O', $length - 2) . mb_substr($name, -1); } /** 一般銷售訂單 */ public function scopeSales($query) { return $query->where('order_type', self::TYPE_SALE); } /** 領藥單 */ public function scopePharmacyPickup($query) { return $query->where('order_type', self::TYPE_PHARMACY_PICKUP); } public function machine() { return $this->belongsTo(Machine::class); } /** 建單者 (領藥單藥師) */ public function creator() { return $this->belongsTo(\App\Models\System\User::class, 'created_by'); } public function member() { return $this->belongsTo(Member::class); } public function items() { return $this->hasMany(OrderItem::class); } public function invoice() { return $this->hasOne(Invoice::class); } public function dispenseRecords() { return $this->hasMany(DispenseRecord::class); } /** 領藥單對應的領藥碼(一單一碼) */ public function pickupCode() { return $this->hasOne(PickupCode::class); } public function staffCardLog() { return $this->hasOne(\App\Models\StaffCardLog::class); } public function welcomeGift() { return $this->belongsTo(WelcomeGift::class); } /** * 取得所有出貨狀態的對照標籤 */ public static function getDeliveryStatusLabels(): array { return [ self::DELIVERY_STATUS_FAILED => __('Dispense Failed'), self::DELIVERY_STATUS_SUCCESS => __('Dispense Success'), self::DELIVERY_STATUS_PARTIAL => __('Partial Dispense Success'), ]; } /** * 出貨狀態是否有意義:唯有付款成功(completed/paid)、機台真的動作過的單才有出貨結果。 * pending(未完成)、failed(支付失敗)、abandoned(未支付)從未出貨,出貨狀態應顯示 '--'。 * ⚠ delivery_status 欄位 DB 預設為 1(出貨成功),這些單若直接讀值會誤顯示成「出貨成功」。 */ public function hasDeliveryOutcome(): bool { return in_array($this->status, [self::STATUS_COMPLETED, 'paid'], true); } /** * 取得目前出貨狀態標籤 (Accessor) */ public function getDeliveryStatusLabelAttribute(): string { if (! $this->hasDeliveryOutcome()) { return '--'; } return self::getDeliveryStatusLabels()[$this->delivery_status] ?? __('Unknown'); } }