import UsersManager from "../Users/Users"; import CompaniesManager from "../Companies/Companies"; import { ConvertU2UMessageConversationParams, CountUnreadConversationParams, CreateMessageConversationParams, DeleteConversationsByCompanyParams, DeleteConversationsByUserParams, DeleteMessageConversationParams, FindConversationItem, FindConversationsResults, IMessageConversation, IMessageConversationsManager, MarkConversationAsReadParams, MESSAGE_CONVERSATION_TYPES, PaginateFindContactsParams, PaginateFindContactsResults, PaginateMessageConversationsParams, PaginateMessageConversationsResults, } from "./MessagesConversations.Interface"; import { MessageConversationsAdapterMongoose } from "./MessagesConversations.Adapter.Mongoose"; import EmployeesList from "../Employees/Employee"; import ClientsList from "../Clients/Clients"; import getAvatar from "../../helpers/getAvatar"; import UserList from "../Users/Users"; import MessagesList from "../Messages/Messages"; import { isNull } from "../../helpers/IsNull"; import SystemNoficationsList from "../SystemNotifications/SystemNotification"; import mongoose from "mongoose"; type GetConversationParams = { userId: string; }; class MessageConversationsManager implements IMessageConversationsManager { conversations: MessageConversationsAdapterMongoose; constructor() { this.conversations = new MessageConversationsAdapterMongoose(); } public async deleteConversationsByUser(data: DeleteConversationsByUserParams): Promise { const conversationsFrom = await this.conversations.find({ userIdFrom: data.userId }); for (const conv of conversationsFrom) { await MessagesList.messages.messageList.deleteMany({ conversationId: conv.id }); } const conversationsTo = await this.conversations.find({ userIdTo: data.userId }); for (const conv of conversationsTo) { await MessagesList.messages.messageList.deleteMany({ conversationId: conv.id }); } await this.conversations.conversationList.deleteMany({ userIdFrom: data.userId }); await this.conversations.conversationList.deleteMany({ userIdTo: data.userId }); } public async deleteConversationsByCompany( data: DeleteConversationsByCompanyParams ): Promise { const conversations = await this.conversations.find({ companyId: data.companyId }); for (const conv of conversations) { await MessagesList.messages.messageList.deleteMany({ conversationId: conv.id }); } await this.conversations.conversationList.deleteMany({ companyId: data.companyId }); } public async createConversation( data: CreateMessageConversationParams ): Promise { if (data.userIdFrom) { const userFromCheck = await UsersManager.users.findOne({ _id: data.userIdFrom }); if (!userFromCheck) { throw new Error("Usuario invalido"); } } if (data.userIdTo) { const userToCheck = await UsersManager.users.findOne({ _id: data.userIdTo }); if (!userToCheck) { throw new Error("Usuario invalido"); } } if (data.companyId) { const companyCheck = await CompaniesManager.companies.findOne({ _id: data.companyId }); if (!companyCheck) { throw new Error("La compañia no existe"); } } const newConversation = await this.conversations.create(data); return newConversation; } public async deleteConversation(data: DeleteMessageConversationParams): Promise { const checkUser = await UsersManager.users.findOne({ _id: data.sessionUser }); if (!checkUser) { throw new Error("Usuario invalido"); } const checkConversation = await this.conversations.conversationList.findOne({ _id: data.id, }); if (!checkConversation) { throw new Error("Conversacion invalida"); } if (checkConversation.type == MESSAGE_CONVERSATION_TYPES.USER_TO_USER) { if (String(checkConversation.userIdFrom) !== data.sessionUser) { throw new Error("No tienes permiso para eliminar esta conversacion"); } } else if (checkConversation.type == MESSAGE_CONVERSATION_TYPES.USER_TO_ORG) { if (String(checkConversation.userIdFrom) !== data.sessionUser) { throw new Error("No tienes permiso para eliminar esta conversacion"); } } await this.conversations.delete(data.id); } public async paginateConversations( filters: PaginateMessageConversationsParams ): Promise { return await this.conversations.paginate(filters); } private async getUserRelationWithMe(userId: string, sessionUser: string): Promise { const myOrgs = await EmployeesList.employees.find({ userId: sessionUser }); for (const org of myOrgs) { const organization = await CompaniesManager.companies.findOne({ _id: org.companyId }); if (!organization) { continue; } //Buscamos si es un colaborador en una de mis organizaciones. const employee = await EmployeesList.employees.findOne({ userId, companyId: org.companyId, }); if (employee) { return "Colaborador en " + organization.name; } //Buscamos si es un cliente en una de mis organizaciones. const client = await ClientsList.clients.findOne({ userId: userId, companyId: org.companyId, }); if (client) { return "Cliente de " + organization.name; } } const orgsAsClient = await ClientsList.clients.find({ userId: sessionUser, }); for (const organization of orgsAsClient) { const checkColaIsCollaborator = await EmployeesList.employees.findOne({ companyId: organization.companyId, userId: userId, }); if (checkColaIsCollaborator) { const org = await CompaniesManager.companies.findOne({ _id: organization.companyId, }); if (!org) { continue; } return "Miembro de " + org.name; } } return "Otros contactos"; } public async findConversations( data: PaginateFindContactsParams ): Promise { const items: FindConversationItem[] = []; const conversations = await this.conversations.paginate(data); for (const conversation of conversations.data) { let contactName = ""; let contactUserId: string | undefined = ""; let contactAvatar: string = ""; let conversationName = ""; let conversationDescription = ""; let conversationImage = ""; if (conversation.type == MESSAGE_CONVERSATION_TYPES.USER_TO_USER) { if (conversation.userIdFrom == data.sessionUser) { const user = await UserList.users.findOne({ _id: conversation.userIdTo }); if (!user) { continue; } contactName = UserList.getUserFullName(user); contactUserId = String(conversation.userIdTo); contactAvatar = user.avatar ? user.avatar : ""; } else if (conversation.userIdTo == data.sessionUser) { const user = await UserList.users.findOne({ _id: conversation.userIdFrom }); if (!user) { continue; } contactName = UserList.getUserFullName(user); contactUserId = String(conversation.userIdFrom); contactAvatar = user.avatar ? user.avatar : ""; } if (contactUserId) { conversationName = contactName; conversationDescription = await this.getUserRelationWithMe( contactUserId, data.sessionUser ); conversationImage = getAvatar(contactUserId, contactAvatar, contactName); } } else if (conversation.type == MESSAGE_CONVERSATION_TYPES.USER_TO_ORG) { if (conversation.userIdFrom == data.sessionUser) { const org = await CompaniesManager.companies.findOne({ _id: conversation.companyId, }); if (!org) { continue; } conversationName = org.name; conversationDescription = org.description; conversationImage = isNull(org.iconFile, org.name); } else if (conversation.companyId) { const user = await UserList.users.findOne({ _id: conversation.userIdFrom }); if (!user) { continue; } conversationName = UserList.getUserFullName(user); conversationDescription = "Consulta a la organización"; conversationImage = getAvatar(user.id, user.avatar, conversationName); } } let unreadCount = 0; if (conversation && conversation.id) { unreadCount = await this.countUnreadMessages({ conversationId: conversation.id, sessionUser: data.sessionUser, }); } items.push({ conversation: { id: conversation.id, userIdFrom: conversation.userIdFrom, userIdTo: conversation.userIdTo, companyId: conversation.companyId, type: conversation.type, newMessages: unreadCount, }, name: conversationName, description: conversationDescription, image: conversationImage, orderWeight: 1, }); } return { data: items, page: conversations.page, pages: conversations.pages, } as FindConversationsResults; } private async getConversationIfExists( data: GetConversationParams ): Promise { let conversation = await this.conversations.conversationList.findOne({ userIdFrom: data.userId, }); if (!conversation) { conversation = await this.conversations.conversationList.findOne({ userIdTo: data.userId, }); } return conversation; } public async paginateFindContacts( data: PaginateFindContactsParams ): Promise { const items: FindConversationItem[] = []; //Mostrar las organizaciones en las que el usuario es cliente. const companiesAsClient = await CompaniesManager.getByClientId({ clientId: data.sessionUser, sessionUser: data.sessionUser, }); for (const org of companiesAsClient) { items.push({ conversation: { companyId: org.id, type: MESSAGE_CONVERSATION_TYPES.USER_TO_ORG, newMessages: 0, }, name: org.name, description: org.description, image: org.logoFile, orderWeight: 1, }); //Mostrar los colaboradores de esa organizacion. const employeesByOrganization = await EmployeesList.findByCompanyId({ companyId: org.id, }); for (const employee of employeesByOrganization) { const conversation = await this.getConversationIfExists({ userId: employee.userId, }); let unreadCount = 0; if (conversation && conversation.id) { unreadCount = await this.countUnreadMessages({ conversationId: conversation.id, sessionUser: data.sessionUser, }); } items.push({ conversation: conversation ? ({ id: conversation.id, userIdFrom: conversation.userIdFrom, userIdTo: conversation.userIdTo, companyId: conversation.companyId, type: conversation.type, newMessages: unreadCount, } as IMessageConversation) : { userIdTo: employee.userId, type: MESSAGE_CONVERSATION_TYPES.USER_TO_USER, newMessages: 0, }, name: employee.fullName, description: org.name, image: employee.avatar, orderWeight: 2, }); } } //Mostras los clientes y colaboradores de las organizaciones donde el usuario es colaborador. const companiesAsCollaborator = await EmployeesList.employees.find({ userId: data.sessionUser, }); for (const org of companiesAsCollaborator) { const organization = await CompaniesManager.companies.findOne({ _id: org.companyId }); if (!organization) { continue; } //Mostras los clientes de las organizaciones donde el usuario es colaborador. const organizationClients = await ClientsList.clients.find({ companyId: org.companyId, }); for (const client of organizationClients) { if (!client.userId) { continue; } const clientName = ClientsList.getClientFullName(client); items.push({ conversation: { userIdFrom: data.sessionUser, userIdTo: client.userId, type: MESSAGE_CONVERSATION_TYPES.USER_TO_USER, newMessages: 0, }, name: clientName, description: "Cliente de " + organization.name, image: getAvatar(client.userId, "", clientName), orderWeight: 2, }); } //Mostrar los colaboradores de las organizaciones donde el usuario es colaborador. const organizationEmployees = await EmployeesList.employees.find({ companyId: org.companyId, }); for (const employee of organizationEmployees) { const employeeUser = await UserList.users.findOne({ _id: employee.userId }); if (!employeeUser) { continue; } if (employee.userId == data.sessionUser) { continue; } const employeeName = UserList.getUserFullName(employeeUser); items.push({ conversation: { userIdFrom: data.sessionUser, userIdTo: employee.userId, type: MESSAGE_CONVERSATION_TYPES.USER_TO_USER, newMessages: 0, }, name: employeeName, description: "Colaborador en " + organization.name, image: getAvatar(employee.userId, "", employeeName), orderWeight: 2, }); } } const query = data.query ? data.query.toUpperCase() : ""; return { data: items.filter( (i) => String(i.name + i.description) .toUpperCase() .indexOf(query) >= 0 ), page: 1, pages: 1, } as PaginateFindContactsResults; } public async markConversationAsRead(data: MarkConversationAsReadParams): Promise { const checkUser = await UsersManager.users.findOne({ _id: data.sessionUser }); if (!checkUser) { throw new Error("Usuario invalido"); } const checkConversation = await this.conversations.conversationList.findOne({ _id: data.conversationId, }); if (!checkConversation) { throw new Error("Conversacion invalida"); } await MessagesList.markAsRead({ conversationId: data.conversationId, sessionUser: data.sessionUser, }); await SystemNoficationsList.deleteConversationNotifications({ conversationId: data.conversationId, userId: data.sessionUser, sessionUser: data.sessionUser, }); } public async convertUserToUser(data: ConvertU2UMessageConversationParams): Promise { const checkUser = await UsersManager.users.findOne({ _id: data.sessionUser }); if (!checkUser) { throw new Error("Usuario invalido"); } const checkConversation = await this.conversations.conversationList.findOne({ _id: data.conversationId, }); if (!checkConversation) { throw new Error("Conversacion invalida"); } checkConversation.type = MESSAGE_CONVERSATION_TYPES.USER_TO_USER; checkConversation.userIdTo = data.sessionUser; await checkConversation.save(); } public async countUnreadMessages(data: CountUnreadConversationParams): Promise { const searchCriteria: mongoose.FilterQuery = {}; searchCriteria.conversationId = data.conversationId; searchCriteria.readed = false; searchCriteria.userId = { $ne: data.sessionUser }; const unreadMessages = await MessagesList.messages.find(searchCriteria); return unreadMessages.length; } } const MessageConversationList = new MessageConversationsManager(); export default MessageConversationList;