505 lines
18 KiB
TypeScript
505 lines
18 KiB
TypeScript
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<void> {
|
|
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<void> {
|
|
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<IMessageConversation> {
|
|
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<void> {
|
|
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<PaginateMessageConversationsResults> {
|
|
return await this.conversations.paginate(filters);
|
|
}
|
|
|
|
private async getUserRelationWithMe(userId: string, sessionUser: string): Promise<string> {
|
|
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<FindConversationsResults> {
|
|
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<string>(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<IMessageConversation | null> {
|
|
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<PaginateFindContactsResults> {
|
|
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<void> {
|
|
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<void> {
|
|
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<number> {
|
|
const searchCriteria: mongoose.FilterQuery<IMessageConversation> = {};
|
|
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;
|