You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

190 lines
5.5 KiB

import { Injectable } from "@nestjs/common";
import { InjectModel } from "@nestjs/sequelize";
import { Product } from "./entities/product.entity";
import { CreateProductDto } from "./dto/create-product.dto";
import { UpdateProductDto } from "./dto/update-product.dto";
import { Op } from "sequelize";
import { HttpException, HttpStatus } from "@nestjs/common";
@Injectable()
export class ProductsService {
constructor(@InjectModel(Product) private readonly productModel: typeof Product) {}
// create a new product
async create(createProductDto: CreateProductDto): Promise<Product> {
try {
const existingProduct = await this.productModel.findOne({
where: { name: createProductDto.name },
});
if (existingProduct) {
existingProduct.quantity += createProductDto.quantity || 0;
await existingProduct.save();
return existingProduct;
}
const newProduct = await this.productModel.create(createProductDto);
return newProduct;
} catch (error) {
if(error instanceof HttpException){
throw error
}
throw new HttpException("An error occurred while creating or updating the product.", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
// find a product by id
async findOne(id: string): Promise<Product> {
try {
const product = await this.productModel.findByPk(id);
if (!product) {
throw new HttpException("Product not found with the given ID.", HttpStatus.NOT_FOUND);
}
return product;
} catch (error) {
if (error instanceof HttpException) {
throw error;
}
throw new HttpException("An unexpected error occurred while fetching the product.", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
// list of all product
async findAll(
search?: string,
priceMin?: number,
priceMax?: number,
page: number = 1,
limit: number = 10,
): Promise<{ products: Product[]; total: number; totalPages: number; currentPage: number }> {
try {
const where: Record<string, any> = {};
if (search) {
where.name = { [Op.iLike]: `%${search}%` };
}
if (priceMin !== undefined || priceMax !== undefined) {
where.price = {};
if (priceMin !== undefined) {
where.price[Op.gte] = priceMin;
}
if (priceMax !== undefined) {
where.price[Op.lte] = priceMax;
}
}
const offset = (page - 1) * limit;
const { rows: products, count: total } = await this.productModel.findAndCountAll({
where,
limit,
offset,
attributes: { exclude: ["description", "quantity", "createdAt", "updatedAt", "tags"] },
});
const totalPages = Math.ceil(total / limit);
return {
products,
total,
totalPages,
currentPage: page,
};
} catch (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 { name, description, price, imageUrl, tags, quantity, brand, color, category } = updateProductDto;
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;
}
if (updated) {
await product.save();
}
return product;
} catch (error) {
if(error instanceof HttpException){
throw error
}
throw new HttpException("An error occurred while updating the product.", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
// delete a product
async remove(id: string): Promise<{ message: string }> {
try {
const product = await this.productModel.findByPk(id);
if (!product) {
throw new HttpException(`Product with id ${id} not found.`, HttpStatus.NOT_FOUND);
}
await product.destroy();
return { message: "Product deleted successfully." };
} catch (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);
}
}
}