Create DTOs and refactor product module routes

master
nicekid1 2 months ago
parent 716c4a6782
commit f190090be1
  1. 41
      src/products/dto/create-product.dto.ts
  2. 40
      src/products/dto/update-product.dto.ts
  3. 20
      src/products/products.controller.ts
  4. 124
      src/products/products.service.ts

@ -0,0 +1,41 @@
import { IsString, IsNumber, IsOptional, IsNotEmpty, IsArray } from 'class-validator';
export class CreateProductDto {
@IsString()
@IsNotEmpty()
name: string;
@IsString()
@IsNotEmpty()
description: string;
@IsNumber()
@IsNotEmpty()
price: number;
@IsOptional()
@IsString()
imageUrl?: string;
@IsOptional()
@IsArray()
@IsString({ each: true })
tags?: string[];
@IsOptional()
@IsNumber()
@IsNotEmpty()
quantity?: number;
@IsOptional()
@IsString()
brand?: string;
@IsOptional()
@IsString()
color?: string;
@IsString()
@IsNotEmpty()
category: string;
}

@ -0,0 +1,40 @@
import { IsString, IsNumber, IsOptional, IsArray } from 'class-validator';
export class UpdateProductDto {
@IsOptional()
@IsString()
name?: string;
@IsOptional()
@IsString()
description?: string;
@IsOptional()
@IsNumber()
price?: number;
@IsOptional()
@IsString()
imageUrl?: string;
@IsOptional()
@IsArray()
@IsString({ each: true })
tags?: string[];
@IsOptional()
@IsNumber()
quantity?: number;
@IsOptional()
@IsString()
brand?: string;
@IsOptional()
@IsString()
color?: string;
@IsOptional()
@IsString()
category?: string;
}

@ -1,35 +1,43 @@
import { Controller, Get, Post, Body, Param, Delete, Query, Put, UseGuards } from "@nestjs/common"; import { Controller, Get, Post, Body, Param, Delete, Query, Put, UseGuards } from "@nestjs/common";
import { ProductsService } from "./products.service"; import { ProductsService } from "./products.service";
import { Product } from "./entities/product.entity"; import { Product } from "./entities/product.entity";
import { CreateProductDto } from "./dto/create-product.dto";
import { UpdateProductDto } from "./dto/update-product.dto";
import { RoleGuard } from "src/guard/role.guard"; import { RoleGuard } from "src/guard/role.guard";
@Controller("products") @Controller("products")
export class ProductsController { export class ProductsController {
constructor(private readonly productsService: ProductsService) {} constructor(private readonly productsService: ProductsService) {}
@UseGuards(RoleGuard) @UseGuards(RoleGuard)
@Post() @Post()
async create(@Body() body: { name: string; description: string; price: number }) { async create(@Body() createProductDto: CreateProductDto) {
const { name, description, price } = body; const product = await this.productsService.create(createProductDto);
const product = await this.productsService.create(name, description, price);
return { return {
message: "Product created successfully!", message: "Product created successfully!",
product, product,
}; };
} }
@Get() @Get()
async findAll(@Query() query: { search?: string; priceMin?: number; priceMax?: number }) { async findAll(@Query() query: { search?: string; priceMin?: number; priceMax?: number }) {
const { search, priceMin, priceMax } = query; const { search, priceMin, priceMax } = query;
return this.productsService.findAll(search, priceMin, priceMax); return this.productsService.findAll(search, priceMin, priceMax);
} }
@Get(":id") @Get(":id")
async findOne(@Param("id") id: string): Promise<Product> { async findOne(@Param("id") id: string): Promise<Product> {
return this.productsService.findOne(id); return this.productsService.findOne(id);
} }
@UseGuards(RoleGuard)
@Put(":id") @Put(":id")
async update(@Param("id") id: string, @Body() body: { name?: string; description?: string; price?: number }): Promise<Product> { async update(
const { name, description, price } = body; @Param("id") id: string,
return this.productsService.update(id, name, description, price); @Body() updateProductDto: UpdateProductDto
): Promise<Product> {
return this.productsService.update(id, updateProductDto);
} }
@UseGuards(RoleGuard)
@Delete(':id') @Delete(':id')
async remove(@Param('id') id: string): Promise<{ message: string }> { async remove(@Param('id') id: string): Promise<{ message: string }> {
return this.productsService.remove(id); return this.productsService.remove(id);

@ -1,74 +1,97 @@
import { Injectable } from "@nestjs/common"; import { Injectable } from "@nestjs/common";
import { InjectModel } from "@nestjs/sequelize"; import { InjectModel } from "@nestjs/sequelize";
import { Product } from "./entities/product.entity"; 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 { Op } from "sequelize";
import { HttpException, HttpStatus } from "@nestjs/common"; import { HttpException, HttpStatus } from "@nestjs/common";
@Injectable() @Injectable()
export class ProductsService { export class ProductsService {
constructor(@InjectModel(Product) private readonly productModel: typeof Product) {} constructor(@InjectModel(Product) private readonly productModel: typeof Product) {}
async create(name: string, description: string, price: number): Promise<Product> { // create a new product
async create(createProductDto: CreateProductDto): Promise<Product> {
try { try {
if (!name || !description || price <= 0) { const existingProduct = await this.productModel.findOne({
throw new Error("Invalid input data"); where: { name: createProductDto.name },
});
if (existingProduct) {
throw new HttpException(
'Product with this name already exists.',
HttpStatus.BAD_REQUEST,
);
} }
const product = await this.productModel.create({ name, description, price });
const product = await this.productModel.create(createProductDto);
return product; return product;
} catch (error) { } catch (error) {
throw new Error("Error creating product"); console.error(error);
throw new HttpException(
'An error occurred while creating the product.',
HttpStatus.INTERNAL_SERVER_ERROR,
);
} }
} }
async findAll(search?: string, priceMin?: number, priceMax?: number): Promise<Product[]> { // find a product by id
const where: any = {}; async findOne(id: string): Promise<Product> {
try { try {
if (search) { const product = await this.productModel.findByPk(id);
where.name = {
[Op.iLike]: `%${search}%`,
};
}
if (priceMin || priceMax) {
where.price = {};
if (priceMin) where.price[Op.gte] = priceMin;
if (priceMax) where.price[Op.lte] = priceMax;
}
const products = await this.productModel.findAll({ where });
if (!products || products.length === 0) { if (!product) {
throw new HttpException("No products found matching the given criteria.", HttpStatus.NOT_FOUND); throw new HttpException(
'Product not found with the given id.',
HttpStatus.NOT_FOUND,
);
} }
return products; return product;
} catch (error) { } catch (error) {
if (error instanceof HttpException) { console.error(error);
throw error; throw new HttpException(
} error.response,
HttpStatus.INTERNAL_SERVER_ERROR,
throw new HttpException("An error occurred while retrieving products.", HttpStatus.INTERNAL_SERVER_ERROR); );
} }
} }
async findOne(id: string): Promise<Product> { // list of all product
async findAll(
search?: string,
priceMin?: number,
priceMax?: number,
): Promise<Product[]> {
try { try {
const product = await this.productModel.findByPk(id); // ساخت شرطهای جستجو و فیلتر
const where: any = {};
if (!product) { if (search) {
throw new HttpException("Product not found with the given id.", HttpStatus.NOT_FOUND); 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 }; // فیلتر حداکثر قیمت
} }
return product; const products = await this.productModel.findAll({ where });
} catch (error) {
if (error instanceof HttpException) { if (!products || products.length === 0) {
throw error; throw new HttpException('No products found.', HttpStatus.NOT_FOUND);
} }
throw new HttpException("An error occurred while retrieving the product.", HttpStatus.INTERNAL_SERVER_ERROR); return products;
} } catch (error) {
} console.error(error);
async update(id: string, name?: string, description?: string, price?: number): Promise<Product> { throw new HttpException(
'An error occurred while retrieving products.',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}}
// update a product info
async update(id: string, updateProductDto: UpdateProductDto): Promise<Product> {
try { try {
const product = await this.productModel.findByPk(id); const product = await this.productModel.findByPk(id);
@ -76,21 +99,26 @@ export class ProductsService {
throw new HttpException("Product not found.", HttpStatus.NOT_FOUND); throw new HttpException("Product not found.", HttpStatus.NOT_FOUND);
} }
const { name, description, price, imageUrl, tags, quantity, brand, color, category } = updateProductDto;
if (name) product.name = name; if (name) product.name = name;
if (description) product.description = description; if (description) product.description = description;
if (price) product.price = price; 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(); await product.save();
return product; return product;
} catch (error) { } catch (error) {
if (error instanceof HttpException) {
throw error;
}
throw new HttpException("An error occurred while updating the product.", HttpStatus.INTERNAL_SERVER_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 }> { async remove(id: string): Promise<{ message: string }> {
try { try {
const product = await this.productModel.findByPk(id); const product = await this.productModel.findByPk(id);
@ -103,10 +131,6 @@ export class ProductsService {
return { message: "Product deleted successfully." }; return { message: "Product deleted successfully." };
} catch (error) { } catch (error) {
if (error instanceof HttpException) {
throw error;
}
throw new HttpException("An error occurred while deleting the product.", HttpStatus.INTERNAL_SERVER_ERROR); throw new HttpException("An error occurred while deleting the product.", HttpStatus.INTERNAL_SERVER_ERROR);
} }
} }

Loading…
Cancel
Save