thzMasterModel = new ThzMasterModel(); $this->thzMasterNotesModel = new ThzMasterNotesModel(); $this->thzTypeModel = new thzTypeModel(); $this->thzHistoryModel = new ThzHistoryModel(); $this->thzControllerCleaner = new ThzControllerCleaner(); $this->userModel = new UserModel(); $this->clientPolicyModel = new ClientPolicyModel(); $this->clientModel = new ClientModel(); $this->cientRmModel = new ClientRMModel(); $this->ticketMailTemplateModel = new TicketMailTemplateModel(); $this->myLogger = \Config\Services::mylogger(); } public function index() { // } public function ticketSave() { try { $rules = [ 'client_id' => [ 'rules' => 'permit_empty|integer', 'errors' => [ 'integer' => 'Invalid client selected' ] ], 'mobile' => [ 'rules' => 'required|regex_match[/^[0-9]{10}$/]', 'errors' => [ 'required' => 'Mobile number is required', 'regex_match' => 'Mobile number must be exactly 10 digits' ] ], 'name' => [ 'rules' => 'required|min_length[3]|max_length[100]|alpha_space', 'errors' => [ 'required' => 'Name is required', 'min_length' => 'Name must be at least 3 characters', 'alpha_space'=> 'Name can contain only letters and spaces' ] ], 'email' => [ 'rules' => 'required|valid_email|max_length[150]', 'errors' => [ 'required' => 'Email is required', 'valid_email' => 'Please enter a valid email address' ] ], 'empcode' => [ 'rules' => 'permit_empty|max_length[50]', 'errors' => [ 'max_length' => 'Employee code is too long' ] ], 'ticket_type' => [ 'rules' => 'required|in_list[Sales,Service]', 'errors' => [ 'required' => 'Ticket Type is required', 'in_list' => 'Invalid Ticket Type selected' ] ], 'assign_to' => [ 'rules' => 'permit_empty|integer', 'errors' => [ 'integer' => 'Invalid assignee selected' ] ], 'subject' => [ 'rules' => 'required|min_length[5]|max_length[150]', 'errors' => [ 'required' => 'Subject is required', 'min_length' => 'Subject must be at least 5 characters', 'max_length' => 'Subject cannot exceed 150 characters' ] ], 'message' => [ 'rules' => 'required|min_length[10]|max_length[1500]', 'errors' => [ 'required' => 'Message is required', 'min_length' => 'Message must be at least 10 characters', 'max_length' => 'Message cannot exceed 1500 characters' ] ], 'status' => [ 'rules' => 'permit_empty|in_list[Open,In Progress,Resolved,Closed]', 'errors' => [ 'in_list' => 'Invalid ticket status' ] ], ]; if (!$this->validate($rules)) { return $this->response->setStatusCode(400)->setJSON([ 'status' => false, 'message' => 'Input validation failed', 'code' => 400, 'errors' => $this->validator->getErrors() ]); } $request_post_data = $this->request->getPost(); $data = sanitizeInputArrayAdvanced($request_post_data); $references = ""; if (!empty($data['thz_id'])) { $text = "update"; // here insert history Status. $old = $this->thzMasterModel->where('thz_id', $data['thz_id'])->get()->getRowArray(); $result = $this->updateTicket($data); $references = ($old && isset($data['status'])) ? $this->handleTicketHistory($old, $data) : "No Details" ; $updateID = $data['thz_id']; } else { $text = "create"; if(!isset($data['assign_to'])){ $data['assign_to'] = $this->getAcmIdUsingClientId($data['client_id'] ?? null); } $insertID = $this->insertTicket($data); $result = true; $references = ""; } $id = isset($insertID) && !empty($insertID) ? $insertID : $updateID; $emailNotificationResult = $this->ticketSaveNotification($data, $insertOrUpdate = $text, $id); $this->myLogger->logme('error', 'emailNotificationResult: ' . json_encode($emailNotificationResult)); return $this->response->setJSON([ 'status' => $result ? 'success' : 'error', 'message' => $result ? "Ticket {$text}d successfully " : "Unable to {$text} ticket. Please try again.", 'notification' => $emailNotificationResult ? 'Email Notification Success..!!' : 'Email Notification Failed..!!', 'ref' => $references ])->setStatusCode($result ? 200 : 400); } catch (\Throwable $e) { return handle_exception($e, $this->myLogger, $this->response); } } public function ticketList() { // try { $returnType = strtolower($this->request->getGet('return_type') ?? 'api'); $data = $this->request->getGet(); if ($returnType === 'web' && in_array(get_role_id(), [4])) { $data['assign_to'] = $data['assign_to'] ?? get_session_userid(); } if ($returnType === 'web' && in_array(get_role_id(), [3])) { $data['clientIds'] = $this->clientModel->getClientIdBasedonLoggedInSessionID(); } $tickets = $this->fetchTicketsBasedOnrole($data); if ($returnType === 'api') { if (empty($tickets)) { $this->myLogger->logme('error', 'empty tickets in ticket list: ' . json_encode($tickets)); return $this->response->setJSON([ 'status' => 'error','message' => 'No tickets found'])->setStatusCode(404); } } else { $data['ticket_data'] = $tickets; $data['assignee'] = $this->userModel->where('is_active', 1)->whereIn('role', ['3', '4'])->findAll(); // enga 5-"head" and 1-"admin" assign pannvaga so dropdown la varakudhathu , 2-"manager l2 " - ivangalum assign pannalam. 3,4 remain person varannum dropdown la. // Roles - 5 (Head) , 1 (Admin) and 2 (Manager) are already assigned to others, so the dropdown should not be shown. // 3 (Account Manager) and 4 (Staff) should be selectable, so have to show in dropdown . $data['client_list'] = $this->clientModel->getCreatedByUserName(); $data['ticket_type'] = $this->thzTypeModel->where('is_active', 1)->findAll(); $data['tab_name'] = "Tickets"; $data['page_name'] = "Tickets"; return $this->loadLayout('thz_list', $data); } return $this->response->setJSON([ 'status' => 'success', 'data' => $tickets, ])->setStatusCode(200); // } catch (\Throwable $e) { // return handle_exception($e, $this->myLogger, $this->response); // } } public function ticketConversationSave() { try { $rules = [ 'notes' => [ 'rules' => 'required|string|min_length[1]|max_length[1500]', 'errors' => [ 'required' => 'Notes is required', 'string' => 'Notes must be valid text', 'min_length' => 'Notes cannot be empty', 'max_length' => 'Notes cannot exceed 1500 characters' ] ], ]; if (!$this->validate($rules)) { return $this->response->setStatusCode(400)->setJSON([ 'status' => false, 'message' => 'Input validation failed', 'code' => 400, 'errors' => $this->validator->getErrors() ]); } $request_post_data = $this->request->getPost(); $data = sanitizeInputArrayAdvanced($request_post_data); $data['notes_type'] = $data['notes_type'] ?? 'External'; $result = $this->thzMasterNotesModel->insert($data); if (empty($result)) { $this->myLogger->logme('error', 'Ticket conversation insert failed..!!: ' . json_encode($result)); throw new \RuntimeException('No tickets found', 404); } $emailNotificationResult = ($data['notes_type'] === "External") ? $this->ticketConversationSaveNotification($data) : false; return $this->response->setJSON([ 'status' => $result ? 'success' : 'error', 'message' => $result ? "Ticket Notes created successfully" : "Unable to create ticket notes. Please try again.", 'notification' => $emailNotificationResult ? 'Email Notification Success..!!' : 'Email Notification Failed Or No Need..!!' ])->setStatusCode($result ? 200 : 400); } catch (\Throwable $e) { return handle_exception($e, $this->myLogger, $this->response); } } public function ticketAutoFetchDetails() { try { $data = $this->request->getPost(); $client_id = $data['client_id'] ?? null; $mobile = $data['mobile'] ?? null; if ($client_id && $mobile) { $details = $this->thzMasterModel->ticketAutoFetchDetails($client_id, $mobile); if (empty($details)) { $this->myLogger->logme('error', 'empty AutoFetchDetails for client_id : ' . json_encode($client_id)); throw new \RuntimeException('No Data found', 400); } $policyIds = array_filter(array_column($details, 'policy_id')); $clientPolicy = !empty($policyIds) ? $this->clientPolicyModel->whereIn('id', $policyIds)->where('is_active', 1)->get()->getResultArray() : []; $result['client_details'] = $details; $result['policy_details'] = $clientPolicy ?? []; } else { throw new \RuntimeException('Client and Mobile Not found', 400); } return $this->response->setJSON(['status' => 'success', 'data' => $result])->setStatusCode(200); } catch (\Throwable $e) { return handle_exception($e, $this->myLogger, $this->response); } } public function ticketConversationList() { $data = $this->request->getGet(); $returnType = strtolower($this->request->getGet('return_type') ?? 'api'); $thz_id = $data['thz_id'] ?? null; $ticketType = $data['notes_type'] ?? 'External'; if ($thz_id) { $result['master'] = $this->thzMasterModel ->select('thz_master.*, user_profiles.first_name as assignee_name') ->join('user_profiles', 'user_profiles.id = thz_master.assign_to', 'left') ->where('thz_master.thz_id', $thz_id) ->findAll(); $clientId = $result['master'][0]['client_id']; $accManagerId = $this->getAcmIdUsingClientId($clientId ?? null); $accManager = $this->userModel->find((int)$accManagerId); if (!empty($result['master'])) { $notes = $this->thzMasterNotesModel->ticketConversationList($thz_id, $returnType); $accManagerName = $accManager['first_name'] ?? ''; foreach ($notes as &$note) { if (empty($note['name'])) { $note['name'] = $accManagerName; } } unset($note); $result['notes'] = !empty($notes) ? $notes : []; } else { $this->myLogger->logme('error', 'No tickets found for ticket id ' . json_encode($thz_id)); throw new \RuntimeException('No tickets found', 400); } } else { // return $this->response->setJSON((['status' => 'error', 'message' => 'No tickets found']))->setStatusCode(404); throw new \RuntimeException('No tickets found', 404); } if ($returnType === 'api') { try { return $this->response->setJSON((['status' => 'success', 'data' => $result]))->setStatusCode(200); } catch (\Throwable $e) { return handle_exception($e, $this->myLogger, $this->response); } } else { $assign_to = $result['master'][0]['assign_to']; $mobile = $result['master'][0]['mobile']; $toGetPolicyId = (!empty($result['master'][0]['policy_id']) && strtolower($result['master'][0]['policy_id']) !== 'null') ? $result['master'][0]['policy_id'] : ''; $result['related_tickets'] = $this->thzMasterModel ->select('thz_master.*, user_profiles.first_name as assignee_name') ->join('user_profiles', 'user_profiles.id = thz_master.assign_to', 'left') ->where('thz_master.assign_to', $assign_to) ->where('thz_master.mobile', $mobile) ->where('thz_master.thz_id !=', $thz_id) ->where('thz_master.status !=', 'Closed') ->where('thz_master.status !=', 'Resolved') ->findAll(); $result['assignee'] = $this->userModel->where('is_active', 1)->whereIn('role', ['2', '3', '4'])->findAll(); // enga 5-"head" and 1-"admin" assign pannvaga so dropdown la varakudhathu // 2,3,4 remain person varannum. $result['policy_terms'] = $toGetPolicyId ? $this->getPolicyTerms($toGetPolicyId) : ''; $result['ticket_type'] = $this->thzTypeModel->where('is_active', 1)->findAll(); $result['tab_name'] = "Tickets"; $result['page_name'] = "Ticket Details"; return $this->loadLayout('thz_notes', $result); } } public function ticketType() { $method = $this->request->getMethod(); // get, post try { if ($method === 'get') { $types = $this->thzTypeModel->select('id,name,is_active')->where('is_active', 1)->findAll(); if (empty($types)) { $this->myLogger->logme('error', 'No ticket types found '); return $this->response->setJSON(['status' => 'error', 'message' => 'No ticket types found'])->setStatusCode(404); } return $this->response->setJSON(['status' => 'success', 'data' => $types])->setStatusCode(200); } if ($method === 'post') { $data = $this->request->getPost(); if (!empty($data['id'])) { $text = "update"; $result = $this->thzTypeModel->update($data['id'], $data); $updateID = $data['id']; } else { $text = "create"; $insertID = $this->thzTypeModel->insert($data); $result = true; } $id = isset($insertID) && !empty($insertID) ? $insertID : ($updateID ?? null); return $this->response->setJSON([ 'status' => $id ? 'success' : 'error', 'message' => $id ? "Ticket Type {$text}d successfully" : "Unable to {$text} ticket type. Please try again.", 'id' => $id ])->setStatusCode($id ? 200 : 400); } return $this->response->setJSON(['status' => 'error', 'message' => 'Invalid request method'])->setStatusCode(405); } catch (\Throwable $e) { return handle_exception($e, $this->myLogger, $this->response); } } public function ticketHistoryList() { try { $data = $this->request->getGet(); $thz_id = $data['thz_id']; // $details = $this->thzHistoryModal->whereIn('thz_id', $thz_id)->where('is_active', 1)->get()->getResultArray(); $details = $this->thzHistoryModel->select('thz_history.*, user_profiles.first_name as created_name') ->join('user_profiles', 'user_profiles.id = thz_history.created_by', 'left') ->where('thz_history.thz_id', $thz_id)->where('thz_history.is_active', 1) ->orderBy('thz_history.created_at', 'desc') ->get()->getResultArray(); if (empty($details)) { $this->myLogger->logme('error', 'No history details found for ticket id ' . json_encode($thz_id)); throw new \RuntimeException('No History found', 404); } return $this->response->setJSON(['status' => 'success', 'data' => $details])->setStatusCode(200); } catch (\Throwable $e) { return handle_exception($e, $this->myLogger, $this->response); } } /************************************************** PRIVATE FUNCTIONS ********************************************************/ private function fetchTicketsBasedOnrole(array $data): array { // $id = $data['thz_id'] ?? null; $assign_to = $data['assign_to'] ?? null; $mobile = $data['mobile'] ?? null; $clientIds = $data['clientIds'] ?? null; if (!empty($assign_to)) { // Tickets assigned to a staff return $this->thzMasterModel ->select('thz_master.*, user_profiles.first_name as assignee_name') ->join('user_profiles', 'user_profiles.id = thz_master.assign_to', 'left') ->where('thz_master.assign_to', $assign_to) ->orderBy('thz_master.created_at', 'desc') ->findAll(); } // if (!empty($id) && !empty($mobile)) { if (!empty($mobile)) { // Specific ticket by ID and mobile return $this->thzMasterModel ->select('thz_master.*, user_profiles.first_name as assignee_name') ->join('user_profiles', 'user_profiles.id = thz_master.assign_to', 'left') // ->where('thz_id', $id) ->where('thz_master.mobile', $mobile) ->orderBy('thz_master.created_at', 'desc') ->findAll(); } if (!empty($clientIds)) { return $this->thzMasterModel ->select('thz_master.*, user_profiles.first_name as assignee_name') ->join('user_profiles', 'user_profiles.id = thz_master.assign_to', 'left') ->whereIn('thz_master.client_id', $clientIds) ->orderBy('thz_master.created_at', 'desc') ->findAll(); } // All tickets (e.g., for managers) return $this->thzMasterModel ->select('thz_master.*, user_profiles.first_name as assignee_name') ->join('user_profiles', 'user_profiles.id = thz_master.assign_to', 'left') ->orderBy('thz_master.created_at', 'desc') ->findAll(); } private function ticketSaveNotification($data, $insertOrUpdate, $id) { $user_email = $data['email'] ?? null; $assignee_id = $data['assign_to'] ?? null; $assignee_email = $this->findAssigneeEmail($assignee_id); $client_id = $data['client_id'] ?? null; $emailToNotified = [ 'user_email' => $user_email, 'assignee_email' => $assignee_email ]; $ticketId = $id; $result = $this->ticketSaveEmailNotificationBasedOnRole($emailToNotified, $insertOrUpdate, $ticketId, $data, $client_id); return $result; } private function ticketConversationSaveNotification($data) { $thz_id = $data['thz_id']; // thz is alias of ticket $data['subject'] = $this->findSubject($data['thz_id']); $assignee_id = $this->findAssigneeId($data['thz_id']); $user_email = $this->findUserEmail($data['thz_id']); $assignee_email = $this->findAssigneeEmail($assignee_id) ?? ''; $sender_mail = $data['notes_by'] == "User" ? $user_email : $assignee_email; $receiver_mail = $data['notes_by'] == "User" ? $assignee_email : $user_email; $templateName = "ticket_conversation_save_notification"; $to_email = $receiver_mail; $ticketId = $thz_id; // $message = $data['notes'] ?? ''; $this->sendEmail($templateName, $data, $to_email, $ticketId); return true; } private function findAssigneeEmail($assignee_id) { $row = $this->userModel->where('id', $assignee_id)->get()->getRow(); $assigneeEmail = $row ? $row->email : null; return $assigneeEmail ? $assigneeEmail : ""; } private function findAssigneeId($ticketId) { $row = $this->thzMasterModel->where('thz_id', $ticketId)->get()->getRow(); $assigneeId = $row ? $row->assign_to : null; return $assigneeId ? $assigneeId : 0; } private function findUserEmail($ticket_id) { $row = $this->thzMasterModel->where('thz_id', $ticket_id)->get()->getRow(); $email = $row ? $row->email : null; return $email ? $email : " "; } private function findSubject($ticketId) { $row = $this->thzMasterModel->where('thz_id', $ticketId)->get()->getRow(); $subject = $row ? $row->subject : null; return $subject ? $subject : " "; } private function ticketSaveEmailNotificationBasedOnRole($emailToNotified, $insertOrUpdate, $ticketId, $data, $client_id) { $user_email = $emailToNotified['user_email'] ?? null; $assignee_email = $emailToNotified['assignee_email'] ?? null; if (!empty($assignee_email)) { switch ($insertOrUpdate) { case 'update': $this->sendEmail('ticket_save_update_assignee', $data, $assignee_email, $ticketId); break; case 'create': $this->sendEmail('ticket_save_create_assignee', $data, $assignee_email, $ticketId); break; default: # code... break; } } if (!empty($user_email)) { switch ($insertOrUpdate) { case 'update': $data['assigneeAndStatus'] = empty($assignee_email) ? "Not Yet Assigned" : "Assigned With {$assignee_email}"; $this->sendEmail('ticket_save_update_user', $data, $user_email, $ticketId); break; case 'create': $account_manager_email = $this->cientRmModel->findAccountManagerEmail($client_id); $cc = getenv('G_ticketing_system_cc'); $this->myLogger->logme('error', "env for cc G_ticketing_system_cc " . $cc); $template = empty($assignee_email) ? 'ticket_save_create_user_unassigned' : 'ticket_save_create_user_assigned'; if (!empty($assignee_email)) { $data['assignee_email'] = $assignee_email; } $this->sendEmail($template, $data, $user_email, $ticketId); // send to account manager and if it is more than one email also no problem we send to all account managers if (!empty($account_manager_email)) { $this->myLogger->logme('error', "mail sent for account manager " . json_encode($account_manager_email)); $this->sendEmail($template, $data, $account_manager_email, $ticketId, $cc); } else { $this->myLogger->logme('error', "mail not sent for account manager "); } break; default: # code... break; } } return true; } private function updateTicket($data) { $data['updated_by'] = get_session_userid(); $ticket_id = $data['thz_id']; $result = $this->thzMasterModel->where('thz_id', $ticket_id)->set($data)->update(); return $result; } private function insertTicket($data) { $data['created_by'] = get_session_userid(); $this->thzMasterModel->insert($data); return $this->thzMasterModel->insertID(); // returns the inserted row's ID } private function sendEmail($templateName, $data, $to_email, $ticketId, $cc = "", $bcc = "") { $mailTemplate = $this->ticketMailTemplateModel->where('template_name', $templateName)->findAll()[0] ?? []; if (empty($mailTemplate)) { $this->myLogger->logme('error', 'No Mail Template Found To send email in ticketing system'); return; } if (empty($cc)) { $this->myLogger->logme('error', 'empty cc attached for template name : ' . json_encode($templateName)); } else { $this->myLogger->logme('error', "cc attached for template name : " . json_encode($templateName)); } $mailTemplate['subject'] = str_replace('%subject%', $data['subject'] ?? '', $mailTemplate['subject']); $mailTemplate['mail_content'] = str_replace('%subject%', $data['subject'] ?? '', $mailTemplate['mail_content']); $mailTemplate['mail_content'] = str_replace('%ticketId%', $ticketId ?? '', $mailTemplate['mail_content']); $mailTemplate['mail_content'] = str_replace('%message%', $data['notes'] ?? '', $mailTemplate['mail_content']); $mailTemplate['mail_content'] = str_replace('%assignee_email%', $data['assignee_email'] ?? '', $mailTemplate['mail_content']); $mailTemplate['mail_content'] = str_replace('%assigneeAndStatus%', $data['assigneeAndStatus'] ?? '', $mailTemplate['mail_content']); $from_mail = ""; $to_mail = $to_email; $cc_string = $cc; $subject = $mailTemplate['subject']; $message = $mailTemplate['mail_content']; $attachments = ""; $reply_to = ""; $bcc_string = $bcc; $res = MailHelper::send_email(['from_mail' => $from_mail, 'mail' => $to_mail, 'cc' => $cc_string, 'subject' => $subject, 'message' => $message, 'attachments' => $attachments, 'reply_to' => $reply_to, 'bcc' => $bcc_string]); $this->myLogger->logme('error', 'Mail Response : ' . json_encode($res)); } public function getPolicyTerms($client_policy_id) { $policy_data = $this->clientPolicyModel->where('is_active', 1)->where('id', $client_policy_id)->first(); $policy_terms = []; if (isset($policy_data['policy_terms']) && !empty($policy_data['policy_terms'])) { $raw_terms = json_decode($policy_data['policy_terms'] ?? [], true) ?? []; $ticketController = new TicketController(); $policy_terms = $ticketController->convertTermsToDisplay($raw_terms); } $data['policy_terms'] = $policy_terms; return view('view_policy_terms', $data); } private function handleTicketHistory(array $old, array $data): string { if ($old['status'] != $data['status']) { $history = [ 'thz_id' => $data['thz_id'], 'field_name' => 'status', 'display_name' => 'Status', 'old_value' => $old['status'], 'new_value' => $data['status'], 'is_active' => 1 ]; if (!empty(get_session_userid())) { $history['created_by'] = get_session_userid(); } $hist_id = $this->thzHistoryModel->insert($history); return $old['status'] . " - " . $data['status'] . " - " . $hist_id; } return $old['status'] . " - " . $data['status']; } private function getAcmIdUsingClientId($client_id) { if(!empty($client_id)){ $acm_data = $this->cientRmModel->where('is_active', 1)->where('level', 3)->where('client_id', $client_id)->orderBy('id', 'asc')->first(); if($acm_data){ return $acm_data['user_id']; } $this->myLogger->logme('error', 'Account Manager data not found'); return null; } $this->myLogger->logme('error', 'client id is null'); return null; } private function getRmsIdUsingClientId($client_id) { if(!empty($client_id)){ $acm_data = $this->cientRmModel ->select('client_rm.*, user_profiles.email') ->join('user_profiles', 'client_rm.user_id = user_profiles.id') ->where('client_rm.is_active', 1) ->where('client_rm.client_id', $client_id) ->orderBy('id', 'asc') ->findAll(); if($acm_data){ return $acm_data; } $this->myLogger->logme('error', 'Account Manager data not found'); return []; } $this->myLogger->logme('error', 'client id is null'); return null; } public function getOpenTicketsOlderThan24HoursAndAssignNextLevel() { $current_day = date('D'); // Sun, Mon, Tue... $nl = (php_sapi_name() === 'cli') ? PHP_EOL : '
'; echo $current_day . $nl; if ($this->request) { echo "REQUEST" . $nl; } else { echo "CLI" . $nl; } if ($current_day === 'Sun') { if($this->request){ return $this->respond(['message' => "Today is Sunday. Ticket reminder mail skipped"], 200); }else{ $this->myLogger->logme('error', 'Today is Sunday. Ticket reminder mail skipped'); echo 'Today is Sunday. Ticket reminder mail skipped'; return; } } $client_id = $this->request->getGet('client_id') ?? null; $ticket_id = $this->request->getGet('ticket_id') ?? null; // Fetch tickets older than 8 hours $builder = $this->thzMasterModel ->whereIn('status', ['Open', 'In Progress']) // ->where('thz_id', 85) ->where('created_at <= DATE_SUB(NOW(), INTERVAL 8 HOUR)', null, false); // add condition only if client_id exists if (!empty($client_id)) { $builder->where('client_id', $client_id); } // add condition only if ticket_id exists if (!empty($ticket_id)) { $builder->where('thz_id', $ticket_id); } $result = $builder->findAll(); $subjectTemplate = 'Ticket Pending for More Than ((HOURS)) Hours – Action Required'; $messageTemplate = ' Ticket ID : ((TICKET_ID)) has remained in the same status for ((HOURS)) hours. Please take the necessary action.'; $common = [ 'module' => 'THZ', 'mail_type' => 'Thz_Reminder_mail' ]; $mail_send_count = 0; if(!empty($result)){ foreach ($result as $value) { // Calculate hours difference $createdAt = new \DateTime($value['created_at']); $now = new \DateTime(); $hours = floor(($now->getTimestamp() - $createdAt->getTimestamp()) / 3600); $ticket_url = base_url('ticketConversationList?return_type=web&thz_id=' . $value['thz_id']); // Replace placeholders $subject = str_replace('((HOURS))', $hours, $subjectTemplate); $message = str_replace( ['((TICKET_ID))', '((HOURS))', '((TICKET_URL))'], [$value['thz_id'], $hours, $ticket_url], $messageTemplate ); $client_id = $value['client_id']; $level_of_user_data = $this->getRmsIdUsingClientId($client_id); if(!empty($level_of_user_data)){ foreach ($level_of_user_data as $user) { $res = MailHelper::send_email([ 'mail' => $user['email'], 'subject' => $subject, 'message' => $message, 'common' => $common ]); $mail_send_count++; $this->myLogger->logme( 'error', 'THZ Reminder Mail Sent | Ticket ID: ' . $value['thz_id'] . ' | Client ID : ' . $client_id . ' | Response: ' . json_encode($res) ); } }else{ $this->myLogger->logme('error', 'CLIENT ID : ' . $client_id . "has no RM's found skipped...." ); } } }else{ if($this->request){ return $this->respond(['message' => "No ticket Pending for More Than 8 hrs"], 200); }else{ $this->myLogger->logme('error', 'No ticket Pending for More Than 8 hrs'); echo 'No ticket Pending for More Than 8 hrs'; return; } } if($this->request){ return $this->respond(['mail_send_count' => $mail_send_count], 200); }else{ print_r(['mail_send_count' => $mail_send_count]); return; } } }