conn = $conn; } /** * Create a new bulk operation record * * @param string $type Operation type (bulk_close, bulk_assign, bulk_priority) * @param array $ticketIds Array of ticket IDs * @param int $userId User performing the operation * @param array|null $parameters Operation parameters * @return int|false Operation ID or false on failure */ public function createBulkOperation($type, $ticketIds, $userId, $parameters = null) { $ticketIdsStr = implode(',', $ticketIds); $totalTickets = count($ticketIds); $parametersJson = $parameters ? json_encode($parameters) : null; $sql = "INSERT INTO bulk_operations (operation_type, ticket_ids, performed_by, parameters, total_tickets) VALUES (?, ?, ?, ?, ?)"; $stmt = $this->conn->prepare($sql); $stmt->bind_param("ssisi", $type, $ticketIdsStr, $userId, $parametersJson, $totalTickets); if ($stmt->execute()) { $operationId = $this->conn->insert_id; $stmt->close(); return $operationId; } $stmt->close(); return false; } /** * Process a bulk operation * * @param int $operationId Operation ID * @return array Result with processed and failed counts */ public function processBulkOperation($operationId) { // Get operation details $sql = "SELECT * FROM bulk_operations WHERE operation_id = ?"; $stmt = $this->conn->prepare($sql); $stmt->bind_param("i", $operationId); $stmt->execute(); $result = $stmt->get_result(); $operation = $result->fetch_assoc(); $stmt->close(); if (!$operation) { return ['processed' => 0, 'failed' => 0, 'error' => 'Operation not found']; } $ticketIds = explode(',', $operation['ticket_ids']); $parameters = $operation['parameters'] ? json_decode($operation['parameters'], true) : []; $processed = 0; $failed = 0; // Load required models require_once dirname(__DIR__) . '/models/TicketModel.php'; require_once dirname(__DIR__) . '/models/AuditLogModel.php'; $ticketModel = new TicketModel($this->conn); $auditLogModel = new AuditLogModel($this->conn); foreach ($ticketIds as $ticketId) { $ticketId = trim($ticketId); $success = false; try { switch ($operation['operation_type']) { case 'bulk_close': // Get current ticket to preserve other fields $currentTicket = $ticketModel->getTicketById($ticketId); if ($currentTicket) { $success = $ticketModel->updateTicket([ 'ticket_id' => $ticketId, 'title' => $currentTicket['title'], 'description' => $currentTicket['description'], 'category' => $currentTicket['category'], 'type' => $currentTicket['type'], 'status' => 'Closed', 'priority' => $currentTicket['priority'] ], $operation['performed_by']); if ($success) { $auditLogModel->log($operation['performed_by'], 'update', 'ticket', $ticketId, ['status' => 'Closed', 'bulk_operation_id' => $operationId]); } } break; case 'bulk_assign': if (isset($parameters['assigned_to'])) { $success = $ticketModel->assignTicket($ticketId, $parameters['assigned_to'], $operation['performed_by']); if ($success) { $auditLogModel->log($operation['performed_by'], 'assign', 'ticket', $ticketId, ['assigned_to' => $parameters['assigned_to'], 'bulk_operation_id' => $operationId]); } } break; case 'bulk_priority': if (isset($parameters['priority'])) { $currentTicket = $ticketModel->getTicketById($ticketId); if ($currentTicket) { $success = $ticketModel->updateTicket([ 'ticket_id' => $ticketId, 'title' => $currentTicket['title'], 'description' => $currentTicket['description'], 'category' => $currentTicket['category'], 'type' => $currentTicket['type'], 'status' => $currentTicket['status'], 'priority' => $parameters['priority'] ], $operation['performed_by']); if ($success) { $auditLogModel->log($operation['performed_by'], 'update', 'ticket', $ticketId, ['priority' => $parameters['priority'], 'bulk_operation_id' => $operationId]); } } } break; case 'bulk_status': if (isset($parameters['status'])) { $currentTicket = $ticketModel->getTicketById($ticketId); if ($currentTicket) { $success = $ticketModel->updateTicket([ 'ticket_id' => $ticketId, 'title' => $currentTicket['title'], 'description' => $currentTicket['description'], 'category' => $currentTicket['category'], 'type' => $currentTicket['type'], 'status' => $parameters['status'], 'priority' => $currentTicket['priority'] ], $operation['performed_by']); if ($success) { $auditLogModel->log($operation['performed_by'], 'update', 'ticket', $ticketId, ['status' => $parameters['status'], 'bulk_operation_id' => $operationId]); } } } break; } if ($success) { $processed++; } else { $failed++; } } catch (Exception $e) { $failed++; error_log("Bulk operation error for ticket $ticketId: " . $e->getMessage()); } } // Update operation status $sql = "UPDATE bulk_operations SET status = 'completed', processed_tickets = ?, failed_tickets = ?, completed_at = NOW() WHERE operation_id = ?"; $stmt = $this->conn->prepare($sql); $stmt->bind_param("iii", $processed, $failed, $operationId); $stmt->execute(); $stmt->close(); return ['processed' => $processed, 'failed' => $failed]; } /** * Get bulk operation by ID * * @param int $operationId Operation ID * @return array|null Operation record or null */ public function getOperationById($operationId) { $sql = "SELECT * FROM bulk_operations WHERE operation_id = ?"; $stmt = $this->conn->prepare($sql); $stmt->bind_param("i", $operationId); $stmt->execute(); $result = $stmt->get_result(); $operation = $result->fetch_assoc(); $stmt->close(); return $operation; } /** * Get bulk operations performed by a user * * @param int $userId User ID * @param int $limit Result limit * @return array Array of operations */ public function getOperationsByUser($userId, $limit = 50) { $sql = "SELECT * FROM bulk_operations WHERE performed_by = ? ORDER BY created_at DESC LIMIT ?"; $stmt = $this->conn->prepare($sql); $stmt->bind_param("ii", $userId, $limit); $stmt->execute(); $result = $stmt->get_result(); $operations = []; while ($row = $result->fetch_assoc()) { if ($row['parameters']) { $row['parameters'] = json_decode($row['parameters'], true); } $operations[] = $row; } $stmt->close(); return $operations; } }