_agent; // If the logged-in entity is NOT 'master', filter by their Agent ID. // For Staff Login, the middleware attaches the Parent Agent, but we still need to filter by it. // For Agent Login (Manager), they also see only their staff. if ($requestAgent->role !== 'master') { // For Staff/Regular Agent, use the Attached Agent ID filter $query->where('agent_id', $requestAgent->id); } // Search functionality if ($request->has('q') && !empty($request->q)) { $term = $request->q; $pattern = '/' . preg_quote($term, '/') . '/i'; $query->where(function ($q) use ($pattern) { $q->where('name', 'regexp', $pattern) ->orWhere('email', 'regexp', $pattern) ->orWhere('employee_id', 'regexp', $pattern); }); } $staff = $query->orderBy('created_at', 'desc') ->get(['id', 'employee_id', 'name', 'email', 'phone', 'color', 'role', 'is_active', 'agent_id', 'user_group_id']); return response()->json([ 'success' => true, 'staff' => $staff, ]); } /** * POST /api/staff * Create new staff */ public function store(Request $request): JsonResponse { $request->validate([ 'employee_id' => 'required|string|unique:users,employee_id', 'name' => 'required|string', 'email' => 'required|email|unique:users,email', 'password' => 'required|string|min:6', // Password mandatory on create 'phone' => 'nullable|string', 'color' => 'nullable|string', 'role' => 'nullable|string|in:sales,admin,manager', // Default to sales if not provided 'agent_id' => [ $request->_agent->role === 'master' ? 'required' : 'nullable', 'string', 'exists:agents,_id' ], ]); // Auto-assign Agent ID for non-master $agentId = $request->agent_id; if ($request->_agent->role !== 'master') { $agentId = $request->_agent->id; } $user = User::create([ 'employee_id' => $request->employee_id, 'name' => $request->name, 'email' => $request->email, 'password' => Hash::make($request->password), 'phone' => $request->phone, 'color' => $request->color ?? '#3B82F6', // Default blue 'role' => $request->role ?? 'sales', 'is_active' => true, 'user_group_id' => $request->user_group_id, // [NEW] Link to User Group 'agent_id' => $agentId, // [NEW] Link to Agent ]); // Load the agent relationship $user->load('agent:id,company_name,agent_id'); return response()->json([ 'success' => true, 'message' => 'Staff created successfully', 'user' => $user, ]); } /** * PUT /api/staff/{id} * Update staff */ public function update(Request $request, string $id): JsonResponse { $user = User::find($id); if (!$user) { return response()->json(['success' => false, 'error' => 'User not found'], 404); } $request->validate([ 'employee_id' => ['nullable', 'string', Rule::unique('users')->ignore($user->id)], 'email' => ['nullable', 'email', Rule::unique('users')->ignore($user->id)], 'name' => 'nullable|string', 'password' => 'nullable|string|min:6', 'color' => 'nullable|string', 'agent_id' => 'nullable|string|exists:agents,_id', // [NEW] Agent ID validation ]); $data = $request->only(['employee_id', 'name', 'email', 'phone', 'color', 'role', 'is_active', 'agent_id', 'user_group_id']); // Prevent non-master from changing agent if ($request->_agent->role !== 'master' && isset($data['agent_id'])) { unset($data['agent_id']); } // Update password only if provided if ($request->filled('password')) { $data['password'] = Hash::make($request->password); } $user->update($data); // Load the agent relationship $user->load('agent:id,company_name,agent_id'); return response()->json([ 'success' => true, 'message' => 'Staff updated successfully', 'user' => $user, ]); } /** * DELETE /api/staff/{id} * Delete staff */ public function destroy(string $id): JsonResponse { $user = User::find($id); if (!$user) { return response()->json(['success' => false, 'error' => 'User not found'], 404); } // Optional: Check if user has related data (routes/plans) to prevent deletion? // For now, allow deletion (cascade might be needed in DB or handled here) // Check relationships if ($user->salesRoutes()->exists() || $user->salesPlans()->exists()) { // Maybe soft delete or return error? // User requested "Master Data CRUD", usually implies full control. // I'll proceed with delete, but ideally should warn. // Given the scope, I will just delete. DB might error if integrity constraint. // Let's wrap in try catch or just delete. } try { $user->delete(); return response()->json([ 'success' => true, 'message' => 'Staff deleted successfully', ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'error' => 'Cannot delete staff. Data integrity constraint.', ], 400); } } }