Compare commits
	
		
			No commits in common. '9e665f8710599849458beb738c56a4ff30d404d0' and 'f190090be164a24362fea323091128126de50b6a' have entirely different histories. 
		
	
	
		
			9e665f8710
			...
			f190090be1
		
	
		
	
				 7 changed files with 93 additions and 219 deletions
			
			
		@ -1,62 +0,0 @@ | 
				
			||||
'use strict'; | 
				
			||||
 | 
				
			||||
module.exports = { | 
				
			||||
  up: async (queryInterface, Sequelize) => { | 
				
			||||
    await queryInterface.createTable('Carts', { | 
				
			||||
      id: { | 
				
			||||
        type: Sequelize.INTEGER, | 
				
			||||
        allowNull: false, | 
				
			||||
        autoIncrement: true, | 
				
			||||
        primaryKey: true, | 
				
			||||
      }, | 
				
			||||
      userId: { | 
				
			||||
        type: Sequelize.INTEGER, | 
				
			||||
        allowNull: false, | 
				
			||||
        references: { | 
				
			||||
          model: 'Users', | 
				
			||||
          key: 'id', | 
				
			||||
        }, | 
				
			||||
        onDelete: 'CASCADE', | 
				
			||||
      }, | 
				
			||||
      productId: { | 
				
			||||
        type: Sequelize.INTEGER, | 
				
			||||
        allowNull: false, | 
				
			||||
        references: { | 
				
			||||
          model: 'Products', 
 | 
				
			||||
          key: 'id', | 
				
			||||
        }, | 
				
			||||
        onDelete: 'CASCADE', | 
				
			||||
      }, | 
				
			||||
      quantity: { | 
				
			||||
        type: Sequelize.INTEGER, | 
				
			||||
        allowNull: false, | 
				
			||||
      }, | 
				
			||||
      productPrice: { | 
				
			||||
        type: Sequelize.DECIMAL(10, 2), | 
				
			||||
        allowNull: false, | 
				
			||||
      }, | 
				
			||||
      totalPrice: { | 
				
			||||
        type: Sequelize.DECIMAL(10, 2), | 
				
			||||
        allowNull: false, | 
				
			||||
      }, | 
				
			||||
      productName: { | 
				
			||||
        type: Sequelize.STRING, | 
				
			||||
        allowNull: false, | 
				
			||||
      }, | 
				
			||||
      createdAt: { | 
				
			||||
        type: Sequelize.DATE, | 
				
			||||
        allowNull: false, | 
				
			||||
        defaultValue: Sequelize.NOW, | 
				
			||||
      }, | 
				
			||||
      updatedAt: { | 
				
			||||
        type: Sequelize.DATE, | 
				
			||||
        allowNull: false, | 
				
			||||
        defaultValue: Sequelize.NOW, | 
				
			||||
      }, | 
				
			||||
    }); | 
				
			||||
  }, | 
				
			||||
 | 
				
			||||
  down: async (queryInterface, Sequelize) => { | 
				
			||||
    await queryInterface.dropTable('Carts'); | 
				
			||||
  }, | 
				
			||||
}; | 
				
			||||
@ -1,46 +1,26 @@ | 
				
			||||
import { Controller, Get, Post, Patch, Delete, Body, Param, UseGuards, Request } from "@nestjs/common"; | 
				
			||||
import { Controller, Get, Post, Body, Patch, Param, Delete } from "@nestjs/common"; | 
				
			||||
import { CartService } from "./cart.service"; | 
				
			||||
import { JwtAuthGuard } from "src/guard/auth.guard"; | 
				
			||||
import { AddToCartDto } from "./dto/add-to-cart.dto"; | 
				
			||||
import { UpdateCartDto } from "./dto/update-cart.dto"; | 
				
			||||
import { Cart } from "./entities/cart.entity"; | 
				
			||||
 | 
				
			||||
@Controller("cart") | 
				
			||||
export class CartController { | 
				
			||||
  constructor(private readonly cartService: CartService) {} | 
				
			||||
 | 
				
			||||
  @UseGuards(JwtAuthGuard) | 
				
			||||
  @Post() | 
				
			||||
  async addToCart(@Body() addToCartDto: AddToCartDto, @Request() req: any): Promise<{ message: string; cartItem: Cart }> { | 
				
			||||
    const userId = req.user.id; | 
				
			||||
    return this.cartService.addToCart({ ...addToCartDto, userId }); | 
				
			||||
  async addToCart(@Body() body: { userId: number; productId: number; quantity: number }): Promise<{ message: string; cartItem: Cart }> { | 
				
			||||
    const { userId, productId, quantity } = body; | 
				
			||||
    const result = await this.cartService.addToCart(userId, productId, quantity); | 
				
			||||
    return result; | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  @UseGuards(JwtAuthGuard) | 
				
			||||
  @Get() | 
				
			||||
  async getUserCart(@Request() req: any): Promise<{ cartItems: Cart[]; totalPrice: number }> { | 
				
			||||
    const userId = req.user.id; | 
				
			||||
  @Get(":userId") | 
				
			||||
  async getUserCart(@Param("userId") userId: number) { | 
				
			||||
    return this.cartService.getUserCart(userId); | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  @UseGuards(JwtAuthGuard) | 
				
			||||
  @Patch(":productId") | 
				
			||||
  async updateCart(@Param("productId") productId: number, @Body() updateCartDto: UpdateCartDto, @Request() req: any): Promise<{ message: string; updatedCart: Cart }> { | 
				
			||||
    const userId = req.user.id; | 
				
			||||
    const updatedCart = await this.cartService.updateCart(userId, productId, updateCartDto.quantity); | 
				
			||||
    return { | 
				
			||||
      message: "Cart updated successfully", | 
				
			||||
      updatedCart, | 
				
			||||
    }; | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  @UseGuards(JwtAuthGuard) | 
				
			||||
  @Delete(":productId") | 
				
			||||
  async removeFromCart(@Param("productId") productId: number, @Request() req: any): Promise<{ message: string }> { | 
				
			||||
    const userId = req.user.id; | 
				
			||||
    await this.cartService.removeFromCart(userId, productId); | 
				
			||||
    return { | 
				
			||||
      message: "Product removed from cart successfully", | 
				
			||||
    }; | 
				
			||||
  @Delete(":userId/:productId") | 
				
			||||
  async removeFromCart( | 
				
			||||
    @Param("userId") userId: number, | 
				
			||||
    @Param("productId") productId: number, 
 | 
				
			||||
  ): Promise<{ message: string }> { | 
				
			||||
    return this.cartService.removeFromCart(userId, productId); | 
				
			||||
  } | 
				
			||||
} | 
				
			||||
 | 
				
			||||
@ -1,98 +1,101 @@ | 
				
			||||
import { Injectable, HttpException, HttpStatus } from "@nestjs/common"; | 
				
			||||
import { Injectable } from "@nestjs/common"; | 
				
			||||
import { InjectModel } from "@nestjs/sequelize"; | 
				
			||||
import { Cart } from "./entities/cart.entity"; | 
				
			||||
import { HttpException, HttpStatus } from "@nestjs/common"; | 
				
			||||
import { CartResponse } from "./cart.response"; | 
				
			||||
import { User } from "src/users/entities/user.entity"; | 
				
			||||
import { Product } from "src/products/entities/product.entity"; | 
				
			||||
import { console } from "inspector"; | 
				
			||||
 | 
				
			||||
@Injectable() | 
				
			||||
export class CartService { | 
				
			||||
  constructor( | 
				
			||||
    @InjectModel(Cart) private readonly cartModel: typeof Cart, | 
				
			||||
    @InjectModel(User) private readonly userModel: typeof User, | 
				
			||||
    @InjectModel(Product) private readonly productModel: typeof Product, | 
				
			||||
  ) {} | 
				
			||||
  
 | 
				
			||||
  // Add product to cart
 | 
				
			||||
  async addToCart(addToCartDto: { userId: number; productId: number; quantity: number }): Promise<{ message: string; cartItem: Cart }> { | 
				
			||||
    const { userId, productId, quantity } = addToCartDto; | 
				
			||||
 | 
				
			||||
    if (!userId || !productId || !quantity) { | 
				
			||||
      throw new HttpException("Missing required parameters: userId, productId, and quantity are required.", HttpStatus.BAD_REQUEST); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    const product = await this.productModel.findByPk(productId); | 
				
			||||
    if (!product) { | 
				
			||||
      throw new HttpException("Product not found!", HttpStatus.NOT_FOUND); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    const existingCartItem = await this.cartModel.findOne({ | 
				
			||||
      where: { userId, productId }, | 
				
			||||
    }); | 
				
			||||
 | 
				
			||||
    if (existingCartItem) { | 
				
			||||
      existingCartItem.quantity += Number(quantity); | 
				
			||||
      existingCartItem.totalPrice = existingCartItem.quantity * existingCartItem.productPrice; | 
				
			||||
      await existingCartItem.save(); | 
				
			||||
  async addToCart(userId: number, productId: number, quantity: number): Promise<CartResponse> { | 
				
			||||
    try { | 
				
			||||
      if (!userId || !productId || !quantity) { | 
				
			||||
        throw new HttpException("Missing required parameters: userId, productId, and quantity are required.", HttpStatus.BAD_REQUEST); | 
				
			||||
      } | 
				
			||||
 | 
				
			||||
      const user = await this.userModel.findByPk(userId); | 
				
			||||
      if (!user) { | 
				
			||||
        throw new HttpException("User not found!", HttpStatus.NOT_FOUND); | 
				
			||||
      } | 
				
			||||
 | 
				
			||||
      const product = await this.productModel.findByPk(productId); | 
				
			||||
      if (!product) { | 
				
			||||
        throw new HttpException("Product not found!", HttpStatus.NOT_FOUND); | 
				
			||||
      } | 
				
			||||
 | 
				
			||||
      const existingCartItem = await this.cartModel.findOne({ | 
				
			||||
        where: { userId, productId }, | 
				
			||||
      }); | 
				
			||||
 | 
				
			||||
      if (existingCartItem) { | 
				
			||||
        existingCartItem.quantity += Number(quantity); | 
				
			||||
        await existingCartItem.save(); | 
				
			||||
        return { | 
				
			||||
          message: "Product quantity updated in cart successfully!", | 
				
			||||
          cartItem: existingCartItem, | 
				
			||||
        }; | 
				
			||||
      } | 
				
			||||
 | 
				
			||||
      const newCartItem = await this.cartModel.create({ userId, productId, quantity }); | 
				
			||||
 | 
				
			||||
      return { | 
				
			||||
        message: "Product quantity updated in cart successfully!", | 
				
			||||
        cartItem: existingCartItem, | 
				
			||||
        message: "Product added to cart successfully!", | 
				
			||||
        cartItem: newCartItem, | 
				
			||||
      }; | 
				
			||||
    } catch (error) { | 
				
			||||
      // Enhanced error handling
 | 
				
			||||
      if (error instanceof HttpException) { | 
				
			||||
        throw error; | 
				
			||||
      } | 
				
			||||
      throw new HttpException(`An error occurred while adding the product to the cart: ${error.message}`, HttpStatus.INTERNAL_SERVER_ERROR); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    const newCartItem = await this.cartModel.create({ userId, productId, quantity, productPrice: product.price, totalPrice: product.price * quantity, productName: product.name }); | 
				
			||||
 | 
				
			||||
    return { | 
				
			||||
      message: "Product added to cart successfully!", | 
				
			||||
      cartItem: newCartItem, | 
				
			||||
    }; | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  // Get user's cart
 | 
				
			||||
  async getUserCart(userId: number): Promise<{ cartItems: Cart[]; totalPrice: number }> { | 
				
			||||
    const cartItems = await this.cartModel.findAll({ | 
				
			||||
      where: { userId }, | 
				
			||||
      include: [ | 
				
			||||
        { | 
				
			||||
          model: Product, | 
				
			||||
          attributes: ["id", "name", "price", "description", "imageUrl"], | 
				
			||||
        }, | 
				
			||||
      ], | 
				
			||||
    }); | 
				
			||||
 | 
				
			||||
    if (!cartItems || cartItems.length === 0) { | 
				
			||||
      throw new HttpException("No cart items found for the specified user.", HttpStatus.NOT_FOUND); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    const totalPrice = cartItems.reduce((sum, item) => sum + Number(item.totalPrice), 0); | 
				
			||||
 | 
				
			||||
    return { cartItems, totalPrice }; | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  // Update cart item quantity
 | 
				
			||||
  async updateCart(userId: number, productId: number, quantity: number): Promise<Cart> { | 
				
			||||
    const cartItem = await this.cartModel.findOne({ where: { userId, productId } }); | 
				
			||||
 | 
				
			||||
    if (!cartItem) { | 
				
			||||
      throw new HttpException("Product not found in the cart.", HttpStatus.NOT_FOUND); | 
				
			||||
  async getUserCart(userId: number): Promise<Cart[]> { | 
				
			||||
    try { | 
				
			||||
      const cartItems = await this.cartModel.findAll({ | 
				
			||||
        where: { userId }, | 
				
			||||
        include: ["product"], | 
				
			||||
      }); | 
				
			||||
      if (!cartItems || cartItems.length === 0) { | 
				
			||||
        throw new HttpException("No cart items found for the specified user.", HttpStatus.NOT_FOUND); | 
				
			||||
      } | 
				
			||||
 | 
				
			||||
      return cartItems; | 
				
			||||
    } catch (error) { | 
				
			||||
      if (error instanceof HttpException) { | 
				
			||||
        throw error; | 
				
			||||
      } | 
				
			||||
 | 
				
			||||
      throw new HttpException("An error occurred while retrieving the cart.", HttpStatus.INTERNAL_SERVER_ERROR); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    cartItem.quantity = quantity; | 
				
			||||
    cartItem.totalPrice = cartItem.quantity * cartItem.productPrice; | 
				
			||||
    await cartItem.save(); | 
				
			||||
    return cartItem; | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  // Remove product from cart
 | 
				
			||||
  async removeFromCart(userId: number, productId: number): Promise<{ message: string }> { | 
				
			||||
    const cartItem = await this.cartModel.findOne({ where: { userId, productId } }); | 
				
			||||
 | 
				
			||||
    if (!cartItem) { | 
				
			||||
      throw new HttpException("Product not found in the cart.", HttpStatus.NOT_FOUND); | 
				
			||||
    try { | 
				
			||||
      const cartItem = await this.cartModel.findOne({ where: { userId, productId } }); | 
				
			||||
  
 | 
				
			||||
      if (!cartItem) { | 
				
			||||
        throw new HttpException('Product not found in the cart.', HttpStatus.NOT_FOUND); | 
				
			||||
      } | 
				
			||||
  
 | 
				
			||||
      await cartItem.destroy(); | 
				
			||||
      return { message: 'Item deleted from your cart successfully.' }; | 
				
			||||
    } catch (error) { | 
				
			||||
      if (error instanceof HttpException) { | 
				
			||||
        throw error; | 
				
			||||
      } | 
				
			||||
  
 | 
				
			||||
      throw new HttpException( | 
				
			||||
        'An error occurred while removing the product from the cart.', | 
				
			||||
        HttpStatus.INTERNAL_SERVER_ERROR, | 
				
			||||
      ); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    await cartItem.destroy(); | 
				
			||||
    return { message: "Item deleted from your cart successfully." }; | 
				
			||||
  } | 
				
			||||
} | 
				
			||||
 | 
				
			||||
@ -1,13 +0,0 @@ | 
				
			||||
// add-to-cart.dto.ts
 | 
				
			||||
import { IsInt, IsNotEmpty, IsNumber, min, Min } from 'class-validator'; | 
				
			||||
 | 
				
			||||
export class AddToCartDto { | 
				
			||||
  @IsNumber()  
 | 
				
			||||
  @IsNotEmpty() | 
				
			||||
  productId: number; | 
				
			||||
 | 
				
			||||
  @IsInt() | 
				
			||||
  @IsNotEmpty() | 
				
			||||
  @Min(0) | 
				
			||||
  quantity: number; | 
				
			||||
} | 
				
			||||
@ -1,8 +0,0 @@ | 
				
			||||
// update-cart.dto.ts
 | 
				
			||||
import { IsInt, Min } from 'class-validator'; | 
				
			||||
 | 
				
			||||
export class UpdateCartDto { | 
				
			||||
  @IsInt() | 
				
			||||
  @Min(1) | 
				
			||||
  quantity: number; | 
				
			||||
} | 
				
			||||
					Loading…
					
					
				
		Reference in new issue