feat: add bulk to cart add
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import { Expose, Type } from "class-transformer";
|
||||
import { IsArray, IsNotEmpty, IsNumber, IsString, Min, ValidateNested } from "class-validator";
|
||||
|
||||
import { ApiProperty } from "../../../common/decorator/swggerDocs";
|
||||
import { IsValidId } from "../../../common/decorator/validation.decorator";
|
||||
import { ProductVariantModel } from "../../product/models/productVariant.model";
|
||||
|
||||
export class BulkCartItemDTO {
|
||||
@Expose()
|
||||
@IsNotEmpty()
|
||||
@IsNumber()
|
||||
@ApiProperty({ type: "number", description: "product id", example: 100000 })
|
||||
productId: number;
|
||||
|
||||
@Expose()
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
@IsValidId(ProductVariantModel)
|
||||
@ApiProperty({ type: "string", description: "variant id of a product", example: "66c0d81ecc135bbc22fc44e3" })
|
||||
variantId: string;
|
||||
|
||||
@Expose()
|
||||
@IsNotEmpty()
|
||||
@IsNumber()
|
||||
@Min(1)
|
||||
@ApiProperty({ type: "number", description: "quantity of a product", example: 2 })
|
||||
quantity: number;
|
||||
}
|
||||
|
||||
export class BulkAddToCartDTO {
|
||||
@Expose()
|
||||
@IsArray()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => BulkCartItemDTO)
|
||||
@ApiProperty({
|
||||
type: "string",
|
||||
description: "Array of items to add to cart",
|
||||
example: [
|
||||
{
|
||||
productId: 100000,
|
||||
variantId: "66c0d81ecc135bbc22fc44e3",
|
||||
quantity: 2,
|
||||
},
|
||||
{
|
||||
productId: 100001,
|
||||
variantId: "66c0d81ecc135bbc22fc44e4",
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
})
|
||||
items: BulkCartItemDTO[];
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import { controller, httpGet, httpPost, request, requestBody } from "inversify-e
|
||||
import { CartService } from "./cart.service";
|
||||
import { HttpStatus } from "../../common";
|
||||
import { AddToCartDTO } from "./DTO/addToCart.dto";
|
||||
import { BulkAddToCartDTO } from "./DTO/bulkAddToCart.dto";
|
||||
import { RemoveFromCartDTO } from "./DTO/removeFromCart.dto";
|
||||
import { UpdateCartDTO } from "./DTO/updateCart.dto";
|
||||
import { BaseController } from "../../common/base/controller";
|
||||
@@ -41,6 +42,17 @@ class CartController extends BaseController {
|
||||
return this.response(data, HttpStatus.Created);
|
||||
}
|
||||
|
||||
@ApiOperation("add multiple products to user cart")
|
||||
@ApiResponse("successful", HttpStatus.Created)
|
||||
@ApiModel(BulkAddToCartDTO)
|
||||
@ApiAuth()
|
||||
@httpPost("/bulk-add", Guard.authUser(), ValidationMiddleware.validateInput(BulkAddToCartDTO))
|
||||
public async bulkAddToCart(@requestBody() bulkAddToCartDto: BulkAddToCartDTO, @request() req: Request) {
|
||||
const user = req.user as IUser;
|
||||
const data = await this.cartService.bulkAddToCartS(bulkAddToCartDto, user._id.toString());
|
||||
return this.response(data, HttpStatus.Created);
|
||||
}
|
||||
|
||||
@ApiOperation("update the user cart")
|
||||
@ApiResponse("successful", HttpStatus.Ok)
|
||||
@ApiModel(UpdateCartDTO)
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ClientSession, Types, startSession } from "mongoose";
|
||||
|
||||
import { CartRepository, CartShipItemRepo } from "./cart.repository";
|
||||
import { AddToCartDTO } from "./DTO/addToCart.dto";
|
||||
import { BulkAddToCartDTO } from "./DTO/bulkAddToCart.dto";
|
||||
import { CartDTO } from "./DTO/cart.dto";
|
||||
import { RemoveFromCartDTO } from "./DTO/removeFromCart.dto";
|
||||
import { UpdateCartDTO } from "./DTO/updateCart.dto";
|
||||
@@ -79,6 +80,65 @@ class CartService {
|
||||
}
|
||||
}
|
||||
|
||||
async bulkAddToCartS(bulkAddToCartDto: BulkAddToCartDTO, userId: string) {
|
||||
const session = await startSession();
|
||||
session.startTransaction();
|
||||
try {
|
||||
const { items } = bulkAddToCartDto;
|
||||
|
||||
// Get or create cart
|
||||
let cart = await this.cartRepo.model.findOne({ user: userId });
|
||||
if (!cart) {
|
||||
cart = (await this.cartRepo.model.create([{ user: userId }], { session }))[0];
|
||||
}
|
||||
|
||||
// Validate all products before making any changes
|
||||
for (const item of items) {
|
||||
const existingCartItem = cart.items.find(
|
||||
(cartItem) => cartItem.product === item.productId && cartItem.variant.toString() === item.variantId,
|
||||
);
|
||||
const existingQuantity = existingCartItem ? existingCartItem.quantity : 0;
|
||||
|
||||
await this.validateProduct(item.productId, item.variantId, existingQuantity + item.quantity);
|
||||
}
|
||||
|
||||
// Process each item
|
||||
for (const item of items) {
|
||||
const existingCartItem = cart.items.find(
|
||||
(cartItem) => cartItem.product === item.productId && cartItem.variant.toString() === item.variantId,
|
||||
);
|
||||
|
||||
if (existingCartItem) {
|
||||
// Update quantity if item already exists in the cart
|
||||
existingCartItem.quantity += item.quantity;
|
||||
} else {
|
||||
// Add new item to the cart
|
||||
cart.items.push({
|
||||
product: item.productId,
|
||||
quantity: item.quantity,
|
||||
variant: new Types.ObjectId(item.variantId),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await cart.save({ session });
|
||||
|
||||
// Commit the transaction
|
||||
await session.commitTransaction();
|
||||
session.endSession();
|
||||
|
||||
return {
|
||||
message: CartMessage.ItemAdded,
|
||||
cart: await this.getCartS(userId),
|
||||
};
|
||||
} catch (error) {
|
||||
// Rollback any changes made in the transaction
|
||||
await session.abortTransaction();
|
||||
session.endSession();
|
||||
throw error; // Re-throw the error to be handled by the calling errorHandler
|
||||
}
|
||||
}
|
||||
|
||||
async updateCartS(updateCartDto: UpdateCartDTO, userId: string) {
|
||||
const { productId, variantId, quantity } = updateCartDto;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user