projeto-hit/backend/src/services/TicketServices/ShowTicketReport.ts

210 lines
5.2 KiB
TypeScript

import Ticket from "../../models/Ticket";
import AppError from "../../errors/AppError";
import Contact from "../../models/Contact";
import User from "../../models/User";
import Queue from "../../models/Queue";
import Message from "../../models/Message";
import { userInfo } from "os";
import { Op, QueryTypes, json, where } from "sequelize";
import { Sequelize } from "sequelize";
import moment from "moment";
const dbConfig = require("../../config/database");
const sequelize = new Sequelize(dbConfig);
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";
interface Request {
userId: string | number;
startDate: string;
endDate: string;
createdOrUpdated?: string;
queueId?: string;
pageNumber?: string;
}
interface Response {
tickets: Ticket[];
count: number;
hasMore: boolean;
}
//Report by user, startDate, endDate
const ShowTicketReport = async ({
userId,
startDate,
endDate,
pageNumber = "1",
createdOrUpdated = "created",
queueId
}: Request): Promise<Response> => {
let where_clause: any = {};
let query = "";
if (userId !== "0") {
where_clause.userid = userId;
query = `AND t.userId = ${userId}`;
}
if (queueId) {
where_clause.queueId = queueId;
query = `AND t.queueId = ${queueId}`;
}
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) }
},
limit,
offset,
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,
separate: true,
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"]
},
{
model: User,
attributes: ["name", "email"]
},
{
model: Queue,
attributes: ["name"]
},
{
model: Whatsapp,
attributes: ["name"]
}
],
order: [["updatedAt", "DESC"]]
});
const hasMore = count > offset + tickets.length;
if (!tickets) {
throw new AppError("ERR_NO_TICKET_FOUND", 404);
}
const ticketIds = tickets.map((t: any) => t.id);
if (ticketIds.length > 0) {
const waiting_time: any = await sequelize.query(
`SELECT t.id as ticketId, t.status, 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 t.id IN (${ticketIds.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
WAITING_TIME;`,
{ type: QueryTypes.SELECT }
);
for (let w of waiting_time) {
const { ticketId, status, WAITING_TIME } = w;
const index = tickets.findIndex((t: any) => +t?.id == +ticketId);
if (index != -1) {
tickets[index].dataValues.waiting_time = WAITING_TIME;
}
}
}
return { tickets, count, hasMore };
};
export default ShowTicketReport;