From 69f6d6cbebd9068f06a40e903cb83982b650efa9 Mon Sep 17 00:00:00 2001 From: amazuecos Date: Wed, 2 Apr 2025 20:19:16 +0200 Subject: [PATCH] chat select cliente contactos --- ci4/app/Controllers/Chat/ChatController.php | 61 +++---------------- .../Clientes/ClienteContactoEntity.php | 11 ++++ ci4/app/Entities/Clientes/ClienteEntity.php | 19 +++++- .../Models/Clientes/ClienteContactoModel.php | 1 + ci4/app/Models/Clientes/ClienteModel.php | 56 +++++++++++------ ci4/app/Services/ChatService.php | 47 +++++++++++--- .../messageNotificationClienteContacto.php | 29 +++++++++ httpdocs/assets/js/safekat/components/chat.js | 34 ++++++++--- 8 files changed, 166 insertions(+), 92 deletions(-) create mode 100644 ci4/app/Views/themes/vuexy/mail/messageNotificationClienteContacto.php diff --git a/ci4/app/Controllers/Chat/ChatController.php b/ci4/app/Controllers/Chat/ChatController.php index 8a716f12..ba44d28e 100644 --- a/ci4/app/Controllers/Chat/ChatController.php +++ b/ci4/app/Controllers/Chat/ChatController.php @@ -210,7 +210,6 @@ class ChatController extends BaseController } public function store_message($model) { - $data = $this->request->getPost(); $chatMessageEntity = $this->chatService->storeChatMessage($data["chat_department_id"],$model,$data["model_id"],$data); return $this->response->setJSON($chatMessageEntity); @@ -338,67 +337,25 @@ class ChatController extends BaseController { $pm = model(PresupuestoModel::class); $p = $pm->find($presupuesto_id); - $query = $this->userModel->builder()->select( - [ - "id", - "CONCAT(first_name,' ',last_name,'(',username,')') as name" - ] - ) - ->where("deleted_at", null) - ->whereNotIn("id", [auth()->user()->id]) - ->where("cliente_id", $p->cliente_id); - if ($this->request->getGet("q")) { - $query->groupStart() - ->orLike("users.username", $this->request->getGet("q")) - ->orLike("CONCAT(first_name,' ',last_name)", $this->request->getGet("q")) - ->groupEnd(); - } - - return $this->response->setJSON($query->get()->getResultObject()); + $cm = model(ClienteModel::class); + $clienteContactos = $cm->querySelectClienteContacto($p->cliente_id,$this->request->getGet('q')); + return $this->response->setJSON($clienteContactos); } public function get_pedido_client_users(int $pedido_id) { $pm = model(PedidoModel::class); $p = $pm->find($pedido_id); - $query = $this->userModel->builder()->select( - [ - "id", - "CONCAT(first_name,' ',last_name,'(',username,')') as name" - ] - ) - ->where("deleted_at", null) - ->whereNotIn("id", [auth()->user()->id]) - ->where("cliente_id", $p->cliente()->id); - if ($this->request->getGet("q")) { - $query->groupStart() - ->orLike("users.username", $this->request->getGet("q")) - ->orLike("CONCAT(first_name,' ',last_name)", $this->request->getGet("q")) - ->groupEnd(); - } - - return $this->response->setJSON($query->get()->getResultObject()); + $cm = model(ClienteModel::class); + $clienteContactos = $cm->querySelectClienteContacto($p->cliente()->id,$this->request->getGet('q')); + return $this->response->setJSON($clienteContactos); } public function get_factura_client_users(int $factura_id) { $fm = model(FacturaModel::class); $f = $fm->find($factura_id); - $query = $this->userModel->builder()->select( - [ - "id", - "CONCAT(first_name,' ',last_name,'(',username,')') as name" - ] - ) - ->where("deleted_at", null) - ->whereNotIn("id", [auth()->user()->id]) - ->where("cliente_id", $f->cliente_id); - if ($this->request->getGet("q")) { - $query->groupStart() - ->orLike("users.username", $this->request->getGet("q")) - ->orLike("CONCAT(first_name,' ',last_name)", $this->request->getGet("q")) - ->groupEnd(); - } - - return $this->response->setJSON($query->get()->getResultObject()); + $cm = model(ClienteModel::class); + $clienteContactos = $cm->querySelectClienteContacto($f->cliente_id,$this->request->getGet('q')); + return $this->response->setJSON($clienteContactos); } public function store_hebra(string $model) { diff --git a/ci4/app/Entities/Clientes/ClienteContactoEntity.php b/ci4/app/Entities/Clientes/ClienteContactoEntity.php index 2c8cb886..3929aed3 100755 --- a/ci4/app/Entities/Clientes/ClienteContactoEntity.php +++ b/ci4/app/Entities/Clientes/ClienteContactoEntity.php @@ -1,6 +1,7 @@ "int", "is_deleted" => "int", ]; + + public function getFullName() : string + { + return trim(implode(" ",[$this->attributes['nombre'] ?? '',$this->attributes["apellidos"] ?? ''])); + } + public function cliente() : ?ClienteEntity + { + $cm = model(ClienteModel::class); + return $cm->find($this->attributes["cliente_id"]); + } } diff --git a/ci4/app/Entities/Clientes/ClienteEntity.php b/ci4/app/Entities/Clientes/ClienteEntity.php index a82664e0..5ea34297 100755 --- a/ci4/app/Entities/Clientes/ClienteEntity.php +++ b/ci4/app/Entities/Clientes/ClienteEntity.php @@ -2,6 +2,7 @@ namespace App\Entities\Clientes; use App\Entities\Usuarios\UserEntity; +use App\Models\Clientes\ClienteContactoModel; use App\Models\Usuarios\UserModel; use CodeIgniter\Entity; @@ -71,9 +72,25 @@ class ClienteEntity extends \CodeIgniter\Entity\Entity "user_update_id" => "int", ]; - public function comercial() : UserEntity + public function comercial() : ?UserEntity { $m = model(UserModel::class); return $m->find($this->attributes["comercial_id"]); } + public function user() : ?UserEntity + { + $m = model(UserModel::class); + return $m->where("cliente_id",$this->attributes["id"])->first(); + } + /** + * Devuelve un array con los contactos del cliente + * + * @return array + */ + public function contactos() : array + { + $m = model(ClienteContactoModel::class); + $clienteContactos = $m->where('cliente_id',$this->attributes['id'])->findAll(); + return $clienteContactos ?? []; + } } diff --git a/ci4/app/Models/Clientes/ClienteContactoModel.php b/ci4/app/Models/Clientes/ClienteContactoModel.php index 5dba9b92..5338f71a 100755 --- a/ci4/app/Models/Clientes/ClienteContactoModel.php +++ b/ci4/app/Models/Clientes/ClienteContactoModel.php @@ -30,6 +30,7 @@ class ClienteContactoModel extends \App\Models\BaseModel protected $createdField = "created_at"; protected $updatedField = "updated_at"; + protected $deletedField = 'deleted_at'; public static $labelField = "nombre"; diff --git a/ci4/app/Models/Clientes/ClienteModel.php b/ci4/app/Models/Clientes/ClienteModel.php index a8de16c8..77af360d 100755 --- a/ci4/app/Models/Clientes/ClienteModel.php +++ b/ci4/app/Models/Clientes/ClienteModel.php @@ -287,8 +287,7 @@ class ClienteModel extends \App\Models\BaseModel ->select( "t1.id AS id, t1.nombre AS nombre, t1.alias AS alias, t1.cif AS cif, t1.email AS email, t1.vencimiento AS vencimiento, t5.first_name AS comercial, t7.nombre AS forma_pago_id" ) - ->where("is_deleted", 0); - ; + ->where("is_deleted", 0);; $builder->join("users t5", "t1.comercial_id = t5.id", "left"); $builder->join("formas_pago t7", "t1.forma_pago_id = t7.id", "left"); @@ -320,11 +319,11 @@ class ClienteModel extends \App\Models\BaseModel ->where("t1.id", $cliente_id); $limite = $builder->get()->getResultObject(); - if($limite){ + if ($limite) { $pendiente = $this->getPendienteCobro($cliente_id); $credito_disponible = floatval($limite[0]->limite_credito) - $pendiente[0] - $pendiente[1] - floatval($total_pedido); - if($credito_disponible < 0) + if ($credito_disponible < 0) return false; return true; } @@ -414,10 +413,9 @@ class ClienteModel extends \App\Models\BaseModel return empty($search) ? $builder->get()->getResultObject() : $builder - ->groupStart() - ->like("t1.nombre", $search) - ->groupEnd()->get()->getResultObject(); - + ->groupStart() + ->like("t1.nombre", $search) + ->groupEnd()->get()->getResultObject(); } public function getPendienteCobro($cliente_id = -1) @@ -460,7 +458,6 @@ class ClienteModel extends \App\Models\BaseModel } else { return [0, round(floatval($pendiente_old), 2)]; } - } private function getTotalPendienteOldERP($customer_id = -1) @@ -499,7 +496,8 @@ class ClienteModel extends \App\Models\BaseModel } } - public function getResumenPagos($cliente_id = -1){ + public function getResumenPagos($cliente_id = -1) + { $result = []; $data = $this->db->table('facturas f') @@ -510,7 +508,7 @@ class ClienteModel extends \App\Models\BaseModel ->where('f.estado_pago', 'pendiente') ->get() ->getResultObject(); - $result['total_facturas_sin_pagar'] = + $result['total_facturas_sin_pagar'] = round(floatval(($data && $data[0]->total != null) ? $data[0]->total : 0), 2); $data = $this->db->table('facturas_pagos fp') @@ -523,7 +521,7 @@ class ClienteModel extends \App\Models\BaseModel ->where('f.deleted_at IS NULL') ->get() ->getResultObject(); - $result['total_facturas_pagadas'] = + $result['total_facturas_pagadas'] = round(floatval(($data && $data[0]->total != null) ? $data[0]->total : 0), 2); $data = $this->db->table('facturas f') @@ -537,7 +535,7 @@ class ClienteModel extends \App\Models\BaseModel ->where('fp.deleted_at IS NULL') ->get() ->getResultObject(); - $result['total_facturas_vencidas'] = + $result['total_facturas_vencidas'] = round(floatval(($data && $data[0]->total != null) ? $data[0]->total : 0), 2); // Subconsulta para verificar la existencia en facturas_lineas @@ -559,7 +557,7 @@ class ClienteModel extends \App\Models\BaseModel ->get() ->getResultObject(); $query = $this->db->getLastQuery(); - $result['total_pedidos_produccion'] = + $result['total_pedidos_produccion'] = round(floatval(($data && $data[0]->total != null) ? $data[0]->total : 0), 2); // Subconsulta para calcular el total de pedidos finalizados @@ -572,12 +570,12 @@ class ClienteModel extends \App\Models\BaseModel ->where("NOT EXISTS $subquery_facturas", null, false) // Implementación manual de NOT EXISTS ->get() ->getResultObject(); - $result['total_pedidos_finalizados'] = + $result['total_pedidos_finalizados'] = round(floatval(($data && $data[0]->total != null) ? $data[0]->total : 0), 2); - $result['total_pendiente'] = + $result['total_pendiente'] = $result['total_facturas_sin_pagar'] - + $result['total_pedidos_produccion'] + + $result['total_pedidos_produccion'] + $result['total_pedidos_finalizados']; $result['total_pendiente'] = round(floatval($result['total_pendiente']), 2); @@ -588,8 +586,28 @@ class ClienteModel extends \App\Models\BaseModel ->get() ->getResultObject()[0]->limite_credito; $result['limite_credito'] = round(floatval($result['limite_credito']), 2); - - $result['margen_disponible'] = round(floatval( $result['limite_credito']-$result['total_pendiente']), 2); + + $result['margen_disponible'] = round(floatval($result['limite_credito'] - $result['total_pendiente']), 2); return $result; } + + public function querySelectClienteContacto(int $cliente_id, string $q): array + { + $query = $this->builder()->select([ + "cliente_contactos.id", + "CONCAT(COALESCE(cliente_contactos.nombre,''),' ',COALESCE(cliente_contactos.apellidos,'')) as name", + 'cliente_contactos.cargo as description' + ]) + ->join('cliente_contactos', 'cliente_contactos.cliente_id = clientes.id', 'left') + ->where('cliente_contactos.deleted_at',null) + ->where('cliente_contactos.email is NOT NULL',null,false) + ->where('cliente_contactos.cliente_id', $cliente_id); + if ($q) { + $query->groupStart(); + $query->orLike('name', $q); + $query->orLike('description', $q); + $query->groupEnd(); + } + return $query->get()->getResultArray() ?? []; + } } diff --git a/ci4/app/Services/ChatService.php b/ci4/app/Services/ChatService.php index c619167b..62331253 100644 --- a/ci4/app/Services/ChatService.php +++ b/ci4/app/Services/ChatService.php @@ -6,6 +6,7 @@ use App\Controllers\Configuracion\ConfigVariables; use App\Entities\Chat\ChatEntity; use App\Entities\Chat\ChatMessageEntity; use App\Entities\Chat\ChatNotificationEntity; +use App\Entities\Clientes\ClienteContactoEntity; use App\Entities\Usuarios\UserEntity; use App\Models\Chat\ChatDeparmentModel; use App\Models\Chat\ChatDeparmentUserModel; @@ -13,11 +14,13 @@ use App\Models\Chat\ChatMessageModel; use App\Models\Chat\ChatModel; use App\Models\ChatNotification; use App\Models\ChatUser; +use App\Models\Clientes\ClienteContactoModel; use App\Models\Configuracion\ConfigVariableModel; use App\Models\Presupuestos\PresupuestoModel; use App\Models\Usuarios\UserModel; use CodeIgniter\Config\BaseService; use App\Services\EmailService; +use Exception; class ChatService extends BaseService { @@ -31,6 +34,7 @@ class ChatService extends BaseService protected PresupuestoModel $presupuestoModel; protected ChatDeparmentModel $chatDepartmentModel; protected ChatDeparmentUserModel $chatDepartmentUserModel; + protected ClienteContactoModel $clienteContactoModel; protected ConfigVariableModel $configVariables; protected array $modelFkMap = [ "presupuesto" => "presupuesto_id", @@ -43,6 +47,7 @@ class ChatService extends BaseService $this->emailService = service('emailService'); // Usar el servicio de email de Safekat y no el de CI4 $this->userModel = model(UserModel::class); $this->chatModel = model(ChatModel::class); + $this->clienteContactoModel = model(ClienteContactoModel::class); $this->chatMessageModel = model(ChatMessageModel::class); $this->chatNotificationModel = model(ChatNotification::class); $this->chatDepartmentUserModel = model(ChatDeparmentUserModel::class); @@ -64,13 +69,17 @@ class ChatService extends BaseService $this->chatEntity = $this->chatModel->find($chatId); } if ($data["client"]) { - $cliente_in_department = $this->chatDepartmentUserModel - ->where('chat_department_id', $chatDepartmentId) - ->where('user_id', $data['client']) - ->where($this->modelFkMap[$model], $modelId) - ->first(); - if ($cliente_in_department == null) { - $this->chatDepartmentUserModel->insert(['chat_department_id' => $chatDepartmentId, 'user_id' => $data['client'], $this->modelFkMap[$model] => $modelId]); + $cliente_contacto = $this->clienteContactoModel->find($data["client"]); + if ($cliente_contacto) { + $userClienteContacto = $cliente_contacto->cliente()->user(); + $cliente_in_department = $this->chatDepartmentUserModel + ->where('chat_department_id', $chatDepartmentId) + ->where('user_id', $userClienteContacto->id) + ->where($this->modelFkMap[$model], $modelId) + ->first(); + if ($cliente_in_department == null) { + $this->chatDepartmentUserModel->insert(['chat_department_id' => $chatDepartmentId, 'user_id' => $userClienteContacto->id, $this->modelFkMap[$model] => $modelId]); + } } } $userAdminDepartment = $this->chatDepartmentUserModel @@ -91,9 +100,9 @@ class ChatService extends BaseService $chat_message_id = $this->chatMessageModel->insert(["chat_id" => $this->chatEntity->id, "sender_id" => auth()->user()->id, "message" => $data["message"]]); $chatMessageEntity = $this->chatMessageModel->find($chat_message_id); if ($data["client"]) { - $userClient = $this->userModel->find($data['client']); - if ($userClient) { - $this->sendMessageNotificationEmail($chatMessageEntity, $userClient); + $cliente_contacto = $this->clienteContactoModel->find($data["client"]); + if ($cliente_contacto) { + $this->sendMessageNotificationToClienteContacto($chatMessageEntity, $cliente_contacto); } } return $chatMessageEntity; @@ -156,6 +165,7 @@ class ChatService extends BaseService ); return true; } + public function getHebras(string $model, int $modelId): array { $chats = $this->chatModel->where('chat_department_id', null) @@ -195,6 +205,23 @@ class ChatService extends BaseService ]); return $this->emailService->send($subject, $message, $toEmail); + } + public function sendMessageNotificationToClienteContacto(ChatMessageEntity $chatMessageEntity, ClienteContactoEntity $clienteContacto): bool + { + $users = auth()->getProvider(); + $toEmail = $clienteContacto->email; + $subject = '[Safekat]' . lang('Chat.mail.mail_subject') . ' - ' . $chatMessageEntity->chat()->title; + + $message = view('themes/vuexy/mail/messageNotificationClienteContacto', [ + "header" => lang('Chat.mail.mail_subject'), + "contacto" => $clienteContacto, + "data" => $chatMessageEntity, + ]); + if ($toEmail) { + return $this->emailService->send($subject, $message, $toEmail); + } else { + throw new Exception('Cliente contacto no tiene email'); + } } } diff --git a/ci4/app/Views/themes/vuexy/mail/messageNotificationClienteContacto.php b/ci4/app/Views/themes/vuexy/mail/messageNotificationClienteContacto.php new file mode 100644 index 00000000..8fe97a29 --- /dev/null +++ b/ci4/app/Views/themes/vuexy/mail/messageNotificationClienteContacto.php @@ -0,0 +1,29 @@ +extend('themes/vuexy/mail/mail_layout') ?> + +section('content'); ?> + + + +endSection() ?> \ No newline at end of file diff --git a/httpdocs/assets/js/safekat/components/chat.js b/httpdocs/assets/js/safekat/components/chat.js index 6f941544..490bb50c 100644 --- a/httpdocs/assets/js/safekat/components/chat.js +++ b/httpdocs/assets/js/safekat/components/chat.js @@ -112,9 +112,22 @@ class Chat { setInterval(this._handleReloadChatDirectMessages.bind(this), 10000) } initSelectClient() { - this.selectClientUser = new ClassSelect(this.selectItem, `/chat/direct/client/users/select/${this.chatType}/${this.modelId}`, "Seleccione contacto", true) + this.selectClientUser = new ClassSelect( + this.selectItem, `/chat/direct/client/users/select/${this.chatType}/${this.modelId}`, + "Seleccione contacto", true) + + this.selectClientUser.config.templateResult = (state) => { + let $state = $(` +
+ ${state.text} + ${state.desc ?? ''} +
`) + console.log(state) + return $state; + } this.selectClientUser.init() this.selectItem.on('change', () => { + console.log(this.selectClientUser.getVal(),this.selectClientUser.getText()) if (this.selectClientUser.getVal()) { this.sendBtnMessageDepartment.attr('disabled', null) } else { @@ -302,7 +315,7 @@ class Chat { null, null, (data) => { - + }, null @@ -364,7 +377,7 @@ class Chat {

${chatMessage?.message}

-
+
${chatMessage?.user?.first_name + " " + chatMessage?.user?.last_name}
@@ -821,7 +834,7 @@ class Chat { } -const addInternalNotification = (e) => { +const addInternalNotification = (e) => { let numberOfMessages = e.unreadMessages if (numberOfMessages > 0) { $("#chat-notification-list").append( @@ -841,7 +854,7 @@ const addInternalNotification = (e) => { ) } } -const addDepartmentNotification = (e) => { +const addDepartmentNotification = (e) => { let numberOfMessages = e.unreadMessages if (numberOfMessages > 0) { $("#chat-notification-list").append( @@ -862,8 +875,7 @@ const addDepartmentNotification = (e) => { } } -const addNotificationsToDom = (data) => -{ +const addNotificationsToDom = (data) => { $("#chat-notification-list").empty() if (data.totalMessages > 0) { $("#chat-message-notification-title").addClass("d-none") @@ -874,11 +886,13 @@ const addNotificationsToDom = (data) => $("#chat-notification-number").addClass("d-none") $("#chat-notification-number").text(0) } - data.departmentNotifications?.map( e => { - addDepartmentNotification(e)} + data.departmentNotifications?.map(e => { + addDepartmentNotification(e) + } ) data.internalNotifications?.map(e => { - addInternalNotification(e)} + addInternalNotification(e) + } ) }