[FEAT] 完善 IoT API 規范化、機台管理介面優化與 B005 改為 GET
All checks were successful
star-cloud-deploy-demo / deploy-demo (push) Successful in 1m4s

1. 將 B005 (廣告同步) 從 POST 改為 GET,符合 RESTful 規範。
2. 完善 B009 (庫存回報) 回應規格,加入業務代碼 (200 OK)。
3. API 文件 UI 優化:新增 Method Badge (方法標籤),並修正 JSON 中文/斜線轉義問題。
4. 機台管理介面優化:實作「唯讀庫存與效期」面板,並將日誌圖示改為「👁️」。
5. 標準化 ID 識別邏輯:資料表全面移除對 sku 的依賴,改以 id 為主、barcode 為輔。
6. 新增 Migration:正式移除 sku 欄位並同步 barcode 指向。
7. 更新多語系支援 (zh_TW, en, ja)。
This commit is contained in:
2026-04-07 14:37:57 +08:00
parent b60afc3abe
commit f2147ae6c4
14 changed files with 548 additions and 85 deletions

View File

@@ -5,9 +5,11 @@ namespace App\Http\Controllers\Api\V1\App;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Machine\Machine;
use App\Models\System\User;
use App\Jobs\Machine\ProcessHeartbeat;
use App\Jobs\Machine\ProcessTimerStatus;
use App\Jobs\Machine\ProcessCoinInventory;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Validator;
class MachineController extends Controller
@@ -104,7 +106,7 @@ class MachineController extends Controller
{
$machine = $request->get('machine');
$slots = $machine->slots()->with('product')->get();
// 自動轉 Success: 若機台來撈 B017代表之前的 reload_stock 指令已成功被機台響應
\App\Models\Machine\RemoteCommand::where('machine_id', $machine->id)
->where('command_type', 'reload_stock')
@@ -203,9 +205,11 @@ class MachineController extends Controller
$machine = $request->get('machine');
$advertisements = \App\Models\Machine\MachineAdvertisement::where('machine_id', $machine->id)
->with(['advertisement' => function ($query) {
$query->active();
}])
->with([
'advertisement' => function ($query) {
$query->active();
}
])
->get()
->filter(fn($ma) => $ma->advertisement !== null)
->map(function ($ma) {
@@ -232,7 +236,7 @@ class MachineController extends Controller
't070v03' => (string) ($posIdMap[$ma->position] ?? '1'), // 位置數字改放這裡 (App 會讀這欄當 Flag)
't070v04' => $ma->advertisement->url,
't070v05' => (string) $ma->sort_order,
'raw_pos_weight' => $posWeight[$ma->position] ?? 99,
'raw_pos_weight' => $posWeight[$ma->position] ?? 99,
'raw_sort' => (int) $ma->sort_order
];
})
@@ -241,7 +245,7 @@ class MachineController extends Controller
['raw_sort', 'asc']
])
->values()
->map(function($item) {
->map(function ($item) {
unset($item['raw_pos_weight'], $item['raw_sort']);
return $item;
});
@@ -260,10 +264,51 @@ class MachineController extends Controller
{
$machine = $request->get('machine');
$payload = $request->all();
$account = $payload['account'] ?? null;
// 映射舊版機台回傳格式 (Map legacy machine format)
// t060v00 -> product_id, num -> stock, tid -> slot_no
// 1. 驗證帳號是否存在 (驗證執行補貨的人員身分)
$user = User::where('username', $account)
->orWhere('email', $account)
->first();
if (!$user) {
return response()->json([
'success' => false,
'code' => 403,
'message' => 'Unauthorized: Account not found',
'status' => ''
], 403);
}
// 2. 階層式權限驗證 (遵循 RBAC 多租戶規範)
$isAuthorized = false;
if ($user->isSystemAdmin()) {
// [系統層]:系統管理員可異動所有機台
$isAuthorized = true;
} elseif ($user->is_admin) {
// [公司層]:公司管理員需驗證此機台是否隸屬於該公司
$isAuthorized = ($machine->company_id === $user->company_id);
} else {
// [人員層]:一般人員需檢查 machine_user 授權表
$isAuthorized = $user->machines()->where('machine_id', $machine->id)->exists();
}
if (!$isAuthorized) {
return response()->json([
'success' => false,
'code' => 403,
'message' => 'Unauthorized: Account not authorized for this machine',
'status' => ''
], 403);
}
// 3. 映射舊版機台回傳格式 (Map legacy machine format)
// 支持單個物件 data: {} 或 陣列 data: [{}] (Handle both single object and array)
$legacyData = $payload['data'] ?? [];
if (Arr::isAssoc($legacyData)) {
$legacyData = [$legacyData];
}
$mappedSlots = array_map(function ($item) {
return [
'slot_no' => $item['tid'] ?? null,