Files
turnosxpress/server/src/Models/Companies/Companies.ts
T

1093 lines
41 KiB
TypeScript

import fs from "fs";
import path from "path";
import { rm } from "fs/promises";
import { CompaniesAdapterMongoose } from "./Companies.Adapter.Mongoose";
import {
CreateCompanyParams,
FindCompaniesParams,
UpdateCompanyParams,
ICompaniesAdapter,
ICompaniesManager,
ICompany,
PaginateCompaniesParams,
PaginateCompaniesResults,
SetCompanyFileParams,
DeleteCompanyFileParams,
MyOranizationsView,
MyOranizationsViewParams,
OranizationsViewByIdParams,
ClientOranizationsViewParams,
ClientOrganizationView,
DeleteCompanyParams,
SetOrganizationPublishedStatusParams,
COMPANY_PUBLISHED_STATUS,
SetNotificationAutoParams,
FixCompanyPostParams,
MoveCompanyFixedPostParams,
SysAdminPaginateCompaniesParams,
SysAdminUpdateCompanyParams,
SysAdminSetCompanyBannedParams,
} from "./Companies.Interface";
import UsersManager from "../Users/Users";
import EmployeesList from "../Employees/Employee";
import { EmployeeRoles } from "../Employees/Employees.Interface";
import { NoPermissionMessage } from "../../helpers/NoPermissionMessage";
import { isNull } from "../../helpers/IsNull";
import sharp from "sharp";
import getHeader from "../../helpers/getHeader";
import MetricsList from "../../Models/Metrics/Metrics";
import { TextObjectFilterResult } from "../TextObjectFilter.model";
import { NotificationsManager } from "../Notifications/Notifications";
import ClientsList from "../Clients/Clients";
import { validateSessionUser, validatePermissionsByCompany } from "../../helpers/check";
import { resizeAndCrop } from "../../helpers/resizeAndCrop";
import HeatMapList from "../HeatMap/HeatMap";
import AppointmentList from "../Appointments/Appointments";
import EmployeesServicesList from "../EmployeesServices/EmployeesServices";
import SchedulesEnabledList from "../SchedulesEnabled/SchedulesEnabled";
import SchedulesList from "../Schedules/Schedules";
import ServiceList from "../Services/Service";
import MessageConversationList from "../MessageConversations/MessagesConversations";
import WapServerList from "../WapServer/WapServer";
import RepeatsList from "../Repeats/Repeats";
import ClientAccount from "../ClientAccounts/ClientAccount";
import Payments from "../Payments/Payments";
import Discounts from "../Discounts/Discounts";
import Templates from "../Templates/Templates";
import Posts from "../Posts/Posts";
import SchedulesDisabledList from "../SchedulesDisabled/SchedulesDisabled";
import DiscountsEmail from "../DiscountsEmail/DiscountsEmail";
import { NotificationType } from "../../Models/SystemNotifications/SystemNotification.Interface";
class CompaniesManager implements ICompaniesManager {
companies: ICompaniesAdapter;
constructor() {
this.companies = new CompaniesAdapterMongoose();
}
private async validatePublicRatingFlagsPlan(ownerId: string): Promise<void> {
const { default: PlanSubscriptionsList } = await import("../PlanSubscriptions/PlanSubscriptons");
const subscription = await PlanSubscriptionsList.getSubscriptionByUser({
sessionUser: ownerId,
});
if (!subscription || subscription.plan.price === 0) {
throw new Error("Esta configuración está disponible solo para planes pagos.");
}
}
public async toggleFixedPost(data: FixCompanyPostParams): Promise<void> {
await validateSessionUser({
sessionUser: data.sessionUser,
});
const { company } = await validatePermissionsByCompany({
companyId: data.companyId,
sessionUser: data.sessionUser,
});
const checkPost = await Posts.posts.findOne({
id: data.postId,
});
if (!checkPost) {
throw new Error("El post que intenta actualizar no existe");
}
checkPost.fixed = !checkPost.fixed;
await checkPost.save();
if (checkPost.fixed) {
company.fixedPostIds?.push(checkPost.id);
} else {
company.fixedPostIds = company.fixedPostIds?.filter(
(item) => String(item) !== String(checkPost.id)
);
}
await company.save();
}
public async moveFixedPost(data: MoveCompanyFixedPostParams): Promise<void> {
await validateSessionUser({
sessionUser: data.sessionUser,
});
const { company } = await validatePermissionsByCompany({
companyId: data.companyId,
sessionUser: data.sessionUser,
});
const checkPost = await Posts.posts.findOne({
id: data.postId,
});
if (!checkPost) {
throw new Error("El post que intenta actualizar no existe");
}
if (!checkPost.fixed) {
throw new Error("El post no es fijo");
}
const currentPosition = company.fixedPostIds?.findIndex(
(item) => String(item) === String(data.postId)
);
if (currentPosition === undefined || currentPosition < 0) {
throw new Error("No es posible mover el post");
}
company.fixedPostIds = company.fixedPostIds?.filter((item) => String(item) !== String(data.postId));
company.fixedPostIds?.splice(currentPosition + data.moveLength, 0, data.postId);
await company.save();
}
public async setNotificationAuto(data: SetNotificationAutoParams): Promise<void> {
const sessionUser = await UsersManager.users.findOne({
_id: data.sessionUser,
});
if (!sessionUser) {
throw new Error("No se ha encontrado el usuario o no tiene permisos para realizar esta acción");
}
const companyCheck = await this.companies.findOne({
_id: data.companyId,
});
if (!companyCheck) {
throw new Error("La compañia no existe");
}
if (!(await EmployeesList.checkPermission(companyCheck, data.sessionUser, EmployeeRoles.ADMIN))) {
throw new Error(NoPermissionMessage());
}
companyCheck.automaticNotifications = isNull<boolean>(data.status, false);
await companyCheck.save();
}
public async setPublishedStatus(data: SetOrganizationPublishedStatusParams): Promise<void> {
const sessionUser = await UsersManager.users.findOne({
_id: data.sessionUser,
});
if (!sessionUser) {
throw new Error("No se ha encontrado el usuario o no tiene permisos para realizar esta acción");
}
const companyCheck = await this.companies.findOne({
_id: data.companyId,
});
if (!companyCheck) {
throw new Error("La compañia no existe");
}
if (!(await EmployeesList.checkPermission(companyCheck, data.sessionUser, EmployeeRoles.ADMIN))) {
throw new Error(NoPermissionMessage());
}
companyCheck.published = data.published;
await companyCheck.save();
}
public async deleteCompany(data: DeleteCompanyParams): Promise<void> {
const userCheck = await UsersManager.users.findOne({
_id: data.sessionUser,
});
if (!userCheck) {
throw new Error("No se ha encontrado el usuario o no tiene permisos para realizar esta acción");
}
const companyCheck = await this.companies.findOne({
_id: data.companyId,
});
if (!companyCheck) {
throw new Error("La compañia no existe");
}
if (String(companyCheck.ownerId) !== data.sessionUser) {
throw new Error(
"No tienes permisos para realizar esta acción. Solo el dueño puede eliminar la organización."
);
}
try {
//eliminar heatmaps
await HeatMapList.deleteHeatMapByCompany({
companyId: data.companyId,
});
//eliminar appointments
await AppointmentList.deleteAppointmentsByCompany({
companyId: data.companyId,
});
//eliminar los employees services
await EmployeesServicesList.deleteEmployeeServiceByCompany({
companyId: data.companyId,
});
//eliminar schedules enabled.
await SchedulesEnabledList.deleteSchedulesEnabledByCompany({
companyId: data.companyId,
});
//eliminar schedules disabled.
await SchedulesDisabledList.deleteSchedulesDisabledByCompany({
companyId: data.companyId,
});
//eliminar scheduyles.
await SchedulesList.deleteSchedulesByCompany({
companyId: data.companyId,
});
//eliminar employees
await EmployeesList.deleteEmployeesByCompany({
companyId: data.companyId,
});
//eliminar metrics
await MetricsList.deleteMetricsByCompany({
companyId: data.companyId,
});
//eliminar services
await ServiceList.deleteServicesByCompany({
companyId: data.companyId,
});
//eliminar cuenta corriente de los clientes
await ClientAccount.deleteClientsAccountsByCompany({
companyId: data.companyId,
});
//eliminar pagos
await Payments.deletePaymentsByCompany({
companyId: data.companyId,
});
//eliminar clients
await ClientsList.deleteClientsByCompany({
companyId: data.companyId,
});
//eliminar conversations
await MessageConversationList.deleteConversationsByCompany({
companyId: data.companyId,
});
//eliminar las repeticiones
await RepeatsList.deleteRepeatsByCompany({
companyId: data.companyId,
});
//eliminar los templates
await Templates.deleteTemplatesByCompany({
companyId: data.companyId,
});
try {
//eliminar wap server asignations
const companyServer = companyCheck.wapServerId;
if (companyServer) {
await WapServerList.deleteBot({
companyId: data.companyId,
sessionUser: data.sessionUser,
});
const server = await WapServerList.servers.findOne({
id: companyServer,
});
if (server) {
server.countBots -= 1;
await server.save();
}
}
} catch (e) {
console.log(e);
}
//eliminar los descuentos por email
await DiscountsEmail.deleteDiscountsEmailByCompany({
companyId: data.companyId,
});
//eliminar descuentos
await Discounts.deleteDiscountsByCompany({
companyId: data.companyId,
});
const companyName = `${companyCheck.name}`;
//eliminar imagenes de la company
await this.deleteCompanyFiles(data.companyId);
//eliminar company
await this.companies.delete(data.companyId);
await NotificationsManager.sendSystemNotification({
subject: "Organización eliminada",
message: `La organización ${companyName} ha sido eliminada.`,
userId: data.sessionUser,
});
} catch (e) {
console.log(e);
}
}
private async deleteCompanyFiles(companyId: string): Promise<void> {
const rootDir =
process.env.NODE_ENV !== "production"
? process.env.UPLOAD_COMPANY_FILES_ROOT_DEV
: process.env.UPLOAD_COMPANY_FILES_ROOT_PRO;
if (!rootDir) {
throw new Error("No se ha encontrado la ruta de los archivos");
}
const companyDir = path.join(__dirname, rootDir, companyId);
try {
await rm(companyDir, { recursive: true, force: true });
} catch (err) {
console.error(`Error al eliminar el directorio ${companyDir}:`, err);
}
}
public getSlug(name: string): string {
return name
.replaceAll(".", "")
.replaceAll(",", "")
.replaceAll(":", "")
.replaceAll(";", "")
.replaceAll("!", "")
.replaceAll("<", "")
.replaceAll(">", "")
.replaceAll("'", "")
.replaceAll('"', "")
.replaceAll("#", "")
.replaceAll("$", "")
.replaceAll("%", "")
.replaceAll("&", "")
.replaceAll("/", "")
.replaceAll("(", "")
.replaceAll(")", "")
.replaceAll("=", "")
.replaceAll("¿", "")
.replaceAll("?", "")
.replaceAll("*", "")
.replaceAll("+", "")
.replaceAll("-", "")
.replaceAll("|", "")
.replaceAll("{", "")
.replaceAll("}", "")
.replaceAll("[", "")
.replaceAll("]", "")
.split(" ")
.filter((item) => item.length > 0)
.reduce((acc, item) => acc + "-" + item.toLowerCase(), "")
.substring(1);
}
public async createCompany(data: CreateCompanyParams): Promise<ICompany> {
const owner = UsersManager.users.findOne({ _id: data.ownerId });
if (!owner) throw new Error("El propietario de la empresa no es un usuario registrado.");
const checkCompany = await this.isValidName(data);
if (!checkCompany) {
throw new Error("El nombre de la organización no es válido. Por favor, pruebe con otro nombre.");
}
await MetricsList.calculateMetrics({ userId: data.ownerId });
const canAdd = await MetricsList.canAddOrganization(data.ownerId);
if (!canAdd) {
throw new Error("Ha alcanzado el limite de organizaciones permitidas de acuerdo a su plan.");
}
const invalidNames = [
"admin",
"components",
"fonts",
"helpers",
"hooks",
"landing",
"messenger",
"theme",
"user",
];
if (invalidNames.includes(data.name.toLowerCase())) {
throw new Error("El nombre de la organización no es válido. Por favor, pruebe con otro nombre.");
}
const newCompany = await this.companies.create({
...data,
...{
slug: this.getSlug(data.name),
name: data.name.toLocaleLowerCase(),
},
});
if (!newCompany.id) {
throw new Error("Ha ocurrido un error al crear la compañia.");
}
await NotificationsManager.sendSystemNotification({
userId: String(data.ownerId),
subject: "Se ha creado una nueva compañia",
message: `Se ha creado la compañia ${data.name} exitosamente.`,
type: NotificationType.COMPANY,
code: String((newCompany as any)._id)
});
await MetricsList.addOrganization({
userId: data.ownerId,
quantity: 1,
});
const newEmplyee = await EmployeesList.createEmployee({
companyId: newCompany.id,
userId: String(newCompany.ownerId),
roles: [EmployeeRoles.OWNER, EmployeeRoles.ADMIN],
sessionUser: String(newCompany.ownerId),
});
//Valida el empleado como aceptado por ambas partes. Solo paso employeeId ya que
//un employee solo pertenece a una empresa.
await EmployeesList.validateFull({
employeeId: String(newEmplyee.id),
sessionUser: String(newCompany.ownerId),
});
await NotificationsManager.sendSystemNotification({
userId: String(data.ownerId),
subject: "Administrador asignado",
message: `Su usuario ha sido asignado como administrador de la compañia ${data.name}.`,
type: NotificationType.COMPANY,
code: String((newCompany as any)._id)
});
return newCompany;
}
public async updateCompany(data: UpdateCompanyParams): Promise<void> {
await validateSessionUser({ sessionUser: data.sessionUser });
await validatePermissionsByCompany({ companyId: data.id, sessionUser: data.sessionUser });
const companyCheck = await this.companies.findOne({ _id: data.id });
if (!companyCheck) {
throw new Error("La compañia no existe");
}
if (data.name) {
const otherCompany = await this.companies.findOne({
name: data.name,
});
if (otherCompany && otherCompany.id !== data.id) {
throw new Error(
"El nuevo nombre de la organización no es válido. Por favor, pruebe con otro nombree ya que su elección actual esta en uso"
);
}
data.name = data.name.toLocaleLowerCase();
}
if (!(await EmployeesList.checkPermission(companyCheck, data.sessionUser, EmployeeRoles.ADMIN))) {
throw new Error(NoPermissionMessage());
}
if (
data.showPublicScores !== undefined ||
data.showPublicOpinions !== undefined ||
data.showPublicProfessionals !== undefined
) {
await this.validatePublicRatingFlagsPlan(String(companyCheck.ownerId));
}
let updateData = {
...data,
};
if (data.name) {
updateData = {
...updateData,
...{ name: data.name.toLocaleLowerCase() },
...{ slug: this.getSlug(data.name) },
};
}
await this.companies.update(updateData);
}
public async isValidName(data: FindCompaniesParams): Promise<boolean> {
if (!data.name) return false;
const checkSlug = this.getSlug(data.name);
const checkCompany = await this.companies.findOne({ slug: checkSlug });
if (checkCompany) {
return false;
}
return true;
}
public async getById(data: OranizationsViewByIdParams): Promise<MyOranizationsView> {
const sessionUser = await UsersManager.users.findOne({
_id: data.sessionUser,
});
if (!sessionUser) {
throw new Error("No se ha encontrado el usuario o no tiene permisos para realizar esta acción");
}
const company = await this.companies.findOne({ _id: data.id });
//TODO: chequear si es el dueño. y si esta aceptado
if (!company) {
throw new Error("La compañia no existe");
}
const employ = await EmployeesList.employees.findOne({
companyId: data.id,
userId: String(data.sessionUser),
removed: { $ne: true },
} as any);
if (!employ) {
throw new Error("El usuario no participa de la organización");
}
const defColor = "#" + String(process.env.DEFAULT_HEADER_COLOR);
const defFontColor = "#" + String(process.env.DEFAULT_HEADER_FONT_COLOR);
const defFontShadowColor = "#" + String(process.env.DEFAULT_HEADER_FONT_SHADOW_COLOR);
const isAdmin = await EmployeesList.checkPermission(company, data.sessionUser, EmployeeRoles.ADMIN);
return {
id: isNull<string>(company.id, ""),
name: isNull<string>(company.name, ""),
slug: isNull<string>(company.slug, ""),
description: isNull<string>(company.description, ""),
categoryId: isNull<number>(company.categoryId, 50000),
ownerId: company.ownerId,
employeeId: String(employ.id),
isOwner: String(company.ownerId) == String(data.sessionUser) ? true : false,
isAdmin: isAdmin,
hostOk: employ.hostOk ? true : false,
guestOk: employ.guestOk ? true : false,
fullOk: employ.hostOk && employ.guestOk ? true : false,
/*headerFile: isNull<string>(company.headerFile, ""),*/
headerFile: getHeader(company.id, isNull<string>(company.headerFile, ""), ""),
headerColor: isNull<string>(company.headerColor, defColor),
headerFontColor: isNull<string>(company.headerFontColor, defFontColor),
headerFontShadowColor: isNull<string>(company.headerFontShadowColor, defFontShadowColor),
iconFile: isNull<string>(company.iconFile, ""),
logoFile: isNull<string>(company.logoFile, ""),
phoneAreaCode: isNull<string>(company.phoneAreaCode, ""),
phoneNumber: isNull<string>(company.phoneNumber, ""),
heatMapFraction: isNull<number>(company.heatMapFraction, 60),
appointmentTime: isNull<number>(company.appointmentTime, 24),
cancellationTime: isNull<number>(company.cancellationTime, 24),
street: isNull<string>(company.street, ""),
streetNumber: isNull<string>(company.streetNumber, ""),
builingFloor: isNull<string>(company.builingFloor, ""),
buildingApartament: isNull<string>(company.buildingApartament, ""),
block: isNull<string>(company.block, ""),
city: isNull<string>(company.city, ""),
state: isNull<string>(company.state, ""),
country: isNull<string>(company.country, ""),
zipCode: isNull<string>(company.zipCode, ""),
latitude: isNull<number>(company.latitude, 0),
longitude: isNull<number>(company.longitude, 0),
published: isNull<COMPANY_PUBLISHED_STATUS>(company.published, COMPANY_PUBLISHED_STATUS.PRIVATE),
automaticNotifications: isNull<boolean>(company.automaticNotifications, false),
appointmentAlert: isNull<string>(company.appointmentAlert, ""),
templateWapNotifId: isNull<string>(company.templateWapNotifId, ""),
templateWapAltaId: isNull<string>(company.templateWapAltaId, ""),
templateEmailNotifId: isNull<string>(company.templateEmailNotifId, ""),
templateEmailAltaId: isNull<string>(company.templateEmailAltaId, ""),
onboardingStep: company.onboardingStep,
onboardingCompleted: company.onboardingCompleted,
showPublicScores: company.showPublicScores ?? true,
showPublicOpinions: company.showPublicOpinions ?? true,
showPublicProfessionals: company.showPublicProfessionals ?? true,
};
}
public async getByClientId(data: ClientOranizationsViewParams): Promise<ClientOrganizationView[]> {
const clientCompanies = await ClientsList.clients.find({
userId: data.clientId,
});
const returnData: ClientOrganizationView[] = [];
//Organizaciones del cliente.
for (const orgItem of clientCompanies) {
const company = await this.companies.findOne({
_id: orgItem.companyId,
});
if (!company) {
continue;
}
returnData.push({
id: isNull<string>(company._id, ""),
name: isNull<string>(company.name, ""),
slug: isNull<string>(company.slug, ""),
description: isNull<string>(company.description, ""),
iconFile: isNull<string>(company.iconFile, ""),
logoFile: isNull<string>(company.logoFile, ""),
});
}
return returnData;
}
public async getByUserId(data: MyOranizationsViewParams): Promise<MyOranizationsView[]> {
const ownerCompanies = await this.companies.find({
ownerId: data.sessionUser,
});
const returnData: MyOranizationsView[] = [];
const defColor = "#" + String(process.env.DEFAULT_HEADER_COLOR);
const defFontColor = "#" + String(process.env.DEFAULT_HEADER_FONT_COLOR);
const defFontShadowColor = "#" + String(process.env.DEFAULT_HEADER_FONT_SHADOW_COLOR);
//Organizaciones del usuario
for (const company of ownerCompanies) {
const companyDoc = await this.companies.findOne({
_id: company.id,
});
if (!companyDoc) {
continue;
}
const employ = await EmployeesList.employees.findOne({
companyId: String(company.id),
userId: String(data.sessionUser),
});
if (!employ) {
continue;
}
const isAdmin = await EmployeesList.checkPermission(
companyDoc,
data.sessionUser,
EmployeeRoles.ADMIN
);
returnData.push({
id: isNull<string>(company.id, ""),
name: isNull<string>(company.name, ""),
slug: isNull<string>(company.slug, ""),
description: isNull<string>(company.description, ""),
categoryId: isNull<number>(company.categoryId, 50000),
ownerId: company.ownerId,
employeeId: employ ? String(employ.id) : "",
isOwner: true,
isAdmin: isAdmin,
hostOk: true,
guestOk: true,
fullOk: true,
//headerFile: isNull<string>(company.headerFile, ""),
headerFile: getHeader(
isNull<string>(company.id, ""),
isNull<string>(company.headerFile, ""),
""
),
headerColor: isNull<string>(company.headerColor, defColor),
headerFontColor: isNull<string>(company.headerFontColor, defFontColor),
headerFontShadowColor: isNull<string>(company.headerFontShadowColor, defFontShadowColor),
iconFile: isNull<string>(company.iconFile, ""),
logoFile: isNull<string>(company.logoFile, ""),
phoneAreaCode: isNull<string>(company.phoneAreaCode, ""),
phoneNumber: isNull<string>(company.phoneNumber, ""),
heatMapFraction: isNull<number>(company.heatMapFraction, 60),
appointmentTime: isNull<number>(company.appointmentTime, 24),
cancellationTime: isNull<number>(company.cancellationTime, 24),
street: isNull<string>(company.street, ""),
streetNumber: isNull<string>(company.streetNumber, ""),
builingFloor: isNull<string>(company.builingFloor, ""),
buildingApartament: isNull<string>(company.buildingApartament, ""),
block: isNull<string>(company.block, ""),
city: isNull<string>(company.city, ""),
state: isNull<string>(company.state, ""),
country: isNull<string>(company.country, ""),
zipCode: isNull<string>(company.zipCode, ""),
latitude: isNull<number>(company.latitude, 0),
longitude: isNull<number>(company.longitude, 0),
published: isNull<COMPANY_PUBLISHED_STATUS>(
company.published,
COMPANY_PUBLISHED_STATUS.PRIVATE
),
automaticNotifications: isNull<boolean>(company.automaticNotifications, false),
appointmentAlert: isNull<string>(company.appointmentAlert, ""),
templateWapNotifId: isNull<string>(company.templateWapNotifId, ""),
templateEmailNotifId: isNull<string>(company.templateEmailNotifId, ""),
templateWapAltaId: isNull<string>(company.templateWapAltaId, ""),
templateEmailAltaId: isNull<string>(company.templateEmailAltaId, ""),
onboardingStep: company.onboardingStep,
onboardingCompleted: company.onboardingCompleted,
showPublicScores: company.showPublicScores ?? true,
showPublicOpinions: company.showPublicOpinions ?? true,
showPublicProfessionals: company.showPublicProfessionals ?? true,
});
}
//Organizaciones en las que participa como colaborador.
const orgCollaborator = await EmployeesList.employees.find({
userId: data.sessionUser,
removed: { $ne: true },
} as any);
for (const item of orgCollaborator) {
if (item.companyId) {
const company = await this.companies.findOne({
_id: item.companyId,
});
if (company) {
if (String(company.ownerId) == String(data.sessionUser)) {
continue;
}
const isAdmin = await EmployeesList.checkPermission(
company,
data.sessionUser,
EmployeeRoles.ADMIN
);
returnData.push({
id: isNull<string>(company.id, ""),
name: isNull<string>(company.name, ""),
slug: isNull<string>(company.slug, ""),
description: isNull<string>(company.description, ""),
categoryId: isNull<number>(company.categoryId, 50000),
ownerId: company.ownerId,
employeeId: String(item.id),
isOwner: false,
isAdmin: isAdmin,
hostOk: item.hostOk ? true : false,
guestOk: item.guestOk ? true : false,
fullOk: item.hostOk && item.guestOk ? true : false,
headerFile: isNull<string>(company.headerFile, ""),
iconFile: isNull<string>(company.iconFile, ""),
logoFile: isNull<string>(company.logoFile, ""),
phoneAreaCode: isNull<string>(company.phoneAreaCode, ""),
phoneNumber: isNull<string>(company.phoneNumber, ""),
heatMapFraction: isNull<number>(company.heatMapFraction, 60),
appointmentTime: isNull<number>(company.appointmentTime, 24),
cancellationTime: isNull<number>(company.cancellationTime, 24),
street: isNull<string>(company.street, ""),
streetNumber: isNull<string>(company.streetNumber, ""),
builingFloor: isNull<string>(company.builingFloor, ""),
buildingApartament: isNull<string>(company.buildingApartament, ""),
block: isNull<string>(company.block, ""),
city: isNull<string>(company.city, ""),
state: isNull<string>(company.state, ""),
country: isNull<string>(company.country, ""),
zipCode: isNull<string>(company.zipCode, ""),
latitude: isNull<number>(company.latitude, 0),
longitude: isNull<number>(company.longitude, 0),
published: isNull<COMPANY_PUBLISHED_STATUS>(
company.published,
COMPANY_PUBLISHED_STATUS.PRIVATE
),
automaticNotifications: isNull<boolean>(company.automaticNotifications, false),
appointmentAlert: isNull<string>(company.appointmentAlert, ""),
templateWapNotifId: isNull<string>(company.templateWapNotifId, ""),
templateEmailNotifId: isNull<string>(company.templateEmailNotifId, ""),
templateWapAltaId: isNull<string>(company.templateWapAltaId, ""),
templateEmailAltaId: isNull<string>(company.templateEmailAltaId, ""),
onboardingStep: company.onboardingStep,
onboardingCompleted: company.onboardingCompleted,
showPublicScores: company.showPublicScores ?? true,
showPublicOpinions: company.showPublicOpinions ?? true,
showPublicProfessionals: company.showPublicProfessionals ?? true,
});
}
}
}
return returnData;
}
public async paginate(filters: PaginateCompaniesParams): Promise<PaginateCompaniesResults> {
return await this.companies.paginate(filters);
}
public async setCompanyHeader(data: SetCompanyFileParams): Promise<void> {
const sessionUser = await UsersManager.users.findOne({
_id: data.sessionUser,
});
if (!sessionUser) {
throw new Error("No se ha encontrado el usuario o no tiene permisos para realizar esta acción");
}
const companyCheck = await this.companies.findOne({
_id: data.companyId,
});
if (!companyCheck) {
throw new Error("La compañia no existe");
}
if (!(await EmployeesList.checkPermission(companyCheck, data.sessionUser, EmployeeRoles.ADMIN))) {
throw new Error(NoPermissionMessage());
}
if (!data.file) {
throw new Error("No se ha enviado el archivo");
}
const rootDir =
process.env.NODE_ENV !== "production"
? process.env.UPLOAD_COMPANY_FILES_ROOT_DEV
: process.env.UPLOAD_COMPANY_FILES_ROOT_PRO;
const uploadPath = path.join(__dirname, rootDir + data.companyId);
if (!fs.existsSync(uploadPath)) {
fs.mkdirSync(uploadPath, { recursive: true });
}
const fileExtension = data.file.originalname.split(".").pop();
const newFileName = "header." + fileExtension;
const filePath = path.join(uploadPath, newFileName);
const bufferImage = await resizeAndCrop(sharp(data.file.buffer), 1138, 248);
bufferImage.webp().toFile(filePath);
//await sharp(data.file.buffer).resize({ height: 150 }).webp().toFile(filePath);
companyCheck.headerFile = newFileName;
await companyCheck.save();
}
public async setCompanyIcon(data: SetCompanyFileParams): Promise<void> {
const sessionUser = await UsersManager.users.findOne({
_id: data.sessionUser,
});
if (!sessionUser) {
throw new Error("No se ha encontrado el usuario o no tiene permisos para realizar esta acción");
}
const companyCheck = await this.companies.findOne({
_id: data.companyId,
});
if (!companyCheck) {
throw new Error("La compañia no existe");
}
if (!(await EmployeesList.checkPermission(companyCheck, data.sessionUser, EmployeeRoles.ADMIN))) {
throw new Error(NoPermissionMessage());
}
if (!data.file) {
throw new Error("No se ha enviado el archivo");
}
const rootDir =
process.env.NODE_ENV !== "production"
? process.env.UPLOAD_COMPANY_FILES_ROOT_DEV
: process.env.UPLOAD_COMPANY_FILES_ROOT_PRO;
const uploadPath = path.join(__dirname, rootDir + data.companyId);
if (!fs.existsSync(uploadPath)) {
fs.mkdirSync(uploadPath, { recursive: true });
}
const fileExtension = data.file.originalname.split(".").pop();
const newFileName = "icon." + fileExtension;
const filePath = path.join(uploadPath, newFileName);
const uint8Array = new Uint8Array(data.file.buffer);
fs.writeFileSync(filePath, uint8Array);
companyCheck.iconFile = newFileName;
await companyCheck.save();
}
public async deleteCompanyHeader(data: DeleteCompanyFileParams): Promise<void> {
const sessionUser = await UsersManager.users.findOne({
_id: data.sessionUser,
});
if (!sessionUser) {
throw new Error("No se ha encontrado el usuario o no tiene permisos para realizar esta acción");
}
const companyCheck = await this.companies.findOne({
_id: data.companyId,
});
if (!companyCheck) {
throw new Error("La compañia no existe");
}
if (!(await EmployeesList.checkPermission(companyCheck, data.sessionUser, EmployeeRoles.ADMIN))) {
throw new Error(NoPermissionMessage());
}
if (!companyCheck.headerFile) {
throw new Error("No hay ningun archivo para borrar");
}
const rootDir =
process.env.NODE_ENV !== "production"
? process.env.UPLOAD_COMPANY_FILES_ROOT_DEV
: process.env.UPLOAD_COMPANY_FILES_ROOT_PRO;
const uploadPath = path.join(__dirname, rootDir + data.companyId);
const filePath = path.join(uploadPath, companyCheck.headerFile);
if (!fs.existsSync(filePath)) {
throw new Error("El archivo no existe");
}
fs.unlinkSync(filePath);
companyCheck.headerFile = undefined;
await companyCheck.save();
}
public async deleteCompanyIcon(data: DeleteCompanyFileParams): Promise<void> {
const sessionUser = await UsersManager.users.findOne({
_id: data.sessionUser,
});
if (!sessionUser) {
throw new Error("No se ha encontrado el usuario o no tiene permisos para realizar esta acción");
}
const companyCheck = await this.companies.findOne({
_id: data.companyId,
});
if (!companyCheck) {
throw new Error("La compañia no existe");
}
if (!(await EmployeesList.checkPermission(companyCheck, data.sessionUser, EmployeeRoles.ADMIN))) {
throw new Error(NoPermissionMessage());
}
if (!companyCheck.iconFile) {
throw new Error("No hay ningun archivo para borrar");
}
const rootDir =
process.env.NODE_ENV !== "production"
? process.env.UPLOAD_COMPANY_FILES_ROOT_DEV
: process.env.UPLOAD_COMPANY_FILES_ROOT_PRO;
const uploadPath = path.join(__dirname, rootDir + data.companyId);
const filePath = path.join(uploadPath, companyCheck.iconFile);
if (!fs.existsSync(filePath)) {
throw new Error("El archivo no existe");
}
fs.unlinkSync(filePath);
companyCheck.iconFile = undefined;
await companyCheck.save();
}
public async filterAll(data: PaginateCompaniesParams): Promise<TextObjectFilterResult[]> {
const companies = await this.companies.paginateFilterAll(data);
const returnData: TextObjectFilterResult[] = [];
for (const company of companies.data) {
returnData.push({
id: isNull<string>(company.id, ""),
name: company.name,
description: company.description,
});
}
return returnData;
}
public getCompanyAddress(data: ICompany): string {
const address = `${isNull<string>(data.street, "")} ${isNull<string>(
data.streetNumber,
""
)} ${isNull<string>(data.builingFloor, "")} ${isNull<string>(
data.buildingApartament,
""
)} ${isNull<string>(data.block, "")} - ${isNull<string>(data.city, "")}, ${isNull<string>(
data.state,
""
)}, ${isNull<string>(data.country, "")} - CP: ${isNull<string>(data.zipCode, "")}`;
return address;
}
public async sysAdminPaginate(data: SysAdminPaginateCompaniesParams): Promise<PaginateCompaniesResults> {
return await this.companies.sysAdminPaginate(data);
}
public async sysAdminUpdate(data: SysAdminUpdateCompanyParams): Promise<void> {
const companyCheck = await this.companies.findOne({ _id: data.id });
if (!companyCheck) {
throw new Error("La compañia no existe");
}
if (data.name) {
const otherCompany = await this.companies.findOne({ name: data.name.toLocaleLowerCase() });
if (otherCompany && otherCompany.id !== data.id) {
throw new Error("El nuevo nombre de la organización está en uso.");
}
data.name = data.name.toLocaleLowerCase();
}
let updateData: any = { ...data, sessionUser: "" };
if (data.name) {
updateData = {
...updateData,
slug: this.getSlug(data.name)
};
}
await this.companies.update(updateData as UpdateCompanyParams);
}
public async sysAdminSetBanned(data: SysAdminSetCompanyBannedParams): Promise<void> {
const companyCheck = await this.companies.findOne({ _id: data.id });
if (!companyCheck) {
throw new Error("La compañia no existe");
}
await this.companies.update({
id: data.id,
banned: data.banned,
sessionUser: "" // sysadmin override
});
}
}
const CompaniesList = new CompaniesManager();
export default CompaniesList;