Merge branch 'feat/message-direct-cliente' into 'main'

send direct message to client users from presupuesto,facturas or pedido forms

See merge request jjimenez/safekat!441
This commit is contained in:
Alvaro
2024-12-15 16:58:19 +00:00
12 changed files with 288 additions and 12 deletions

View File

@ -795,6 +795,11 @@ $routes->group('chat', ['namespace' => 'App\Controllers\Chat'], function ($route
$routes->get('direct/conversation/(:num)', 'ChatController::get_chat_direct/$1', ['as' => 'getChatDirect']);
$routes->get('direct/users/select/(:num)', 'ChatController::get_chat_direct_select_users/$1', ['as' => 'getChatDirectSelectUsers']);
$routes->get('direct/client/users/select/presupuesto/(:num)', 'ChatController::get_presupuesto_client_users/$1/$2', ['as' => 'getPresupuestoClientUsers']);
$routes->get('direct/client/users/select/pedido/(:num)', 'ChatController::get_pedido_client_users/$1/$2', ['as' => 'getPedidoClientUsers']);
$routes->get('direct/client/users/select/factura/(:num)', 'ChatController::get_factura_client_users/$1/$2', ['as' => 'getFacturaClientUsers']);
$routes->get('direct/users/(:num)', 'ChatController::get_chat_direct_users', ['as' => 'getChatDirectUsers']);
$routes->post('direct/users/(:num)', 'ChatController::store_chat_direct_users/$1', ['as' => 'storeChatDirectUsers']);
$routes->get('direct/messages/(:num)', 'ChatController::get_chat_direct_messages/$1', ['as' => 'getChatDirectMessages']);

View File

@ -10,6 +10,9 @@ use App\Models\Chat\ChatModel;
use App\Models\ChatNotification;
use App\Models\ChatUser;
use App\Models\Clientes\ClienteModel;
use App\Models\Facturas\FacturaModel;
use App\Models\Pedidos\PedidoModel;
use App\Models\Presupuestos\PresupuestoModel;
use App\Models\Usuarios\UserModel;
use App\Services\MessageService;
use CodeIgniter\HTTP\ResponseInterface;
@ -396,6 +399,72 @@ class ChatController extends BaseController
return $this->response->setJSON($query->get()->getResultObject());
}
public function get_presupuesto_client_users(int $presupuesto_id)
{
$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());
}
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());
}
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());
}
public function store_hebra_presupuesto()
{
$auth_user = auth()->user();

View File

@ -1,6 +1,10 @@
<?php
namespace App\Entities\Pedidos;
use App\Entities\Clientes\ClienteEntity;
use App\Models\Clientes\ClienteModel;
use App\Models\Pedidos\PedidoLineaModel;
use App\Models\Presupuestos\PresupuestoModel;
use CodeIgniter\Entity;
class PedidoEntity extends \CodeIgniter\Entity\Entity
@ -27,4 +31,14 @@ class PedidoEntity extends \CodeIgniter\Entity\Entity
"total_precio" => "float",
"total_tirada" => "float",
];
public function cliente() : ?ClienteEntity
{
$m = model(ClienteModel::class);
$pl = model(PedidoLineaModel::class);
$pm = model(PresupuestoModel::class);
$pedido_linea = $pl->where('pedido_id',$this->attributes["id"])->first();
$pre = $pm->find($pedido_linea->presupuesto_id);
return $m->find($pre->cliente_id);
}
}

View File

@ -1,4 +1,9 @@
<div class="col-md-12" id="chat-factura" data-id="<?= $modelId ?>">
<?php if (auth()->user()->inGroup('admin')) { ?>
<div class="d-flex justify-content-start align-items-start gap-2 mb-3">
<button class="btn btn-primary btn-md" id="direct-message-cliente"><i class="ti ti-xs ti-message"></i> Mensaje directo a cliente</button>
</div>
<?php } ?>
<div class="app-chat card overflow-hidden">
<div class="row g-0">
@ -119,6 +124,8 @@
<div class="app-overlay"></div>
</div>
</div>
<?= view("themes/vuexy/components/modals/modalNewDirectMessageClient", ["modelId" => $modelId]) ?>
</div>
<?= $this->section('css') ?>

View File

@ -1,5 +1,9 @@
<div class="col-md-12" id="chat-pedido" data-id="<?= $modelId ?>">
<?php if (auth()->user()->inGroup('admin')) { ?>
<div class="d-flex justify-content-start align-items-start gap-2 mb-3">
<button class="btn btn-primary btn-md" id="direct-message-cliente"><i class="ti ti-xs ti-message"></i> Mensaje directo a cliente</button>
</div>
<?php } ?>
<div class="app-chat card overflow-hidden">
<div class="row g-0">
@ -117,6 +121,8 @@
<div class="app-overlay"></div>
</div>
</div>
<?= view("themes/vuexy/components/modals/modalNewDirectMessageClient", ["modelId" => $modelId]) ?>
</div>

View File

@ -1,7 +1,11 @@
<div class="col-md-12" id="chat-presupuesto" data-id="<?= $modelId ?>">
<div class="app-chat card overflow-hidden">
<?php if (auth()->user()->inGroup('admin')) { ?>
<div class="d-flex justify-content-start align-items-start gap-2 mb-3">
<button class="btn btn-primary btn-md" id="direct-message-cliente"><i class="ti ti-xs ti-message"></i> Mensaje directo a cliente</button>
</div>
<?php } ?>
<div class="app-chat card overflow-hidden border">
<div class="row g-0">
<!-- Chat & Contacts -->
<div class="col app-chat-contacts app-sidebar flex-grow-0 overflow-hidden border-end"
id="app-chat-contacts">
@ -30,8 +34,8 @@
</div>
<!-- Chats -->
<ul class="list-unstyled chat-contact-list" id="chat-list">
<!-- CHAT LIST -->
</ul>
@ -116,6 +120,7 @@
<div class="app-overlay"></div>
</div>
</div>
<?= view("themes/vuexy/components/modals/modalNewDirectMessageClient", ["modelId" => $modelId]) ?>
</div>
<?= $this->section('css') ?>

View File

@ -0,0 +1,47 @@
<!-- Modal -->
<div class="modal fade" id="modalNewDirectMessageClient" tabindex="-1" aria-hidden="true" data-id=<?= $modelId ?>>
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel1"><?= lang('Chat.modal.new_message') ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="col-12 mb-0">
<?= view("themes/vuexy/components/alerts/alert", ["id" => "alertDirectMessage"]) ?>
</div>
<form id="new-direct-message-form">
<div class="form-group">
<div class="row">
<div class="col-12 mb-0">
<label for="new-direct-message-title" class="form-label"><?= lang('Chat.modal.title') ?></label>
<input type="input" rows="4" cols="10" id="new-direct-message-cliente-title" name="title" placeholder="Escriba un título" name="title" class="form-control" required />
</div>
<div class="col-12 mb-0">
<label for="description" class="required form-label"><?= lang('Chat.modal.new_message') ?></label>
<textarea type="input" rows="4" cols="10" id="new-direct-message-cliente-text" name="message" placeholder="Escribe el mensaje ..." name="message" class="form-control" required></textarea>
</div>
<div class="col-12 mb-0">
<label for="select-clients" class="required form-label"><?= lang('Chat.modal.new_receivers') ?></label>
<select id="select-clients" name="clientes" class="form-control" multiple required>
<option value="0"></option>
</select>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-label-secondary" data-bs-dismiss="modal"><?= lang('App.global_come_back') ?></button>
<?php if (auth()->user()->inGroup('admin')) { ?>
<button type="button" id="submit-new-direct-message-client" class="btn btn-primary"><?= lang('Chat.modal.btn_send') ?></button>
<?php } ?>
</div>
</div>
</div>
</div>

View File

@ -7,6 +7,8 @@ class Alert {
this.icon = this.item.find(".icon-alert")
this.iconSuccess = "ti-circle-check"
this.iconError = "ti-exclamation-mark"
this.iconInfo = "ti-question-mark"
@ -14,6 +16,7 @@ class Alert {
setIcon(iconClass){
this.icon.removeClass(this.iconSuccess)
this.icon.removeClass(this.iconError)
this.icon.removeClass(this.iconInfo)
this.icon.addClass(iconClass)
}
setAsError() {
@ -24,16 +27,25 @@ class Alert {
}
setAsSuccess() {
this.item.removeClass("alert-danger")
this.item.removeClass("alert-warning")
this.item.removeClass("alert-info")
this.item.addClass("alert-success")
this.setIcon(this.iconSuccess)
}
setAsWarning() {
this.item.removeClass("alert-success")
this.item.removeClass("alert-danger")
this.item.removeClass("alert-info")
this.item.addClass("alert-warning")
this.setIcon(this.iconError)
}
setAsInfo() {
this.item.removeClass("alert-*")
this.item.removeClass("alert-success")
this.item.removeClass("alert-danger")
this.item.addClass("alert-warning")
this.item.addClass("alert-info")
this.setIcon(this.iconInfo)
}
show() {
this.item.removeClass("d-none")
@ -48,6 +60,16 @@ class Alert {
this.body.append(content)
}
setErrors() { }
reset(){
this.item.removeClass("alert-success")
this.item.removeClass("alert-danger")
this.item.removeClass("alert-warning")
this.item.removeClass("alert-info")
this.item.setContent("")
this.item.setHeadingTitle("")
this.item.hide()
}
}
export default Alert;

View File

@ -0,0 +1,85 @@
import Ajax from "../ajax.js";
import Modal from "../modal.js"
import ClassSelect from "../select2.js";
import Alert from "../alerts/alert.js";
class ModalDirectMessageClient {
constructor(model="presupuesto",domItem = null) {
this.item = domItem
this.modal = new Modal(domItem)
this.alert = new Alert(this.item.find("#alertDirectMessage"))
this.modelId = this.item.data("id");
this.selectItem = this.item.find("#select-clients")
this.model = model
this.selectClientUser = new ClassSelect(this.selectItem,`/chat/direct/client/users/select/${this.model}/${this.modelId}`,"Seleccione contacto",true)
this.messageInput = this.item.find("#new-direct-message-cliente-text")
this.title = this.item.find("#new-direct-message-cliente-title")
this.btnSubmitMessage = this.item.find("#submit-new-direct-message-client")
}
init() {
this.selectClientUser.init()
this.modal.item.on("hidden.bs.modal",this.reset_close.bind(this))
this.modal.item.on("shown.bs.modal",this.reset_show.bind(this))
this.btnSubmitMessage.on("click",this._handleStoreChatDirectMessage.bind(this))
}
reset(){
this.messageInput.val("")
this.title.val("")
this.selectClientUser.reset();
}
reset_close(){
this.messageInput.val("")
this.title.val("")
this.selectClientUser.reset();
this.alert.hide()
this.alert.setHeadingTitle("")
this.alert.setContent("")
this.alert.setAsSuccess()
}
reset_show(){
this.messageInput.val("")
this.title.val("")
this.selectClientUser.reset();
this.alert.hide()
this.alert.setHeadingTitle("")
this.alert.setContent("")
this.alert.setAsSuccess()
}
_handleStoreChatDirectMessage() {
const data = { "message": this.messageInput.val(), "title": this.title.val() , "users" : this.selectClientUser.getVal() }
if (data.message) {
const ajax = new Ajax(
`/messages/direct`,
data,
null,
this._handleStoreNewDirectMessageSuccess.bind(this),
this._handleStoreNewDirectMessageError.bind(this)
)
ajax.post()
}else{
this.alert.show()
this.alert.setAsWarning()
this.alert.setHeadingTitle("Tienes que añadir un mensaje")
}
}
_handleStoreNewDirectMessageSuccess(response) {
try {
this.alert.setAsSuccess()
this.alert.setHeadingTitle(response.message)
this.alert.setContent(response.message)
this.alert.show()
} catch (error) {
} finally {
this.reset()
}
}
_handleStoreNewDirectMessageError(error){
this.alert.setHeadingTitle(error.message)
this.alert.setAsError()
this.alert.setContent(JSON.stringify(error.errors))
this.alert.show()
}
}
export default ModalDirectMessageClient

View File

@ -1,5 +1,6 @@
import Chat from '../components/chat.js'
import InternalMessages from "../components/internalMessagesSection.js"
import ModalDirectMessageClient from '../components/modals/modalDirectMessageClient.js'
$(document).ready(() => {
let chat = new Chat($("#chat-factura"))
@ -9,5 +10,9 @@ $(document).ready(() => {
let internalMessages = new InternalMessages($("#internal_messages_chat"))
internalMessages.init()
}
let modalDirectMessageClient = new ModalDirectMessageClient("factura", $("#modalNewDirectMessageClient"))
modalDirectMessageClient.init()
$("#direct-message-cliente").on("click",() => {
modalDirectMessageClient.modal.show()
})
})

View File

@ -1,5 +1,6 @@
import Chat from '../components/chat.js'
import InternalMessages from "../components/internalMessagesSection.js"
import ModalDirectMessageClient from '../components/modals/modalDirectMessageClient.js'
$(document).ready(() => {
let chat = new Chat($("#chat-pedido"))
@ -9,5 +10,10 @@ $(document).ready(() => {
let internalMessages = new InternalMessages($("#internal_messages_chat"))
internalMessages.init()
}
let modalDirectMessageClient = new ModalDirectMessageClient("pedido", $("#modalNewDirectMessageClient"))
modalDirectMessageClient.init()
$("#direct-message-cliente").on("click",() => {
modalDirectMessageClient.modal.show()
})
})

View File

@ -1,13 +1,18 @@
import Chat from '../components/chat.js'
import InternalMessages from "../components/internalMessagesSection.js"
$(document).ready(() => {
import ModalDirectMessageClient from '../components/modals/modalDirectMessageClient.js'
$(function () {
let chat = new Chat($("#chat-presupuesto"))
chat.init()
chat.initPresupuesto()
if($("#internal_messages_chat").length > 0){
let internalMessages = new InternalMessages($("#internal_messages_chat"))
internalMessages.init()
if ($("#internal_messages_chat").length > 0) {
let internalMessages = new InternalMessages($("#internal_messages_chat"))
internalMessages.init()
let modalDirectMessageClient = new ModalDirectMessageClient("presupuesto", $("#modalNewDirectMessageClient"))
modalDirectMessageClient.init()
$("#direct-message-cliente").on("click",() => {
modalDirectMessageClient.modal.show()
})
}
})