feat: Implement solution for searching by message content and fix bug when closing ticket

feat-scaling-ticket-remote-creation
adriano 2024-04-29 17:27:15 -03:00
parent beb4fd64c4
commit e71150ff75
6 changed files with 203 additions and 105 deletions

View File

@ -0,0 +1,23 @@
const monthsAgo = (months: number) => {
const { subMonths, startOfMonth, format } = require("date-fns");
// Get the current date
const currentDate = new Date();
// Subtract 4 months from the current date
const monthsAgo = subMonths(currentDate, months);
// Get the start of the month for the current date and four months ago
// const startOfCurrentMonth = startOfMonth(currentDate);
const startMonthsAgo = startOfMonth(monthsAgo);
// Format the dates in YYYY-MM-DD format
// const formattedCurrentMonth = format(startOfCurrentMonth, "yyyy-MM-dd");
const formattedMonthsAgo = format(startMonthsAgo, "yyyy-MM-dd");
// console.log("Current Month:", formattedCurrentMonth);
// console.log("Months Ago:", formattedMonthsAgo);
return formattedMonthsAgo;
};
export default monthsAgo;

View File

@ -70,7 +70,7 @@ export async function clearAllKeys(...keys: string[]) {
// If there are keys, delete them
if (del_keys.length > 0) {
console.log("del_keys: ", del_keys);
// console.log("del_keys: ", del_keys);
await redis.del(...del_keys);
}
}
@ -220,3 +220,5 @@ export async function getHashesWithPattern(
return hashes;
}

View File

@ -6,14 +6,18 @@ import { StartAllWhatsAppsSessions } from "./services/WbotServices/StartAllWhats
import User from "./models/User";
import Whatsapp from "./models/Whatsapp";
import endPointQuery from "./helpers/EndPointQuery";
import { cacheSize, flushCache, loadTicketsCache } from "./helpers/TicketCache";
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";
import "./helpers/AutoCloseTickets";
import "./helpers/AutoRemoteTickets"
import "./helpers/AutoRemoteTickets";
import "./helpers/SchedulingNotifySendMessage";
import axios from "axios";
@ -30,6 +34,7 @@ import { json } from "sequelize";
import { setBotInfo } from "./helpers/SetBotInfo";
import Queue from "./models/Queue";
import StatusChatEnd from "./models/StatusChatEnd";
import Message from "./models/Message";
const server = app.listen(process.env.PORT, () => {
logger.info(`Server started on port: ${process.env.PORT}`);
@ -50,7 +55,21 @@ gracefulShutdown(server);
(async () => {
console.log("os.tmpdir(): ", os.tmpdir());
await clearAllKeys("user:*", "whatsapp:*", "queue:*", "statusChatEnd:*");
await clearAllKeys(
"user:*",
"whatsapp:*",
"queue:*",
"statusChatEnd:*",
);
// let messages: any = await Message.findAll({
// attributes: ["id", "ticketId", "body"]
// });
// for (const message of messages) {
// const { id, body, ticketId } = message;
// await set(`message:ticketId:${ticketId}:id:${id}`, body);
// }
const statusChatEnds = await StatusChatEnd.findAll();
@ -90,17 +109,17 @@ gracefulShutdown(server);
try {
const { phoneNumberId, id, greetingMessage } = whatsapps[i];
if (phoneNumberId) {
// await set(
// `whatsapp:${whatsapps[i].dataValues.id}`,
// JSON.stringify({
// number: whatsapps[i].dataValues.number,
// id,
// greetingMessage,
// phoneNumberId
// })
// );
}
// if (phoneNumberId) {
// await set(
// `whatsapp:${whatsapps[i].dataValues.id}`,
// JSON.stringify({
// number: whatsapps[i].dataValues.number,
// id,
// greetingMessage,
// phoneNumberId
// })
// );
// }
await set(
`whatsapp:${whatsapps[i].dataValues.id}`,

View File

@ -15,12 +15,10 @@ const dateToday = splitDateTime(
new Date(format(new Date(), "yyyy-MM-dd HH:mm:ss", { locale: ptBR }))
);
import ListTicketServiceCache from "./ListTicketServiceCache";
import { searchTicketCache, loadTicketsCache } from "../../helpers/TicketCache";
import { getWbot } from "../../libs/wbot";
import User from "../../models/User";
import { get } from "../../helpers/RedisClient";
import monthsAgo from "../../helpers/MonthsAgo";
interface Request {
searchParam?: string;
@ -54,7 +52,12 @@ const ListTicketsService = async ({
unlimited = "false",
searchParamContent = ""
}: Request): Promise<Response> => {
console.log("----------> searchParamContent: ", searchParamContent);
console.log(
"----------> searchParamContent: ",
searchParamContent,
" | searchParam: ",
searchParam
);
let whereCondition: Filterable["where"] = {
[Op.or]: [{ userId }, { status: "pending" }],
@ -67,46 +70,46 @@ const ListTicketsService = async ({
pageNumber = "1";
}
if (searchParam && searchParam.trim().length > 0 && process.env.CACHE) {
try {
const offset = 40 * (+pageNumber - 1);
// if (searchParam && searchParam.trim().length > 0 && process.env.CACHE) {
// try {
// const offset = 40 * (+pageNumber - 1);
searchParam = searchParam.replace(/\s+/g, " ").trim().toLowerCase();
// searchParam = searchParam.replace(/\s+/g, " ").trim().toLowerCase();
console.log("QUERY TICKET SEARCH PARAM FROM CACHE: ", searchParam);
// console.log("QUERY TICKET SEARCH PARAM FROM CACHE: ", searchParam);
let tickets: any = await searchTicketCache(searchParam, offset, 40);
// let tickets: any = await searchTicketCache(searchParam, offset, 40);
if (tickets) {
console.log(
"QUERY TICKET SEARCH PARAM FROM CACHE LENGTH...: ",
tickets.length
);
// if (tickets) {
// console.log(
// "QUERY TICKET SEARCH PARAM FROM CACHE LENGTH...: ",
// tickets.length
// );
tickets.map((t: any) => {
t["contact.number"] = t["contact_number"];
delete t["contact_number"];
// tickets.map((t: any) => {
// t["contact.number"] = t["contact_number"];
// delete t["contact_number"];
return { ...["contact_number"] };
});
// return { ...["contact_number"] };
// });
tickets = tickets.map((e: any) => unflatten(e));
// tickets = tickets.map((e: any) => unflatten(e));
return {
tickets,
count: tickets.length,
hasMore: tickets.length > 0 ? true : false
};
}
} catch (error) {
console.log(
"There was an error on search ListTicketservice.ts search cache: ",
error
);
}
// return {
// tickets,
// count: tickets.length,
// hasMore: tickets.length > 0 ? true : false
// };
// }
// } catch (error) {
// console.log(
// "There was an error on search ListTicketservice.ts search cache: ",
// error
// );
// }
console.log("QUERY TICKETS FROM DATABASE...");
}
// console.log("QUERY TICKETS FROM DATABASE...");
// }
let includeCondition: Includeable[];
@ -143,38 +146,32 @@ const ListTicketsService = async ({
if (searchParam) {
const sanitizedSearchParam = searchParam.toLocaleLowerCase().trim();
const sanitizedSearchParamContent = searchParamContent
.toLocaleLowerCase()
.trim();
if (searchParamContent.length > 0) {
includeCondition = [
...includeCondition,
{
model: Message,
as: "messages",
attributes: ["id", "body"],
where: {
body: where(
fn("LOWER", col("body")),
"LIKE",
`%${sanitizedSearchParamContent}%`
)
},
required: false,
duplicating: false
}
];
includeCondition = [
...includeCondition,
{
model: Message,
as: "messages",
attributes: ["id", "body"],
where: {
body: where(
fn("LOWER", col("body")),
"LIKE",
`%${sanitizedSearchParam}%`
)
},
required: false,
duplicating: false
}
];
whereCondition = {
...whereCondition,
"$message.body$": where(
fn("LOWER", col("body")),
"LIKE",
`%${sanitizedSearchParamContent}%`
)
};
}
whereCondition = {
...whereCondition,
createdAt: {
[Op.gte]: monthsAgo(4) + " 00:00:00.000000",
[Op.lte]: dateToday.fullDate + " 23:59:59.999999"
}
};
whereCondition = {
...whereCondition,
@ -186,11 +183,65 @@ const ListTicketsService = async ({
`%${sanitizedSearchParam}%`
)
},
{ "$contact.number$": { [Op.like]: `%${sanitizedSearchParam}%` } }
{ "$contact.number$": { [Op.like]: `%${sanitizedSearchParam}%` } },
{
"$message.body$": where(
fn("LOWER", col("body")),
"LIKE",
`%${sanitizedSearchParam}%`
)
}
]
};
// const sanitizedSearchParamContent = searchParamContent
// .toLocaleLowerCase()
// .trim();
// if (searchParamContent.length > 0) {
// includeCondition = [
// ...includeCondition,
// {
// model: Message,
// as: "messages",
// attributes: ["id", "body"],
// where: {
// body: where(
// fn("LOWER", col("body")),
// "LIKE",
// `%${sanitizedSearchParamContent}%`
// )
// },
// required: false,
// duplicating: false
// }
// ];
// whereCondition = {
// ...whereCondition,
// "$message.body$": where(
// fn("LOWER", col("body")),
// "LIKE",
// `%${sanitizedSearchParamContent}%`
// )
// };
// }
// whereCondition = {
// ...whereCondition,
// [Op.or]: [
// {
// "$contact.name$": where(
// fn("LOWER", col("contact.name")),
// "LIKE",
// `%${sanitizedSearchParam}%`
// )
// },
// { "$contact.number$": { [Op.like]: `%${sanitizedSearchParam}%` } }
// ]
// };
const userProfile: any = await User.findByPk(userId);
if (

View File

@ -75,16 +75,19 @@ const UpdateTicketService = async ({
del(`remote:ticketId:${ticket.id}`);
let ticketsIds = await get({ key: `remote:controll`, parse: true });
const index = ticketsIds.findIndex((t: any) => t == ticket.id);
console.log("ticketsIds 1: ", ticketsIds);
if (ticketsIds) {
const index = ticketsIds.findIndex((t: any) => t == ticket.id);
if (index != -1) {
ticketsIds.splice(index, 1);
console.log("ticketsIds 1: ", ticketsIds);
console.log("ticketsIds 2: ", ticketsIds);
if (index != -1) {
ticketsIds.splice(index, 1);
set(`remote:controll`, JSON.stringify(ticketsIds));
console.log("ticketsIds 2: ", ticketsIds);
set(`remote:controll`, JSON.stringify(ticketsIds));
}
}
}

View File

@ -346,7 +346,7 @@ const TicketsManager = () => {
{/* <IconButton onClick={() => setShowContentSearch(prev => !prev)}>
<MenuIcon className={classes.menuSearch} />
</IconButton> */}
<Tooltip
{/* <Tooltip
open={openTooltipSearch}
onOpen={() => handleOpenTooltipSearch()}
onClose={() => handleCloseTooltipSearch()}
@ -360,22 +360,22 @@ const TicketsManager = () => {
<MenuIcon className={classes.menuSearch} />
</IconButton>
</span>
</Tooltip>
</Tooltip> */}
</div>
{
// showContentSearch ?
(showContentSearch && searchParam.searchParam.length >= 4) ?
(<div className={classes.searchContentInput}>
<FindInPageIcon className={classes.searchIcon} />
<InputBase
className={classes.searchInput}
inputRef={searchContentInputRef}
placeholder={i18n.t("Busca por conteúdo")}
type="search"
value={inputContentSearch}
onChange={(e) => handleContentSearch(e)}
/>
</div>) : null
// (showContentSearch /*&& searchParam.searchParam.length >= 4*/) ?
// (<div className={classes.searchContentInput}>
// <FindInPageIcon className={classes.searchIcon} />
// <InputBase
// className={classes.searchInput}
// inputRef={searchContentInputRef}
// placeholder={i18n.t("Busca por conteúdo")}
// type="search"
// value={inputContentSearch}
// onChange={(e) => handleContentSearch(e)}
// />
// </div>) : null
}
</div>
) : (