import { Sequelize } from "sequelize"; const dbConfig = require("../../config/database"); const sequelize = new Sequelize(dbConfig); const { QueryTypes } = require("sequelize"); import { splitDateTime } from "../../helpers/SplitDateTime"; import format from "date-fns/format"; import ptBR from "date-fns/locale/pt-BR"; import Whatsapp from "../../models/Whatsapp"; import { number } from "yup"; import ShowWhatsAppService from "../WhatsappService/ShowWhatsAppService"; interface Request { startDate: string | number; endDate: string; queue?: boolean; } const ReportByNumberQueueService = async ({ startDate, endDate, queue = false }: Request): Promise => { let reportServiceData: any[] = []; const whatsapps = await Whatsapp.findAll(); if (!queue) { for (const whatsapp of whatsapps) { const { id, name, number } = whatsapp; if ( !number || reportServiceData.findIndex((w: any) => w?.number == number) != -1 ) continue; console.log("NUMBER: ", number); // CHAT STARTED BY AGENT const startedByAgent: any = await sequelize.query( `SELECT COUNT(DISTINCT t.id) AS ticket_count 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 m.createdAt = (SELECT MIN(createdAt) FROM Messages WHERE ticketId = t.id) AND m.fromAgent = 1 AND w.number = ${number};`, { type: QueryTypes.SELECT } ); // CHAT STARTED BY CLIENT const startedByClient: any = await sequelize.query( `SELECT COUNT(DISTINCT t.id) AS ticket_count 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 m.createdAt = (SELECT MIN(createdAt) FROM Messages WHERE ticketId = t.id) AND m.fromMe = 0 AND w.number = ${number};`, { type: QueryTypes.SELECT } ); // CHAT CLOSED const closedChat: any = await sequelize.query( `SELECT COUNT(DISTINCT t.id) AS ticket_count 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.status = 'closed' AND w.number = ${number};`, { type: QueryTypes.SELECT } ); // CHAT WAINTING TIME const avgChatWaitingTime: any = await sequelize.query( ` SELECT TIME_FORMAT( SEC_TO_TIME( TIMESTAMPDIFF( SECOND, ( 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 LIMIT 1 ) ) ), '%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 m.createdAt = (SELECT MIN(createdAt) FROM Messages WHERE ticketId = t.id) AND m.fromMe = 0 -- AND q.id = 2 AND w.number = ${number} AND (t.status = 'open' OR t.status = 'closed') ORDER BY WAITING_TIME;`, { type: QueryTypes.SELECT } ); // CHAT PENDING const pendingChat: any = await sequelize.query( `SELECT COUNT(DISTINCT t.id) AS ticket_count 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.status = 'pending' AND w.number = ${number};`, { type: QueryTypes.SELECT } ); reportServiceData.push({ id, name, number, startedByAgent: startedByAgent[0]?.ticket_count, startedByClient: startedByClient[0]?.ticket_count, closedChat: closedChat[0]?.ticket_count, avgChatWaitingTime: avg(avgChatWaitingTime), pendingChat: pendingChat[0]?.ticket_count }); } } else { for (const whatsapp of whatsapps) { const { id, name, number } = whatsapp; if ( !number || reportServiceData.findIndex((w: any) => w?.number == number) != -1 ) continue; const data = await ShowWhatsAppService(id); const queues: any = data.queues.map((q: any) => { const { id, name, color } = q; return { id, name, color }; }); console.log("NUMBER 2: ", number); for (const q of queues) { // CHAT STARTED BY AGENT const startedByAgent: any = await sequelize.query( `SELECT COUNT(DISTINCT t.id) AS ticket_count 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 m.createdAt = (SELECT MIN(createdAt) FROM Messages WHERE ticketId = t.id) AND m.fromAgent = 1 AND q.id = ${q.id};`, { type: QueryTypes.SELECT } ); // CHAT STARTED BY CLIENT const startedByClient: any = await sequelize.query( `SELECT COUNT(DISTINCT t.id) AS ticket_count 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 m.createdAt = (SELECT MIN(createdAt) FROM Messages WHERE ticketId = t.id) AND m.fromMe = 0 AND q.id = ${q.id};`, { type: QueryTypes.SELECT } ); // CHAT CLOSED const closedChat: any = await sequelize.query( `SELECT COUNT(DISTINCT t.id) AS ticket_count 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.status = 'closed' AND q.id = ${q.id};`, { type: QueryTypes.SELECT } ); // CHAT WAINTING TIME const avgChatWaitingTime: any = await sequelize.query( `SELECT TIME_FORMAT( SEC_TO_TIME( TIMESTAMPDIFF( SECOND, ( 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 LIMIT 1 ) ) ), '%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 m.createdAt = (SELECT MIN(createdAt) FROM Messages WHERE ticketId = t.id) AND m.fromMe = 0 AND q.id = ${q.id} AND (t.status = 'open' OR t.status = 'closed') ORDER BY WAITING_TIME;`, { type: QueryTypes.SELECT } ); // CHAT PENDING const pendingChat: any = await sequelize.query( `SELECT COUNT(DISTINCT t.id) AS ticket_count 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.status = 'pending' AND q.id = ${q.id};`, { type: QueryTypes.SELECT } ); reportServiceData.push({ id, name, number, queueName: q.name, queueColor: q.color, startedByAgent: startedByAgent[0]?.ticket_count, startedByClient: startedByClient[0]?.ticket_count, closedChat: closedChat[0]?.ticket_count, avgChatWaitingTime: avg(avgChatWaitingTime), pendingChat: pendingChat[0]?.ticket_count }); } } } return reportServiceData; }; export default ReportByNumberQueueService; function avg(avgChatWaitingTime: any) { let waitingAVG: any = avgChatWaitingTime .filter((t: any) => t?.WAITING_TIME) .map((t: any) => t.WAITING_TIME) if (waitingAVG.length > 0) { let midIndex = Math.floor((0 + waitingAVG.length) / 2) if (waitingAVG.length % 2 == 1) { waitingAVG = waitingAVG[midIndex] } else { waitingAVG = calculateAverageTime( waitingAVG[midIndex - 1], waitingAVG[midIndex] ) } } else { waitingAVG = 0 } return waitingAVG } function calculateAverageTime(time1: string, time2: string) { // Function to parse time string to seconds function timeStringToSeconds(timeString: string) { const [hours, minutes, seconds] = timeString.split(":").map(Number); return hours * 3600 + minutes * 60 + seconds; } // Function to convert seconds to time string function secondsToTimeString(seconds: number) { const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); const remainingSeconds = seconds % 60; return `${hours.toString().padStart(2, "0")}:${minutes .toString() .padStart(2, "0")}:${remainingSeconds.toString().padStart(2, "0")}`; } // Convert time strings to seconds const time1Seconds = timeStringToSeconds(time1); const time2Seconds = timeStringToSeconds(time2); // Calculate average seconds const averageSeconds = Math.round((time1Seconds + time2Seconds) / 2); // Convert average seconds back to time string const averageTime = secondsToTimeString(averageSeconds); return averageTime; }