210 lines
5.2 KiB
TypeScript
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;
|