diff --git a/TEST_SERVER1/whats/app.js b/TEST_SERVER1/whats/app.js index 62f316e..f8c030e 100644 --- a/TEST_SERVER1/whats/app.js +++ b/TEST_SERVER1/whats/app.js @@ -183,11 +183,17 @@ socketIo.on('connect_error', async function (err) { }) // +const wwebVersion = '2.2402.5'; + //NOVA OPÇÃO MD client = new Client({ authStrategy: new LocalAuth({ clientId: 'omnihit_sesssion' }), puppeteer: { args: ['--no-sandbox', '--disable-setuid-sandbox'], executablePath: process.env.CHROME_BIN || '/usr/bin/google-chrome-stable' }, + webVersionCache: { + type: 'remote', + remotePath: `https://raw.githubusercontent.com/wppconnect-team/wa-version/main/html/${wwebVersion}.html`, + }, }) client.initialize() diff --git a/backend/src/controllers/QueueController.ts b/backend/src/controllers/QueueController.ts index 493b951..eeb3703 100644 --- a/backend/src/controllers/QueueController.ts +++ b/backend/src/controllers/QueueController.ts @@ -8,6 +8,9 @@ import UpdateQueueService from "../services/QueueService/UpdateQueueService"; import Queue from "../models/Queue"; import AppError from "../errors/AppError"; import { del, get, set } from "../helpers/RedisClient"; +import { Op } from "sequelize"; +import ListWhatsAppsService from "../services/WhatsappService/ListWhatsAppsService"; +import Whatsapp from "../models/Whatsapp"; export const index = async (req: Request, res: Response): Promise => { const queues = await ListQueuesService(); @@ -15,6 +18,58 @@ export const index = async (req: Request, res: Response): Promise => { return res.status(200).json(queues); }; +export const listQueues = async ( + req: Request, + res: Response +): Promise => { + const whatsapps = await Whatsapp.findAll({ + where: { + name: { [Op.ne]: "botqueue" }, + number: { [Op.ne]: "" }, + phoneNumberId: false + }, + attributes: ["number"], + include: [ + { + model: Queue, + as: "queues", + attributes: ["id", "name"] + } + ] + }); + + const whats = whatsapps + ?.filter((w: any) => w?.queues?.length > 0) + ?.map((w: any) => { + const { number, queues } = w; + return { + number, + queues: queues?.map((q: any) => { + const { id, name } = q; + return { id, name }; + }) + }; + }); + + let _queues: any = []; + + for (const w of whats) { + const { queues } = w; + + for (const q of queues) { + const { id: queueId, name } = q; + + const auxQueue = _queues.findIndex((q: any) => q.queueId == queueId); + + if (auxQueue == -1) { + _queues.push({ queueId, name }); + } + } + } + + return res.status(200).json(_queues); +}; + export const store = async (req: Request, res: Response): Promise => { const { name, color, greetingMessage } = req.body; diff --git a/backend/src/controllers/ReportController.ts b/backend/src/controllers/ReportController.ts index a2956f0..d7d70b3 100644 --- a/backend/src/controllers/ReportController.ts +++ b/backend/src/controllers/ReportController.ts @@ -262,9 +262,7 @@ export const reportMessagesUserByDateStartDateEnd = async ( data_query_messages[i].fromMe = "Cliente"; } - data_query_messages[i].id = i + 1; - - console.log("data_query_messages: ", data_query_messages[i]); + data_query_messages[i].id = i + 1; } return res.status(200).json(data_query_messages); diff --git a/backend/src/controllers/SettingController.ts b/backend/src/controllers/SettingController.ts index d131ceb..e1d0e46 100644 --- a/backend/src/controllers/SettingController.ts +++ b/backend/src/controllers/SettingController.ts @@ -20,14 +20,14 @@ export const index = async (req: Request, res: Response): Promise => { // const config = await SettingTicket.findAll(); - return res.status(200).json({ settings, }); + return res.status(200).json({ settings }); }; export const ticketSettings = async ( req: Request, res: Response ): Promise => { - const { number } = req.params; + const { number } = req.params; const config = await SettingTicket.findAll({ where: { number } }); @@ -40,6 +40,7 @@ export const updateTicketSettings = async ( ): Promise => { const { number, + saturdayBusinessTime, outBusinessHours, ticketExpiration, weekend, @@ -47,7 +48,7 @@ export const updateTicketSettings = async ( sunday, holiday } = req.body; - + if (!number) throw new AppError("No number selected", 400); if (outBusinessHours && Object.keys(outBusinessHours).length > 0) { @@ -58,6 +59,14 @@ export const updateTicketSettings = async ( }); } + if (saturdayBusinessTime && Object.keys(saturdayBusinessTime).length > 0) { + await updateSettingTicket({ + ...saturdayBusinessTime, + key: "saturdayBusinessTime", + number + }); + } + if (ticketExpiration && Object.keys(ticketExpiration).length > 0) { await updateSettingTicket({ ...ticketExpiration, diff --git a/backend/src/controllers/TicketController.ts b/backend/src/controllers/TicketController.ts index e8f327c..549e460 100644 --- a/backend/src/controllers/TicketController.ts +++ b/backend/src/controllers/TicketController.ts @@ -75,10 +75,10 @@ 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" +import { get } from "../helpers/RedisClient"; +import CountStatusChatEndService from "../services/StatusChatEndService/CountStatusChatEndService"; -export const index = async (req: Request, res: Response): Promise => { +export const index = async (req: Request, res: Response): Promise => { const { pageNumber, status, @@ -110,8 +110,8 @@ export const index = async (req: Request, res: Response): Promise => { withUnreadMessages, unlimited, searchParamContent - }); - + }); + return res.status(200).json({ tickets, count, hasMore }); }; @@ -119,10 +119,10 @@ export const remoteTicketCreation = async ( req: Request, res: Response ): Promise => { - const { contact_from, contact_to, msg, contact_name }: any = req.body; + const { queueId, contact_to, msg, contact_name }: any = req.body; - const validate = ["contact_from", "contact_to", "msg"]; - const validateOnlyNumber = ["contact_from", "contact_to"]; + const validate = ["queueId", "contact_to", "msg"]; + const validateOnlyNumber = ["queueId", "contact_to"]; for (let prop of validate) { if (!req.body[prop]) @@ -139,109 +139,97 @@ export const remoteTicketCreation = async ( } } - const whatsapp = await Whatsapp.findOne({ - where: { number: contact_from, status: "CONNECTED" } - }); + const whatsapps = await ListWhatsAppsForQueueService(queueId, "CONNECTED"); - if (whatsapp) { - const { id: whatsappId, number, status } = whatsapp; - - const queue: any = await WhatsappQueue.findOne({ - where: { whatsappId }, - attributes: ["queueId"] + 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 { queueId } = queue; + const { id: whatsappId } = whatsapps[0]; - // const validNumber = await CheckIsValidContact(contact_to, true); - const validNumber = contact_to; + // const validNumber = await CheckIsValidContact(contact_to, true); + const validNumber = contact_to; - if (validNumber) { - let contact = await Contact.findOne({ where: { number: validNumber } }); + if (validNumber) { + let contact = await Contact.findOne({ where: { number: validNumber } }); - if (!contact) { - // const profilePicUrl = await GetProfilePicUrl(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 } - ] - } + contact = await CreateContactService({ + name: contact_name ? contact_name : contact_to, + number: validNumber + // profilePicUrl }); - 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 + io.emit("contact", { + action: "create", + contact }); - - console.log( - `REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 200 | MSG: success` - ); - return res.status(200).json({ msg: "success" }); } + 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: 500 | MSG: The number ${contact_to} does not exist on WhatsApp` + `REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 200 | MSG: success` ); - return res - .status(500) - .json({ msg: `The number ${contact_to} does not exist on WhatsApp` }); + return res.status(200).json({ msg: "success" }); } console.log( - `REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 500 | MSG: Whatsapp number ${contact_from} disconnected or it doesn't exist in omnihit` + `REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 500 | MSG: The number ${contact_to} does not exist on WhatsApp` ); - return res.status(500).json({ - msg: `Whatsapp number ${contact_from} disconnected or it doesn't exist in omnihit` - }); + return res + .status(500) + .json({ msg: `The number ${contact_to} does not exist on WhatsApp` }); }; export const store = async (req: Request, res: Response): Promise => { @@ -408,7 +396,6 @@ export const update = async ( for (const w of whatsappsByqueue) { let whats = await ListWhatsAppsNumber(w.id); - console.log("-------> WHATS: ", JSON.stringify(whats, null, 6)); const ticket = await Ticket.findOne({ where: { [Op.and]: [ diff --git a/backend/src/database/seeds/20240328181254-add-setting-ticket-saturday-business-time.ts b/backend/src/database/seeds/20240328181254-add-setting-ticket-saturday-business-time.ts new file mode 100644 index 0000000..60c411d --- /dev/null +++ b/backend/src/database/seeds/20240328181254-add-setting-ticket-saturday-business-time.ts @@ -0,0 +1,25 @@ +import { QueryInterface } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.bulkInsert( + "SettingTickets", + [ + { + message: "", + startTime: new Date(), + endTime: new Date(), + value: "disabled", + key: "saturdayBusinessTime", + createdAt: new Date(), + updatedAt: new Date() + } + ], + {} + ); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.bulkDelete("SettingTickets", {}); + } +}; diff --git a/backend/src/helpers/TicketConfig.ts b/backend/src/helpers/TicketConfig.ts index 0f7416e..fe29a61 100644 --- a/backend/src/helpers/TicketConfig.ts +++ b/backend/src/helpers/TicketConfig.ts @@ -39,7 +39,7 @@ const isHoliday = async (number: string | number) => { locale: ptBR }) ) - ); + ); if (currentDate.fullDate == startTime.fullDate) { obj.set = true; @@ -62,21 +62,8 @@ const isWeekend = async (number: string | number) => { weekend.value == "enabled" && weekend.message?.trim()?.length > 0 ) { - // Specify your desired timezone - const brazilTimeZone = "America/Sao_Paulo"; - - const currentDateUtc = new Date(); - - // Convert UTC date to Brazil time zone - const currentDate = utcToZonedTime(currentDateUtc, brazilTimeZone); - - // Format the date using the desired format - const formattedDate = _format(currentDate, "yyyy-MM-dd HH:mm:ssXXX"); - - const parsedDate = parseISO(formattedDate); - // Convert parsed date to Brazil time zone - const localDate = utcToZonedTime(parsedDate, brazilTimeZone); + const localDate = localDateConvert(); // Check if it's Saturday or Sunday if (isSaturday(localDate)) { @@ -173,8 +160,104 @@ async function isOutBusinessTime(number: string | number) { return obj; } -export { - isWeekend, - isHoliday, - isOutBusinessTime -}; +async function isOutBusinessTimeSaturday(number: string | number) { + let obj = { set: false, msg: "" }; + + // Convert parsed date to Brazil time zone + const localDate = localDateConvert(); + + // Check if it's Saturday or Sunday + if (!isSaturday(localDate)) { + return obj; + } + + const outBusinessHoursSaturday = await SettingTicket.findOne({ + where: { key: "saturdayBusinessTime", number } + }); + + let isWithinRange = false; + + if ( + outBusinessHoursSaturday && + outBusinessHoursSaturday.value == "enabled" && + outBusinessHoursSaturday?.message?.trim()?.length > 0 + ) { + const ticketDateTimeUpdate = splitDateTime( + new Date( + _format(new Date(), "yyyy-MM-dd HH:mm:ss", { + locale: ptBR + }) + ) + ); + + const startTime = splitDateTime( + new Date( + _format( + new Date(outBusinessHoursSaturday.startTime), + "yyyy-MM-dd HH:mm:ss", + { + locale: ptBR + } + ) + ) + ); + + const endTime = splitDateTime( + new Date( + _format( + new Date(outBusinessHoursSaturday.endTime), + "yyyy-MM-dd HH:mm:ss", + { + locale: ptBR + } + ) + ) + ); + + const format = "HH:mm:ss"; + const parsedStartTime = parse( + ticketDateTimeUpdate.fullTime, + format, + new Date() + ); + const parsedEndTime = parse(startTime.fullTime, format, new Date()); + const parsedTimeToCheck = parse(endTime.fullTime, format, new Date()); + const timeInterval = { start: parsedStartTime, end: parsedEndTime }; + + // If the time range spans across different days, handle the date part + if (parsedEndTime < parsedStartTime) { + const nextDay = new Date(parsedStartTime); + nextDay.setDate(nextDay.getDate() + 1); + timeInterval.end = nextDay; + } + + isWithinRange = isWithinInterval(parsedTimeToCheck, timeInterval); + + if (!isWithinRange) { + obj.set = true; + obj.msg = outBusinessHoursSaturday.message; + } + } + + return obj; +} + +function localDateConvert() { + const brazilTimeZone = "America/Sao_Paulo"; + + const currentDateUtc = new Date(); + + // Convert UTC date to Brazil time zone + const currentDate = utcToZonedTime(currentDateUtc, brazilTimeZone); + + // Format the date using the desired format + const formattedDate = _format(currentDate, "yyyy-MM-dd HH:mm:ssXXX"); + + const parsedDate = parseISO(formattedDate); + + // Convert parsed date to Brazil time zone + const localDate = utcToZonedTime(parsedDate, brazilTimeZone); + return localDate; +} + +export { isWeekend, isHoliday, isOutBusinessTime, isOutBusinessTimeSaturday }; diff --git a/backend/src/middleware/isAuth.ts b/backend/src/middleware/isAuth.ts index b19552e..91061fc 100644 --- a/backend/src/middleware/isAuth.ts +++ b/backend/src/middleware/isAuth.ts @@ -19,10 +19,11 @@ const isAuth = (req: Request, res: Response, next: NextFunction): void => { throw new AppError("ERR_SESSION_EXPIRED", 401); } - const [, token] = authHeader.split(" "); + const [, token] = authHeader.split(" "); if ( - req.originalUrl == "/tickets/remote/create" && + (req.originalUrl == "/queue/remote/list" || + req.originalUrl == "/tickets/remote/create") && token === process.env.TOKEN_REMOTE_TICKET_CREATION ) { return next(); diff --git a/backend/src/routes/queueRoutes.ts b/backend/src/routes/queueRoutes.ts index 6de13d9..96bb509 100644 --- a/backend/src/routes/queueRoutes.ts +++ b/backend/src/routes/queueRoutes.ts @@ -11,6 +11,8 @@ queueRoutes.post("/queue", isAuth, QueueController.store); queueRoutes.post("/queue/customization", QueueController.customization); +queueRoutes.get("/queue/remote/list", isAuth, QueueController.listQueues); + queueRoutes.get("/queue/:queueId", isAuth, QueueController.show); queueRoutes.put("/queue/:queueId", isAuth, QueueController.update); diff --git a/backend/src/services/TicketServices/ShowTicketReport.ts b/backend/src/services/TicketServices/ShowTicketReport.ts index f26919a..1c4b1ea 100644 --- a/backend/src/services/TicketServices/ShowTicketReport.ts +++ b/backend/src/services/TicketServices/ShowTicketReport.ts @@ -18,6 +18,7 @@ import { startOfDay, endOfDay, parseISO, getDate } from "date-fns"; import { string } from "yup/lib/locale"; import Whatsapp from "../../models/Whatsapp"; import Query from "mysql2/typings/mysql/lib/protocol/sequences/Query"; +import { te } from "date-fns/locale"; interface Request { userId: string | number; @@ -43,43 +44,56 @@ const ShowTicketReport = async ({ createdOrUpdated = "created", queueId }: Request): Promise => { - let where_clause: any = {}; - let query = ""; + // let where_clause: any = {}; + // let query = ""; - if (userId !== "0") { - where_clause.userid = userId; - query = `AND t.userId = ${userId}`; - } + // if (userId !== "0") { + // where_clause.userid = userId; + // query = `AND t.userId = ${userId}`; + // } + + // if (queueId) { + // where_clause.queueId = queueId; + // query = `AND t.queueId = ${queueId}`; + // } + + const createdAtOrUpdatedAt = + createdOrUpdated == "created" ? "createdAt" : "updatedAt"; + + let where_clause = {}; if (queueId) { - where_clause.queueId = queueId; - query = `AND t.queueId = ${queueId}`; + where_clause = { + queueId: queueId, + [createdAtOrUpdatedAt]: { + [Op.gte]: startDate + " 00:00:00.000000", + [Op.lte]: endDate + " 23:59:59.999999" + } + }; + } else if (userId == "0") { + where_clause = { + [createdAtOrUpdatedAt]: { + [Op.gte]: startDate + " 00:00:00.000000", + [Op.lte]: endDate + " 23:59:59.999999" + } + }; + } else if (userId != "0") { + where_clause = { + userid: userId, + [createdAtOrUpdatedAt]: { + [Op.gte]: startDate + " 00:00:00.000000", + [Op.lte]: endDate + " 23:59:59.999999" + } + }; } const limit = 40; const offset = limit * (+pageNumber - 1); - const createdAtOrUpdatedAt = - createdOrUpdated == "created" ? "createdAt" : "updatedAt"; - - const _ticketsId = await sequelize.query( - `SELECT t.id - FROM Tickets t - INNER JOIN ( - SELECT DISTINCT ticketId - FROM Messages - WHERE ${createdAtOrUpdatedAt} >= '${startDate} 00:00:00' AND ${createdAtOrUpdatedAt} <= '${endDate} 23:59:59' - ) AS m ON m.ticketId = t.id ${query};`, - { type: QueryTypes.SELECT } - ); - let { count, rows: tickets }: any = await Ticket.findAndCountAll({ - where: { - id: { [Op.in]: _ticketsId.map((t: any) => t.id) } - }, + where: where_clause, limit, offset, - attributes: [ "id", "status", @@ -151,43 +165,41 @@ const ShowTicketReport = async ({ throw new AppError("ERR_NO_TICKET_FOUND", 404); } - const ticketIds = tickets.map((t: any) => t.id); - - if (ticketIds.length > 0) { + if (tickets.length > 0) { const waiting_time: any = await sequelize.query( `SELECT t.id as ticketId, t.status, TIME_FORMAT( - SEC_TO_TIME( + SEC_TO_TIME( TIMESTAMPDIFF( SECOND, ( - SELECT createdAt - FROM Messages - WHERE ticketId = m.ticketId - AND fromMe = 0 - ORDER BY createdAt ASC + SELECT createdAt + FROM Messages + WHERE ticketId = m.ticketId + AND fromMe = 0 + ORDER BY createdAt ASC LIMIT 1 - ), + ), ( - SELECT createdAt - FROM Messages - WHERE ticketId = m.ticketId - AND fromAgent = 1 - ORDER BY createdAt ASC + SELECT createdAt + FROM Messages + WHERE ticketId = m.ticketId + AND fromAgent = 1 + ORDER BY createdAt ASC LIMIT 1 ) - ) - ), '%H:%i:%s') AS WAITING_TIME - FROM Tickets t + ) + ), '%H:%i:%s') AS WAITING_TIME + FROM Tickets t JOIN Messages m ON t.id = m.ticketId JOIN Whatsapps w ON t.whatsappId = w.id JOIN Queues q ON q.id = t.queueId - WHERE DATE(m.createdAt) BETWEEN '${startDate} 00:00:00.000000' AND '${endDate} 23:59:59.999999' - AND t.id IN (${ticketIds.join()}) - AND m.createdAt = (SELECT MIN(createdAt) FROM Messages WHERE ticketId = t.id) - AND m.fromMe = 0 + WHERE DATE(m.createdAt) BETWEEN '${startDate} 00:00:00.000000' AND '${endDate} 23:59:59.999999' + AND t.id IN (${tickets.map((t: any) => t.id).join()}) + AND m.createdAt = (SELECT MIN(createdAt) FROM Messages WHERE ticketId = t.id) + AND m.fromMe = 0 AND t.status IN ('open', 'closed') HAVING WAITING_TIME IS NOT NULL - ORDER BY + ORDER BY WAITING_TIME;`, { type: QueryTypes.SELECT } ); diff --git a/backend/src/services/WbotServices/wbotMessageListener.ts b/backend/src/services/WbotServices/wbotMessageListener.ts index 2739c73..ffa650e 100644 --- a/backend/src/services/WbotServices/wbotMessageListener.ts +++ b/backend/src/services/WbotServices/wbotMessageListener.ts @@ -10,6 +10,7 @@ import path from "path"; import { isHoliday, isOutBusinessTime, + isOutBusinessTimeSaturday, isWeekend } from "../../helpers/TicketConfig"; @@ -1221,6 +1222,13 @@ const outOfService = async (number: string) => { objs.push({ type: "holiday", msg: holiday.msg }); } + // MESSAGE TO SATURDAY BUSINESS TIME + const businessTimeSaturday = await isOutBusinessTimeSaturday(number); + + if (businessTimeSaturday && businessTimeSaturday.set) { + objs.push({ type: "saturdayBusinessTime", msg: businessTimeSaturday.msg }); + } + // MESSAGES TO SATURDAY OR SUNDAY const weekend: any = await isWeekend(number); diff --git a/backend/src/services/WhatsappService/ListWhatsAppsForQueueService.ts b/backend/src/services/WhatsappService/ListWhatsAppsForQueueService.ts index 1f16647..836ef9e 100644 --- a/backend/src/services/WhatsappService/ListWhatsAppsForQueueService.ts +++ b/backend/src/services/WhatsappService/ListWhatsAppsForQueueService.ts @@ -6,17 +6,30 @@ const { QueryTypes } = require("sequelize"); const sequelize = new Sequelize(dbConfig); -const ListWhatsAppsForQueueService = async (queueId: number | string): Promise => { - const distinctWhatsapps = await sequelize.query( - `SELECT w.id, w.number, w.status, wq.whatsappId, wq.queueId -FROM Whatsapps w -JOIN WhatsappQueues wq ON w.id = wq.whatsappId AND wq.queueId = ${queueId} -GROUP BY w.number;`, - { type: QueryTypes.SELECT } - ); +const ListWhatsAppsForQueueService = async ( + queueId: number | string, + status?: string +): Promise => { + let distinctWhatsapps: any; + + if (status) { + distinctWhatsapps = await sequelize.query( + `SELECT w.id, w.number, w.status, wq.whatsappId, wq.queueId FROM Whatsapps w + JOIN WhatsappQueues wq ON w.id = wq.whatsappId AND wq.queueId = ${queueId} AND w.status = '${status}' + AND phoneNumberId = false + GROUP BY w.number;`, + { type: QueryTypes.SELECT } + ); + } else { + distinctWhatsapps = await sequelize.query( + `SELECT w.id, w.number, w.status, wq.whatsappId, wq.queueId FROM Whatsapps w + JOIN WhatsappQueues wq ON w.id = wq.whatsappId AND wq.queueId = ${queueId} + GROUP BY w.number;`, + { type: QueryTypes.SELECT } + ); + } return distinctWhatsapps; }; export default ListWhatsAppsForQueueService; - \ No newline at end of file diff --git a/frontend/src/components/ConfigModal/index.js b/frontend/src/components/ConfigModal/index.js index 40099ea..cf41fa3 100644 --- a/frontend/src/components/ConfigModal/index.js +++ b/frontend/src/components/ConfigModal/index.js @@ -77,8 +77,16 @@ const ConfigModal = ({ open, onClose, change }) => { const initialState = { startTimeBus: new Date(), endTimeBus: new Date(), + + startTimeBusSaturday: new Date(), + endTimeBusSaturday: new Date(), + messageBus: '', + messageBusSaturday: '', + businessTimeEnable: false, + businessTimeEnableSaturday: false, + ticketTimeExpiration: new Date(), ticketExpirationMsg: '', ticketExpirationEnable: false, @@ -115,13 +123,16 @@ const ConfigModal = ({ open, onClose, change }) => { if (!selectedNumber) return const { data } = await api.get(`/settings/ticket/${selectedNumber}`) - + if (data?.config && data.config.length === 0) { setConfig(initialState) return } const outBusinessHours = data.config.find((c) => c.key === "outBusinessHours") + + const saturdayBusinessTime = data.config.find((c) => c.key === "saturdayBusinessTime") + const ticketExpiration = data.config.find((c) => c.key === "ticketExpiration") const saturday = data.config.find((c) => c.key === "saturday") const sunday = data.config.find((c) => c.key === "sunday") @@ -134,6 +145,11 @@ const ConfigModal = ({ open, onClose, change }) => { messageBus: outBusinessHours.message, businessTimeEnable: outBusinessHours.value === 'enabled' ? true : false, + startTimeBusSaturday: saturdayBusinessTime.startTime, + endTimeBusSaturday: saturdayBusinessTime.endTime, + messageBusSaturday: saturdayBusinessTime.message, + businessTimeEnableSaturday: saturdayBusinessTime.value === 'enabled' ? true : false, + ticketTimeExpiration: ticketExpiration.startTime, ticketExpirationMsg: ticketExpiration.message, ticketExpirationEnable: ticketExpiration.value === 'enabled' ? true : false, @@ -165,6 +181,14 @@ const ConfigModal = ({ open, onClose, change }) => { message: values.messageBus, value: values.businessTimeEnable ? 'enabled' : 'disabled' }, + + saturdayBusinessTime: { + startTime: values.startTimeBusSaturday, + endTime: values.endTimeBusSaturday, + message: values.messageBusSaturday, + value: values.businessTimeEnableSaturday ? 'enabled' : 'disabled' + }, + ticketExpiration: { startTime: values.ticketTimeExpiration, message: values.ticketExpirationMsg, @@ -205,7 +229,7 @@ const ConfigModal = ({ open, onClose, change }) => { onClose() // setConfig(initialState) } - + return (
{
+
+ {/* SABADO INICIO */} +
+ + {' '} + + + + } + label={'Ativar/Desativar'} /> +
+ +
+ +
+ {/* SABADO FIM */}
diff --git a/frontend/src/pages/Dashboard/PieChart.js b/frontend/src/pages/Dashboard/PieChart.js index 64b64b8..b1b6c46 100644 --- a/frontend/src/pages/Dashboard/PieChart.js +++ b/frontend/src/pages/Dashboard/PieChart.js @@ -76,7 +76,7 @@ const PieChart = ({ data = dataExample }) => { > - Tickets Status + Tickets encerramento diff --git a/frontend/src/pages/Dashboard/index.js b/frontend/src/pages/Dashboard/index.js index ccbb674..ca6fe4e 100644 --- a/frontend/src/pages/Dashboard/index.js +++ b/frontend/src/pages/Dashboard/index.js @@ -258,7 +258,7 @@ const Dashboard = () => { const [usersOnlineInfo, dispatch] = useReducer(reducer, []) const [ticketStatusChange, setStatus] = useState() const [ticketsStatus, setTicktsStatus] = useState({ open: 0, openAll: 0, pending: 0, closed: 0 }) - + const [ticketStatusChatEnd, setTicketStatusChatEnd] = useState([]) const { user } = useContext(AuthContext) useEffect(() => { @@ -287,12 +287,17 @@ const Dashboard = () => { const { data } = await api.get("/reports/user/services", { params: { userId: null, startDate: dateToday, endDate: dateToday }, - }) - - // console.log('data.data: ', data.usersProfile) + }) dispatch({ type: "RESET" }) dispatch({ type: "LOAD_QUERY", payload: data.usersProfile }) + + const { data: ticketStatusChatEndData } = await api.get("/reports/count/statusChatEnd", { + params: { startDate: dateToday, endDate: dateToday }, + }) + + setTicketStatusChatEnd(ticketStatusChatEndData.reportStatusChatEnd) + } catch (err) { } @@ -506,7 +511,7 @@ const Dashboard = () => { - + diff --git a/frontend/src/pages/Report/index.js b/frontend/src/pages/Report/index.js index d3b97fa..1724682 100644 --- a/frontend/src/pages/Report/index.js +++ b/frontend/src/pages/Report/index.js @@ -363,7 +363,7 @@ const Report = () => { if (reportOption === '1') { const { data } = await api.get("/reports/", { params: { userId, startDate, endDate, pageNumber: pageNumberTickets, createdOrUpdated: selectedValue, queueId }, userQueues: userA.queues }) - + let ticketsQueue = data.tickets let userQueues = userA.queues let filterQueuesTickets = []