viewData['pageTitle'] = lang('Tickets.moduleTitle'); // Breadcrumbs $this->viewData['breadcrumb'] = [ ['title' => lang("App.menu_soporte"), 'route' => "javascript:void(0);", 'active' => false], ['title' => lang("App.menu_soporte_ticket_list"), 'route' => route_to('TicketIndex'), 'active' => true] ]; parent::initController($request, $response, $logger); } public function index() { checkPermission('tickets.menu'); $viewData = [ 'currentModule' => static::$controllerSlug, 'pageSubTitle' => lang('Basic.global.ManageAllRecords', [lang('Tickets.tickets')]), 'usingServerSideDataTable' => true, 'userType' => auth()->user()->can('tickets.edit') ? 1 : 0, ]; $viewData = array_merge($this->viewData, $viewData); // merge any possible values from the parent controller class return view(static::$viewPath . 'viewTicketList', $viewData); } private function sendMail($subject, $body, $recipient) { // Funcion wrapper para el servicio de envio de correos dentro de la fucionalidad previa $emailService = service('emailService'); return $emailService->send($subject, $body, $recipient); } public function add() { checkPermission('tickets.create'); if ($this->request->getPost()): $nullIfEmpty = false; // !(phpversion() >= '8.1'); $postData = $this->request->getPost(); // get user id $postData['usuario_id'] = auth()->user()->id; $postData['user_soporte_id'] = model('App\Models\Configuracion\ConfigVariableModel')->getVariable('default_soporte_user_id')->value; $sanitizedData = $this->sanitized($postData, $nullIfEmpty); $noException = true; if ($successfulResult = $this->canValidate()): // if ($successfulResult = $this->validate($this->formValidationRules) ) : if ($this->canValidate()): try { $successfulResult = $this->model->skipValidation(true)->save($sanitizedData); } catch (\Exception $e) { $noException = false; $this->dealWithException($e); } else: $this->viewData['errorMessage'] = lang('Basic.global.formErr1', [lang('Basic.global.record')]); $this->session->setFlashdata('formErrors', $this->model->errors()); endif; $thenRedirect = true; // Change this to false if you want your user to stay on the form after submission endif; if ($noException && $successfulResult): $id = $this->model->db->insertID(); $this->saveImages($id, $this->request->getFiles()); $message = lang('Basic.global.saveSuccess', [lang('Basic.global.record')]) . '.'; $userModel = new \App\Models\Usuarios\UserModel(); $this->sendMail(lang('Tickets.newTicket'), lang('Tickets.newTicketBody') . base_url(route_to('editTicket', $id)), $userModel->find($sanitizedData['user_soporte_id'])->email); if ($thenRedirect): if (!empty($this->indexRoute)): return redirect()->to(route_to($this->indexRoute))->with('successMessage', $message); else: return $this->redirect2listView('successMessage', $message); endif; else: $this->session->setFlashData('sweet-success', $message); endif; endif; // $noException && $successfulResult endif; // ($requestMethod === 'post') $this->viewData['ticket'] = isset($sanitizedData) ? new TicketEntity($sanitizedData) : new TicketEntity(); $this->viewData['formAction'] = route_to('NewTicket'); $this->viewData['categorias'] = $this->model->getCategorias(); $this->viewData['estados'] = $this->model->getEstados(); $this->viewData['secciones'] = $this->model->getSecciones(); $this->viewData['supportUsers'] = $this->getSupportUsers(); $this->viewData['boxTitle'] = lang('Basic.global.addNew') . ' ' . lang('Tickets.ticket') . ' ' . lang('Basic.global.addNewSuffix'); return $this->displayForm(__METHOD__); } // end function add() public function edit($requestedId = null) { checkPermission('tickets.edit'); $modelRespuesta = new \App\Models\Soporte\TicketRespuestaModel(); if ($requestedId == null): return $this->redirect2listView(); endif; $id = filter_var($requestedId, FILTER_SANITIZE_URL); $ticket = $this->model->find($id); if ($ticket == false): $message = lang('Basic.global.notFoundWithIdErr', [mb_strtolower(lang('Tickets.ticket')), $id]); return $this->redirect2listView('errorMessage', $message); endif; if (!auth()->user()->can('Tickets.edit') && auth()->user()->id != $ticket->usuario_id) { return redirect()->to(route_to('TicketIndex'))->with('errorMessage', lang('Basic.global.noPermission')); } if ($this->request->getPost()): $oldUserSupport = $ticket->user_soporte_id; $oldState = $ticket->estado_id; $postData = $this->request->getPost(); $sanitizedData = $this->sanitized($postData, false); $noException = true; if ($successfulResult = $this->canValidate()): // if ($successfulResult = $this->validate($this->formValidationRules) ) : if ($this->canValidate()): try { $successfulResult = $this->model->skipValidation(true)->update($id, $sanitizedData); $this->saveImages($id, $this->request->getFiles()); if (auth()->user()->can('Tickets.edit')) { $respuesta = $modelRespuesta->where('ticket_id', $id)->first(); if ($respuesta == null) { $modelRespuesta->insert([ 'ticket_id' => $id, 'usuario_id' => auth()->user()->id, 'mensaje' => $sanitizedData['respuesta_mensaje'] ]); } else { $modelRespuesta->update($respuesta->id, [ 'mensaje' => $sanitizedData['respuesta_mensaje'], 'usuario_id' => auth()->user()->id, ]); } // envio de correos $userModel = new \App\Models\Usuarios\UserModel(); if ($oldUserSupport != $sanitizedData['user_soporte_id']) { $this->sendMail(lang('Tickets.asgignToChanged'), lang('Tickets.asgignToChangedBody') . base_url(route_to('editTicket', $id)), $userModel->find($sanitizedData['user_soporte_id'])->email); } if ($oldState != $sanitizedData['estado_id']) { $this->sendMail(lang('Tickets.stateChange'), lang('Tickets.stateChangeBody') . base_url(route_to('editTicket', $id)), $userModel->find($ticket->usuario_id)->email); } } } catch (\Exception $e) { $noException = false; $this->dealWithException($e); } else: $this->viewData['warningMessage'] = lang('Basic.global.formErr1', [mb_strtolower(lang('Tickets.ticket'))]); $this->session->setFlashdata('formErrors', $this->model->errors()); endif; $ticket->fill($sanitizedData); $thenRedirect = false; endif; if ($noException && $successfulResult): $id = $ticket->id ?? $id; $message = lang('Basic.global.updateSuccess', [lang('Basic.global.record')]) . '.'; if ($thenRedirect): if (!empty($this->indexRoute)): return redirect()->to(route_to($this->indexRoute))->with('successMessage', $message); else: return $this->redirect2listView('successMessage', $message); endif; else: return redirect()->to(route_to("editTicket", $id))->with('successMessage', $message); //$this->session->setFlashData('sweet-success', $message); endif; endif; // $noException && $successfulResult endif; // ($requestMethod === 'post') $this->viewData['ticket'] = $ticket; $this->viewData['respuesta'] = $modelRespuesta->where('ticket_id', $id)->first(); $this->viewData['formAction'] = route_to('updateTicket', $id); $this->viewData['categorias'] = $this->model->getCategorias(); $this->viewData['estados'] = $this->model->getEstados(); $this->viewData['secciones'] = $this->model->getSecciones(); $this->viewData['supportUsers'] = $this->getSupportUsers(); $this->viewData['imagesTicket'] = $this->getImages('ticket', $id); $this->viewData['imagesRespuesta'] = $this->getImages('respuesta', $id); $this->viewData['boxTitle'] = lang('Basic.global.edit2') . ' ' . lang('Tickets.ticket') . ' ' . lang('Basic.global.edit3'); return $this->displayForm(__METHOD__, $id); } // end function edit(...) public function datatable() { if ($this->request->isAJAX()) { $reqData = $this->request->getPost(); if (!isset($reqData['draw']) || !isset($reqData['columns'])) { $errstr = 'No data available in response to this specific request.'; $response = $this->respond(Collection::datatable([], 0, 0, $errstr), 400, $errstr); return $response; } $start = $reqData['start'] ?? 0; $length = $reqData['length'] ?? 5; $requestedOrder = $reqData['order'] ?? []; $searchValues = get_filter_datatables_columns($reqData); if (auth()->user()->can('tickets.edit')) { $user_id = null; } else { $user_id = auth()->user()->id; } $resourceData = $this->model->getResource($searchValues, $user_id); foreach ($requestedOrder as $order) { $column = $order['column'] ?? 0; $dir = $order['dir'] ?? 'asc'; $orderColumn = $this->model::SORTABLE[$column] ?? null; if ($orderColumn) { $resourceData->orderBy($orderColumn, $dir); } } $resourceData = $resourceData->limit($length, $start)->get()->getResultObject(); return $this->respond(Collection::datatable( $resourceData, $this->model->getResource($searchValues)->countAllResults(), $this->model->getResource($searchValues)->countAllResults() )); } else { return $this->failUnauthorized('Invalid request', 403); } } public function image($imageName) { $filePath = WRITEPATH . "uploads/tickets/" . $imageName; if (!file_exists($filePath)) { return $this->response->setStatusCode(404, 'Imagen no encontrada'); } $mimeType = mime_content_type($filePath); return $this->response ->setHeader('Content-Type', $mimeType) ->setBody(file_get_contents($filePath)); } private function saveImages($ticket_id, $files = []) { $uploadPath = WRITEPATH . 'uploads/tickets/'; $fileModel = new ticketFileModel(); if ($files && isset($files['files'])) { foreach ($files['files'] as $file) { if ($file->isValid() && !$file->hasMoved()) { $originalName = $file->getClientName(); $fileExt = $file->getExtension(); // Generar hash SHA-256 basado en el contenido del archivo $fileHash = hash_file("sha256", $file->getTempName()); $newFileName = $fileHash . '.' . $fileExt; // Mover el archivo con el nombre basado en el hash $file->move($uploadPath, $newFileName); // Guardar en la base de datos $fileModel->insert([ 'nombre' => $originalName, 'ticket_id' => $ticket_id, 'hash' => $fileHash, 'path' => 'uploads/tickets/' . $newFileName ]); } } } } private function getImages($tipo = 'ticket', $id = null) { $images = []; $model = new ticketFileModel(); if ($tipo == 'ticket') { $files = $model->where('ticket_id', $id)->findAll(); foreach ($files as $file) { $ext = pathinfo($file['nombre'], PATHINFO_EXTENSION); array_push($images, array( "path" => '/soporte/image/' . $file['hash'] . "." . $ext, "name" => $file['nombre'] )); } } else { $files = $model->where('respuesta_id', $id)->findAll(); foreach ($files as $file) { $ext = pathinfo($file['nombre'], PATHINFO_EXTENSION); array_push($images, array( "path" => '/soporte/image/' . $file['hash'] . "." . $ext, "name" => $file['nombre'] )); } } return $images; } private function getSupportUsers() { $defatulSoporteUserId = model('App\Models\Configuracion\ConfigVariableModel')->getVariable('default_soporte_user_id')->value; $supportUsers = array( array( 'id' => $defatulSoporteUserId, 'name' => model('App\Models\Usuarios\UserModel')->getFullName($defatulSoporteUserId) ), array( 'id' => 2, 'name' => model('App\Models\Usuarios\UserModel')->getFullName(2) ), array( 'id' => 1, 'name' => model('App\Models\Usuarios\UserModel')->getFullName(1) ), ); return $supportUsers; } }