first commit

This commit is contained in:
2026-07-16 20:48:43 -03:00
commit 5696cee264
1111 changed files with 322270 additions and 0 deletions
@@ -0,0 +1,84 @@
import {
FindEmployeesServicesParams,
IEmployeesServicesAdapter,
IEmployeeService,
CreateEmployeeServiceParams,
UpdateEmployeeServiceParams,
PaginateEmployeesServicesParams,
PaginateEmployeesServicesResults,
} from "./EmployeesServices.Interface";
import { Document, Model, Schema, model } from "mongoose";
export interface IEmployeeServiceDocument extends Omit<IEmployeeService, "id">, Document {}
export class EmployeesServicesAdapterMongoose implements IEmployeesServicesAdapter {
schema: Schema;
employeesServicesList: Model<IEmployeeServiceDocument>;
constructor() {
this.schema = new Schema({
serviceId: { type: Schema.Types.ObjectId, required: true, ref: "Service" },
employeeId: { type: Schema.Types.ObjectId, required: true, ref: "Employee" },
companyId: { type: Schema.Types.ObjectId, required: true, ref: "Companie" },
price: { type: Number, required: false },
creationDate: { type: Date, required: true, default: Date.now },
});
this.employeesServicesList = model<IEmployeeServiceDocument>(
"EmployeeService",
this.schema
);
}
public async create(data: CreateEmployeeServiceParams): Promise<IEmployeeService> {
return await this.employeesServicesList.create(data);
}
public async update(data: UpdateEmployeeServiceParams): Promise<void> {
const updateEmployeeService = await this.employeesServicesList.findOne({ _id: data.id });
if (!updateEmployeeService) {
throw new Error("Employee service not found");
}
if (data.price) {
updateEmployeeService.price = data.price;
}
await updateEmployeeService.save();
}
public async delete(id: string): Promise<void> {
await this.employeesServicesList.deleteOne({ _id: id }).exec();
}
public async find(filters: FindEmployeesServicesParams): Promise<IEmployeeService[]> {
return this.employeesServicesList.find(filters).exec();
}
public async findOne(
filters: FindEmployeesServicesParams
): Promise<IEmployeeServiceDocument | null> {
return this.employeesServicesList.findOne(filters).exec();
}
public async paginate(
filters: PaginateEmployeesServicesParams
): Promise<PaginateEmployeesServicesResults> {
const { page, limit, ...findFilters } = filters; //Extract page and limit from filters
const count = await this.employeesServicesList.countDocuments(findFilters).exec();
const skip = (page - 1) * limit;
const results = await this.employeesServicesList
.find(findFilters)
.skip(skip)
.limit(filters.limit)
.exec();
return {
data: results,
page: filters.page,
pages: Math.ceil(count / filters.limit),
};
}
}
@@ -0,0 +1,119 @@
import { TextObjectFilterResult } from "../../Models/TextObjectFilter.model";
export type FindEmployeesServicesParams = {
_id?: string;
companyId?: string;
employeeId?: string;
serviceId?: string;
};
export type FindEmployeesByServiceParams = {
serviceId?: string;
};
export type PaginateEmployeesServicesParams = FindEmployeesServicesParams & {
page: number;
limit: number;
};
export type PaginateEmployeesServicesResults = {
data: IEmployeeService[];
page: number;
pages: number;
};
export type CreateEmployeeServiceParams = {
companyId: string;
serviceId: string;
employeeId: string;
price?: number;
sessionUser: string;
};
export type UpdateEmployeeServiceParams = CreateEmployeeServiceParams & {
id: string;
};
export type DeleteEmployeeServiceParams = {
companyId: string;
employeeId: string;
serviceId: string;
sessionUser: string;
};
export interface IEmployeeService {
id?: string;
companyId: string;
employeeId: string;
serviceId: string;
price?: number;
}
export type FindCollaboratorServicesParams = {
companyId: string;
employeeId: string;
sessionUser: string;
};
export type UpdateCollaboratorServicesParams = {
companyId: string;
employeeId: string;
services: ServiceStatusItem[];
sessionUser: string;
};
export type DeleteEmployeeServiceByCompanyParams = {
companyId: string;
};
export type DeleteEmployeeServiceByEmployeeParams = {
employeeId: string;
};
export interface CollaboratorServiceItems {
id: string;
name: string;
description: string;
length: number;
price: number;
limit: number;
active: boolean;
}
export interface CollaboratorServiceView {
companyId: string;
employeeId: string;
fullName: string;
avatar: string;
services: CollaboratorServiceItems[];
}
export interface ServiceStatusItem {
serviceId: string;
active: boolean;
}
export interface IEmployeesServicesAdapter {
create(data: CreateEmployeeServiceParams): Promise<IEmployeeService>;
update(data: UpdateEmployeeServiceParams): Promise<void>;
delete(id: string): Promise<void>;
find(filters: FindEmployeesServicesParams): Promise<IEmployeeService[]>;
findOne(filters: FindEmployeesServicesParams): Promise<IEmployeeService | null>;
paginate(filters: PaginateEmployeesServicesParams): Promise<PaginateEmployeesServicesResults>;
}
export interface IEmployeesServicesManager {
employeesServices: IEmployeesServicesAdapter;
createEmployeeService(data: CreateEmployeeServiceParams): Promise<IEmployeeService>;
updateEmployeeService(data: UpdateEmployeeServiceParams): Promise<void>;
updateCollaboratorServices(data: UpdateCollaboratorServicesParams): Promise<void>;
find(data: FindEmployeesServicesParams): Promise<IEmployeeService[]>;
findAllServicesByCollaborator(
data: FindEmployeesServicesParams
): Promise<CollaboratorServiceView>;
delete(data: DeleteEmployeeServiceParams): Promise<void>;
textObjectFilter(data: FindEmployeesServicesParams): Promise<TextObjectFilterResult[]>;
findByService(data: FindEmployeesByServiceParams): Promise<TextObjectFilterResult[]>;
deleteEmployeeServiceByCompany(data: DeleteEmployeeServiceByCompanyParams): Promise<void>;
deleteEmployeeServiceByEmployee(data: DeleteEmployeeServiceByEmployeeParams): Promise<void>;
}
@@ -0,0 +1,434 @@
import { EmployeesServicesAdapterMongoose } from "./EmployeesServices.Adapter.Mongoose";
import {
CreateEmployeeServiceParams,
UpdateEmployeeServiceParams,
DeleteEmployeeServiceParams,
FindEmployeesServicesParams,
IEmployeeService,
IEmployeesServicesManager,
PaginateEmployeesServicesParams,
PaginateEmployeesServicesResults,
CollaboratorServiceView,
FindCollaboratorServicesParams,
CollaboratorServiceItems,
UpdateCollaboratorServicesParams,
FindEmployeesByServiceParams,
DeleteEmployeeServiceByCompanyParams,
DeleteEmployeeServiceByEmployeeParams,
} from "./EmployeesServices.Interface";
import { EmployeeRoles } from "../Employees/Employees.Interface";
import UsersManager from "../Users/Users";
import CompaniesManager from "../Companies/Companies";
import EmployeesList from "../Employees/Employee";
import ServicesManager from "../Services/Service";
import { NoPermissionMessage } from "../../helpers/NoPermissionMessage";
import { isNull } from "../../helpers/IsNull";
import { joinStrings } from "../../helpers/String";
import getAvatar from "../../helpers/getAvatar";
import { TextObjectFilterResult } from "../../Models/TextObjectFilter.model";
import { NotificationsManager } from "../Notifications/Notifications";
import { NotificationType } from "../../Models/SystemNotifications/SystemNotification.Interface";
class EmployeesServicesManager implements IEmployeesServicesManager {
employeesServices: EmployeesServicesAdapterMongoose;
constructor() {
this.employeesServices = new EmployeesServicesAdapterMongoose();
}
public async deleteEmployeeServiceByEmployee(
data: DeleteEmployeeServiceByEmployeeParams
): Promise<void> {
await this.employeesServices.employeesServicesList.deleteMany({
employeeId: data.employeeId,
});
}
public async deleteEmployeeServiceByCompany(
data: DeleteEmployeeServiceByCompanyParams
): Promise<void> {
await this.employeesServices.employeesServicesList.deleteMany({
companyId: data.companyId,
});
}
public async createEmployeeService(
data: CreateEmployeeServiceParams
): Promise<IEmployeeService> {
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 CompaniesManager.companies.findOne({ _id: data.companyId });
if (!companyCheck) {
throw new Error("La compañia no existe");
}
const serviceCheck = await ServicesManager.services.findOne({
_id: data.serviceId,
companyId: data.companyId,
});
if (!serviceCheck) {
throw new Error("El servicio no existe o no pertenece a la compañia.");
}
if (
!(await EmployeesList.checkPermission(
companyCheck,
data.sessionUser,
EmployeeRoles.ADMIN
))
) {
throw new Error(NoPermissionMessage());
}
const employeeCheck = await EmployeesList.employees.findOne({
companyId: data.companyId,
_id: data.employeeId,
});
if (!employeeCheck) {
throw new Error("El empleado no existe o no pertenece a la compañia.");
}
const employeeServiceCheck = await this.employeesServices.findOne({
employeeId: data.employeeId,
serviceId: data.serviceId,
companyId: data.companyId,
});
if (employeeServiceCheck) {
throw new Error("El servicio ya fue asignado para este empleado");
}
const newEmplyeeService = await this.employeesServices.create(data);
await NotificationsManager.sendSystemNotification({
userId: String(employeeCheck.userId),
subject: "Servicio asignado",
message: `Su usuario ha sido asignado para brindar el servicio ${serviceCheck.name} para la organización ${companyCheck.name}.`,
type: NotificationType.EMPLOYEE,
code: String(employeeCheck._id)
});
return newEmplyeeService;
}
public async updateEmployeeService(data: UpdateEmployeeServiceParams): 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 CompaniesManager.companies.findOne({ _id: data.companyId });
if (!companyCheck) {
throw new Error("La compañia no existe");
}
const serviceCheck = await ServicesManager.services.findOne({
_id: data.serviceId,
companyId: data.companyId,
});
if (!serviceCheck) {
throw new Error("El servicio no existe o no pertenece a la compañia.");
}
if (
!(await EmployeesList.checkPermission(
companyCheck,
data.sessionUser,
EmployeeRoles.ADMIN
))
) {
throw new Error(NoPermissionMessage());
}
const employeeCheck = await EmployeesList.employees.findOne({
companyId: data.companyId,
_id: data.employeeId,
});
if (!employeeCheck) {
throw new Error("El empleado no existe o no pertenece a la compañia.");
}
await this.employeesServices.update(data);
}
public async updateCollaboratorServices(data: UpdateCollaboratorServicesParams): 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 CompaniesManager.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());
}
const employeeCheck = await EmployeesList.employees.findOne({
companyId: data.companyId,
_id: data.employeeId,
});
if (!employeeCheck) {
throw new Error("El empleado no existe o no pertenece a la compañia.");
}
for (const service of data.services) {
const serviceCheck = await ServicesManager.services.findOne({
_id: service.serviceId,
companyId: data.companyId,
});
if (!serviceCheck) {
continue;
}
try {
if (!service.active) {
//Aca no envio notificacion porque ya lo hace internamente createEmployeeService
await this.delete({
employeeId: data.employeeId,
serviceId: service.serviceId,
companyId: data.companyId,
sessionUser: data.sessionUser,
});
}
} catch (error) {
continue;
}
try {
if (service.active) {
//Aca no envio notificacion porque ya lo hace internamente createEmployeeService
await this.createEmployeeService({
employeeId: data.employeeId,
serviceId: service.serviceId,
companyId: data.companyId,
sessionUser: data.sessionUser,
});
}
} catch (error) {
continue;
}
}
}
public async paginate(
filters: PaginateEmployeesServicesParams
): Promise<PaginateEmployeesServicesResults> {
return await this.employeesServices.paginate(filters);
}
public async findAllServicesByCollaborator(
filters: FindCollaboratorServicesParams
): Promise<CollaboratorServiceView> {
const employeeCheck = await EmployeesList.employees.findOne({
_id: filters.employeeId,
});
if (!employeeCheck) {
throw new Error("El empleado no existe o no pertenece a la compañia.");
}
const userCheck = await UsersManager.users.findOne({
_id: employeeCheck.userId,
});
if (!userCheck) {
throw new Error("El usuario no existe");
}
const services = await ServicesManager.services.find({ companyId: filters.companyId });
const returnServices: CollaboratorServiceItems[] = [];
for (const service of services) {
const hasService = await this.employeesServices.findOne({
employeeId: filters.employeeId,
serviceId: String(service.id),
companyId: filters.companyId,
});
returnServices.push({
id: isNull<string>(service.id, ""),
name: isNull<string>(service.name, ""),
description: isNull<string>(service.description, ""),
length: isNull<number>(service.length, 0),
price: isNull<number>(service.price, 0),
limit: isNull<number>(service.limit, 1),
active: hasService ? true : false,
});
}
const fullName = joinStrings([userCheck.firstName, userCheck.lastName], " ");
return {
companyId: filters.companyId,
employeeId: filters.employeeId,
services: returnServices,
fullName: fullName,
avatar: getAvatar(userCheck.id, userCheck.avatar, fullName),
};
}
public async find(filters: FindEmployeesServicesParams): Promise<IEmployeeService[]> {
return await this.employeesServices.find(filters);
}
public async delete(data: DeleteEmployeeServiceParams): 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 CompaniesManager.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());
}
const employeeCheck = await EmployeesList.employees.findOne({
companyId: data.companyId,
_id: data.employeeId,
});
if (!employeeCheck) {
throw new Error("El empleado no existe o no pertenece a la compañia.");
}
const serviceCheck = await ServicesManager.services.findOne({
_id: data.serviceId,
companyId: data.companyId,
});
if (!serviceCheck) {
throw new Error("El servicio no existe o no pertenece a la compañia.");
}
const deleteItem = await this.employeesServices.findOne({
companyId: data.companyId,
employeeId: data.employeeId,
serviceId: data.serviceId,
});
if (!deleteItem) {
throw new Error("Ha ocurrido un error al quitar el servicio");
}
await this.employeesServices.delete(String(deleteItem._id));
await NotificationsManager.sendSystemNotification({
userId: String(employeeCheck.userId),
subject: "Servicio quitado",
message: `E servicio ${serviceCheck.name} de la organización ${companyCheck.name} ya no se encuentra asignado a su usuario.`,
type: NotificationType.EMPLOYEE,
code: String(employeeCheck._id)
});
}
public async textObjectFilter(
data: FindEmployeesServicesParams
): Promise<TextObjectFilterResult[]> {
const employeeCheck = await EmployeesList.employees.findOne({
_id: data.employeeId,
});
if (!employeeCheck) {
throw new Error("El empleado no existe o no pertenece a la compañia.");
}
const userCheck = await UsersManager.users.findOne({
_id: employeeCheck.userId,
});
if (!userCheck) {
throw new Error("El usuario no existe");
}
const services = await this.employeesServices.find({
employeeId: data.employeeId,
companyId: data.companyId,
});
const returnServices: TextObjectFilterResult[] = [];
for (const service of services) {
const serviceData = await ServicesManager.services.findOne({
_id: String(service.serviceId),
});
if (!serviceData) {
continue;
}
returnServices.push({
id: isNull<string>(service.serviceId, ""),
name: isNull<string>(serviceData.name, ""),
description: isNull<string>(serviceData.description, ""),
});
}
return returnServices;
}
public async findByService(
data: FindEmployeesByServiceParams
): Promise<TextObjectFilterResult[]> {
const returnData: TextObjectFilterResult[] = [];
const servicesByEmployee = await this.employeesServices.find({
serviceId: data.serviceId,
});
for (const service of servicesByEmployee) {
const employeeData = await EmployeesList.findById({ id: service.employeeId });
returnData.push({
id: isNull<string>(service.employeeId, ""),
name: isNull<string>(employeeData.fullName, ""),
image: isNull<string>(employeeData.avatar, ""),
});
}
return returnData;
}
}
const EmployeesServicesList = new EmployeesServicesManager();
export default EmployeesServicesList;