Improve integration between invoice and order processing

master
nicekid1 2 months ago
parent 122bbacc0d
commit 187811a048
  1. 15
      src/cart/cart.controller.ts
  2. 29
      src/cart/cart.service.ts
  3. 2
      src/config/database.config.ts
  4. 52
      src/invoice/entities/invoice.entity.ts
  5. 5
      src/invoice/invoice.controller.ts
  6. 42
      src/invoice/invoice.service.ts
  7. 4
      src/main.ts

@ -4,6 +4,7 @@ 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";
import { Invoice } from "src/invoice/entities/invoice.entity";
@Controller("cart")
export class CartController {
@ -45,11 +46,11 @@ export class CartController {
}
@Post(':userId/checkout')
async processOrder(
async processOrder(
@Param('userId') userId: number,
@Body('totalAmount') totalAmount: number,
): Promise<string> {
if (!totalAmount || totalAmount <= 0) {
): Promise<{ message: string; invoice: Invoice }> {
if (!totalAmount || totalAmount <= 0 || isNaN(totalAmount)) {
throw new HttpException('Invalid total amount.', HttpStatus.BAD_REQUEST);
}
@ -57,7 +58,11 @@ export class CartController {
const result = await this.cartService.processOrder(userId, totalAmount);
return result;
} catch (error) {
throw new HttpException(error.message || 'Order processing failed.', HttpStatus.INTERNAL_SERVER_ERROR);
}
throw new HttpException(
error.message || 'An unexpected error occurred while processing the order.',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
}

@ -4,6 +4,7 @@ import { Cart } from "./entities/cart.entity";
import { Product } from "src/products/entities/product.entity";
import { WalletService } from "src/wallet/wallet.service";
import { InvoiceService } from "src/invoice/invoice.service";
import { Invoice } from "src/invoice/entities/invoice.entity";
@Injectable()
export class CartService {
@ -12,7 +13,7 @@ export class CartService {
@InjectModel(Product) private readonly productModel: typeof Product,
private readonly walletService: WalletService,
@Inject(forwardRef(() => InvoiceService))
private invoiceService: InvoiceService
private invoiceService: InvoiceService,
) {}
// Add product to cart
@ -108,14 +109,18 @@ export class CartService {
}
//order(clearCart unable)
async processOrder(userId: number, totalAmount: number): Promise<string> {
async processOrder(userId: number, totalAmount: number): Promise<{ message: string; invoice: Invoice }> {
try {
// Deducting credit from wallet
await this.walletService.processPayment(userId, totalAmount);
//Reduce the number purchased from the number of products
// 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;
@ -129,12 +134,22 @@ export class CartService {
throw new HttpException(`Insufficient stock for product ID ${productId}.`, HttpStatus.BAD_REQUEST);
}
product.quantity -= quantity;
product.quantity -= quantity; // Reduce stock
await product.save();
// await this.clearCart(userId);
}
const invoice = await this.invoiceService.createInvoiceFromCart(userId)
return "Order processed successfully";
// Create the invoice after processing the cart
const invoice = await this.invoiceService.createInvoiceFromCart(userId);
return { message: "Order processed successfully", invoice };
} catch (error) {
console.log(error);
if (error instanceof HttpException) {
throw error;
} else {
throw new HttpException(`An error occurred while processing the order: ${error.message}`, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
}

@ -13,5 +13,5 @@ export const databaseConfig: SequelizeModuleOptions = {
database: process.env.DATABASE_NAME || "ecommerce",
models: [path.join(__dirname, "../**/entities/*.entity.ts")],
autoLoadModels: true,
synchronize: true,
synchronize:true,
};

@ -9,21 +9,55 @@ export class Invoice extends Model<Invoice> {
@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;
@Column
totalAmount: number;
@Column({ type: DataType.JSON })
products: {
@Column({
type: DataType.INTEGER,
allowNull: false,
})
productId: number;
@Column({
type: DataType.INTEGER,
allowNull: false,
})
quantity: number;
price: number;
name: string;
}[];
@Column
paymentStatus: string;
@Column({
type: DataType.DECIMAL(10, 2),
allowNull: false,
})
price: number;
@Column
refId: string;
@Column({
type: DataType.STRING,
allowNull: false,
})
productName: string;
}

@ -4,11 +4,6 @@ import { InvoiceService } from "./invoice.service";
@Controller("invoice")
export class InvoiceController {
constructor(private readonly invoiceService: InvoiceService) {}
@Post("create")
async createInvoice(@Body() body: { userId: number; totalAmount: number; products: any[]; refId: string; paymentStatus: string }) {
const { userId, totalAmount, products, refId, paymentStatus } = body;
return this.invoiceService.createInvoice(userId, totalAmount, products, refId, paymentStatus);
}
@Get(":userId")
async getInvoices(@Param("userId") userId: number): Promise<any> {
return this.invoiceService.getInvoicesByUser(userId);

@ -23,36 +23,42 @@ export class InvoiceService {
throw new HttpException("Cart is empty", HttpStatus.BAD_REQUEST);
}
const totalAmount = userCartItems.totalPrice;
const products = userCartItems.cartItems.map(item => ({
const products = userCartItems.cartItems.map(item => {
return {
productId: item.productId,
quantity: item.quantity,
price: item.productPrice,
name: item.productName,
}));
productName: item.productName,
totalPrice: item.totalPrice,
};
});
const newInvoice = await this.invoiceModel.create({
for (const product of products) {
await this.invoiceModel.create({
userId,
totalAmount,
products,
paymentStatus: "pending",
refId: "",
firstName: user.firstName,
lastName: user.lastName,
phoneNumber: user.phoneNumber,
email: user.email,
totalAmount: userCartItems.totalPrice,
productId: product.productId,
quantity: product.quantity,
price: product.price,
productName: product.productName,
});
return newInvoice;
}
async createInvoice(userId: number, totalAmount: number, products: any[], refId: string, paymentStatus: string): Promise<Invoice> {
const newInvoice = await this.invoiceModel.create({
const newInvoice = new Invoice({
userId,
totalAmount,
products,
refId,
paymentStatus,
firstName: user.firstName,
lastName: user.lastName,
phoneNumber: user.phoneNumber,
email: user.email,
totalAmount: userCartItems.totalPrice,
});
return newInvoice;
}
async getInvoicesByUser(userId: number): Promise<Invoice[]> {
try {
if (!userId) {

@ -1,9 +1,11 @@
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';
import { Sequelize } from 'sequelize-typescript';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const sequelize = app.get(Sequelize);
await sequelize.sync({ alter: true });
app.useGlobalPipes(new ValidationPipe());
await app.listen(process.env.PORT ?? 3000);
}

Loading…
Cancel
Save