import { Request, Response } from "express"; import { getIO } from "../libs/socket"; import CreateTicketService from "../services/TicketServices/CreateTicketService"; import DeleteTicketService from "../services/TicketServices/DeleteTicketService"; import ListTicketsService from "../services/TicketServices/ListTicketsService"; import ShowTicketService from "../services/TicketServices/ShowTicketService"; import UpdateTicketService from "../services/TicketServices/UpdateTicketService"; import SendWhatsAppMessage from "../services/WbotServices/SendWhatsAppMessage"; import ShowWhatsAppService from "../services/WhatsappService/ShowWhatsAppService"; import ShowStatusChatEndService from "../services/StatusChatEndService/ShowStatusChatEndService"; import CreateSchedulingNotifyService from "../services/SchedulingNotifyServices/CreateSchedulingNotifyService"; import ListSchedulingNotifyContactService from "../services/SchedulingNotifyServices/ListSchedulingNotifyContactService"; import { isScheduling } from "../helpers/CheckSchedulingReminderNotify"; import ptBR from "date-fns/locale/pt-BR"; import { splitDateTime } from "../helpers/SplitDateTime"; import format from "date-fns/format"; import ListTicketsServiceCache from "../services/TicketServices/ListTicketServiceCache"; import { searchTicketCache, loadTicketsCache } from "../helpers/TicketCache"; import { Op, where } from "sequelize"; type IndexQuery = { searchParam: string; pageNumber: string; status: string; date: string; showAll: string; withUnreadMessages: string; queueIds: string; unlimited?: string; searchParamContent?: string; }; interface TicketData { contactId: number; status: string; queueId: number; userId: number; whatsappId?: string | number; msg?: string; transfer?: boolean | undefined; fromMe?: boolean; } import ListStatusChatEndService from "../services/StatusChatEndService/ListStatusChatEndService"; import Ticket from "../models/Ticket"; import ShowUserServiceReport from "../services/UserServices/ShowUserServiceReport"; import TicketEmiterSumOpenClosedByUser from "../helpers/OnlineReporEmiterInfoByUser"; import CountTicketService from "../services/TicketServices/CountTicketService"; import CountTicketsByUserQueue from "../services/UserServices/CountTicketsByUserQueue"; import ShowUserService from "../services/UserServices/ShowUserService"; import axios from "axios"; import User from "../models/User"; import CheckContactOpenTickets from "../helpers/CheckContactOpenTickets"; import GetDefaultWhatsApp from "../helpers/GetDefaultWhatsApp"; import { getWbot } from "../libs/wbot"; import endPointQuery from "../helpers/old_EndPointQuery"; import Contact from "../models/Contact"; import BotIsOnQueue from "../helpers/BotIsOnQueue"; import { setMessageAsRead } from "../helpers/SetMessageAsRead"; import { getSettingValue } from "../helpers/WhaticketSettings"; import ListWhatsAppsForQueueService from "../services/WhatsappService/ListWhatsAppsForQueueService"; import ListWhatsAppsNumber from "../services/WhatsappService/ListWhatsAppsNumber"; import Whatsapp from "../models/Whatsapp"; import AppError from "../errors/AppError"; import CreateOrUpdateContactService from "../services/ContactServices/CreateOrUpdateContactService"; import FindOrCreateTicketService from "../services/TicketServices/FindOrCreateTicketService"; import CheckIsValidContact from "../services/WbotServices/CheckIsValidContact"; import GetProfilePicUrl from "../services/WbotServices/GetProfilePicUrl"; import CreateContactService from "../services/ContactServices/CreateContactService"; import { botSendMessage } from "../services/WbotServices/wbotMessageListener"; import WhatsappQueue from "../models/WhatsappQueue"; import { get } from "../helpers/RedisClient"; import CountStatusChatEndService from "../services/StatusChatEndService/CountStatusChatEndService"; export const index = async (req: Request, res: Response): Promise => { const { pageNumber, status, date, searchParam, showAll, queueIds: queueIdsStringified, withUnreadMessages, unlimited, searchParamContent } = req.query as IndexQuery; const userId = req.user.id; let queueIds: number[] = []; if (queueIdsStringified && queueIdsStringified.trim().length > 0) { queueIds = JSON.parse(queueIdsStringified); } const { tickets, count, hasMore } = await ListTicketsService({ searchParam, pageNumber, status, date, showAll, userId, queueIds, withUnreadMessages, unlimited, searchParamContent }); return res.status(200).json({ tickets, count, hasMore }); }; export const remoteTicketCreation = async ( req: Request, res: Response ): Promise => { let { queueId, contact_from, contact_to, msg, contact_name }: any = req.body; let whatsappId: any; if (!queueId && !contact_from) { return res .status(400) .json({ error: `Property 'queueId' or 'contact_from' is required.` }); } const validate = ["contact_to", "msg"]; const validateOnlyNumber = ["queueId", "contact_to", "contact_from"]; for (let prop of validate) { if (!req.body[prop]) return res .status(400) .json({ error: `Property '${prop}' is undefined.` }); if (validateOnlyNumber.includes(prop)) { if (!/^\d+$/.test(req.body[prop])) { return res .status(400) .json({ error: `The property '${prop}' must be a number` }); } } } if (queueId) { const whatsapps = await ListWhatsAppsForQueueService(queueId, "CONNECTED"); if (!whatsapps || whatsapps?.length == 0) { return res.status(500).json({ msg: `queueId ${queueId} does not have a WhatsApp number associated with it or the number's session is disconnected.` }); } const { id } = whatsapps[0]; whatsappId = id; } else if (contact_from) { const whatsapp = await Whatsapp.findOne({ where: { number: contact_from, status: "CONNECTED" } }); if (!whatsapp) { return res.status(404).json({ msg: `Whatsapp number ${contact_from} not found or disconnected!` }); } const { id } = whatsapp; const { queues } = await ShowWhatsAppService(id); if (!queues || queues.length == 0) { return res.status(500).json({ msg: `The WhatsApp number ${contact_from} is not associated with any queue! ` }); } queueId = queues[0].id; whatsappId = id; } // const validNumber = await CheckIsValidContact(contact_to, true); const validNumber = contact_to; if (validNumber) { let contact = await Contact.findOne({ where: { number: validNumber } }); if (!contact) { // const profilePicUrl = await GetProfilePicUrl(validNumber); contact = await CreateContactService({ name: contact_name ? contact_name : contact_to, number: validNumber // profilePicUrl }); const io = getIO(); io.emit("contact", { action: "create", contact }); } const { id: contactId } = contact; const botInfo = await BotIsOnQueue("botqueue"); let ticket = await Ticket.findOne({ where: { [Op.or]: [ { contactId, status: "queueChoice" }, { contactId, status: "open", userId: botInfo.userIdBot } ] } }); if (getSettingValue("whatsaAppCloudApi")?.value == "enabled") { if (ticket) { await UpdateTicketService({ ticketData: { status: "closed" }, ticketId: ticket.id }); ticket = null; } } else { if (ticket) { await UpdateTicketService({ ticketData: { status: "closed" }, ticketId: ticket.id }); } } if (!ticket) { ticket = await FindOrCreateTicketService( contact, whatsappId, 0, undefined, queueId ); botSendMessage(ticket, `${msg}`); } const io = getIO(); io.to(ticket.status).emit("ticket", { action: "update", ticket }); console.log( `REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 200 | MSG: success` ); return res.status(200).json({ msg: "success" }); } console.log( `REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 500 | MSG: The number ${contact_to} does not exist on WhatsApp` ); return res .status(500) .json({ msg: `The number ${contact_to} does not exist on WhatsApp` }); }; export const store = async (req: Request, res: Response): Promise => { const { contactId, status, userId, msg, queueId, whatsappId }: TicketData = req.body; const botInfo = await BotIsOnQueue("botqueue"); let ticket = await Ticket.findOne({ where: { [Op.or]: [ { contactId, status: "queueChoice" }, { contactId, status: "open", userId: botInfo.userIdBot } ] } }); if (getSettingValue("whatsaAppCloudApi")?.value == "enabled") { if (ticket) { await UpdateTicketService({ ticketData: { status: "closed" }, ticketId: ticket.id }); ticket = null; } } else { if (ticket) { await UpdateTicketService({ ticketData: { status: "open", userId: userId, queueId }, ticketId: ticket.id }); } } if (!ticket) { ticket = await CreateTicketService({ contactId, status, userId, queueId, whatsappId }); } const io = getIO(); io.to(ticket.status).emit("ticket", { action: "update", ticket }); return res.status(200).json(ticket); }; export const show = async (req: Request, res: Response): Promise => { const { ticketId } = req.params; const contact = await ShowTicketService(ticketId); const { statusChatEnd, count, hasMore } = await ListStatusChatEndService({ searchParam: "", pageNumber: "1" }); ////////////////// const schedulesContact = await ListSchedulingNotifyContactService( contact.contact.number ); ///////////////// return res.status(200).json({ contact, statusChatEnd, schedulesContact }); }; export const count = async (req: Request, res: Response): Promise => { // type indexQ = { status: string; date?: string; }; const { status, date } = req.query as IndexQuery; const ticketCount = await CountTicketService(status, date); return res.status(200).json(ticketCount); }; export const update = async ( req: Request, res: Response ): Promise => { console.log("ENTROU NO UPDATE TICKET CONTROLLER"); const { ticketId } = req.params; const userOldInfo = await Ticket.findByPk(ticketId); let ticket2 = {}; if (req.body["status"] === "closed") { const { status, userId, schedulingNotifyData } = req.body; // lembrete const scheduleData = JSON.parse(schedulingNotifyData); const statusChatEndName = await ShowStatusChatEndService( scheduleData.statusChatEndId ); const { ticket } = await UpdateTicketService({ ticketData: { status: status, userId: userId, statusChatEnd: statusChatEndName.name, statusChatEndId: statusChatEndName.id }, ticketId }); if (scheduleData.farewellMessage) { const whatsapp = await ShowWhatsAppService(ticket.whatsappId); const { farewellMessage } = whatsapp; if (farewellMessage) { await SendWhatsAppMessage({ body: farewellMessage, ticket }); } } // lembrete // agendamento if ( scheduleData.statusChatEndId === "2" || scheduleData.statusChatEndId === "3" ) { if ( isScheduling(scheduleData.schedulingDate, scheduleData.schedulingTime) ) { console.log("*** É AGENDAMENTO!"); } else { console.log("*** É LEMBRETE!"); } const schedulingNotifyCreate = await CreateSchedulingNotifyService({ ticketId: scheduleData.ticketId, statusChatEndId: scheduleData.statusChatEndId, schedulingDate: scheduleData.schedulingDate, schedulingTime: scheduleData.schedulingTime, message: scheduleData.message }); } ticket2 = ticket; } else { // Para aparecer pendente para todos usuarios que estao na fila if (req.body.transfer) { req.body.userId = null; } let ticketData: TicketData = req.body; if (getSettingValue("oneContactChatWithManyWhats")?.value == "enabled") { if (ticketData.transfer) { const whatsappsByqueue = await ListWhatsAppsForQueueService( ticketData.queueId ); if (userOldInfo) { let listTicketOpenPending: any = []; for (const w of whatsappsByqueue) { let whats = await ListWhatsAppsNumber(w.id); const ticket = await Ticket.findOne({ where: { [Op.and]: [ { contactId: userOldInfo.contactId }, { whatsappId: { [Op.in]: whats.whatsapps.map((w: any) => w.id) } }, { status: { [Op.or]: ["open", "pending"] } } ] } }); if (ticket) { listTicketOpenPending.push({ ticketId: ticket.id, status: ticket.status, userId: ticket.userId, contactId: ticket.contactId, whatsappId: ticket.whatsappId, queueId: ticket.queueId }); } } // console.log("userOldInfo: ", JSON.stringify(userOldInfo, null, 6)); // console.log("##########") // console.log( // "listTicketOpenPending: ", // JSON.stringify(listTicketOpenPending) // ); if ( listTicketOpenPending.filter( (ob: any) => userOldInfo.whatsappId != ob.whatsappId )?.length > 0 ) { throw new AppError("ERR_OTHER_OPEN_TICKET"); } } ////////////////////////////////////////////// // const defaultWhatsapp: any = await GetDefaultWhatsApp({ // userId: ticketData.userId // }); // console.log( // "ticketData.userId: ", // ticketData.userId, // " | defaultWhatsapp: ", // JSON.stringify(defaultWhatsapp, null, 6) // ); // const _ticket: any = await Ticket.findByPk(ticketId); // if (defaultWhatsapp && ticketData.status != "open") { // await CheckContactOpenTickets( // _ticket.dataValues.contactId, // defaultWhatsapp.dataValues.id // ); // } // ticketData.whatsappId = defaultWhatsapp.dataValues.id; } } console.log( "--------> ticketData.status: ", ticketData.status, " | ticketData.fromMe: ", ticketData.fromMe ); const { ticket } = await UpdateTicketService({ ticketData, ticketId }); if (ticketData.status == "open" && !ticketData.fromMe) { await setMessageAsRead(ticket); } if (ticketData.userId) { const dateToday = splitDateTime( new Date(format(new Date(), "yyyy-MM-dd HH:mm:ss", { locale: ptBR })) ); TicketEmiterSumOpenClosedByUser( ticketData.userId.toString(), dateToday.fullDate, dateToday.fullDate ); } ticket2 = ticket; } if (userOldInfo) { const dateToday = splitDateTime( new Date(format(new Date(), "yyyy-MM-dd HH:mm:ss", { locale: ptBR })) ); if (userOldInfo.userId) { TicketEmiterSumOpenClosedByUser( userOldInfo.userId.toString(), dateToday.fullDate, dateToday.fullDate ); } } return res.status(200).json(ticket2); }; // export const update = async ( // req: Request, // res: Response // ): Promise => { // const { ticketId } = req.params; // const ticketData: TicketData = req.body; // const { ticket } = await UpdateTicketService({ // ticketData, // ticketId // }); // if (ticket.status === "closed") { // const whatsapp = await ShowWhatsAppService(ticket.whatsappId); // const { farewellMessage } = whatsapp; // if (farewellMessage) { // await SendWhatsAppMessage({ body: farewellMessage, ticket }); // } // } // return res.status(200).json(ticket); // }; export const remove = async ( req: Request, res: Response ): Promise => { const { ticketId } = req.params; const ticket = await DeleteTicketService(ticketId); const io = getIO(); io.to(ticket.status).to(ticketId).to("notification").emit("ticket", { action: "delete", ticketId: +ticketId }); return res.status(200).json({ message: "ticket deleted" }); };