diff --git a/migrations/20250105085732-create-invoice.js b/migrations/20250105085732-create-invoice.js index 76b70b2..af58df6 100644 --- a/migrations/20250105085732-create-invoice.js +++ b/migrations/20250105085732-create-invoice.js @@ -1,10 +1,10 @@ -"use strict"; +'use strict'; module.exports = { + up: async (queryInterface, Sequelize) => { - await queryInterface.dropTable("Invoices", { cascade: true }); - - await queryInterface.createTable("Invoices", { + await queryInterface.dropTable('Invoices', { cascade: true }); + await queryInterface.createTable('Invoices', { id: { type: Sequelize.INTEGER, autoIncrement: true, @@ -15,66 +15,38 @@ module.exports = { type: Sequelize.INTEGER, allowNull: false, references: { - model: "Users", - key: "id", + model: 'Users', + key: 'id', }, - onDelete: "CASCADE", - }, - firstName: { - type: Sequelize.STRING, - allowNull: false, - }, - lastName: { - type: Sequelize.STRING, - allowNull: false, - }, - phoneNumber: { - type: Sequelize.STRING, - allowNull: false, - }, - email: { - type: Sequelize.STRING, - allowNull: false, - unique: false, - }, - totalPaymentAmount: { - type: Sequelize.DECIMAL(10, 2), - allowNull: true, + onDelete: 'CASCADE', }, - productId: { + cartId: { type: Sequelize.INTEGER, allowNull: false, + references: { + model: 'Carts', + key: 'id', + }, + onDelete: 'CASCADE', }, - quantity: { - type: Sequelize.INTEGER, - allowNull: false, - }, - price: { - type: Sequelize.DECIMAL(10, 2), - allowNull: false, - }, - totalPrice: { - type: Sequelize.DECIMAL(10, 2), - allowNull: false, - }, - productName: { - type: Sequelize.STRING, + totalPaymentAmount: { + type: Sequelize.FLOAT, allowNull: false, }, createdAt: { type: Sequelize.DATE, allowNull: false, - defaultValue: Sequelize.fn("NOW"), + defaultValue: Sequelize.fn('NOW'), }, updatedAt: { type: Sequelize.DATE, allowNull: false, - defaultValue: Sequelize.fn("NOW"), + defaultValue: Sequelize.fn('NOW'), }, }); }, down: async (queryInterface, Sequelize) => { - await queryInterface.dropTable("Invoices"); + await queryInterface.dropTable('Invoices'); }, }; diff --git a/src/cart/cart.controller.ts b/src/cart/cart.controller.ts index 9a95591..a4e4831 100644 --- a/src/cart/cart.controller.ts +++ b/src/cart/cart.controller.ts @@ -49,7 +49,7 @@ export class CartController { async processOrder( @Param('userId') userId: number, @Body('totalAmount') totalAmount: number, - ):Promise<{ message: string; invoices: Invoice[] }> { + ):Promise<{ message: string; invoices: Invoice}> { if (!totalAmount || totalAmount <= 0) { throw new HttpException('Invalid total amount.', HttpStatus.BAD_REQUEST); } diff --git a/src/cart/cart.service.ts b/src/cart/cart.service.ts index 335e7f9..568a6f8 100644 --- a/src/cart/cart.service.ts +++ b/src/cart/cart.service.ts @@ -109,39 +109,46 @@ export class CartService { } //order(clearCart disable) - async processOrder(userId: number, totalAmount: number): Promise<{ message: string; invoices: Invoice[] }> { + async processOrder(userId: number, totalAmount: number): Promise<{ message: string; invoices: Invoice }> { try { + const cart = await this.cartModel.findOne({ where: { userId } }); + if (!cart) { + throw new HttpException("Cart not found for this user.", HttpStatus.NOT_FOUND); + } + + const cartId = cart.id; + // Deducting credit from wallet await this.walletService.processPayment(userId, totalAmount); - + // Retrieve cart items const cartItems = await this.cartModel.findAll({ where: { userId } }); if (cartItems.length === 0) { throw new HttpException("Cart is empty.", HttpStatus.BAD_REQUEST); } - + // Process each cart item and update stock for (const cartItem of cartItems) { const { productId, quantity } = cartItem; - + const product = await this.productModel.findOne({ where: { id: productId } }); - + if (!product) { throw new HttpException(`Product with ID ${productId} not found.`, HttpStatus.NOT_FOUND); } - + if (product.quantity < quantity) { throw new HttpException(`Insufficient stock for product ID ${productId}.`, HttpStatus.BAD_REQUEST); } - + product.quantity -= quantity; // Reduce stock await product.save(); } - - // Create the invoices for all cart items - const invoices = await this.invoiceService.createInvoiceFromCart(userId); - - return { message: "Order processed successfully", invoices }; // Return invoices as an array + + // Create the invoices for all cart + const invoices = await this.invoiceService.createInvoiceFromCart(userId,cartId); + + return { message: "Order processed successfully", invoices }; } catch (error) { console.log(error); if (error instanceof HttpException) { @@ -151,7 +158,4 @@ export class CartService { } } } - - - } diff --git a/src/invoice/entities/invoice.entity.ts b/src/invoice/entities/invoice.entity.ts index 37858fe..0cd92a9 100644 --- a/src/invoice/entities/invoice.entity.ts +++ b/src/invoice/entities/invoice.entity.ts @@ -1,71 +1,33 @@ -import { Table, Column, ForeignKey, BelongsTo, DataType, Model } from "sequelize-typescript"; +import { + Table, + Column, + ForeignKey, + BelongsTo, + DataType, + Model, +} from "sequelize-typescript"; import { User } from "../../users/entities/user.entity"; +import { Cart } from "src/cart/entities/cart.entity"; @Table export class Invoice extends Model { - - @ForeignKey(() => User) @Column userId: number; - @BelongsTo(() => User, { onDelete: "CASCADE" }) + @BelongsTo(() => User, { onDelete: "CASCADE" }) user: User; - @Column({ - type: DataType.STRING, - allowNull: false, - }) - firstName: string; - - @Column({ - type: DataType.STRING, - allowNull: false, - }) - lastName: string; - - @Column({ - type: DataType.STRING, - allowNull: false, - }) - phoneNumber: string; - - @Column({ - type: DataType.STRING, - allowNull: false, - unique: false, - }) - email: string; + @ForeignKey(() => Cart) @Column - totalPaymentAmount: number; + cartId: number; - @Column({ - type: DataType.INTEGER, - allowNull: false, - }) - productId: number; + @BelongsTo(() => Cart, { onDelete: "CASCADE" }) + cart: Cart; @Column({ - type: DataType.INTEGER, + type: DataType.FLOAT, allowNull: false, }) - quantity: number; - - @Column({ - type: DataType.DECIMAL(10, 2), - allowNull: false, - }) - price: number; - - @Column({ - type: DataType.DECIMAL(10, 2), - allowNull: false, - }) - totalPrice: number; - - @Column({ - type: DataType.STRING, - allowNull: false, - }) - productName: string; + totalPaymentAmount: number; } diff --git a/src/invoice/invoice.service.ts b/src/invoice/invoice.service.ts index d00e28b..50d7d2e 100644 --- a/src/invoice/invoice.service.ts +++ b/src/invoice/invoice.service.ts @@ -12,7 +12,7 @@ export class InvoiceService { private cartService: CartService, ) {} - async createInvoiceFromCart(userId: number): Promise { + async createInvoiceFromCart(userId: number,cartId:number): Promise { const user = await User.findByPk(userId); if (!user) { throw new HttpException("User not found", HttpStatus.NOT_FOUND); @@ -22,28 +22,13 @@ export class InvoiceService { if (!userCartItems || userCartItems.cartItems.length === 0) { throw new HttpException("Cart is empty", HttpStatus.BAD_REQUEST); } - - const invoices: Invoice[] = []; - - for (const cartItem of userCartItems.cartItems) { - const invoice = await this.invoiceModel.create({ - userId, - firstName: user.firstName, - lastName: user.lastName, - phoneNumber: user.phoneNumber, - email: user.email, - totalPaymentAmount: userCartItems.totalPrice, - productId: cartItem.productId, - quantity: cartItem.quantity, - price: cartItem.productPrice, - totalPrice:(cartItem.quantity*cartItem.productPrice), - productName: cartItem.productName, - }); - - invoices.push(invoice); - } - - return invoices; // بازگرداندن آرایه‌ای از فاکتورها + + const invoice = await this.invoiceModel.create({ + userId, + cartId, + totalPaymentAmount:userCartItems.totalPrice, + }) + return invoice }