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,229 @@
import Discounts from "../Discounts/Discounts";
import {
FindServicesParams,
IServicesAdapter,
IService,
CreateServiceParams,
UpdateServiceParams,
PaginateServicesParams,
PaginateServicesResults,
SERVICE_PUBLISHED_STATUS,
SysAdminPaginateServicesParams,
} from "./Service.Interface";
import mongoose, { Document, Model, Schema, model } from "mongoose";
export interface IServiceDocument extends Omit<IService, "id">, Document {}
export class ServicesAdapterMongoose implements IServicesAdapter {
schema: Schema;
serviceList: Model<IServiceDocument>;
constructor() {
this.schema = new Schema({
companyId: { type: Schema.Types.ObjectId, required: true, ref: "Companie" },
discountId: { type: Schema.Types.ObjectId, required: false, ref: "Discount" },
categoryId: { type: Number, required: false },
name: { type: String, required: true },
description: { type: String, required: true },
price: { type: Number, required: true, default: 0 },
originalPrice: { type: Number, required: false, default: 0 },
length: { type: Number, required: true, default: 0 },
limit: { type: Number, required: true, default: 0 },
image: { type: String, required: false },
color: { type: String, required: false },
fontColor: { type: String, required: false },
fontShadowColor: { 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 },
published: { type: String, required: false },
banned: { type: Boolean, required: false, default: false },
});
this.serviceList = model<IServiceDocument>("Service", this.schema);
}
public async create(data: CreateServiceParams): Promise<IService> {
return await this.serviceList.create(data);
}
public async update(data: UpdateServiceParams): Promise<void> {
const updateService = await this.serviceList.findOne({ _id: data.id });
if (!updateService) {
throw new Error("Service not found");
}
if (data.categoryId) updateService.categoryId = data.categoryId;
if (data.name) updateService.name = data.name;
if (data.description) updateService.description = data.description;
if (data.originalPrice) {
updateService.originalPrice = data.originalPrice;
//Si tiene un descuento aplicado tenemos que actualizar el precio
//aplicando el descuento al precio original
if (updateService.discountId) {
const discount = await Discounts.discounts.discountsList.findOne({
_id: String(updateService.discountId),
companyId: data.companyId,
});
if (discount) {
updateService.price =
updateService.originalPrice - updateService.originalPrice * (discount.value / 100);
}
} else {
updateService.price = updateService.originalPrice;
}
}
if (data.length) updateService.length = data.length;
if (data.limit) updateService.limit = data.limit;
if (data.image) updateService.image = data.image;
if (data.color) updateService.color = data.color;
if (data.fontColor) updateService.fontColor = data.fontColor;
if (data.fontShadowColor) updateService.fontShadowColor = data.fontShadowColor;
if (data.block) updateService.block = data.block;
if (data.city) updateService.city = data.city;
if (data.state) updateService.state = data.state;
if (data.country) updateService.country = data.country;
if (data.zipCode) updateService.zipCode = data.zipCode;
if (data.latitude) updateService.latitude = data.latitude;
if (data.longitude) updateService.longitude = data.longitude;
if (data.banned !== undefined) updateService.banned = data.banned;
await updateService.save();
}
public async delete(id: string): Promise<void> {
await this.serviceList.findByIdAndDelete(id).exec();
}
public async find(filters: FindServicesParams): Promise<IService[]> {
return this.serviceList.find(filters).exec();
}
public async findOne(filters: FindServicesParams): Promise<IServiceDocument | null> {
return this.serviceList.findOne(filters).exec();
}
public async paginate(filters: PaginateServicesParams): Promise<PaginateServicesResults> {
const { page, limit, ...findFilters } = filters;
const count = await this.serviceList.countDocuments(findFilters).exec();
const skip = (page - 1) * limit;
const results = await this.serviceList.find(findFilters).skip(skip).limit(limit).exec();
return {
data: results,
page,
pages: Math.ceil(count / limit),
};
}
// Método para búsqueda con expresiones regulares y paginación
public async paginateFiltered(data: PaginateServicesParams): Promise<PaginateServicesResults> {
const skip = (data.page - 1) * data.limit;
// Construye los criterios de búsqueda
const searchCriteria: mongoose.FilterQuery<IService> = {};
// Agrega filtro por query usando expresiones regulares para 'name' y 'description'
if (data.query) {
const regex = new RegExp(data.query, "i");
searchCriteria.$or = [{ name: regex }, { description: regex }];
}
// Filtra por categoryId si está presente
if (data.categoryId !== undefined) {
searchCriteria.categoryId = data.categoryId;
}
if (data.companyId !== undefined) {
searchCriteria.companyId = data.companyId;
}
if (data.serviceId !== undefined) {
searchCriteria._id = data.serviceId;
}
// Filtra por rango de precios
if (data.priceFrom !== undefined || data.priceTo !== undefined) {
searchCriteria.price = {};
if (data.priceFrom !== undefined) searchCriteria.price.$gte = data.priceFrom;
if (data.priceTo !== undefined) searchCriteria.price.$lte = data.priceTo;
}
// Filtra por rango de longitud
if (data.lengthFrom !== undefined || data.lengthTo !== undefined) {
searchCriteria.length = {};
if (data.lengthFrom !== undefined) searchCriteria.length.$gte = data.lengthFrom;
if (data.lengthTo !== undefined) searchCriteria.length.$lte = data.lengthTo;
}
// Filtra por block si está presente
if (data.block) {
searchCriteria.block = data.block;
}
// Filtra por city si está presente
if (data.city) {
searchCriteria.city = data.city;
}
// Filtra por state si está presente
if (data.state) {
searchCriteria.state = data.state;
}
if (data.published !== undefined) {
searchCriteria.published = data.published;
if (data.published === SERVICE_PUBLISHED_STATUS.PUBLISHED) {
searchCriteria.banned = { $ne: true };
}
}
// Realiza la consulta con paginación
const results = await this.serviceList
.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.serviceList.countDocuments(searchCriteria).exec();
return {
data: results,
page: data.page,
pages: Math.ceil(count / data.limit),
};
}
public async sysAdminPaginate(data: SysAdminPaginateServicesParams): Promise<PaginateServicesResults> {
const { page, limit, companyId } = data;
const query: any = {};
if (companyId) {
query.companyId = companyId;
}
const count = await this.serviceList.countDocuments(query).exec();
const skip = (page - 1) * limit;
const results = await this.serviceList
.find(query)
.sort({ name: 1 })
.skip(skip)
.limit(limit)
.exec();
return {
data: results,
page: page,
pages: Math.ceil(count / limit),
};
}
}