diff --git a/backend/src/controllers/ReportController.ts b/backend/src/controllers/ReportController.ts index bced8df..880452d 100644 --- a/backend/src/controllers/ReportController.ts +++ b/backend/src/controllers/ReportController.ts @@ -4,28 +4,19 @@ import { Request, Response } from "express"; import AppError from "../errors/AppError"; import ShowTicketReport from "../services/TicketServices/ShowTicketReport"; import ShowMessageReport from "../services/MessageServices/ShowMessageReport"; - import onlineUserService from "../services/UserServices/CreateOrUpdateOnlineUserService"; import User from "../models/User"; import Queue from "../models/Queue"; import UserOnlineTime from "../models/UserOnlineTime"; - import { Op, Sequelize, literal } from "sequelize"; -import format from 'date-fns/format'; -import ptBR from 'date-fns/locale/pt-BR'; +import format from "date-fns/format"; +import ptBR from "date-fns/locale/pt-BR"; import { splitDateTime } from "../helpers/SplitDateTime"; import ListUserOnlineOffline from "../services/UserServices/ListUsersOnlineOfflineService"; import ListUserParamiterService from "../services/UserServices/ListUserParamiterService"; - import ShowUserServiceReport from "../services/UserServices/ShowUserServiceReport"; - import CountTicketsByUserQueue from "../services/UserServices/CountTicketsByUserQueue"; - import ShowQueuesByUser from "../services/UserServices/ShowQueuesByUser"; - - -// import { filter } from "bluebird"; - import { getIO } from "../libs/socket"; import { Json } from "sequelize/types/lib/utils"; @@ -33,6 +24,8 @@ type IndexQuery = { userId: string; startDate: string; endDate: string; + createdOrUpdated: string; + queueId: string; pageNumber: string; userQueues: []; }; @@ -40,11 +33,12 @@ type IndexQuery = { type ReportOnQueue = { userId: string; identifier: string; -} - - -export const reportUserByDateStartDateEnd = async (req: Request, res: Response): Promise => { +}; +export const reportUserByDateStartDateEnd = async ( + req: Request, + res: Response +): Promise => { if ( req.user.profile !== "master" && req.user.profile !== "admin" && @@ -53,79 +47,143 @@ export const reportUserByDateStartDateEnd = async (req: Request, res: Response): throw new AppError("ERR_NO_PERMISSION", 403); } - const { userId, startDate, endDate, pageNumber, userQueues } = req.query as IndexQuery + const { + userId, + startDate, + endDate, + pageNumber, + userQueues, + createdOrUpdated, + queueId + } = req.query as IndexQuery; - console.log("userId, startDate, endDate, pageNumber: ", userId, startDate, endDate, pageNumber); + console.log( + "userId, startDate, endDate, pageNumber, userQueues, createdOrUpdated, queueId: ", + userId, + startDate, + endDate, + pageNumber, + userQueues, + createdOrUpdated, + queueId + ); - const { tickets, count, hasMore } = await ShowTicketReport({ userId, startDate, endDate, pageNumber }); - // console.log('kkkkkkkkkkkkkkkkkk tickets: ', JSON.stringify(tickets, null, 6)) - - return res.status(200).json({ tickets, count, hasMore }); + const { tickets, count, hasMore } = await ShowTicketReport({ + userId, + startDate, + endDate, + pageNumber, + createdOrUpdated, + queueId + }); + + const queues = await Queue.findAll({ attributes: ["id", "name"] }); + + return res.status(200).json({ tickets, count, hasMore, queues }); }; - -export const reportUserService = async (req: Request, res: Response): Promise => { - - if (req.user.profile !== "master" && req.user.profile !== "admin" && req.user.profile !=="supervisor") { +export const reportUserService = async ( + req: Request, + res: Response +): Promise => { + if ( + req.user.profile !== "master" && + req.user.profile !== "admin" && + req.user.profile !== "supervisor" + ) { throw new AppError("ERR_NO_PERMISSION", 403); } - const { userId, startDate, endDate } = req.query as IndexQuery - + const { userId, startDate, endDate } = req.query as IndexQuery; + // let usersProfile = await ListUserParamiterService({ profile: 'user' }) let usersProfile = await ListUserParamiterService({ profiles: ["user", "supervisor"], raw: true }); - const sumUserOlineTime = await ShowUserServiceReport({ startDate, endDate, userId }); - const closedByUser = await ShowUserServiceReport({ startDate, endDate, ticketStatus: 'closed', userId }); - const openByUser = await ShowUserServiceReport({ startDate, endDate, ticketStatus: 'open', userId }); + const sumUserOlineTime = await ShowUserServiceReport({ + startDate, + endDate, + userId + }); + const closedByUser = await ShowUserServiceReport({ + startDate, + endDate, + ticketStatus: "closed", + userId + }); + const openByUser = await ShowUserServiceReport({ + startDate, + endDate, + ticketStatus: "open", + userId + }); - let dateTime = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR }))) - const onlineUsers = await ListUserOnlineOffline({ date: dateTime.fullDate }) + let dateTime = splitDateTime( + new Date(format(new Date(), "yyyy-MM-dd HH:mm:ss", { locale: ptBR })) + ); + const onlineUsers = await ListUserOnlineOffline({ date: dateTime.fullDate }); - const openByUserOnQueue = await CountTicketsByUserQueue({ startDate: startDate, endDate: endDate, status: 'open', clientChatStart: true }) - const openByUserOutQueue = await CountTicketsByUserQueue({ startDate: startDate, endDate: endDate, status: 'open', clientChatStart: false }) + const openByUserOnQueue = await CountTicketsByUserQueue({ + startDate: startDate, + endDate: endDate, + status: "open", + clientChatStart: true + }); + const openByUserOutQueue = await CountTicketsByUserQueue({ + startDate: startDate, + endDate: endDate, + status: "open", + clientChatStart: false + }); - const closedByUserOnQueue = await CountTicketsByUserQueue({ startDate: startDate, endDate: endDate, status: 'closed', clientChatStart: true }) - const closedUserOutQueue = await CountTicketsByUserQueue({ startDate: startDate, endDate: endDate, status: 'closed', clientChatStart: false }) + const closedByUserOnQueue = await CountTicketsByUserQueue({ + startDate: startDate, + endDate: endDate, + status: "closed", + clientChatStart: true + }); + const closedUserOutQueue = await CountTicketsByUserQueue({ + startDate: startDate, + endDate: endDate, + status: "closed", + clientChatStart: false + }); // let openQueueInOut = openByUserOnQueue.concat(openByUserOutQueue) // let closedQueueInOut = closedByUserOnQueue.concat(closedUserOutQueue) + const queuesByUser = await ShowQueuesByUser({ profile: "user" }); - const queuesByUser = await ShowQueuesByUser({ profile: 'user' }) - - let openCloseOnQueue = openByUserOnQueue.concat(closedByUserOnQueue) - let openCloseOutQueue = openByUserOutQueue.concat(closedUserOutQueue) - + let openCloseOnQueue = openByUserOnQueue.concat(closedByUserOnQueue); + let openCloseOutQueue = openByUserOutQueue.concat(closedUserOutQueue); // console.log('onlineUsers: ',JSON.parse(JSON.stringify(onlineUsers))) // console.log('sumUserOlineTime: ', JSON.parse(JSON.stringify(sumUserOlineTime))) for (let i = 0; i < queuesByUser.length; i++) { - - queuesByUser[i].countOpen = 0 - queuesByUser[i].countClosed = 0 + queuesByUser[i].countOpen = 0; + queuesByUser[i].countClosed = 0; for (let x = 0; x < openCloseOnQueue.length; x++) { - if ((queuesByUser[i].userId == openCloseOnQueue[x].userId) && - (queuesByUser[i].queueId == openCloseOnQueue[x].queueId && openCloseOnQueue[x].status == 'open')) { - queuesByUser[i].countOpen = openCloseOnQueue[x].totAttendance + if ( + queuesByUser[i].userId == openCloseOnQueue[x].userId && + queuesByUser[i].queueId == openCloseOnQueue[x].queueId && + openCloseOnQueue[x].status == "open" + ) { + queuesByUser[i].countOpen = openCloseOnQueue[x].totAttendance; + } else if ( + queuesByUser[i].userId == openCloseOnQueue[x].userId && + queuesByUser[i].queueId == openCloseOnQueue[x].queueId && + openCloseOnQueue[x].status == "closed" + ) { + queuesByUser[i].countClosed = openCloseOnQueue[x].totAttendance; } - else if ((queuesByUser[i].userId == openCloseOnQueue[x].userId) && - (queuesByUser[i].queueId == openCloseOnQueue[x].queueId && openCloseOnQueue[x].status == 'closed')) { - queuesByUser[i].countClosed = openCloseOnQueue[x].totAttendance - } - } } - - usersProfile.map((user: any) => { - - let index = sumUserOlineTime.findIndex((e: any) => e.userId == user.id) + let index = sumUserOlineTime.findIndex((e: any) => e.userId == user.id); if (index != -1) { user.sumOnlineTime = sumUserOlineTime[index]; @@ -133,68 +191,67 @@ export const reportUserService = async (req: Request, res: Response): Promise e.userId == user.id) + index = closedByUser.findIndex((e: any) => e.userId == user.id); if (index != -1) { user.sumClosed = closedByUser[index]; } - index = openByUser.findIndex((e: any) => e.userId == user.id) + index = openByUser.findIndex((e: any) => e.userId == user.id); if (index != -1) { - user.sumOpen = openByUser[index] + user.sumOpen = openByUser[index]; } - // OPEN, CLOSED TICKETS STARTED BY USERS - let openClosedOutQueue = {} - let open = openCloseOutQueue.filter((e) => e.userId == user.id && e.status == 'open') - let closed = openCloseOutQueue.filter((e) => e.userId == user.id && e.status == 'closed') + let openClosedOutQueue = {}; + let open = openCloseOutQueue.filter( + e => e.userId == user.id && e.status == "open" + ); + let closed = openCloseOutQueue.filter( + e => e.userId == user.id && e.status == "closed" + ); openClosedOutQueue = { ...openClosedOutQueue, userId: user.id, countOpen: open && open.length > 0 ? open[0].totAttendance : 0, countClosed: closed && closed.length > 0 ? closed[0].totAttendance : 0 - } - - user.openClosedOutQueue = openClosedOutQueue + }; + user.openClosedOutQueue = openClosedOutQueue; // OPEN, CLOSED TICKETS STARTED BY CLIENTS - let openClosedInQueue = queuesByUser.filter((e) => e.userId == user.id) + let openClosedInQueue = queuesByUser.filter(e => e.userId == user.id); if (openClosedInQueue && openClosedInQueue.length > 0) { - user.openClosedInQueue = openClosedInQueue + user.openClosedInQueue = openClosedInQueue; } - - index = onlineUsers.findIndex((e: any) => e.userId == user.id) + index = onlineUsers.findIndex((e: any) => e.userId == user.id); if (index != -1) { - user.statusOnline = onlineUsers[index] + user.statusOnline = onlineUsers[index]; } - if (startDate.length > 0 && startDate.split('-').length == 3) { - let date = startDate.split('-') - user.startDate = `${date[2]}/${date[1]}/${date[0]}` + if (startDate.length > 0 && startDate.split("-").length == 3) { + let date = startDate.split("-"); + user.startDate = `${date[2]}/${date[1]}/${date[0]}`; } - if (endDate.length > 0 && endDate.split('-').length == 3) { - let date = endDate.split('-') - user.endDate = `${date[2]}/${date[1]}/${date[0]}` + if (endDate.length > 0 && endDate.split("-").length == 3) { + let date = endDate.split("-"); + user.endDate = `${date[2]}/${date[1]}/${date[0]}`; } + }); - }) - - return res.status(200).json({usersProfile: usersProfile}); - + return res.status(200).json({ usersProfile: usersProfile }); }; - - -export const reportMessagesUserByDateStartDateEnd = async (req: Request, res: Response): Promise => { - +export const reportMessagesUserByDateStartDateEnd = async ( + req: Request, + res: Response +): Promise => { if ( req.user.profile !== "master" && req.user.profile !== "admin" && @@ -203,35 +260,32 @@ export const reportMessagesUserByDateStartDateEnd = async (req: Request, res: Re throw new AppError("ERR_NO_PERMISSION", 403); } - const { userId, startDate, endDate } = req.query as IndexQuery + const { userId, startDate, endDate } = req.query as IndexQuery; let data_query_messages = await ShowMessageReport(userId, startDate, endDate); for (var i = 0; i < data_query_messages.length; i++) { - if (data_query_messages[i].fromMe) { - data_query_messages[i].fromMe = 'Atendente' - } - else { - data_query_messages[i].fromMe = 'Cliente' + data_query_messages[i].fromMe = "Atendente"; + } else { + data_query_messages[i].fromMe = "Cliente"; } - data_query_messages[i].id = (i + 1) + data_query_messages[i].id = i + 1; - console.log('data_query_messages: ', data_query_messages[i]) + console.log("data_query_messages: ", data_query_messages[i]); } return res.status(200).json(data_query_messages); - }; - - -export const reportOnQueue = async (req: Request, res: Response): Promise => { - +export const reportOnQueue = async ( + req: Request, + res: Response +): Promise => { // console.log(req.body) - const { adminId, identifier, queueStatus, file } = req.body + const { adminId, identifier, queueStatus, file } = req.body; const io = getIO(); io.emit("queryOnQueueStatus", { @@ -244,10 +298,5 @@ export const reportOnQueue = async (req: Request, res: Response): Promise => { - - let where_clause = {} + pageNumber = "1", + createdOrUpdated = "created", + queueId +}: Request): Promise => { + let where_clause = {}; - if(userId=='0'){ - where_clause = { - updatedAt: { - [Op.gte]: startDate+' 00:00:00.000000', - [Op.lte]: endDate +' 23:59:59.999999' - }, + if (userId == "0") { + if (createdOrUpdated == "updated") { + where_clause = { + updatedAt: { + [Op.gte]: startDate + " 00:00:00.000000", + [Op.lte]: endDate + " 23:59:59.999999" + } + }; + } else if (createdOrUpdated == "created") { + where_clause = { + createdAt: { + [Op.gte]: startDate + " 00:00:00.000000", + [Op.lte]: endDate + " 23:59:59.999999" + } + }; } - } - else{ - where_clause = { - userid: userId, - updatedAt: { - [Op.gte]: startDate+' 00:00:00.000000', - [Op.lte]: endDate +' 23:59:59.999999' - }, + + if (queueId) { + where_clause = { ...where_clause, queueId }; + } + } else { + if (createdOrUpdated == "updated") { + where_clause = { + userid: userId, + updatedAt: { + [Op.gte]: startDate + " 00:00:00.000000", + [Op.lte]: endDate + " 23:59:59.999999" + } + }; + } else if (createdOrUpdated == "created") { + where_clause = { + userid: userId, + createdAt: { + [Op.gte]: startDate + " 00:00:00.000000", + [Op.lte]: endDate + " 23:59:59.999999" + } + }; } } - const limit = 40; const offset = limit * (+pageNumber - 1); - - const {count, rows: tickets} = await Ticket.findAndCountAll({ - where: where_clause , + const { count, rows: tickets } = await Ticket.findAndCountAll({ + where: where_clause, limit, offset, //attributes: ['id', 'status', 'createdAt', 'updatedAt'], - attributes: ['id', 'status', 'statusChatEnd', [Sequelize.fn("DATE_FORMAT",Sequelize.col("Ticket.createdAt"),"%d/%m/%Y %H:%i:%s"),"createdAt"], - [Sequelize.fn("DATE_FORMAT",Sequelize.col("Ticket.updatedAt"),"%d/%m/%Y %H:%i:%s"),"updatedAt"]], + attributes: [ + "id", + "status", + "statusChatEnd", + [ + Sequelize.fn( + "DATE_FORMAT", + Sequelize.col("Ticket.createdAt"), + "%d/%m/%Y %H:%i:%s" + ), + "createdAt" + ], + [ + Sequelize.fn( + "DATE_FORMAT", + Sequelize.col("Ticket.updatedAt"), + "%d/%m/%Y %H:%i:%s" + ), + "updatedAt" + ] + ], include: [ { model: Message, - required:true, + required: true, separate: true, - + // attributes: ['body', 'read', 'mediaType','fromMe', 'mediaUrl','createdAt'], - attributes: ['body', 'read', 'mediaType','fromMe', 'mediaUrl', [Sequelize.fn("DATE_FORMAT",Sequelize.col("createdAt"),"%d/%m/%Y %H:%i:%s"),"createdAt"]], + attributes: [ + "body", + "read", + "mediaType", + "fromMe", + "mediaUrl", + [ + Sequelize.fn( + "DATE_FORMAT", + Sequelize.col("createdAt"), + "%d/%m/%Y %H:%i:%s" + ), + "createdAt" + ] + ], - order: [ - ['createdAt', 'ASC'] - ] - }, - { - model: Contact, - attributes: ['name', 'number'] + order: [["createdAt", "ASC"]] }, { - model: User, - attributes: ['name', 'email'] + model: Contact, + attributes: ["name", "number"] }, { - model: Queue, - attributes: ['name'] + model: User, + attributes: ["name", "email"] }, { - model: Whatsapp, - attributes: ['name'] + model: Queue, + attributes: ["name"] }, - ], + { + model: Whatsapp, + attributes: ["name"] + } + ], - order: [ - ['id', 'ASC'] - ] - - }); + order: [["updatedAt", "DESC"]] + }); const hasMore = count > offset + tickets.length; - - + if (!tickets) { throw new AppError("ERR_NO_TICKET_FOUND", 404); } - return {tickets, count, hasMore}; -}; + return { tickets, count, hasMore }; +}; export default ShowTicketReport; diff --git a/frontend/src/pages/Report/index.js b/frontend/src/pages/Report/index.js index 5c5484d..24d8490 100644 --- a/frontend/src/pages/Report/index.js +++ b/frontend/src/pages/Report/index.js @@ -9,6 +9,10 @@ import PropTypes from 'prop-types' import Box from '@mui/material/Box' import { AuthContext } from "../../context/Auth/AuthContext" import { Can } from "../../components/Can" +import FormControlLabel from "@mui/material/FormControlLabel" +import Checkbox from '@mui/material/Checkbox' + + import { Button } from "@material-ui/core" @@ -25,6 +29,9 @@ import openSocket from "socket.io-client" import { i18n } from "../../translate/i18n" +import Switch from '@mui/material/Switch' + +const label = { inputProps: { 'aria-label': 'Size switch demo' } } const report = [{ 'value': '1', 'label': 'Atendimento por atendentes' }, { 'value': '2', 'label': 'Usuários online/offline' }] @@ -48,9 +55,13 @@ const reducerQ = (state, action) => { if (action.type === 'LOAD_QUERY') { - const queries = action.payload + let queries = action.payload const newQueries = [] + if (queries?.hasOwnProperty('usersProfile')) { + queries = queries.usersProfile + } + queries.forEach((query) => { const queryIndex = state.findIndex((q) => q.id === query.id) @@ -235,7 +246,7 @@ let columnsDataSuper = [ ] - + // function convertAndFormatDate(dateString) { // // Check if the input date string is in the desired format // const isDesiredFormat = /^\w{3} \w{3} \d{2} \d{4} \d{2}:\d{2}:\d{2} GMT[-+]\d{4} \([\w\s]+\)$/i.test(dateString) @@ -273,7 +284,7 @@ const Report = () => { const [startDate, setDatePicker1] = useState(new Date()) const [endDate, setDatePicker2] = useState(new Date()) const [userId, setUser] = useState(null) - const [query, dispatchQ] = useReducer(reducerQ, []) + const [query, dispatchQ] = useReducer(reducerQ, []) const [reportOption, setReport] = useState('1') const [reporList,] = useState(report) @@ -281,14 +292,18 @@ const Report = () => { const [dataRows, setData] = useState([]) const [onQueueStatus, setOnQueueProcessStatus] = useState(undefined) - const [csvFile, setCsvFile] = useState() + const [csvFile, setCsvFile] = useState() + const [selectedValue, setSelectedValue] = useState('created') + const [checked, setChecked] = useState(true) + const [queues, setQueues] = useState([]) + const [queueId, setQueue] = useState(null) useEffect(() => { dispatch({ type: "RESET" }) dispatchQ({ type: "RESET" }) setTicketsPageNumber(1) setPageNumber(1) - }, [searchParam, profile]) + }, [searchParam, profile]) useEffect(() => { @@ -302,7 +317,7 @@ const Report = () => { const { data } = await api.get("/users/", { params: { searchParam, pageNumber, profile }, }) - + dispatch({ type: "LOAD_USERS", payload: data.users }) //setLoading(false); @@ -328,28 +343,29 @@ const Report = () => { setLoading(true) const fetchQueries = async () => { try { - if (reportOption === '1') { + if (reportOption === '1') { // const { data } = await api.get("/reports/", { params: { userId: userId ? userId : 0, startDate: convertAndFormatDate(startDate), endDate: convertAndFormatDate(endDate), pageNumber: pageNumberTickets }, }) - const { data } = await api.get("/reports/", { params: { userId, startDate, endDate, pageNumber: pageNumberTickets }, userQueues: userA.queues}) + 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 = []; - if(userQueues.length > 1){ - filterQueuesTickets = ticketsQueue.filter(ticket => userQueues.some(queue => queue?.name === ticket?.queue?.name)); - }else if(userQueues.length > 0) { - filterQueuesTickets = ticketsQueue.filter(ticket => ticket?.queue?.name === userQueues[0]?.name); + let ticketsQueue = data.tickets + let userQueues = userA.queues + let filterQueuesTickets = [] + if (userQueues.length > 1) { + filterQueuesTickets = ticketsQueue.filter(ticket => userQueues.some(queue => queue?.name === ticket?.queue?.name)) + } else if (userQueues.length > 0) { + filterQueuesTickets = ticketsQueue.filter(ticket => ticket?.queue?.name === userQueues[0]?.name) } - data.tickets = filterQueuesTickets; + data.tickets = filterQueuesTickets dispatchQ({ type: "LOAD_QUERY", payload: data.tickets }) setHasMore(data.hasMore) setTotalCountTickets(data.count) setLoading(false) + setQueues(data.queues) + - } else if (reportOption === '2') { @@ -370,9 +386,13 @@ const Report = () => { }, 500) return () => clearTimeout(delayDebounceFn) - }, [userId, startDate, endDate, reportOption, pageNumberTickets, totalCountTickets]) + }, [userId, queueId, checked, startDate, endDate, reportOption, pageNumberTickets, totalCountTickets, selectedValue]) + const handleCheckBoxChange = (value) => { + setSelectedValue(value) + } + // Get from child 1 const datePicker1Value = (data) => { @@ -387,18 +407,23 @@ const Report = () => { // Get from child 3 const textFieldSelectUser = (data) => { - + setQueue(null) setUser(data) } + const textFieldSelectQueue = (data) => { + setUser(0) + setQueue(data) + } // Get from report option - const reportValue = (data) => { - - setReport(data) - + const reportValue = (data) => { + if(data === '2'){ + setChecked(true) + } + setReport(data) } useEffect(() => { @@ -479,8 +504,8 @@ const Report = () => { const fetchQueries = async () => { - try { - + try { + const querySavedOnQueue = await apiBroker.post("/reports/messages", { app: { @@ -567,7 +592,7 @@ const Report = () => { } - }, [reportOption, startDate, endDate, userId, userA]) + }, [reportOption, startDate, endDate, userId, queueId, checked, userA, selectedValue]) useEffect(() => { @@ -657,6 +682,10 @@ const Report = () => { } + const handleChange = (event) => { + setChecked(event.target.checked) + } + return ( { yes={() => ( - + - { - return { 'value': obj.id, 'label': obj.name } - })} /> + - - + {checked ? + { + return { 'value': obj.id, 'label': obj.name } + })} /> : + { + return { 'value': obj.id, 'label': obj.name } + })} /> + } - + {reportOption === '1' && +
+ +
+ } + + +
+ + + + + + + {reportOption === '1' ? + + handleCheckBoxChange('created')} />} + label="Criado" + /> + handleCheckBoxChange('updated')} />} + label="Atualizado" + /> + : + + + + + } + + @@ -688,7 +768,7 @@ const Report = () => { } - +
@@ -700,17 +780,15 @@ const Report = () => { {reportOption === '1' && - <> - + <> - + table_title={i18n.t("reports.listTitles.title1_1")} /> }