All checks were successful
star-cloud-deploy-demo / deploy-demo (push) Successful in 42s
265 lines
8.5 KiB
PHP
265 lines
8.5 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Models\Machine\Machine;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\View\View;
|
|
|
|
class MachineController extends AdminController
|
|
{
|
|
/**
|
|
* 顯示所有機台列表或效期管理
|
|
*/
|
|
public function index(Request $request): View
|
|
{
|
|
$tab = $request->input('tab', 'list');
|
|
$per_page = $request->input('per_page', 10);
|
|
|
|
$query = Machine::query();
|
|
|
|
// 搜尋:名稱或序號
|
|
if ($search = $request->input('search')) {
|
|
$query->where(function ($q) use ($search) {
|
|
$q->where('name', 'like', "%{$search}%")
|
|
->orWhere('serial_no', 'like', "%{$search}%");
|
|
});
|
|
}
|
|
|
|
if ($tab === 'list') {
|
|
$machines = $query->when($request->status, function ($query, $status) {
|
|
return $query->where('status', $status);
|
|
})
|
|
->latest()
|
|
->paginate($per_page)
|
|
->withQueryString();
|
|
|
|
return view('admin.machines.index', compact('machines', 'tab'));
|
|
} else {
|
|
// 效期管理模式:獲取機台及其貨道統計
|
|
$machines = $query->withCount(['slots as total_slots'])
|
|
->withCount(['slots as expired_count' => function ($q) {
|
|
$q->where('expiry_date', '<', now()->toDateString());
|
|
}])
|
|
->withCount(['slots as pending_count' => function ($q) {
|
|
$q->whereNull('expiry_date');
|
|
}])
|
|
->withCount(['slots as warning_count' => function ($q) {
|
|
$q->whereBetween('expiry_date', [now()->toDateString(), now()->addDays(7)->toDateString()]);
|
|
}])
|
|
->latest()
|
|
->paginate($per_page)
|
|
->withQueryString();
|
|
|
|
return view('admin.machines.index', compact('machines', 'tab'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 顯示特定機台的日誌與詳細資訊
|
|
*/
|
|
public function show(int $id): View
|
|
{
|
|
$machine = Machine::with(['logs' => function ($query) {
|
|
$query->latest()->limit(50);
|
|
}])->findOrFail($id);
|
|
|
|
return view('admin.machines.show', compact('machine'));
|
|
}
|
|
|
|
|
|
/**
|
|
* AJAX: 取得機台抽屜面板所需的歷程日誌
|
|
*/
|
|
public function logsAjax(Request $request, Machine $machine)
|
|
{
|
|
$per_page = $request->input('per_page', 10);
|
|
|
|
$startDate = $request->get('start_date', now()->format('Y-m-d'));
|
|
$endDate = $request->get('end_date', now()->format('Y-m-d'));
|
|
|
|
$logs = $machine->logs()
|
|
->when($request->level, function ($query, $level) {
|
|
return $query->where('level', $level);
|
|
})
|
|
->whereDate('created_at', '>=', $startDate)
|
|
->whereDate('created_at', '<=', $endDate)
|
|
->when($request->type, function ($query, $type) {
|
|
return $query->where('type', $type);
|
|
})
|
|
->latest()
|
|
->paginate($per_page);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => $logs->items(),
|
|
'pagination' => [
|
|
'total' => $logs->total(),
|
|
'current_page' => $logs->currentPage(),
|
|
'last_page' => $logs->lastPage(),
|
|
]
|
|
]);
|
|
}
|
|
|
|
|
|
/**
|
|
* AJAX: 取得特定帳號的機台分配狀態
|
|
*/
|
|
public function getAccountMachines(\App\Models\System\User $user)
|
|
{
|
|
$currentUser = auth()->user();
|
|
|
|
// 安全檢查:只能操作自己公司的帳號(除非是系統管理員)
|
|
if (!$currentUser->isSystemAdmin() && $user->company_id !== $currentUser->company_id) {
|
|
return response()->json(['error' => 'Unauthorized'], 403);
|
|
}
|
|
|
|
// 取得該公司所有機台 (限定 company_id 以實作資料隔離)
|
|
$machines = Machine::where('company_id', $user->company_id)
|
|
->get(['id', 'name', 'serial_no']);
|
|
|
|
$assignedIds = $user->machines()->pluck('machines.id')->toArray();
|
|
|
|
return response()->json([
|
|
'user' => $user,
|
|
'machines' => $machines,
|
|
'assigned_ids' => $assignedIds
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* AJAX: 儲存特定帳號的機台分配
|
|
*/
|
|
public function syncAccountMachines(Request $request, \App\Models\System\User $user)
|
|
{
|
|
$currentUser = auth()->user();
|
|
|
|
// 安全檢查
|
|
if (!$currentUser->isSystemAdmin() && $user->company_id !== $currentUser->company_id) {
|
|
return response()->json(['error' => 'Unauthorized'], 403);
|
|
}
|
|
|
|
$request->validate([
|
|
'machine_ids' => 'nullable|array',
|
|
'machine_ids.*' => 'exists:machines,id'
|
|
]);
|
|
|
|
// 加固驗證:確保所有機台 ID 都屬於該使用者的公司
|
|
if ($request->has('machine_ids')) {
|
|
$machineIds = array_unique($request->machine_ids);
|
|
$validCount = Machine::where('company_id', $user->company_id)
|
|
->whereIn('id', $machineIds)
|
|
->count();
|
|
|
|
if ($validCount !== count($machineIds)) {
|
|
return response()->json(['error' => 'Invalid machine IDs provided.'], 422);
|
|
}
|
|
}
|
|
|
|
$user->machines()->sync($request->machine_ids ?? []);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => __('Permissions updated successfully.'),
|
|
'assigned_machines' => $user->machines()->select('machines.id', 'machines.name', 'machines.serial_no')->get()
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 機台使用率統計
|
|
*/
|
|
public function utilization(Request $request): View
|
|
{
|
|
// 取得當前使用者有權限的所有機台 (已透過 Global Scope 過濾)
|
|
$machines = Machine::all();
|
|
|
|
$date = $request->get('date', now()->toDateString());
|
|
$service = app(\App\Services\Machine\MachineService::class);
|
|
$fleetStats = $service->getFleetStats($date);
|
|
|
|
return view('admin.machines.utilization', [
|
|
'machines' => $machines,
|
|
'fleetStats' => $fleetStats,
|
|
'compactMachines' => $machines->map(fn($m) => [
|
|
'id' => $m->id,
|
|
'name' => $m->name,
|
|
'serial_no' => $m->serial_no,
|
|
'status' => $m->status
|
|
])->values()
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* AJAX: 取得機台所有貨道資訊 (供效期管理視覺化圖表使用)
|
|
*/
|
|
public function slotsAjax(Machine $machine)
|
|
{
|
|
$slots = $machine->slots()->with('product:id,name,image')->orderByRaw('CAST(slot_no AS UNSIGNED) ASC')->get();
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'machine' => $machine->only(['id', 'name', 'serial_no']),
|
|
'slots' => $slots
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* AJAX: 更新貨道效期
|
|
*/
|
|
public function updateSlotExpiry(Request $request, Machine $machine)
|
|
{
|
|
$request->validate([
|
|
'slot_no' => 'required|integer',
|
|
'expiry_date' => 'nullable|date',
|
|
'apply_all_same_product' => 'boolean'
|
|
]);
|
|
|
|
$slotNo = $request->slot_no;
|
|
$expiryDate = $request->expiry_date;
|
|
$applyAll = $request->apply_all_same_product ?? false;
|
|
|
|
$slot = $machine->slots()->where('slot_no', $slotNo)->firstOrFail();
|
|
$slot->update(['expiry_date' => $expiryDate]);
|
|
|
|
if ($applyAll && $slot->product_id) {
|
|
$machine->slots()
|
|
->where('product_id', $slot->product_id)
|
|
->update(['expiry_date' => $expiryDate]);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => __('Expiry updated successfully.')
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 取得機台統計數據 (AJAX)
|
|
*/
|
|
public function utilizationData(Request $request, $id = null)
|
|
{
|
|
$date = $request->get('date', now()->toDateString());
|
|
$service = app(\App\Services\Machine\MachineService::class);
|
|
|
|
if ($id) {
|
|
$machine = Machine::findOrFail($id);
|
|
$stats = $service->getUtilizationStats($machine, $date);
|
|
} else {
|
|
$stats = $service->getFleetStats($date);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => $stats
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 機台維護紀錄 (開發中)
|
|
*/
|
|
public function maintenance(Request $request): View
|
|
{
|
|
return view('admin.machines.index', ['machines' => Machine::paginate(1)]); // Placeholder
|
|
}
|
|
}
|