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,110 @@
import { Schema, model, Model, FilterQuery } from "mongoose";
import {
CreateTemplateParams,
DeleteTemplateParams,
FindTemplatesParams,
ITemplate,
ITemplateDocument,
ITemplatesAdapter,
PaginateTemplatesParams,
PaginateTemplatesResults,
TemplateTypes,
UpdateTemplateParams,
} from "./Templates.Interface";
export class TemplatesAdapterMongoose implements ITemplatesAdapter {
schema: Schema;
templatesList: Model<ITemplateDocument>;
constructor() {
this.schema = new Schema({
companyId: {
type: Schema.Types.ObjectId,
required: true,
ref: "Company",
},
name: { type: String, required: true },
code: { type: String, required: true },
type: { type: String, enum: Object.values(TemplateTypes), required: true },
template: { type: String, required: true },
createdAt: { type: Date, default: Date.now, required: true },
});
this.templatesList = model<ITemplateDocument>("Template", this.schema);
}
public async create(data: Omit<CreateTemplateParams, "sessionUser">): Promise<ITemplate> {
return await this.templatesList.create(data);
}
public async update(data: Omit<UpdateTemplateParams, "sessionUser">): Promise<ITemplate> {
await this.templatesList
.updateOne(
{ _id: data.templateId },
{
name: data.name,
code: data.code,
type: data.type,
template: data.template,
}
)
.exec();
const updatedTemplate = await this.templatesList.findById(data.templateId).exec();
if (!updatedTemplate) {
throw new Error("Error al actualizar la plantilla");
}
return updatedTemplate;
}
public async delete(data: Omit<DeleteTemplateParams, "sessionUser">): Promise<void> {
await this.templatesList.deleteOne({ _id: data.id });
}
public async find(filters: Omit<FindTemplatesParams, "sessionUser">): Promise<ITemplate[]> {
const searchCriteria = this.buildSearchCriteria(filters);
return await this.templatesList.find(searchCriteria).exec();
}
public async findOne(
filters: Omit<FindTemplatesParams, "sessionUser">
): Promise<ITemplateDocument | null> {
const searchCriteria = this.buildSearchCriteria(filters);
return await this.templatesList.findOne(searchCriteria).exec();
}
private buildSearchCriteria(
filters: Omit<FindTemplatesParams, "sessionUser">
): FilterQuery<ITemplate> {
const searchCriteria: FilterQuery<ITemplate> = {};
if (filters.id) searchCriteria._id = filters.id;
if (filters.companyId) searchCriteria.companyId = filters.companyId;
if (filters.name) searchCriteria.name = { $regex: filters.name, $options: "i" };
if (filters.code) searchCriteria.code = { $regex: filters.code, $options: "i" };
if (filters.type) searchCriteria.type = filters.type;
return searchCriteria;
}
public async paginate(filters: PaginateTemplatesParams): Promise<PaginateTemplatesResults> {
const searchCriteria = this.buildSearchCriteria(filters);
const count = await this.templatesList.countDocuments(searchCriteria).exec();
const skip = (filters.page - 1) * filters.limit;
const results = await this.templatesList
.find(searchCriteria)
.skip(skip)
.limit(filters.limit)
.sort({ createdAt: -1 })
.exec();
let pages = Math.ceil(count / filters.limit);
if (pages == 0) {
pages = 1;
}
return { data: results, page: filters.page, pages: pages };
}
}
@@ -0,0 +1,110 @@
import { Document } from "mongoose";
import { TextObjectFilterResult } from "../TextObjectFilter.model";
export enum TemplateTypes {
WAP_NEW_APPOINTMENT = "wap-new-appointment",
WAP_REMINDER = "wap-reminder",
EMAIL_NEW_APPOINTMENT = "email-new-appointment",
EMAIL_REMINDER = "email-reminder",
}
export interface ITemplate {
id?: string;
_id?: string;
companyId: string;
name: string;
code: string;
type: TemplateTypes;
template: string;
createdAt: Date;
}
export interface ITemplateDocument extends Omit<ITemplate, "id" | "_id">, Document {
_id: string;
}
export interface ITemplatesAdapter {
create(data: Omit<CreateTemplateParams, "sessionUser">): Promise<ITemplate>;
update(data: Omit<UpdateTemplateParams, "sessionUser">): Promise<ITemplate>;
delete(data: Omit<DeleteTemplateParams, "sessionUser">): Promise<void>;
find(filters: Omit<FindTemplatesParams, "sessionUser">): Promise<ITemplate[]>;
findOne(filters: Omit<FindTemplatesParams, "sessionUser">): Promise<ITemplateDocument | null>;
paginate(filters: PaginateTemplatesParams): Promise<PaginateTemplatesResults>;
}
export type FindTemplatesParams = {
id?: string;
companyId: string;
code?: string;
name?: string;
type?: TemplateTypes;
sessionUser: string;
};
export type PaginateTemplatesParams = FindTemplatesParams & {
page: number;
limit: number;
};
export type PaginateTemplatesResults = {
data: ITemplate[];
page: number;
pages: number;
};
export type CreateTemplateParams = {
companyId: string;
name: string;
code: string;
type: TemplateTypes;
template: string;
sessionUser: string;
};
export type UpdateTemplateParams = {
templateId: string;
companyId: string;
name: string;
code: string;
type: TemplateTypes;
template: string;
sessionUser: string;
};
export type SaveTemplateParams = {
templateId?: string;
companyId: string;
name: string;
code: string;
type: TemplateTypes;
template: string;
sessionUser: string;
};
export type DeleteTemplateParams = {
id: string;
companyId: string;
sessionUser: string;
};
export type GetDefaultTemplateParams = {
type: TemplateTypes;
companyId: string;
sessionUser: string;
};
export type DeleteTemplatesByCompanyParams = {
companyId: string;
};
export interface ITemplatesManager {
templates: ITemplatesAdapter;
deleteTemplatesByCompany(data: DeleteTemplatesByCompanyParams): Promise<void>;
createTemplate(data: CreateTemplateParams): Promise<ITemplate>;
updateTemplate(data: UpdateTemplateParams): Promise<ITemplate>;
saveTemplate(data: SaveTemplateParams): Promise<ITemplate>;
deleteTemplate(data: DeleteTemplateParams): Promise<void>;
paginate(data: PaginateTemplatesParams): Promise<PaginateTemplatesResults>;
getTemplate(data: FindTemplatesParams): Promise<ITemplate>;
textObjectFilter(data: FindTemplatesParams): Promise<TextObjectFilterResult[]>;
getDefaultTemplate(data: GetDefaultTemplateParams): Promise<string>;
}
+229
View File
@@ -0,0 +1,229 @@
import { isNull } from "../../helpers/IsNull";
import { validatePermissionsByCompany, validateSessionUser } from "../../helpers/check";
import { TextObjectFilterResult } from "../TextObjectFilter.model";
import { TemplatesAdapterMongoose } from "./Templates.Adapter.Mongoose";
import {
CreateTemplateParams,
DeleteTemplateParams,
DeleteTemplatesByCompanyParams,
FindTemplatesParams,
GetDefaultTemplateParams,
ITemplate,
ITemplatesManager,
PaginateTemplatesParams,
PaginateTemplatesResults,
SaveTemplateParams,
TemplateTypes,
UpdateTemplateParams,
} from "./Templates.Interface";
export class TemplatesManager implements ITemplatesManager {
templates: TemplatesAdapterMongoose;
constructor() {
this.templates = new TemplatesAdapterMongoose();
}
public async deleteTemplatesByCompany(data: DeleteTemplatesByCompanyParams): Promise<void> {
if (!data.companyId) {
return;
}
await this.templates.templatesList.deleteMany({
companyId: data.companyId,
});
}
public async createTemplate(data: CreateTemplateParams): Promise<ITemplate> {
await validateSessionUser({
sessionUser: data.sessionUser,
});
await validatePermissionsByCompany({
companyId: data.companyId,
sessionUser: data.sessionUser,
});
const checkTemplate = await this.templates.findOne({
companyId: data.companyId,
code: data.code,
});
if (checkTemplate) {
throw new Error("Ya existe una plantilla con el mismo código");
}
// La lógica de negocio se implementará aquí
const template = this.templates.create(data);
if (!template) {
throw new Error("Error al crear la plantilla");
}
return template;
}
public async updateTemplate(data: UpdateTemplateParams): Promise<ITemplate> {
await validateSessionUser({
sessionUser: data.sessionUser,
});
await validatePermissionsByCompany({
companyId: data.companyId,
sessionUser: data.sessionUser,
});
const checkTemplate = await this.templates.findOne({
companyId: data.companyId,
id: data.templateId,
});
if (!checkTemplate) {
throw new Error("La plantilla que intenta actualizar no existe");
}
const updatedTemplate = await this.templates.update(data);
if (!updatedTemplate) {
throw new Error("Error al actualizar la plantilla");
}
return updatedTemplate;
}
public async saveTemplate(data: SaveTemplateParams): Promise<ITemplate> {
if (data.templateId) {
return this.updateTemplate({
templateId: data.templateId,
companyId: data.companyId,
name: data.name,
code: data.code,
type: data.type,
template: data.template,
sessionUser: data.sessionUser,
});
} else {
return this.createTemplate({
companyId: data.companyId,
name: data.name,
code: data.code,
type: data.type,
template: data.template,
sessionUser: data.sessionUser,
});
}
}
public async deleteTemplate(data: DeleteTemplateParams): Promise<void> {
await validateSessionUser({
sessionUser: data.sessionUser,
});
const template = await this.templates.findOne({ id: data.id, companyId: data.companyId });
if (!template) {
throw new Error("La plantilla que intenta eliminar no existe");
}
const validation = await validatePermissionsByCompany({
companyId: String(template.companyId),
sessionUser: data.sessionUser,
});
//Desvincular de la organizacion.
const companyCheck = validation.company;
if (!companyCheck) {
throw new Error(
"No se puede determinar la organización a la que pertenece la plantilla"
);
}
if (String(companyCheck.templateEmailAltaId) === String(data.id)) {
companyCheck.templateEmailAltaId = undefined;
}
if (String(companyCheck.templateEmailNotifId) === String(data.id)) {
companyCheck.templateEmailNotifId = undefined;
}
if (String(companyCheck.templateWapAltaId) === String(data.id)) {
companyCheck.templateWapAltaId = undefined;
}
if (String(companyCheck.templateWapNotifId) === String(data.id)) {
companyCheck.templateWapNotifId = undefined;
}
await this.templates.delete(data);
}
public async paginate(data: PaginateTemplatesParams): Promise<PaginateTemplatesResults> {
return this.templates.paginate(data);
}
public async getTemplate(data: FindTemplatesParams): Promise<ITemplate> {
await validateSessionUser({
sessionUser: data.sessionUser,
});
await validatePermissionsByCompany({
companyId: data.companyId,
sessionUser: data.sessionUser,
});
const checkTemplate = await this.templates.findOne({
companyId: data.companyId,
id: data.id,
});
if (!checkTemplate) {
throw new Error("La plantilla que intenta obtener no existe");
}
return checkTemplate;
}
public async textObjectFilter(data: FindTemplatesParams): Promise<TextObjectFilterResult[]> {
const templates = await this.templates.find(data);
const formattedResult: TextObjectFilterResult[] = [];
for (const item of templates) {
formattedResult.push({
id: isNull<string>(item.id, ""),
name: item.name,
image: "",
});
}
return formattedResult;
}
public async getDefaultTemplate(data: GetDefaultTemplateParams): Promise<string> {
let defaultTemplate = "";
await validateSessionUser({
sessionUser: data.sessionUser,
});
await validatePermissionsByCompany({
companyId: data.companyId,
sessionUser: data.sessionUser,
});
switch (data.type) {
case TemplateTypes.WAP_REMINDER:
defaultTemplate = `${process.env.WAP_REMINDER}`;
break;
case TemplateTypes.WAP_NEW_APPOINTMENT:
defaultTemplate = `${process.env.WAP_ALTA}`;
break;
case TemplateTypes.EMAIL_REMINDER:
defaultTemplate = `${process.env.WAP_REMINDER}`;
break;
case TemplateTypes.EMAIL_NEW_APPOINTMENT:
defaultTemplate = `${process.env.WAP_ALTA}`;
break;
}
return defaultTemplate;
}
}
export default new TemplatesManager();