telegramService = $telegramService; $this->managerChatId = $chatId; $this->managerTelegramUserId = $telegramUserId; $this->loadManagerEmployeeId(); } private function loadManagerEmployeeId(): void { $employeeModel = new Employee(Database::getInstance()); $manager = $employeeModel->findByChatUserId((string) $this->managerTelegramUserId); if ($manager && $manager->id) { $this->managerEmployeeId = $manager->id; // log_message("ManagerActionHandler: Manager Employee ID {$this->managerEmployeeId} loaded for Telegram User ID {$this->managerTelegramUserId}"); } else { log_message("ManagerActionHandler: No employee record found for manager with Telegram User ID {$this->managerTelegramUserId}."); } } /** * Handles manager's action (approve/reject) on a leave request. * @param string $callbackData e.g., "mgrAction_approve_123" or "mgrAction_reject_123" * @param int $originalMessageId The ID of the message manager interacted with (to edit it) */ public function handleApprovalAction(string $callbackData, int $originalMessageId): void { if ($this->managerEmployeeId === null) { $this->telegramService->sendMessage($this->managerChatId, "ขออภัยค่ะ ไม่สามารถดำเนินการได้เนื่องจากไม่พบข้อมูลผู้จัดการ (ID: {$this->managerTelegramUserId}) ของคุณในระบบ"); return; } $parts = explode('_', $callbackData); if (count($parts) !== 3) { $this->telegramService->editMessageText($this->managerChatId, $originalMessageId, "ข้อมูลการดำเนินการไม่ถูกต้องค่ะ (invalid callback format)"); log_message("ManagerActionHandler: Invalid callback data format: {$callbackData}"); return; } $action = $parts[1]; $leaveRequestId = (int) $parts[2]; $leaveRequestModel = new LeaveRequest(Database::getInstance()); $request = $leaveRequestModel->read($leaveRequestId); if (!$request || !isset($request->id)) { $this->telegramService->editMessageText($this->managerChatId, $originalMessageId, "ไม่พบคำขอ ID: {$leaveRequestId} ในระบบค่ะ"); return; } $requesterEmployeeModel = new Employee(Database::getInstance()); $requester = $requesterEmployeeModel->read($request->employee_id); if (!$requester || !isset($requester->manager_id) || $requester->manager_id !== $this->managerEmployeeId) { $this->telegramService->editMessageText($this->managerChatId, $originalMessageId, "คุณไม่มีสิทธิ์ดำเนินการกับคำขอ ID: {$leaveRequestId} นี้ค่ะ"); log_message("Authorization failed: Manager {$this->managerEmployeeId} (Telegram User {$this->managerTelegramUserId}) tried to action request {$leaveRequestId} for employee {$request->employee_id} whose manager is ".($requester->manager_id ?? 'N/A')); return; } if ($request->status !== 'PENDING') { $this->telegramService->editMessageText($this->managerChatId, $originalMessageId, "คำขอ ID: {$leaveRequestId} ได้รับการดำเนินการไปแล้ว (สถานะปัจจุบัน: {$request->status})"); return; } $newStatus = ''; $actionText = ''; $notifyRequesterMessage = ''; // Changed from $notifyRequesterText to avoid confusion with boolean result // Use the loaded $request object for updates $requestForUpdate = new LeaveRequest(Database::getInstance()); $requestForUpdate->id = $request->id; // Set ID for updateStatus if ($action === 'approve') { $newStatus = 'APPROVED'; $actionText = 'อนุมัติ'; $leaveTypeModel = new LeaveType(Database::getInstance()); $leaveType = $leaveTypeModel->read($request->leave_type_id); $balanceDeductedSuccessfully = true; // Assume success unless deduction fails if ($leaveType && $leaveType->deducts_balance) { $daysToDeduct = LeaveBalance::calculateLeaveDurationInDays($request->start_date, $request->end_date); $currentYear = (int) date('Y', strtotime($request->start_date)); $leaveBalanceModel = new LeaveBalance(Database::getInstance()); if ($daysToDeduct > 0) { if (!$leaveBalanceModel->deductFromBalance($request->employee_id, $request->leave_type_id, $currentYear, $daysToDeduct)) { $balanceDeductedSuccessfully = false; log_message("Error deducting balance for approved request {$leaveRequestId}. Still marked APPROVED."); } else { log_message("Successfully deducted {$daysToDeduct} days for request {$leaveRequestId}."); } } } if ($requestForUpdate->updateStatus($newStatus, $this->managerEmployeeId)) { $notifyRequesterMessage = "คำขอ{$this->getRequestTypeText($request->leave_type_id)}ของคุณ (ID: {$leaveRequestId}) ได้รับการ *อนุมัติ* แล้วค่ะ"; if (!$balanceDeductedSuccessfully) { $notifyRequesterMessage .= "\n*(หมายเหตุ: เกิดปัญหาในการอัปเดตยอดวันลาคงเหลือ กรุณาติดต่อ HR)*"; } } else { $this->telegramService->editMessageText($this->managerChatId, $originalMessageId, "เกิดข้อผิดพลาดในการอนุมัติคำขอ ID: {$leaveRequestId}"); return; } } elseif ($action === 'reject') { $newStatus = 'REJECTED'; $actionText = 'ไม่อนุมัติ'; if ($requestForUpdate->updateStatus($newStatus, $this->managerEmployeeId)) { $notifyRequesterMessage = "คำขอ{$this->getRequestTypeText($request->leave_type_id)}ของคุณ (ID: {$leaveRequestId}) ถูก *ปฏิเสธ* ค่ะ"; } else { $this->telegramService->editMessageText($this->managerChatId, $originalMessageId, "เกิดข้อผิดพลาดในการไม่อนุมัติคำขอ ID: {$leaveRequestId}"); return; } } else { $this->telegramService->editMessageText($this->managerChatId, $originalMessageId, "การดำเนินการไม่ถูกต้อง ({$action}) สำหรับคำขอ ID: {$leaveRequestId}"); return; } // Sanitize for MarkdownV2 $escape = function ($text) {return preg_replace('/([_*\[\]()~`>#\+\-=|{}.!\\\\])/', '\\\\$1', $text);}; $finalMessageToManager = "คุณได้ *{$escape($actionText)}* คำขอ ID: {$escape((string) $leaveRequestId)} เรียบร้อยแล้ว\n"; $finalMessageToManager .= "(ผู้ขอ: {$escape($requester->first_name)}, ประเภท: {$escape($request->leaveType->name ?? 'N/A')}, วันที่: {$escape($request->start_date)} \\- {$escape($request->end_date)})"; // Try to edit the message. If it fails (e.g. message too old, or bot removed from chat), send a new one. $editSuccess = $this->telegramService->editMessageText($this->managerChatId, $originalMessageId, $finalMessageToManager, null, "MarkdownV2"); if (!$editSuccess || (isset($editSuccess['ok']) && !$editSuccess['ok'])) { log_message("Failed to edit manager's message (MsgID: {$originalMessageId}). Sending new message. Error: ".json_encode($editSuccess)); $this->telegramService->sendMessage($this->managerChatId, $finalMessageToManager, null, "MarkdownV2"); } if (!empty($notifyRequesterMessage)) { $this->notifyRequester($request->employee_id, $leaveRequestId, $newStatus, $notifyRequesterMessage); } } /** * @param int $leaveTypeId */ private function getRequestTypeText(int $leaveTypeId): string { $leaveTypeModel = new LeaveType(Database::getInstance()); $leaveType = $leaveTypeModel->read($leaveTypeId); // Assuming alias 'wfh' is specific to WFH types if ($leaveType && isset($leaveType->alias) && strtolower($leaveType->alias) === 'wfh') { return " WFH "; } return "ลา"; } /** * @param int $requesterEmployeeId * @param int $leaveRequestId * @param string $status * @param string $messageForRequester * @return null */ private function notifyRequester(int $requesterEmployeeId, int $leaveRequestId, string $status, string $messageForRequester): void { $employeeModel = new Employee(Database::getInstance()); $requester = $employeeModel->read($requesterEmployeeId); if ($requester && isset($requester->chat_user_id) && $requester->chat_user_id) { $requesterChatId = (int) $requester->chat_user_id; if ($requesterChatId === 0) { log_message("Could not notify requester (Employee ID: {$requesterEmployeeId}): Invalid chat_user_id '{$requester->chat_user_id}'"); return; } $this->telegramService->sendMessage($requesterChatId, $messageForRequester, null, "MarkdownV2"); log_message("Notified requester (Employee ID: {$requesterEmployeeId}, Chat ID: {$requesterChatId}) about request {$leaveRequestId} status: {$status}"); } else { log_message("Could not notify requester (Employee ID: {$requesterEmployeeId}): User not found or no chat_user_id."); } } }