|
|
|
@ -18,20 +18,15 @@ export class ProductsService { |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
if (existingProduct) { |
|
|
|
|
throw new HttpException( |
|
|
|
|
'Product with this name already exists.', |
|
|
|
|
HttpStatus.BAD_REQUEST, |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
existingProduct.quantity += createProductDto.quantity || 0; |
|
|
|
|
await existingProduct.save(); |
|
|
|
|
|
|
|
|
|
const product = await this.productModel.create(createProductDto); |
|
|
|
|
return product; |
|
|
|
|
return existingProduct; |
|
|
|
|
} |
|
|
|
|
const newProduct = await this.productModel.create(createProductDto); |
|
|
|
|
return newProduct; |
|
|
|
|
} catch (error) { |
|
|
|
|
console.error(error); |
|
|
|
|
throw new HttpException( |
|
|
|
|
'An error occurred while creating the product.', |
|
|
|
|
HttpStatus.INTERNAL_SERVER_ERROR, |
|
|
|
|
); |
|
|
|
|
throw new HttpException("An error occurred while creating or updating the product.", HttpStatus.INTERNAL_SERVER_ERROR); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -41,19 +36,16 @@ export class ProductsService { |
|
|
|
|
const product = await this.productModel.findByPk(id); |
|
|
|
|
|
|
|
|
|
if (!product) { |
|
|
|
|
throw new HttpException( |
|
|
|
|
'Product not found with the given id.', |
|
|
|
|
HttpStatus.NOT_FOUND, |
|
|
|
|
); |
|
|
|
|
throw new HttpException("Product not found with the given ID.", HttpStatus.NOT_FOUND); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return product; |
|
|
|
|
} catch (error) { |
|
|
|
|
console.error(error); |
|
|
|
|
throw new HttpException( |
|
|
|
|
error.response, |
|
|
|
|
HttpStatus.INTERNAL_SERVER_ERROR, |
|
|
|
|
); |
|
|
|
|
if (error instanceof HttpException) { |
|
|
|
|
throw error; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
throw new HttpException("An unexpected error occurred while fetching the product.", HttpStatus.INTERNAL_SERVER_ERROR); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -62,55 +54,105 @@ export class ProductsService { |
|
|
|
|
search?: string, |
|
|
|
|
priceMin?: number, |
|
|
|
|
priceMax?: number, |
|
|
|
|
): Promise<Product[]> { |
|
|
|
|
page: number = 1, |
|
|
|
|
limit: number = 10, |
|
|
|
|
): Promise<{ products: Product[]; total: number; totalPages: number; currentPage: number }> { |
|
|
|
|
try { |
|
|
|
|
// ساخت شرطهای جستجو و فیلتر
|
|
|
|
|
const where: any = {}; |
|
|
|
|
const where: Record<string, any> = {}; |
|
|
|
|
|
|
|
|
|
if (search) { |
|
|
|
|
where.name = { [Op.like]: `%${search}%` }; // جستجوی نام محصول به صورت جزئی
|
|
|
|
|
} |
|
|
|
|
if (priceMin !== undefined) { |
|
|
|
|
where.price = { ...(where.price || {}), [Op.gte]: priceMin }; // فیلتر حداقل قیمت
|
|
|
|
|
} |
|
|
|
|
if (priceMax !== undefined) { |
|
|
|
|
where.price = { ...(where.price || {}), [Op.lte]: priceMax }; // فیلتر حداکثر قیمت
|
|
|
|
|
where.name = { [Op.iLike]: `%${search}%` }; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const products = await this.productModel.findAll({ where }); |
|
|
|
|
|
|
|
|
|
if (!products || products.length === 0) { |
|
|
|
|
throw new HttpException('No products found.', HttpStatus.NOT_FOUND); |
|
|
|
|
|
|
|
|
|
if (priceMin !== undefined || priceMax !== undefined) { |
|
|
|
|
where.price = {}; |
|
|
|
|
if (priceMin !== undefined) { |
|
|
|
|
where.price[Op.gte] = priceMin; |
|
|
|
|
} |
|
|
|
|
if (priceMax !== undefined) { |
|
|
|
|
where.price[Op.lte] = priceMax; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return products; |
|
|
|
|
|
|
|
|
|
const offset = (page - 1) * limit; |
|
|
|
|
|
|
|
|
|
const { rows: products, count: total } = await this.productModel.findAndCountAll({ |
|
|
|
|
where, |
|
|
|
|
limit, |
|
|
|
|
offset, |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
const totalPages = Math.ceil(total / limit); |
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
products, |
|
|
|
|
total, |
|
|
|
|
totalPages, |
|
|
|
|
currentPage: page, |
|
|
|
|
}; |
|
|
|
|
} catch (error) { |
|
|
|
|
console.error(error); |
|
|
|
|
throw new HttpException( |
|
|
|
|
'An error occurred while retrieving products.', |
|
|
|
|
HttpStatus.INTERNAL_SERVER_ERROR, |
|
|
|
|
); |
|
|
|
|
}} |
|
|
|
|
console.error("Error retrieving products:", error.message); |
|
|
|
|
|
|
|
|
|
if (error instanceof HttpException) { |
|
|
|
|
throw error; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
throw new HttpException("An unexpected error occurred while retrieving products.", HttpStatus.INTERNAL_SERVER_ERROR); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// update a product info
|
|
|
|
|
async update(id: string, updateProductDto: UpdateProductDto): Promise<Product> { |
|
|
|
|
const product = await this.productModel.findByPk(id); |
|
|
|
|
|
|
|
|
|
if (!product) { |
|
|
|
|
throw new HttpException("Product not found.", HttpStatus.NOT_FOUND); |
|
|
|
|
} |
|
|
|
|
try { |
|
|
|
|
const product = await this.productModel.findByPk(id); |
|
|
|
|
const { name, description, price, imageUrl, tags, quantity, brand, color, category } = updateProductDto; |
|
|
|
|
|
|
|
|
|
if (!product) { |
|
|
|
|
throw new HttpException("Product not found.", HttpStatus.NOT_FOUND); |
|
|
|
|
let updated = false; // متغیر برای بررسی تغییرات
|
|
|
|
|
|
|
|
|
|
if (name && name !== product.name) { |
|
|
|
|
product.name = name; |
|
|
|
|
updated = true; |
|
|
|
|
} |
|
|
|
|
if (description && description !== product.description) { |
|
|
|
|
product.description = description; |
|
|
|
|
updated = true; |
|
|
|
|
} |
|
|
|
|
if (price !== undefined && price !== product.price) { |
|
|
|
|
product.price = price; |
|
|
|
|
updated = true; |
|
|
|
|
} |
|
|
|
|
if (imageUrl && imageUrl !== product.imageUrl) { |
|
|
|
|
product.imageUrl = imageUrl; |
|
|
|
|
updated = true; |
|
|
|
|
} |
|
|
|
|
if (tags && tags !== product.tags) { |
|
|
|
|
product.tags = tags; |
|
|
|
|
updated = true; |
|
|
|
|
} |
|
|
|
|
if (quantity !== undefined && quantity !== product.quantity) { |
|
|
|
|
product.quantity = quantity; |
|
|
|
|
updated = true; |
|
|
|
|
} |
|
|
|
|
if (brand && brand !== product.brand) { |
|
|
|
|
product.brand = brand; |
|
|
|
|
updated = true; |
|
|
|
|
} |
|
|
|
|
if (color && color !== product.color) { |
|
|
|
|
product.color = color; |
|
|
|
|
updated = true; |
|
|
|
|
} |
|
|
|
|
if (category && category !== product.category) { |
|
|
|
|
product.category = category; |
|
|
|
|
updated = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const { name, description, price, imageUrl, tags, quantity, brand, color, category } = updateProductDto; |
|
|
|
|
if (name) product.name = name; |
|
|
|
|
if (description) product.description = description; |
|
|
|
|
if (price) product.price = price; |
|
|
|
|
if (imageUrl) product.imageUrl = imageUrl; |
|
|
|
|
if (tags) product.tags = tags; |
|
|
|
|
if (quantity) product.quantity = quantity; |
|
|
|
|
if (brand) product.brand = brand; |
|
|
|
|
if (color) product.color = color; |
|
|
|
|
if (category) product.category = category; |
|
|
|
|
|
|
|
|
|
await product.save(); |
|
|
|
|
if (updated) { |
|
|
|
|
await product.save(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return product; |
|
|
|
|
} catch (error) { |
|
|
|
@ -124,14 +166,19 @@ export class ProductsService { |
|
|
|
|
const product = await this.productModel.findByPk(id); |
|
|
|
|
|
|
|
|
|
if (!product) { |
|
|
|
|
throw new HttpException("Product not found with the given id.", HttpStatus.NOT_FOUND); |
|
|
|
|
throw new HttpException(`Product with id ${id} not found.`, HttpStatus.NOT_FOUND); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
await product.destroy(); |
|
|
|
|
|
|
|
|
|
return { message: "Product deleted successfully." }; |
|
|
|
|
} catch (error) { |
|
|
|
|
throw new HttpException("An error occurred while deleting the product.", HttpStatus.INTERNAL_SERVER_ERROR); |
|
|
|
|
console.error("Error during product deletion:", error.message); |
|
|
|
|
if (error instanceof HttpException) { |
|
|
|
|
throw error; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
throw new HttpException("An unexpected error occurred while deleting the product.", HttpStatus.INTERNAL_SERVER_ERROR); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|