From e71150ff75dbb52d544e3be9f89fb082bb61a2c7 Mon Sep 17 00:00:00 2001 From: adriano Date: Mon, 29 Apr 2024 17:27:15 -0300 Subject: [PATCH] feat: Implement solution for searching by message content and fix bug when closing ticket --- backend/src/helpers/MonthsAgo.ts | 23 +++ backend/src/helpers/RedisClient.ts | 6 +- backend/src/server.ts | 47 +++-- .../TicketServices/ListTicketsService.ts | 189 +++++++++++------- .../TicketServices/UpdateTicketService.ts | 15 +- .../src/components/TicketsManager/index.js | 28 +-- 6 files changed, 203 insertions(+), 105 deletions(-) create mode 100644 backend/src/helpers/MonthsAgo.ts diff --git a/backend/src/helpers/MonthsAgo.ts b/backend/src/helpers/MonthsAgo.ts new file mode 100644 index 0000000..51203d8 --- /dev/null +++ b/backend/src/helpers/MonthsAgo.ts @@ -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; diff --git a/backend/src/helpers/RedisClient.ts b/backend/src/helpers/RedisClient.ts index fb99d6e..2520588 100644 --- a/backend/src/helpers/RedisClient.ts +++ b/backend/src/helpers/RedisClient.ts @@ -29,7 +29,7 @@ export async function getSimple(key: string) { export async function get({ key, value, parse }: getData) { if (key.includes("*")) { - const keys = await redis.keys(key); + const keys = await redis.keys(key); if (keys.length > 0) { if (value) { for (const key of keys) { @@ -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; } + + diff --git a/backend/src/server.ts b/backend/src/server.ts index 9fba998..2a34717 100644 --- a/backend/src/server.ts +++ b/backend/src/server.ts @@ -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}`, diff --git a/backend/src/services/TicketServices/ListTicketsService.ts b/backend/src/services/TicketServices/ListTicketsService.ts index f91a671..6068b97 100644 --- a/backend/src/services/TicketServices/ListTicketsService.ts +++ b/backend/src/services/TicketServices/ListTicketsService.ts @@ -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 => { - 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 ( @@ -243,8 +294,8 @@ const ListTicketsService = async ({ const hasMore = count > offset + tickets.length; - const ticketIds = await get({ key: `remote:controll`, parse: true }); - + const ticketIds = await get({ key: `remote:controll`, parse: true }); + return { tickets, count, diff --git a/backend/src/services/TicketServices/UpdateTicketService.ts b/backend/src/services/TicketServices/UpdateTicketService.ts index f508a15..f744270 100644 --- a/backend/src/services/TicketServices/UpdateTicketService.ts +++ b/backend/src/services/TicketServices/UpdateTicketService.ts @@ -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)); + } } } diff --git a/frontend/src/components/TicketsManager/index.js b/frontend/src/components/TicketsManager/index.js index 06ac9c9..9c2b71d 100644 --- a/frontend/src/components/TicketsManager/index.js +++ b/frontend/src/components/TicketsManager/index.js @@ -346,7 +346,7 @@ const TicketsManager = () => { {/* setShowContentSearch(prev => !prev)}> */} - handleOpenTooltipSearch()} onClose={() => handleCloseTooltipSearch()} @@ -360,22 +360,22 @@ const TicketsManager = () => { - + */} { // showContentSearch ? - (showContentSearch && searchParam.searchParam.length >= 4) ? - (
- - handleContentSearch(e)} - /> -
) : null + // (showContentSearch /*&& searchParam.searchParam.length >= 4*/) ? + // (
+ // + // handleContentSearch(e)} + // /> + //
) : null } ) : (