234 lines
9.1 KiB
TypeScript
234 lines
9.1 KiB
TypeScript
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 },
|
|
showPublicScores: { type: Boolean, required: false, default: true },
|
|
showPublicOpinions: { type: Boolean, required: false, default: true },
|
|
});
|
|
|
|
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;
|
|
if (data.showPublicScores !== undefined) updateService.showPublicScores = data.showPublicScores;
|
|
if (data.showPublicOpinions !== undefined) updateService.showPublicOpinions = data.showPublicOpinions;
|
|
|
|
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),
|
|
};
|
|
}
|
|
}
|