feat: Support IVR(ura) for bot interactions, optimize botqueue user checks, and allow supervisor to view all tickets
parent
dfa4be6253
commit
ad89d3ccdb
|
@ -5,6 +5,9 @@ import DeleteQueueService from "../services/QueueService/DeleteQueueService";
|
|||
import ListQueuesService from "../services/QueueService/ListQueuesService";
|
||||
import ShowQueueService from "../services/QueueService/ShowQueueService";
|
||||
import UpdateQueueService from "../services/QueueService/UpdateQueueService";
|
||||
import Queue from "../models/Queue"
|
||||
import AppError from "../errors/AppError"
|
||||
import { get, set } from "../helpers/RedisClient";
|
||||
|
||||
|
||||
|
||||
|
@ -28,6 +31,106 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
|||
return res.status(200).json(queue);
|
||||
};
|
||||
|
||||
export const customization = async (
|
||||
req: Request,
|
||||
res: Response
|
||||
): Promise<Response> => {
|
||||
const { ura } = req.body;
|
||||
|
||||
if (!ura) throw new AppError("BAD REQUEST", 400);
|
||||
|
||||
let new_queues: any;
|
||||
|
||||
if (ura.length > 0) {
|
||||
new_queues = ura
|
||||
.filter(
|
||||
(u: any) =>
|
||||
u.idmaster === ura[1].id &&
|
||||
u?.queueName &&
|
||||
u?.color &&
|
||||
u?.greetingMessage
|
||||
)
|
||||
.map((u: any) => {
|
||||
const { queueName, color, greetingMessage } = u;
|
||||
return {
|
||||
queueName: queueName?.trim()?.replace(/\s+/g, " "),
|
||||
color,
|
||||
greetingMessage
|
||||
};
|
||||
});
|
||||
|
||||
if (new_queues && new_queues.length > 0) {
|
||||
const db_queues: any = await Queue.findAll();
|
||||
|
||||
for (const i in new_queues) {
|
||||
let { queueName: name, color, greetingMessage } = new_queues[i];
|
||||
|
||||
name = name?.trim()?.replace(/\s+/g, " ");
|
||||
|
||||
const update = db_queues.find(
|
||||
(q: any) => q.name?.trim()?.replace(/\s+/g, " ") == name
|
||||
);
|
||||
|
||||
if (update) {
|
||||
const { id } = update;
|
||||
// UPDATE
|
||||
// const queue = await UpdateQueueService(id, {
|
||||
// name,
|
||||
// color,
|
||||
// greetingMessage
|
||||
// });
|
||||
|
||||
// const io = getIO();
|
||||
// io.emit("queue", {
|
||||
// action: "update",
|
||||
// queue
|
||||
// });
|
||||
} else {
|
||||
// CREATE
|
||||
// const queue = await CreateQueueService({
|
||||
// name,
|
||||
// color,
|
||||
// greetingMessage
|
||||
// });
|
||||
// const io = getIO();
|
||||
// io.emit("queue", {
|
||||
// action: "update",
|
||||
// queue
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
||||
let remove_queues = db_queues.filter(
|
||||
(q: any) =>
|
||||
!new_queues
|
||||
.map((nq: any) => nq.queueName)
|
||||
.includes(q.name?.trim()?.replace(/\s+/g, " "))
|
||||
);
|
||||
|
||||
for (const i in remove_queues) {
|
||||
const { id, name } = remove_queues[i];
|
||||
|
||||
// await DeleteQueueService(id);
|
||||
|
||||
// const io = getIO();
|
||||
// io.emit("queue", {
|
||||
// action: "delete",
|
||||
// queueId: +id
|
||||
// });
|
||||
}
|
||||
|
||||
// await set("ura", ura);
|
||||
}
|
||||
}
|
||||
|
||||
await set("ura", ura);
|
||||
|
||||
const _ura = await get("ura");
|
||||
console.log("_URA: ", _ura);
|
||||
|
||||
return res.status(200).json({ new_queues });
|
||||
};
|
||||
|
||||
export const show = async (req: Request, res: Response): Promise<Response> => {
|
||||
const { queueId } = req.params;
|
||||
|
||||
|
|
|
@ -110,11 +110,13 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
|||
const { contactId, status, userId, msg, queueId, whatsappId }: TicketData =
|
||||
req.body;
|
||||
|
||||
const botInfo = await BotIsOnQueue("botqueue");
|
||||
|
||||
let ticket = await Ticket.findOne({
|
||||
where: {
|
||||
[Op.or]: [
|
||||
{ contactId, status: "queueChoice" }
|
||||
// { contactId, status: "open", userId: botInfo.userIdBot }
|
||||
{ contactId, status: "queueChoice" },
|
||||
{ contactId, status: "open", userId: botInfo.userIdBot }
|
||||
]
|
||||
}
|
||||
});
|
||||
|
|
|
@ -12,6 +12,7 @@ import DeleteUserService from "../services/UserServices/DeleteUserService";
|
|||
|
||||
import ListUser from "../services/UserServices/ListUserParamiterService";
|
||||
import User from "../models/User";
|
||||
import { get, set } from "../helpers/RedisClient";
|
||||
|
||||
import {
|
||||
startWhoIsOnlineMonitor,
|
||||
|
@ -134,7 +135,8 @@ export const all = async (req: Request, res: Response): Promise<Response> => {
|
|||
};
|
||||
|
||||
export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||
const { email, password, name, profile, positionCompany, queueIds } = req.body;
|
||||
const { email, password, name, profile, positionCompany, queueIds } =
|
||||
req.body;
|
||||
|
||||
console.log("===========> req.url: ", req.url);
|
||||
|
||||
|
@ -149,13 +151,10 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
|||
getSettingValue("userCreation")?.value == "disabled"
|
||||
) {
|
||||
throw new AppError("ERR_USER_CREATION_DISABLED", 403);
|
||||
} else if (
|
||||
req.user.profile !== "master"
|
||||
) {
|
||||
} else if (req.user.profile !== "master") {
|
||||
throw new AppError("ERR_NO_PERMISSION", 403);
|
||||
}
|
||||
|
||||
|
||||
const user = await CreateUserService({
|
||||
email,
|
||||
password,
|
||||
|
@ -266,12 +265,38 @@ export const update = async (
|
|||
}
|
||||
}
|
||||
|
||||
// console.log('userQueuesAttendance: ', userQueuesAttendance)
|
||||
|
||||
// return res.status(200).json({});
|
||||
|
||||
let user: any = await UpdateUserService({ userData, userId });
|
||||
|
||||
if (user?.name?.trim() == "botqueue") {
|
||||
let botInfo;
|
||||
|
||||
if (
|
||||
user?.queues?.length > 0 &&
|
||||
user.queues[0]?.name?.trim() == "botqueue"
|
||||
) {
|
||||
botInfo = JSON.stringify({
|
||||
userId: user.id,
|
||||
queueId: user.queues[0].id,
|
||||
botIsOnQueue: true
|
||||
});
|
||||
botInfo = JSON.parse(botInfo);
|
||||
|
||||
await set("botInfo", botInfo);
|
||||
} else if (
|
||||
user?.queues?.length == 0 ||
|
||||
user.queues[0]?.name?.trim() != "botqueue"
|
||||
) {
|
||||
botInfo = JSON.stringify({
|
||||
userId: user.id,
|
||||
queueId: 0,
|
||||
botIsOnQueue: false
|
||||
});
|
||||
botInfo = JSON.parse(botInfo);
|
||||
|
||||
await set("botInfo", botInfo);
|
||||
}
|
||||
}
|
||||
|
||||
const io = getIO();
|
||||
io.emit("user", {
|
||||
action: "update",
|
||||
|
|
|
@ -1,37 +1,26 @@
|
|||
const fsPromises = require("fs/promises");
|
||||
const fs = require('fs')
|
||||
const fs = require("fs");
|
||||
|
||||
import ListUsersService from "../services/UserServices/ListUsersService"
|
||||
import ListUsersService from "../services/UserServices/ListUsersService";
|
||||
import { get } from "./RedisClient";
|
||||
|
||||
const _botIsOnQueue = async (botName: string) => {
|
||||
|
||||
const { users, count, hasMore } = await ListUsersService({searchParam:`${botName}`,pageNumber:1});
|
||||
let botIsOnQueue = false
|
||||
let userIdBot = null
|
||||
let queueId = null
|
||||
|
||||
if(users.length > 0){
|
||||
|
||||
try {
|
||||
|
||||
console.log('----------------- bot queue id: ', Object(users)[0]["queues"][0].id)
|
||||
queueId = Object(users)[0]["queues"][0].id;
|
||||
userIdBot = Object(users)[0].id
|
||||
botIsOnQueue = true
|
||||
|
||||
}catch(err){
|
||||
|
||||
console.log('O usuário botqueue não está em nenhuma fila err: ',err)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
console.log('Usuário botqueue não existe!')
|
||||
}
|
||||
|
||||
return { userIdBot: userIdBot, botQueueId: queueId, isOnQueue: botIsOnQueue }
|
||||
const botInfo = await get("botInfo");
|
||||
|
||||
if (
|
||||
botInfo &&
|
||||
botInfo?.userId &&
|
||||
botInfo?.queueId &&
|
||||
botInfo?.botIsOnQueue == true
|
||||
) {
|
||||
return {
|
||||
userIdBot: botInfo.userId,
|
||||
botQueueId: botInfo.queueId,
|
||||
isOnQueue: botInfo.botIsOnQueue
|
||||
};
|
||||
}
|
||||
return { userIdBot: null, botQueueId: null, isOnQueue: false };
|
||||
};
|
||||
|
||||
export default _botIsOnQueue;
|
||||
export default _botIsOnQueue;
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
import ListTicketTimeLife from "../services/TicketServices/ListTicketTimeLife";
|
||||
import UpdateTicketService from "../services/TicketServices/UpdateTicketService";
|
||||
import BotIsOnQueue from "./BotIsOnQueue";
|
||||
|
||||
const fsPromises = require("fs/promises");
|
||||
const fs = require('fs')
|
||||
|
||||
let timer: any
|
||||
|
||||
const CloseBotTickets = async () => {
|
||||
|
||||
try {
|
||||
|
||||
const botInfo = await BotIsOnQueue('botqueue')
|
||||
|
||||
if (!botInfo.userIdBot) return
|
||||
|
||||
let tickets: any = await ListTicketTimeLife({ timeseconds: 60, status: 'open', userId: botInfo.userIdBot })
|
||||
|
||||
console.log('tickets: ', tickets)
|
||||
|
||||
for (let i = 0; i < tickets.length; i++) {
|
||||
|
||||
await UpdateTicketService({
|
||||
ticketData: { 'status': 'closed', 'userId': botInfo.userIdBot, 'statusChatEnd': 'FINALIZADO' },
|
||||
ticketId: tickets[i].ticket_id
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log('There was an error on try close the bot tickets: ', error)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const schedule = async () => {
|
||||
|
||||
try {
|
||||
clearInterval(timer);
|
||||
|
||||
await CloseBotTickets()
|
||||
|
||||
} catch (error) {
|
||||
console.log('error on schedule: ', error)
|
||||
}
|
||||
finally {
|
||||
timer = setInterval(schedule, 60000);
|
||||
}
|
||||
}
|
||||
|
||||
timer = setInterval(schedule, 60000);
|
||||
|
||||
export default schedule;
|
|
@ -0,0 +1,130 @@
|
|||
const Redis = require("ioredis");
|
||||
const redis = new Redis(process.env.REDIS_URI);
|
||||
|
||||
type WhatsappData = {
|
||||
whatsappId: string;
|
||||
contactId: string;
|
||||
identifier: string;
|
||||
value?: string;
|
||||
};
|
||||
|
||||
export async function set(key: string, value: string) {
|
||||
await redis.set(key, JSON.stringify(value));
|
||||
}
|
||||
|
||||
export async function get(key: string) {
|
||||
const value: any = await redis.get(key);
|
||||
return JSON.parse(value);
|
||||
}
|
||||
|
||||
export async function createObject({
|
||||
whatsappId,
|
||||
contactId,
|
||||
identifier,
|
||||
value
|
||||
}: WhatsappData) {
|
||||
const key = `whatsappId:${whatsappId}:contactId:${contactId}:identifier:${identifier}`;
|
||||
const result = await redis.hmset(
|
||||
key,
|
||||
"whatsappId",
|
||||
whatsappId,
|
||||
"contactId",
|
||||
contactId,
|
||||
"identifier",
|
||||
identifier,
|
||||
"value",
|
||||
value
|
||||
);
|
||||
|
||||
await redis.expire(key, 300);
|
||||
}
|
||||
|
||||
export async function updateObject({
|
||||
whatsappId,
|
||||
contactId,
|
||||
identifier,
|
||||
value
|
||||
}: WhatsappData) {
|
||||
const key = `whatsappId:${whatsappId}:contactId:${contactId}:identifier:${identifier}`;
|
||||
|
||||
await redis.hset(key, "value", value);
|
||||
}
|
||||
|
||||
export async function findObject(
|
||||
whatsappId: string,
|
||||
contactId: string,
|
||||
identifier: string
|
||||
) {
|
||||
const key = `whatsappId:${whatsappId}:contactId:${contactId}:identifier:${identifier}`;
|
||||
const result = await redis.hmget(
|
||||
key,
|
||||
"whatsappId",
|
||||
"contactId",
|
||||
"identifier",
|
||||
"value"
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function deleteObject(
|
||||
whatsappId: string,
|
||||
contactId: string,
|
||||
identifier: string
|
||||
) {
|
||||
const key = `whatsappId:${whatsappId}:contactId:${contactId}:identifier:${identifier}`;
|
||||
const deletedCount = await redis.del(key);
|
||||
}
|
||||
|
||||
export async function deleteKeysWithPattern(
|
||||
whatsappId: string,
|
||||
contactId: string
|
||||
) {
|
||||
const pattern = `whatsappId:${whatsappId}:contactId:${contactId}:*`;
|
||||
|
||||
let cursor = "0";
|
||||
|
||||
do {
|
||||
const [newCursor, keys] = await redis.scan(
|
||||
cursor,
|
||||
"MATCH",
|
||||
pattern,
|
||||
"COUNT",
|
||||
"100"
|
||||
);
|
||||
|
||||
for (const key of keys) {
|
||||
await redis.del(key);
|
||||
}
|
||||
|
||||
cursor = newCursor;
|
||||
} while (cursor !== "0");
|
||||
}
|
||||
|
||||
export async function getHashesWithPattern(
|
||||
whatsappId: string,
|
||||
contactId: string
|
||||
) {
|
||||
const pattern = `whatsappId:${whatsappId}:contactId:${contactId}:*`;
|
||||
|
||||
let cursor = "0";
|
||||
const hashes = [];
|
||||
|
||||
do {
|
||||
const [newCursor, keys] = await redis.scan(
|
||||
cursor,
|
||||
"MATCH",
|
||||
pattern,
|
||||
"COUNT",
|
||||
"100"
|
||||
);
|
||||
|
||||
for (const key of keys) {
|
||||
const hash = await redis.hgetall(key);
|
||||
hashes.push(hash);
|
||||
}
|
||||
|
||||
cursor = newCursor;
|
||||
} while (cursor !== "0");
|
||||
|
||||
return hashes;
|
||||
}
|
|
@ -9,6 +9,8 @@ queueRoutes.get("/queue", isAuth, QueueController.index);
|
|||
|
||||
queueRoutes.post("/queue", isAuth, QueueController.store);
|
||||
|
||||
queueRoutes.post("/queue/customization", QueueController.customization);
|
||||
|
||||
queueRoutes.get("/queue/:queueId", isAuth, QueueController.show);
|
||||
|
||||
queueRoutes.put("/queue/:queueId", isAuth, QueueController.update);
|
||||
|
|
|
@ -7,6 +7,8 @@ import User from "./models/User";
|
|||
import Whatsapp from "./models/Whatsapp";
|
||||
import endPointQuery from "./helpers/EndPointQuery";
|
||||
import { cacheSize, flushCache, loadTicketsCache } from "./helpers/TicketCache";
|
||||
|
||||
import "./helpers/CloseBotTickets";
|
||||
import { loadContactsCache } from "./helpers/ContactsCache";
|
||||
import { loadSchedulesCache } from "./helpers/SchedulingNotifyCache";
|
||||
import { delRestoreControllFile } from "./helpers/RestoreControll";
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
import { subHours, subMinutes, subSeconds } from "date-fns";
|
||||
import { Op } from "sequelize";
|
||||
import BotIsOnQueue from "../../helpers/BotIsOnQueue";
|
||||
import Contact from "../../models/Contact";
|
||||
import Ticket from "../../models/Ticket";
|
||||
import ShowWhatsAppService from "../WhatsappService/ShowWhatsAppService";
|
||||
import ShowTicketService from "./ShowTicketService";
|
||||
import AppError from "../../errors/AppError";
|
||||
import { userInfo } from "os";
|
||||
import ShowQueueService from "../QueueService/ShowQueueService";
|
||||
import UpdateTicketService from "./UpdateTicketService";
|
||||
|
||||
|
||||
const FindOrCreateTicketServiceBot = async (
|
||||
contact: Contact,
|
||||
whatsappId: number,
|
||||
unreadMessages: number,
|
||||
groupContact?: Contact
|
||||
): Promise<any> => {
|
||||
|
||||
try {
|
||||
|
||||
let ticket = await Ticket.findOne({
|
||||
where: {
|
||||
status: {
|
||||
[Op.or]: ["open", "pending", "queueChoice"]
|
||||
},
|
||||
contactId: groupContact ? groupContact.id : contact.id
|
||||
}
|
||||
});
|
||||
|
||||
const { queues, greetingMessage } = await ShowWhatsAppService(whatsappId);
|
||||
|
||||
|
||||
//Habilitar esse caso queira usar o bot
|
||||
const botInfo = await BotIsOnQueue('botqueue')
|
||||
// const botInfo = { isOnQueue: false }
|
||||
|
||||
|
||||
|
||||
if (ticket) {
|
||||
await ticket.update({ unreadMessages });
|
||||
}
|
||||
|
||||
// if (!ticket && groupContact) {
|
||||
// ticket = await Ticket.findOne({
|
||||
// where: {
|
||||
// contactId: groupContact.id
|
||||
// },
|
||||
// order: [["updatedAt", "DESC"]]
|
||||
// });
|
||||
|
||||
|
||||
|
||||
// if (ticket) {
|
||||
|
||||
// await ticket.update({
|
||||
// status: "pending",
|
||||
// userId: null,
|
||||
// unreadMessages
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
if (!ticket && !groupContact) {
|
||||
|
||||
console.log('BOT CREATING OR REOPENING THE TICKET')
|
||||
|
||||
ticket = await Ticket.findOne({
|
||||
where: {
|
||||
contactId: contact.id,
|
||||
userId: botInfo.userIdBot
|
||||
},
|
||||
order: [["updatedAt", "DESC"]]
|
||||
});
|
||||
|
||||
if (ticket) {
|
||||
|
||||
await ticket.update({
|
||||
status: "open",
|
||||
userId: botInfo.userIdBot,
|
||||
unreadMessages
|
||||
});
|
||||
|
||||
console.log('lxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
|
||||
|
||||
await dialogFlowStartContext(contact, ticket, botInfo);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
let created = false
|
||||
|
||||
if (!ticket) {
|
||||
|
||||
created = true
|
||||
|
||||
let status = "open"
|
||||
|
||||
if (queues.length > 1 && !botInfo.isOnQueue) {
|
||||
status = "queueChoice"
|
||||
}
|
||||
|
||||
ticket = await Ticket.create({
|
||||
contactId: groupContact ? groupContact.id : contact.id,
|
||||
status: status,
|
||||
userId: botInfo.userIdBot,
|
||||
isGroup: !!groupContact,
|
||||
unreadMessages,
|
||||
whatsappId
|
||||
});
|
||||
|
||||
console.log('yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy')
|
||||
|
||||
await dialogFlowStartContext(contact, ticket, botInfo);
|
||||
|
||||
}
|
||||
|
||||
ticket = await ShowTicketService(ticket.id);
|
||||
|
||||
return { ticket, created };
|
||||
|
||||
} catch (error: any) {
|
||||
console.error('===> Error on FindOrCreateTicketServiceBot.ts file: \n', error)
|
||||
throw new AppError(error.message);
|
||||
}
|
||||
};
|
||||
|
||||
export default FindOrCreateTicketServiceBot;
|
||||
|
||||
async function dialogFlowStartContext(contact: Contact, ticket: Ticket, botInfo: any) {
|
||||
|
||||
let msg: any = { type: 'chat', from: `${contact.number}@c.us`, body: '0' };
|
||||
|
||||
let queue = await ShowQueueService(botInfo.botQueueId);
|
||||
|
||||
await UpdateTicketService({
|
||||
ticketData: { queueId: queue.id },
|
||||
ticketId: ticket.id
|
||||
});
|
||||
|
||||
ticket = await ShowTicketService(ticket.id);
|
||||
|
||||
// await sendDialogflowAnswer(ticket.whatsappId, ticket, msg, contact, false);
|
||||
|
||||
}
|
||||
|
|
@ -9,6 +9,8 @@ import ShowTicketService from "./ShowTicketService";
|
|||
import { createOrUpdateTicketCache } from "../../helpers/TicketCache";
|
||||
import AppError from "../../errors/AppError";
|
||||
import sendWhatsAppMessageSocket from "../../helpers/SendWhatsappMessageSocket";
|
||||
import BotIsOnQueue from "../../helpers/BotIsOnQueue";
|
||||
import { deleteObject } from "../../helpers/RedisClient"
|
||||
var flatten = require("flat");
|
||||
|
||||
interface TicketData {
|
||||
|
@ -49,6 +51,15 @@ const UpdateTicketService = async ({
|
|||
|
||||
const ticket = await ShowTicketService(ticketId);
|
||||
|
||||
const botInfo = await BotIsOnQueue("botqueue");
|
||||
|
||||
if (
|
||||
status == "closed" ||
|
||||
(status == "open" && ticket && `${userId}` != `${botInfo.userIdBot}`)
|
||||
) {
|
||||
deleteObject(`${ticket.whatsappId}`, `${ticket.contactId}`, "ura");
|
||||
}
|
||||
|
||||
const oldStatus = ticket.status;
|
||||
const oldUserId = ticket.user?.id;
|
||||
|
||||
|
@ -68,7 +79,6 @@ const UpdateTicketService = async ({
|
|||
await ticket.reload();
|
||||
|
||||
if (msg?.trim().length > 0) {
|
||||
|
||||
setTimeout(async () => {
|
||||
sendWhatsAppMessageSocket(ticket, msg);
|
||||
}, 2000);
|
||||
|
|
|
@ -2,7 +2,7 @@ import User from "../../models/User";
|
|||
import AppError from "../../errors/AppError";
|
||||
import Ticket from "../../models/Ticket";
|
||||
import UpdateDeletedUserOpenTicketsStatus from "../../helpers/UpdateDeletedUserOpenTicketsStatus";
|
||||
|
||||
import { set } from "../../helpers/RedisClient"
|
||||
|
||||
const DeleteUserService = async (id: string | number): Promise<void> => {
|
||||
const user = await User.findOne({
|
||||
|
@ -13,6 +13,17 @@ const DeleteUserService = async (id: string | number): Promise<void> => {
|
|||
throw new AppError("ERR_NO_USER_FOUND", 404);
|
||||
}
|
||||
|
||||
if (user?.name?.trim() == "botqueue") {
|
||||
let botInfo = JSON.stringify({
|
||||
userId: 0,
|
||||
queueId: 0,
|
||||
botIsOnQueue: false
|
||||
});
|
||||
botInfo = JSON.parse(botInfo);
|
||||
|
||||
await set("botInfo", botInfo);
|
||||
}
|
||||
|
||||
const userOpenTickets: Ticket[] = await user.$get("tickets", {
|
||||
where: { status: "open" }
|
||||
});
|
||||
|
@ -21,9 +32,7 @@ const DeleteUserService = async (id: string | number): Promise<void> => {
|
|||
UpdateDeletedUserOpenTicketsStatus(userOpenTickets);
|
||||
}
|
||||
|
||||
|
||||
await user.destroy();
|
||||
|
||||
};
|
||||
|
||||
export default DeleteUserService;
|
||||
|
|
|
@ -88,6 +88,7 @@ import { Op } from "sequelize";
|
|||
import SettingTicket from "../../models/SettingTicket";
|
||||
import mostRepeatedPhrase from "../../helpers/MostRepeatedPhrase";
|
||||
import ListWhatsAppsNumber from "../WhatsappService/ListWhatsAppsNumber";
|
||||
import { createObject, findObject, get } from "../../helpers/RedisClient";
|
||||
|
||||
var lst: any[] = getWhatsappIds();
|
||||
|
||||
|
@ -298,8 +299,8 @@ const verifyQueue = async (
|
|||
let choosenQueue = null;
|
||||
|
||||
//Habilitar esse caso queira usar o bot
|
||||
// const botInfo = await BotIsOnQueue('botqueue')
|
||||
const botInfo = { isOnQueue: false, botQueueId: 0, userIdBot: 0 };
|
||||
const botInfo = await BotIsOnQueue("botqueue");
|
||||
// const botInfo = { isOnQueue: false, botQueueId: 0, userIdBot: 0 };
|
||||
|
||||
if (botInfo.isOnQueue) {
|
||||
choosenQueue = await ShowQueueService(botInfo.botQueueId);
|
||||
|
@ -337,9 +338,17 @@ const verifyQueue = async (
|
|||
ticketId: ticket.id
|
||||
});
|
||||
|
||||
data_ura.forEach((s, index) => {
|
||||
botOptions += `*${index + 1}* - ${s.option}\n`;
|
||||
const data = await get("ura");
|
||||
|
||||
await createObject({
|
||||
whatsappId: `${ticket.whatsappId}`,
|
||||
contactId: `${ticket.contactId}`,
|
||||
identifier: "ura",
|
||||
value: data[1].id
|
||||
});
|
||||
|
||||
botSendMessage(ticket, data[1].value);
|
||||
return;
|
||||
}
|
||||
//
|
||||
|
||||
|
@ -479,12 +488,35 @@ const queuesOutBot = async (wbot: Session, botId: string | number) => {
|
|||
return { queues, greetingMessage };
|
||||
};
|
||||
|
||||
const botTransferTicket = async (
|
||||
queues: Queue,
|
||||
ticket: Ticket,
|
||||
contact: Contact,
|
||||
wbot: Session
|
||||
) => {
|
||||
const transferTicket = async (queueName: any, wbot: any, ticket: Ticket) => {
|
||||
const botInfo = await BotIsOnQueue("botqueue");
|
||||
|
||||
console.log("kkkkkkkkkkkkkkkkkkkkk queueName: ", queueName);
|
||||
|
||||
const queuesWhatsGreetingMessage = await queuesOutBot(
|
||||
wbot,
|
||||
botInfo.botQueueId
|
||||
);
|
||||
|
||||
let queue: any;
|
||||
|
||||
const queues = queuesWhatsGreetingMessage.queues;
|
||||
|
||||
// console.log("queues ---> ", console.log(JSON.stringify(queues, null, 6)));
|
||||
|
||||
if (typeof queueName == "string") {
|
||||
queue = queues.find(
|
||||
(q: any) => q?.name?.toLowerCase() == queueName.trim().toLowerCase()
|
||||
);
|
||||
// await deleteObject(wbot.id, `${ticket.contactId}`, "ura");
|
||||
} else if (typeof queueName == "number") {
|
||||
queue = queues[queueName];
|
||||
}
|
||||
|
||||
if (queue) await botTransferTicket(queue, ticket);
|
||||
};
|
||||
|
||||
const botTransferTicket = async (queues: Queue, ticket: Ticket) => {
|
||||
await ticket.update({ userId: null });
|
||||
|
||||
await UpdateTicketService({
|
||||
|
@ -683,9 +715,72 @@ const handleMessage = async (
|
|||
// O bot interage com o cliente e encaminha o atendimento para fila de atendende quando o usuário escolhe a opção falar com atendente
|
||||
|
||||
//Habilitar esse caso queira usar o bot
|
||||
// const botInfo = await BotIsOnQueue('botqueue')
|
||||
const botInfo = await BotIsOnQueue("botqueue");
|
||||
// const botInfo = { isOnQueue: false, botQueueId: 0, userIdBot: 0 };
|
||||
|
||||
if (
|
||||
botInfo.isOnQueue &&
|
||||
!msg.fromMe &&
|
||||
ticket.userId == botInfo.userIdBot
|
||||
) {
|
||||
const repet: any = await mostRepeatedPhrase(ticket.id);
|
||||
|
||||
console.log("repet.occurrences: ", repet.occurrences);
|
||||
|
||||
if (repet.occurrences > 4) {
|
||||
await transferTicket(0, wbot, ticket);
|
||||
|
||||
await SendWhatsAppMessage({
|
||||
body: `Seu atendimento foi transferido para um agente!\n\nPara voltar ao menu principal digite *0*
|
||||
`,
|
||||
ticket,
|
||||
number: `${contact.number}@c.us`
|
||||
});
|
||||
} else {
|
||||
console.log("MSG body: ", msg.body);
|
||||
|
||||
const menuMsg: any = await menu(msg.body, wbot.id, contact.id);
|
||||
|
||||
console.log("menuMsg: ", menuMsg);
|
||||
|
||||
await botSendMessage(ticket, menuMsg.value);
|
||||
|
||||
if (
|
||||
menuMsg?.transferToQueue &&
|
||||
menuMsg.transferToQueue.trim().length > 0
|
||||
) {
|
||||
console.log(
|
||||
"YYYYYYYYYYYYYYYYYYYY menuMsg.transferToQueue: ",
|
||||
menuMsg.transferToQueue
|
||||
);
|
||||
|
||||
transferTicket(menuMsg.transferToQueue.trim(), wbot, ticket);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (
|
||||
!msg.fromMe &&
|
||||
msg.body == "0" &&
|
||||
ticket.status == "pending" &&
|
||||
ticket.queueId
|
||||
) {
|
||||
let choosenQueue = await ShowQueueService(botInfo.botQueueId);
|
||||
|
||||
await UpdateTicketService({
|
||||
ticketData: {
|
||||
status: "open",
|
||||
userId: botInfo.userIdBot,
|
||||
queueId: choosenQueue.id
|
||||
},
|
||||
ticketId: ticket.id
|
||||
});
|
||||
const menuMsg: any = await menu(msg.body, wbot.id, contact.id);
|
||||
await botSendMessage(ticket, menuMsg.value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg && !msg.fromMe && ticket.status == "pending") {
|
||||
await setMessageAsRead(ticket);
|
||||
}
|
||||
|
@ -720,6 +815,133 @@ const handleMessage = async (
|
|||
}
|
||||
};
|
||||
|
||||
const menu = async (userTyped: string, whatsappId: any, contactId: any) => {
|
||||
let lastId = await findObject(whatsappId, contactId, "ura");
|
||||
const data: any = await get("ura");
|
||||
|
||||
console.log("lastId[0]: ", lastId[0]);
|
||||
|
||||
if (!lastId[0]) {
|
||||
await createObject({
|
||||
whatsappId,
|
||||
contactId,
|
||||
identifier: "ura",
|
||||
value: data[1].id
|
||||
});
|
||||
}
|
||||
|
||||
lastId = await findObject(whatsappId, contactId, "ura");
|
||||
console.log("LAST ID: ", lastId);
|
||||
let option: any;
|
||||
|
||||
if (
|
||||
lastId &&
|
||||
lastId.length == 4 &&
|
||||
lastId[3] &&
|
||||
lastId[3].trim().length > 0
|
||||
) {
|
||||
option = data.find(
|
||||
(o: any) =>
|
||||
o.idmaster == lastId[3] &&
|
||||
o.value.toLowerCase() == userTyped.toLowerCase()
|
||||
);
|
||||
|
||||
// TEST DEL
|
||||
console.log("OPTION: ", option);
|
||||
|
||||
if (!option && userTyped != "0") {
|
||||
if (!existSubMenu()) {
|
||||
const response = await mainOptionsMenu(userTyped);
|
||||
if (response) return response;
|
||||
else {
|
||||
console.log("kkkkkkkkkkkkkkkkkkk");
|
||||
await createObject({
|
||||
whatsappId,
|
||||
contactId,
|
||||
identifier: "ura",
|
||||
value: data[1].id
|
||||
});
|
||||
|
||||
return data[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
|
||||
if (option) {
|
||||
let response: any = data.find((o: any) => o.idmaster == option.id);
|
||||
|
||||
console.log(
|
||||
"RRRRRRRRRRRRRRRRRRRRRRRRRRRRR response: ",
|
||||
response,
|
||||
" | option: ",
|
||||
option
|
||||
);
|
||||
|
||||
await createObject({
|
||||
whatsappId,
|
||||
contactId,
|
||||
identifier: "ura",
|
||||
value: response.id
|
||||
});
|
||||
|
||||
return response;
|
||||
} else if (userTyped == "0") {
|
||||
await createObject({
|
||||
whatsappId,
|
||||
contactId,
|
||||
identifier: "ura",
|
||||
value: data[1].id
|
||||
});
|
||||
|
||||
return data[1];
|
||||
} else {
|
||||
console.log("INVALID SEARCH");
|
||||
|
||||
let response = await existSubMenu();
|
||||
if (response) return response;
|
||||
|
||||
return {
|
||||
value: data.find((o: any) => o.id == lastId[3])?.value
|
||||
};
|
||||
|
||||
// return {
|
||||
// value: `Você digitou uma opçao inválida!\n\n${
|
||||
// data.find((o: any) => o.id == lastId[3])?.value
|
||||
// }\n\nDigite 0 para voltar ao menu `
|
||||
// };
|
||||
}
|
||||
}
|
||||
|
||||
function existSubMenu() {
|
||||
let existSubMenu = data.find((o: any) => o.idmaster == lastId[3]);
|
||||
|
||||
if (existSubMenu) true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
async function mainOptionsMenu(userTyped: any) {
|
||||
let menuOption = data.find(
|
||||
(o: any) => o.value.toLowerCase() == userTyped.toLowerCase()
|
||||
);
|
||||
console.log("============> menuOption OPTION: ", menuOption);
|
||||
if (menuOption) {
|
||||
let response = data.find((o: any) => o.idmaster == menuOption.id);
|
||||
if (response) {
|
||||
await createObject({
|
||||
whatsappId,
|
||||
contactId,
|
||||
identifier: "ura",
|
||||
value: response.id
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleMsgAck = async (
|
||||
msg_id: any,
|
||||
ack: any,
|
||||
|
|
|
@ -161,7 +161,9 @@ const TicketsManager = () => {
|
|||
let searchContentTimeout;
|
||||
|
||||
useEffect(() => {
|
||||
if (user.profile.toUpperCase() === "ADMIN") {
|
||||
if (user.profile.toUpperCase() === "ADMIN" ||
|
||||
user.profile.toUpperCase() === "SUPERVISOR" ||
|
||||
user.profile.toUpperCase() === "MASTER") {
|
||||
setShowAllTickets(true);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
|
|
@ -9,7 +9,8 @@ const rules = {
|
|||
"user-view:show",
|
||||
"user-modal:editQueues",
|
||||
'dashboard-view:show',
|
||||
'ticket-report:show'
|
||||
'ticket-report:show',
|
||||
'tickets-manager:showall'
|
||||
]
|
||||
},
|
||||
|
||||
|
|
Loading…
Reference in New Issue