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,350 @@
import ServiceList from "../Services/Service";
import {
FindCompaniesParams,
UpdateCompanyParams,
ICompaniesAdapter,
ICompany,
PaginateCompaniesParams,
PaginateCompaniesResults,
SysAdminPaginateCompaniesParams,
} from "./Companies.Interface";
import mongoose, { Document, Model, Schema, model } from "mongoose";
export interface ICompanyDocument extends Omit<ICompany, "id">, Document {}
export class CompaniesAdapterMongoose implements ICompaniesAdapter {
schema: Schema;
companyList: Model<ICompanyDocument>;
constructor() {
this.schema = new Schema({
name: { type: String, required: true, unique: true },
slug: { type: String, required: true, unique: true },
description: { type: String, required: true, default: "" },
categoryId: { type: Number, required: false, default: 50000 },
street: { type: String, required: false },
streetNumber: { type: String, required: false },
builingFloor: { type: String, required: false },
buildingApartament: { type: String, required: false },
block: { type: String, required: false },
city: { type: String, required: false },
state: { type: String, required: false },
country: { type: String, required: false },
zipCode: { type: String, required: false },
latitude: { type: Number, required: false, default: 0 },
longitude: { type: Number, required: false, default: 0 },
phoneCountryCode: { type: String, required: false },
phoneAreaCode: { type: String, required: false },
phoneNumber: { type: String, required: false },
heatMapFraction: { type: Number, required: false },
headerFile: { type: String, required: false },
headerColor: { type: String, required: false },
headerFontColor: { type: String, required: false },
headerFontShadowColor: { type: String, required: false },
iconFile: { type: String, required: false },
logoFile: { type: String, required: false },
wapServerId: { type: Schema.Types.ObjectId, required: false, ref: "WapServer" },
ownerId: { type: Schema.Types.ObjectId, required: true, ref: "User" },
creationDate: { type: Date, required: true, default: Date.now },
published: { type: String, required: false },
automaticNotifications: { type: Boolean, required: false },
appointmentTime: { type: Number, required: false },
cancellationTime: { type: Number, required: false },
appointmentAlert: { type: String, required: false },
templateWapNotifId: { type: Schema.Types.ObjectId, required: false, ref: "Template" },
templateWapAltaId: { type: Schema.Types.ObjectId, required: false, ref: "Template" },
templateEmailNotifId: { type: Schema.Types.ObjectId, required: false, ref: "Template" },
templateEmailAltaId: { type: Schema.Types.ObjectId, required: false, ref: "Template" },
onboardingStep: { type: Number, required: false, default: 0 },
onboardingCompleted: { type: Boolean, required: false, default: false },
fixedPostIds: { type: Array, required: false },
banned: { type: Boolean, required: false, default: false },
});
this.companyList = model<ICompanyDocument>("Company", this.schema);
}
public async create(company: ICompany): Promise<ICompany> {
const newCompany = await this.companyList.create({
...company,
onboardingStep: company.onboardingStep || 0
});
return newCompany;
}
public async update(data: UpdateCompanyParams): Promise<void> {
const updateCompany = await this.companyList.findOne({ _id: data.id });
if (!updateCompany) {
throw new Error("Company not found");
}
if (data.name) {
updateCompany.name = data.name;
}
if (data.description) {
updateCompany.description = data.description;
}
if (data.categoryId) {
updateCompany.categoryId = data.categoryId;
}
if (data.headerFile) {
updateCompany.headerFile = data.headerFile;
}
if (data.iconFile) {
updateCompany.iconFile = data.iconFile;
}
if (data.logoFile) {
updateCompany.logoFile = data.logoFile;
}
if (data.headerColor) {
updateCompany.headerColor = data.headerColor;
}
if (data.headerFontColor) {
updateCompany.headerFontColor = data.headerFontColor;
}
if (data.headerFontShadowColor) {
updateCompany.headerFontShadowColor = data.headerFontShadowColor;
}
if (data.street) {
updateCompany.street = data.street;
}
if (data.streetNumber) {
updateCompany.streetNumber = data.streetNumber;
}
if (data.builingFloor) {
updateCompany.builingFloor = data.builingFloor;
}
if (data.buildingApartament) {
updateCompany.buildingApartament = data.buildingApartament;
}
if (data.block) {
updateCompany.block = data.block;
}
if (data.city) {
updateCompany.city = data.city;
}
if (data.state) {
updateCompany.state = data.state;
}
if (data.country) {
updateCompany.country = data.country;
}
if (data.zipCode) {
updateCompany.zipCode = data.zipCode;
}
if (data.latitude) {
updateCompany.latitude = data.latitude;
}
if (data.longitude) {
updateCompany.longitude = data.longitude;
}
if (data.phoneCountryCode) {
updateCompany.phoneCountryCode = data.phoneCountryCode;
}
if (data.phoneAreaCode) {
updateCompany.phoneAreaCode = data.phoneAreaCode;
}
if (data.phoneNumber) {
updateCompany.phoneNumber = data.phoneNumber;
}
if (data.heatMapFraction) {
updateCompany.heatMapFraction = data.heatMapFraction;
}
if (data.appointmentTime) {
updateCompany.appointmentTime = data.appointmentTime;
}
if (data.cancellationTime) {
updateCompany.cancellationTime = data.cancellationTime;
}
if (data.wapServerId) {
updateCompany.wapServerId = data.wapServerId;
}
if (data.appointmentAlert) {
updateCompany.appointmentAlert = data.appointmentAlert;
}
if (data.templateWapNotifId) {
updateCompany.templateWapNotifId = data.templateWapNotifId;
}
if (data.templateWapAltaId) {
updateCompany.templateWapAltaId = data.templateWapAltaId;
}
if (data.templateEmailNotifId) {
updateCompany.templateEmailNotifId = data.templateEmailNotifId;
}
if (data.templateEmailAltaId) {
updateCompany.templateEmailAltaId = data.templateEmailAltaId;
}
if (data.onboardingStep !== undefined) {
updateCompany.onboardingStep = data.onboardingStep;
}
if (data.onboardingCompleted !== undefined) {
updateCompany.onboardingCompleted = data.onboardingCompleted;
}
if (data.banned !== undefined) {
updateCompany.banned = data.banned;
}
updateCompany.save();
//actualizo los campos correspondientes a la localizacion de los servicios de la organizacion.
try {
const servicesUpdate = await ServiceList.services.find({ companyId: updateCompany.id });
for (const service of servicesUpdate) {
if (!service.id) {
continue;
}
await ServiceList.updateService({
id: service.id,
companyId: updateCompany.id,
latitude: updateCompany.latitude,
longitude: updateCompany.longitude,
block: updateCompany.block,
city: updateCompany.city,
state: updateCompany.state,
country: updateCompany.country,
zipCode: updateCompany.zipCode,
sessionUser: data.sessionUser,
});
}
} catch (error) {
console.log(
"Ha ocurrido un error al actualizar la localizacion de los servicios de la organizacion."
);
}
}
public async delete(id: string): Promise<void> {
await this.companyList.deleteOne({ _id: id }).exec();
}
public async find(filters: FindCompaniesParams): Promise<ICompany[]> {
return await this.companyList.find(filters).exec();
}
public async findOne(filters: FindCompaniesParams): Promise<ICompanyDocument | null> {
return await this.companyList.findOne(filters).exec();
}
public async paginate(filters: PaginateCompaniesParams): Promise<PaginateCompaniesResults> {
const { page, limit, ...findFilters } = filters; //Extract page and limit from filters
const count = await this.companyList.countDocuments(findFilters).exec();
const skip = (page - 1) * limit;
const results = await this.companyList
.find(findFilters)
.skip(skip)
.limit(filters.limit)
.exec();
return {
data: results,
page: filters.page,
pages: Math.ceil(count / filters.limit),
};
}
public async sysAdminPaginate(filters: SysAdminPaginateCompaniesParams): Promise<PaginateCompaniesResults> {
const { page, limit, sortBy, sortOrder, name, banned } = filters as any;
const query: any = {};
if (name) {
query.name = { $regex: name, $options: "i" };
}
if (banned !== undefined) {
query.banned = banned;
}
const count = await this.companyList.countDocuments(query).exec();
const skip = (page - 1) * limit;
const sortObj: any = {};
if (sortBy) {
sortObj[sortBy] = sortOrder === "desc" ? -1 : 1;
}
const results = await this.companyList
.find(query)
.sort(sortObj)
.skip(skip)
.limit(limit)
.exec();
return {
data: results,
page: page,
pages: Math.ceil(count / limit),
};
}
public async paginateFilterAll(
data: PaginateCompaniesParams
): Promise<PaginateCompaniesResults> {
const skip = (data.page - 1) * data.limit;
const searchCriteria: mongoose.FilterQuery<ICompany> = {};
if (data.name) {
const words = data.name.split(" ").map((word) => new RegExp(word, "i"));
searchCriteria.$and = words.map((word) => ({
$or: [{ name: word }, { description: word }],
}));
}
// Realiza la consulta con paginación
const results = await this.companyList
.find(searchCriteria)
.sort({ price: 1 }) // Ordena por precio ascendente
.skip(skip)
.limit(data.limit)
.exec();
// Cuenta el total de documentos que coinciden con los criterios de búsqueda
const count = await this.companyList.countDocuments(searchCriteria).exec();
return {
data: results,
page: data.page,
pages: Math.ceil(count / data.limit),
};
}
}
@@ -0,0 +1,298 @@
import { TextObjectFilterResult } from "../TextObjectFilter.model";
import { ICompanyDocument } from "./Companies.Adapter.Mongoose";
export enum COMPANY_PUBLISHED_STATUS {
PUBLISHED = "published",
PRIVATE = "private",
}
export type CreateCompanyParams = {
name: string;
description: string;
categoryId: number;
ownerId: string;
onboardingStep?: number;
};
export type UpdateCompanyParams = {
id: string;
name?: string;
description?: string;
categoryId?: number;
headerFile?: string;
iconFile?: string;
logoFile?: string;
headerColor?: string;
headerFontColor?: string;
headerFontShadowColor?: string;
street?: string;
streetNumber?: string;
builingFloor?: string;
buildingApartament?: string;
block?: string;
city?: string;
state?: string;
country?: string;
zipCode?: string;
latitude?: number;
longitude?: number;
phoneCountryCode?: string;
phoneAreaCode?: string;
phoneNumber?: string;
heatMapFraction?: number;
appointmentTime?: number;
cancellationTime?: number;
wapServerId?: string;
appointmentAlert?: string;
sessionUser: string;
templateWapNotifId?: string;
templateWapAltaId?: string;
templateEmailNotifId?: string;
templateEmailAltaId?: string;
onboardingStep?: number;
onboardingCompleted?: boolean;
banned?: boolean;
};
export type SetCompanyFileParams = {
companyId: string;
sessionUser: string;
file: Express.Multer.File;
};
export type DeleteCompanyFileParams = {
companyId: string;
sessionUser: string;
};
export type DeleteCompanyParams = {
companyId: string;
sessionUser: string;
};
export type FindCompaniesParams = {
_id?: string;
name?: string;
slug?: string;
categoryId?: number;
street?: string;
streetNumber?: string;
builingFloor?: string;
buildingApartament?: string;
block?: string;
city?: string;
state?: string;
country?: string;
zipCode?: string;
latitude?: number;
longitude?: number;
phoneCountryCode?: string;
phoneAreaCode?: string;
phoneNumber?: string;
heatMapFraction?: number;
appointmentTime?: number;
cancellationTime?: number;
ownerId?: string;
wapServerId?: string;
};
export type SetOrganizationPublishedStatusParams = {
companyId: string;
published: COMPANY_PUBLISHED_STATUS;
sessionUser: string;
};
export type SetNotificationAutoParams = {
companyId: string;
status?: boolean;
sessionUser: string;
};
export interface ICompany {
id?: string;
name: string;
slug: string;
description: string;
categoryId: number;
ownerId: string;
headerFile?: string;
iconFile?: string;
logoFile?: string;
headerColor?: string;
headerFontColor?: string;
headerFontShadowColor?: string;
street?: string;
streetNumber?: string;
builingFloor?: string;
buildingApartament?: string;
block?: string;
city?: string;
state?: string;
country?: string;
zipCode?: string;
latitude?: number;
longitude?: number;
phoneCountryCode?: string;
phoneAreaCode?: string;
phoneNumber?: string;
heatMapFraction?: number;
appointmentTime?: number;
cancellationTime?: number;
wapServerId?: string;
appointmentAlert?: string;
published?: COMPANY_PUBLISHED_STATUS;
automaticNotifications?: boolean;
templateWapNotifId?: string;
templateWapAltaId?: string;
templateEmailNotifId?: string;
templateEmailAltaId?: string;
onboardingStep?: number;
onboardingCompleted?: boolean;
fixedPostIds?: Array<string>;
banned?: boolean;
}
export interface MyOranizationsView {
id: string;
name: string;
slug: string;
description: string;
categoryId: number;
ownerId: string;
employeeId: string;
isOwner: boolean;
isAdmin: boolean;
hostOk: boolean;
guestOk: boolean;
fullOk: boolean;
headerFile?: string;
headerColor?: string;
headerFontColor?: string;
headerFontShadowColor?: string;
iconFile?: string;
logoFile?: string;
phoneAreaCode?: string;
phoneNumber?: string;
heatMapFraction?: number;
appointmentTime?: number;
cancellationTime?: number;
block?: string;
street?: string;
streetNumber?: string;
builingFloor?: string;
buildingApartament?: string;
city?: string;
state?: string;
country?: string;
zipCode?: string;
latitude?: number;
longitude?: number;
published?: COMPANY_PUBLISHED_STATUS;
automaticNotifications?: boolean;
appointmentAlert?: string;
templateWapNotifId?: string;
templateWapAltaId?: string;
templateEmailNotifId?: string;
templateEmailAltaId?: string;
onboardingStep?: number;
onboardingCompleted?: boolean;
banned?: boolean;
}
export interface ClientOrganizationView {
id: string;
name: string;
description: string;
slug: string;
iconFile: string;
logoFile: string;
}
export interface MyOranizationsViewParams {
sessionUser: string;
}
export interface ClientOranizationsViewParams {
clientId: string;
sessionUser: string;
}
export interface OranizationsViewByIdParams {
id: string;
sessionUser: string;
}
export type PaginateCompaniesParams = FindCompaniesParams & {
page: number;
limit: number;
};
export type PaginateCompaniesResults = {
data: ICompany[];
page: number;
pages: number;
};
export type SysAdminPaginateCompaniesParams = PaginateCompaniesParams & {
banned?: boolean;
};
export type SysAdminUpdateCompanyParams = {
id: string;
name?: string;
description?: string;
categoryId?: number;
};
export type SysAdminSetCompanyBannedParams = {
id: string;
banned: boolean;
};
export type FixCompanyPostParams = {
companyId: string;
postId: string;
sessionUser: string;
};
export type MoveCompanyFixedPostParams = {
companyId: string;
postId: string;
moveLength: number;
sessionUser: string;
};
export interface ICompaniesAdapter {
create(company: ICompany): Promise<ICompany>;
delete(id: string): Promise<void>;
find(filters: FindCompaniesParams): Promise<ICompany[]>;
findOne(filters: FindCompaniesParams): Promise<ICompanyDocument | null>;
paginate(filters: PaginateCompaniesParams): Promise<PaginateCompaniesResults>;
sysAdminPaginate(data: SysAdminPaginateCompaniesParams): Promise<PaginateCompaniesResults>;
paginateFilterAll(data: PaginateCompaniesParams): Promise<PaginateCompaniesResults>;
update(data: UpdateCompanyParams): Promise<void>;
}
export interface ICompaniesManager {
companies: ICompaniesAdapter;
createCompany(data: CreateCompanyParams): Promise<ICompany>;
isValidName(data: FindCompaniesParams): Promise<boolean>;
updateCompany(data: UpdateCompanyParams): Promise<void>;
setCompanyHeader(data: SetCompanyFileParams): Promise<void>;
setCompanyIcon(data: SetCompanyFileParams): Promise<void>;
deleteCompanyHeader(data: DeleteCompanyFileParams): Promise<void>;
deleteCompanyIcon(data: DeleteCompanyFileParams): Promise<void>;
getByUserId(data: MyOranizationsViewParams): Promise<MyOranizationsView[]>;
getByClientId(data: ClientOranizationsViewParams): Promise<ClientOrganizationView[]>;
getById(data: OranizationsViewByIdParams): Promise<MyOranizationsView>;
filterAll(data: PaginateCompaniesParams): Promise<TextObjectFilterResult[]>;
getCompanyAddress(data: ICompany): string;
deleteCompany(data: DeleteCompanyParams): Promise<void>;
setPublishedStatus(data: SetOrganizationPublishedStatusParams): Promise<void>;
setNotificationAuto(data: SetNotificationAutoParams): Promise<void>;
toggleFixedPost(data: FixCompanyPostParams): Promise<void>;
moveFixedPost(data: MoveCompanyFixedPostParams): Promise<void>;
sysAdminPaginate(data: SysAdminPaginateCompaniesParams): Promise<PaginateCompaniesResults>;
sysAdminUpdate(data: SysAdminUpdateCompanyParams): Promise<void>;
sysAdminSetBanned(data: SysAdminSetCompanyBannedParams): Promise<void>;
}
File diff suppressed because it is too large Load Diff