with(['os' => fn($q) => $q->with('host.datacenter.vCenter')->orderBy('version')]) ->when( $request->get('filter'), fn($q, $f) => $q->where('name', 'like', "%{$f}%") ) ->orderBy('name'); if ($request->boolean('all')) { $items = $query->get(); return response()->json([ 'error' => false, 'data' => $items->map(fn($g) => $this->formatGroup($g)), ]); } $perPage = min((int) $request->get('per_page', 15), 100); $paginator = $query->paginate($perPage); return response()->json([ 'error' => false, 'data' => [ 'items' => collect($paginator->items())->map(fn($g) => $this->formatGroup($g)), 'total' => $paginator->total(), 'per_page' => $paginator->perPage(), 'current_page' => $paginator->currentPage(), 'last_page' => $paginator->lastPage(), ], ]); } public function show(int $id): JsonResponse { $group = OsGroup::withCount('os') ->with(['os' => fn($q) => $q->with('host.datacenter.vCenter')->orderBy('version')]) ->find($id); if (! $group) { return response()->json(['error' => true, 'message' => 'Không tìm thấy nhóm OS.'], 404); } return response()->json(['error' => false, 'data' => $this->formatGroup($group)]); } public function store(Request $request): JsonResponse { $validated = $request->validate([ 'name' => 'required|string|max:255', 'is_active' => 'boolean', ]); $group = OsGroup::create([ 'name' => $validated['name'], 'status' => ($validated['is_active'] ?? true) ? 1 : 0, ]); return response()->json([ 'error' => false, 'message' => 'Tạo nhóm OS thành công.', 'data' => $this->formatGroup($group->load('os')), ], 201); } public function update(Request $request, int $id): JsonResponse { $group = OsGroup::find($id); if (! $group) { return response()->json(['error' => true, 'message' => 'Không tìm thấy nhóm OS.'], 404); } $validated = $request->validate([ 'name' => 'sometimes|required|string|max:255', 'is_active' => 'boolean', ]); $group->update([ 'name' => $validated['name'] ?? $group->name, 'status' => isset($validated['is_active']) ? ($validated['is_active'] ? 1 : 0) : $group->status, ]); return response()->json([ 'error' => false, 'message' => 'Cập nhật nhóm OS thành công.', 'data' => $this->formatGroup($group->fresh(['os'])), ]); } public function destroy(int $id): JsonResponse { $group = OsGroup::withCount('os')->find($id); if (! $group) { return response()->json(['error' => true, 'message' => 'Không tìm thấy nhóm OS.'], 404); } if ($group->os_count > 0) { return response()->json([ 'error' => true, 'message' => "Không thể xoá nhóm đang chứa {$group->os_count} OS. Hãy xoá các OS trước.", ], 422); } $group->delete(); return response()->json(['error' => false, 'message' => 'Xoá nhóm OS thành công.']); } // ── helpers ────────────────────────────────────────────────────────────── private function formatGroup(OsGroup $group): array { return [ 'id' => $group->id, 'name' => $group->name, 'is_active' => (bool) $group->status, 'os_count' => $group->os_count ?? $group->os->count(), 'os_list' => $group->relationLoaded('os') ? $group->os->map(fn($o) => $this->formatOs($o))->values() : [], ]; } private function formatOs(\App\Models\Os $os): array { $host = $os->relationLoaded('host') ? $os->host : null; return [ 'id' => $os->id, 'version' => $os->version, 'template_id' => $os->template_id, 'is_active' => (bool) $os->status, 'os_group_id' => $os->os_group_id, 'module_host_id' => $os->module_host_id, 'host_name' => $host?->name, 'datacenter_name' => $host?->datacenter?->name, 'vcenter_name' => $host?->datacenter?->vCenter?->host, ]; } }