diff --git a/.agents/skills/api-technical-specs/SKILL.md b/.agents/skills/api-technical-specs/SKILL.md index 1467c40..f49f9d1 100644 --- a/.agents/skills/api-technical-specs/SKILL.md +++ b/.agents/skills/api-technical-specs/SKILL.md @@ -414,7 +414,7 @@ description: 本技能規範定義了 Star Cloud 系統中所有機台 (IoT) 與 | 代碼 | 支付方式 | 備註 / 說明 | | :--- | :--- | :--- | | `1` | 信用卡 | 一般實體信用卡刷卡 | -| `2` | 電子票證 | 包含悠遊卡、一卡通等 | +| `2` | 電子票證 | 包含悠遊卡、一卡通、iCash 等(與信用卡、手機支付共用同一台實體刷卡機)| | `3` | 掃碼支付 | 一般掃碼支付 | | `4` | 投幣機支付 | 實體紙鈔機 | | `5` | 通行碼 | 現場維護人員測試使用 | @@ -431,8 +431,10 @@ description: 本技能規範定義了 Star Cloud 系統中所有機台 (IoT) 與 | `34` | TapPay - 全盈+PAY | | | `40` | 會員驗證取貨商品 | | | `41` | 員工卡 | RFID / NFC 刷卡 | +| `42` | 取物單 | | | `50` ~ `54` | 線下付款 + TapPay | `50`=線下+30, `51`=線下+31... `54`=線下+34 | | `70` | LINE Pay(官方直連) | LINE Pay 官方直連,非 TapPay 底下的 `30` | | `60` | 點數 / 優惠卷全額折抵 | 點數全額折抵出貨 或 優惠卷全額折抵出貨 | | `61` ~ `69` | 會員 + X | `61`=會員+1, `62`=會員+2... `69`=會員+9 | | `90` ~ `94` | 會員 + TapPay | `90`=會員+30, `91`=會員+31... `94`=會員+34 | +| `100` | 遠端出貨 | 後台遠端觸發出貨 | diff --git a/app/Http/Controllers/Admin/MachineController.php b/app/Http/Controllers/Admin/MachineController.php index 8d7b6a5..6ac1339 100644 --- a/app/Http/Controllers/Admin/MachineController.php +++ b/app/Http/Controllers/Admin/MachineController.php @@ -34,6 +34,21 @@ class MachineController extends AdminController $query->where('company_id', $companyId); } + // 刷卡機狀態:以彙總/相關子查詢預載,避免列表逐列 N+1 + $query->select('machines.*') + ->withCount([ + 'logs as card_terminal_error_count' => fn($q) => $q->where('type', 'card_terminal')->where('level', 'error')->where('is_resolved', false), + 'logs as card_terminal_warning_count' => fn($q) => $q->where('type', 'card_terminal')->where('level', 'warning')->where('is_resolved', false), + ]) + ->addSelect(['latest_card_terminal_log_at' => \App\Models\Machine\MachineLog::select('created_at') + ->whereColumn('machine_id', 'machines.id') + ->where('type', 'card_terminal') + ->whereIn('level', ['error', 'warning']) + ->where('is_resolved', false) + ->latest() + ->limit(1) + ]); + // 預加載統計資料 $machines = $query->orderBy("last_heartbeat_at", "desc") ->orderBy("id", "desc") diff --git a/app/Jobs/Transaction/ProcessTransactionFinalized.php b/app/Jobs/Transaction/ProcessTransactionFinalized.php index a9976ef..617758d 100644 --- a/app/Jobs/Transaction/ProcessTransactionFinalized.php +++ b/app/Jobs/Transaction/ProcessTransactionFinalized.php @@ -11,11 +11,16 @@ use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\Log; use App\Jobs\Machine\ProcessStateLog; +use App\Models\Transaction\Order; +use App\Services\Machine\MachineService; class ProcessTransactionFinalized implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + /** 走實體刷卡機(Nexsys)的支付類型:1 信用卡、2 電子票證、10 手機感應支付,共用同一台機器。 */ + private const CARD_TERMINAL_PAYMENT_TYPES = [1, 2, 10]; + protected $serialNo; protected $payload; @@ -59,7 +64,10 @@ class ProcessTransactionFinalized implements ShouldQueue ], 'transaction' ); - + + // 刷卡機健康狀態同步:成功消警 / 失敗寫 card_terminal 日誌 + $this->syncCardTerminalStatus($machine, $order); + Log::info("MQTT Transaction [finalize] processed successfully", [ 'serial_no' => $this->serialNo, 'order_no' => $order->order_no @@ -89,4 +97,45 @@ class ProcessTransactionFinalized implements ShouldQueue throw $e; } } + + /** + * 刷卡機 (信用卡/電子票證/手機支付,payment_type 1/2/10) 狀態同步。 + * 刷卡機沒有斷線心跳,所以靠交易結果維護燈號: + * - 成功交易 → 自動消除該機台先前未解決的刷卡機警告,恢復正常。 + * - 失敗交易(payment_response 帶 NFC 回應碼) → 寫一筆 type='card_terminal' 的 warning 日誌 + * (warning 級依 MachineLog 既有規則不會觸發 Discord)。 + */ + private function syncCardTerminalStatus(Machine $machine, Order $order): void + { + if (!in_array((int) $order->payment_type, self::CARD_TERMINAL_PAYMENT_TYPES, true)) { + return; + } + + // 刷卡成功 → 消警,恢復刷卡機燈號 + if ((int) $order->payment_status === Order::PAYMENT_STATUS_SUCCESS) { + $machine->logs() + ->where('type', 'card_terminal') + ->where('is_resolved', false) + ->update(['is_resolved' => true]); + return; + } + + // 刷卡失敗 → 解析 App 端格式 "[電文] | code=XXXX" 取回應碼 + if (!preg_match('/\|\s*code=([A-Za-z0-9_]+)/', (string) $order->payment_response, $m)) { + return; // 無刷卡機回應碼(例如顧客未感應就放棄),不視為硬體訊號問題 + } + $code = $m[1]; + if ($code === '0000') { + return; // 0000 為成功碼,理論上不會走到失敗分支,保險過濾 + } + + ProcessStateLog::dispatch( + $machine->id, + $machine->company_id, + 'Card payment failed', + 'warning', + ['card_code' => $code, 'order_no' => $order->order_no], + 'card_terminal' + ); + } } diff --git a/app/Models/Machine/Machine.php b/app/Models/Machine/Machine.php index ecaafd8..f446325 100644 --- a/app/Models/Machine/Machine.php +++ b/app/Models/Machine/Machine.php @@ -221,6 +221,52 @@ class Machine extends Model ->first()?->created_at; } + /** + * 刷卡機健康狀態 (基於 type = 'card_terminal' 未解決日誌)。 + * 信用卡/電子票證/手機支付共用同一台實體刷卡機,刷卡失敗會寫此類日誌, + * 下一次刷卡成功時由 finalize 自動消警恢復正常。 + * 列表頁優先使用 MachineController 預載的彙總欄位 (避免 N+1),其餘情境退回即時查詢。 + */ + public function getCardTerminalStatusAttribute(): string + { + if (array_key_exists('card_terminal_error_count', $this->attributes) + || array_key_exists('card_terminal_warning_count', $this->attributes)) { + if (($this->attributes['card_terminal_error_count'] ?? 0) > 0) { + return 'error'; + } + if (($this->attributes['card_terminal_warning_count'] ?? 0) > 0) { + return 'warning'; + } + return 'normal'; + } + + if ($this->logs()->where('type', 'card_terminal')->where('level', 'error')->where('is_resolved', false)->exists()) { + return 'error'; + } + if ($this->logs()->where('type', 'card_terminal')->where('level', 'warning')->where('is_resolved', false)->exists()) { + return 'warning'; + } + return 'normal'; + } + + /** + * 取得最新一筆未解決的刷卡機日誌時間 (列表頁優先用預載 subquery 欄位,避免 N+1)。 + */ + public function getLatestCardTerminalLogTimeAttribute() + { + if (array_key_exists('latest_card_terminal_log_at', $this->attributes)) { + $value = $this->attributes['latest_card_terminal_log_at']; + return $value ? \Illuminate\Support\Carbon::parse($value) : null; + } + + return $this->logs() + ->where('type', 'card_terminal') + ->whereIn('level', ['error', 'warning']) + ->where('is_resolved', false) + ->latest() + ->first()?->created_at; + } + /** * Scope: 判定在線 (讀取 status 欄位) */ diff --git a/app/Models/Machine/MachineLog.php b/app/Models/Machine/MachineLog.php index 231dd52..3a64125 100644 --- a/app/Models/Machine/MachineLog.php +++ b/app/Models/Machine/MachineLog.php @@ -99,6 +99,13 @@ class MachineLog extends Model { $context = $this->context; + // 刷卡機回應碼:用目前代碼表重組失敗原因,支援多語系顯示。 + if (isset($context['card_code'])) { + $code = $context['card_code']; + $reason = \App\Services\Machine\MachineService::CARD_TERMINAL_CODE_MAP[$code] ?? 'Transaction failed'; + return __('Card payment failed') . ':' . __($reason) . " (Code: {$code})"; + } + // B013 封裝:優先用目前代碼表重組,讓舊日誌也能吃到最新文案。 if (isset($context['translated_label'])) { $code = $context['raw_code'] ?? $context['error_code'] ?? '0000'; diff --git a/app/Services/Machine/MachineService.php b/app/Services/Machine/MachineService.php index dbb084d..7964815 100644 --- a/app/Services/Machine/MachineService.php +++ b/app/Services/Machine/MachineService.php @@ -149,6 +149,37 @@ class MachineService */ public const DISPENSE_SUCCESS_CODES = ['0402', '0424']; + /** + * 刷卡機 (Nexsys 終端機 / NCCC 標準) 交易回應碼對照表。 + * 來源:聯合信用卡處理中心終端機回應碼規格。 + * 用於把 order.payment_response 內的 "| code=XXXX" 解析成可讀(可多語)的失敗原因, + * 寫入 type='card_terminal' 機台日誌。信用卡(1)/電子票證(2)/手機支付(10) 共用同一台實體刷卡機。 + * 值為英文翻譯鍵,實際顯示由 lang/*.json 多語系翻譯。 + */ + public const CARD_TERMINAL_CODE_MAP = [ + '0000' => 'Transaction approved', + '0001' => 'Transaction failed (issuer/card declined)', + '0002' => 'Please contact bank / e-wallet provider', + '0003' => 'Transaction timeout', + '0004' => 'Operation error', + '0005' => 'Communication failure', + '0006' => 'User terminated transaction', + '0009' => 'Non-participating institution card', + '0010' => 'Message format error', + '0011' => 'Not a co-branded card', + '0012' => 'Stored-value amount over limit', + '0013' => 'Card locked', + '0014' => 'Cannot match original stored-value transaction', + '0015' => 'Card auto-load not enabled', + '0016' => 'Insufficient stored-value / e-wallet balance', + '0017' => 'Multiple cards detected', + '0018' => 'Please re-tap card / re-scan / retry', + '0019' => 'Auto-load succeeded but purchase failed', + '1001' => 'Credit card and stored-value settlement both failed', + '1002' => 'Credit card settled, stored-value settlement failed', + '1003' => 'Credit card settlement failed, stored-value settled', + ]; + /** * Update machine heartbeat and status. * diff --git a/config/api-docs.php b/config/api-docs.php index f1e4418..4cafd83 100644 --- a/config/api-docs.php +++ b/config/api-docs.php @@ -857,7 +857,7 @@ return [ 'order.original_amount' => ['type' => 'numeric', 'description' => '(選填) 原始標價金額', 'required' => false], 'order.discount_amount' => ['type' => 'numeric', 'description' => '(選填) 折扣金額,預設 0', 'required' => false], 'order.points_used' => ['type' => 'integer', 'description' => '(選填) 使用點數,預設 0', 'required' => false], - 'order.payment_type' => ['type' => 'integer', 'description' => "(必填) 支付類型代碼:\n1:信用卡, 2:悠遊卡/一卡通, 3:掃碼支付, 4:紙鈔機, 5:通行碼, 6:取貨碼, 7:來店禮, 8:問卷, 9:零錢, 10:手機支付(行動支付/NFC手機), 41:員工卡, 42:取物單。\n21~25:線下付款+X (21:線下+1, 22:線下+2, 23:線下+3, 24:線下+4, 25:線下+9)。\n30:LINE Pay, 31:街口, 32:悠遊付, 33:Pi, 34:全盈+。\n70:LINE Pay(官方直連,非 TapPay 底下的 30)。\n40:會員驗證取貨商品。\n50~54:線下付款+TapPay (50:線下+30, 51:線下+31, 52:線下+32, 53:線下+33, 54:線下+34)。\n60:點數/優惠卷全額折抵。61~69:會員+X (61:會員+1...69:會員+9)。\n90~94:會員+TapPay (90:會員+30...94:會員+34)。\n100:遠端出貨。"], + 'order.payment_type' => ['type' => 'integer', 'description' => "(必填) 支付類型代碼:\n1:信用卡, 2:電子票證(悠遊卡/一卡通/iCash 等), 3:掃碼支付, 4:紙鈔機, 5:通行碼, 6:取貨碼, 7:來店禮, 8:問卷, 9:零錢(硬幣), 10:手機支付(行動支付/NFC 手機感應), 41:員工卡, 42:取物單。\n※ 1(信用卡)、2(電子票證)、10(手機支付) 走同一台實體刷卡機(Nexsys 終端機)。\n21~25:線下付款+基本類型 (21:線下+1 信用卡, 22:線下+2 電子票證, 23:線下+3 掃碼, 24:線下+4 紙鈔, 25:線下+9 零錢)。\n30:LINE Pay(TapPay), 31:街口, 32:悠遊付, 33:Pi 拍錢包, 34:全盈+PAY。\n70:LINE Pay(官方直連,非 TapPay 底下的 30)。\n40:會員驗證取貨商品。\n50~54:線下付款+TapPay (50:線下+30, 51:線下+31, 52:線下+32, 53:線下+33, 54:線下+34)。\n60:點數/優惠券全額折抵。61~69:會員+基本類型 (61:會員+1...69:會員+9)。\n90~94:會員+TapPay (90:會員+30...94:會員+34)。\n100:遠端出貨。"], 'order.payment_status' => ['type' => 'integer', 'description' => '(必填) 支付狀態 (1:成功)'], 'order.code_id' => ['type' => 'string', 'description' => '(選填) 閉環勾稽用的代碼 ID (payment_type 為 5, 6, 41 時必填)', 'required' => false], 'order.payment_request' => ['type' => 'string', 'description' => '(選填) 金流請求原始字串', 'required' => false], diff --git a/database/migrations/2026_06_15_000000_change_products_spec_to_text.php b/database/migrations/2026_06_15_000000_change_products_spec_to_text.php index e992e88..2b98167 100644 --- a/database/migrations/2026_06_15_000000_change_products_spec_to_text.php +++ b/database/migrations/2026_06_15_000000_change_products_spec_to_text.php @@ -12,11 +12,16 @@ return new class extends Migration */ public function up(): void { - DB::statement('ALTER TABLE products MODIFY spec TEXT NULL COMMENT \'詳情\''); + // sqlite 為動態型別,VARCHAR/TEXT 等價且不支援 MODIFY 語法,僅在 MySQL 執行。 + if (DB::getDriverName() !== 'sqlite') { + DB::statement('ALTER TABLE products MODIFY spec TEXT NULL COMMENT \'詳情\''); + } } public function down(): void { - DB::statement('ALTER TABLE products MODIFY spec VARCHAR(255) NULL COMMENT \'規格\''); + if (DB::getDriverName() !== 'sqlite') { + DB::statement('ALTER TABLE products MODIFY spec VARCHAR(255) NULL COMMENT \'規格\''); + } } }; diff --git a/lang/en.json b/lang/en.json index 6054d97..bb6fac5 100644 --- a/lang/en.json +++ b/lang/en.json @@ -214,6 +214,7 @@ "Authorized Status": "Authorized Status", "Auto Refresh": "Auto Refresh", "Auto Replenishment": "Auto Replenishment", + "Auto-load succeeded but purchase failed": "Auto-load succeeded but purchase failed", "Automatically calculate replenishment needs based on machine capacity": "Automatically calculate replenishment needs based on machine capacity", "Availability": "Availability", "Available Machines": "Available Machines", @@ -274,6 +275,7 @@ "Cannot delete model that is currently in use by machines.": "Cannot delete model that is currently in use by machines.", "Cannot delete role with active users.": "Cannot delete role with active users.", "Cannot delete warehouse with existing stock": "Cannot delete warehouse with existing stock", + "Cannot match original stored-value transaction": "Cannot match original stored-value transaction", "Card Machine System": "Card Machine System", "Card Payment": "Card Payment", "Card Reader": "Card Reader", @@ -284,8 +286,13 @@ "Card Side Background": "Card Side Background", "Card System": "Card System", "Card Terminal": "Card Terminal", + "Card Terminal Logs": "Card Terminal Logs", + "Card Terminal Status": "Card Terminal Status", "Card Terminal System": "Card Terminal System", "Card UID": "Card UID", + "Card auto-load not enabled": "Card auto-load not enabled", + "Card locked": "Card locked", + "Card payment failed": "Card payment failed", "Cash Module": "Cash Module", "Cash Module Feature": "Cash Module Feature", "Cash Module Function": "Cash Module Function", @@ -342,6 +349,7 @@ "Command has been queued successfully.": "Command has been queued successfully.", "Command not found": "Command not found", "Command queued successfully.": "Command queued successfully.", + "Communication failure": "Communication failure", "Company": "Company", "Company Code": "Company Code", "Company Discord notification settings updated successfully.": "Company Discord notification settings updated successfully.", @@ -440,6 +448,9 @@ "Credit Card": "Credit Card", "Credit Card / Contactless": "Credit Card / Contactless", "Credit Card Payment": "Credit Card Payment", + "Credit card and stored-value settlement both failed": "Credit card and stored-value settlement both failed", + "Credit card settled, stored-value settlement failed": "Credit card settled, stored-value settlement failed", + "Credit card settlement failed, stored-value settled": "Credit card settlement failed, stored-value settled", "Critical": "Critical", "Critical failures requiring immediate hands-on attention.": "Critical failures requiring immediate hands-on attention.", "Cross-Company / Headquarter Global Stats": "Cross-Company / Headquarter Global Stats", @@ -941,6 +952,7 @@ "Installation": "Installation", "Installation Location": "Installation Location", "Insufficient stock for transfer": "Insufficient stock for transfer", + "Insufficient stored-value / e-wallet balance": "Insufficient stored-value / e-wallet balance", "Invalid personnel selection": "Invalid personnel selection", "Invalid status transition": "Invalid status transition", "Inventory": "Inventory", @@ -1202,6 +1214,7 @@ "Message": "Message", "Message Content": "Message Content", "Message Display": "Message Display", + "Message format error": "Message format error", "Microwave delivery door close error": "Microwave delivery door close error", "Microwave delivery door close error (0211)": "Microwave delivery door close error (0211)", "Microwave delivery door closing": "Microwave delivery door closing", @@ -1245,6 +1258,7 @@ "Movement History": "Movement History", "Movement Logs": "Movement Logs", "Multilingual Names": "Multilingual Names", + "Multiple cards detected": "Multiple cards detected", "Must be strictly greater than previous version": "Must be strictly greater than previous version", "N/A": "N/A", "Name": "Name", @@ -1344,11 +1358,13 @@ "No versions found": "No versions found", "No warehouses found": "No warehouses found", "No welcome gifts found": "No welcome gifts found", + "Non-participating institution card": "Non-participating institution card", "None": "None", "Normal": "Normal", "Not Configured": "Not Configured", "Not Used": "Not Used", "Not Used Description": "Not Used Description", + "Not a co-branded card": "Not a co-branded card", "Note": "Note", "Note (optional)": "Note (optional)", "Notes": "Notes", @@ -1403,6 +1419,7 @@ "Operation Logs": "Operation Logs", "Operation Note": "Operation Note", "Operation Records": "Operation Records", + "Operation error": "Operation error", "Operation failed": "Operation failed", "Operational Parameters": "Operational Parameters", "Operations": "Operations", @@ -1548,6 +1565,7 @@ "Please check the following errors:": "Please check the following errors:", "Please check the form for errors.": "Please check the form for errors.", "Please confirm the details below": "Please confirm the details below", + "Please contact bank / e-wallet provider": "Please contact bank / e-wallet provider", "Please enter Webhook URL first.": "Please enter Webhook URL first.", "Please enter a valid ECPay e-invoice notification email.": "Please enter a valid ECPay e-invoice notification email.", "Please enter address first": "Please enter address first", @@ -1556,6 +1574,7 @@ "Please enter version name": "Please enter version name", "Please make sure to enable \"Background graphics\" in your browser print settings to print product images and styled components correctly.": "Please make sure to enable \"Background graphics\" in your browser print settings to print product images and styled components correctly.", "Please provide a download URL": "Please provide a download URL", + "Please re-tap card / re-scan / retry": "Please re-tap card / re-scan / retry", "Please remove bento from microwave": "Please remove bento from microwave", "Please select a company": "Please select a company", "Please select a company.": "Please select a company.", @@ -2017,6 +2036,7 @@ "Store ID": "Store ID", "Store Management": "Store Management", "StoreID": "StoreID", + "Stored-value amount over limit": "Stored-value amount over limit", "Sub / Card / Scan": "Sub / Card / Scan", "Sub Account Management": "Sub Account Management", "Sub Account Roles": "Sub Account Roles", @@ -2168,7 +2188,11 @@ "Transaction Info": "Transaction Info", "Transaction Orders": "Transaction Orders", "Transaction Time": "Transaction Time", + "Transaction approved": "Transaction approved", + "Transaction failed": "Transaction failed", + "Transaction failed (issuer/card declined)": "Transaction failed (issuer/card declined)", "Transaction processed: :id": "Transaction processed: :id", + "Transaction timeout": "Transaction timeout", "Transfer Audit": "Transfer Audit", "Transfer Details": "Transfer Details", "Transfer In": "Transfer In", @@ -2258,6 +2282,7 @@ "User": "User", "User Info": "User Info", "User logged in: :name": "User logged in: :name", + "User terminated transaction": "User terminated transaction", "Username": "Username", "Users": "Users", "Utilization Rate": "Utilization Rate", diff --git a/lang/ja.json b/lang/ja.json index d08fba3..1700291 100644 --- a/lang/ja.json +++ b/lang/ja.json @@ -214,6 +214,7 @@ "Authorized Status": "承認ステータス", "Auto Refresh": "自動更新", "Auto Replenishment": "一括補充", + "Auto-load succeeded but purchase failed": "オートチャージ成功、但し購買取引失敗", "Automatically calculate replenishment needs based on machine capacity": "機器容量に基づいて補充必要量を自動計算", "Availability": "可用性 (Availability)", "Available Machines": "割り当て可能な機器", @@ -274,6 +275,7 @@ "Cannot delete model that is currently in use by machines.": "機器で使用中のモデルは削除できません。", "Cannot delete role with active users.": "ユーザーが紐付けられているロールは削除できません。", "Cannot delete warehouse with existing stock": "在庫がある倉庫は削除できません", + "Cannot match original stored-value transaction": "元の電子マネー取引と照合できません", "Card Machine System": "カードリーダーシステム", "Card Payment": "カード決済", "Card Reader": "カードリーダー", @@ -284,8 +286,13 @@ "Card Side Background": "カード側背景画像", "Card System": "カードシステム", "Card Terminal": "カード端末", + "Card Terminal Logs": "カード端末ログ", + "Card Terminal Status": "カード端末ステータス", "Card Terminal System": "カードリーダーシステム", "Card UID": "カードUID", + "Card auto-load not enabled": "カードのオートチャージが未設定です", + "Card locked": "カードがロックされています", + "Card payment failed": "カード決済失敗", "Cash Module": "現金モジュール", "Cash Module Feature": "現金モジュール機能", "Cash Module Function": "現金モジュール機能", @@ -342,6 +349,7 @@ "Command has been queued successfully.": "コマンドがキューに追加されました。", "Command not found": "コマンドが見つかりません", "Command queued successfully.": "コマンドが正常にキューされました。", + "Communication failure": "通信エラー", "Company": "顧客企業", "Company Code": "会社コード", "Company Discord notification settings updated successfully.": "会社の Discord 通知設定が正常に更新されました。", @@ -440,6 +448,9 @@ "Credit Card": "クレジットカード", "Credit Card / Contactless": "クレジットカード/非接触決済対応", "Credit Card Payment": "クレジットカード決済", + "Credit card and stored-value settlement both failed": "クレジットカード・電子マネーともに精算失敗", + "Credit card settled, stored-value settlement failed": "クレジットカード精算成功、電子マネー精算失敗", + "Credit card settlement failed, stored-value settled": "クレジットカード精算失敗、電子マネー精算成功", "Critical": "深刻", "Critical failures requiring immediate hands-on attention.": "即座に対処が必要な重大な障害。", "Cross-Company / Headquarter Global Stats": "複数会社間 / 本部グローバル統計", @@ -941,6 +952,7 @@ "Installation": "設置", "Installation Location": "設置場所", "Insufficient stock for transfer": "在庫不足のため移動できません", + "Insufficient stored-value / e-wallet balance": "電子マネー/電子ウォレット残高不足", "Invalid personnel selection": "無効な担当者選択", "Invalid status transition": "無効なステータス遷移", "Inventory": "在庫概要", @@ -1202,6 +1214,7 @@ "Message": "メッセージ", "Message Content": "メッセージ内容", "Message Display": "メッセージ表示", + "Message format error": "電文/フォーマットエラー", "Microwave delivery door close error": "電子レンジ搬入口扉閉鎖エラー", "Microwave delivery door close error (0211)": "電子レンジ搬入口扉閉エラー (0211)", "Microwave delivery door closing": "電子レンジ搬入口扉閉鎖中", @@ -1245,6 +1258,7 @@ "Movement History": "変動履歴", "Movement Logs": "変動ログ", "Multilingual Names": "多言語名", + "Multiple cards detected": "複数カードの読み取り失敗", "Must be strictly greater than previous version": "Must be strictly greater than previous version", "N/A": "なし", "Name": "名前", @@ -1344,11 +1358,13 @@ "No versions found": "No versions found", "No warehouses found": "倉庫が見つかりません", "No welcome gifts found": "ウェルカムギフトが見つかりません", + "Non-participating institution card": "非参加機関のカード", "None": "なし", "Normal": "正常", "Not Configured": "未設定", "Not Used": "使用しない", "Not Used Description": "サードパーティ決済を使用しない", + "Not a co-branded card": "提携カードではありません", "Note": "備考", "Note (optional)": "備考 (任意)", "Notes": "備考", @@ -1403,6 +1419,7 @@ "Operation Logs": "Operation Logs", "Operation Note": "操作メモ", "Operation Records": "操作記録", + "Operation error": "操作エラー", "Operation failed": "操作失敗", "Operational Parameters": "運用パラメータ", "Operations": "運用設定", @@ -1548,6 +1565,7 @@ "Please check the following errors:": "以下のエラーを確認してください:", "Please check the form for errors.": "フォームのエラーを確認してください。", "Please confirm the details below": "以下の詳細を確認してください", + "Please contact bank / e-wallet provider": "銀行/電子マネー事業者へお問い合わせください", "Please enter Webhook URL first.": "最初にWebhook URLを入力してください。", "Please enter a valid ECPay e-invoice notification email.": "有効な ECPay 電子インボイス通知用メールアドレスを入力してください。", "Please enter address first": "先に住所を入力してください", @@ -1556,6 +1574,7 @@ "Please enter version name": "Please enter version name", "Please make sure to enable \"Background graphics\" in your browser print settings to print product images and styled components correctly.": "商品の画像やスタイル付きコンポーネントを正しく印刷するために、ブラウザの印刷設定で『背景のグラフィック』を有効にしてください。", "Please provide a download URL": "Please provide a download URL", + "Please re-tap card / re-scan / retry": "カードを再タッチ/再スキャン/再試行してください", "Please remove bento from microwave": "電子レンジ内の弁当を取り出してください", "Please select a company": "会社を選択してください", "Please select a company.": "会社を選択してください。", @@ -2017,6 +2036,7 @@ "Store ID": "店舗ID (Store ID)", "Store Management": "店舗管理", "StoreID": "店舗ID", + "Stored-value amount over limit": "電子マネー金額が上限超過", "Sub / Card / Scan": "下位機 / カードリーダー / スキャナー", "Sub Account Management": "サブアカウント管理", "Sub Account Roles": "サブアカウントロール", @@ -2168,7 +2188,11 @@ "Transaction Info": "取引情報", "Transaction Orders": "取引注文", "Transaction Time": "取引時間", + "Transaction approved": "取引成功", + "Transaction failed": "取引失敗", + "Transaction failed (issuer/card declined)": "取引失敗(ホストまたはカード拒否)", "Transaction processed: :id": "取引処理完了: :id", + "Transaction timeout": "取引タイムアウト", "Transfer Audit": "移動伝票監査", "Transfer Details": "移動伝票詳細", "Transfer In": "転入", @@ -2258,6 +2282,7 @@ "User": "一般ユーザー", "User Info": "ユーザー情報", "User logged in: :name": "ユーザーがログインしました: :name", + "User terminated transaction": "ユーザーが取引を中止しました", "Username": "ユーザー名", "Users": "アカウント数", "Utilization Rate": "機器稼働率", diff --git a/lang/zh_TW.json b/lang/zh_TW.json index 499c900..1b10223 100644 --- a/lang/zh_TW.json +++ b/lang/zh_TW.json @@ -214,6 +214,7 @@ "Authorized Status": "已授權", "Auto Refresh": "自動更新", "Auto Replenishment": "自動補貨單", + "Auto-load succeeded but purchase failed": "自動加值成功,但購貨交易失敗", "Automatically calculate replenishment needs based on machine capacity": "根據機台容量自動計算補貨需求", "Availability": "可用性 (Availability)", "Available Machines": "可供分配的機台", @@ -274,6 +275,7 @@ "Cannot delete model that is currently in use by machines.": "無法刪除目前正在被機台使用的型號。", "Cannot delete role with active users.": "無法刪除已有綁定帳號的角色。", "Cannot delete warehouse with existing stock": "無法刪除仍有庫存的倉庫", + "Cannot match original stored-value transaction": "無法比對原始電票交易", "Card Machine System": "刷卡機系統", "Card Payment": "卡片支付", "Card Reader": "刷卡機", @@ -284,8 +286,13 @@ "Card Side Background": "左側卡片背景圖", "Card System": "刷卡機系統", "Card Terminal": "刷卡機端", + "Card Terminal Logs": "刷卡機日誌", + "Card Terminal Status": "刷卡機狀態", "Card Terminal System": "刷卡機系統", "Card UID": "卡片 UID", + "Card auto-load not enabled": "票卡未開啟自動加值", + "Card locked": "票卡已鎖", + "Card payment failed": "刷卡失敗", "Cash Module": "現金模組", "Cash Module Feature": "現金模組功能", "Cash Module Function": "現金模組功能", @@ -342,6 +349,7 @@ "Command has been queued successfully.": "指令已成功排入佇列。", "Command not found": "找不到指令", "Command queued successfully.": "指令已加入佇列。", + "Communication failure": "通訊失敗", "Company": "客戶公司", "Company Code": "公司代碼", "Company Discord notification settings updated successfully.": "公司 Discord 通知設定已成功更新。", @@ -440,6 +448,9 @@ "Credit Card": "信用卡", "Credit Card / Contactless": "支援信用卡 / 感應支付", "Credit Card Payment": "信用卡支付", + "Credit card and stored-value settlement both failed": "信用卡及電票皆結帳失敗", + "Credit card settled, stored-value settlement failed": "信用卡結帳成功,電票結帳失敗", + "Credit card settlement failed, stored-value settled": "信用卡結帳失敗,電票結帳成功", "Critical": "嚴重", "Critical failures requiring immediate hands-on attention.": "需要立即處理的關鍵故障。", "Cross-Company / Headquarter Global Stats": "跨公司 / 總部全域統計", @@ -941,6 +952,7 @@ "Installation": "裝機", "Installation Location": "安裝位置", "Insufficient stock for transfer": "庫存不足,無法調撥", + "Insufficient stored-value / e-wallet balance": "電票/電子錢包餘額不足", "Invalid personnel selection": "無效的人員選擇", "Invalid status transition": "無效的狀態轉換", "Inventory": "庫存概覽", @@ -1202,6 +1214,7 @@ "Message": "訊息", "Message Content": "日誌內容", "Message Display": "訊息顯示", + "Message format error": "電文/格式錯誤", "Microwave delivery door close error": "微波爐進貨口門關閉錯誤", "Microwave delivery door close error (0211)": "微波爐進貨口門關閉錯誤", "Microwave delivery door closing": "正在關閉微波爐進貨口門", @@ -1245,6 +1258,7 @@ "Movement History": "異動紀錄", "Movement Logs": "異動紀錄", "Multilingual Names": "多語系名稱", + "Multiple cards detected": "多張票卡讀取失敗", "Must be strictly greater than previous version": "必須嚴格大於上一個版本代碼", "N/A": "不適用", "Name": "名稱", @@ -1344,11 +1358,13 @@ "No versions found": "未找到任何版本", "No warehouses found": "未找到倉庫", "No welcome gifts found": "找不到來店禮資料", + "Non-participating institution card": "非參加機構卡片", "None": "無", "Normal": "正常", "Not Configured": "尚未設定", "Not Used": "不使用", "Not Used Description": "不使用第三方支付介接", + "Not a co-branded card": "非聯名卡", "Note": "備註", "Note (optional)": "備註 (選填)", "Notes": "備註", @@ -1403,6 +1419,7 @@ "Operation Logs": "操作紀錄", "Operation Note": "操作備註", "Operation Records": "操作紀錄", + "Operation error": "操作錯誤", "Operation failed": "操作失敗", "Operational Parameters": "運作參數", "Operations": "運作設定", @@ -1548,6 +1565,7 @@ "Please check the following errors:": "請檢查以下錯誤:", "Please check the form for errors.": "請檢查欄位內容是否正確。", "Please confirm the details below": "請確認以下詳細資訊", + "Please contact bank / e-wallet provider": "請連絡銀行/電子錢包業者", "Please enter Webhook URL first.": "請先輸入 Webhook 網址。", "Please enter a valid ECPay e-invoice notification email.": "請輸入有效的綠界電子發票通知 Email。", "Please enter address first": "請先輸入地址", @@ -1556,6 +1574,7 @@ "Please enter version name": "請輸入版本名稱", "Please make sure to enable \"Background graphics\" in your browser print settings to print product images and styled components correctly.": "請確保在瀏覽器列印設定中啟用「背景圖形」,以便正確列印商品圖片和樣式元件。", "Please provide a download URL": "請提供下載連結", + "Please re-tap card / re-scan / retry": "請重新感應卡片/重新掃碼/重試交易", "Please remove bento from microwave": "請取出微波爐內盒飯", "Please select a company": "請選擇公司", "Please select a company.": "請選擇公司", @@ -2017,6 +2036,7 @@ "Store ID": "商店代號", "Store Management": "店家管理", "StoreID": "商店代號 (StoreID)", + "Stored-value amount over limit": "電票金額超過上限", "Sub / Card / Scan": "下位機 / 刷卡機 / 掃碼機", "Sub Account Management": "子帳號管理", "Sub Account Roles": "子帳號角色", @@ -2168,7 +2188,11 @@ "Transaction Info": "交易資訊", "Transaction Orders": "交易訂單", "Transaction Time": "交易時間", + "Transaction approved": "交易成功", + "Transaction failed": "交易失敗", + "Transaction failed (issuer/card declined)": "交易失敗(主機或卡片拒絕)", "Transaction processed: :id": "交易處理完成::id", + "Transaction timeout": "交易逾時", "Transfer Audit": "調撥單", "Transfer Details": "調撥單詳情", "Transfer In": "轉入", @@ -2258,6 +2282,7 @@ "User": "一般用戶", "User Info": "用戶資訊", "User logged in: :name": "使用者登入::name", + "User terminated transaction": "使用者終止交易", "Username": "使用者帳號", "Users": "帳號數", "Utilization Rate": "機台稼動率", diff --git a/resources/views/admin/machines/index.blade.php b/resources/views/admin/machines/index.blade.php index b35bd0c..e8a071a 100644 --- a/resources/views/admin/machines/index.blade.php +++ b/resources/views/admin/machines/index.blade.php @@ -641,17 +641,18 @@