513 lines
21 KiB
PHP
513 lines
21 KiB
PHP
<?php
|
||
|
||
namespace App\Controllers;
|
||
use CodeIgniter\RESTful\ResourceController;
|
||
use App\Controllers\BaseController;
|
||
use App\Models\StaffModel;
|
||
use App\Models\ManagerIncentiveFileModel;
|
||
|
||
class StaffController extends ResourceController
|
||
{
|
||
protected $db;
|
||
protected $StaffModel;
|
||
protected $ManagerIncentiveFileModel;
|
||
|
||
public function __construct()
|
||
{
|
||
$this->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";
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
}
|