db = \Config\Database::connect(); $this->StaffModel = new StaffModel(); $this->ManagerIncentiveFileModel = new ManagerIncentiveFileModel(); } // List of all Staffs public function staffList() { try{ $manager_id = $this->request->getGet('manager_id'); $handler_id = $this->request->getGet('handler_id'); if(!empty($manager_id)) { $data = $this->StaffModel->select('partner_staff.* , R.role') ->join('partner_role_master R', 'R.id = partner_staff.role_id', 'left') ->where('partner_staff.manager_id' , $manager_id ) ->whereIn('partner_staff.role_id' , [1,2,3,4] ) ->findAll(); }else if(!empty($handler_id)){ $data = $this->StaffModel->select('partner_staff.* , R.role') ->join('partner_role_master R', 'R.id = partner_staff.role_id', 'left') ->where("JSON_CONTAINS(partner_staff.handler_id, '\"$handler_id\"')") // ->where('partner_staff.handler_id' , $handler_id ) ->findAll(); } return $this->respond(['status' => 'success', 'code' => 200, 'data' => $data], 200); } catch (\Exception $e) { return $this->respond(['status' => 'failed', 'code' => 500, 'data' => $e->getMessage()], 500); } } public function staffListForEnquiryAssignDropdown() { try{ $handler_id = $this->request->getGet('handler_id'); $manager_id = $this->request->getGet('manager_id'); $data = []; if(!empty($manager_id)) { $staffData = $this->db->table('partner_staff ps') ->select(" ps.id, ps.name, R.role, -- today's assigned count SUM(CASE WHEN DATE(pe.created_on) = CURDATE() THEN 1 ELSE 0 END) AS today_assigned, -- not completed today SUM(CASE WHEN pe.enquiry_status != 'Completed' AND DATE(pe.created_on) = CURDATE() THEN 1 ELSE 0 END) AS total_pending ") ->join('partner_role_master R', 'R.id = ps.role_id', 'left') ->join('partner_enquiry pe', 'pe.assigned_to = ps.id AND pe.is_active = 1', 'left') ->where('ps.manager_id', $manager_id) ->groupStart() ->whereIn('ps.role_id', [2,3]) ->orWhere('ps.id', $manager_id) ->groupEnd() ->where('ps.is_active', 1) ->groupBy('ps.id') ->orderBy('ps.name', 'ASC') ->get() ->getResultArray(); // $staffData = $this->StaffModel->select('partner_staff.id, partner_staff.name , R.role') // ->join('partner_role_master R', 'R.id = partner_staff.role_id', 'left') // ->where('partner_staff.manager_id' , $manager_id ) // ->where('partner_staff.role_id' , 3 ) // ->where('partner_staff.is_active' , 1 ) // ->findAll(); // $managerData = $this->StaffModel->select('partner_staff.id, partner_staff.name , R.role') // ->join('partner_role_master R', 'R.id = partner_staff.role_id', 'left') // ->where('partner_staff.id', $manager_id ) // ->where('partner_staff.is_active' , 1 ) // ->first(); // $data = array_values(array_unique(array_merge($staffData, [$managerData]), SORT_REGULAR)); }else if(!empty($handler_id)){ $staffData = $this->db->table('partner_staff ps') ->select(" ps.id, ps.name, R.role, -- today's assigned count SUM(CASE WHEN DATE(pe.created_on) = CURDATE() THEN 1 ELSE 0 END) AS today_assigned, -- not completed today SUM(CASE WHEN pe.enquiry_status != 'Completed' AND DATE(pe.created_on) = CURDATE() THEN 1 ELSE 0 END) AS total_pending ") ->join('partner_role_master R', 'R.id = ps.role_id', 'left') ->join('partner_enquiry pe', 'pe.assigned_to = ps.id AND pe.is_active = 1', 'left') ->groupStart() ->where("JSON_CONTAINS(ps.handler_id, '\"$handler_id\"')") ->orWhere('ps.id', $handler_id) ->groupEnd() ->where('ps.is_active', 1) ->groupBy('ps.id') ->orderBy('ps.name', 'ASC') ->get() ->getResultArray(); // $staffData = $this->StaffModel->select('partner_staff.id, partner_staff.name , R.role') // ->join('partner_role_master R', 'R.id = partner_staff.role_id', 'left') // ->where("JSON_CONTAINS(partner_staff.handler_id, '\"$handler_id\"')") // ->where('partner_staff.role_id' , 3 ) // ->where('partner_staff.is_active' , 1 ) // ->findAll(); // $handlerData = $this->StaffModel->select('partner_staff.id, partner_staff.name , R.role') // ->join('partner_role_master R', 'R.id = partner_staff.role_id', 'left') // ->where('partner_staff.id', $handler_id ) // ->where('partner_staff.is_active' , 1 ) // ->first(); // $data = array_values(array_unique(array_merge($staffData, [$handlerData]), SORT_REGULAR)); } return $this->respond(['status' => 'success', 'code' => 200, 'data' => $staffData], 200); } catch (\Exception $e) { return $this->respond(['status' => 'failed', 'code' => 500, 'data' => $e->getMessage()], 500); } } public function handlerListForStaffCreationDropdown() { try{ $manager_id = $this->request->getGet('manager_id'); $data = $this->StaffModel->select('partner_staff.id, partner_staff.name , R.role') ->join('partner_role_master R', 'R.id = partner_staff.role_id', 'left') ->where('partner_staff.manager_id' , $manager_id ) ->where('partner_staff.role_id' , 2 ) ->where('partner_staff.is_active' , 1 ) ->findAll(); return $this->respond(['status' => 'success', 'code' => 200, 'data' => $data], 200); } catch (\Exception $e) { return $this->respond(['status' => 'failed', 'code' => 500, 'data' => $e->getMessage()], 500); } } // Find a Staff public function findStaff() { try{ $id = $this->request->getGet('id'); $record = $this->StaffModel->find((int)$id); if (!$record) { return $this->respond(['status' => 'failed', 'code' => 404, 'data' => []], 200); } return $this->respond(['status' => 'success', 'code' => 200, 'data' => $record], 200); } catch (\Exception $e) { return $this->respond(['status' => 'failed', 'code' => 500, 'data' => $e->getMessage()], 500); } } // CREATE Staff public function createStaff() { try{ $data = $this->request->getJSON(true); // 1️⃣ Either email or mobile must be present if (empty($data['email']) && empty($data['mobile'])) { return $this->respond([ 'status' => 'failed', 'code' => 422, 'data' => [ 'message' => 'Either email or mobile is required' ] ], 200); } // 2️⃣ Validation rules $rules = [ 'email' => 'permit_empty|valid_email|is_unique[partner_staff.email]', 'mobile' => 'permit_empty|numeric|min_length[10]|max_length[15]|is_unique[partner_staff.mobile]', 'name' => 'required', 'role_id'=> 'required' ]; $messages = [ 'email' => [ 'valid_email' => 'Invalid email format', 'is_unique' => 'Email already exists' ], 'mobile' => [ 'numeric' => 'Mobile must be numeric', 'min_length'=> 'Mobile must be at least 10 digits', 'max_length'=> 'Mobile must be at most 15 digits', 'is_unique' => 'Mobile number already exists' ], 'name' => [ 'required' => 'Name is required' ], 'role_id' => [ 'required' => 'Role is required' ] ]; if (!$this->validate($rules, $messages)) { return $this->respond([ 'status' => 'failed', 'code' => 422, 'data' => $this->validator->getErrors() ], 200); } // 3️⃣ Insert data $insertData = [ 'name' => $data['name'], 'email' => $data['email'] ?? null, 'mobile' => $data['mobile'] ?? null, 'role_id' => $data['role_id'], 'manager_id' => $data['manager_id'] ?? null, 'handler_id' => (isset($data['handler_id']) && !empty($data['handler_id'])) ? json_encode($data['handler_id']) : json_encode([]), 'created_by' => $data['created_by'] ]; $this->StaffModel->insert($insertData); return $this->respond(['status' => 'success', 'code' => 200, 'data' => []], 200); } catch (\Exception $e) { return $this->respond(['status' => 'failed', 'code' => 500, 'data' => $e->getMessage()], 500); } } // UPDATE Staff public function updateStaff() { try{ $data = $this->request->getJSON(true); if (!isset($data['id'])) { return $this->respond(['status' => 'failed', 'code' => 200, 'data' => 'ID Required'], 200); } $id = $data['id']; // check if Staff exists $Staff = $this->StaffModel->find((int)$id); if (!$Staff) { return $this->respond(['status' => 'failed', 'code' => 200, 'data' => 'Date Not Found'], 200); } $updateData = [ 'name' => $data['name'], 'email' => $data['email'], 'mobile' => $data['mobile'], 'role_id' => $data['role_id'], 'handler_id' => (isset($data['handler_id']) && !empty($data['handler_id'])) ? json_encode($data['handler_id']) : json_encode([]), 'updated_by' => $data['updated_by'], ]; $this->StaffModel->update($id, $updateData); return $this->respond(['status' => 'success', 'code' => 200, 'data' => []], 200); } catch (\Exception $e) { return $this->respond(['status' => 'failed', 'code' => 500, 'data' => $e->getMessage()], 500); } } // ACTIVATE / DEACTIVATE Staff public function changeStaffStatus() { try { $data = $this->request->getJSON(true); // validate inputs if (!isset($data['id']) || !isset($data['is_active'])) { return $this->respond(['status' => 'failed', 'code' => 200,'data' => 'ID and Status are required'], 200); } $id = $data['id']; $is_active = (int) $data['is_active']; // 0 or 1 $status = ($is_active == 1) ? 0 : 1; // check if Staff exists $Staff = $this->StaffModel->find((int)$id); if (!$Staff) { return $this->respond(['status' => 'failed','code' => 200, 'data' => 'Staff not found'], 200); } // update status $this->StaffModel->update($id, ['is_active' => $status]); return $this->respond([ 'status' => 'success', 'code' => 200,'data' => "Staff status updated"], 200); } catch (\Exception $e) { return $this->respond(['status' => 'failed','code' => 500,'data' => $e->getMessage()], 500); } } // List of all manager incentive files public function managerIncentiveFileList() { try{ $manager_id = $this->request->getGet('manager_id'); $data = $this->ManagerIncentiveFileModel->where('manager_id',$manager_id)->where('is_active',1)->findAll(); return $this->respond(['status' => 'success', 'code' => 200, 'data' => $data], 200); } catch (\Exception $e) { return $this->respond(['status' => 'failed', 'code' => 500, 'data' => $e->getMessage()], 500); } } // Download manager incentive file (proxy to external app) public function downloadManagerIncentiveFile() { try { $id = $this->request->getGet('id'); // External API URL $url = "https://venbait.in/nhance/dev/user/download-incentive-file/" . urlencode($id); // Use CURL request to fetch the file $client = \Config\Services::curlrequest(); $response = $client->get($url); if ($response->getStatusCode() === 200) { // Pass the file contents back as download return $this->response ->setHeader('Content-Type', $response->getHeaderLine('Content-Type')) ->setHeader('Content-Disposition', 'attachment; id="' . basename($id) . '"') ->setBody($response->getBody()); } else { return $this->respond([ 'status' => 'failed', 'code' => 404, 'message' => 'Unable to fetch file from source' ], $response->getStatusCode()); } } catch (\Exception $e) { return $this->respond(['status' => 'failed', 'code' => 500,'data' => $e->getMessage()], 500); } } public function monthlyLoginCount() { $month = $this->request->getGet('month') ?? date('Y-m'); // Default: current month $manager_id = $this->request->getGet('manager_id'); // Extract year-month format (e.g., '2025-10') $startDateTime = date('Y-m-01 00:00:00', strtotime($month)); $endDateTime = date('Y-m-t 23:59:59', strtotime($month)); $db = \Config\Database::connect(); $builder = $db->table('partner_staff_attendance a'); $builder->select('a.staff_id , s.name AS staff_name, DATE_FORMAT(a.login_datetime, "%Y-%m") AS month, COUNT(a.id) AS login_count, s.manager_id'); $builder->join('partner_staff s', 's.id = a.staff_id', 'left'); $builder->where('a.login_datetime >=', $startDateTime); $builder->where('a.login_datetime <=', $endDateTime); $builder->where('a.manager_id ', $manager_id); $builder->groupBy('a.staff_id'); $builder->groupBy('month'); $builder->orderBy('s.name', 'ASC'); $result = $builder->get()->getResultArray(); foreach ($result as $key => $value) { // Skip (remove) rows that don't match the requested manager_id if (!empty($manager_id) && $value['manager_id'] != $manager_id) { unset($result[$key]); continue; } $result[$key]['month'] = date('M Y', strtotime($value['month'])); } // Reindex array so JSON returns as an array, not an object $result = array_values($result); return $this->respond(['status' => 'success', 'code' => 200, 'month' => $month, 'data' => $result], 200); } public function staffLoggedDays() { $staffId = $this->request->getGet('staff_id'); $month = $this->request->getGet('month') ?? date('Y-m'); $startDateTime = date('Y-m-01 00:00:00', strtotime($month)); $endDateTime = date('Y-m-t 23:59:59', strtotime($month)); $db = \Config\Database::connect(); $builder = $db->table('partner_staff_attendance'); $builder->select('id, DATE(login_datetime) AS login_date, MIN(login_datetime) AS first_login, MAX(logout_datetime) AS last_logout'); $builder->where('staff_id', $staffId); $builder->where('login_datetime >=', $startDateTime); $builder->where('login_datetime <=', $endDateTime); $builder->groupBy('DATE(login_datetime)'); $builder->orderBy('login_date', 'ASC'); $records = $builder->get()->getResultArray(); //get Staff name $staff = $this->StaffModel->where('id',$staffId)->first(); // Format result $formatted = []; foreach ($records as $row) { $formatted[] = [ 'name' => $staff['name'], 'id' => $row['id'], 'date' => $row['first_login'] ? date('d-m-Y', strtotime($row['first_login'])) : null, 'login_time' => $row['first_login'] ? date('h:i A', strtotime($row['first_login'])) : null, 'logout_time' => $row['last_logout'] ? date('h:i A', strtotime($row['last_logout'])) : null, 'no_of_logged_in_time' => $this->getLoginDuration($row['first_login'], $row['last_logout']) ]; } return $this->respond([ 'status' => 'success', 'code' => 200, 'month' => $month, 'data' => $formatted ], 200); } private function getLoginDuration($login, $logout) { if (empty($login) || empty($logout)) { return null; } $loginTime = strtotime($login); $logoutTime = strtotime($logout); $diffSeconds = $logoutTime - $loginTime; if ($diffSeconds < 0) { return null; // Invalid data } $hours = floor($diffSeconds / 3600); $minutes = floor(($diffSeconds % 3600) / 60); if ($hours > 0 && $minutes > 0) { return "{$hours}h {$minutes}m"; } elseif ($hours > 0) { return "{$hours}h"; } elseif ($minutes > 0) { return "{$minutes}m"; } else { return "0m"; } } }