From 9114269a7a2396a5fc65b6fcbed7a1ef2d4ec0e6 Mon Sep 17 00:00:00 2001 From: sky121113 Date: Wed, 22 Apr 2026 14:59:28 +0800 Subject: [PATCH] =?UTF-8?q?[FEAT]=20=E5=AE=8C=E5=96=84=E9=81=A0=E7=AB=AF?= =?UTF-8?q?=E5=87=BA=E8=B2=A8=E8=88=87=E5=BA=AB=E5=AD=98=E7=95=B0=E5=8B=95?= =?UTF-8?q?=E7=9A=84=E4=BD=B5=E7=99=BC=E6=8E=A7=E5=88=B6=E8=88=87=E8=A6=96?= =?UTF-8?q?=E8=A6=BA=E5=9B=9E=E9=A5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 修正 RemoteController 中的 MachineService 注入問題,解決遠端出貨指令失效的 500 錯誤。 2. 在 MachineService 實作貨道鎖定機制 (lockSlot/unlockSlot),防止重複扣庫存導致的數據不一致。 3. 採用樂觀扣除模式,發送指令時即更新預扣庫存,並在 ProcessCommandAck 實作失敗自動 Rollback。 4. 優化 UI 互動:在操作紀錄詳情顯示庫存變化 (如 6 -> 5),且針對執行失敗的指令加上刪除線樣式。 5. 完成指令詳情、操作紀錄與庫存歷史的語系對照表同步 (zh_TW, en, ja)。 --- .agents/skills/api-technical-specs/SKILL.md | 28 +- .../skills/mqtt-communication-specs/SKILL.md | 14 +- .../Controllers/Admin/MachineController.php | 38 +- .../Controllers/Admin/RemoteController.php | 75 +- app/Jobs/Machine/ProcessCommandAck.php | 44 +- app/Services/Machine/MachineService.php | 125 +- lang/en.json | 20 +- lang/ja.json | 1180 +---------------- lang/zh_TW.json | 19 +- resources/views/admin/remote/index.blade.php | 34 +- .../partials/tab-history-index.blade.php | 3 +- .../remote/partials/tab-history.blade.php | 5 +- resources/views/admin/remote/stock.blade.php | 33 +- 13 files changed, 290 insertions(+), 1328 deletions(-) diff --git a/.agents/skills/api-technical-specs/SKILL.md b/.agents/skills/api-technical-specs/SKILL.md index 1368235..90dc0b0 100644 --- a/.agents/skills/api-technical-specs/SKILL.md +++ b/.agents/skills/api-technical-specs/SKILL.md @@ -21,7 +21,7 @@ description: 本技能規範定義了 Star Cloud 系統中所有機台 (IoT) 與 - **Header**:`Authorization: Bearer `。 ### 2.2 機台通訊認證 (Machine Authentication) -- **適用 API**:B012, B013, B600 等後續通訊。 +- **適用 API**:B012, B009 等後續通訊。 - **方式**:使用機台專屬之 **api_token**。 - **Header**:`Authorization: Bearer `。 @@ -80,18 +80,14 @@ description: 本技能規範定義了 Star Cloud 系統中所有機台 (IoT) 與 ### 3.3 B009: 貨道庫存即時回報 (Supplementary Report) 當維修或補貨人員在機台端完成操作後,將目前的貨道實體狀態同步回雲端。 -#### B009 權限驗證邏輯 (RBAC Compliance) -系統會依據 account 欄位進行三層式權限核查: -1. **系統層 (System Admin)**:當 company_id 為 null 時,具備全局管理權限,直接放行。 -2. **公司層 (Company Admin)**:當 is_admin 為 true 時,檢查機台的 company_id 是否與該帳號一致。 -3. **人員層 (Operator/User)**:當帳號僅為一般人員時,檢查 machine_user 授權表,確認該帳號有被分配至此機台。 + - **URL**: PUT /api/v1/app/products/supplementary/B009 -- **Request Body:** +- **Authentication**: Bearer Token (Header) +- **Request Body:** 無 (由 Token 自動識別機台) | 參數 | 類型 | 必填 | 說明 | 範例 | | :--- | :--- | :--- | :--- | :--- | -| account | String | 是 | 操作人員帳號 | 0999123456 | | data | Array | 是 | 貨道數據陣列 | [{"tid":"1", "t060v00":"1", "num":"10"}] | - **data 陣列內部欄位:** @@ -152,24 +148,12 @@ description: 本技能規範定義了 Star Cloud 系統中所有機台 (IoT) 與 ### 3.6 B013: [DEPRECATED / REMOVED] 機台故障與異常狀態上報 > [!WARNING] > **此 REST API 已廢棄並移除**。機台異常上報已全面遷移至 **MQTT** 即時通訊架構。 -> 請參閱 [MQTT 通訊規範 - B013 異常上報](file:///home/mama/projects/star-cloud/.agents/skills/mqtt-communication-specs/SKILL.md#32-異常與錯誤上報-b013) 進行串接。 +> 詳細錯誤代碼請參閱:[MQTT 通訊規範 - B013 硬體代碼對照表](file:///home/mama/projects/star-cloud/.agents/skills/mqtt-communication-specs/SKILL.md#32-異常與錯誤上報-b013) ### 3.12 B010: [DEPRECATED / REMOVED] 心跳上報與狀態同步 > [!WARNING] > **此 REST API 已廢棄並移除**。機台心跳上報與指令下發已全面遷移至 **MQTT** 架構。 -> 請參閱 [MQTT 通訊規範 - B010 心跳上報](file:///home/mama/projects/star-cloud/.agents/skills/mqtt-communication-specs/SKILL.md#31-心跳上報-b010) 進行串接。 - -#### B013 硬體代碼對照表 (由 MachineService 自動翻譯) - -| 代碼 | 英文 Key (i18n) | 級別 | 範例繁中翻譯 | -| :--- | :--- | :--- | :--- | -| **0402** | Dispense successful | info | 出貨成功 | -| **0403** | Slot jammed | error | **貨道卡貨** (重大異常) | -| **0202** | Product empty | warning | 貨道缺貨 | -| **0412** | Elevator rise error | error | 昇降機上升異常 | -| **0415** | Pickup door error | error | 取貨門異常 | -| **5402** | Pickup door not closed | warning | **取貨門未關** (警告) | -| **5403** | Elevator failure | error | 昇降系統故障 | +> 詳細格式請參閱:[MQTT 通訊規範 - B010 心跳上報](file:///home/mama/projects/star-cloud/.agents/skills/mqtt-communication-specs/SKILL.md#31-心跳上報-b010) --- diff --git a/.agents/skills/mqtt-communication-specs/SKILL.md b/.agents/skills/mqtt-communication-specs/SKILL.md index 461ae46..eece7c5 100644 --- a/.agents/skills/mqtt-communication-specs/SKILL.md +++ b/.agents/skills/mqtt-communication-specs/SKILL.md @@ -136,7 +136,19 @@ Mqtt3Client client = MqttClient.builder() "error_code": "0403" } ``` - *(註:`error_code` 應遵循 `MachineService::ERROR_CODE_MAP` 定義,雲端將自動轉換為對應語言標籤。`tid` 為貨道或任務 ID。)* +#### B013 硬體代碼對照表 (由 MachineService 自動翻譯) + +| 代碼 | 英文 Key (i18n) | 級別 | 範例繁中翻譯 | +| :--- | :--- | :--- | :--- | +| **0402** | Dispense successful | info | 出貨成功 | +| **0403** | Slot jammed | error | **貨道卡貨** (重大異常) | +| **0202** | Product empty | warning | 貨道缺貨 | +| **0412** | Elevator rise error | error | 昇降機上升異常 | +| **0415** | Pickup door error | error | 取貨門異常 | +| **5402** | Pickup door not closed | warning | **取貨門未關** (警告) | +| **5403** | Elevator failure | error | 昇降系統故障 | + +*(註:`error_code` 應遵循此表定義,雲端將根據 `i18n` 自動轉換。`tid` 為貨道或任務 ID。)* ### 3.3 交易生命週期上報 (Transaction) - `machine/{serial_no}/transaction` diff --git a/app/Http/Controllers/Admin/MachineController.php b/app/Http/Controllers/Admin/MachineController.php index f732afb..a69ce71 100644 --- a/app/Http/Controllers/Admin/MachineController.php +++ b/app/Http/Controllers/Admin/MachineController.php @@ -133,7 +133,24 @@ class MachineController extends AdminController */ public function slotsAjax(Machine $machine) { - $slots = $machine->slots()->with('product:id,name,image_url')->orderByRaw('CAST(slot_no AS UNSIGNED) ASC')->get(); + $slots = $machine->slots() + ->with('product:id,name,image_url') + ->orderByRaw('CAST(slot_no AS UNSIGNED) ASC') + ->get(); + + // 取得該機台目前所有等待中的庫存更新指令 (Pending Commands) + $pendingSlotNos = \App\Models\Machine\RemoteCommand::where('machine_id', $machine->id) + ->where('command_type', 'reload_stock') + ->where('status', 'pending') + ->get() + ->pluck('payload.slot_no') + ->flatten() + ->toArray(); + + // 將待處理狀態注入貨道物件 + $slots->each(function ($slot) use ($pendingSlotNos) { + $slot->is_pending = in_array((int)$slot->slot_no, $pendingSlotNos); + }); return response()->json([ 'success' => true, @@ -154,14 +171,21 @@ class MachineController extends AdminController 'batch_no' => 'nullable|string|max:50', ]); - $this->machineService->updateSlot($machine, $validated, auth()->id()); + try { + $this->machineService->updateSlot($machine, $validated, auth()->id()); - session()->flash('success', __('Slot updated successfully.')); + session()->flash('success', __('Slot updated successfully.')); - return response()->json([ - 'success' => true, - 'message' => __('Slot updated successfully.') - ]); + return response()->json([ + 'success' => true, + 'message' => __('Slot updated successfully.') + ]); + } catch (\Exception $e) { + return response()->json([ + 'success' => false, + 'message' => $e->getMessage() + ], 422); + } } /** diff --git a/app/Http/Controllers/Admin/RemoteController.php b/app/Http/Controllers/Admin/RemoteController.php index 83dd0ac..de49323 100644 --- a/app/Http/Controllers/Admin/RemoteController.php +++ b/app/Http/Controllers/Admin/RemoteController.php @@ -7,15 +7,18 @@ use Illuminate\Http\Request; use App\Models\Machine\Machine; use App\Models\Machine\RemoteCommand; use App\Services\Machine\MqttService; +use App\Services\Machine\MachineService; use Illuminate\Support\Facades\Auth; class RemoteController extends Controller { protected $mqttService; + protected $machineService; - public function __construct(MqttService $mqttService) + public function __construct(MqttService $mqttService, MachineService $machineService) { $this->mqttService = $mqttService; + $this->machineService = $machineService; } /** @@ -138,41 +141,47 @@ class RemoteController extends Controller 'note' => 'nullable|string|max:255', ]); - $payload = []; - if ($validated['command_type'] === 'change') { - $payload['amount'] = $validated['amount']; - } elseif ($validated['command_type'] === 'dispense') { - $payload['slot_no'] = $validated['slot_no']; - } + if ($validated['command_type'] === 'dispense') { + $this->machineService->dispatchDispense( + Machine::findOrFail($validated['machine_id']), + $validated['slot_no'], + auth()->id() + ); + } else { + $payload = []; + if ($validated['command_type'] === 'change') { + $payload['amount'] = $validated['amount']; + } - // 指令去重:將同機台、同類型的 pending 指令標記為「已取代」 - RemoteCommand::where('machine_id', $validated['machine_id']) - ->where('command_type', $validated['command_type']) - ->where('status', 'pending') - ->update([ - 'status' => 'superseded', - 'note' => __('Superseded by new command'), - 'executed_at' => now(), + // 指令去重:將同機台、同類期的 pending 指令標記為「已取代」 + RemoteCommand::where('machine_id', $validated['machine_id']) + ->where('command_type', $validated['command_type']) + ->where('status', 'pending') + ->update([ + 'status' => 'superseded', + 'note' => __('Superseded by new command'), + 'executed_at' => now(), + ]); + + $command = RemoteCommand::create([ + 'machine_id' => $validated['machine_id'], + 'user_id' => auth()->id(), + 'command_type' => $validated['command_type'], + 'payload' => $payload, + 'status' => 'pending', + 'note' => $validated['note'] ?? null, ]); - $command = RemoteCommand::create([ - 'machine_id' => $validated['machine_id'], - 'user_id' => auth()->id(), - 'command_type' => $validated['command_type'], - 'payload' => $payload, - 'status' => 'pending', - 'note' => $validated['note'] ?? null, - ]); - - // 【新增】同步推播 MQTT 指令 - $machine = Machine::find($validated['machine_id']); - if ($machine) { - $this->mqttService->pushCommand( - $machine->serial_no, - $command->command_type, - $command->payload, - $command->id - ); + // 推播 MQTT 指令 + $machine = Machine::find($validated['machine_id']); + if ($machine) { + $this->mqttService->pushCommand( + $machine->serial_no, + $command->command_type, + $command->payload, + (string) $command->id + ); + } } session()->flash('success', __('Command has been queued successfully.')); diff --git a/app/Jobs/Machine/ProcessCommandAck.php b/app/Jobs/Machine/ProcessCommandAck.php index 3f6af2f..9f5c8cb 100644 --- a/app/Jobs/Machine/ProcessCommandAck.php +++ b/app/Jobs/Machine/ProcessCommandAck.php @@ -88,26 +88,18 @@ class ProcessCommandAck implements ShouldQueue $machine = $command->machine; if ($command->command_type === 'dispense') { - // 若成功,連動更新貨道庫存 - if ($status === 'success' && isset($command->payload['slot_no'])) { - $slotNo = $command->payload['slot_no']; - $slot = $machine->slots()->where('slot_no', $slotNo)->first(); - - if ($slot) { - $oldStock = $slot->stock; - // 若 APP 回傳的庫存大於 0 則使用回傳值,否則執行扣減 - $newStock = (int) ($stockReported ?? 0); - if ($newStock <= 0 && $oldStock > 0) { - $newStock = $oldStock - 1; + $slotNo = $command->payload['slot_no'] ?? null; + $slot = $machine->slots()->where('slot_no', $slotNo)->first(); + + if ($slot) { + if ($status === 'success') { + // 若出貨成功,且 APP 回報了最新的庫存值,則以 APP 為準進行校準 + // 否則維持預扣後的狀態 (不需要額外動作,因為下發時已扣除) + if ($stockReported !== null) { + $slot->update(['stock' => (int)$stockReported]); + $payloadUpdates['new_stock'] = (int)$stockReported; } - $finalStock = max(0, $newStock); - $slot->update(['stock' => $finalStock]); - - // 紀錄庫存變化供前端顯示 - $payloadUpdates['old_stock'] = $oldStock; - $payloadUpdates['new_stock'] = $finalStock; - ProcessStateLog::dispatch( $machine->id, $machine->company_id, @@ -115,9 +107,23 @@ class ProcessCommandAck implements ShouldQueue 'info', ['slot' => $slotNo] ); + } else { + // 若出貨失敗,執行回滾 (Rollback):將預扣的庫存加回去 + $oldStock = $command->payload['old_stock'] ?? $slot->stock; + $slot->update(['stock' => $oldStock]); + + $payloadUpdates['rolled_back'] = true; + $payloadUpdates['new_stock'] = $oldStock; + + Log::warning('MQTT Dispense failed, rolled back inventory', [ + 'serial_no' => $this->serialNo, + 'slot_no' => $slotNo, + 'rolled_back_to' => $oldStock + ]); } } - } elseif ($command->command_type === 'reload_stock') { + } + elseif ($command->command_type === 'reload_stock') { // 若同步失敗,自動 Rollback 回滾庫存 if ($status === 'failed' && isset($command->payload['slot_no'], $command->payload['old'])) { $slotNo = $command->payload['slot_no']; diff --git a/app/Services/Machine/MachineService.php b/app/Services/Machine/MachineService.php index ff42d46..0424124 100644 --- a/app/Services/Machine/MachineService.php +++ b/app/Services/Machine/MachineService.php @@ -203,46 +203,49 @@ class MachineService */ public function updateSlot(Machine $machine, array $data, ?int $userId = null): void { - $command = DB::transaction(function () use ($machine, $data, $userId) { + DB::transaction(function () use ($machine, $data, $userId) { $slotNo = $data['slot_no']; $stock = $data['stock'] ?? null; $expiryDate = $data['expiry_date'] ?? null; $batchNo = $data['batch_no'] ?? null; - $slot = $machine->slots()->where('slot_no', $slotNo)->firstOrFail(); + + $slot = $machine->slots()->where('slot_no', $slotNo)->lockForUpdate()->firstOrFail(); - // 紀錄舊數據以供 Payload 使用 + // 1. 併行檢查:確保同一個貨道在同一時間只有一個指令在執行中 (Pending) + // 包含 reload_stock 與 dispense 兩種會異動庫存的類型 + $isPending = RemoteCommand::where('machine_id', $machine->id) + ->whereIn('command_type', ['reload_stock', 'dispense']) + ->where('status', 'pending') + ->whereJsonContains('payload->slot_no', (string)$slotNo) + ->exists(); + + if ($isPending) { + throw new \Exception(__('This slot has a pending update. Please wait for the previous command to complete.')); + } + + // 紀錄舊數據以供回滾使用 $oldData = [ 'stock' => $slot->stock, 'expiry_date' => $slot->expiry_date ? Carbon::parse($slot->expiry_date)->toDateString() : null, 'batch_no' => $slot->batch_no, ]; + // 2. 執行樂觀更新 (Optimistic Update) $updateData = [ 'expiry_date' => $expiryDate, 'batch_no' => $batchNo, ]; if ($stock !== null) $updateData['stock'] = (int)$stock; - $slot->update($updateData); - // 指令去重:將該機台所有尚未領取的舊庫存同步指令標記為「已取代」 - RemoteCommand::where('machine_id', $machine->id) - ->where('command_type', 'reload_stock') - ->where('status', 'pending') - ->update([ - 'status' => 'superseded', - 'note' => __('Superseded by new adjustment'), - 'executed_at' => now(), - ]); - - // 建立遠端指令紀錄 (Unified Command Concept) - return RemoteCommand::create([ + // 3. 建立遠端指令紀錄 + $command = RemoteCommand::create([ 'machine_id' => $machine->id, 'user_id' => $userId, 'command_type' => 'reload_stock', 'status' => 'pending', 'payload' => [ - 'slot_no' => $slotNo, + 'slot_no' => (string)$slotNo, 'old' => $oldData, 'new' => [ 'stock' => $stock !== null ? (int)$stock : $oldData['stock'], @@ -251,26 +254,80 @@ class MachineService ] ] ]); - }); - // 交易成功後,推播 MQTT 遠端指令 - $mqttPayload = [ - 'data' => [ - [ - 'slot_no' => $command->payload['slot_no'], - 'stock' => $command->payload['new']['stock'], - 'expiry_date' => $command->payload['new']['expiry_date'], - 'batch_no' => $command->payload['new']['batch_no'] ?? null, + // 4. 推播 MQTT + $mqttPayload = [ + 'data' => [ + [ + 'slot_no' => $command->payload['slot_no'], + 'stock' => $command->payload['new']['stock'], + 'expiry_date' => $command->payload['new']['expiry_date'], + 'batch_no' => $command->payload['new']['batch_no'] ?? null, + ] ] - ] - ]; + ]; - app(\App\Services\Machine\MqttService::class)->pushCommand( - $machine->serial_no, - 'update_inventory', - $mqttPayload, - (string) $command->id - ); + app(\App\Services\Machine\MqttService::class)->pushCommand( + $machine->serial_no, + 'update_inventory', + $mqttPayload, + (string) $command->id + ); + }); + } + + /** + * 遠端出貨指令下發 (含樂觀扣庫存與鎖定) + */ + public function dispatchDispense(Machine $machine, string $slotNo, ?int $userId = null): RemoteCommand + { + return DB::transaction(function () use ($machine, $slotNo, $userId) { + $slot = $machine->slots()->where('slot_no', $slotNo)->lockForUpdate()->firstOrFail(); + + // 併行檢查 + $isPending = RemoteCommand::where('machine_id', $machine->id) + ->whereIn('command_type', ['reload_stock', 'dispense']) + ->where('status', 'pending') + ->whereJsonContains('payload->slot_no', (string)$slotNo) + ->exists(); + + if ($isPending) { + throw new \Exception(__('This slot has a pending command. Please wait.')); + } + + if ($slot->stock <= 0) { + throw new \Exception(__('Out of stock.')); + } + + $oldStock = $slot->stock; + $newStock = $oldStock - 1; + + // 1. 執行樂觀扣薪 + $slot->update(['stock' => $newStock]); + + // 2. 建立指令紀錄 + $command = RemoteCommand::create([ + 'machine_id' => $machine->id, + 'user_id' => $userId, + 'command_type' => 'dispense', + 'status' => 'pending', + 'payload' => [ + 'slot_no' => (string)$slotNo, + 'old_stock' => $oldStock, + 'new_stock' => $newStock, + ] + ]); + + // 3. 推播 MQTT + app(\App\Services\Machine\MqttService::class)->pushCommand( + $machine->serial_no, + 'dispense', + $command->payload, + (string) $command->id + ); + + return $command; + }); } /** diff --git a/lang/en.json b/lang/en.json index 8c75673..37e0f7e 100644 --- a/lang/en.json +++ b/lang/en.json @@ -815,7 +815,7 @@ "Sale Price": "Sale Price", "Sales": "Sales", "sales": "sales", - "Sales Activity": "銷售活動", + "Sales Activity": "Sales Activity", "Sales Management": "Sales Management", "Sales Permissions": "Sales Permissions", "Sales Records": "Sales Records", @@ -823,10 +823,10 @@ "Save Changes": "Save Changes", "Save Config": "Save Config", "Save Material": "Save Material", - "Save Permissions": "儲存權限", + "Save Permissions": "Save Permissions", "Saved.": "Saved.", - "Saving...": "儲存中...", - "Scale level and access control": "層級與存取控制", + "Saving...": "Saving...", + "Scale level and access control": "Scale level and access control", "Scan this code to quickly access the maintenance form for this device.": "Scan this code to quickly access the maintenance form for this device.", "Search accounts...": "Search accounts...", "Search by name or S/N...": "Search by name or S/N...", @@ -1178,5 +1178,15 @@ "Unauthorized: Account not found": "Unauthorized: Account not found", "Unauthorized: Account not authorized for this machine": "Unauthorized: Account not authorized for this machine", "Slot report synchronized success": "Slot report synchronized success", - "Error: :message (:code)": "Error: :message (:code)" + "Error: :message (:code)": "Error: :message (:code)", + "Syncing": "Syncing", + "This slot is syncing with the machine. Please wait.": "This slot is syncing with the machine. Please wait.", + "Loading Data": "Loading Data", + "All Status": "All Status", + "CASH": "CASH", + "ITEM": "ITEM", + "This slot has a pending update. Please wait for the previous command to complete.": "This slot has a pending update. Please wait for the previous command to complete.", + "This slot has a pending command. Please wait.": "This slot has a pending command. Please wait.", + "Out of stock.": "Out of stock.", + "Save error:": "Save error:" } \ No newline at end of file diff --git a/lang/ja.json b/lang/ja.json index 198bdf1..ec747fa 100644 --- a/lang/ja.json +++ b/lang/ja.json @@ -1,1179 +1 @@ -{ - "15 Seconds": "15秒", - "30 Seconds": "30秒", - "60 Seconds": "60秒", - "A new verification link has been sent to your email address.": "新しい認証リンクがメールアドレスに送信されました。", - "Abnormal": "異常", - "Account": "アカウント", - "Account :name status has been changed to :status.": "アカウント :name のステータスが :status に変更されました。", - "Account created successfully.": "アカウントが正常に作成されました。", - "Account deleted successfully.": "アカウントが正常に削除されました。", - "Account Info": "アカウント情報", - "Account List": "アカウント一覧", - "Account Management": "アカウント管理", - "Account Name": "アカウント名", - "Account Settings": "アカウント設定", - "Account Status": "アカウント状態", - "Account updated successfully.": "アカウントが正常に更新されました。", - "Account:": "アカウント:", - "accounts": "アカウント管理", - "Accounts / Machines": "アカウント / 機体", - "Action": "操作", - "Actions": "操作", - "Active": "有効", - "Active Status": "有効ステータス", - "Ad Settings": "広告設定", - "Add Account": "アカウント追加", - "Add Advertisement": "広告を追加", - "Add Category": "カテゴリーを追加", - "Add Customer": "顧客追加", - "Add Machine": "機体追加", - "Add Machine Model": "モデル追加", - "Add Maintenance Record": "メンテナンス記録追加", - "Add Product": "商品を追加", - "Add Role": "権限追加", - "Adjust Stock": "在庫調整", - "Adjust Stock & Expiry": "在庫と消費期限の調整", - "Admin": "管理者", - "admin": "管理員", - "Admin display name": "管理者表示名", - "Admin Name": "管理者名", - "Admin Page": "管理者ページ", - "Admin Sellable Products": "商品表示管理", - "Administrator": "管理者", - "Advertisement assigned successfully": "広告の割り当てに成功しました", - "Advertisement assigned successfully.": "広告の割り当てに成功しました。", - "Advertisement created successfully": "広告の作成に成功しました", - "Advertisement created successfully.": "広告の作成に成功しました。", - "Advertisement deleted successfully": "広告の削除に成功しました", - "Advertisement deleted successfully.": "広告の削除に成功しました。", - "Advertisement List": "広告一覧", - "Advertisement Management": "広告管理", - "Advertisement updated successfully": "広告の更新に成功しました", - "Advertisement updated successfully.": "広告の更新に成功しました。", - "Advertisement Video/Image": "広告動画/画像", - "Affiliated Company": "所属会社", - "Affiliated Unit": "所属会社", - "Affiliation": "所属会社", - "AI Prediction": "AI予測", - "Alert Summary": "アラート概要", - "Alerts": "アラート", - "Alerts Pending": "保留中のアラート", - "All": "すべて", - "All Affiliations": "すべての所属", - "All Categories": "すべてのカテゴリ", - "All Companies": "すべての会社", - "All Levels": "すべてのレベル", - "All Machines": "すべての機体", - "All Stable": "全機正常", - "All Times System Timezone": "時間はすべてシステムタイムゾーンに基づきます", - "Amount": "金額", - "An error occurred while saving.": "保存中にエラーが発生しました。", - "analysis": "分析管理", - "Analysis Management": "分析管理", - "Analysis Permissions": "分析権限", - "API Token": "APIトークン", - "API Token Copied": "APIトークンをコピーしました", - "API Token regenerated successfully.": "APIトークンが正常に再生成されました。", - "APK Versions": "APKバージョン", - "app": "APP管理", - "APP Features": "APP機能設定", - "APP Management": "APP管理", - "APP Version": "APPバージョン", - "APP_ID": "APP_ID", - "APP_KEY": "APP_KEY", - "Apply changes to all identical products in this machine": "この機台の同一商品すべてに変更を適用", - "Apply to all identical products in this machine": "この機体内のすべての同一商品に適用する", - "Are you sure to delete this customer?": "この顧客を削除してもよろしいですか?", - "Are you sure you want to change the status of this item? This will affect its visibility on vending machines.": "この項目のステータスを変更してもよろしいですか?自動販売機での表示に影響します。", - "Are you sure you want to change the status of this product? Disabled products will not be visible on the machine.": "この商品のステータスを変更してもよろしいですか?無効にすると機体に表示されなくなります。", - "Are you sure you want to change the status? After disabling, this account will no longer be able to log in to the system.": "ステータスを変更してもよろしいですか?無効にすると、このアカウントはシステムにログインできなくなります。", - "Are you sure you want to change the status? This may affect associated accounts.": "ステータスを変更してもよろしいですか?関連するアカウントに影響を与える可能性があります。", - "Are you sure you want to deactivate this account? After deactivating, this account will no longer be able to log in to the system.": "このアカウントを無効化してもよろしいですか?無効化すると、システムにログインできなくなります。", - "Are you sure you want to delete this account?": "このアカウントを削除してもよろしいですか?", - "Are you sure you want to delete this account? This action cannot be undone.": "このアカウントを削除してもよろしいですか?この操作は取り消せません。", - "Are you sure you want to delete this advertisement? This will also remove all assignments to machines.": "Are you sure you want to delete this advertisement? This will also remove all assignments to machines.", - "Are you sure you want to delete this configuration?": "この設定を削除してもよろしいですか?", - "Are you sure you want to delete this configuration? This action cannot be undone.": "この設定を削除してもよろしいですか?この操作は取り消せません。", - "Are you sure you want to delete this item? This action cannot be undone.": "この項目を削除してもよろしいですか?この操作は取り消せません。", - "Are you sure you want to delete this product or category? This action cannot be undone.": "この商品またはカテゴリーを削除してもよろしいですか?この操作は取り消せません。", - "Are you sure you want to delete this product?": "この商品を削除してもよろしいですか?", - "Are you sure you want to delete this product? All related historical translation data will also be removed.": "この商品を削除してもよろしいですか?関連するすべての翻訳履歴データも削除されます。", - "Are you sure you want to delete this role? This action cannot be undone.": "この権限を削除してもよろしいですか?この操作は取り消せません。", - "Are you sure you want to delete your account?": "アカウントを削除してもよろしいですか?", - "Are you sure you want to proceed? This action cannot be undone.": "続行してもよろしいですか?この操作は取り消せません。", - "Are you sure you want to remove this assignment?": "この割り当てを解除してもよろしいですか?", - "Are you sure you want to send this command?": "このコマンドを送信してもよろしいですか?", - "Are you sure?": "よろしいですか?", - "Assign": "割り当て", - "Assign Advertisement": "広告を割り当て", - "Assign Machines": "機体割り当て", - "Assigned Machines": "割り当て済み機体", - "Assignment removed successfully.": "割り当てを解除しました。", - "audit": "監査管理", - "Audit Management": "監査管理", - "Audit Permissions": "稽核権限", - "Authorization updated successfully": "権限が正常に更新されました", - "Authorize": "認証", - "Authorize Btn": "認証", - "Authorized Accounts": "認証済みアカウント", - "Authorized Accounts Tab": "認証済みアカウント", - "Authorized Machines": "認証済み機体", - "Authorized Machines Management": "認証済み機体管理", - "Authorized Status": "認証状態", - "Availability": "可用性", - "Available Machines": "割り当て可能な機体", - "Avatar updated successfully.": "アバターが正常に更新されました。", - "Avg Cycle": "平均サイクル", - "Back to History": "履歴に戻る", - "Back to List": "リストに戻る", - "Badge Settings": "バッジ設定", - "Barcode": "バーコード", - "Barcode / Material": "バーコード / 素材", - "Basic Information": "基本情報", - "Basic Settings": "基本設定", - "Basic Specifications": "基本仕様", - "basic-settings": "基本設定", - "basic.machines": "機体設定", - "basic.payment-configs": "顧客決済設定", - "Batch": "バッチ", - "Batch No": "ロット番号", - "Batch Number": "バッチ番号", - "Belongs To": "所属会社", - "Belongs To Company": "所属会社", - "Business Type": "業種", - "Buyout": "買い取り", - "Cancel": "キャンセル", - "Cancel Purchase": "購入キャンセル", - "Cannot change Super Admin status.": "Super Admin のステータスは変更できません。", - "Cannot delete advertisement being used by machines.": "マシンで使用中の広告は削除できません。", - "Cannot delete company with active accounts.": "有効なアカウントを持つ会社は削除できません。", - "Cannot delete model that is currently in use by machines.": "機体で使用中のモデルは削除できません。", - "Cannot Delete Role": "権限を削除できません", - "Cannot delete role with active users.": "有効なユーザーを持つ権限は削除できません。", - "Card Reader": "カードリーダー", - "Card Reader No": "カードリーダー番号", - "Card Reader Reboot": "カードリーダーの再起動", - "Card Reader Restart": "カードリーダー再起動", - "Card Reader Seconds": "カードリーダー秒数", - "Card Terminal": "カード端末", - "Category": "カテゴリ", - "Category Management": "カテゴリー管理", - "Category Name": "カテゴリー名", - "Category Name (en)": "カテゴリ名 (英語)", - "Category Name (ja)": "カテゴリ名 (日本語)", - "Category Name (zh_TW)": "カテゴリ名 (繁体字中国語)", - "Change": "変更", - "Change Stock": "在庫変更", - "Channel Limits": "チャネル制限", - "Channel Limits (Track/Spring)": "チャネル上限(トラック/スプリング)", - "Channel Limits Configuration": "チャネル制限設定", - "ChannelId": "チャネルID", - "ChannelSecret": "チャネルシークレット", - "Checkout Time 1": "チェックアウト時間1", - "Checkout Time 2": "チェックアウト時間2", - "Clear": "クリア", - "Clear Filter": "フィルターをクリア", - "Clear Stock": "在庫クリア", - "Click here to re-send the verification email.": "認証メールを再送信するにはここをクリックしてください。", - "Click to Open Dashboard": "クリックしてダッシュボードを開く", - "Click to upload": "クリックしてアップロード", - "Close Panel": "パネルを閉じる", - "Command Center": "指令センター", - "Command Confirmation": "コマンド実行の確認", - "Command error:": "コマンドエラー:", - "Command has been queued successfully.": "コマンドがキューに正常に追加されました。", - "Command queued successfully.": "コマンドが正常にキューに追加されました。", - "Command Type": "コマンドタイプ", - "companies": "顧客管理", - "Company": "会社", - "Company Code": "会社コード", - "Company Information": "会社情報", - "Company Level": "会社レベル", - "Company Name": "会社名", - "Config Name": "設定名", - "Configuration Name": "設定名", - "Confirm": "確認", - "Confirm Account Deactivation": "無効化の確認", - "Confirm Account Status Change": "アカウントステータス変更の確認", - "Confirm Assignment": "割り当てを確認", - "Confirm Changes": "変更を確認", - "Confirm Deletion": "削除の確認", - "Confirm Password": "パスワード(確認)", - "Confirm Status Change": "ステータス変更の確認", - "Connected": "通信中", - "Connecting...": "接続中...", - "Connectivity Status": "接続状態", - "Connectivity vs Sales Correlation": "接続状態と売上の相関分析", - "Contact & Details": "連絡先と詳細", - "Contact Email": "連絡用メールアドレス", - "Contact Info": "連絡先情報", - "Contact Name": "担当者名", - "Contact Phone": "電話番号", - "Contract Period": "契約期間", - "Contract Until (Optional)": "契約終了日(任意)", - "Control": "操作", - "Cost": "コスト", - "Coupons": "クーポン", - "Create": "作成", - "Create a new role and assign permissions.": "新しい権限を定義し、パーミッションを割り当てます。", - "Create Config": "設定作成", - "Create Machine": "機体作成", - "Create New Role": "新しい権限を作成", - "Create Payment Config": "決済設定作成", - "Create Product": "商品作成", - "Create Role": "権限作成", - "Create Sub Account Role": "子アカウント権限作成", - "Creation Time": "作成日時", - "Critical": "致命的", - "Current": "現在", - "Current Password": "現在のパスワード", - "Current Status": "現在のステータス", - "Current Stock": "現在庫", - "Current Type": "現在のタイプ", - "Current:": "現在:", - "Customer and associated accounts disabled successfully.": "顧客と関連アカウントが正常に無効化されました。", - "Customer created successfully.": "顧客が正常に作成されました。", - "Customer deleted successfully.": "顧客が正常に削除されました。", - "Customer Details": "顧客詳細", - "Customer enabled successfully.": "顧客が正常に有効化されました。", - "Customer Info": "顧客情報", - "Customer Management": "顧客管理", - "Customer Payment Config": "顧客決済設定", - "Customer updated successfully.": "顧客が正常に更新されました。", - "Cycle Efficiency": "サイクル効率", - "Daily Revenue": "日次収益", - "Danger Zone: Delete Account": "危険区域:アカウント削除", - "Dashboard": "ダッシュボード", - "Data Configuration": "データ設定", - "Data Configuration Permissions": "データ設定権限", - "data-config": "データ設定", - "data-config.sub-account-roles": "子アカウント権限", - "data-config.sub-accounts": "子アカウント管理", - "Date Range": "期間", - "Day Before": "前日", - "Default Donate": "デフォルト寄付する", - "Default Not Donate": "デフォルト寄付しない", - "Define and manage security roles and permissions.": "セキュリティ権限とパーミッションを定義し管理します。", - "Define new third-party payment parameters": "新しい外部決済パラメータを定義します", - "Delete": "削除", - "Delete Account": "アカウント削除", - "Delete Advertisement": "広告を削除", - "Delete Advertisement Confirmation": "広告削除の確認", - "Delete Permanently": "完全に削除", - "Delete Product": "商品を削除", - "Delete Product Confirmation": "商品削除の確認", - "Deposit Bonus": "リチャージボーナス", - "Describe the repair or maintenance status...": "修理またはメンテナンスの状況を記入してください...", - "Deselect All": "すべて解除", - "Detail": "詳細", - "Device Information": "端末情報", - "Device Status Logs": "端末状態ログ", - "Devices": "端末", - "Disable": "無効にする", - "Disable Product Confirmation": "商品無効化の確認", - "Disabled": "無効", - "Discord Notifications": "Discord通知", - "Dispense Failed": "払い出し失敗", - "Dispense Success": "払い出し成功", - "Dispensing": "払い出し中", - "Duration": "再生時間", - "Duration (Seconds)": "再生時間(秒)", - "e.g. 500ml / 300g": "例: 500ml / 300g", - "e.g. John Doe": "例:山田太郎", - "e.g. johndoe": "例:yamadataro", - "e.g. Taiwan Star": "例:Taiwan Star", - "e.g. TWSTAR": "例:TWSTAR", - "e.g., Beverage": "例:飲料", - "e.g., Company Standard Pay": "例:標準決済設定", - "e.g., Drinks": "例:ドリンク", - "e.g., Taipei Station": "例:台北駅前", - "e.g., お飲み物": "例:お飲み物", - "E.SUN QR Scan": "玉山銀行QRスキャン", - "E.SUN QR Scan Settings Description": "玉山銀行QRスキャン決済設定", - "EASY_MERCHANT_ID": "EASY_MERCHANT_ID", - "ECPay Invoice": "緑界(ECPay)電子請求書", - "ECPay Invoice Settings Description": "緑界(ECPay)電子請求書発行設定", - "Edit": "編集", - "Edit Account": "アカウント編集", - "Edit Advertisement": "広告を編集", - "Edit Category": "カテゴリ編集", - "Edit Customer": "顧客編集", - "Edit Expiry": "有効期限編集", - "Edit Machine": "機体編集", - "Edit Machine Model": "モデル編集", - "Edit Machine Name": "マシン名を編集", - "Edit Machine Settings": "機体設定編集", - "Edit Name": "名前を編集", - "Edit Payment Config": "決済設定編集", - "Edit Product": "商品編集", - "Edit Role": "権限編集", - "Edit Role Permissions": "権限パーミッション編集", - "Edit Settings": "設定編集", - "Edit Slot": "スロット編集", - "Edit Sub Account Role": "子アカウント権限編集", - "Email": "メールアドレス", - "Enable": "有効にする", - "Enable Material Code": "品目コードを有効にする", - "Enable Points": "ポイントを有効にする", - "Enabled": "有効", - "Enabled/Disabled": "有効/無効", - "End Date": "終了日", - "Engineer": "エンジニア", - "English": "英語", - "Ensure your account is using a long, random password to stay secure.": "セキュリティを保つため、アカウントには長くランダムなパスワードを使用してください。", - "Enter ad material name": "広告素材名を入力", - "Enter login ID": "ログインIDを入力", - "Enter machine location": "設置場所を入力", - "Enter machine name": "機体名を入力", - "Enter machine name...": "マシン名を入力...", - "Enter model name": "モデル名を入力", - "Enter role name": "権限名を入力", - "Enter serial number": "シリアル番号を入力", - "Enter your password to confirm": "確認のためパスワードを入力してください", - "Entire Machine": "機体全体", - "Equipment efficiency and OEE metrics": "設備効率とOEE総合指標", - "Error": "エラー", - "Error processing request": "リクエスト処理エラー", - "Execute": "実行する", - "Execute Change": "釣り銭払い出し実行", - "Execute Delivery Now": "今すぐ払い出し", - "Execute maintenance and operational commands remotely": "機材のメンテナンスや操作コマンドの遠隔実行", - "Execute Remote Change": "遠隔払い出し実行", - "Execution Time": "実行時間", - "Exp": "有効期限", - "Expired": "期限切れ", - "Expired / Disabled": "期限切れ / 無効", - "Expiring": "期限間近", - "Expiry": "期限", - "Expiry Date": "有効期限", - "Expiry Management": "賞味期限管理", - "failed": "失敗", - "Failed": "失敗", - "Failed to fetch machine data.": "機体データの取得に失敗しました。", - "Failed to load permissions": "権限の読み込みに失敗しました", - "Failed to save permissions.": "権限の保存に失敗しました。", - "Failed to update machine images: ": "機体画像の更新に失敗しました: ", - "Feature Settings": "機能設定", - "Feature Toggles": "機能切り替え", - "files selected": "個のファイルを選択", - "Fill in the device repair or maintenance details": "修理またはメンテナンスの詳細を記入してください", - "Fill in the product details below": "商品の詳細を記入してください", - "Firmware Version": "ファームウェアバージョン", - "Fleet Avg OEE": "フリート平均OEE", - "Fleet Performance": "フリートパフォーマンス", - "Force end current session": "現在のセッションを強制終了", - "Force End Session": "セッション強制終了", - "From": "から", - "From:": "から:", - "Full Access": "フルアクセス", - "Full Name": "氏名", - "Full Points": "フルポイント", - "Games": "ゲーム", - "General permissions not linked to a specific menu.": "特定のメニューに関連付けられていない一般的な権限。", - "Gift Definitions": "ギフト定義", - "Global roles accessible by all administrators.": "すべての管理者がアクセス可能なグローバル権限。", - "Got it": "了解しました", - "Grant UI Access": "UIアクセス許可", - "Half Points": "ハーフポイント", - "Half Points Amount": "ハーフポイント金額", - "Hardware & Network": "ハードウェアとネットワーク", - "Hardware & Slots": "ハードウェアとスロット", - "HashIV": "HashIV", - "HashKey": "HashKey", - "Heartbeat": "ハートビート", - "Heating End Time": "加熱終了時間", - "Heating Range": "加熱範囲", - "Heating Start Time": "加熱開始時間", - "Helper": "ヘルパー", - "Home Page": "ホームページ", - "hours ago": "時間前", - "Identity & Codes": "IDとコード", - "image": "画像", - "Info": "情報", - "Initial Admin Account": "初期管理者アカウント", - "Initial Role": "初期権限", - "Installation": "設置", - "Invoice Status": "請求書ステータス", - "Items": "項目", - "items": "項目", - "Japanese": "日本語", - "JKO_MERCHANT_ID": "JKO_MERCHANT_ID", - "john@example.com": "john@example.com", - "Joined": "参加日", - "Just now": "たった今", - "Key": "キー", - "Key No": "キー番号", - "Last Communication": "最終通信", - "Last Heartbeat": "最終ハートビート", - "Last Page": "最後のページ", - "Last Signal": "最終信号", - "Last Sync": "最終通信", - "Last Time": "最終時間", - "Last Updated": "最終更新", - "Lease": "リース", - "Level": "レベル", - "LEVEL TYPE": "レベルタイプ", - "line": "Line管理", - "Line Coupons": "Lineクーポン", - "Line Machines": "Line連携機体", - "Line Management": "Line管理", - "Line Members": "Line会員", - "Line Official Account": "Line公式アカウント", - "Line Orders": "Line注文", - "LINE Pay Direct": "LINE Pay直販", - "LINE Pay Direct Settings Description": "LINE Pay公式直接接続設定", - "Line Permissions": "Line権限", - "Line Products": "Line商品", - "LINE_MERCHANT_ID": "LINE_MERCHANT_ID", - "LIVE": "ライブ", - "Live Fleet Updates": "リアルタイム機体状況", - "Loading Cabinet...": "棚を読み込み中...", - "Loading machines...": "機体を読み込み中...", - "Loading...": "読み込み中...", - "Location": "場所", - "Lock": "ロック", - "Lock Now": "今すぐロック", - "Lock Page": "ページロック", - "Lock Page Lock": "ページをロック", - "Lock Page Unlock": "ロック解除", - "Locked Page": "ロックされたページ", - "Login History": "ログイン履歴", - "Logout": "ログアウト", - "Logs": "ログ", - "Low": "在庫不足", - "Low Stock": "在庫不足", - "Loyalty & Features": "ロイヤリティと機能", - "Machine Advertisement Settings": "マシン広告設定", - "Machine Count": "機体数", - "Machine created successfully.": "機体が正常に作成されました。", - "Machine Details": "機体詳細", - "Machine Images": "機体画像", - "Machine images updated successfully.": "機体画像が正常に更新されました。", - "Machine Info": "機体情報", - "Machine Information": "機体情報", - "Machine Inventory": "マシン在庫", - "Machine is heartbeat normal": "通信状態良好", - "Machine List": "機体一覧", - "Machine Login Logs": "機体ログインログ", - "Machine Logs": "機体ログ", - "Machine Management": "機体管理", - "Machine Management Permissions": "機体管理権限", - "Machine Model": "機体モデル", - "Machine model created successfully.": "機体モデルが正常に作成されました。", - "Machine model deleted successfully.": "機体モデルが正常に削除されました。", - "Machine Model Settings": "機体モデル設定", - "Machine model updated successfully.": "機体モデルが正常に更新されました。", - "Machine Name": "機体名", - "Machine Permissions": "機体権限", - "Machine Reboot": "マシンの再起動", - "Machine Registry": "機体レジストリ", - "Machine Reports": "機体レポート", - "Machine Restart": "機体再起動", - "Machine Settings": "機体設定", - "Machine settings updated successfully.": "機体設定が正常に更新されました。", - "Machine Status": "機体状態", - "Machine Status List": "機体稼動状況リスト", - "Machine updated successfully.": "マシンが正常に更新されました。", - "Machine Utilization": "機台稼働率", - "Machines": "機体", - "machines": "機体管理", - "Machines Online": "オンライン機体", - "Maintenance": "メンテナンス", - "Maintenance Content": "メンテナンス内容", - "Maintenance Date": "メンテナンス日", - "Maintenance Details": "メンテナンス詳細", - "Maintenance Operations": "メンテナンス操作", - "Maintenance Photos": "メンテナンス写真", - "Maintenance QR": "メンテナンスQR", - "Maintenance QR Code": "メンテナンスQRコード", - "Maintenance record created successfully": "メンテナンス記録が正常に作成されました", - "Maintenance Records": "メンテナンス記録", - "Manage": "管理", - "Manage Account Access": "アカウントアクセス管理", - "Manage ad materials and machine playback settings": "広告素材とマシン再生設定を管理", - "Manage administrative and tenant accounts": "管理者およびテナントアカウントの管理", - "Manage all tenant accounts and validity": "すべてのテナントアカウントと有効性の管理", - "Manage Expiry": "有効期限管理", - "Manage inventory and monitor expiry dates across all machines": "全機台の在庫管理と賞味期限の監視", - "Manage machine access permissions": "機体のアクセス権限管理", - "Manage your ad material details": "広告素材の詳細を管理", - "Manage your catalog, categories, and inventory settings.": "カタログ、カテゴリー、在庫設定を管理します。", - "Manage your catalog, prices, and multilingual details.": "カタログ、価格、多言語詳細を管理します。", - "Manage your machine fleet and operational data": "機体群と運用データを管理します", - "Manage your profile information, security settings, and login history": "プロフィール、セキュリティ、ログイン履歴を管理します", - "Management of operational parameters": "運用パラメータの管理", - "Management of operational parameters and models": "運用パラメータとモデルの管理", - "Manufacturer": "メーカー", - "Material Code": "品目コード", - "Material Name": "素材名", - "Material Type": "素材タイプ", - "Max": "最大", - "Max 3": "最大3枚", - "Max 50MB": "最大50MB", - "Max 5MB": "最大5MB", - "Max Capacity:": "最大容量:", - "Member": "会員", - "Member & External": "会員と外部連携", - "Member List": "会員一覧", - "Member Management": "会員管理", - "Member Price": "会員価格", - "Member Status": "会員状態", - "Member System": "会員システム", - "members": "会員管理", - "Membership Tiers": "会員ランク", - "Menu Permissions": "メニュー権限", - "menu.analysis": "分析管理", - "menu.app": "APP管理", - "menu.audit": "監査管理", - "menu.basic": "基本管理", - "menu.basic-settings": "基本設定", - "menu.basic.machines": "機体設定", - "menu.basic.payment-configs": "顧客決済設定", - "menu.data-config": "データ設定", - "menu.data-config.admin-products": "商品表示管理", - "menu.data-config.advertisements": "広告管理", - "menu.data-config.badges": "バッジ設定", - "menu.data-config.points": "ポイント設定", - "menu.data-config.products": "商品管理", - "menu.data-config.sub-accounts": "子アカウント管理", - "menu.line": "Line管理", - "menu.machines": "機体管理", - "menu.machines.list": "機体一覧", - "menu.machines.maintenance": "メンテナンス記録", - "menu.machines.permissions": "機体権限", - "menu.machines.utilization": "稼働率", - "menu.members": "会員管理", - "menu.permission": "パーミッション設定", - "menu.permissions": "権限管理", - "menu.permissions.accounts": "アカウント管理", - "menu.permissions.companies": "顧客管理", - "menu.permissions.roles": "権限管理", - "menu.remote": "リモート管理", - "menu.reservation": "予約システム", - "menu.sales": "売上管理", - "menu.special-permission": "特別権限", - "menu.warehouses": "倉庫管理", - "Merchant IDs": "ショップID", - "Merchant payment gateway settings management": "ショップ決済ゲートウェイ設定管理", - "Message": "メッセージ", - "Message Content": "メッセージ内容", - "Message Display": "メッセージ表示", - "min": "分", - "Min 8 characters": "最低8文字", - "mins ago": "分前", - "Model": "モデル", - "Model Name": "モデル名", - "Models": "モデル", - "Modifying your own administrative permissions may result in losing access to certain system functions.": "自分自身の管理権限を変更すると、特定のシステム機能へのアクセスを失う可能性があります。", - "Monitor and manage stock levels across your fleet": "全機台の在庫状況を監視・管理します", - "Monitor events and system activity across your vending fleet.": "自動販売機群のイベントとシステムアクティビティを監視します。", - "Monthly cumulative revenue overview": "月間累積収益の概要", - "Monthly Transactions": "月間取引数", - "Multilingual Names": "多言語名称", - "N/A": "N/A", - "Name": "名前", - "Name in English": "英語名", - "Name in Japanese": "日本語名", - "Name in Traditional Chinese": "繁体字中国語名", - "Never Connected": "未接続", - "New Command": "新規コマンド", - "New Machine Name": "新しいマシン名", - "New Password": "新しいパスワード", - "New Password (leave blank to keep current)": "新しいパスワード(変更しない場合は空白)", - "New Record": "新規記録", - "New Role": "新しい権限", - "New Sub Account Role": "新しい子アカウント権限", - "Next": "次へ", - "No accounts found": "アカウントが見つかりません", - "No active cargo lanes found": "アクティブな貨道が見つかりません", - "No additional notes": "追加のメモはありません", - "No advertisements found.": "広告が見つかりません。", - "No alert summary": "アラートの概要はありません", - "No assignments": "割り当てなし", - "No command history": "コマンド履歴なし", - "No Company": "会社なし", - "No configurations found": "設定が見つかりません", - "No content provided": "内容が提供されていません", - "No customers found": "顧客が見つかりません", - "No data available": "データがありません", - "No file uploaded.": "ファイルがアップロードされていません。", - "No heartbeat for over 30 seconds": "30秒以上ハートビートがありません", - "No images uploaded": "画像がアップロードされていません", - "No Invoice": "請求書なし", - "No location set": "場所が設定されていません", - "No login history yet": "ログイン履歴がまだありません", - "No logs found": "ログが見つかりません", - "No Machine Selected": "機体が選択されていません", - "No machines assigned": "機体が割り当てられていません", - "No machines available": "利用可能な機体はありません", - "No machines available in this company.": "この会社で割り当て可能な機体はありません。", - "No maintenance records found": "メンテナンス記録がありません", - "No matching logs found": "一致するログが見つかりません", - "No matching machines": "一致する機体が見つかりません", - "No materials available": "利用可能な素材がありません", - "No permissions": "権限なし", - "No records found": "記録が見つかりません", - "No roles available": "利用可能な権限はありません", - "No roles found.": "権限が見つかりません。", - "No slots found": "スロットが見つかりません", - "No slot data available": "スロットデータがありません", - "No users found": "ユーザーが見つかりません", - "None": "なし", - "Normal": "通常", - "Not Used": "不使用", - "Not Used Description": "外部決済サービスを使用しない", - "Notes": "備考", - "OEE": "OEE", - "OEE Efficiency Trend": "OEE効率傾向", - "OEE Score": "OEEスコア", - "OEE.Activity": "アクティビティ", - "OEE.Errors": "エラー", - "OEE.Hours": "時間", - "OEE.Orders": "注文数", - "OEE.Sales": "売上高", - "of": "/", - "Offline": "オフライン", - "Offline Machines": "オフライン機体", - "Once your account is deleted, all of its resources and data will be permanently deleted. Before deleting your account, please download any data or information that you wish to retain.": "アカウントを削除すると、そのすべてのリソースとデータが完全に削除されます。削除する前に、保存しておきたいデータをダウンロードしてください。", - "Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.": "アカウントを削除すると、そのすべてのリソースとデータが完全に削除されます。完全に削除するには、パスワードを入力してください。", - "Online": "オンライン", - "Online Duration": "オンライン継続時間", - "Online Machines": "オンライン機体", - "Online Status": "オンライン状態", - "Only system roles can be assigned to platform administrative accounts.": "プラットフォーム管理アカウントにはシステム権限のみを割り当てることができます。", - "Operation Note": "操作メモ", - "Operation Records": "操作記録", - "Operational Parameters": "運用パラメータ", - "Operations": "運用", - "Operator": "操作員", - "Optimal": "最適", - "Optimized for display. Supported formats: JPG, PNG, WebP.": "表示用に最適化。対応形式:JPG, PNG, WebP。", - "Optimized Performance": "最適化されたパフォーマンス", - "Optional": "任意", - "Order Management": "注文管理", - "Orders": "注文", - "Original": "元", - "Original Type": "元のタイプ", - "Original:": "元:", - "Other Permissions": "その他の権限", - "Others": "その他", - "Output Count": "出力数", - "Owner": "所属会社", - "Page Lock Status": "ページロック状態", - "Parameters": "パラメータ", - "PARTNER_KEY": "PARTNER_KEY", - "Pass Code": "パスコード", - "Pass Codes": "パスコード", - "Password": "パスワード", - "Password updated successfully.": "パスワードが正常に更新されました。", - "Payment & Invoice": "決済と請求書", - "Payment Buffer Seconds": "決済猶予秒数", - "Payment Config": "決済設定", - "Payment Configuration": "決済設定", - "Payment Configuration created successfully.": "決済設定が正常に作成されました。", - "Payment Configuration deleted successfully.": "決済設定が正常に削除されました。", - "Payment Configuration updated successfully.": "決済設定が正常に更新されました。", - "Payment Selection": "決済選択", - "Pending": "機台の取得待ち", - "pending": "機台の取得待ち", - "Performance": "パフォーマンス", - "Permanent": "永久", - "Permanently Delete Account": "アカウントを完全に削除", - "Permission Settings": "パーミッション設定", - "Permissions": "パーミッション", - "permissions": "permissions", - "Permissions updated successfully": "権限が正常に更新されました", - "permissions.accounts": "permissions.accounts", - "permissions.companies": "permissions.companies", - "permissions.roles": "permissions.roles", - "Phone": "電話番号", - "Photo Slot": "写真スロット", - "PI_MERCHANT_ID": "PI_MERCHANT_ID", - "Picked up": "取得", - "Picked up Time": "取得日時", - "Pickup Code": "受け取りコード", - "Pickup Codes": "受け取りコード", - "Playback Order": "再生順序", - "Please check the following errors:": "以下のエラーを確認してください:", - "Please check the form for errors.": "フォームのエラーを確認してください。", - "Please confirm the details below": "以下の操作内容を確認してください", - "Please select a machine first": "先にマシンを選択してください", - "Please select a machine to view and manage its advertisements.": "広告を表示・管理するマシンを選択してください。", - "Please select a machine to view metrics": "データを確認する機体を選択してください", - "Please select a material": "素材を選択してください", - "Please select a slot": "スロットを選択してください", - "PNG, JPG up to 2MB": "2MB以下のPNG、JPG", - "PNG, JPG, WEBP up to 10MB": "PNG, JPG, WEBP 最大10MB", - "Point Rules": "ポイントルール", - "Point Settings": "ポイント設定", - "Points Rule": "ポイントルール", - "Points Settings": "ポイント設定", - "Points toggle": "ポイント切替", - "POS Reboot": "POS再起動", - "Position": "位置", - "Preview": "プレビュー", - "Previous": "前へ", - "Price / Member": "価格 / 会員", - "Pricing Information": "価格情報", - "Product Count": "商品数", - "Product created successfully": "商品が正常に作成されました", - "Product deleted successfully": "商品が正常に削除されました", - "Product Details": "商品詳細", - "Product Image": "商品画像", - "Product Info": "商品情報", - "Product List": "商品一覧", - "Product Management": "商品管理", - "Product Name (Multilingual)": "商品名(多言語)", - "Product Reports": "商品レポート", - "Product Status": "商品状態", - "Product status updated to :status": "商品ステータスが :status に更新されました", - "Product updated successfully": "商品が正常に更新されました", - "Production Company": "製造会社", - "Profile": "プロフィール", - "Profile Information": "プロフィール情報", - "Profile Settings": "プロフィール設定", - "Profile updated successfully.": "プロフィールが正常に更新されました。", - "Promotions": "販促", - "Protected": "保護済み", - "PS_LEVEL": "PS_LEVEL", - "PS_MERCHANT_ID": "PS_MERCHANT_ID", - "Purchase Audit": "購入監査", - "Purchase Finished": "購入完了", - "Purchases": "購入", - "Purchasing": "購入中", - "Qty": "数量", - "Quality": "品質", - "Questionnaire": "アンケート", - "Quick Expiry Check": "有効期限クイックチェック", - "Quick Maintenance": "クイックメンテナンス", - "Quick search...": "クイック検索...", - "Quick Select": "クイック選択", - "Real-time fleet efficiency and OEE metrics": "リアルタイムのフリート効率とOEE指標", - "Real-time monitoring across all machines": "全機体のリアルタイム監視", - "Real-time monitoring and adjustment of cargo lane inventory and expiration dates": "各マシンの在庫と賞味期限をリアルタイムで監視・調整します", - "Real-time OEE analysis awaits": "リアルタイムOEE分析を待機中", - "Real-time Operation Logs (Last 50)": "リアルタイム稼働ログ(直近50件)", - "Real-time performance analytics": "リアルタイムのパフォーマンス分析", - "Real-time status monitoring": "リアルタイムの状態監視", - "Reason for this command...": "このコマンドの理由...", - "Receipt Printing": "レシート印刷", - "Recent Commands": "最近のコマンド", - "Recent Login": "最近のログイン", - "Recently reported errors or warnings in logs": "最近のログにエラーまたは警告があります", - "Regenerate": "再生成", - "Regenerating the token will disconnect the physical machine until it is updated. Continue?": "トークンを再生成すると、機体を更新するまで接続が切断されます。続行しますか?", - "remote": "remote", - "Remote Change": "リモート変更", - "Remote Checkout": "リモートチェックアウト", - "Remote Command Center": "遠隔指令センター", - "Remote Dispense": "リモート払い出し", - "Remote Lock": "リモートロック", - "Remote Management": "リモート管理", - "Remote Permissions": "リモート権限", - "Remote Reboot": "リモート精算", - "Remote Settlement": "遠隔決済処理", - "Removal": "取り外し", - "Repair": "修理", - "Replenishment Audit": "補充監査", - "Replenishment Page": "補充ページ", - "Replenishment Records": "補充記録", - "Replenishments": "補充", - "Reporting Period": "レポート期間", - "reservation": "reservation", - "Reservation Members": "予約会員", - "Reservation System": "予約システム", - "Reservations": "予約", - "Reset POS terminal": "POS端末のリセット", - "Restart entire machine": "機台全体を再起動", - "Restrict machine UI access": "機台UIアクセス制限", - "Restrict UI Access": "UIアクセス制限", - "Retail Price": "小売価格", - "Returns": "返品", - "Risk": "リスク", - "Role": "役職", - "Role created successfully.": "権限が正常に作成されました。", - "Role deleted successfully.": "権限が正常に削除されました。", - "Role Identification": "権限識別", - "Role Management": "権限管理", - "Role Name": "権限名", - "Role name already exists in this company.": "この会社内に同じ名前の権限が既に存在します。", - "Role not found.": "権限が見つかりません。", - "Role Permissions": "権限パーミッション", - "Role Settings": "権限パーミッション設定", - "Role Type": "権限タイプ", - "Role updated successfully.": "権限が正常に更新されました。", - "Roles": "権限パーミッション", - "roles": "roles", - "Roles scoped to specific customer companies.": "特定の顧客会社に限定された権限。", - "Running": "稼働中", - "Running Status": "稼働状態", - "s": "s", - "Sale Price": "販売価格", - "Sales": "売上", - "sales": "sales", - "Sales Activity": "販売アクティビティ", - "Sales Management": "売上管理", - "Sales Permissions": "売上権限", - "Sales Records": "売上記録", - "Save": "保存", - "Save Changes": "変更を保存", - "Save Config": "設定保存", - "Save Material": "素材を保存", - "Save Permissions": "パーミッション保存", - "Saved.": "保存しました。", - "Saving...": "保存中...", - "Scale level and access control": "規模レベルとアクセス制御", - "Scan this code to quickly access the maintenance form for this device.": "このコードをスキャンして、端末のメンテナンスフォームに素早くアクセスします。", - "Search accounts...": "アカウントを検索...", - "Search by name or S/N...": "名称または製造番号で検索...", - "Search cargo lane": "貨道を検索", - "Search Company Title...": "会社名を検索...", - "Search categories...": "カテゴリーを検索...", - "Search company...": "会社を検索...", - "Search configurations...": "設定を検索...", - "Search customers...": "顧客を検索...", - "Search Machine...": "マシンを検索...", - "Search machines by name or serial...": "機体名またはシリアルで検索...", - "Search machines...": "機体を検索...", - "Search models...": "モデルを検索...", - "Search products...": "商品を検索...", - "Search roles...": "権限を検索...", - "Search serial no or name...": "シリアルまたは名前を検索...", - "Search serial or machine...": "シリアルまたは機体を検索...", - "Search serial or name...": "シリアルまたは名前を検索...", - "Search users...": "ユーザーを検索...", - "Search...": "検索...", - "Seconds": "秒", - "Security & State": "セキュリティと状態", - "Security Controls": "セキュリティ制御", - "Select a machine to deep dive": "詳細分析を行う機体を選択してください", - "Select a material to play on this machine": "このマシンで再生する素材を選択", - "Select All": "すべて選択", - "Select an asset from the left to start analysis": "左側から資産を選択して分析を開始", - "Select Cargo Lane": "貨道選択", - "Select Category": "カテゴリーを選択", - "Select Company": "会社名を選択", - "Select Company (Default: System)": "会社を選択(デフォルト:システム)", - "Select date to sync data": "同期する日付を選択してください", - "Select Machine": "機体を選択", - "Select Machine to view metrics": "データを確認する機体を選択してください", - "Select Material": "素材を選択", - "Select Model": "モデルを選択", - "Select Owner": "会社名を選択", - "Select Slot...": "貨道を選択...", - "Select Target Slot": "ターゲットスロットを選択", - "Select...": "選択...", - "Selected": "選択中", - "Selected Date": "検索日", - "Selection": "選択", - "sent": "機台が取得済み", - "Sent": "機台が取得済み", - "Serial & Version": "シリアルとバージョン", - "Serial NO": "シリアル番号", - "Serial No": "シリアル番号", - "Serial Number": "シリアル番号", - "set": "設定済み", - "Settlement": "決済処理", - "Show": "表示", - "Show material code field in products": "商品の品目コードを表示する", - "Show points rules in products": "商品のポイントルールを表示する", - "Showing": "表示中", - "Showing :from to :to of :total items": ":from から :to まで表示中 (全 :total 項目)", - "Sign in to your account": "アカウントにサインイン", - "Signed in as": "ログイン中:", - "Slot": "スロット", - "Slot Mechanism (default: Conveyor, check for Spring)": "スロット機構(デフォルト:ベルト、スプリングはチェック)", - "Slot No": "スロット番号", - "Slot Status": "スロット状態", - "Slot Test": "スロットテスト", - "Slot updated successfully.": "スロットが正常に更新されました。", - "Smallest number plays first.": "番号が小さい順に再生されます。", - "Some fields need attention": "いくつかの入力項目を確認してください", - "Sort Order": "並び順", - "Special Permission": "特別権限", - "special-permission": "special-permission", - "Specification": "仕様", - "Specifications": "仕様", - "Spring Channel Limit": "スプリングチャネル制限", - "Spring Limit": "スプリング制限", - "Staff Stock": "スタッフ在庫", - "Standby": "スタンバイ", - "standby": "standby", - "Standby Ad": "スタンバイ広告", - "Start Date": "開始日", - "Statistics": "統計", - "Status": "ステータス", - "Sub / Card / Scan": "下位機 / カード機 / スキャン機", - "Status / Temp / Sub / Card / Scan": "状態 / 温度 / 子機 / カード / スキャン", - "Stock": "在庫", - "Stock & Expiry": "在庫と消費期限", - "Stock & Expiry Management": "在庫・期限管理", - "Stock & Expiry Overview": "在庫・期限一覧", - "Stock Management": "在庫管理", - "Stock Quantity": "在庫数", - "Stock:": "在庫:", - "Store Gifts": "ショップギフト", - "Store ID": "ストアID", - "Store Management": "ショップ管理", - "StoreID": "ストアID", - "Sub Account Management": "子アカウント管理", - "Sub Account Roles": "子アカウント権限", - "Sub Accounts": "子アカウント", - "Sub-actions": "サブアクション", - "Sub-machine Status Request": "子機状態", - "Submit Record": "記録を提出", - "Success": "成功", - "success": "成功", - "Super Admin": "Super Admin", - "super-admin": "super-admin", - "Super-admin role cannot be assigned to tenant accounts.": "Super Admin 権限はテナントアカウントに割り当てることはできません。", - "Superseded": "取り消し", - "Superseded by new adjustment": "この指令は新しい調整によって置き換えられました", - "Superseded by new command": "この指令は新しいコマンドによって置き換えられました", - "Survey Analysis": "アンケート分析", - "Syncing Permissions...": "権限を同期中...", - "SYSTEM": "システム", - "System": "システム", - "System & Security Control": "システムとセキュリティ制御", - "System Default": "システムデフォルト", - "System Default (All Companies)": "システムデフォルト(全社)", - "System Default (Common)": "システムデフォルト(共通)", - "System Level": "システムレベル", - "System Official": "システム公式", - "System Reboot": "システム再起動", - "System Role": "システム権限", - "System role name cannot be modified.": "システム権限名は変更できません。", - "System roles cannot be deleted by tenant administrators.": "テナント管理者はシステム権限を削除できません。", - "System roles cannot be modified by tenant administrators.": "テナント管理者はシステム権限を変更できません。", - "System super admin accounts cannot be deleted.": "システム Super Admin アカウントは削除できません。", - "System super admin accounts cannot be modified via this interface.": "システム Super Admin アカウントはこの画面から変更できません。", - "Systems Initializing": "システム初期化中", - "TapPay Integration": "TapPay連携", - "TapPay Integration Settings Description": "TapPay決済連携設定", - "Target": "目標", - "Target Position": "ターゲット位置", - "Tax ID": "税務番号", - "Tax ID (Optional)": "統一編號(任意)", - "Temperature": "温度", - "TermID": "端末ID", - "The image is too large. Please upload an image smaller than 1MB.": "画像サイズが大きすぎます。1MB以下の画像をアップロードしてください。", - "The Super Admin role cannot be deleted.": "Super Admin 権限は削除できません。", - "The Super Admin role is immutable.": "Super Admin 権限は変更できません。", - "The Super Admin role name cannot be modified.": "Super Admin 権限名は変更できません。", - "This is a system administrator role. Its name is locked to ensure system stability.": "これはシステム管理者権限です。システムの安定性を確保するため、名称はロックされています。", - "This role belongs to another company and cannot be assigned.": "この権限は別の会社に属しているため割り当てられません。", - "Time": "時間", - "Time Slots": "時間帯", - "Timer": "タイマー", - "Timestamp": "タイムスタンプ", - "To": "へ", - "to": "to", - "To:": "宛先:", - "Today Cumulative Sales": "本日累積売上高", - "Today's Transactions": "本日の取引数", - "Total": "合計", - "Total Connected": "合計接続数", - "Total Customers": "合計顧客数", - "Total Daily Sales": "本日の総売上", - "Total Gross Value": "総グロス価値", - "Total items": "合計項目数: :count", - "Total Logins": "合計ログイン数", - "Total Selected": "選択済み合計", - "Total Slots": "総スロット数", - "Track Channel Limit": "軌道チャネル制限", - "Track device health and maintenance history": "端末の健全性とメンテナンス履歴を追跡", - "Track Limit": "軌通制限", - "Traditional Chinese": "繁體中文", - "Transfer Audit": "転送監査", - "Transfers": "転送", - "Trigger": "実行", - "Trigger Dispense": "出庫トリガー", - "Trigger Remote Dispense": "リモート出荷を実行", - "Tutorial Page": "チュートリアルページ", - "Type": "タイプ", - "Type to search or leave blank for system defaults.": "検索キーワードを入力するか、空白のままにしてシステムデフォルトを使用します。", - "UI Elements": "UI要素", - "Unauthorized Status": "未認証", - "Uncategorized": "未分類", - "Unified Operational Timeline": "統合運用タイムライン", - "Units": "ユニット", - "Unknown": "不明", - "Unlock": "解除", - "Unlock Now": "今すぐ解除", - "Unlock Page": "ページ解除", - "Update": "更新", - "Update Authorization": "認証更新", - "Update Customer": "顧客更新", - "Update existing role and permissions.": "既存の権限とパーミッションを更新します。", - "Update identification for your asset": "資産の識別名を更新", - "Update Password": "パスワード更新", - "Update Product": "商品更新", - "Update your account's profile information and email address.": "アカウントのプロフィール情報とメールアドレスを更新します。", - "Upload Image": "画像をアップロード", - "Upload New Images": "新しい画像をアップロード", - "Upload Video": "動画をアップロード", - "Uploading new images will replace all existing images.": "新しい画像をアップロードすると、既存の画像はすべて入れ替わります。", - "User": "ユーザー", - "user": "user", - "User Info": "ユーザー情報", - "Username": "ユーザー名", - "Users": "ユーザー", - "Utilization Rate": "稼働率", - "Utilization Timeline": "稼動時序", - "Utilization, OEE and Operational Intelligence": "稼動率、OEE と運用インテリジェンス", - "Utilized Time": "稼動時間", - "Valid Until": "有効期限", - "Validation Error": "バリデーションエラー", - "Vending": "自販機", - "vending": "vending", - "Vending Page": "自販機ページ", - "Venue Management": "会場管理", - "video": "video", - "View Details": "詳細を見る", - "View Inventory": "在庫を見る", - "View Logs": "ログを見る", - "View More": "もっと見る", - "Visit Gift": "来店ギフト", - "visit_gift": "visit_gift", - "vs Yesterday": "前日比", - "Waiting for Payment": "支払い待ち", - "Warehouse List": "倉庫リスト", - "Warehouse List (All)": "倉庫リスト(すべて)", - "Warehouse List (Individual)": "倉庫リスト(個別)", - "Warehouse Management": "倉庫管理", - "Warehouse Permissions": "倉庫権限", - "warehouses": "warehouses", - "Warning": "警告", - "Warning: You are editing your own role!": "警告:自分自身の権限を編集しています!", - "Welcome Gift": "ウェルカムギフト", - "Welcome Gift Status": "ウェルカムギフト状態", - "Work Content": "作業内容", - "Yes, regenerate": "はい、再生成します", - "Yesterday": "昨日", - "You cannot assign permissions you do not possess.": "自分が持っていないパーミッションを割り当てることはできません。", - "You cannot delete your own account.": "自分自身のアカウントを削除することはできません。", - "Your email address is unverified.": "メールアドレスが未認証です。", - "Your recent account activity": "最近のアカウントアクティビティ", - "待填寫": "待填寫", - "Dispensing in progress": "商品搬送中", - "Dispense successful": "搬送成功", - "Slot jammed": "貨道詰まり (K-PDT)", - "Motor not stopped": "モーター停止異常", - "Slot not found": "指定貨道が見つかりません", - "Dispense error (0407)": "搬送異常 (0407)", - "Dispense error (0408)": "搬送異常 (0408)", - "Dispense error (0409)": "搬送異常 (0409)", - "Dispense error (040A)": "搬送異常 (040A)", - "Elevator rising": "昇降機上昇中", - "Elevator descending": "昇降機下降中", - "Elevator rise error": "昇降機上昇異常", - "Elevator descent error": "昇降機下降異常", - "Pickup door closed": "取出口ドア閉鎖", - "Pickup door error": "取出口ドア異常", - "Delivery door opened": "配送口ドア開放", - "Delivery door open error": "配送口ドア開放異常", - "Delivering product": "商品配送中", - "Delivery door closed": "配送口ドア閉鎖", - "Delivery door close error": "配送口ドア閉鎖異常", - "Hopper empty": "ホッパー空", - "Hopper overheated": "ホッパー過熱", - "Hopper heating timeout": "ホッパー加熱タイムアウト", - "Hopper error (0424)": "ホッパー異常 (0424)", - "Microwave door opened": "電子レンジドア開放", - "Microwave door error": "電子レンジドア異常", - "Dispense stopped": "搬送停止", - "Slot normal": "貨道正常", - "Product empty": "品切れ (PDT_EMPTY)", - "Slot empty": "貨道空 (SLOT_EMPTY)", - "Slot not closed": "貨道未閉鎖", - "Slot motor error (0207)": "貨道モーター故障 (0207)", - "Slot motor error (0208)": "貨道モーター故障 (0208)", - "Slot motor error (0209)": "貨道モーター故障 (0209)", - "Hopper empty (0212)": "ホッパー空 (0212)", - "Machine normal": "システム正常", - "Elevator sensor error": "昇降センサー異常", - "Pickup door not closed": "取出口ドア未閉鎖", - "Elevator failure": "昇降システム故障", - "Page 0": "オフライン", - "Page 1": "ホーム", - "Page 2": "販売ページ", - "Page 3": "管理ページ", - "Page 4": "補充ページ", - "Page 5": "チュートリアル", - "Page 6": "購入中", - "Page 7": "ロック中", - "Page 60": "排出成功", - "Page 61": "スロットテスト", - "Page 62": "支払い方法選択", - "Page 63": "支払い待ち", - "Page 64": "排出中", - "Page 65": "レシート", - "Page 66": "パスコード", - "Page 67": "受取コード", - "Page 68": "メッセージ", - "Page 69": "購入キャンセル", - "Page 610": "購入完了", - "Page 611": "来店ギフト", - "Page 612": "排出失敗", - "Door Opened": "機ドア開放", - "Door Closed": "機ドア閉鎖", - "Firmware updated to :version": "ファームウェアがバージョン :version に更新されました", - "Model changed to :model": "モデル変更::model", - "User logged in: :name": "ユーザーログイン::name", - "Login failed: :account": "ログイン失敗::account", - "Unauthorized login attempt: :account": "不許可のログイン試行::account", - "Contract Model": "契約モデル", - "Warranty Service": "保証サービス", - "Software Service": "ソフトウェアサービス", - "Modification History": "変更履歴", - "No history records": "履歴なし", - "Initial contract registration": "初期契約登録", - "Contract information updated": "契約情報更新", - "Warranty Start": "保証開始", - "Warranty End": "保証終了", - "Software Start": "ソフト開始", - "Software End": "ソフト終了", - "Contract History": "契約履歴", - "Unlimited": "無期限", - "Change Note": "変更メモ", - "Log Time": "記録時間", - "Service Periods": "サービス期間", - "Creator": "作成者", - "View Full History": "全履歴を表示", - "Contract Start": "契約開始", - "Contract End": "契約終了", - "Contract History Detail": "契約履歴の詳細", - "by": "作成者:", - "Service Terms": "サービス期間", - "Contract": "契約", - "Warranty": "保証", - "Software": "ソフトウェア", - "Schedule": "スケジュール設定", - "Immediate": "即時", - "Indefinite": "無期限", - "Ongoing": "進行中", - "Waiting": "待機中", - "Publish Time": "公開時間", - "Expired Time": "終了時間", - "Inventory synced with machine": "在庫が機体と同期されました", - "Failed to load tab content": "タブコンテンツの読み込みに失敗しました", - "No machines found": "マシンが見つかりません", - "No products found matching your criteria.": "条件に一致する商品が見つかりませんでした。", - "No categories found.": "カテゴリーが見つかりませんでした。", - "Track Limit (Track/Spring)": "在庫上限 (ベルト/スプリング)", - "Temperature reported: :temp°C": "温度が報告されました::temp°C", - "Temperature updated to :temp°C": "温度が :temp°C に更新されました", - "Transaction processed: :id": "取引が處理されました::id", - "Unknown error": "不明なエラー", - "Remote dispense successful for slot :slot": "スロット :slot の遠隔払い出しに成功しました", - "Machine not found": "機台が見つかりません", - "Command not found": "コマンドが見つかりません", - "Restock report accepted": "補充レポートが受理されました", - "Result reported": "結果が報告されました", - "Error report accepted": "エラーレポートが受理されました", - "Unauthorized: Account not found": "認證失敗:アカウントが見つかりません", - "Unauthorized: Account not authorized for this machine": "認證失敗:このアカウントにはこの機台へのアクセス權限がありません", - "Slot report synchronized success": "スロットレポートの同期に成功しました", - "Error: :message (:code)": "エラー::message (:code)" -} \ No newline at end of file +null \ No newline at end of file diff --git a/lang/zh_TW.json b/lang/zh_TW.json index 0948102..94bfa9e 100644 --- a/lang/zh_TW.json +++ b/lang/zh_TW.json @@ -433,7 +433,7 @@ "LINE_MERCHANT_ID": "LINE Pay 商店代號", "LIVE": "實時", "Live Fleet Updates": "即時數據更新", - "Loading Cabinet...": "正在載入貨道...", + "Loading Cabinet...": "正在載入機台貨盤...", "Loading machines...": "正在載入機台...", "Loading...": "載入中...", "Location": "位置", @@ -619,7 +619,7 @@ "No matching machines": "查無匹配機台", "No materials available": "沒有可用的素材", "No permissions": "無權限項目", - "No records found": "查無操作紀錄", + "No records found": "未找到相關紀錄", "No roles available": "目前沒有角色資料。", "No roles found.": "找不到角色資料。", "No slots found": "未找到貨道資訊", @@ -698,7 +698,7 @@ "Photo Slot": "照片欄位", "PI_MERCHANT_ID": "Pi 拍錢包 商店代號", "Picked up": "領取", - "Picked up Time": "讀取時間", + "Picked up Time": "領取時間", "Pickup Code": "取貨碼", "Pickup Codes": "取貨碼", "Playback Order": "播放順序", @@ -998,7 +998,7 @@ "Spring": "彈簧", "Transfer Audit": "調撥單", "Transfers": "調撥單", - "Trigger": "觸發", + "Trigger": "執行", "Trigger Dispense": "觸發出貨", "Trigger Remote Dispense": "觸發遠端出貨", "Tutorial Page": "教學頁", @@ -1188,5 +1188,14 @@ "Unauthorized: Account not found": "授權失敗:找不到帳號", "Unauthorized: Account not authorized for this machine": "授權失敗:此帳號無存取該機台的權限", "Slot report synchronized success": "貨道狀態同步成功", - "Error: :message (:code)": "錯誤::message (:code)" + "Error: :message (:code)": "錯誤::message (:code)", + "Syncing": "同步中", + "This slot is syncing with the machine. Please wait.": "此貨道正在與機台同步中,請稍候。", + "Loading Data": "載入資料中", + "CASH": "CASH", + "ITEM": "ITEM", + "This slot has a pending update. Please wait for the previous command to complete.": "此貨道已有更新指令在執行中,請等候前一個指令完成。", + "This slot has a pending command. Please wait.": "此貨道已有指令正在執行,請稍後。", + "Out of stock.": "庫存不足。", + "Save error:": "儲存錯誤:" } \ No newline at end of file diff --git a/resources/views/admin/remote/index.blade.php b/resources/views/admin/remote/index.blade.php index eef9997..c470238 100644 --- a/resources/views/admin/remote/index.blade.php +++ b/resources/views/admin/remote/index.blade.php @@ -56,6 +56,7 @@ 'Amount' => __('Amount'), 'Command error:' => __('Command error:'), 'Command has been queued successfully.' => __('Command has been queued successfully.'), + 'Remote Settlement' => __('Remote Settlement'), 'Just now' => __('Just now'), 'mins ago' => __('mins ago'), 'hours ago' => __('hours ago'), @@ -69,8 +70,10 @@ async init() { // Watch for machine data changes to rebuild slot select - this.$watch('selectedMachine.slots', () => { - this.$nextTick(() => this.updateSlotSelect()); + this.$watch('selectedMachine', (val) => { + if (val && val.slots) { + this.$nextTick(() => this.updateSlotSelect()); + } }); // 首次載入時綁定分頁連結 @@ -376,8 +379,12 @@ body: formData }); - if (res.ok) { + const data = await res.json(); + + if (res.ok && data.success) { window.location.href = this.appConfig.indexUrl; + } else { + throw new Error(data.message || 'Unknown error'); } } catch (e) { window.dispatchEvent(new CustomEvent('toast', { @@ -424,7 +431,7 @@ const names = { 'reboot': this.translations['Machine Reboot'], 'reboot_card': this.translations['Card Reader Reboot'], - 'checkout': this.translations['Remote Reboot'], + 'checkout': this.translations['Remote Settlement'], 'lock': this.translations['Lock Page Lock'], 'unlock': this.translations['Lock Page Unlock'], 'change': this.translations['Remote Change'], @@ -452,7 +459,8 @@ translateNote(note) { if (!note) return ''; const translations = { - 'Superseded by new adjustment': this.translations['Superseded by new adjustment'] + 'Superseded by new adjustment': this.translations['Superseded by new adjustment'], + 'Superseded by new command': this.translations['Superseded by new command'] }; return translations[note] || note; }, @@ -485,7 +493,7 @@ if (item.command_type === 'dispense' && item.payload) { let details = `${this.translations['Slot']} ${item.payload.slot_no}`; - if (item.status === 'success' && item.payload.old_stock !== undefined) { + if (item.payload.old_stock !== undefined && item.payload.new_stock !== undefined) { details += `: ${this.translations['Stock']} ${item.payload.old_stock} → ${item.payload.new_stock}`; } return details; @@ -752,7 +760,7 @@
- CASH
+ {{ __('CASH') }}
@@ -799,7 +807,7 @@
- ITEM
+ {{ __('ITEM') }}
@@ -876,6 +884,7 @@
@@ -892,8 +901,7 @@ -
{{ __('No command - history') }}
+
{{ __('No command history') }}
@@ -937,16 +945,14 @@

{{ __('Command Confirmation') }}

-

{{ __('Please - confirm the details below') }}

+

{{ __('Please confirm the details below') }}

- {{ __('Command - Type') }} + {{ __('Command Type') }}
diff --git a/resources/views/admin/remote/partials/tab-history-index.blade.php b/resources/views/admin/remote/partials/tab-history-index.blade.php index 4af2008..f35d54b 100644 --- a/resources/views/admin/remote/partials/tab-history-index.blade.php +++ b/resources/views/admin/remote/partials/tab-history-index.blade.php @@ -69,7 +69,7 @@ value="{{ request('start_date') }}">
@@ -197,6 +197,7 @@
@if($item->note)
- + @if($item->note) @endif diff --git a/resources/views/admin/remote/stock.blade.php b/resources/views/admin/remote/stock.blade.php index 369b213..dd6b948 100644 --- a/resources/views/admin/remote/stock.blade.php +++ b/resources/views/admin/remote/stock.blade.php @@ -190,6 +190,15 @@ }, openEdit(slot) { + if (slot.is_pending) { + window.dispatchEvent(new CustomEvent('toast', { + detail: { + message: '{{ __("This slot is syncing with the machine. Please wait.") }}', + type: 'warning' + } + })); + return; + } this.selectedSlot = slot; this.formData = { stock: slot.stock || 0, @@ -214,10 +223,9 @@ const data = await res.json(); if (data.success) { this.showEditModal = false; - - // Redirect instantly to history tab. - // The success toast will be handled by the session() flash in the controller. window.location.href = "{{ route('admin.remote.stock') }}"; + } else { + throw new Error(data.message || 'Unknown error'); } } catch (e) { window.dispatchEvent(new CustomEvent('toast', { @@ -261,7 +269,7 @@ const names = { 'reboot': {{ Js::from(__('Machine Reboot')) }}, 'reboot_card': {{ Js::from(__('Card Reader Reboot')) }}, - 'checkout': {{ Js::from(__('Remote Reboot')) }}, + 'checkout': {{ Js::from(__('Remote Settlement')) }}, 'lock': {{ Js::from(__('Lock Page Lock')) }}, 'unlock': {{ Js::from(__('Lock Page Unlock')) }}, 'change': {{ Js::from(__('Remote Change')) }}, @@ -331,7 +339,8 @@ translateNote(note) { if (!note) return ''; const translations = { - 'Superseded by new adjustment': {{ Js::from(__('Superseded by new adjustment')) }} + 'Superseded by new adjustment': {{ Js::from(__('Superseded by new adjustment')) }}, + 'Superseded by new command': {{ Js::from(__('Superseded by new command')) }} }; return translations[note] || note; } @@ -583,8 +592,18 @@