Compare commits

...

5 Commits

  1. 9
      src/admin/admin.controller.ts
  2. 42
      src/admin/admin.service.ts
  3. 24
      src/cart/cart.controller.ts
  4. 131
      src/cart/cart.service.ts
  5. 2
      src/invoice/invoice.service.ts
  6. 11
      src/users/users.controller.ts
  7. 130
      src/users/users.service.ts

@ -1,25 +1,24 @@
import { Controller, Get, Post, Body, Request, Put, UseGuards } from "@nestjs/common"; import { Controller, Get, Post, Body, Request, Put, UseGuards } from "@nestjs/common";
import { AdminService } from "./admin.service"; import { AdminService } from "./admin.service";
import { Admin } from "./entities/admin.entity";
import { CreateAdminDto } from "./dto/create-Admin.dto"; import { CreateAdminDto } from "./dto/create-Admin.dto";
import { LoginAdminDto } from "./dto/login-Admin.dto"; import { LoginAdminDto } from "./dto/login-Admin.dto";
import { JwtAuthGuard } from "src/guard/auth.guard";
import { UpdateUserDto } from "./dto/update-user.dto"; import { UpdateUserDto } from "./dto/update-user.dto";
import { RoleGuard } from "src/guard/role.guard";
@Controller("admin") @Controller("admin")
export class AdminController { export class AdminController {
constructor(private readonly adminService: AdminService) {} constructor(private readonly adminService: AdminService) {}
@Post("register") @Post("register")
async register(@Body() createAdminDto: CreateAdminDto): Promise<Admin> { async register(@Body() createAdminDto: CreateAdminDto): Promise<{message}> {
return this.adminService.register(createAdminDto); return this.adminService.register(createAdminDto);
} }
@Post("login") @Post("login")
async login(@Body() loginAdminDto: LoginAdminDto): Promise<{ token: string }> { async login(@Body() loginAdminDto: LoginAdminDto): Promise<{ token: string }> {
return this.adminService.login(loginAdminDto); return this.adminService.login(loginAdminDto);
} }
@UseGuards(JwtAuthGuard) @UseGuards(RoleGuard)
@Put() @Put()
async editAdminProfile(@Request() req, @Body() updateAdminDto: UpdateUserDto): Promise<Admin> { async editAdminProfile(@Request() req, @Body() updateAdminDto: UpdateUserDto): Promise<{message}>{
const userId = req.user.id; const userId = req.user.id;
return this.adminService.editAdminProfile(userId, updateAdminDto); return this.adminService.editAdminProfile(userId, updateAdminDto);
} }

@ -15,38 +15,38 @@ export class AdminService {
private readonly configService: ConfigService, private readonly configService: ConfigService,
) {} ) {}
//register method //register method
async register(createAdminDto: CreateAdminDto): Promise<Admin> { async register(createAdminDto: CreateAdminDto): Promise<{ message }> {
try { try {
const existingAdmin = await this.adminModel.findOne({ where: { email: createAdminDto.email } }); const existingAdmin = await this.adminModel.findOne({
where: { email: createAdminDto.email },
});
if (existingAdmin) { if (existingAdmin) {
throw new HttpException("Email is already registered.", HttpStatus.CONFLICT); throw new HttpException("The provided email is already registered.", HttpStatus.CONFLICT);
} }
createAdminDto.password = await bcrypt.hash(createAdminDto.password, 10); createAdminDto.password = await bcrypt.hash(createAdminDto.password, 10);
await this.adminModel.create(createAdminDto);
const admin = await this.adminModel.create(createAdminDto); return { message: "admin register is successful" };
return admin;
} catch (error) { } catch (error) {
console.log(error);
if (error instanceof HttpException) { if (error instanceof HttpException) {
throw error; throw error;
} }
throw new HttpException("An error occurred during registration.", HttpStatus.INTERNAL_SERVER_ERROR); throw new HttpException("An unexpected error occurred. Please try again later.", HttpStatus.INTERNAL_SERVER_ERROR);
} }
} }
//login method //login method
async login(loginAdminDto: LoginAdminDto): Promise<{ token: string }> { async login(loginAdminDto: LoginAdminDto): Promise<{ token: string }> {
try { try {
const admin = await this.adminModel.findOne({ where: { email: loginAdminDto.email } }); const admin = await this.adminModel.findOne({
where: { email: loginAdminDto.email },
});
if (!admin) { if (!admin) {
throw new HttpException("Invalid email or password or username", HttpStatus.UNAUTHORIZED); throw new HttpException("Invalid email or password.", HttpStatus.UNAUTHORIZED);
} }
const isValidPassword = await bcrypt.compare(loginAdminDto.password, admin.password); const isValidPassword = await bcrypt.compare(loginAdminDto.password, admin.password);
if (!isValidPassword) { if (!isValidPassword) {
throw new HttpException("Invalid email or password or username", HttpStatus.UNAUTHORIZED); throw new HttpException("Invalid email or password.", HttpStatus.UNAUTHORIZED);
} }
const token = this.jwtService.sign( const token = this.jwtService.sign(
@ -59,21 +59,27 @@ export class AdminService {
return { token }; return { token };
} catch (error) { } catch (error) {
throw new HttpException(error.response, HttpStatus.INTERNAL_SERVER_ERROR); if (error instanceof HttpException) {
throw error;
}
throw new HttpException("An unexpected error occurred. Please try again later.", HttpStatus.INTERNAL_SERVER_ERROR);
} }
} }
//edit admin profile method //edit admin profile method
async editAdminProfile(userId: number, updateAdminDto: UpdateUserDto): Promise<Admin> { async editAdminProfile(userId: number, updateAdminDto: UpdateUserDto) {
try { try {
const user = await this.adminModel.findOne({ where: { id: userId } }); let user = await this.adminModel.findOne({ where: { id: userId } });
if (!user) { if (!user) {
throw new Error("Admin not found"); throw new Error("Admin not found");
} }
await user.update(updateAdminDto); await user.update(updateAdminDto);
user = await this.adminModel.findOne({
return user; where: { id: userId },
attributes: { exclude: ["password"] },
});
return { message: "user account updated successful", user };
} catch (error) { } catch (error) {
throw new Error(`An error occurred while updating admin: ${error.message}`); throw new Error(`An error occurred while updating admin: ${error.message}`);
} }

@ -20,9 +20,9 @@ export class CartController {
@UseGuards(JwtAuthGuard) @UseGuards(JwtAuthGuard)
@Get() @Get()
async getUserCart(@Request() req: any): Promise<{ cartItems: Cart[]; totalPrice: number }> { async getUserOpenCart(@Request() req: any): Promise<{ cartItems: Cart[]; totalPrice: number }> {
const userId = req.user.id; const userId = req.user.id;
return this.cartService.getUserCart(userId); return this.cartService.getUserOpenCart(userId);
} }
@UseGuards(JwtAuthGuard) @UseGuards(JwtAuthGuard)
@ -38,21 +38,17 @@ export class CartController {
@UseGuards(JwtAuthGuard) @UseGuards(JwtAuthGuard)
@Delete(":productId") @Delete(":productId")
async removeFromCart(@Param("productId") productId: number, @Request() req: any): Promise<{ message: string }> { async removeFromCart(@Param("productId") productId: number, @Request() req: any) {
const userId = req.user.id; const userId = req.user.id;
await this.cartService.removeFromCart(userId, productId); return await this.cartService.removeFromCart(userId, productId);
return {
message: "Product removed from cart successfully",
};
} }
@Post(":userId/checkout") @UseGuards(JwtAuthGuard)
async processOrder(@Param("userId") userId: number, @Body("totalAmount") totalAmount: number): Promise<{ message: string; invoice: Invoice }> { @Get("checkout")
if (!totalAmount || totalAmount <= 0) { async processOrder(@Request() req: any): Promise<{ message: string; invoice: Invoice }> {
throw new HttpException("Invalid total amount.", HttpStatus.BAD_REQUEST); const userId = req.user.id;
}
try { try {
const totalAmount = (await this.cartService.getUserOpenCart(userId)).totalPrice
const result = await this.cartService.processOrder(userId, totalAmount); const result = await this.cartService.processOrder(userId, totalAmount);
return result; return result;
} catch (error) { } catch (error) {

@ -23,92 +23,106 @@ export class CartService {
if (!userId || !productId || !quantity || isNaN(Number(quantity)) || Number(quantity) <= 0) { if (!userId || !productId || !quantity || isNaN(Number(quantity)) || Number(quantity) <= 0) {
throw new HttpException("Invalid parameters: userId, productId, and a positive quantity are required.", HttpStatus.BAD_REQUEST); throw new HttpException("Invalid parameters: userId, productId, and a positive quantity are required.", HttpStatus.BAD_REQUEST);
} }
const product = await this.productModel.findByPk(productId); const product = await this.productModel.findByPk(productId);
if (!product) { if (!product) {
throw new HttpException("Product not found!", HttpStatus.NOT_FOUND); throw new HttpException("Product not found!", HttpStatus.NOT_FOUND);
} }
if (product.quantity < quantity) {
let invoice = await this.invoiceModel.findOne({ where: { userId, status: "pending" } }); throw new HttpException("Product quantity insufficient!", HttpStatus.CONFLICT);
if (!invoice) {
invoice = await this.invoiceService.createInvoiceFromCart(userId);
}
const invoiceId = invoice.id;
let cart = await this.cartModel.findOne({ where: { userId, productId, status: "open" } });
console.log(cart);
if (!cart) {
cart = await this.cartModel.create({
userId,
productId,
invoiceId,
quantity,
productPrice: product.price,
status: "open",
});
await cart.save();
} else {
cart.quantity += Number(quantity);
await cart.save();
} }
try {
let invoice = await this.invoiceModel.findOne({ where: { userId, status: "pending" } });
if (!invoice) {
invoice = await this.invoiceService.createInvoiceFromCart(userId);
}
const invoiceId = invoice.id;
let cart = await this.cartModel.findOne({ where: { userId, productId, status: "open" } });
if (!cart) {
cart = await this.cartModel.create({
userId,
productId,
invoiceId,
quantity,
productPrice: product.price,
status: "open",
});
await cart.save();
} else {
cart.quantity += Number(quantity);
await cart.save();
}
await this.invoiceService.updateTotalPayment(userId); await this.invoiceService.updateTotalPayment(userId);
return { return {
message: cart.id ? "Product quantity updated in cart successfully!" : "Product added to cart successfully!", message: cart.id ? "Product quantity updated in cart successfully!" : "Product added to cart successfully!",
cartItem: cart, cartItem: cart,
}; };
} catch (error) {
console.error("Error during adding item to cart:", error);
throw new HttpException("An unexpected error occurred while adding the product to cart. Please try again later.", HttpStatus.INTERNAL_SERVER_ERROR);
}
} }
// Get user's cart // Get user's cart
async getUserCart(userId: number): Promise<{ cartItems: Cart[]; totalPrice: number }> { async getUserOpenCart(userId: number): Promise<{ cartItems: Cart[]; totalPrice: number }> {
if (!userId) { if (!userId) {
throw new HttpException("User ID is required.", HttpStatus.BAD_REQUEST); throw new HttpException("User ID is required.", HttpStatus.BAD_REQUEST);
} }
const cartItems = await this.cartModel.findAll({ try {
where: { userId }, const cartItems = await this.cartModel.findAll({
include: [ where: { userId, status: "open" },
{ include: [
model: Product, {
attributes: [], model: Product,
}, attributes: ["name"],
], },
}); ],
});
if (!cartItems || cartItems.length === 0) {
throw new HttpException("No cart items found for the specified user.", HttpStatus.NOT_FOUND); 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.productPrice * item.quantity) || 0), 0); const totalPrice = cartItems.reduce((sum, item) => sum + (Number(item.productPrice) * item.quantity || 0), 0);
return { cartItems, totalPrice }; return { cartItems, totalPrice };
} catch (error) {
throw new HttpException("An unexpected error occurred while fetching the cart. Please try again later.", HttpStatus.INTERNAL_SERVER_ERROR);
}
} }
// Update cart item quantity // Update cart item quantity
async updateCart(userId: number, productId: number, quantity: number): Promise<Cart> { async updateCart(userId: number, productId: number, quantity: number): Promise<Cart> {
const cartItem = await this.cartModel.findOne({ where: { userId, productId } }); const cartItem = await this.cartModel.findOne({ where: { userId, productId, status: "open" } });
if (!cartItem) { if (!cartItem) {
throw new HttpException("Product not found in the cart.", HttpStatus.NOT_FOUND); throw new HttpException("Product not found in the cart.", HttpStatus.NOT_FOUND);
} }
try {
cartItem.quantity = quantity; cartItem.quantity = quantity;
await cartItem.save(); await cartItem.save();
await this.invoiceService.updateTotalPayment(userId); await this.invoiceService.updateTotalPayment(userId);
return cartItem; return cartItem;
} catch (error) {
throw new HttpException("An unexpected error occurred while updating the cart. Please try again later.", HttpStatus.INTERNAL_SERVER_ERROR);
}
} }
// Remove an item from cart // Remove an item from cart
async removeFromCart(userId: number, productId: number): Promise<{ message: string }> { async removeFromCart(userId: number, productId: number): Promise<{ message: string; cartItem: Cart }> {
const cartItem = await this.cartModel.findOne({ where: { userId, productId } }); const cartItem = await this.cartModel.findOne({ where: { userId, productId, status: "open" } });
if (!cartItem) { if (!cartItem) {
throw new HttpException("Product not found in the cart.", HttpStatus.NOT_FOUND); throw new HttpException("Product not found in the cart.", HttpStatus.NOT_FOUND);
} }
await cartItem.destroy(); try {
await this.invoiceService.updateTotalPayment(userId); await cartItem.destroy();
return { message: "Item deleted from your cart successfully." }; await this.invoiceService.updateTotalPayment(userId);
return { message: "Item deleted from your cart successfully.", cartItem };
} catch (error) {
throw new HttpException("An unexpected error occurred while removing the item from the cart. Please try again later.", HttpStatus.INTERNAL_SERVER_ERROR);
}
} }
//delete whole cart //delete whole cart
@ -120,7 +134,6 @@ export class CartService {
async processOrder(userId: number, totalAmount: number): Promise<{ message: string; invoice: Invoice }> { async processOrder(userId: number, totalAmount: number): Promise<{ message: string; invoice: Invoice }> {
try { try {
const carts = await this.cartModel.findAll({ where: { userId, status: "open" } }); const carts = await this.cartModel.findAll({ where: { userId, status: "open" } });
if (!carts || carts.length === 0) { if (!carts || carts.length === 0) {
throw new HttpException("No open carts found for this user.", HttpStatus.NOT_FOUND); throw new HttpException("No open carts found for this user.", HttpStatus.NOT_FOUND);
} }

@ -29,7 +29,7 @@ export class InvoiceService {
throw new HttpException("User not found", HttpStatus.NOT_FOUND); throw new HttpException("User not found", HttpStatus.NOT_FOUND);
} }
const userCartItems = await this.cartService.getUserCart(userId); const userCartItems = await this.cartService.getUserOpenCart(userId);
if (!userCartItems || !userCartItems.cartItems || userCartItems.cartItems.length === 0) { if (!userCartItems || !userCartItems.cartItems || userCartItems.cartItems.length === 0) {
throw new HttpException("Cart is empty", HttpStatus.BAD_REQUEST); throw new HttpException("Cart is empty", HttpStatus.BAD_REQUEST);
} }

@ -1,4 +1,4 @@
import { Controller, Post, Body, UseGuards, Get, Request, Put } from "@nestjs/common"; import { Controller, Post, Body, UseGuards, Get, Request, Put, Param } from "@nestjs/common";
import { UsersService } from "./users.service"; import { UsersService } from "./users.service";
import { User } from "./entities/user.entity"; import { User } from "./entities/user.entity";
import { CreateUserDto } from "./dto/create-user.dto"; import { CreateUserDto } from "./dto/create-user.dto";
@ -12,7 +12,7 @@ export class UsersController {
constructor(private readonly usersService: UsersService) {} constructor(private readonly usersService: UsersService) {}
//register as user //register as user
@Post("register") @Post("register")
async register(@Body() createUserDto: CreateUserDto): Promise<User> { async register(@Body() createUserDto: CreateUserDto): Promise<{message}> {
return this.usersService.register(createUserDto); return this.usersService.register(createUserDto);
} }
//login as user //login as user
@ -31,7 +31,7 @@ export class UsersController {
//edit user profile //edit user profile
@UseGuards(JwtAuthGuard) @UseGuards(JwtAuthGuard)
@Put() @Put()
async editProfile(@Request() req, @Body() updateUserDto: UpdateUserDto): Promise<User> { async editProfile(@Request() req, @Body() updateUserDto: UpdateUserDto) {
const userId = req.user.id; const userId = req.user.id;
return this.usersService.editProfile(userId, updateUserDto); return this.usersService.editProfile(userId, updateUserDto);
} }
@ -41,4 +41,9 @@ export class UsersController {
async findAll(): Promise<User[]> { async findAll(): Promise<User[]> {
return this.usersService.findAll(); return this.usersService.findAll();
} }
@UseGuards(RoleGuard)
@Get("users/:id")
async findSpecificUserInfoByUser(@Param("id") id): Promise<User> {
return this.usersService.findSpecificUserInfoByUser(id);
}
} }

@ -1,4 +1,4 @@
import { HttpException, HttpStatus, Injectable, UnauthorizedException, BadRequestException, NotFoundException } from "@nestjs/common"; import { HttpException, HttpStatus, Injectable, UnauthorizedException, BadRequestException, NotFoundException, UseGuards } from "@nestjs/common";
import { InjectModel } from "@nestjs/sequelize"; import { InjectModel } from "@nestjs/sequelize";
import { User } from "./entities/user.entity"; import { User } from "./entities/user.entity";
import * as bcrypt from "bcrypt"; import * as bcrypt from "bcrypt";
@ -17,83 +17,115 @@ export class UsersService {
) {} ) {}
// Register method // Register method
async register(createUserDto: CreateUserDto): Promise<User> { async register(createUserDto: CreateUserDto): Promise<{ message }> {
try { try {
createUserDto.password = await bcrypt.hash(createUserDto.password, parseInt(process.env.BCRYPT_SALT_ROUNDS || "10", 10)); createUserDto.password = await bcrypt.hash(createUserDto.password, parseInt(process.env.BCRYPT_SALT_ROUNDS || "10", 10));
const userExists = await this.userModel.findOne({ const userExists = await this.userModel.findOne({
where: { email: createUserDto.email }, where: { email: createUserDto.email },
}); });
if (userExists) { if (userExists) {
throw new BadRequestException("Email already exists"); throw new BadRequestException("Email is already registered.");
} }
const user = await this.userModel.create(createUserDto); const user = await this.userModel.create(createUserDto);
return user; return { message: "user registered successful" };
} catch (error) { } catch (error) {
throw new HttpException(`An error occurred: ${error.message}`, HttpStatus.INTERNAL_SERVER_ERROR); if (error instanceof HttpException) {
throw error;
}
throw new HttpException("An unexpected error occurred. Please try again later.", HttpStatus.INTERNAL_SERVER_ERROR);
} }
} }
// Login method // Login method
async login(loginUserDto: LoginUserDto): Promise<{ token: string }> { async login(loginUserDto: LoginUserDto): Promise<{ token: string }> {
const user = await this.userModel.findOne({ try {
where: { email: loginUserDto.email }, const user = await this.userModel.findOne({
}); where: { email: loginUserDto.email },
if (!user) { });
throw new UnauthorizedException("Invalid email or password");
}
const passwordMatch = await bcrypt.compare(loginUserDto.password, user.password); if (!user) {
if (!passwordMatch) { throw new UnauthorizedException("Invalid email or password.");
throw new UnauthorizedException("Invalid email or password"); }
const passwordMatch = await bcrypt.compare(loginUserDto.password, user.password);
if (!passwordMatch) {
throw new UnauthorizedException("Invalid email or password.");
}
const token = this.jwtService.sign(
{ id: user.id, role: user.role },
{
secret: this.configService.get<string>("JWT_SECRET"),
expiresIn: this.configService.get<string | number>("JWT_EXPIRES") || "1h",
},
);
return { token };
} catch (error) {
if (error instanceof HttpException) {
throw error;
}
throw new HttpException("An unexpected error occurred. Please try again later.", HttpStatus.INTERNAL_SERVER_ERROR);
} }
const token = this.jwtService.sign(
{ id: user.id,role:user.role },
{
secret: this.configService.get<string>("JWT_SECRET"),
expiresIn: this.configService.get<string | number>("JWT_EXPIRES") || "1h",
},
);
return { token };
} }
//get information user method //get information user method
async getProfile(userId: number): Promise<User> { async getProfile(userId: number): Promise<User> {
const user = await this.userModel.findOne({ try {
where: { id: userId }, const user = await this.userModel.findOne({
attributes: { exclude: ["password"] }, where: { id: userId },
}); attributes: { exclude: ["password"] },
});
if (!user) { if (!user) {
throw new Error("User not found"); throw new HttpException("User not found.", HttpStatus.NOT_FOUND);
}
return user;
} catch (error) {
throw new HttpException("An unexpected error occurred. Please try again later.", HttpStatus.INTERNAL_SERVER_ERROR);
} }
return user;
} }
//edit profile user method //edit profile user method
async editProfile(userId: number, updateUserDto: UpdateUserDto) { async editProfile(userId: number, updateUserDto: UpdateUserDto) {
const user = await this.userModel.findOne({ where: { id: userId } }); try {
let user = await this.userModel.findOne({ where: { id: userId } });
if (!user) { if (!user) {
throw new NotFoundException("User not found"); throw new NotFoundException('User not found.');
} }
if (updateUserDto.password) {
if (updateUserDto.password) { updateUserDto.password = await bcrypt.hash(updateUserDto.password, 10);
updateUserDto.password = await bcrypt.hash(updateUserDto.password, 10); }
await user.update(updateUserDto);
user = await this.userModel.findOne({
where: { id: userId },
attributes: { exclude: ['password'] },
});
return { message: 'User account updated successfully.', user };
} catch (error) {
throw new HttpException(
'An unexpected error occurred. Please try again later.',
HttpStatus.INTERNAL_SERVER_ERROR,
);
} }
await user.update(updateUserDto);
return user;
} }
//get users list //get users list
async findAll(): Promise<User[]> { async findAll(): Promise<User[]> {
try { try {
return await this.userModel.findAll(); return await this.userModel.findAll();
} catch (error) { } catch (error) {
throw new Error("An error occurred while fetching users"); throw new HttpException(
'An unexpected error occurred while fetching users.',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
//get users list
async findSpecificUserInfoByUser(userId: number): Promise<User> {
try {
const user = await this.userModel.findByPk(userId);
if (!user) {
throw new HttpException('User not found.', HttpStatus.NOT_FOUND);
}
return user;
} catch (error) {
throw new HttpException(
'An unexpected error occurred while fetching user information.',
HttpStatus.INTERNAL_SERVER_ERROR,
);
} }
} }
} }

Loading…
Cancel
Save